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: }