FileDocCategorySizeDatePackage
LWTextComponent.javaAPI DocExample12492Wed Apr 19 11:19:38 BST 2000None

LWTextComponent

public class LWTextComponent extends Component implements KeyListener, FocusListener
Implements a very simple lightweight text editing component. It lets the user edit a single line of text using the keyboard. The only special character that it knows about is backspace; all other characters are added to the text. Selections are not supported, so there's only a simple caret indicating the insertion point. The component also displays a component name above the editable text line, and draws a black frame whose thickness indicates whether the component has the focus.

The component can be initialized to enable or disable input through input methods. Other than that, it doesn't do anything to support input methods, so input method interaction (if any) will occur in a separate composition window. However, the component is designed to be easily extended with full input method support. It distinguishes between "displayed text" and "committed text" - here, they're the same, but in a subclass that supports on-the-spot input, the displayed text would be the combination of committed text and composed text. The component also uses TextLayout to draw the text, so it can be easily extended to handle input method highlights.

Fields Summary
private transient boolean
haveFocus
private String
name
private StringBuffer
committedText
private transient TextLayout
textLayout
private transient boolean
validTextLayout
private static final int
LINE_OFFSET
private int
textOriginX
private int
nameOriginY
private int
textOriginY
Constructors Summary
public LWTextComponent(String name, boolean enableInputMethods)
Constructs a LWTextComponent.

param
name the component name to be displayed above the text
param
enableInputMethods whether to enable input methods for this component


                                 
         
        super();
        this.name = name;
	setSize(300, 80);
	// we have to set the foreground color because otherwise
	// text may not display correctly when we use an input
	// method highlight that swaps background and foreground
	// colors
	setForeground(Color.black);
	setBackground(Color.white);
	setFontSize(12);
	setVisible(true);
	setEnabled(true);
	addKeyListener(this);
	addFocusListener(this);
	addMouseListener(new MouseFocusListener(this));
	enableInputMethods(enableInputMethods);
    
Methods Summary
public voidfocusGained(java.awt.event.FocusEvent event)
Turns on drawing of the component's thicker frame and the caret.

        haveFocus = true;
	repaint();
    
public voidfocusLost(java.awt.event.FocusEvent event)
Turns off drawing of the component's thicker frame and the caret.

        haveFocus = false;
	repaint();
    
public java.awt.font.TextHitInfogetCaret()
Returns a text hit info indicating the current caret (insertion point). This class always returns a caret at the end of the text that the user has entered. Subclasses may return a different caret or null.

return
the caret, or null

        return TextHitInfo.trailing(committedText.length() - 1);
    
public java.awt.RectanglegetCaretRectangle()
Returns a 0-width caret rectangle. This rectangle is derived from the caret returned by getCaret. getCaretRectangle returns null iff getCaret does.

see
#getCaret
return
the caret rectangle, or null

        TextHitInfo caret = getCaret();
        if (caret == null) {
            return null;
        }
        return getCaretRectangle(caret);
    
public java.awt.RectanglegetCaretRectangle(java.awt.font.TextHitInfo caret)
Returns a 0-width caret rectangle for the given text index. It is calculated based on the text layout returned by getTextLayout, so this method can be used for the entire displayed text.

param
caret the text index for which to calculate a caret rectangle
return
the caret rectangle

        TextLayout textLayout = getTextLayout();
        int caretLocation;
        if (textLayout != null) {
            caretLocation = Math.round(textLayout.getCaretInfo(caret)[0]);
        } else {
            caretLocation = 0;
        }
        FontMetrics metrics = getGraphics().getFontMetrics();
        return new Rectangle(textOriginX + caretLocation,
                             textOriginY - metrics.getAscent(),
                             0, metrics.getAscent() + metrics.getDescent());
    
public java.text.AttributedCharacterIteratorgetCommittedText()
Returns the text that the user has entered and committed. Since this component does not support on-the-spot input, there's no composed text, so all text that has been entered is committed.

return
an AttributedCharacterIterator for the text that the user has entered and committed

        AttributedString string = new AttributedString(committedText.toString());
        return string.getIterator();
    
public java.text.AttributedCharacterIteratorgetCommittedText(int beginIndex, int endIndex)
Returns a subrange of the text that the user has entered and committed. Since this component does not support on-the-spot input, there's no composed text, so all text that has been entered is committed.

