Vertical Text in Java
by Lee Ann Rucker03/22/2002
If you're developing your application using Java on the Macintosh, you may have noticed that Apple's Human Interface Guidelines specify vertical text in side tabs, but Java only supports horizontal text.
To address this, I wrote the VTextIcon class, which manages vertical text with support for localization. VTextIcon does so using only the Swing and Graphics2D APIs, so you should be able to use the VTextIcon class on any Java2 platform, and in any JComponent which supports Icons.
This article will help you learn how to display vertical text in a Swing component such as a JTabbedPane. It is written for intermediate-level programmers.
The VTextIcon Class
Here are the methods you'll use to create and manage a
VTextIcon:
public VTextIcon(Component component, String label) {
this(component, label, ROTATE_DEFAULT);
}
public VTextIcon(Component component, String label,
int rotateHint) {
fComponent = component;
fLabel = label;
fRotation = verifyRotation(label, rotateHint);
calcDimensions();
fComponent.addPropertyChangeListener(this);
}
public void setLabel(String label) {
fLabel = label;
// Make sure the current rotation is still legal
fRotation = verifyRotation(label, fRotation);
recalcDimensions();
}
|
| |
You provide a Component so that VTextIcon knows which Font to use
when calculating the string dimensions for getIconWidth
and getIconHeight. It also invalidates the Component's
layout when the dimensions change, either because you used
setLabel to change the label or because the Component's
font changed.
The verifyRotation method determines the best
rotation based on the rotation style from rotateHint and
the characters in the label. If your label doesn't
support the style in rotateHint,
verifyRotation will return the default.
VTextIcon supports three rotation styles:
ROTATE_NONE
ROTATE_LEFT
ROTATE_RIGHT
Along with:
ROTATE_DEFAULT
Note that not all styles are available for all scripts. Roman, for instance, can be drawn in any style, but Chinese, Japanese, and Korean (CJK) cannot be rotated, and Arabic, Hebrew and Syriac should be rotated.
While Unicode doesn't define the behavior for vertical text -- considering it a "formatting style” --- it does describe common approaches:
When setting text using the Arabic script in vertical lines, it is more common to employ a horizontal baseline that is rotated by 90º counterclockwise so that the characters are ordered from top to bottom. Latin text and numbers may be rotated 90º clockwise so that the characters are also ordered from top to bottom.
So the default for Roman is ROTATE_RIGHT and for
Arabic ROTATE_LEFT, though they can be rotated in either
direction.
|
|
|
|
| If Roman text isn't rotated, it should be centered |
Japanese for "Japanese" It would be difficult to read if it was rotated |
Here is the Arabic word for beach (shatt), showing the individual letters and the entire word. Arabic letters take on different forms depending on their position in the word. |
calcDimensions determines the width and height, and
also checks for special Japanese characters, as described in the next
section. recalcDimensions is used after the VTextIcon has been
created; it calls calcDimensions, then checks whether the
size has changed, and if so invalidates the Component's layout.
Japanese and Small Kana
In addition to the ideographs ("kanji"), Japanese has two syllabaries, known as "kana." Most syllables are represented by a single kana, but some are represented by two. In these cases the second kana is drawn slightly smaller than the normal characters, though it takes up the same amount of space. When drawn horizontally, the small kana should be in the bottom-left quadrant of the space, but when drawn vertically it goes in the top-right. Additionally, vertical punctuation is shifted to the far top-right corner. Since the VTextIcon can't tell Java that the kana is being drawn vertically, it has to shift the glyph into the correct location in paintIcon.

