Source for javax.swing.text.TextAction

   1: /* TextAction.java --
   2:    Copyright (C) 2002, 2004 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.text;
  40: 
  41: import java.awt.Component;
  42: import java.awt.KeyboardFocusManager;
  43: import java.awt.Point;
  44: import java.awt.event.ActionEvent;
  45: import java.util.HashMap;
  46: import java.util.Iterator;
  47: 
  48: import javax.swing.AbstractAction;
  49: import javax.swing.Action;
  50: 
  51: /**
  52:  * TextAction
  53:  * @author Andrew Selkirk
  54:  */
  55: public abstract class TextAction extends AbstractAction
  56: {
  57:   /**
  58:    * Constructor TextAction
  59:    * @param name TODO
  60:    */
  61:   public TextAction(String name)
  62:   {
  63:     super(name);
  64:   }
  65: 
  66:   /**
  67:    * Returns the <code>JTextComponent</code> object associated with the given
  68:    * <code>ActionEvent</code>. If the source of the event is not a
  69:    * <code>JTextComponent</code> the currently focused text component is returned.
  70:    *
  71:    * @param event the action event
  72:    *
  73:    * @return the <code>JTextComponent</code>
  74:    */
  75:   protected final JTextComponent getTextComponent(ActionEvent event)
  76:   {
  77:     JTextComponent target = null;
  78:     if (event != null)
  79:       {
  80:         Object source = event.getSource();
  81:         if (source instanceof JTextComponent)
  82:           target = (JTextComponent) source;
  83:       }
  84:     if (target == null)
  85:       target = getFocusedComponent();
  86:     return target;
  87:   }
  88: 
  89:   /**
  90:    * Creates a new array of <code>Action</code> containing both given arrays.
  91:    *
  92:    * @param list1 the first action array
  93:    * @param list2 the second action array
  94:    *
  95:    * @return the augmented array of actions
  96:    */
  97:   public static final Action[] augmentList(Action[] list1, Action[] list2)
  98:   {
  99:     HashMap<Object,Action> actions = new HashMap<Object,Action>();
 100: 
 101:     for (int i = 0; i < list1.length; ++i)
 102:       {
 103:         Action a = list1[i];
 104:         Object name = a.getValue(Action.NAME);
 105:         actions.put(name != null ? name : "", a);
 106:       }
 107: 
 108:     for (int i = 0; i < list2.length; ++i)
 109:       {
 110:         Action a = list2[i];
 111:         Object name = a.getValue(Action.NAME);
 112:         actions.put(name != null ? name : "", a);
 113:       }
 114:     Action[] augmented = new Action[actions.size()];
 115: 
 116:     int i = 0;
 117:     for (Iterator<Action> it = actions.values().iterator(); it.hasNext(); i++)
 118:       augmented[i] = it.next();
 119:     return augmented;
 120: 
 121:   }
 122: 
 123:   /**
 124:    * Returns the current focused <code>JTextComponent</code> object.
 125:    *
 126:    * @return the <code>JTextComponent</code>
 127:    */
 128:   protected final JTextComponent getFocusedComponent()
 129:   {
 130:     KeyboardFocusManager kfm =
 131:       KeyboardFocusManager.getCurrentKeyboardFocusManager();
 132:     Component focused = kfm.getPermanentFocusOwner();
 133:     JTextComponent textComp = null;
 134:     if (focused instanceof JTextComponent)
 135:       textComp = (JTextComponent) focused;
 136:     return textComp;
 137:   }
 138: 
 139:   /** Abstract helper class which implements everything needed for an
 140:    * Action implementation in <code>DefaultEditorKit</code> which
 141:    * does horizontal movement (and selection).
 142:    */
 143:   abstract static class HorizontalMovementAction extends TextAction
 144:   {
 145:     int dir;
 146: 
 147:     HorizontalMovementAction(String name, int direction)
 148:     {
 149:       super(name);
 150:       dir = direction;
 151:     }
 152: 
 153:     public void actionPerformed(ActionEvent event)
 154:     {
 155:       JTextComponent t = getTextComponent(event);
 156:       try
 157:       {
 158:         if (t != null)
 159:           {
 160:             int offs
 161:               = Utilities.getNextVisualPositionFrom(t,
 162:                                                     t.getCaretPosition(),
 163:                                                     dir);
 164: 
 165:             Caret c = t.getCaret();
 166: 
 167:             actionPerformedImpl(c, offs);
 168: 
 169:             c.setMagicCaretPosition(t.modelToView(offs).getLocation());
 170:           }
 171:       }
 172:     catch(BadLocationException ble)
 173:       {
 174:         throw
 175:           (InternalError) new InternalError("Illegal offset").initCause(ble);
 176:       }
 177: 
 178:     }
 179: 
 180:     protected abstract void actionPerformedImpl(Caret c, int offs)
 181:       throws BadLocationException;
 182:   }
 183: 
 184:   /** Abstract helper class which implements everything needed for an
 185:    * Action implementation in <code>DefaultEditorKit</code> which
 186:    * does vertical movement (and selection).
 187:    */
 188:   abstract static class VerticalMovementAction extends TextAction
 189:   {
 190:     int dir;
 191: 
 192:     VerticalMovementAction(String name, int direction)
 193:     {
 194:       super(name);
 195:       dir = direction;
 196:     }
 197: 
 198:     public void actionPerformed(ActionEvent event)
 199:     {
 200:       JTextComponent t = getTextComponent(event);
 201:       try
 202:         {
 203:           if (t != null)
 204:             {
 205:               Caret c = t.getCaret();
 206:               // The magic caret position may be null when the caret
 207:               // has not moved yet.
 208:               Point mcp = c.getMagicCaretPosition();
 209: 
 210:               int pos;
 211:               if (mcp != null)
 212:                 {
 213:                   mcp.y = t.modelToView(c.getDot()).y;
 214:                   pos = t.viewToModel(mcp);
 215:                 }
 216:               else
 217:                 pos = c.getDot();
 218: 
 219:               pos = Utilities.getNextVisualPositionFrom(t,
 220:                                                         t.getCaretPosition(),
 221:                                                         dir);
 222: 
 223:               if (pos > -1)
 224:                 actionPerformedImpl(c, pos);
 225:             }
 226:         }
 227:       catch(BadLocationException ble)
 228:       {
 229:         throw
 230:           (InternalError) new InternalError("Illegal offset").initCause(ble);
 231:       }
 232:     }
 233: 
 234:     protected abstract void actionPerformedImpl(Caret c, int offs)
 235:     throws BadLocationException;
 236: 
 237:   }
 238: 
 239: 
 240: }