Component
Orientation in Swing
How
JFC Components Support 'BIDI' Text
By Ralph Kar
Swing
1.1, which is now part of JDK 1.2, offers some support for the use
of "BIDI" (bi-directional) text in buttons, labels and
menu items. This new feature is a must for writing programs in languages
that are not oriented from left to right and from top to bottom.
Some written languages, such as Chinese, are traditionally written
from top to bottom and from right to left. Other languages, such
as Hebrew and Arabic are written horizontally but from right to
left. So one important goal of the creators of Swing was to provide
an easy mechanism that allows some support for those languages.
The currently existing Swing components with BIDI support are JLabelapi,
JButtonapi,
JMenuItemapi,
JCheckBoxMenuItemapi,
JMenuapi,
JRadioButtonMenuItemapi,
JToggleButtonapi,
JCheckBoxapi,
and JRadioButtonapi.
None of Swing's text components currently has BIDI support, but
as Swing continues to evolve, plans are to add BIDI support to all
approprate Swing components.
To support BIDI text, Swing uses the new java.awt.ComponentOrientation
class in JDK 1.2. This new class allows components to encapsulate
language-sensitive orientation information. With that capability,
a component can be oriented vertically or horizontally and left-to-right
or right-to-left. In JDK 1.2, the layout managers java.awt.FlowLayout
and java.awt.BorderLayout
have been updated to be able to handle these newly available orientation
styles as well.
To provide backward compatibility, Swing's BIDI support can be
used with JDK1.1.x as well. But when BIDI text is used with
JDK 1.1.x, Swing always defaults to the left-to-right/top-to-bottom
orientation.
To support BIDI text, Swing 1.1 recognizes two special constants:
LEADING and TRAILING. Applications can use these constants to specify
a horizontal text position in buttons, labels and menu items. The
LEADING and TRAILING constants are designed to be used with two
new methods: setHorizontalTextPosition()
and setHorizontalAlignment().
Here's an example:
button.setHorizontalAlignment(JButton.LEADING);
button.setHorizontalTextPosition(JButton.TRAILING);
The LEADING and TRAILING constants
By using the LEADING and TRAILING constants, as shown in preceding
examples, the calculations for laying out a Swing component can
make use of a ComponentOrientation object. When a ComponentOrientation
object is attached to a Swing component, LEADING is translated to
mean LEFT in a left-to-right environment, but is translated to right
RIGHT in a right-to-left environment. Conversely, the TRAILING constant
is translated to mean RIGHT in a left-to-right environment and to
mean LEFT in a right-to-left environment.
Here is how the text positioning looks like in a left-to-right
environment:
And here is the same program running in a right-to-left environment:
BIDI coding: An example
In Example 1, we present the actual code that was used to create
the pictures shown above. As you can see, this example demonstrates
the use of Swing's BIDI text-orientation feature.
If you like, you can download a zip file containtaining the complete
program and all its resources by clicking the Download button.
Example 1
How a Swing app can support bi-directional text
// Imports
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* This class demonstrates the BIDI text feature in Swing 1.1
* under JDK 1.2.
*/
public class BidiDemo extends JApplet implements ActionListener
{
ImageIcon icon = new ImageIcon("duke.gif");
JPanel panel = new JPanel(new GridLayout(4, 2, 10, 5));
JButton but1 = new JButton("LEADING", icon);
JButton but2 = new JButton("TRAILING", icon);
JCheckBox box1 = new JCheckBox("LEADING");
JCheckBox box2 = new JCheckBox("TRAILING");
JRadioButton radio1 = new JRadioButton("LEADING");
JRadioButton radio2 = new JRadioButton("TRAILING");
JLabel label1 = new JLabel("LEADING", icon, JLabel.CENTER);
JLabel label2 = new JLabel("TRAILING", icon, JLabel.CENTER);
JButton switchOrientation = new JButton("Orientation: " +
"Left to Right");
boolean left2right = true;
/**
* Constructor for class BidiDemo.
*/
public BidiDemo() {
// Set the horizontal alignment and the horizontal
// text position for all the components.
but1.setHorizontalAlignment(JButton.LEADING);
but1.setHorizontalTextPosition(JButton.LEADING);
but2.setHorizontalAlignment(JButton.TRAILING);
but2.setHorizontalTextPosition(JButton.TRAILING);
box1.setHorizontalAlignment(JCheckBox.LEADING);
box1.setHorizontalTextPosition(JCheckBox.LEADING);
box2.setHorizontalAlignment(JCheckBox.TRAILING);
box2.setHorizontalTextPosition(JCheckBox.TRAILING);
label1.setHorizontalAlignment(JLabel.LEADING);
label1.setHorizontalTextPosition(JLabel.LEADING);
label2.setHorizontalAlignment(JLabel.TRAILING);
label2.setHorizontalTextPosition(JLabel.TRAILING);
radio1.setHorizontalAlignment(JRadioButton.LEADING);
radio1.setHorizontalTextPosition(JRadioButton.LEADING);
radio2.setHorizontalAlignment(JRadioButton.TRAILING);
radio2.setHorizontalTextPosition(JRadioButton.TRAILING);
// Place the components in the panel.
panel.add(but1);
panel.add(but2);
panel.add(box1);
panel.add(box2);
panel.add(label1);
panel.add(label2);
panel.add(radio1);
panel.add(radio2);
switchOrientation.addActionListener(this);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(panel, BorderLayout.CENTER);
this.getContentPane().add(switchOrientation, BorderLayout.SOUTH);
}
/**
* Event handler for the button clicks.
*/
public void actionPerformed(ActionEvent ev) {
if (ev.getSource() == switchOrientation) {
if (left2right) {
// Set the orientation of each component
// to RIGHT_TO_LEFT.
but1.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
but2.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
box1.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
box2.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
radio1.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
radio2.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
label1.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
label2.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
switchOrientation.setText("Orientation: Right to Left");
left2right = false;
}
else {
// Set the orientation of each component
// to LEFT_TO_RIGHT.
but1.setComponentOrientation(
ComponentOrientation.LEFT_TO_RIGHT);
but2.setComponentOrientation(
ComponentOrientation.LEFT_TO_RIGHT);
box1.setComponentOrientation(
ComponentOrientation.LEFT_TO_RIGHT);
box2.setComponentOrientation(
ComponentOrientation.LEFT_TO_RIGHT);
radio1.setComponentOrientation(
ComponentOrientation.LEFT_TO_RIGHT);
radio2.setComponentOrientation(
ComponentOrientation.LEFT_TO_RIGHT);
label1.setComponentOrientation(
ComponentOrientation.LEFT_TO_RIGHT);
label2.setComponentOrientation(
ComponentOrientation.LEFT_TO_RIGHT);
switchOrientation.setText("Orientation: Left to Right");
left2right = true;
}
}
panel.revalidate();
repaint();
}
/**
* Main method
*/
static public void main(String args[]) {
JFrame frame = new JFrame("Bidi Text Demonstration");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
BidiDemo demo = new BidiDemo();
frame.getContentPane().add(demo);
frame.setSize(400, 400);
frame.setVisible(true);
}
}
|