Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Online Training

Downloads, APIs, Documentation
Java Developer Connection
Tutorials, Tech Articles, Training
Online Support
Community Discussion
News & Events from Everywhere
Products from Everywhere
How Java Technology is Used Worldwide
Print Button
 
Training Index

2D Text Tutorial
Lesson 3: Interacting with Styled Text

By Monica Pawlan

[<<BACK] [CONTENTS] [NEXT>>]

The java.awt.font.TextLayout class lets you respond to end user mouse clicks or keyboard inputs by displaying cursors and highlight regions in the styled text at specified locations. This lesson explains how.

The samples in this lesson support foreign language text. In the source there is code for strong and weak carets, which appear in bidirectional foreign language text. See Lesson 4: Foreign Language Support for more information.


Hit Testing

Hit testing is mapping a graphical location on the display to a character position in the source text. The graphical location is often determined by end user mouse inputs or keyboard selections, and is represented by a caret. A TextLayout object provides default caret shapes including angled carets for italic and oblique glyphs. If you want to use your own caret shapes, you can retrieve the angle and position of the default carets from the TextLayout object and use that information to draw your own shapes.

This sample application draws the default caret wherever the end user clicks on the TextLayout. The mouseClicked method uses TextLayout.hitTestChar to return a java.awt.font.TextHitInfo object that contains the mouse click location (the insertion index) in the TextLayout object.

Information returned by the TextLayout getAscent, getDescent, and getAdvance methods is used to compute the location of the origin for the TextLayout object so it is horizontally and vertically centered.

Here is the complete HitTestSample.java source code.

public void paint(Graphics g) {
  Graphics2D graphics2D = (Graphics2D) g;
  Point2D origin = computeLayoutOrigin();
  graphics2D.translate(origin.getX(), origin.getY());
  textLayout.draw(graphics2D, 0, 0);
  Shape[] carets = 
    textLayout.getCaretShapes(insertionIndex);
  graphics2D.setColor(STRONG_CARET_COLOR);
  graphics2D.draw(carets[0]);

  if (carets[1] != null) {
    graphics2D.setColor(WEAK_CARET_COLOR);
    graphics2D.draw(carets[1]);
  }
}

private class HitTestMouseListener 
    extends MouseAdapter {
  public void mouseClicked(MouseEvent e) {
    Point2D origin = computeLayoutOrigin();
    float clickX = (float) (e.getX() - origin.getX());
    float clickY = (float) (e.getY() - origin.getY());

    TextHitInfo currentHit = 
      textLayout.hitTestChar(clickX, 
      insertionIndex = currentHit.getInsertionIndex();
    repaint();
  }
}

Selection Highlighting

A TextLayout object supports highlighting the entire length or portion of a text string on the screen. In this example, the text string draws with caret at the beginning of the line. The end user can drag the mouse from there or click somewhere else and drag to highlight the characters. The code uses theTextLayout.hitTestChar. and TextLayout.getLogicalHighlightShape to compute the endpoint and get a Shape that represents the highlight region.

Here is the complete SelectionSample.java source code.

public void paint(Graphics g) {
  Graphics2D graphics2D = (Graphics2D) g;
  Point2D origin = computeLayoutOrigin();
  graphics2D.translate(origin.getX(), origin.getY());
  boolean haveCaret = anchorEnd == activeEnd;

  if (!haveCaret) {
    Shape highlight = 
      textLayout.getLogicalHighlightShape(
      anchorEnd, activeEnd);
    graphics2D.setColor(HIGHLIGHT_COLOR);
    graphics2D.fill(highlight);
  }

  graphics2D.setColor(TEXT_COLOR);
  extLayout.draw(graphics2D, 0, 0);

  if (haveCaret) {
    Shape[] carets = 
      textLayout.getCaretShapes(anchorEnd);
    graphics2D.setColor(STRONG_CARET_COLOR);
    graphics2D.draw(carets[0]);

    if (carets[1] != null) {
      graphics2D.setColor(WEAK_CARET_COLOR);
      graphics2D.draw(carets[1]);
    }
  } 
}
private class SelectionMouseMotionListener 
    extends MouseMotionAdapter {
  public void mouseDragged(MouseEvent e) {
    Point2D origin = computeLayoutOrigin();

    float clickX = (float) (e.getX() - origin.getX());
    float clickY = (float) (e.getY() - origin.getY());
    TextHitInfo position = 
      textLayout.hitTestChar(clickX, clickY);
    int newActiveEnd = position.getInsertionIndex();

    if (activeEnd != newActiveEnd) {
      activeEnd = newActiveEnd;
      repaint();
    }
  }
}

private class SelectionMouseListener 
    extends MouseAdapter {
  public void mousePressed(MouseEvent e) {
    Point2D origin = computeLayoutOrigin();
    float clickX = (float) (e.getX() - origin.getX());
    float clickY = (float) (e.getY() - origin.getY());
    TextHitInfo position = 
      textLayout.hitTestChar(clickX, clickY);
    anchorEnd = position.getInsertionIndex();
    activeEnd = anchorEnd;
    repaint();
  }
}

Moving the Caret

A TextLayout object supports moving through the text string on the display one character at a time when the end user presses the left and right arrow keys. In this next example, an insertion offset is initially set to 0 and moved by calling TextLayout.getNextRightHit and TextLayout.getNextLeftHit as appropriate in response to left and right arrow key presses.

Here is the complete ArrowKeySample.java source code.

public void paint(Graphics g) {
  Graphics2D graphics2D = (Graphics2D) g;
  Point2D origin = computeLayoutOrigin();
  graphics2D.translate(origin.getX(), origin.getY());

  textLayout.draw(graphics2D, 0, 0);
  Shape[] carets = 
    textLayout.getCaretShapes(insertionIndex);
  graphics2D.setColor(STRONG_CARET_COLOR);
  graphics2D.draw(carets[0]);

  if (carets[1] != null) {
    graphics2D.setColor(WEAK_CARET_COLOR);
    graphics2D.draw(carets[1]);
  }
 }

 private class ArrowKeyListener extends KeyAdapter {
   private void handleArrowKey(boolean rightArrow) {
     TextHitInfo newPosition;

     if (rightArrow) {
       newPosition = 
         textLayout.getNextRightHit(insertionIndex);
     }
     else {
       newPosition = 
         textLayout.getNextLeftHit(insertionIndex);
     }

    if (newPosition != null) {
      insertionIndex = newPosition.getInsertionIndex();
      repaint();
    }
  }
  public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();

    if (keyCode == KeyEvent.VK_LEFT ||
                   keyCode == KeyEvent.VK_RIGHT) {
      handleArrowKey(keyCode == KeyEvent.VK_RIGHT);
    }
  }

Print Button
[ This page was updated: 21-Sep-2000 ]
Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary | Feedback | A-Z Index
For more information on Java technology
and other software from Sun Microsystems, call:
(800) 786-7638
Outside the U.S. and Canada, dial your country's AT&T Direct Access Number first.
Sun Microsystems, Inc.
Copyright © 1995-2000 Sun Microsystems, Inc.
All Rights Reserved. Terms of Use. Privacy Policy.