Merge from mainline
[official-gcc.git] / libjava / classpath / javax / swing / text / JTextComponent.java
blobafa1f24a6a4f6342ba96095001675c961fc8da62
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)
9 any later version.
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
19 02110-1301 USA.
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.
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
88 /**
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;
97 /**
98 * Constructor AccessibleJTextComponent
100 public AccessibleJTextComponent()
102 // Nothing to do here.
106 * getCaretPosition
107 * @return int
109 public int getCaretPosition()
111 return 0; // TODO
115 * getSelectedText
116 * @return String
118 public String getSelectedText()
120 return null; // TODO
124 * getSelectionStart
125 * @return int
127 public int getSelectionStart()
129 return 0; // TODO
133 * getSelectionEnd
134 * @return int
136 public int getSelectionEnd()
138 return 0; // TODO
142 * caretUpdate
143 * @param value0 TODO
145 public void caretUpdate(CaretEvent value0)
147 // TODO
151 * getAccessibleStateSet
152 * @return AccessibleStateSet
154 public AccessibleStateSet getAccessibleStateSet()
156 return null; // TODO
160 * getAccessibleRole
161 * @return AccessibleRole
163 public AccessibleRole getAccessibleRole()
165 return null; // TODO
169 * getAccessibleText
170 * @return AccessibleText
172 public AccessibleText getAccessibleText()
174 return null; // TODO
178 * insertUpdate
179 * @param value0 TODO
181 public void insertUpdate(DocumentEvent value0)
183 // TODO
187 * removeUpdate
188 * @param value0 TODO
190 public void removeUpdate(DocumentEvent value0)
192 // TODO
196 * changedUpdate
197 * @param value0 TODO
199 public void changedUpdate(DocumentEvent value0)
201 // TODO
205 * getIndexAtPoint
206 * @param value0 TODO
207 * @return int
209 public int getIndexAtPoint(Point value0)
211 return 0; // TODO
215 * getRootEditorRect
216 * @return Rectangle
218 Rectangle getRootEditorRect()
220 return null;
224 * getCharacterBounds
225 * @param value0 TODO
226 * @return Rectangle
228 public Rectangle getCharacterBounds(int value0)
230 return null; // TODO
234 * getCharCount
235 * @return int
237 public int getCharCount()
239 return 0; // TODO
243 * getCharacterAttribute
244 * @param value0 TODO
245 * @return AttributeSet
247 public AttributeSet getCharacterAttribute(int value0)
249 return null; // TODO
253 * getAtIndex
254 * @param value0 TODO
255 * @param value1 TODO
256 * @return String
258 public String getAtIndex(int value0, int value1)
260 return null; // TODO
264 * getAfterIndex
265 * @param value0 TODO
266 * @param value1 TODO
267 * @return String
269 public String getAfterIndex(int value0, int value1)
271 return null; // TODO
275 * getBeforeIndex
276 * @param value0 TODO
277 * @param value1 TODO
278 * @return String
280 public String getBeforeIndex(int value0, int value1)
282 return null; // TODO
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)
299 this.key = key;
300 this.actionName = actionName;
305 * According to <a
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
310 * the new framework.
312 * <p>A little bit of experimentation with these classes reveals the following
313 * structure:
315 * <ul>
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
325 * its keys. </li>
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.
332 * </ul>
335 private class KeymapWrapper extends InputMap
337 Keymap map;
339 public KeymapWrapper(Keymap k)
341 map = k;
344 public int size()
346 return map.getBoundKeyStrokes().length + super.size();
349 public Object get(KeyStroke ks)
351 Action mapped = null;
352 Keymap m = map;
353 while(mapped == null && m != null)
355 mapped = m.getAction(ks);
356 if (mapped == null && ks.getKeyEventType() == KeyEvent.KEY_TYPED)
357 mapped = m.getDefaultAction();
358 if (mapped == null)
359 m = m.getResolveParent();
362 if (mapped == null)
363 return super.get(ks);
364 else
365 return mapped;
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];
377 return bothKeys;
380 public KeyStroke[] allKeys()
382 KeyStroke[] superKeys = super.allKeys();
383 KeyStroke[] mapKeys = map.getBoundKeyStrokes();
384 int skl = 0;
385 int mkl = 0;
386 if (superKeys != null)
387 skl = superKeys.length;
388 if (mapKeys != null)
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];
395 return bothKeys;
399 private class KeymapActionMap extends ActionMap
401 Keymap map;
403 public KeymapActionMap(Keymap k)
405 map = k;
408 public Action get(Object cmd)
410 if (cmd instanceof Action)
411 return (Action) cmd;
412 else
413 return super.get(cmd);
416 public int size()
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];
430 return bothKeys;
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];
442 return bothKeys;
447 static class DefaultKeymap implements Keymap
449 String name;
450 Keymap parent;
451 Hashtable map;
452 Action defaultAction;
454 public DefaultKeymap(String name)
456 this.name = name;
457 this.map = new Hashtable();
460 public void addActionForKeyStroke(KeyStroke key, Action a)
462 map.put(key, 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);
480 else
481 return null;
484 public Action[] getBoundActions()
486 Action [] ret = new Action[map.size()];
487 Enumeration e = map.elements();
488 int i = 0;
489 while (e.hasMoreElements())
491 ret[i++] = (Action) e.nextElement();
493 return ret;
496 public KeyStroke[] getBoundKeyStrokes()
498 KeyStroke [] ret = new KeyStroke[map.size()];
499 Enumeration e = map.keys();
500 int i = 0;
501 while (e.hasMoreElements())
503 ret[i++] = (KeyStroke) e.nextElement();
505 return ret;
508 public Action getDefaultAction()
510 return defaultAction;
513 public KeyStroke[] getKeyStrokesForAction(Action a)
515 int i = 0;
516 Enumeration e = map.keys();
517 while (e.hasMoreElements())
519 if (map.get(e.nextElement()).equals(a))
520 ++i;
522 KeyStroke [] ret = new KeyStroke[i];
523 i = 0;
524 e = map.keys();
525 while (e.hasMoreElements())
527 KeyStroke k = (KeyStroke) e.nextElement();
528 if (map.get(k).equals(a))
529 ret[i++] = k;
531 return ret;
534 public String getName()
536 return name;
539 public Keymap getResolveParent()
541 return parent;
544 public boolean isLocallyDefined(KeyStroke key)
546 return map.containsKey(key);
549 public void removeBindings()
551 map.clear();
554 public void removeKeyStrokeBinding(KeyStroke key)
556 map.remove(key);
559 public void setDefaultAction(Action a)
561 defaultAction = a;
564 public void setResolveParent(Keymap p)
566 parent = 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()
578 && flavors != null))
579 return false;
581 for (int i = 0; i < flavors.length; ++i)
582 if (flavors[i].equals(DataFlavor.stringFlavor))
583 return true;
585 return false;
588 public void exportToClipboard(JComponent component, Clipboard clipboard,
589 int action)
591 JTextComponent textComponent = (JTextComponent) component;
592 int start = textComponent.getSelectionStart();
593 int end = textComponent.getSelectionEnd();
595 if (start == end)
596 return;
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.
606 if (action == MOVE)
607 doc.remove(start, end - start);
609 catch (BadLocationException e)
611 // Ignore this and do nothing.
615 public int getSourceActions()
617 return NONE;
620 public boolean importData(JComponent component, Transferable transferable)
622 DataFlavor flavor = null;
623 DataFlavor[] flavors = transferable.getTransferDataFlavors();
625 if (flavors == null)
626 return false;
628 for (int i = 0; i < flavors.length; ++i)
629 if (flavors[i].equals(DataFlavor.stringFlavor))
630 flavor = flavors[i];
632 if (flavor == null)
633 return false;
637 JTextComponent textComponent = (JTextComponent) component;
638 String data = (String) transferable.getTransferData(flavor);
639 textComponent.replaceSelection(data);
640 return true;
642 catch (IOException e)
644 // Ignored.
646 catch (UnsupportedFlavorException e)
648 // Ignored.
651 return false;
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
674 * @see #addKeymap
675 * @see #removeKeymap
676 * @see #keymaps
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
690 * @see #addKeymap
691 * @see #getKeymap()
692 * @see #keymaps
694 public static Keymap removeKeymap(String n)
696 Keymap km = (Keymap) keymaps.get(n);
697 keymaps.remove(n);
698 return km;
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
706 * harmless.
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
713 * @see #removeKeymap
714 * @see #getKeymap()
715 * @see #keymaps
717 public static Keymap addKeymap(String n, Keymap parent)
719 Keymap k = new DefaultKeymap(n);
720 k.setResolveParent(parent);
721 if (n != null)
722 keymaps.put(n, k);
723 return k;
727 * Get the current Keymap of this component.
729 * @return The component's current Keymap
731 * @see #setKeymap
732 * @see #keymap
734 public Keymap getKeymap()
736 return keymap;
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>.
745 * @see #getKeymap()
746 * @see #keymap
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
759 // course).
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);
765 else
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)
780 if (kw == null)
781 childInputMap.setParent(childInputMap.getParent().getParent());
782 else
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)
793 if (kw != null)
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)
806 setActionMap(kam);
807 else
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)
822 if (kam == null)
823 childActionMap.setParent(childActionMap.getParent().getParent());
824 else
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)
835 if (kam != null)
837 kam.setParent(childActionMap.getParent());
838 childActionMap.setParent(kam);
843 // phase 3: update the explicit keymap field
845 Keymap old = keymap;
846 keymap = k;
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
856 * <code>a</code>.
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
862 * @see Action#NAME
863 * @see Action#getValue
864 * @see KeyBinding#actionName
866 public static void loadKeymap(Keymap map,
867 JTextComponent.KeyBinding[] bindings,
868 Action[] actions)
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.
897 Document doc;
898 Caret caret;
899 boolean editable;
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());
921 setFocusable(true);
922 setEditable(true);
923 enableEvents(AWTEvent.KEY_EVENT_MASK);
924 updateUI();
927 public void setDocument(Document newDoc)
929 Document oldDoc = doc;
930 doc = newDoc;
931 firePropertyChange("document", oldDoc, newDoc);
932 revalidate();
933 repaint();
936 public Document getDocument()
938 return doc;
942 * Get the <code>AccessibleContext</code> of this object.
944 * @return an <code>AccessibleContext</code> object
946 public AccessibleContext getAccessibleContext()
948 return null;
951 public void setMargin(Insets m)
953 margin = m;
956 public Insets getMargin()
958 return margin;
961 public void setText(String text)
965 if (doc instanceof AbstractDocument)
966 ((AbstractDocument) doc).replace(0, doc.getLength(), text, null);
967 else
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.
982 * @return the text
984 * @exception NullPointerException if the underlaying document is null
986 public String getText()
988 if (doc == null)
989 return null;
993 return doc.getText(0, doc.getLength());
995 catch (BadLocationException e)
997 // This should never happen.
998 return "";
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
1008 * @return the text
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.
1034 return null;
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()
1065 return (TextUI) ui;
1069 * This method sets the label's UI delegate.
1071 * @param newUI The label's UI delegate.
1073 public void setUI(TextUI newUI)
1075 super.setUI(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,
1093 int direction)
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;
1100 else
1101 throw new IllegalArgumentException("orientation must be either "
1102 + "javax.swing.SwingConstants.VERTICAL "
1103 + "or "
1104 + "javax.swing.SwingConstants.HORIZONTAL"
1108 public int getScrollableBlockIncrement(Rectangle visible, int orientation,
1109 int direction)
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;
1116 else
1117 throw new IllegalArgumentException("orientation must be either "
1118 + "javax.swing.SwingConstants.VERTICAL "
1119 + "or "
1120 + "javax.swing.SwingConstants.HORIZONTAL"
1125 * Checks whether this text component it editable.
1127 * @return true if editable, false otherwise
1129 public boolean isEditable()
1131 return editable;
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)
1142 return;
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()
1156 return caret;
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)
1166 if (caret != null)
1167 caret.deinstall(this);
1169 Caret oldCaret = caret;
1170 caret = newCaret;
1172 if (caret != null)
1173 caret.install(this);
1175 firePropertyChange("caret", oldCaret, newCaret);
1178 public Color getCaretColor()
1180 return caretColor;
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)
1243 if (doc == null)
1244 return;
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)
1258 if (doc == null)
1259 return;
1261 if (position < 0 || position > doc.getLength())
1262 throw new IllegalArgumentException();
1264 caret.moveDot(position);
1267 public Highlighter getHighlighter()
1269 return highlighter;
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)
1362 caret.setDot(dot);
1363 return;
1368 int start = getSelectionStart();
1369 int end = getSelectionEnd();
1371 // Remove selected text.
1372 if (dot != mark)
1373 doc.remove(start, end - start);
1375 // Insert new text.
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;
1392 return false;
1395 public boolean getScrollableTracksViewportWidth()
1397 if (getParent() instanceof JViewport)
1398 return ((JViewport) getParent()).getWidth() > getPreferredSize().width;
1400 return false;
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
1435 * was updated.
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()
1484 return dragEnabled;
1487 public void setDragEnabled(boolean enabled)
1489 dragEnabled = enabled;
1492 public int viewToModel(Point pt)
1494 return getUI().viewToModel(this, pt);
1497 public void copy()
1499 doTransferAction("copy", TransferHandler.getCopyAction());
1502 public void cut()
1504 doTransferAction("cut", TransferHandler.getCutAction());
1507 public void paste()
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);
1523 // Perform action.
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)
1532 return;
1534 char oldKey = focusAccelerator;
1535 focusAccelerator = newKey;
1536 firePropertyChange(FOCUS_ACCELERATOR_KEY, oldKey, newKey);
1539 public char getFocusAccelerator()
1541 return focusAccelerator;
1545 * @since 1.4
1547 public NavigationFilter getNavigationFilter()
1549 return navigationFilter;
1553 * @since 1.4
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)
1578 throws IOException
1580 if (streamDescription != null)
1582 Document d = getDocument();
1583 if (d != null)
1584 d.putProperty(Document.StreamDescriptionProperty, streamDescription);
1587 StringBuffer b = new StringBuffer();
1588 int c;
1590 // Read till -1 (EOF).
1591 while ((c = input.read()) >= 0)
1592 b.append((char) c);
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)
1606 throws IOException
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
1619 * event
1621 public String getToolTipText(MouseEvent ev)
1623 return getUI().getToolTipText(this, ev.getPoint());