1 /* JTextComponent.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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
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
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. */
39 package javax
.swing
.text
;
41 import java
.awt
.AWTEvent
;
42 import java
.awt
.Color
;
43 import java
.awt
.Dimension
;
44 import java
.awt
.Insets
;
45 import java
.awt
.Point
;
46 import java
.awt
.Rectangle
;
47 import java
.awt
.datatransfer
.Clipboard
;
48 import java
.awt
.datatransfer
.DataFlavor
;
49 import java
.awt
.datatransfer
.StringSelection
;
50 import java
.awt
.datatransfer
.Transferable
;
51 import java
.awt
.datatransfer
.UnsupportedFlavorException
;
52 import java
.awt
.event
.ActionEvent
;
53 import java
.awt
.event
.InputMethodListener
;
54 import java
.awt
.event
.KeyEvent
;
55 import java
.awt
.event
.MouseEvent
;
56 import java
.io
.IOException
;
57 import java
.io
.Reader
;
58 import java
.io
.Writer
;
59 import java
.util
.Enumeration
;
60 import java
.util
.Hashtable
;
62 import javax
.accessibility
.Accessible
;
63 import javax
.accessibility
.AccessibleContext
;
64 import javax
.accessibility
.AccessibleRole
;
65 import javax
.accessibility
.AccessibleStateSet
;
66 import javax
.accessibility
.AccessibleText
;
67 import javax
.swing
.Action
;
68 import javax
.swing
.ActionMap
;
69 import javax
.swing
.InputMap
;
70 import javax
.swing
.JComponent
;
71 import javax
.swing
.JViewport
;
72 import javax
.swing
.KeyStroke
;
73 import javax
.swing
.Scrollable
;
74 import javax
.swing
.SwingConstants
;
75 import javax
.swing
.TransferHandler
;
76 import javax
.swing
.UIManager
;
77 import javax
.swing
.event
.CaretEvent
;
78 import javax
.swing
.event
.CaretListener
;
79 import javax
.swing
.event
.DocumentEvent
;
80 import javax
.swing
.event
.DocumentListener
;
81 import javax
.swing
.plaf
.ActionMapUIResource
;
82 import javax
.swing
.plaf
.InputMapUIResource
;
83 import javax
.swing
.plaf
.TextUI
;
85 public abstract class JTextComponent
extends JComponent
86 implements Scrollable
, Accessible
89 * AccessibleJTextComponent
91 // FIXME: This inner class is a complete stub and needs to be implemented.
92 public class AccessibleJTextComponent
extends AccessibleJComponent
93 implements AccessibleText
, CaretListener
, DocumentListener
95 private static final long serialVersionUID
= 7664188944091413696L;
98 * Constructor AccessibleJTextComponent
100 public AccessibleJTextComponent()
102 // Nothing to do here.
109 public int getCaretPosition()
118 public String
getSelectedText()
127 public int getSelectionStart()
136 public int getSelectionEnd()
145 public void caretUpdate(CaretEvent value0
)
151 * getAccessibleStateSet
152 * @return AccessibleStateSet
154 public AccessibleStateSet
getAccessibleStateSet()
161 * @return AccessibleRole
163 public AccessibleRole
getAccessibleRole()
170 * @return AccessibleText
172 public AccessibleText
getAccessibleText()
181 public void insertUpdate(DocumentEvent value0
)
190 public void removeUpdate(DocumentEvent value0
)
199 public void changedUpdate(DocumentEvent value0
)
209 public int getIndexAtPoint(Point value0
)
218 Rectangle
getRootEditorRect()
228 public Rectangle
getCharacterBounds(int value0
)
237 public int getCharCount()
243 * getCharacterAttribute
245 * @return AttributeSet
247 public AttributeSet
getCharacterAttribute(int value0
)
258 public String
getAtIndex(int value0
, int value1
)
269 public String
getAfterIndex(int value0
, int value1
)
280 public String
getBeforeIndex(int value0
, int value1
)
286 public static class KeyBinding
288 public KeyStroke key
;
289 public String actionName
;
292 * Creates a new <code>KeyBinding</code> instance.
294 * @param key a <code>KeyStroke</code> value
295 * @param actionName a <code>String</code> value
297 public KeyBinding(KeyStroke key
, String actionName
)
300 this.actionName
= actionName
;
306 * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">this
307 * report</a>, a pair of private classes wraps a {@link
308 * javax.swing.text.Keymap} in the new {@link InputMap} / {@link
309 * ActionMap} interfaces, such that old Keymap-using code can make use of
312 * <p>A little bit of experimentation with these classes reveals the following
317 * <li>KeymapWrapper extends {@link InputMap} and holds a reference to
318 * the underlying {@link Keymap}.</li>
320 * <li>KeymapWrapper maps {@link KeyStroke} objects to {@link Action}
321 * objects, by delegation to the underlying {@link Keymap}.</li>
323 * <li>KeymapActionMap extends {@link ActionMap} also holds a reference to
324 * the underlying {@link Keymap} but only appears to use it for listing
327 * <li>KeymapActionMap maps all {@link Action} objects to
328 * <em>themselves</em>, whether they exist in the underlying {@link
329 * Keymap} or not, and passes other objects to the parent {@link
330 * ActionMap} for resolving.
335 private class KeymapWrapper
extends InputMap
339 public KeymapWrapper(Keymap k
)
346 return map
.getBoundKeyStrokes().length
+ super.size();
349 public Object
get(KeyStroke ks
)
351 Action mapped
= null;
353 while(mapped
== null && m
!= null)
355 mapped
= m
.getAction(ks
);
356 if (mapped
== null && ks
.getKeyEventType() == KeyEvent
.KEY_TYPED
)
357 mapped
= m
.getDefaultAction();
359 m
= m
.getResolveParent();
363 return super.get(ks
);
368 public KeyStroke
[] keys()
370 KeyStroke
[] superKeys
= super.keys();
371 KeyStroke
[] mapKeys
= map
.getBoundKeyStrokes();
372 KeyStroke
[] bothKeys
= new KeyStroke
[superKeys
.length
+ mapKeys
.length
];
373 for (int i
= 0; i
< superKeys
.length
; ++i
)
374 bothKeys
[i
] = superKeys
[i
];
375 for (int i
= 0; i
< mapKeys
.length
; ++i
)
376 bothKeys
[i
+ superKeys
.length
] = mapKeys
[i
];
380 public KeyStroke
[] allKeys()
382 KeyStroke
[] superKeys
= super.allKeys();
383 KeyStroke
[] mapKeys
= map
.getBoundKeyStrokes();
386 if (superKeys
!= null)
387 skl
= superKeys
.length
;
389 mkl
= mapKeys
.length
;
390 KeyStroke
[] bothKeys
= new KeyStroke
[skl
+ mkl
];
391 for (int i
= 0; i
< skl
; ++i
)
392 bothKeys
[i
] = superKeys
[i
];
393 for (int i
= 0; i
< mkl
; ++i
)
394 bothKeys
[i
+ skl
] = mapKeys
[i
];
399 private class KeymapActionMap
extends ActionMap
403 public KeymapActionMap(Keymap k
)
408 public Action
get(Object cmd
)
410 if (cmd
instanceof Action
)
413 return super.get(cmd
);
418 return map
.getBoundKeyStrokes().length
+ super.size();
421 public Object
[] keys()
423 Object
[] superKeys
= super.keys();
424 Object
[] mapKeys
= map
.getBoundKeyStrokes();
425 Object
[] bothKeys
= new Object
[superKeys
.length
+ mapKeys
.length
];
426 for (int i
= 0; i
< superKeys
.length
; ++i
)
427 bothKeys
[i
] = superKeys
[i
];
428 for (int i
= 0; i
< mapKeys
.length
; ++i
)
429 bothKeys
[i
+ superKeys
.length
] = mapKeys
[i
];
433 public Object
[] allKeys()
435 Object
[] superKeys
= super.allKeys();
436 Object
[] mapKeys
= map
.getBoundKeyStrokes();
437 Object
[] bothKeys
= new Object
[superKeys
.length
+ mapKeys
.length
];
438 for (int i
= 0; i
< superKeys
.length
; ++i
)
439 bothKeys
[i
] = superKeys
[i
];
440 for (int i
= 0; i
< mapKeys
.length
; ++i
)
441 bothKeys
[i
+ superKeys
.length
] = mapKeys
[i
];
447 static class DefaultKeymap
implements Keymap
452 Action defaultAction
;
454 public DefaultKeymap(String name
)
457 this.map
= new Hashtable();
460 public void addActionForKeyStroke(KeyStroke key
, Action a
)
466 * Looks up a KeyStroke either in the current map or the parent Keymap;
467 * does <em>not</em> return the default action if lookup fails.
469 * @param key The KeyStroke to look up an Action for.
471 * @return The mapping for <code>key</code>, or <code>null</code>
472 * if no mapping exists in this Keymap or any of its parents.
474 public Action
getAction(KeyStroke key
)
476 if (map
.containsKey(key
))
477 return (Action
) map
.get(key
);
478 else if (parent
!= null)
479 return parent
.getAction(key
);
484 public Action
[] getBoundActions()
486 Action
[] ret
= new Action
[map
.size()];
487 Enumeration e
= map
.elements();
489 while (e
.hasMoreElements())
491 ret
[i
++] = (Action
) e
.nextElement();
496 public KeyStroke
[] getBoundKeyStrokes()
498 KeyStroke
[] ret
= new KeyStroke
[map
.size()];
499 Enumeration e
= map
.keys();
501 while (e
.hasMoreElements())
503 ret
[i
++] = (KeyStroke
) e
.nextElement();
508 public Action
getDefaultAction()
510 return defaultAction
;
513 public KeyStroke
[] getKeyStrokesForAction(Action a
)
516 Enumeration e
= map
.keys();
517 while (e
.hasMoreElements())
519 if (map
.get(e
.nextElement()).equals(a
))
522 KeyStroke
[] ret
= new KeyStroke
[i
];
525 while (e
.hasMoreElements())
527 KeyStroke k
= (KeyStroke
) e
.nextElement();
528 if (map
.get(k
).equals(a
))
534 public String
getName()
539 public Keymap
getResolveParent()
544 public boolean isLocallyDefined(KeyStroke key
)
546 return map
.containsKey(key
);
549 public void removeBindings()
554 public void removeKeyStrokeBinding(KeyStroke key
)
559 public void setDefaultAction(Action a
)
564 public void setResolveParent(Keymap p
)
570 class DefaultTransferHandler
extends TransferHandler
572 public boolean canImport(JComponent component
, DataFlavor
[] flavors
)
574 JTextComponent textComponent
= (JTextComponent
) component
;
576 if (! (textComponent
.isEnabled()
577 && textComponent
.isEditable()
581 for (int i
= 0; i
< flavors
.length
; ++i
)
582 if (flavors
[i
].equals(DataFlavor
.stringFlavor
))
588 public void exportToClipboard(JComponent component
, Clipboard clipboard
,
591 JTextComponent textComponent
= (JTextComponent
) component
;
592 int start
= textComponent
.getSelectionStart();
593 int end
= textComponent
.getSelectionEnd();
600 // Copy text to clipboard.
601 String data
= textComponent
.getDocument().getText(start
, end
);
602 StringSelection selection
= new StringSelection(data
);
603 clipboard
.setContents(selection
, null);
605 // Delete selected text on cut action.
607 doc
.remove(start
, end
- start
);
609 catch (BadLocationException e
)
611 // Ignore this and do nothing.
615 public int getSourceActions()
620 public boolean importData(JComponent component
, Transferable transferable
)
622 DataFlavor flavor
= null;
623 DataFlavor
[] flavors
= transferable
.getTransferDataFlavors();
628 for (int i
= 0; i
< flavors
.length
; ++i
)
629 if (flavors
[i
].equals(DataFlavor
.stringFlavor
))
637 JTextComponent textComponent
= (JTextComponent
) component
;
638 String data
= (String
) transferable
.getTransferData(flavor
);
639 textComponent
.replaceSelection(data
);
642 catch (IOException e
)
646 catch (UnsupportedFlavorException e
)
655 private static final long serialVersionUID
= -8796518220218978795L;
657 public static final String DEFAULT_KEYMAP
= "default";
658 public static final String FOCUS_ACCELERATOR_KEY
= "focusAcceleratorKey";
660 private static DefaultTransferHandler defaultTransferHandler
;
661 private static Hashtable keymaps
= new Hashtable();
662 private Keymap keymap
;
663 private char focusAccelerator
= '\0';
664 private NavigationFilter navigationFilter
;
667 * Get a Keymap from the global keymap table, by name.
669 * @param n The name of the Keymap to look up
671 * @return A Keymap associated with the provided name, or
672 * <code>null</code> if no such Keymap exists
678 public static Keymap
getKeymap(String n
)
680 return (Keymap
) keymaps
.get(n
);
684 * Remove a Keymap from the global Keymap table, by name.
686 * @param n The name of the Keymap to remove
688 * @return The keymap removed from the global table
694 public static Keymap
removeKeymap(String n
)
696 Keymap km
= (Keymap
) keymaps
.get(n
);
702 * Create a new Keymap with a specific name and parent, and add the new
703 * Keymap to the global keymap table. The name may be <code>null</code>,
704 * in which case the new Keymap will <em>not</em> be added to the global
705 * Keymap table. The parent may also be <code>null</code>, which is
708 * @param n The name of the new Keymap, or <code>null</code>
709 * @param parent The parent of the new Keymap, or <code>null</code>
711 * @return The newly created Keymap
717 public static Keymap
addKeymap(String n
, Keymap parent
)
719 Keymap k
= new DefaultKeymap(n
);
720 k
.setResolveParent(parent
);
727 * Get the current Keymap of this component.
729 * @return The component's current Keymap
734 public Keymap
getKeymap()
740 * Set the current Keymap of this component, installing appropriate
741 * {@link KeymapWrapper} and {@link KeymapActionMap} objects in the
742 * {@link InputMap} and {@link ActionMap} parent chains, respectively,
743 * and fire a property change event with name <code>"keymap"</code>.
748 public void setKeymap(Keymap k
)
751 // phase 1: replace the KeymapWrapper entry in the InputMap chain.
752 // the goal here is to always maintain the following ordering:
754 // [InputMap]? -> [KeymapWrapper]? -> [InputMapUIResource]*
756 // that is to say, component-specific InputMaps need to remain children
757 // of Keymaps, and Keymaps need to remain children of UI-installed
758 // InputMaps (and the order of each group needs to be preserved, of
761 KeymapWrapper kw
= (k
== null ?
null : new KeymapWrapper(k
));
762 InputMap childInputMap
= getInputMap(JComponent
.WHEN_FOCUSED
);
763 if (childInputMap
== null)
764 setInputMap(JComponent
.WHEN_FOCUSED
, kw
);
767 while (childInputMap
.getParent() != null
768 && !(childInputMap
.getParent() instanceof KeymapWrapper
)
769 && !(childInputMap
.getParent() instanceof InputMapUIResource
))
770 childInputMap
= childInputMap
.getParent();
772 // option 1: there is nobody to replace at the end of the chain
773 if (childInputMap
.getParent() == null)
774 childInputMap
.setParent(kw
);
776 // option 2: there is already a KeymapWrapper in the chain which
777 // needs replacing (possibly with its own parents, possibly without)
778 else if (childInputMap
.getParent() instanceof KeymapWrapper
)
781 childInputMap
.setParent(childInputMap
.getParent().getParent());
784 kw
.setParent(childInputMap
.getParent().getParent());
785 childInputMap
.setParent(kw
);
789 // option 3: there is an InputMapUIResource in the chain, which marks
790 // the place where we need to stop and insert ourselves
791 else if (childInputMap
.getParent() instanceof InputMapUIResource
)
795 kw
.setParent(childInputMap
.getParent());
796 childInputMap
.setParent(kw
);
801 // phase 2: replace the KeymapActionMap entry in the ActionMap chain
803 KeymapActionMap kam
= (k
== null ?
null : new KeymapActionMap(k
));
804 ActionMap childActionMap
= getActionMap();
805 if (childActionMap
== null)
809 while (childActionMap
.getParent() != null
810 && !(childActionMap
.getParent() instanceof KeymapActionMap
)
811 && !(childActionMap
.getParent() instanceof ActionMapUIResource
))
812 childActionMap
= childActionMap
.getParent();
814 // option 1: there is nobody to replace at the end of the chain
815 if (childActionMap
.getParent() == null)
816 childActionMap
.setParent(kam
);
818 // option 2: there is already a KeymapActionMap in the chain which
819 // needs replacing (possibly with its own parents, possibly without)
820 else if (childActionMap
.getParent() instanceof KeymapActionMap
)
823 childActionMap
.setParent(childActionMap
.getParent().getParent());
826 kam
.setParent(childActionMap
.getParent().getParent());
827 childActionMap
.setParent(kam
);
831 // option 3: there is an ActionMapUIResource in the chain, which marks
832 // the place where we need to stop and insert ourselves
833 else if (childActionMap
.getParent() instanceof ActionMapUIResource
)
837 kam
.setParent(childActionMap
.getParent());
838 childActionMap
.setParent(kam
);
843 // phase 3: update the explicit keymap field
847 firePropertyChange("keymap", old
, k
);
851 * Resolves a set of bindings against a set of actions and inserts the
852 * results into a {@link Keymap}. Specifically, for each provided binding
853 * <code>b</code>, if there exists a provided action <code>a</code> such
854 * that <code>a.getValue(Action.NAME) == b.ActionName</code> then an
855 * entry is added to the Keymap mapping <code>b</code> to
858 * @param map The Keymap to add new mappings to
859 * @param bindings The set of bindings to add to the Keymap
860 * @param actions The set of actions to resolve binding names against
863 * @see Action#getValue
864 * @see KeyBinding#actionName
866 public static void loadKeymap(Keymap map
,
867 JTextComponent
.KeyBinding
[] bindings
,
870 Hashtable acts
= new Hashtable(actions
.length
);
871 for (int i
= 0; i
< actions
.length
; ++i
)
872 acts
.put(actions
[i
].getValue(Action
.NAME
), actions
[i
]);
873 for (int i
= 0; i
< bindings
.length
; ++i
)
874 if (acts
.containsKey(bindings
[i
].actionName
))
875 map
.addActionForKeyStroke(bindings
[i
].key
, (Action
) acts
.get(bindings
[i
].actionName
));
879 * Returns the set of available Actions this component's associated
880 * editor can run. Equivalent to calling
881 * <code>getUI().getEditorKit().getActions()</code>. This set of Actions
882 * is a reasonable value to provide as a parameter to {@link
883 * #loadKeymap}, when resolving a set of {@link KeyBinding} objects
884 * against this component.
886 * @return The set of available Actions on this component's {@link EditorKit}
888 * @see TextUI#getEditorKit
889 * @see EditorKit#getActions()
891 public Action
[] getActions()
893 return getUI().getEditorKit(this).getActions();
896 // These are package-private to avoid an accessor method.
901 private Highlighter highlighter
;
902 private Color caretColor
;
903 private Color disabledTextColor
;
904 private Color selectedTextColor
;
905 private Color selectionColor
;
906 private Insets margin
;
907 private boolean dragEnabled
;
910 * Creates a new <code>JTextComponent</code> instance.
912 public JTextComponent()
914 Keymap defkeymap
= getKeymap(DEFAULT_KEYMAP
);
915 if (defkeymap
== null)
917 defkeymap
= addKeymap(DEFAULT_KEYMAP
, null);
918 defkeymap
.setDefaultAction(new DefaultEditorKit
.DefaultKeyTypedAction());
923 enableEvents(AWTEvent
.KEY_EVENT_MASK
);
927 public void setDocument(Document newDoc
)
929 Document oldDoc
= doc
;
931 firePropertyChange("document", oldDoc
, newDoc
);
936 public Document
getDocument()
942 * Get the <code>AccessibleContext</code> of this object.
944 * @return an <code>AccessibleContext</code> object
946 public AccessibleContext
getAccessibleContext()
951 public void setMargin(Insets m
)
956 public Insets
getMargin()
961 public void setText(String text
)
965 if (doc
instanceof AbstractDocument
)
966 ((AbstractDocument
) doc
).replace(0, doc
.getLength(), text
, null);
969 doc
.remove(0, doc
.getLength());
970 doc
.insertString(0, text
, null);
973 catch (BadLocationException e
)
975 // This can never happen.
980 * Retrieves the current text in this text document.
984 * @exception NullPointerException if the underlaying document is null
986 public String
getText()
993 return doc
.getText(0, doc
.getLength());
995 catch (BadLocationException e
)
997 // This should never happen.
1003 * Retrieves a part of the current text in this document.
1005 * @param offset the postion of the first character
1006 * @param length the length of the text to retrieve
1010 * @exception BadLocationException if arguments do not hold pre-conditions
1012 public String
getText(int offset
, int length
)
1013 throws BadLocationException
1015 return getDocument().getText(offset
, length
);
1019 * Retrieves the currently selected text in this text document.
1021 * @return the selected text
1023 * @exception NullPointerException if the underlaying document is null
1025 public String
getSelectedText()
1029 return doc
.getText(getSelectionStart(), getSelectionEnd());
1031 catch (BadLocationException e
)
1033 // This should never happen.
1039 * Returns a string that specifies the name of the Look and Feel class
1040 * that renders this component.
1042 * @return the string "TextComponentUI"
1044 public String
getUIClassID()
1046 return "TextComponentUI";
1050 * Returns a string representation of this JTextComponent.
1052 protected String
paramString()
1054 // TODO: Do something useful here.
1055 return super.paramString();
1059 * This method returns the label's UI delegate.
1061 * @return The label's UI delegate.
1063 public TextUI
getUI()
1069 * This method sets the label's UI delegate.
1071 * @param newUI The label's UI delegate.
1073 public void setUI(TextUI newUI
)
1079 * This method resets the label's UI delegate to the default UI for the
1080 * current look and feel.
1082 public void updateUI()
1084 setUI((TextUI
) UIManager
.getUI(this));
1087 public Dimension
getPreferredScrollableViewportSize()
1089 return getPreferredSize();
1092 public int getScrollableUnitIncrement(Rectangle visible
, int orientation
,
1095 // We return 1/10 of the visible area as documented in Sun's API docs.
1096 if (orientation
== SwingConstants
.HORIZONTAL
)
1097 return visible
.width
/ 10;
1098 else if (orientation
== SwingConstants
.VERTICAL
)
1099 return visible
.height
/ 10;
1101 throw new IllegalArgumentException("orientation must be either "
1102 + "javax.swing.SwingConstants.VERTICAL "
1104 + "javax.swing.SwingConstants.HORIZONTAL"
1108 public int getScrollableBlockIncrement(Rectangle visible
, int orientation
,
1111 // We return the whole visible area as documented in Sun's API docs.
1112 if (orientation
== SwingConstants
.HORIZONTAL
)
1113 return visible
.width
;
1114 else if (orientation
== SwingConstants
.VERTICAL
)
1115 return visible
.height
;
1117 throw new IllegalArgumentException("orientation must be either "
1118 + "javax.swing.SwingConstants.VERTICAL "
1120 + "javax.swing.SwingConstants.HORIZONTAL"
1125 * Checks whether this text component it editable.
1127 * @return true if editable, false otherwise
1129 public boolean isEditable()
1135 * Enables/disabled this text component's editability.
1137 * @param newValue true to make it editable, false otherwise.
1139 public void setEditable(boolean newValue
)
1141 if (editable
== newValue
)
1144 boolean oldValue
= editable
;
1145 editable
= newValue
;
1146 firePropertyChange("editable", oldValue
, newValue
);
1150 * The <code>Caret</code> object used in this text component.
1152 * @return the caret object
1154 public Caret
getCaret()
1160 * Sets a new <code>Caret</code> for this text component.
1162 * @param newCaret the new <code>Caret</code> to set
1164 public void setCaret(Caret newCaret
)
1167 caret
.deinstall(this);
1169 Caret oldCaret
= caret
;
1173 caret
.install(this);
1175 firePropertyChange("caret", oldCaret
, newCaret
);
1178 public Color
getCaretColor()
1183 public void setCaretColor(Color newColor
)
1185 Color oldCaretColor
= caretColor
;
1186 caretColor
= newColor
;
1187 firePropertyChange("caretColor", oldCaretColor
, newColor
);
1190 public Color
getDisabledTextColor()
1192 return disabledTextColor
;
1195 public void setDisabledTextColor(Color newColor
)
1197 Color oldColor
= disabledTextColor
;
1198 disabledTextColor
= newColor
;
1199 firePropertyChange("disabledTextColor", oldColor
, newColor
);
1202 public Color
getSelectedTextColor()
1204 return selectedTextColor
;
1207 public void setSelectedTextColor(Color newColor
)
1209 Color oldColor
= selectedTextColor
;
1210 selectedTextColor
= newColor
;
1211 firePropertyChange("selectedTextColor", oldColor
, newColor
);
1214 public Color
getSelectionColor()
1216 return selectionColor
;
1219 public void setSelectionColor(Color newColor
)
1221 Color oldColor
= selectionColor
;
1222 selectionColor
= newColor
;
1223 firePropertyChange("selectionColor", oldColor
, newColor
);
1227 * Retrisves the current caret position.
1229 * @return the current position
1231 public int getCaretPosition()
1233 return caret
.getDot();
1237 * Sets the caret to a new position.
1239 * @param position the new position
1241 public void setCaretPosition(int position
)
1246 if (position
< 0 || position
> doc
.getLength())
1247 throw new IllegalArgumentException();
1249 caret
.setDot(position
);
1253 * Moves the caret to a given position. This selects the text between
1254 * the old and the new position of the caret.
1256 public void moveCaretPosition(int position
)
1261 if (position
< 0 || position
> doc
.getLength())
1262 throw new IllegalArgumentException();
1264 caret
.moveDot(position
);
1267 public Highlighter
getHighlighter()
1272 public void setHighlighter(Highlighter newHighlighter
)
1274 if (highlighter
!= null)
1275 highlighter
.deinstall(this);
1277 Highlighter oldHighlighter
= highlighter
;
1278 highlighter
= newHighlighter
;
1280 if (highlighter
!= null)
1281 highlighter
.install(this);
1283 firePropertyChange("highlighter", oldHighlighter
, newHighlighter
);
1287 * Returns the start postion of the currently selected text.
1289 * @return the start postion
1291 public int getSelectionStart()
1293 return Math
.min(caret
.getDot(), caret
.getMark());
1297 * Selects the text from the given postion to the selection end position.
1299 * @param start the start positon of the selected text.
1301 public void setSelectionStart(int start
)
1303 select(start
, getSelectionEnd());
1307 * Returns the end postion of the currently selected text.
1309 * @return the end postion
1311 public int getSelectionEnd()
1313 return Math
.max(caret
.getDot(), caret
.getMark());
1317 * Selects the text from the selection start postion to the given position.
1319 * @param end the end positon of the selected text.
1321 public void setSelectionEnd(int end
)
1323 select(getSelectionStart(), end
);
1327 * Selects a part of the content of the text component.
1329 * @param start the start position of the selected text
1330 * @param end the end position of the selected text
1332 public void select(int start
, int end
)
1334 int length
= doc
.getLength();
1336 start
= Math
.max(start
, 0);
1337 start
= Math
.min(start
, length
);
1339 end
= Math
.max(end
, start
);
1340 end
= Math
.min(end
, length
);
1342 setCaretPosition(start
);
1343 moveCaretPosition(end
);
1347 * Selects the whole content of the text component.
1349 public void selectAll()
1351 select(0, doc
.getLength());
1354 public synchronized void replaceSelection(String content
)
1356 int dot
= caret
.getDot();
1357 int mark
= caret
.getMark();
1359 // If content is empty delete selection.
1360 if (content
== null)
1368 int start
= getSelectionStart();
1369 int end
= getSelectionEnd();
1371 // Remove selected text.
1373 doc
.remove(start
, end
- start
);
1376 doc
.insertString(start
, content
, null);
1378 // Set dot to new position.
1379 setCaretPosition(start
+ content
.length());
1381 catch (BadLocationException e
)
1383 // This should never happen.
1387 public boolean getScrollableTracksViewportHeight()
1389 if (getParent() instanceof JViewport
)
1390 return ((JViewport
) getParent()).getHeight() > getPreferredSize().height
;
1395 public boolean getScrollableTracksViewportWidth()
1397 if (getParent() instanceof JViewport
)
1398 return ((JViewport
) getParent()).getWidth() > getPreferredSize().width
;
1404 * Adds a <code>CaretListener</code> object to this text component.
1406 * @param listener the listener to add
1408 public void addCaretListener(CaretListener listener
)
1410 listenerList
.add(CaretListener
.class, listener
);
1414 * Removed a <code>CaretListener</code> object from this text component.
1416 * @param listener the listener to remove
1418 public void removeCaretListener(CaretListener listener
)
1420 listenerList
.remove(CaretListener
.class, listener
);
1424 * Returns all added <code>CaretListener</code> objects.
1426 * @return an array of listeners
1428 public CaretListener
[] getCaretListeners()
1430 return (CaretListener
[]) getListeners(CaretListener
.class);
1434 * Notifies all registered <code>CaretListener</code> objects that the caret
1437 * @param event the event to send
1439 protected void fireCaretUpdate(CaretEvent event
)
1441 CaretListener
[] listeners
= getCaretListeners();
1443 for (int index
= 0; index
< listeners
.length
; ++index
)
1444 listeners
[index
].caretUpdate(event
);
1448 * Adds an <code>InputListener</code> object to this text component.
1450 * @param listener the listener to add
1452 public void addInputMethodListener(InputMethodListener listener
)
1454 listenerList
.add(InputMethodListener
.class, listener
);
1458 * Removes an <code>InputListener</code> object from this text component.
1460 * @param listener the listener to remove
1462 public void removeInputMethodListener(InputMethodListener listener
)
1464 listenerList
.remove(InputMethodListener
.class, listener
);
1468 * Returns all added <code>InputMethodListener</code> objects.
1470 * @return an array of listeners
1472 public InputMethodListener
[] getInputMethodListeners()
1474 return (InputMethodListener
[]) getListeners(InputMethodListener
.class);
1477 public Rectangle
modelToView(int position
) throws BadLocationException
1479 return getUI().modelToView(this, position
);
1482 public boolean getDragEnabled()
1487 public void setDragEnabled(boolean enabled
)
1489 dragEnabled
= enabled
;
1492 public int viewToModel(Point pt
)
1494 return getUI().viewToModel(this, pt
);
1499 doTransferAction("copy", TransferHandler
.getCopyAction());
1504 doTransferAction("cut", TransferHandler
.getCutAction());
1509 doTransferAction("paste", TransferHandler
.getPasteAction());
1512 private void doTransferAction(String name
, Action action
)
1514 // Install default TransferHandler if none set.
1515 if (getTransferHandler() == null)
1517 if (defaultTransferHandler
== null)
1518 defaultTransferHandler
= new DefaultTransferHandler();
1520 setTransferHandler(defaultTransferHandler
);
1524 ActionEvent event
= new ActionEvent(this, ActionEvent
.ACTION_PERFORMED
,
1525 action
.getValue(Action
.NAME
).toString());
1526 action
.actionPerformed(event
);
1529 public void setFocusAccelerator(char newKey
)
1531 if (focusAccelerator
== newKey
)
1534 char oldKey
= focusAccelerator
;
1535 focusAccelerator
= newKey
;
1536 firePropertyChange(FOCUS_ACCELERATOR_KEY
, oldKey
, newKey
);
1539 public char getFocusAccelerator()
1541 return focusAccelerator
;
1547 public NavigationFilter
getNavigationFilter()
1549 return navigationFilter
;
1555 public void setNavigationFilter(NavigationFilter filter
)
1557 navigationFilter
= filter
;
1561 * Read and set the content this component. If not overridden, the
1562 * method reads the component content as a plain text.
1564 * The second parameter of this method describes the input stream. It can
1565 * be String, URL, File and so on. If not null, this object is added to
1566 * the properties of the associated document under the key
1567 * {@link Document#StreamDescriptionProperty}.
1569 * @param input an input stream to read from.
1570 * @param streamDescription an object, describing the stream.
1572 * @throws IOException if the reader throws it.
1574 * @see #getDocument()
1575 * @see Document#getProperty(Object)
1577 public void read(Reader input
, Object streamDescription
)
1580 if (streamDescription
!= null)
1582 Document d
= getDocument();
1584 d
.putProperty(Document
.StreamDescriptionProperty
, streamDescription
);
1587 StringBuffer b
= new StringBuffer();
1590 // Read till -1 (EOF).
1591 while ((c
= input
.read()) >= 0)
1594 setText(b
.toString());
1598 * Write the content of this component to the given stream. If not
1599 * overridden, the method writes the component content as a plain text.
1601 * @param output the writer to write into.
1603 * @throws IOException if the writer throws it.
1605 public void write(Writer output
)
1608 output
.write(getText());
1612 * Returns the tooltip text for this text component for the given mouse
1613 * event. This forwards the call to
1614 * {@link TextUI#getToolTipText(JTextComponent, Point)}.
1616 * @param ev the mouse event
1618 * @return the tooltip text for this text component for the given mouse
1621 public String
getToolTipText(MouseEvent ev
)
1623 return getUI().getToolTipText(this, ev
.getPoint());