import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; /** * Class RectDrawingListener extends Java's MouseInputAdpater to provide * handlers for three mouse events: mouse pressed, mouse dragged, and mouse * released. The comments for the event-handling methods describe in * detail what each method does to allow the user to draw rectangles. *
* The general drawing strategy is to add and remove rectangles from the * canvas shapeList as the mouse is being dragged, repainting the canvas at * each addition. Since repainting is done efficiently by Java, this * technique is visually OK even if the canvas shapeList contains a large * number of other rectangles to be drawn. */ public class TextDrawingListener extends MouseInputAdapter implements ActionListener { private DrawingCanvas canvas; private WorkSpace workSpace; /** The starting x-axis position for drawing a shape */ private int startX; /** The starting y-axis position for drawing a shape */ private int startY; /** Quadrant-I normalized value of startY */ private int nStartY; /** True if the user is moving the mouse. */ private boolean moving = false; /** Text field for entering text. It's non-null or null value inicidates, * respectively, whether typing is in progress. */ JTextField textField; /** * Construct this with the given canvas and workspace. */ public TextDrawingListener(DrawingCanvas canvas, WorkSpace workSpace) { this.canvas = canvas; this.workSpace = workSpace; } /** * The press event does it all in this listener. If the text field is * null, create it and display it at the x/y click location. If the text * field is non-null, and the click happens outside the text field, call * createTextShape to finish things off. */ public void mousePressed(MouseEvent e) { Shape selection = workSpace.getSelection(); if (selection != null) { selection.selected = false; } if (textField == null) { int ch = canvas.getHeight(); startX = e.getX(); startY = e.getY(); nStartY = ch - startY; } if (textField == null) { /* * Turn off any previously selected text * workSpace.setSelection(null); * * OK, so this is not working as expected. */ textField = new JTextField(40); textField.addActionListener(this); canvas.add(textField); textField.setBounds(e.getX(), e.getY(), 40*8, 20); textField.grabFocus(); canvas.revalidate(); } else { createTextShape(); mousePressed(e); // this'll keep putting up text fields; // its behavior is seemingly a bit volatile at // this point, and rather beyond 102 // expectations; however, let's leave it in } } /** * Per the JTextField documentation, pressing the enter (aka, return) key * in a JTextField triggers an ActionEvent. In our case, we want to * finalize the text entry by calling this.createTextShape(). */ public void actionPerformed(ActionEvent e) { createTextShape(); } /** * When the user is done typing, get the text field string, remove the text * field, and add the string-valued Text shape to the workspace. */ private void createTextShape() { Point p = textField.getLocation(); String s = textField.getText(); int ch = canvas.getHeight(); String value = textField.getText(); canvas.remove(textField); textField = null; int x_fudge = 6; int y_fudge = 1; int width = (int) canvas.getFont().getStringBounds( s, canvas.getGraphics2D().getFontRenderContext()).getWidth(); int height = (int) canvas.getFont().getStringBounds( s, canvas.getGraphics2D().getFontRenderContext()).getHeight(); Text text = new Text(s, width, height, startX + x_fudge, startY + y_fudge, Color.BLACK, false); workSpace.add(text); workSpace.setSelection(text); text.selected = true; moving = false; canvas.grabFocus(); canvas.repaint(); } /** * Do nothing. */ public void mouseDragged(MouseEvent e) { } /** * Do nothing. */ public void mouseReleased(MouseEvent e) { } }