001    /*
002     * @(#)TextTool.java
003     *
004     * Project:             JHotdraw - a GUI framework for technical drawings
005     *                              http://www.jhotdraw.org
006     *                              http://jhotdraw.sourceforge.net
007     * Copyright:   © by the original author(s) and all contributors
008     * License:             Lesser GNU Public License (LGPL)
009     *                              http://www.opensource.org/licenses/lgpl-license.html
010     */
011    
012    package org.objectweb.jac.ide.diagrams;
013    
014    import CH.ifa.draw.framework.DrawingEditor;
015    import CH.ifa.draw.framework.Figure;
016    import CH.ifa.draw.standard.TextHolder;
017    import org.objectweb.jac.util.Log;
018    import java.awt.Container;
019    import java.awt.Dimension;
020    import java.awt.Rectangle;
021    import java.awt.event.ActionEvent;
022    import java.awt.event.ActionListener;
023    import java.awt.event.KeyEvent;
024    import java.awt.event.KeyListener;
025    import java.awt.event.MouseEvent;
026    
027    /**
028     * Tool to create new or edit existing text figures.
029     * The editing behavior is implemented by overlaying the
030     * Figure providing the text with a FloatingTextField.<p>
031     * A tool interaction is done once a Figure that is not
032     * a TextHolder is clicked.
033     *
034     * @see TextHolder
035     * @see FloatingTextField
036     *
037     * @version <$CURRENT_VERSION$>
038     */
039    public class TextTool extends CreationTool 
040       implements ActionListener, KeyListener
041    {
042    
043       private FloatingTextField   fTextField;
044       private TextHolder  fTypingTarget;
045    
046       public TextTool(DrawingEditor newDrawingEditor, Figure prototype) {
047          super(newDrawingEditor, prototype);
048       }
049    
050       /**
051        * If the pressed figure is a TextHolder it can be edited otherwise
052        * a new text figure is created.
053        */
054       public void mouseDown(MouseEvent e, int x, int y)
055       {
056          TextHolder textHolder = null;
057          Figure pressedFigure = drawing().findFigureInside(x, y);
058          if (pressedFigure instanceof TextHolder) {
059             textHolder = (TextHolder) pressedFigure;
060             if (!textHolder.acceptsTyping())
061                textHolder = null;
062          }
063          if (textHolder != null) {
064             beginEdit(textHolder);
065             return;
066          }
067          if (getTypingTarget() != null) {
068             endEdit();
069             editor().toolDone();
070          } else {
071             super.mouseDown(e, x, y);
072             // update view so the created figure is drawn before the floating text
073             // figure is overlaid. (Note, fDamage should be null in StandardDrawingView
074             // when the overlay figure is drawn because a JTextField cannot be scrolled)
075             view().checkDamage();
076             textHolder = (TextHolder)getCreatedFigure();
077             beginEdit(textHolder);
078          }
079       }
080    
081       public void mouseDrag(MouseEvent e, int x, int y) {
082       }
083    
084       public void mouseUp(MouseEvent e, int x, int y) {
085       }
086    
087       /**
088        * Terminates the editing of a text figure.
089        */
090       public void deactivate() {
091          endEdit();
092          super.deactivate();
093       }
094    
095       /**
096        * Sets the text cursor.
097        */
098       public void activate() {
099          super.activate();
100          view().clearSelection();
101          // JDK1.1 TEXT_CURSOR has an incorrect hot spot
102          //view().setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
103       }
104    
105       /**
106        * Test whether the text tool is currently activated and is displaying
107        * a overlay TextFigure for accepting input.
108        *
109        * @return true, if the text tool has a accepting target TextFigure for its input, false otherwise
110        */
111       public boolean isActivated() {
112          return getTypingTarget() != null;
113       }
114            
115       // ActionListener
116       public void actionPerformed(ActionEvent e) {
117          endEdit();
118       }
119    
120       // KeyListener
121       public void keyPressed(KeyEvent e) {
122          int code = e.getKeyCode();
123          if (code==KeyEvent.VK_ESCAPE) {
124             abortEdit();
125          }
126       }
127       public void keyReleased(KeyEvent e) {}
128       public void keyTyped(KeyEvent e) {}
129    
130       protected void beginEdit(TextHolder figure) {
131          if (fTextField == null) {
132             fTextField = new FloatingTextField();
133          }
134               
135          if (figure != getTypingTarget() && getTypingTarget() != null) {
136             endEdit();
137          }
138    
139          fTextField.addActionListener(this);
140          fTextField.addKeyListener(this);
141          fTextField.createOverlay((Container)view(), figure.getFont());
142          fTextField.setBounds(fieldBounds(figure), figure.getText());
143    
144          setTypingTarget(figure);
145       }
146    
147       protected void endEdit() {
148          Log.trace("diagram","End edit");
149          if (getTypingTarget() != null) {
150             if (fTextField.getText().length() > 0) {
151                getTypingTarget().setText(fTextField.getText());
152             } else {
153                drawing().orphan((Figure)getAddedFigure());
154             }
155                  
156             setTypingTarget(null);
157             fTextField.endOverlay();
158             fTextField.removeActionListener(this);
159             fTextField.removeKeyListener(this);
160             //             view().checkDamage();
161          }
162       }
163    
164       protected void abortEdit() {
165          Log.trace("diagram","Abort edit");
166          if (getTypingTarget() != null) {
167             setTypingTarget(null);
168             fTextField.endOverlay();
169             fTextField.removeActionListener(this);
170             fTextField.removeKeyListener(this);
171             //             view().checkDamage();
172          }
173       }
174    
175       private Rectangle fieldBounds(TextHolder figure) {
176          Rectangle box = figure.textDisplayBox();
177          int nChars = figure.overlayColumns();
178          Dimension d = fTextField.getPreferredSize(nChars);
179          return new Rectangle(box.x, box.y, d.width, d.height);
180       }
181            
182       protected void setTypingTarget(TextHolder newTypingTarget) {
183          fTypingTarget = newTypingTarget;
184       }
185            
186       protected TextHolder getTypingTarget() {
187          return fTypingTarget;
188       }
189    
190    }
191