try { String data = (String)t.getTransferData(flavor); ((JTextComponent)comp).replaceSelection(data); return true; } catch (UnsupportedFlavorException ufe) { } catch (IOException ioe) { } } } return false; } public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) { JTextComponent c = (JTextComponent)comp; if (!(c.isEditable() && c.isEnabled())) { return false; } return (getFlavor(transferFlavors) != null); } public int getSourceActions(JComponent c) { return NONE; } private DataFlavor getFlavor(DataFlavor[] flavors) { if (flavors != null) { for (DataFlavor flavor : flavors) { if (flavor.equals(DataFlavor.stringFlavor)) { return flavor; } } } return null; } } /** * Returns the JTextComponent that most recently had focus. The returned * value may currently have focus. */ static final JTextComponent getFocusedComponent() { return (JTextComponent)AppContext.getAppContext(). get(FOCUSED_COMPONENT); } private int getCurrentEventModifiers() { int modifiers = 0; AWTEvent currentEvent = EventQueue.getCurrentEvent(); if (currentEvent instanceof InputEvent) { modifiers = ((InputEvent)currentEvent).getModifiers(); } else if (currentEvent instanceof ActionEvent) { modifiers = ((ActionEvent)currentEvent).getModifiers(); } return modifiers; } private static final Object KEYMAP_TABLE = new StringBuilder("JTextComponent_KeymapTable"); // // member variables used for on-the-spot input method // editing style support // private transient InputMethodRequests inputMethodRequestsHandler; private SimpleAttributeSet composedTextAttribute; private String composedTextContent; private Position composedTextStart; private Position composedTextEnd; private Position latestCommittedTextStart; private Position latestCommittedTextEnd; private ComposedTextCaret composedTextCaret; private transient Caret originalCaret; /** * Set to true after the check for the override of processInputMethodEvent * has been checked. */ private boolean checkedInputOverride; private boolean needToSendKeyTypedEvent; static class DefaultKeymap implements Keymap { DefaultKeymap(String nm, Keymap parent) { this.nm = nm; this.parent = parent; bindings = new Hashtable<KeyStroke, Action>(); } /** * Fetch the default action to fire if a * key is typed (ie a KEY_TYPED KeyEvent is received) * and there is no binding for it. Typically this * would be some action that inserts text so that * the keymap doesn't require an action for each * possible key. */ public Action getDefaultAction() { if (defaultAction != null) { return defaultAction; } return (parent != null) ? parent.getDefaultAction() : null; } /** * Set the default action to fire if a key is typed. */ public void setDefaultAction(Action a) { defaultAction = a; } public String getName() { return nm; } public Action getAction(KeyStroke key) { Action a = bindings.get(key); if ((a == null) && (parent != null)) { a = parent.getAction(key); } return a; } public KeyStroke[] getBoundKeyStrokes() { KeyStroke[] keys = new KeyStroke[bindings.size()]; int i = 0; for (Enumeration<KeyStroke> e = bindings.keys() ; e.hasMoreElements() ;) { keys[i++] = e.nextElement(); } return keys; } public Action[] getBoundActions() { Action[] actions = new Action[bindings.size()]; int i = 0; for (Enumeration<Action> e = bindings.elements() ; e.hasMoreElements() ;) { actions[i++] = e.nextElement(); } return actions; } public KeyStroke[] getKeyStrokesForAction(Action a) { if (a == null) { return null; } KeyStroke[] retValue = null; // Determine local bindings first. Vector<KeyStroke> keyStrokes = null; for (Enumeration<KeyStroke> keys = bindings.keys(); keys.hasMoreElements();) { KeyStroke key = keys.nextElement(); if (bindings.get(key) == a) { if (keyStrokes == null) { keyStrokes = new Vector<KeyStroke>(); } keyStrokes.addElement(key); } } // See if the parent has any. if (parent != null) { KeyStroke[] pStrokes = parent.getKeyStrokesForAction(a); if (pStrokes != null) { // Remove any bindings defined in the parent that // are locally defined. int rCount = 0; for (int counter = pStrokes.length - 1; counter >= 0; counter--) { if (isLocallyDefined(pStrokes[counter])) { pStrokes[counter] = null; rCount++; } } if (rCount > 0 && rCount < pStrokes.length) { if (keyStrokes == null) { keyStrokes = new Vector<KeyStroke>(); } for (int counter = pStrokes.length - 1; counter >= 0; counter--) { if (pStrokes[counter] != null) { keyStrokes.addElement(pStrokes[counter]); } } } else if (rCount == 0) { if (keyStrokes == null) { retValue = pStrokes; } else { retValue = new KeyStroke[keyStrokes.size() + pStrokes.length]; keyStrokes.copyInto(retValue); System.arraycopy(pStrokes, 0, retValue, keyStrokes.size(), pStrokes.length); keyStrokes = null; } } } } if (keyStrokes != null) { retValue = new KeyStroke[keyStrokes.size()]; keyStrokes.copyInto(retValue); } return retValue; } public boolean isLocallyDefined(KeyStroke key) { return bindings.containsKey(key); } public void addActionForKeyStroke(KeyStroke key, Action a) { bindings.put(key, a); } public void removeKeyStrokeBinding(KeyStroke key) { bindings.remove(key); } public void removeBindings() { bindings.clear(); } public Keymap getResolveParent() { return parent; } public void setResolveParent(Keymap parent) { this.parent = parent; } /** * String representation of the keymap... potentially * a very long string. */ public String toString() { return "Keymap[" + nm + "]" + bindings; } String nm; Keymap parent; Hashtable<KeyStroke, Action> bindings; Action defaultAction; } /** * KeymapWrapper wraps a Keymap inside an InputMap. For KeymapWrapper * to be useful it must be used with a KeymapActionMap. * KeymapWrapper for the most part, is an InputMap with two parents. * The first parent visited is ALWAYS the Keymap, with the second * parent being the parent inherited from InputMap. If * <code>keymap.getAction</code> returns null, implying the Keymap * does not have a binding for the KeyStroke, * the parent is then visited. If the Keymap has a binding, the * Action is returned, if not and the KeyStroke represents a * KeyTyped event and the Keymap has a defaultAction, * <code>DefaultActionKey</code> is returned. * <p>KeymapActionMap is then able to transate the object passed in * to either message the Keymap, or message its default implementation. */ static class KeymapWrapper extends InputMap { static final Object DefaultActionKey = new Object(); private Keymap keymap; KeymapWrapper(Keymap keymap) { this.keymap = keymap; } public KeyStroke[] keys() { KeyStroke[] sKeys = super.keys(); KeyStroke[] keymapKeys = keymap.getBoundKeyStrokes(); int sCount = (sKeys == null) ? 0 : sKeys.length; int keymapCount = (keymapKeys == null) ? 0 : keymapKeys.length; if (sCount == 0) { return keymapKeys; } if (keymapCount == 0) { return sKeys; } KeyStroke[] retValue = new KeyStroke[sCount + keymapCount]; // There may be some duplication here... System.arraycopy(sKeys, 0, retValue, 0, sCount); System.arraycopy(keymapKeys, 0, retValue, sCount, keymapCount); return retValue; } public int size() { // There may be some duplication here... KeyStroke[] keymapStrokes = keymap.getBoundKeyStrokes(); int keymapCount = (keymapStrokes == null) ? 0: keymapStrokes.length; return super.size() + keymapCount; } public Object get(KeyStroke keyStroke) { Object retValue = keymap.getAction(keyStroke); if (retValue == null) { retValue = super.get(keyStroke); if (retValue == null && keyStroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED && keymap.getDefaultAction() != null) { // Implies this is a KeyTyped event, use the default // action. retValue = DefaultActionKey; } } return retValue; } } /** * Wraps a Keymap inside an ActionMap. This is used with * a KeymapWrapper. If <code>get</code> is passed in * <code>KeymapWrapper.DefaultActionKey</code>, the default action is * returned, otherwise if the key is an Action, it is returned. */ static class KeymapActionMap extends ActionMap { private Keymap keymap; KeymapActionMap(Keymap keymap) { this.keymap = keymap; } public Object[] keys() { Object[] sKeys = super.keys(); Object[] keymapKeys = keymap.getBoundActions(); int sCount = (sKeys == null) ? 0 : sKeys.length; int keymapCount = (keymapKeys == null) ? 0 : keymapKeys.length; boolean hasDefault = (keymap.getDefaultAction() != null); if (hasDefault) { keymapCount++; } if (sCount == 0) { if (hasDefault) { Object[] retValue = new Object[keymapCount]; if (keymapCount > 1) { System.arraycopy(keymapKeys, 0, retValue, 0, keymapCount - 1); } retValue[keymapCount - 1] = KeymapWrapper.DefaultActionKey; return retValue; } return keymapKeys; } if (keymapCount == 0) { return sKeys; } Object[] retValue = new Object[sCount + keymapCount]; // There may be some duplication here... System.arraycopy(sKeys, 0, retValue, 0, sCount); if (hasDefault) { if (keymapCount > 1) { System.arraycopy(keymapKeys, 0, retValue, sCount, keymapCount - 1); } retValue[sCount + keymapCount - 1] = KeymapWrapper. DefaultActionKey; } else { System.arraycopy(keymapKeys, 0, retValue, sCount, keymapCount); } return retValue; } public int size() { // There may be some duplication here... Object[] actions = keymap.getBoundActions(); int keymapCount = (actions == null) ? 0 : actions.length; if (keymap.getDefaultAction() != null) { keymapCount++; } return super.size() + keymapCount; } public Action get(Object key) { Action retValue = super.get(key); if (retValue == null) { // Try the Keymap. if (key == KeymapWrapper.DefaultActionKey) { retValue = keymap.getDefaultAction(); } else if (key instanceof Action) { // This is a little iffy, technically an Action is // a valid Key. We're assuming the Action came from // the InputMap though. retValue = (Action)key; } } return retValue; } } private static final Object FOCUSED_COMPONENT = new StringBuilder("JTextComponent_FocusedComponent"); /** * The default keymap that will be shared by all * <code>JTextComponent</code> instances unless they * have had a different keymap set. */ public static final String DEFAULT_KEYMAP = "default"; /** * Event to use when firing a notification of change to caret * position. This is mutable so that the event can be reused * since caret events can be fairly high in bandwidth. */ static class MutableCaretEvent extends CaretEvent implements ChangeListener, FocusListener, MouseListener { MutableCaretEvent(JTextComponent c) { super(c); } final void fire() { JTextComponent c = (JTextComponent) getSource(); if (c != null) { Caret caret = c.getCaret(); dot = caret.getDot(); mark = caret.getMark(); c.fireCaretUpdate(this); } } public final String toString() { return "dot=" + dot + "," + "mark=" + mark; } // --- CaretEvent methods ----------------------- public final int getDot() { return dot; } public final int getMark() { return mark; } // --- ChangeListener methods ------------------- public final void stateChanged(ChangeEvent e) { if (! dragActive) { fire(); } } // --- FocusListener methods ----------------------------------- public void focusGained(FocusEvent fe) { AppContext.getAppContext().put(FOCUSED_COMPONENT, fe.getSource()); } public void focusLost(FocusEvent fe) { } // --- MouseListener methods ----------------------------------- /** * Requests focus on the associated * text component, and try to set the cursor position. * * @param e the mouse event * @see MouseListener#mousePressed */ public final void mousePressed(MouseEvent e) { dragActive = true; } /** * Called when the mouse is released. * * @param e the mouse event * @see MouseListener#mouseReleased */ public final void mouseReleased(MouseEvent e) { dragActive = false; fire(); } public final void mouseClicked(MouseEvent e) { } public final void mouseEntered(MouseEvent e) { } public final void mouseExited(MouseEvent e) { } private boolean dragActive; private int dot; private int mark; } // // Process any input method events that the component itself // recognizes. The default on-the-spot handling for input method // composed(uncommitted) text is done here after all input // method listeners get called for stealing the events. // protected void processInputMethodEvent(InputMethodEvent e) { // let listeners handle the events super.processInputMethodEvent(e); if (!e.isConsumed()) {Lines 4001–4500 of 5073. Previous lines Load more
try { String data = (String)t.getTransferData(flavor); ((JTextComponent)comp).replaceSelection(data); return true; } catch (UnsupportedFlavorException ufe) { } catch (IOException ioe) { } } } return false; } public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) { JTextComponent c = (JTextComponent)comp; if (!(c.isEditable() && c.isEnabled())) { return false; } return (getFlavor(transferFlavors) != null); } public int getSourceActions(JComponent c) { return NONE; } private DataFlavor getFlavor(DataFlavor[] flavors) { if (flavors != null) { for (DataFlavor flavor : flavors) { if (flavor.equals(DataFlavor.stringFlavor)) { return flavor; } } } return null; } } /** * Returns the JTextComponent that most recently had focus. The returned * value may currently have focus. */ static final JTextComponent getFocusedComponent() { return (JTextComponent)AppContext.getAppContext(). get(FOCUSED_COMPONENT); } private int getCurrentEventModifiers() { int modifiers = 0; AWTEvent currentEvent = EventQueue.getCurrentEvent(); if (currentEvent instanceof InputEvent) { modifiers = ((InputEvent)currentEvent).getModifiers(); } else if (currentEvent instanceof ActionEvent) { modifiers = ((ActionEvent)currentEvent).getModifiers(); } return modifiers; } private static final Object KEYMAP_TABLE = new StringBuilder("JTextComponent_KeymapTable"); // // member variables used for on-the-spot input method // editing style support // private transient InputMethodRequests inputMethodRequestsHandler; private SimpleAttributeSet composedTextAttribute; private String composedTextContent; private Position composedTextStart; private Position composedTextEnd; private Position latestCommittedTextStart; private Position latestCommittedTextEnd; private ComposedTextCaret composedTextCaret; private transient Caret originalCaret; /** * Set to true after the check for the override of processInputMethodEvent * has been checked. */ private boolean checkedInputOverride; private boolean needToSendKeyTypedEvent; static class DefaultKeymap implements Keymap { DefaultKeymap(String nm, Keymap parent) { this.nm = nm; this.parent = parent; bindings = new Hashtable<KeyStroke, Action>(); } /** * Fetch the default action to fire if a * key is typed (ie a KEY_TYPED KeyEvent is received) * and there is no binding for it. Typically this * would be some action that inserts text so that * the keymap doesn't require an action for each * possible key. */ public Action getDefaultAction() { if (defaultAction != null) { return defaultAction; } return (parent != null) ? parent.getDefaultAction() : null; } /** * Set the default action to fire if a key is typed. */ public void setDefaultAction(Action a) { defaultAction = a; } public String getName() { return nm; } public Action getAction(KeyStroke key) { Action a = bindings.get(key); if ((a == null) && (parent != null)) { a = parent.getAction(key); } return a; } public KeyStroke[] getBoundKeyStrokes() { KeyStroke[] keys = new KeyStroke[bindings.size()]; int i = 0; for (Enumeration<KeyStroke> e = bindings.keys() ; e.hasMoreElements() ;) { keys[i++] = e.nextElement(); } return keys; } public Action[] getBoundActions() { Action[] actions = new Action[bindings.size()]; int i = 0; for (Enumeration<Action> e = bindings.elements() ; e.hasMoreElements() ;) { actions[i++] = e.nextElement(); } return actions; } public KeyStroke[] getKeyStrokesForAction(Action a) { if (a == null) { return null; } KeyStroke[] retValue = null; // Determine local bindings first. Vector<KeyStroke> keyStrokes = null; for (Enumeration<KeyStroke> keys = bindings.keys(); keys.hasMoreElements();) { KeyStroke key = keys.nextElement(); if (bindings.get(key) == a) { if (keyStrokes == null) { keyStrokes = new Vector<KeyStroke>(); } keyStrokes.addElement(key); } } // See if the parent has any. if (parent != null) { KeyStroke[] pStrokes = parent.getKeyStrokesForAction(a); if (pStrokes != null) { // Remove any bindings defined in the parent that // are locally defined. int rCount = 0; for (int counter = pStrokes.length - 1; counter >= 0; counter--) { if (isLocallyDefined(pStrokes[counter])) { pStrokes[counter] = null; rCount++; } } if (rCount > 0 && rCount < pStrokes.length) { if (keyStrokes == null) { keyStrokes = new Vector<KeyStroke>(); } for (int counter = pStrokes.length - 1; counter >= 0; counter--) { if (pStrokes[counter] != null) { keyStrokes.addElement(pStrokes[counter]); } } } else if (rCount == 0) { if (keyStrokes == null) { retValue = pStrokes; } else { retValue = new KeyStroke[keyStrokes.size() + pStrokes.length]; keyStrokes.copyInto(retValue); System.arraycopy(pStrokes, 0, retValue, keyStrokes.size(), pStrokes.length); keyStrokes = null; } } } } if (keyStrokes != null) { retValue = new KeyStroke[keyStrokes.size()]; keyStrokes.copyInto(retValue); } return retValue; } public boolean isLocallyDefined(KeyStroke key) { return bindings.containsKey(key); } public void addActionForKeyStroke(KeyStroke key, Action a) { bindings.put(key, a); } public void removeKeyStrokeBinding(KeyStroke key) { bindings.remove(key); } public void removeBindings() { bindings.clear(); } public Keymap getResolveParent() { return parent; } public void setResolveParent(Keymap parent) { this.parent = parent; } /** * String representation of the keymap... potentially * a very long string. */ public String toString() { return "Keymap[" + nm + "]" + bindings; } String nm; Keymap parent; Hashtable<KeyStroke, Action> bindings; Action defaultAction; } /** * KeymapWrapper wraps a Keymap inside an InputMap. For KeymapWrapper * to be useful it must be used with a KeymapActionMap. * KeymapWrapper for the most part, is an InputMap with two parents. * The first parent visited is ALWAYS the Keymap, with the second * parent being the parent inherited from InputMap. If * <code>keymap.getAction</code> returns null, implying the Keymap * does not have a binding for the KeyStroke, * the parent is then visited. If the Keymap has a binding, the * Action is returned, if not and the KeyStroke represents a * KeyTyped event and the Keymap has a defaultAction, * <code>DefaultActionKey</code> is returned. * <p>KeymapActionMap is then able to transate the object passed in * to either message the Keymap, or message its default implementation. */ static class KeymapWrapper extends InputMap { static final Object DefaultActionKey = new Object(); private Keymap keymap; KeymapWrapper(Keymap keymap) { this.keymap = keymap; } public KeyStroke[] keys() { KeyStroke[] sKeys = super.keys(); KeyStroke[] keymapKeys = keymap.getBoundKeyStrokes(); int sCount = (sKeys == null) ? 0 : sKeys.length; int keymapCount = (keymapKeys == null) ? 0 : keymapKeys.length; if (sCount == 0) { return keymapKeys; } if (keymapCount == 0) { return sKeys; } KeyStroke[] retValue = new KeyStroke[sCount + keymapCount]; // There may be some duplication here... System.arraycopy(sKeys, 0, retValue, 0, sCount); System.arraycopy(keymapKeys, 0, retValue, sCount, keymapCount); return retValue; } public int size() { // There may be some duplication here... KeyStroke[] keymapStrokes = keymap.getBoundKeyStrokes(); int keymapCount = (keymapStrokes == null) ? 0: keymapStrokes.length; return super.size() + keymapCount; } public Object get(KeyStroke keyStroke) { Object retValue = keymap.getAction(keyStroke); if (retValue == null) { retValue = super.get(keyStroke); if (retValue == null && keyStroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED && keymap.getDefaultAction() != null) { // Implies this is a KeyTyped event, use the default // action. retValue = DefaultActionKey; } } return retValue; } } /** * Wraps a Keymap inside an ActionMap. This is used with * a KeymapWrapper. If <code>get</code> is passed in * <code>KeymapWrapper.DefaultActionKey</code>, the default action is * returned, otherwise if the key is an Action, it is returned. */ static class KeymapActionMap extends ActionMap { private Keymap keymap; KeymapActionMap(Keymap keymap) { this.keymap = keymap; } public Object[] keys() { Object[] sKeys = super.keys(); Object[] keymapKeys = keymap.getBoundActions(); int sCount = (sKeys == null) ? 0 : sKeys.length; int keymapCount = (keymapKeys == null) ? 0 : keymapKeys.length; boolean hasDefault = (keymap.getDefaultAction() != null); if (hasDefault) { keymapCount++; } if (sCount == 0) { if (hasDefault) { Object[] retValue = new Object[keymapCount]; if (keymapCount > 1) { System.arraycopy(keymapKeys, 0, retValue, 0, keymapCount - 1); } retValue[keymapCount - 1] = KeymapWrapper.DefaultActionKey; return retValue; } return keymapKeys; } if (keymapCount == 0) { return sKeys; } Object[] retValue = new Object[sCount + keymapCount]; // There may be some duplication here... System.arraycopy(sKeys, 0, retValue, 0, sCount); if (hasDefault) { if (keymapCount > 1) { System.arraycopy(keymapKeys, 0, retValue, sCount, keymapCount - 1); } retValue[sCount + keymapCount - 1] = KeymapWrapper. DefaultActionKey; } else { System.arraycopy(keymapKeys, 0, retValue, sCount, keymapCount); } return retValue; } public int size() { // There may be some duplication here... Object[] actions = keymap.getBoundActions(); int keymapCount = (actions == null) ? 0 : actions.length; if (keymap.getDefaultAction() != null) { keymapCount++; } return super.size() + keymapCount; } public Action get(Object key) { Action retValue = super.get(key); if (retValue == null) { // Try the Keymap. if (key == KeymapWrapper.DefaultActionKey) { retValue = keymap.getDefaultAction(); } else if (key instanceof Action) { // This is a little iffy, technically an Action is // a valid Key. We're assuming the Action came from // the InputMap though. retValue = (Action)key; } } return retValue; } } private static final Object FOCUSED_COMPONENT = new StringBuilder("JTextComponent_FocusedComponent"); /** * The default keymap that will be shared by all * <code>JTextComponent</code> instances unless they * have had a different keymap set. */ public static final String DEFAULT_KEYMAP = "default"; /** * Event to use when firing a notification of change to caret * position. This is mutable so that the event can be reused * since caret events can be fairly high in bandwidth. */ static class MutableCaretEvent extends CaretEvent implements ChangeListener, FocusListener, MouseListener { MutableCaretEvent(JTextComponent c) { super(c); } final void fire() { JTextComponent c = (JTextComponent) getSource(); if (c != null) { Caret caret = c.getCaret(); dot = caret.getDot(); mark = caret.getMark(); c.fireCaretUpdate(this); } } public final String toString() { return "dot=" + dot + "," + "mark=" + mark; } // --- CaretEvent methods ----------------------- public final int getDot() { return dot; } public final int getMark() { return mark; } // --- ChangeListener methods ------------------- public final void stateChanged(ChangeEvent e) { if (! dragActive) { fire(); } } // --- FocusListener methods ----------------------------------- public void focusGained(FocusEvent fe) { AppContext.getAppContext().put(FOCUSED_COMPONENT, fe.getSource()); } public void focusLost(FocusEvent fe) { } // --- MouseListener methods ----------------------------------- /** * Requests focus on the associated * text component, and try to set the cursor position. * * @param e the mouse event * @see MouseListener#mousePressed */ public final void mousePressed(MouseEvent e) { dragActive = true; } /** * Called when the mouse is released. * * @param e the mouse event * @see MouseListener#mouseReleased */ public final void mouseReleased(MouseEvent e) { dragActive = false; fire(); } public final void mouseClicked(MouseEvent e) { } public final void mouseEntered(MouseEvent e) { } public final void mouseExited(MouseEvent e) { } private boolean dragActive; private int dot; private int mark; } // // Process any input method events that the component itself // recognizes. The default on-the-spot handling for input method // composed(uncommitted) text is done here after all input // method listeners get called for stealing the events. // protected void processInputMethodEvent(InputMethodEvent e) { // let listeners handle the events super.processInputMethodEvent(e); if (!e.isConsumed()) {