/**
* @author Stanislav Lapitsky
* @version 1.0
*/
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.event.*;
public class VerticalTextPane extends JEditorPane {
public static void main(String[] args) {
JFrame frame = new JFrame("Vertical text editting in JEditorPane example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final VerticalTextPane scaledTextPane = new VerticalTextPane();
JScrollPane scroll = new JScrollPane(scaledTextPane);
frame.getContentPane().add(scroll);
final JRadioButton rdbDownUp = new JRadioButton("Bottom to top", false);
final JRadioButton rdbUpDown = new JRadioButton("Top to bottom", true);
ButtonGroup bg = new ButtonGroup();
bg.add(rdbDownUp);
bg.add(rdbUpDown);
ActionListener lst = new ActionListener() {
public void actionPerformed(ActionEvent e) {
VerticalView root = (VerticalView) scaledTextPane.getUI().getRootView(scaledTextPane).getView(0);
if (rdbDownUp.isSelected()) {
root.orientation = VerticalView.ORIENTATION_DOWN_UP;
}
else {
root.orientation = VerticalView.ORIENTATION_UP_DOWN;
}
scaledTextPane.invalidate();
scaledTextPane.validate();
scaledTextPane.repaint();
}
};
rdbDownUp.addActionListener(lst);
rdbUpDown.addActionListener(lst);
JPanel p = new JPanel();
p.add(rdbDownUp);
p.add(rdbUpDown);
frame.getContentPane().add(p, BorderLayout.NORTH);
frame.setSize(600, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public VerticalTextPane() {
super();
final SimpleAttributeSet attrs = new SimpleAttributeSet();
setEditorKit(new VerticalEditorKit());
StyledDocument doc = (StyledDocument) VerticalTextPane.this.getDocument();
doc.setCharacterAttributes(0, 1, attrs, true);
try {
StyleConstants.setFontSize(attrs, 16);
doc.insertString(0, "16 font test\n", attrs);
StyleConstants.setFontSize(attrs, 20);
doc.insertString(0, "20 font test\n", attrs);
StyleConstants.setFontSize(attrs, 24);
doc.insertString(0, "24 font test\n", attrs);
}
catch (BadLocationException ex) {
}
}
public void repaint(int x, int y, int width, int height) {
super.repaint(0, 0, getWidth(), getHeight());
}
}
class VerticalEditorKit extends StyledEditorKit {
public ViewFactory getViewFactory() {
return new StyledViewFactory();
}
class StyledViewFactory implements ViewFactory {
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new LabelView(elem);
}
else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
}
else if (kind.equals(AbstractDocument.SectionElementName)) {
return new VerticalView(elem, View.Y_AXIS);
}
else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
}
else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
}
}
// default to text display
return new LabelView(elem);
}
}
}
//-----------------------------------------------------------------
class VerticalView extends BoxView {
public static final int ORIENTATION_UP_DOWN = 0;
public static final int ORIENTATION_DOWN_UP = 1;
int orientation = ORIENTATION_UP_DOWN;
float w = 0;
float h = 0;
public VerticalView(Element elem, int axis) {
super(elem, axis);
}
public void setSize(float width, float height) {
this.w = height;
this.h = width;
super.setSize(width, height);
}
public void paint(Graphics g, Shape allocation) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform old = g2d.getTransform();
if (orientation == ORIENTATION_DOWN_UP) {
g2d.rotate( -Math.PI / 2, 0, 0);
g2d.translate( -w, 0);
}
else {
g2d.rotate(Math.PI / 2, 0, 0);
g2d.translate(0, -h);
}
super.paint(g2d, allocation);
g2d.setTransform(old);
}
public float getMinimumSpan(int axis) {
if (axis == View.X_AXIS) {
return super.getMinimumSpan(View.Y_AXIS);
}
else {
return super.getMinimumSpan(View.X_AXIS);
}
}
public float getMaximumSpan(int axis) {
if (axis == View.X_AXIS) {
return super.getMaximumSpan(View.Y_AXIS);
}
else {
return super.getMaximumSpan(View.X_AXIS);
}
}
public float getPreferredSpan(int axis) {
if (axis == View.X_AXIS) {
return super.getPreferredSpan(View.Y_AXIS);
}
else {
return super.getPreferredSpan(View.X_AXIS);
}
}
protected void layout(int width, int height) {
super.layout(height, width);
}
public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
Rectangle alloc;
alloc = a.getBounds();
Shape s = super.modelToView(pos, alloc, b);
alloc = s.getBounds();
if (orientation == ORIENTATION_DOWN_UP) {
int tmp = alloc.x;
alloc.x = alloc.y + 10;
alloc.y = (int) w - tmp;
tmp = alloc.width;
alloc.width = alloc.height;
}
else {
int tmp = alloc.x;
alloc.x = (int) h - alloc.y - 10;
alloc.y = tmp;
tmp = alloc.width;
alloc.width = alloc.height;
}
JEditorPane c = (JEditorPane)this.getContainer();
c.putClientProperty("caretWidth", new Integer(alloc.width));
alloc.height = 2;
return alloc;
}
public int viewToModel(float x, float y, Shape a,
Position.Bias[] bias) {
Rectangle alloc = a.getBounds();
int tmp = alloc.width;
alloc.width = alloc.height;
alloc.height = tmp;
if (orientation == ORIENTATION_DOWN_UP) {
return super.viewToModel(w - y, x, alloc, bias);
}
else {
return super.viewToModel(y, h - x, alloc, bias);
}
}
public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
int direction, Position.Bias[] biasRet) throws BadLocationException {
int d = direction;
if (orientation == ORIENTATION_DOWN_UP) {
switch (direction) {
case NORTH:
d = EAST;
break;
case SOUTH:
d = WEST;
break;
case EAST:
d = SOUTH;
break;
case WEST:
d = NORTH;
break;
}
}
else {
switch (direction) {
case NORTH:
d = WEST;
break;
case SOUTH:
d = EAST;
break;
case EAST:
d = NORTH;
break;
case WEST:
d = SOUTH;
break;
}
}
return super.getNextVisualPositionFrom(pos, b, a, d, biasRet);
}
}