Vertical and horizontal small kana
Mixed-Language Strings
Because the rotated text is drawn using Graphics2D.rotate, it's rendered by Java as if it were horizontal. This may cause undesired effects in mixed-language strings. Unicode has this to say on mixed Arabic and Latin:
The bidirectional algorithm also comes into effect when some characters are ordered from bottom to top. For example, this happens with a mixture of Arabic and Latin glyphs when all the glyphs are rotated uniformly 90º clockwise. (The choice of whether text is to be presented horizontally or vertically, or whether text is to be rotated, is not specified by the Unicode Standard, and is left up to higher-level protocols.)
It's common for mixed CJK/Roman to rotate the Roman string, but VTextIcon does not support mixed rotation styles. The implementation of mixed-language strings is left as the proverbial exercise for the reader.
CompositeIcon
Since you're using your JComponent's Icon for text, does this mean
you can't have a graphical Icon? No. That's what CompositeIcon does
for you -- it takes two Icons (of any kind) and draws them with
a specified position relative to each other and orientation within
the allotted space.
/**
CompositeIcon is an Icon implementation which draws two icons
with a specified relative position:
LEFT, RIGHT, TOP, BOTTOM
specify how icon1 is drawn relative to icon2
CENTER
icon1 is drawn first, icon2 is drawn over it
and with horizontal and vertical orientations
within the allotted space
It's useful with VTextIcon when you want an icon with your text:
if icon1 is the graphic icon and icon2 is the VTextIcon,
you get a similar effect to a JLabel
with a graphic icon and text
*/
Creating a JTabbedPane With a VTextIcon
To create tabs with vertical text, first create a JTabbedPane with LEFT or RIGHT tabs:
JTabbedPane panel = new JTabbedPane(LEFT);
Then create a VTextIcon for that panel. We'll use the default orientation here:
VTextIcon textIcon = new VTextIcon(panel, "Mac OS X");
The test application uses one of the FileView icons, but any icon will do:
Icon graphicIcon = UIManager.getIcon("FileView.computerIcon");
Now use a CompositeIcon to combine them:
CompositeIcon icon = new CompositeIcon(graphicIcon, textIcon);
Finally, create the tab, passing in "null" for the title, the CompositeIcon, and the Component to be displayed when this tab is active (makePane is a placeholder in the test application):
panel.addTab(null, icon, makePane());
If you only want to display text, just use the VTextIcon in addTab:
panel.addTab(null, textIcon, makePane());
Summary
By using VTextIcon and CompositeIcon, you can provide side tabs with vertical text without losing any of the functionality of the standard tabs with graphic icons and horizontal text.
Sources
You can find the complete sources for VTextIcon.java, CompositeIcon.java, and a sample application, Test.java here.
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 17 of 17.
-
How to use JBuilder to compile the code
2006-08-03 19:53:19 amunhoz [Reply | View]
I am trying to compile the code posted here in JBuilder 2006 and the application fails to compile.
Does anyone knows how to place the code into JBuilder and compile it from there?
Thanks a lot.
Aldo
-
I need a sample code.
2005-08-25 18:03:08 ChicagoGeek [Reply | View]
how can we get sample code..
DTS....................
http://www.jobs.co.in/
-
Very usefule - could be easily used as a panel
2005-01-10 02:46:29 sgloor [Reply | View]
public class VTextPanel extends Panel
...
public VTextPanel(Font font, String label, int rotateHint) {
...
public void paint(Graphics g) {
// instead of paintIcon
-
Vertical Text
2003-11-27 07:02:54 anonymous2 [Reply | View]
Hi!
This is very good idea! Thanks a lot!
Maciek
-
Java Applet
2003-10-27 19:13:51 anonymous2 [Reply | View]
Has anyone put this into a Java Applet for use on web pages?
Thanks,
Tony
-
i love you thanks!!
2003-05-12 12:40:46 anonymous2 [Reply | View]
this is great for anyone needing to display sideways text, even non-mac users
-
Great Help!!
2003-03-20 06:25:28 anonymous2 [Reply | View]
Very useful, saved me lot of work.
Hemant Mahidhara
-
HOW TO DRAW VERTICAL TEXT USING JDK1.1.8 WITHOUT SWING
2002-08-11 22:45:30 sharmilaspx [Reply | View]
have to draw vertical text using jdk1.1.8 but
do not know how to convert horizontal baseline
to vertical. can any one help
sharmila.
-
to make it look prettier
2002-06-27 16:10:53 jedierikb [Reply | View]
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-
Excellent work!
2002-04-09 09:44:26 joltguy [Reply | View]
Just wanted to say thanks for this nifty addition to my Java toolchest. It works perfectly!









fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);to make sure the JFrame exit when the window is closed.