param
beginIndex the index of the first character of the subrange
param
endIndex the index of the character following the subrange
return
an AttributedCharacterIterator for a subrange of the text that the user has entered and committed

        AttributedString string = new AttributedString(committedText.toString());
        return string.getIterator(null, beginIndex, endIndex);
    
public intgetCommittedTextLength()
Returns the length of the text that the user has entered and committed. Since this component does not support on-the-spot input, there's no composed text, so all text that has been entered is committed.

return
the length of the text that the user has entered and committed

        return committedText.length();
    
public java.text.AttributedCharacterIteratorgetDisplayText()
Returns the text that the user has entered. As TextLayout requires a font to be defined for each character, the default font is applied to the entire text. A subclass that supports on-the-spot input must override this method to include composed text.

return
the text that the user has entered

        AttributedString string = new AttributedString(committedText.toString());
        if (committedText.length() > 0) {
            string.addAttribute(TextAttribute.FONT, getFont());
        }
        return string.getIterator();
    
public synchronized java.awt.font.TextLayoutgetTextLayout()
Returns a text layout for the text that the user has entered. This text layout is created from the text returned by getDisplayText. The text layout is cached until invalidateTextLayout is called.

see
#invalidateTextLayout
see
#getDisplayText
return
a text layout for the text that the user has entered, or null

        if (!validTextLayout) {
            textLayout = null;
            AttributedCharacterIterator text = getDisplayText();
            if (text.getEndIndex() > text.getBeginIndex()) {
                FontRenderContext context = ((Graphics2D) getGraphics()).getFontRenderContext();
                textLayout = new TextLayout(text, context);
            }
        }
        validTextLayout = true;
        return textLayout;
    
public java.awt.PointgetTextOrigin()
Returns the origin of the text. This is the leftmost point on the baseline of the text.

return
the origin of the text

        return new Point(textOriginX, textOriginY);
    
public voidinsertCharacter(char c)
Inserts the given character at the end of the text.

param
c the character to be inserted

        committedText.append(c);
	invalidateTextLayout();
    
public synchronized voidinvalidateTextLayout()
Invalidates the cached text layout. This must be called whenever the component's text is modified.

see
#getTextLayout

        validTextLayout = false;
    
public voidkeyPressed(java.awt.event.KeyEvent event)
Ignores key pressed events.

public voidkeyReleased(java.awt.event.KeyEvent event)
Ignores key released events.

public voidkeyTyped(java.awt.event.KeyEvent event)
Handles the key typed event. If the character is backspace, the last character is removed from the text that the user has entered. Otherwise, the character is appended to the text. Then, the text is redrawn.

event
the key event to be handled

        char keyChar = event.getKeyChar();
        if (keyChar == '\b") {
            int len = committedText.length();
            if (len > 0) {
                committedText.setLength(len - 1);
	    invalidateTextLayout();
            }
        } else {
            insertCharacter(keyChar);
        }
	event.consume();
	repaint();
    
public synchronized voidpaint(java.awt.Graphics g)
Draws the component. The following items are drawn:
  • the component's background
  • a frame, thicker if the component has the focus
  • the component name
  • the text that the user has entered
  • the caret, if the component has the focus


        // draw the background
	g.setColor(getBackground());
	Dimension size = getSize();
	g.fillRect(0, 0, size.width, size.height);
	
	// draw the frame, thicker if the component has the focus
	g.setColor(Color.black);
	g.drawRect(0, 0, size.width - 1, size.height - 1);
	if (haveFocus) {
	    g.drawRect(1, 1, size.width - 3, size.height - 3);
	}

        // draw the component name
	g.setColor(getForeground());
	g.drawString(name, textOriginX, nameOriginY);

        // draw the text that the user has entered
        TextLayout textLayout = getTextLayout();
        if (textLayout != null) {
            textLayout.draw((Graphics2D) g, textOriginX, textOriginY);
        }
        
        // draw the caret, if the component has the focus
	Rectangle rectangle = getCaretRectangle();
	if (haveFocus && rectangle != null) {
	    g.setXORMode(getBackground());
            g.fillRect(rectangle.x, rectangle.y, 1, rectangle.height);
	    g.setPaintMode();
        }
    
public voidsetFontSize(int size)

        setFont(new Font("Dialog", Font.PLAIN, size));
        nameOriginY = LINE_OFFSET + size;
        textOriginX = 10;
        textOriginY = 2 * (LINE_OFFSET + size);