newKM.setParent(km.getParent()); km.setParent(newKM); } } // Do the same thing with the ActionMap ActionMap am = getActionMap(); ActionMap lastAM = am; while (am != null && !(am instanceof KeymapActionMap)) { lastAM = am; am = am.getParent(); } if (am != null) { // Found it, tweak the Actionap that points to it, as well // as anything it points to. if (newKm == null) { if (lastAM != am) { lastAM.setParent(am.getParent()); } else { lastAM.setParent(null); } } else { ActionMap newAM = new KeymapActionMap(newKm); lastAM.setParent(newAM); if (lastAM != am) { newAM.setParent(am.getParent()); } } } else if (newKm != null) { am = getActionMap(); if (am != null) { // Couldn't find it. // Set the parent of ActionMap to be the new one. ActionMap newAM = new KeymapActionMap(newKm); newAM.setParent(am.getParent()); am.setParent(newAM); } } } /** * Fetches the keymap currently active in this text * component. * * @return the keymap */ public Keymap getKeymap() { return keymap; } /** * Adds a new keymap into the keymap hierarchy. Keymap bindings * resolve from bottom up so an attribute specified in a child * will override an attribute specified in the parent. * * @param nm the name of the keymap (must be unique within the * collection of named keymaps in the document); the name may * be <code>null</code> if the keymap is unnamed, * but the caller is responsible for managing the reference * returned as an unnamed keymap can't * be fetched by name * @param parent the parent keymap; this may be <code>null</code> if * unspecified bindings need not be resolved in some other keymap * @return the keymap */ public static Keymap addKeymap(String nm, Keymap parent) { Keymap map = new DefaultKeymap(nm, parent); if (nm != null) { // add a named keymap, a class of bindings getKeymapTable().put(nm, map); } return map; } /** * Removes a named keymap previously added to the document. Keymaps * with <code>null</code> names may not be removed in this way. * * @param nm the name of the keymap to remove * @return the keymap that was removed */ public static Keymap removeKeymap(String nm) { return getKeymapTable().remove(nm); } /** * Fetches a named keymap previously added to the document. * This does not work with <code>null</code>-named keymaps. * * @param nm the name of the keymap * @return the keymap */ public static Keymap getKeymap(String nm) { return getKeymapTable().get(nm); } private static HashMap<String,Keymap> getKeymapTable() { synchronized (KEYMAP_TABLE) { AppContext appContext = AppContext.getAppContext(); HashMap<String,Keymap> keymapTable = (HashMap<String,Keymap>)appContext.get(KEYMAP_TABLE); if (keymapTable == null) { keymapTable = new HashMap<String,Keymap>(17); appContext.put(KEYMAP_TABLE, keymapTable); //initialize default keymap Keymap binding = addKeymap(DEFAULT_KEYMAP, null); binding.setDefaultAction(new DefaultEditorKit.DefaultKeyTypedAction()); } return keymapTable; } } /** * Binding record for creating key bindings. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. */ public static class KeyBinding { /** * The key. */ public KeyStroke key; /** * The name of the action for the key. */ public String actionName; /** * Creates a new key binding. * * @param key the key * @param actionName the name of the action for the key */ public KeyBinding(KeyStroke key, String actionName) { this.key = key; this.actionName = actionName; } } /** * <p> * Loads a keymap with a bunch of * bindings. This can be used to take a static table of * definitions and load them into some keymap. The following * example illustrates an example of binding some keys to * the cut, copy, and paste actions associated with a * JTextComponent. A code fragment to accomplish * this might look as follows: * <pre><code> * * static final JTextComponent.KeyBinding[] defaultBindings = { * new JTextComponent.KeyBinding( * KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK), * DefaultEditorKit.copyAction), * new JTextComponent.KeyBinding( * KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK), * DefaultEditorKit.pasteAction), * new JTextComponent.KeyBinding( * KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK), * DefaultEditorKit.cutAction), * }; * * JTextComponent c = new JTextPane(); * Keymap k = c.getKeymap(); * JTextComponent.loadKeymap(k, defaultBindings, c.getActions()); * * </code></pre> * The sets of bindings and actions may be empty but must be * non-<code>null</code>. * * @param map the keymap * @param bindings the bindings * @param actions the set of actions */ public static void loadKeymap(Keymap map, KeyBinding[] bindings, Action[] actions) { Hashtable<String, Action> h = new Hashtable<String, Action>(); for (Action a : actions) { String value = (String)a.getValue(Action.NAME); h.put((value!=null ? value:""), a); } for (KeyBinding binding : bindings) { Action a = h.get(binding.actionName); if (a != null) { map.addActionForKeyStroke(binding.key, a); } } } /** * Returns true if <code>klass</code> is NOT a JTextComponent and it or * one of its superclasses (stoping at JTextComponent) overrides * <code>processInputMethodEvent</code>. It is assumed this will be * invoked from within a <code>doPrivileged</code>, and it is also * assumed <code>klass</code> extends <code>JTextComponent</code>. */ private static Boolean isProcessInputMethodEventOverridden(Class<?> klass) { if (klass == JTextComponent.class) { return Boolean.FALSE; } Boolean retValue = overrideMap.get(klass.getName()); if (retValue != null) { return retValue; } Boolean sOverriden = isProcessInputMethodEventOverridden( klass.getSuperclass()); if (sOverriden.booleanValue()) { // If our superclass has overriden it, then by definition klass // overrides it. overrideMap.put(klass.getName(), sOverriden); return sOverriden; } // klass's superclass didn't override it, check for an override in // klass. try { Class[] classes = new Class[1]; classes[0] = InputMethodEvent.class; Method m = klass.getDeclaredMethod("processInputMethodEvent", classes); retValue = Boolean.TRUE; } catch (NoSuchMethodException nsme) { retValue = Boolean.FALSE; } overrideMap.put(klass.getName(), retValue); return retValue; } /** * Fetches the current color used to render the * caret. * * @return the color */ public Color getCaretColor() { return caretColor; } /** * Sets the current color used to render the caret. * Setting to <code>null</code> effectively restores the default color. * Setting the color results in a PropertyChange event ("caretColor") * being fired. * * @param c the color * @see #getCaretColor * @beaninfo * description: the color used to render the caret * bound: true * preferred: true */ public void setCaretColor(Color c) { Color old = caretColor; caretColor = c; firePropertyChange("caretColor", old, caretColor); } /** * Fetches the current color used to render the * selection. * * @return the color */ public Color getSelectionColor() { return selectionColor; } /** * Sets the current color used to render the selection. * Setting the color to <code>null</code> is the same as setting * <code>Color.white</code>. Setting the color results in a * PropertyChange event ("selectionColor"). * * @param c the color * @see #getSelectionColor * @beaninfo * description: color used to render selection background * bound: true * preferred: true */ public void setSelectionColor(Color c) { Color old = selectionColor; selectionColor = c; firePropertyChange("selectionColor", old, selectionColor); } /** * Fetches the current color used to render the * selected text. * * @return the color */ public Color getSelectedTextColor() { return selectedTextColor; } /** * Sets the current color used to render the selected text. * Setting the color to <code>null</code> is the same as * <code>Color.black</code>. Setting the color results in a * PropertyChange event ("selectedTextColor") being fired. * * @param c the color * @see #getSelectedTextColor * @beaninfo * description: color used to render selected text * bound: true * preferred: true */ public void setSelectedTextColor(Color c) { Color old = selectedTextColor; selectedTextColor = c; firePropertyChange("selectedTextColor", old, selectedTextColor); } /** * Fetches the current color used to render the * disabled text. * * @return the color */ public Color getDisabledTextColor() { return disabledTextColor; } /** * Sets the current color used to render the * disabled text. Setting the color fires off a * PropertyChange event ("disabledTextColor"). * * @param c the color * @see #getDisabledTextColor * @beaninfo * description: color used to render disabled text * bound: true * preferred: true */ public void setDisabledTextColor(Color c) { Color old = disabledTextColor; disabledTextColor = c; firePropertyChange("disabledTextColor", old, disabledTextColor); } /** * Replaces the currently selected content with new content * represented by the given string. If there is no selection * this amounts to an insert of the given text. If there * is no replacement text this amounts to a removal of the * current selection. * <p> * This is the method that is used by the default implementation * of the action for inserting content that gets bound to the * keymap actions. * * @param content the content to replace the selection with */ public void replaceSelection(String content) { Document doc = getDocument(); if (doc != null) { try { boolean composedTextSaved = saveComposedText(caret.getDot()); int p0 = Math.min(caret.getDot(), caret.getMark()); int p1 = Math.max(caret.getDot(), caret.getMark()); if (doc instanceof AbstractDocument) { ((AbstractDocument)doc).replace(p0, p1 - p0, content,null); } else { if (p0 != p1) { doc.remove(p0, p1 - p0); } if (content != null && content.length() > 0) { doc.insertString(p0, content, null); } } if (composedTextSaved) { restoreComposedText(); } } catch (BadLocationException e) { UIManager.getLookAndFeel().provideErrorFeedback(JTextComponent.this); } } } /** * Fetches a portion of the text represented by the * component. Returns an empty string if length is 0. * * @param offs the offset >= 0 * @param len the length >= 0 * @return the text * @exception BadLocationException if the offset or length are invalid */ public String getText(int offs, int len) throws BadLocationException { return getDocument().getText(offs, len); } /** * Converts the given location in the model to a place in * the view coordinate system. * The component must have a positive size for * this translation to be computed (i.e. layout cannot * be computed until the component has been sized). The * component does not have to be visible or painted. * * @param pos the position >= 0 * @return the coordinates as a rectangle, with (r.x, r.y) as the location * in the coordinate system, or null if the component does * not yet have a positive size. * @exception BadLocationException if the given position does not * represent a valid location in the associated document * @see TextUI#modelToView */ public Rectangle modelToView(int pos) throws BadLocationException { return getUI().modelToView(this, pos); } /** * Converts the given place in the view coordinate system * to the nearest representative location in the model. * The component must have a positive size for * this translation to be computed (i.e. layout cannot * be computed until the component has been sized). The * component does not have to be visible or painted. * * @param pt the location in the view to translate * @return the offset >= 0 from the start of the document, * or -1 if the component does not yet have a positive * size. * @see TextUI#viewToModel */ public int viewToModel(Point pt) { return getUI().viewToModel(this, pt); } /** * Transfers the currently selected range in the associated * text model to the system clipboard, removing the contents * from the model. The current selection is reset. Does nothing * for <code>null</code> selections. * * @see java.awt.Toolkit#getSystemClipboard * @see java.awt.datatransfer.Clipboard */ public void cut() { if (isEditable() && isEnabled()) { invokeAction("cut", TransferHandler.getCutAction()); } } /** * Transfers the currently selected range in the associated * text model to the system clipboard, leaving the contents * in the text model. The current selection remains intact. * Does nothing for <code>null</code> selections. * * @see java.awt.Toolkit#getSystemClipboard * @see java.awt.datatransfer.Clipboard */ public void copy() { invokeAction("copy", TransferHandler.getCopyAction()); } /** * Transfers the contents of the system clipboard into the * associated text model. If there is a selection in the * associated view, it is replaced with the contents of the * clipboard. If there is no selection, the clipboard contents * are inserted in front of the current insert position in * the associated view. If the clipboard is empty, does nothing. * * @see #replaceSelection * @see java.awt.Toolkit#getSystemClipboard * @see java.awt.datatransfer.Clipboard */ public void paste() { if (isEditable() && isEnabled()) { invokeAction("paste", TransferHandler.getPasteAction()); } } /** * This is a conveniance method that is only useful for * <code>cut</code>, <code>copy</code> and <code>paste</code>. If * an <code>Action</code> with the name <code>name</code> does not * exist in the <code>ActionMap</code>, this will attemp to install a * <code>TransferHandler</code> and then use <code>altAction</code>.Lines 1001–1500 of 5073. Previous lines Load more
newKM.setParent(km.getParent()); km.setParent(newKM); } } // Do the same thing with the ActionMap ActionMap am = getActionMap(); ActionMap lastAM = am; while (am != null && !(am instanceof KeymapActionMap)) { lastAM = am; am = am.getParent(); } if (am != null) { // Found it, tweak the Actionap that points to it, as well // as anything it points to. if (newKm == null) { if (lastAM != am) { lastAM.setParent(am.getParent()); } else { lastAM.setParent(null); } } else { ActionMap newAM = new KeymapActionMap(newKm); lastAM.setParent(newAM); if (lastAM != am) { newAM.setParent(am.getParent()); } } } else if (newKm != null) { am = getActionMap(); if (am != null) { // Couldn't find it. // Set the parent of ActionMap to be the new one. ActionMap newAM = new KeymapActionMap(newKm); newAM.setParent(am.getParent()); am.setParent(newAM); } } } /** * Fetches the keymap currently active in this text * component. * * @return the keymap */ public Keymap getKeymap() { return keymap; } /** * Adds a new keymap into the keymap hierarchy. Keymap bindings * resolve from bottom up so an attribute specified in a child * will override an attribute specified in the parent. * * @param nm the name of the keymap (must be unique within the * collection of named keymaps in the document); the name may * be <code>null</code> if the keymap is unnamed, * but the caller is responsible for managing the reference * returned as an unnamed keymap can't * be fetched by name * @param parent the parent keymap; this may be <code>null</code> if * unspecified bindings need not be resolved in some other keymap * @return the keymap */ public static Keymap addKeymap(String nm, Keymap parent) { Keymap map = new DefaultKeymap(nm, parent); if (nm != null) { // add a named keymap, a class of bindings getKeymapTable().put(nm, map); } return map; } /** * Removes a named keymap previously added to the document. Keymaps * with <code>null</code> names may not be removed in this way. * * @param nm the name of the keymap to remove * @return the keymap that was removed */ public static Keymap removeKeymap(String nm) { return getKeymapTable().remove(nm); } /** * Fetches a named keymap previously added to the document. * This does not work with <code>null</code>-named keymaps. * * @param nm the name of the keymap * @return the keymap */ public static Keymap getKeymap(String nm) { return getKeymapTable().get(nm); } private static HashMap<String,Keymap> getKeymapTable() { synchronized (KEYMAP_TABLE) { AppContext appContext = AppContext.getAppContext(); HashMap<String,Keymap> keymapTable = (HashMap<String,Keymap>)appContext.get(KEYMAP_TABLE); if (keymapTable == null) { keymapTable = new HashMap<String,Keymap>(17); appContext.put(KEYMAP_TABLE, keymapTable); //initialize default keymap Keymap binding = addKeymap(DEFAULT_KEYMAP, null); binding.setDefaultAction(new DefaultEditorKit.DefaultKeyTypedAction()); } return keymapTable; } } /** * Binding record for creating key bindings. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. */ public static class KeyBinding { /** * The key. */ public KeyStroke key; /** * The name of the action for the key. */ public String actionName; /** * Creates a new key binding. * * @param key the key * @param actionName the name of the action for the key */ public KeyBinding(KeyStroke key, String actionName) { this.key = key; this.actionName = actionName; } } /** * <p> * Loads a keymap with a bunch of * bindings. This can be used to take a static table of * definitions and load them into some keymap. The following * example illustrates an example of binding some keys to * the cut, copy, and paste actions associated with a * JTextComponent. A code fragment to accomplish * this might look as follows: * <pre><code> * * static final JTextComponent.KeyBinding[] defaultBindings = { * new JTextComponent.KeyBinding( * KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK), * DefaultEditorKit.copyAction), * new JTextComponent.KeyBinding( * KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK), * DefaultEditorKit.pasteAction), * new JTextComponent.KeyBinding( * KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK), * DefaultEditorKit.cutAction), * }; * * JTextComponent c = new JTextPane(); * Keymap k = c.getKeymap(); * JTextComponent.loadKeymap(k, defaultBindings, c.getActions()); * * </code></pre> * The sets of bindings and actions may be empty but must be * non-<code>null</code>. * * @param map the keymap * @param bindings the bindings * @param actions the set of actions */ public static void loadKeymap(Keymap map, KeyBinding[] bindings, Action[] actions) { Hashtable<String, Action> h = new Hashtable<String, Action>(); for (Action a : actions) { String value = (String)a.getValue(Action.NAME); h.put((value!=null ? value:""), a); } for (KeyBinding binding : bindings) { Action a = h.get(binding.actionName); if (a != null) { map.addActionForKeyStroke(binding.key, a); } } } /** * Returns true if <code>klass</code> is NOT a JTextComponent and it or * one of its superclasses (stoping at JTextComponent) overrides * <code>processInputMethodEvent</code>. It is assumed this will be * invoked from within a <code>doPrivileged</code>, and it is also * assumed <code>klass</code> extends <code>JTextComponent</code>. */ private static Boolean isProcessInputMethodEventOverridden(Class<?> klass) { if (klass == JTextComponent.class) { return Boolean.FALSE; } Boolean retValue = overrideMap.get(klass.getName()); if (retValue != null) { return retValue; } Boolean sOverriden = isProcessInputMethodEventOverridden( klass.getSuperclass()); if (sOverriden.booleanValue()) { // If our superclass has overriden it, then by definition klass // overrides it. overrideMap.put(klass.getName(), sOverriden); return sOverriden; } // klass's superclass didn't override it, check for an override in // klass. try { Class[] classes = new Class[1]; classes[0] = InputMethodEvent.class; Method m = klass.getDeclaredMethod("processInputMethodEvent", classes); retValue = Boolean.TRUE; } catch (NoSuchMethodException nsme) { retValue = Boolean.FALSE; } overrideMap.put(klass.getName(), retValue); return retValue; } /** * Fetches the current color used to render the * caret. * * @return the color */ public Color getCaretColor() { return caretColor; } /** * Sets the current color used to render the caret. * Setting to <code>null</code> effectively restores the default color. * Setting the color results in a PropertyChange event ("caretColor") * being fired. * * @param c the color * @see #getCaretColor * @beaninfo * description: the color used to render the caret * bound: true * preferred: true */ public void setCaretColor(Color c) { Color old = caretColor; caretColor = c; firePropertyChange("caretColor", old, caretColor); } /** * Fetches the current color used to render the * selection. * * @return the color */ public Color getSelectionColor() { return selectionColor; } /** * Sets the current color used to render the selection. * Setting the color to <code>null</code> is the same as setting * <code>Color.white</code>. Setting the color results in a * PropertyChange event ("selectionColor"). * * @param c the color * @see #getSelectionColor * @beaninfo * description: color used to render selection background * bound: true * preferred: true */ public void setSelectionColor(Color c) { Color old = selectionColor; selectionColor = c; firePropertyChange("selectionColor", old, selectionColor); } /** * Fetches the current color used to render the * selected text. * * @return the color */ public Color getSelectedTextColor() { return selectedTextColor; } /** * Sets the current color used to render the selected text. * Setting the color to <code>null</code> is the same as * <code>Color.black</code>. Setting the color results in a * PropertyChange event ("selectedTextColor") being fired. * * @param c the color * @see #getSelectedTextColor * @beaninfo * description: color used to render selected text * bound: true * preferred: true */ public void setSelectedTextColor(Color c) { Color old = selectedTextColor; selectedTextColor = c; firePropertyChange("selectedTextColor", old, selectedTextColor); } /** * Fetches the current color used to render the * disabled text. * * @return the color */ public Color getDisabledTextColor() { return disabledTextColor; } /** * Sets the current color used to render the * disabled text. Setting the color fires off a * PropertyChange event ("disabledTextColor"). * * @param c the color * @see #getDisabledTextColor * @beaninfo * description: color used to render disabled text * bound: true * preferred: true */ public void setDisabledTextColor(Color c) { Color old = disabledTextColor; disabledTextColor = c; firePropertyChange("disabledTextColor", old, disabledTextColor); } /** * Replaces the currently selected content with new content * represented by the given string. If there is no selection * this amounts to an insert of the given text. If there * is no replacement text this amounts to a removal of the * current selection. * <p> * This is the method that is used by the default implementation * of the action for inserting content that gets bound to the * keymap actions. * * @param content the content to replace the selection with */ public void replaceSelection(String content) { Document doc = getDocument(); if (doc != null) { try { boolean composedTextSaved = saveComposedText(caret.getDot()); int p0 = Math.min(caret.getDot(), caret.getMark()); int p1 = Math.max(caret.getDot(), caret.getMark()); if (doc instanceof AbstractDocument) { ((AbstractDocument)doc).replace(p0, p1 - p0, content,null); } else { if (p0 != p1) { doc.remove(p0, p1 - p0); } if (content != null && content.length() > 0) { doc.insertString(p0, content, null); } } if (composedTextSaved) { restoreComposedText(); } } catch (BadLocationException e) { UIManager.getLookAndFeel().provideErrorFeedback(JTextComponent.this); } } } /** * Fetches a portion of the text represented by the * component. Returns an empty string if length is 0. * * @param offs the offset >= 0 * @param len the length >= 0 * @return the text * @exception BadLocationException if the offset or length are invalid */ public String getText(int offs, int len) throws BadLocationException { return getDocument().getText(offs, len); } /** * Converts the given location in the model to a place in * the view coordinate system. * The component must have a positive size for * this translation to be computed (i.e. layout cannot * be computed until the component has been sized). The * component does not have to be visible or painted. * * @param pos the position >= 0 * @return the coordinates as a rectangle, with (r.x, r.y) as the location * in the coordinate system, or null if the component does * not yet have a positive size. * @exception BadLocationException if the given position does not * represent a valid location in the associated document * @see TextUI#modelToView */ public Rectangle modelToView(int pos) throws BadLocationException { return getUI().modelToView(this, pos); } /** * Converts the given place in the view coordinate system * to the nearest representative location in the model. * The component must have a positive size for * this translation to be computed (i.e. layout cannot * be computed until the component has been sized). The * component does not have to be visible or painted. * * @param pt the location in the view to translate * @return the offset >= 0 from the start of the document, * or -1 if the component does not yet have a positive * size. * @see TextUI#viewToModel */ public int viewToModel(Point pt) { return getUI().viewToModel(this, pt); } /** * Transfers the currently selected range in the associated * text model to the system clipboard, removing the contents * from the model. The current selection is reset. Does nothing * for <code>null</code> selections. * * @see java.awt.Toolkit#getSystemClipboard * @see java.awt.datatransfer.Clipboard */ public void cut() { if (isEditable() && isEnabled()) { invokeAction("cut", TransferHandler.getCutAction()); } } /** * Transfers the currently selected range in the associated * text model to the system clipboard, leaving the contents * in the text model. The current selection remains intact. * Does nothing for <code>null</code> selections. * * @see java.awt.Toolkit#getSystemClipboard * @see java.awt.datatransfer.Clipboard */ public void copy() { invokeAction("copy", TransferHandler.getCopyAction()); } /** * Transfers the contents of the system clipboard into the * associated text model. If there is a selection in the * associated view, it is replaced with the contents of the * clipboard. If there is no selection, the clipboard contents * are inserted in front of the current insert position in * the associated view. If the clipboard is empty, does nothing. * * @see #replaceSelection * @see java.awt.Toolkit#getSystemClipboard * @see java.awt.datatransfer.Clipboard */ public void paste() { if (isEditable() && isEnabled()) { invokeAction("paste", TransferHandler.getPasteAction()); } } /** * This is a conveniance method that is only useful for * <code>cut</code>, <code>copy</code> and <code>paste</code>. If * an <code>Action</code> with the name <code>name</code> does not * exist in the <code>ActionMap</code>, this will attemp to install a * <code>TransferHandler</code> and then use <code>altAction</code>.