KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > text > JTextComponent


1 /*
2  * @(#)JTextComponent.java 1.213 06/04/10
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing.text;
8
9 import java.lang.reflect.Method JavaDoc;
10
11 import java.security.AccessController JavaDoc;
12 import java.security.PrivilegedAction JavaDoc;
13
14 import java.util.Collections JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Hashtable JavaDoc;
17 import java.util.Enumeration JavaDoc;
18 import java.util.Vector JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.Map.Entry;
22 import java.util.Set JavaDoc;
23
24 import java.io.*;
25
26 import java.awt.*;
27 import java.awt.event.*;
28 import java.awt.datatransfer.*;
29 import java.awt.im.InputContext JavaDoc;
30 import java.awt.im.InputMethodRequests JavaDoc;
31 import java.awt.font.TextHitInfo JavaDoc;
32 import java.awt.font.TextAttribute JavaDoc;
33
34 import java.text.*;
35 import java.text.AttributedCharacterIterator.Attribute;
36
37 import javax.swing.*;
38 import javax.swing.event.*;
39 import javax.swing.plaf.*;
40
41 import javax.accessibility.*;
42
43 import sun.awt.AppContext;
44
45 /**
46  * <code>JTextComponent</code> is the base class for swing text
47  * components. It tries to be compatible with the
48  * <code>java.awt.TextComponent</code> class
49  * where it can reasonably do so. Also provided are other services
50  * for additional flexibility (beyond the pluggable UI and bean
51  * support).
52  * You can find information on how to use the functionality
53  * this class provides in
54  * <a HREF="http://java.sun.com/docs/books/tutorial/uiswing/components/generaltext.html">General Rules for Using Text Components</a>,
55  * a section in <em>The Java Tutorial.</em>
56  *
57  * <p>
58  * <dl>
59  * <dt><b><font size=+1>Caret Changes</font></b>
60  * <dd>
61  * The caret is a pluggable object in swing text components.
62  * Notification of changes to the caret position and the selection
63  * are sent to implementations of the <code>CaretListener</code>
64  * interface that have been registered with the text component.
65  * The UI will install a default caret unless a customized caret
66  * has been set. <br>
67  * By default the caret tracks all the document changes
68  * performed on the Event Dispatching Thread and updates it's position
69  * accordingly if an insertion occurs before or at the caret position
70  * or a removal occurs before the caret position. <code>DefaultCaret</code>
71  * tries to make itself visible which may lead to scrolling
72  * of a text component within <code>JScrollPane</code>. The default caret
73  * behavior can be changed by the {@link DefaultCaret#setUpdatePolicy} method.
74  * <br>
75  * <b>Note</b>: Non-editable text components also have a caret though
76  * it may not be painted.
77  *
78  * <p>
79  * <dt><b><font size=+1>Commands</font></b>
80  * <dd>
81  * Text components provide a number of commands that can be used
82  * to manipulate the component. This is essentially the way that
83  * the component expresses its capabilities. These are expressed
84  * in terms of the swing <code>Action</code> interface,
85  * using the <code>TextAction</code> implementation.
86  * The set of commands supported by the text component can be
87  * found with the {@link #getActions} method. These actions
88  * can be bound to key events, fired from buttons, etc.
89  *
90  * <p>
91  * <dt><b><font size=+1>Text Input</font></b>
92  * <dd>
93  * The text components support flexible and internationalized text input, using
94  * keymaps and the input method framework, while maintaining compatibility with
95  * the AWT listener model.
96  * <p>
97  * A {@link javax.swing.text.Keymap} lets an application bind key
98  * strokes to actions.
99  * In order to allow keymaps to be shared across multiple text components, they
100  * can use actions that extend <code>TextAction</code>.
101  * <code>TextAction</code> can determine which <code>JTextComponent</code>
102  * most recently has or had focus and therefore is the subject of
103  * the action (In the case that the <code>ActionEvent</code>
104  * sent to the action doesn't contain the target text component as its source).
105  * <p>
106  * The <a HREF="../../../../guide/imf/spec.html">input method framework</a>
107  * lets text components interact with input methods, separate software
108  * components that preprocess events to let users enter thousands of
109  * different characters using keyboards with far fewer keys.
110  * <code>JTextComponent</code> is an <em>active client</em> of
111  * the framework, so it implements the preferred user interface for interacting
112  * with input methods. As a consequence, some key events do not reach the text
113  * component because they are handled by an input method, and some text input
114  * reaches the text component as committed text within an {@link
115  * java.awt.event.InputMethodEvent} instead of as a key event.
116  * The complete text input is the combination of the characters in
117  * <code>keyTyped</code> key events and committed text in input method events.
118  * <p>
119  * The AWT listener model lets applications attach event listeners to
120  * components in order to bind events to actions. Swing encourages the
121  * use of keymaps instead of listeners, but maintains compatibility
122  * with listeners by giving the listeners a chance to steal an event
123  * by consuming it.
124  * <p>
125  * Keyboard event and input method events are handled in the following stages,
126  * with each stage capable of consuming the event:
127  *
128  * <table border=1 summary="Stages of keyboard and input method event handling">
129  * <tr>
130  * <th id="stage"><p align="left">Stage</p></th>
131  * <th id="ke"><p align="left">KeyEvent</p></th>
132  * <th id="ime"><p align="left">InputMethodEvent</p></th></tr>
133  * <tr><td headers="stage">1. </td>
134  * <td headers="ke">input methods </td>
135  * <td headers="ime">(generated here)</td></tr>
136  * <tr><td headers="stage">2. </td>
137  * <td headers="ke">focus manager </td>
138  * <td headers="ime"></td>
139  * </tr>
140  * <tr>
141  * <td headers="stage">3. </td>
142  * <td headers="ke">registered key listeners</td>
143  * <td headers="ime">registered input method listeners</tr>
144  * <tr>
145  * <td headers="stage">4. </td>
146  * <td headers="ke"></td>
147  * <td headers="ime">input method handling in JTextComponent</tr>
148  * <tr>
149  * <td headers="stage">5. </td><td headers="ke ime" colspan=2>keymap handling using the current keymap</td></tr>
150  * <tr><td headers="stage">6. </td><td headers="ke">keyboard handling in JComponent (e.g. accelerators, component navigation, etc.)</td>
151  * <td headers="ime"></td></tr>
152  * </table>
153  *
154  * <p>
155  * To maintain compatibility with applications that listen to key
156  * events but are not aware of input method events, the input
157  * method handling in stage 4 provides a compatibility mode for
158  * components that do not process input method events. For these
159  * components, the committed text is converted to keyTyped key events
160  * and processed in the key event pipeline starting at stage 3
161  * instead of in the input method event pipeline.
162  * <p>
163  * By default the component will create a keymap (named <b>DEFAULT_KEYMAP</b>)
164  * that is shared by all JTextComponent instances as the default keymap.
165  * Typically a look-and-feel implementation will install a different keymap
166  * that resolves to the default keymap for those bindings not found in the
167  * different keymap. The minimal bindings include:
168  * <ul>
169  * <li>inserting content into the editor for the
170  * printable keys.
171  * <li>removing content with the backspace and del
172  * keys.
173  * <li>caret movement forward and backward
174  * </ul>
175  *
176  * <p>
177  * <dt><b><font size=+1>Model/View Split</font></b>
178  * <dd>
179  * The text components have a model-view split. A text component pulls
180  * together the objects used to represent the model, view, and controller.
181  * The text document model may be shared by other views which act as observers
182  * of the model (e.g. a document may be shared by multiple components).
183  *
184  * <p align=center><img SRC="doc-files/editor.gif" alt="Diagram showing interaction between Controller, Document, events, and ViewFactory"
185  * HEIGHT=358 WIDTH=587></p>
186  *
187  * <p>
188  * The model is defined by the {@link Document} interface.
189  * This is intended to provide a flexible text storage mechanism
190  * that tracks change during edits and can be extended to more sophisticated
191  * models. The model interfaces are meant to capture the capabilities of
192  * expression given by SGML, a system used to express a wide variety of
193  * content.
194  * Each modification to the document causes notification of the
195  * details of the change to be sent to all observers in the form of a
196  * {@link DocumentEvent} which allows the views to stay up to date with the model.
197  * This event is sent to observers that have implemented the
198  * {@link DocumentListener}
199  * interface and registered interest with the model being observed.
200  *
201  * <p>
202  * <dt><b><font size=+1>Location Information</font></b>
203  * <dd>
204  * The capability of determining the location of text in
205  * the view is provided. There are two methods, {@link #modelToView}
206  * and {@link #viewToModel} for determining this information.
207  *
208  * <p>
209  * <dt><b><font size=+1>Undo/Redo support</font></b>
210  * <dd>
211  * Support for an edit history mechanism is provided to allow
212  * undo/redo operations. The text component does not itself
213  * provide the history buffer by default, but does provide
214  * the <code>UndoableEdit</code> records that can be used in conjunction
215  * with a history buffer to provide the undo/redo support.
216  * The support is provided by the Document model, which allows
217  * one to attach UndoableEditListener implementations.
218  *
219  * <p>
220  * <dt><b><font size=+1>Thread Safety</font></b>
221  * <dd>
222  * The swing text components provide some support of thread
223  * safe operations. Because of the high level of configurability
224  * of the text components, it is possible to circumvent the
225  * protection provided. The protection primarily comes from
226  * the model, so the documentation of <code>AbstractDocument</code>
227  * describes the assumptions of the protection provided.
228  * The methods that are safe to call asynchronously are marked
229  * with comments.
230  *
231  * <p>
232  * <dt><b><font size=+1>Newlines</font></b>
233  * <dd>
234  * For a discussion on how newlines are handled, see
235  * <a HREF="DefaultEditorKit.html">DefaultEditorKit</a>.
236  * </dl>
237  *
238  * <p>
239  * <strong>Warning:</strong>
240  * Serialized objects of this class will not be compatible with
241  * future Swing releases. The current serialization support is
242  * appropriate for short term storage or RMI between applications running
243  * the same version of Swing. As of 1.4, support for long term storage
244  * of all JavaBeans<sup><font size="-2">TM</font></sup>
245  * has been added to the <code>java.beans</code> package.
246  * Please see {@link java.beans.XMLEncoder}.
247  *
248  * @beaninfo
249  * attribute: isContainer false
250  *
251  * @author Timothy Prinzing
252  * @version 1.213 04/10/06
253  * @see Document
254  * @see DocumentEvent
255  * @see DocumentListener
256  * @see Caret
257  * @see CaretEvent
258  * @see CaretListener
259  * @see TextUI
260  * @see View
261  * @see ViewFactory
262  */

263 public abstract class JTextComponent extends JComponent implements Scrollable, Accessible
264 {
265     /**
266      * Creates a new <code>JTextComponent</code>.
267      * Listeners for caret events are established, and the pluggable
268      * UI installed. The component is marked as editable. No layout manager
269      * is used, because layout is managed by the view subsystem of text.
270      * The document model is set to <code>null</code>.
271      */

272     public JTextComponent() {
273         super();
274     // enable InputMethodEvent for on-the-spot pre-editing
275
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.INPUT_METHOD_EVENT_MASK);
276         caretEvent = new MutableCaretEvent(this);
277         addMouseListener(caretEvent);
278         addFocusListener(caretEvent);
279         setEditable(true);
280     setDragEnabled(false);
281         setLayout(null); // layout is managed by View hierarchy
282
updateUI();
283     }
284
285     /**
286      * Fetches the user-interface factory for this text-oriented editor.
287      *
288      * @return the factory
289      */

290     public TextUI getUI() { return (TextUI)ui; }
291
292     /**
293      * Sets the user-interface factory for this text-oriented editor.
294      *
295      * @param ui the factory
296      */

297     public void setUI(TextUI ui) {
298         super.setUI(ui);
299     }
300
301     /**
302      * Reloads the pluggable UI. The key used to fetch the
303      * new interface is <code>getUIClassID()</code>. The type of
304      * the UI is <code>TextUI</code>. <code>invalidate</code>
305      * is called after setting the UI.
306      */

307     public void updateUI() {
308         setUI((TextUI)UIManager.getUI(this));
309         invalidate();
310     }
311
312     /**
313      * Adds a caret listener for notification of any changes
314      * to the caret.
315      *
316      * @param listener the listener to be added
317      * @see javax.swing.event.CaretEvent
318      */

319     public void addCaretListener(CaretListener listener) {
320         listenerList.add(CaretListener.class, listener);
321     }
322
323     /**
324      * Removes a caret listener.
325      *
326      * @param listener the listener to be removed
327      * @see javax.swing.event.CaretEvent
328      */

329     public void removeCaretListener(CaretListener listener) {
330         listenerList.remove(CaretListener.class, listener);
331     }
332
333     /**
334      * Returns an array of all the caret listeners
335      * registered on this text component.
336      *
337      * @return all of this component's <code>CaretListener</code>s
338      * or an empty
339      * array if no caret listeners are currently registered
340      *
341      * @see #addCaretListener
342      * @see #removeCaretListener
343      *
344      * @since 1.4
345      */

346     public CaretListener[] getCaretListeners() {
347         return (CaretListener[])listenerList.getListeners(CaretListener.class);
348     }
349
350     /**
351      * Notifies all listeners that have registered interest for
352      * notification on this event type. The event instance
353      * is lazily created using the parameters passed into
354      * the fire method. The listener list is processed in a
355      * last-to-first manner.
356      *
357      * @param e the event
358      * @see EventListenerList
359      */

360     protected void fireCaretUpdate(CaretEvent e) {
361         // Guaranteed to return a non-null array
362
Object JavaDoc[] listeners = listenerList.getListenerList();
363         // Process the listeners last to first, notifying
364
// those that are interested in this event
365
for (int i = listeners.length-2; i>=0; i-=2) {
366             if (listeners[i]==CaretListener.class) {
367                 ((CaretListener)listeners[i+1]).caretUpdate(e);
368             }
369         }
370     }
371
372     /**
373      * Associates the editor with a text document.
374      * The currently registered factory is used to build a view for
375      * the document, which gets displayed by the editor after revalidation.
376      * A PropertyChange event ("document") is propagated to each listener.
377      *
378      * @param doc the document to display/edit
379      * @see #getDocument
380      * @beaninfo
381      * description: the text document model
382      * bound: true
383      * expert: true
384      */

385     public void setDocument(Document JavaDoc doc) {
386         Document JavaDoc old = model;
387
388     /*
389      * aquire a read lock on the old model to prevent notification of
390      * mutations while we disconnecting the old model.
391      */

392     try {
393         if (old instanceof AbstractDocument JavaDoc) {
394         ((AbstractDocument JavaDoc)old).readLock();
395         }
396         if (accessibleContext != null) {
397         model.removeDocumentListener(
398             ((AccessibleJTextComponent)accessibleContext));
399         }
400         if (inputMethodRequestsHandler != null) {
401         model.removeDocumentListener((DocumentListener)inputMethodRequestsHandler);
402         }
403         model = doc;
404
405             // Set the document's run direction property to match the
406
// component's ComponentOrientation property.
407
Boolean JavaDoc runDir = getComponentOrientation().isLeftToRight()
408                              ? TextAttribute.RUN_DIRECTION_LTR
409                              : TextAttribute.RUN_DIRECTION_RTL;
410             doc.putProperty( TextAttribute.RUN_DIRECTION, runDir );
411
412         firePropertyChange("document", old, doc);
413     } finally {
414         if (old instanceof AbstractDocument JavaDoc) {
415         ((AbstractDocument JavaDoc)old).readUnlock();
416         }
417     }
418
419         revalidate();
420         repaint();
421         if (accessibleContext != null) {
422             model.addDocumentListener(
423                 ((AccessibleJTextComponent)accessibleContext));
424         }
425     if (inputMethodRequestsHandler != null) {
426             model.addDocumentListener((DocumentListener)inputMethodRequestsHandler);
427         }
428     }
429
430     /**
431      * Fetches the model associated with the editor. This is
432      * primarily for the UI to get at the minimal amount of
433      * state required to be a text editor. Subclasses will
434      * return the actual type of the model which will typically
435      * be something that extends Document.
436      *
437      * @return the model
438      */

439     public Document JavaDoc getDocument() {
440         return model;
441     }
442
443     // Override of Component.setComponentOrientation
444
public void setComponentOrientation( ComponentOrientation o ) {
445         // Set the document's run direction property to match the
446
// ComponentOrientation property.
447
Document JavaDoc doc = getDocument();
448         if( doc != null ) {
449             Boolean JavaDoc runDir = o.isLeftToRight()
450                              ? TextAttribute.RUN_DIRECTION_LTR
451                              : TextAttribute.RUN_DIRECTION_RTL;
452             doc.putProperty( TextAttribute.RUN_DIRECTION, runDir );
453         }
454         super.setComponentOrientation( o );
455     }
456
457     /**
458      * Fetches the command list for the editor. This is
459      * the list of commands supported by the plugged-in UI
460      * augmented by the collection of commands that the
461      * editor itself supports. These are useful for binding
462      * to events, such as in a keymap.
463      *
464      * @return the command list
465      */

466     public Action JavaDoc[] getActions() {
467         return getUI().getEditorKit(this).getActions();
468     }
469
470     /**
471      * Sets margin space between the text component's border
472      * and its text. The text component's default <code>Border</code>
473      * object will use this value to create the proper margin.
474      * However, if a non-default border is set on the text component,
475      * it is that <code>Border</code> object's responsibility to create the
476      * appropriate margin space (else this property will effectively
477      * be ignored). This causes a redraw of the component.
478      * A PropertyChange event ("margin") is sent to all listeners.
479      *
480      * @param m the space between the border and the text
481      * @beaninfo
482      * description: desired space between the border and text area
483      * bound: true
484      */

485     public void setMargin(Insets m) {
486         Insets old = margin;
487         margin = m;
488         firePropertyChange("margin", old, m);
489         invalidate();
490     }
491
492     /**
493      * Returns the margin between the text component's border and
494      * its text.
495      *
496      * @return the margin
497      */

498     public Insets getMargin() {
499         return margin;
500     }
501
502     /**
503      * Sets the <code>NavigationFilter</code>. <code>NavigationFilter</code>
504      * is used by <code>DefaultCaret</code> and the default cursor movement
505      * actions as a way to restrict the cursor movement.
506      *
507      * @since 1.4
508      */

509     public void setNavigationFilter(NavigationFilter JavaDoc filter) {
510         navigationFilter = filter;
511     }
512
513     /**
514      * Returns the <code>NavigationFilter</code>. <code>NavigationFilter</code>
515      * is used by <code>DefaultCaret</code> and the default cursor movement
516      * actions as a way to restrict the cursor movement. A null return value
517      * implies the cursor movement and selection should not be restricted.
518      *
519      * @since 1.4
520      * @return the NavigationFilter
521      */

522     public NavigationFilter JavaDoc getNavigationFilter() {
523         return navigationFilter;
524     }
525
526     /**
527      * Fetches the caret that allows text-oriented navigation over
528      * the view.
529      *
530      * @return the caret
531      */

532     public Caret JavaDoc getCaret() {
533         return caret;
534     }
535
536     /**
537      * Sets the caret to be used. By default this will be set
538      * by the UI that gets installed. This can be changed to
539      * a custom caret if desired. Setting the caret results in a
540      * PropertyChange event ("caret") being fired.
541      *
542      * @param c the caret
543      * @see #getCaret
544      * @beaninfo
545      * description: the caret used to select/navigate
546      * bound: true
547      * expert: true
548      */

549     public void setCaret(Caret JavaDoc c) {
550         if (caret != null) {
551             caret.removeChangeListener(caretEvent);
552             caret.deinstall(this);
553         }
554         Caret JavaDoc old = caret;
555         caret = c;
556         if (caret != null) {
557             caret.install(this);
558             caret.addChangeListener(caretEvent);
559         }
560         firePropertyChange("caret", old, caret);
561     }
562
563     /**
564      * Fetches the object responsible for making highlights.
565      *
566      * @return the highlighter
567      */

568     public Highlighter JavaDoc getHighlighter() {
569         return highlighter;
570     }
571
572     /**
573      * Sets the highlighter to be used. By default this will be set
574      * by the UI that gets installed. This can be changed to
575      * a custom highlighter if desired. The highlighter can be set to
576      * <code>null</code> to disable it.
577      * A PropertyChange event ("highlighter") is fired
578      * when a new highlighter is installed.
579      *
580      * @param h the highlighter
581      * @see #getHighlighter
582      * @beaninfo
583      * description: object responsible for background highlights
584      * bound: true
585      * expert: true
586      */

587     public void setHighlighter(Highlighter JavaDoc h) {
588         if (highlighter != null) {
589             highlighter.deinstall(this);
590         }
591         Highlighter JavaDoc old = highlighter;
592         highlighter = h;
593         if (highlighter != null) {
594             highlighter.install(this);
595         }
596         firePropertyChange("highlighter", old, h);
597     }
598
599     /**
600      * Sets the keymap to use for binding events to
601      * actions. Setting to <code>null</code> effectively disables
602      * keyboard input.
603      * A PropertyChange event ("keymap") is fired when a new keymap
604      * is installed.
605      *
606      * @param map the keymap
607      * @see #getKeymap
608      * @beaninfo
609      * description: set of key event to action bindings to use
610      * bound: true
611      */

612     public void setKeymap(Keymap JavaDoc map) {
613         Keymap JavaDoc old = keymap;
614         keymap = map;
615         firePropertyChange("keymap", old, keymap);
616     updateInputMap(old, map);
617     }
618
619     /**
620      * Sets the <code>dragEnabled</code> property,
621      * which must be <code>true</code> to enable
622      * automatic drag handling (the first part of drag and drop)
623      * on this component.
624      * The <code>transferHandler</code> property needs to be set
625      * to a non-<code>null</code> value for the drag to do
626      * anything. The default value of the <code>dragEnabled</code>
627      * property
628      * is <code>false</code>.
629      * <p>
630      * When automatic drag handling is enabled,
631      * most look and feels begin a drag-and-drop operation
632      * whenever the user presses the mouse button over a selection
633      * and then moves the mouse a few pixels.
634      * Setting this property to <code>true</code>
635      * can therefore have a subtle effect on
636      * how selections behave.
637      * <p>
638      * Some look and feels might not support automatic drag and drop;
639      * they will ignore this property. You can work around such
640      * look and feels by modifying the component
641      * to directly call the <code>exportAsDrag</code> method of a
642      * <code>TransferHandler</code>.
643      *
644      * @param b the value to set the <code>dragEnabled</code> property to
645      * @exception HeadlessException if
646      * <code>b</code> is <code>true</code> and
647      * <code>GraphicsEnvironment.isHeadless()</code>
648      * returns <code>true</code>
649      * @see java.awt.GraphicsEnvironment#isHeadless
650      * @see #getDragEnabled
651      * @see #setTransferHandler
652      * @see TransferHandler
653      * @since 1.4
654      *
655      * @beaninfo
656      * description: determines whether automatic drag handling is enabled
657      * bound: false
658      */

659     public void setDragEnabled(boolean b) {
660         if (b && GraphicsEnvironment.isHeadless()) {
661             throw new HeadlessException();
662         }
663     dragEnabled = b;
664     }
665
666     /**
667      * Gets the <code>dragEnabled</code> property.
668      *
669      * @return the value of the <code>dragEnabled</code> property
670      * @see #setDragEnabled
671      * @since 1.4
672      */

673     public boolean getDragEnabled() {
674     return dragEnabled;
675     }
676
677
678     /**
679      * Updates the <code>InputMap</code>s in response to a
680      * <code>Keymap</code> change.
681      * @param oldKm the old <code>Keymap</code>
682      * @param newKm the new <code>Keymap</code>
683      */

684     void updateInputMap(Keymap JavaDoc oldKm, Keymap JavaDoc newKm) {
685     // Locate the current KeymapWrapper.
686
InputMap km = getInputMap(JComponent.WHEN_FOCUSED);
687     InputMap last = km;
688     while (km != null && !(km instanceof KeymapWrapper)) {
689         last = km;
690         km = km.getParent();
691     }
692     if (km != null) {
693         // Found it, tweak the InputMap that points to it, as well
694
// as anything it points to.
695
if (newKm == null) {
696         if (last != km) {
697             last.setParent(km.getParent());
698         }
699         else {
700             last.setParent(null);
701         }
702         }
703         else {
704         InputMap newKM = new KeymapWrapper(newKm);
705         last.setParent(newKM);
706         if (last != km) {
707             newKM.setParent(km.getParent());
708         }
709         }
710     }
711     else if (newKm != null) {
712         km = getInputMap(JComponent.WHEN_FOCUSED);
713         if (km != null) {
714         // Couldn't find it.
715
// Set the parent of WHEN_FOCUSED InputMap to be the new one.
716
InputMap newKM = new KeymapWrapper(newKm);
717         newKM.setParent(km.getParent());
718         km.setParent(newKM);
719         }
720     }
721
722     // Do the same thing with the ActionMap
723
ActionMap am = getActionMap();
724     ActionMap lastAM = am;
725     while (am != null && !(am instanceof KeymapActionMap)) {
726         lastAM = am;
727         am = am.getParent();
728     }
729     if (am != null) {
730         // Found it, tweak the Actionap that points to it, as well
731
// as anything it points to.
732
if (newKm == null) {
733         if (lastAM != am) {
734             lastAM.setParent(am.getParent());
735         }
736         else {
737             lastAM.setParent(null);
738         }
739         }
740         else {
741         ActionMap newAM = new KeymapActionMap(newKm);
742         lastAM.setParent(newAM);
743         if (lastAM != am) {
744             newAM.setParent(am.getParent());
745         }
746         }
747     }
748     else if (newKm != null) {
749         am = getActionMap();
750         if (am != null) {
751         // Couldn't find it.
752
// Set the parent of ActionMap to be the new one.
753
ActionMap newAM = new KeymapActionMap(newKm);
754         newAM.setParent(am.getParent());
755         am.setParent(newAM);
756         }
757     }
758     }
759
760     /**
761      * Fetches the keymap currently active in this text
762      * component.
763      *
764      * @return the keymap
765      */

766     public Keymap JavaDoc getKeymap() {
767         return keymap;
768     }
769
770     /**
771      * Adds a new keymap into the keymap hierarchy. Keymap bindings
772      * resolve from bottom up so an attribute specified in a child
773      * will override an attribute specified in the parent.
774      *
775      * @param nm the name of the keymap (must be unique within the
776      * collection of named keymaps in the document); the name may
777      * be <code>null</code> if the keymap is unnamed,
778      * but the caller is responsible for managing the reference
779      * returned as an unnamed keymap can't
780      * be fetched by name
781      * @param parent the parent keymap; this may be <code>null</code> if
782      * unspecified bindings need not be resolved in some other keymap
783      * @return the keymap
784      */

785     public static Keymap JavaDoc addKeymap(String JavaDoc nm, Keymap JavaDoc parent) {
786         Keymap JavaDoc map = new DefaultKeymap(nm, parent);
787         if (nm != null) {
788             // add a named keymap, a class of bindings
789
getKeymapTable().put(nm, map);
790         }
791         return map;
792     }
793
794     /**
795      * Removes a named keymap previously added to the document. Keymaps
796      * with <code>null</code> names may not be removed in this way.
797      *
798      * @param nm the name of the keymap to remove
799      * @return the keymap that was removed
800      */

801     public static Keymap JavaDoc removeKeymap(String JavaDoc nm) {
802         return getKeymapTable().remove(nm);
803     }
804
805     /**
806      * Fetches a named keymap previously added to the document.
807      * This does not work with <code>null</code>-named keymaps.
808      *
809      * @param nm the name of the keymap
810      * @return the keymap
811      */

812     public static Keymap JavaDoc getKeymap(String JavaDoc nm) {
813         return getKeymapTable().get(nm);
814     }
815
816     private static HashMap JavaDoc<String JavaDoc,Keymap JavaDoc> getKeymapTable() {
817         AppContext appContext = AppContext.getAppContext();
818         HashMap JavaDoc<String JavaDoc,Keymap JavaDoc> keymapTable =
819             (HashMap JavaDoc<String JavaDoc,Keymap JavaDoc>)appContext.get(KEYMAP_TABLE);
820         if (keymapTable == null) {
821             keymapTable = new HashMap JavaDoc<String JavaDoc,Keymap JavaDoc>(17);
822             appContext.put(KEYMAP_TABLE, keymapTable);
823             //initialize default keymap
824
Keymap JavaDoc binding = addKeymap(DEFAULT_KEYMAP, null);
825             binding.setDefaultAction(new
826                                      DefaultEditorKit.DefaultKeyTypedAction JavaDoc());
827         }
828         return keymapTable;
829     }
830
831     /**
832      * Binding record for creating key bindings.
833      * <p>
834      * <strong>Warning:</strong>
835      * Serialized objects of this class will not be compatible with
836      * future Swing releases. The current serialization support is
837      * appropriate for short term storage or RMI between applications running
838      * the same version of Swing. As of 1.4, support for long term storage
839      * of all JavaBeans<sup><font size="-2">TM</font></sup>
840      * has been added to the <code>java.beans</code> package.
841      * Please see {@link java.beans.XMLEncoder}.
842      */

843     public static class KeyBinding {
844         
845         /**
846          * The key.
847          */

848         public KeyStroke key;
849
850         /**
851          * The name of the action for the key.
852          */

853         public String JavaDoc actionName;
854
855         /**
856          * Creates a new key binding.
857          *
858          * @param key the key
859          * @param actionName the name of the action for the key
860          */

861         public KeyBinding(KeyStroke key, String JavaDoc actionName) {
862             this.key = key;
863             this.actionName = actionName;
864         }
865     }
866
867     /**
868      * <p>
869      * Loads a keymap with a bunch of
870      * bindings. This can be used to take a static table of
871      * definitions and load them into some keymap. The following
872      * example illustrates an example of binding some keys to
873      * the cut, copy, and paste actions associated with a
874      * JTextComponent. A code fragment to accomplish
875      * this might look as follows:
876      * <pre><code>
877      *
878      * static final JTextComponent.KeyBinding[] defaultBindings = {
879      * new JTextComponent.KeyBinding(
880      * KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK),
881      * DefaultEditorKit.copyAction),
882      * new JTextComponent.KeyBinding(
883      * KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK),
884      * DefaultEditorKit.pasteAction),
885      * new JTextComponent.KeyBinding(
886      * KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK),
887      * DefaultEditorKit.cutAction),
888      * };
889      *
890      * JTextComponent c = new JTextPane();
891      * Keymap k = c.getKeymap();
892      * JTextComponent.loadKeymap(k, defaultBindings, c.getActions());
893      *
894      * </code></pre>
895      * The sets of bindings and actions may be empty but must be
896      * non-<code>null</code>.
897      *
898      * @param map the keymap
899      * @param bindings the bindings
900      * @param actions the set of actions
901      */

902     public static void loadKeymap(Keymap JavaDoc map, KeyBinding[] bindings, Action JavaDoc[] actions) {
903         Hashtable JavaDoc h = new Hashtable JavaDoc();
904         for (int i = 0; i < actions.length; i++) {
905             Action JavaDoc a = actions[i];
906             String JavaDoc value = (String JavaDoc)a.getValue(Action.NAME);
907             h.put((value!=null ? value:""), a);
908         }
909         for (int i = 0; i < bindings.length; i++) {
910             Action JavaDoc a = (Action JavaDoc) h.get(bindings[i].actionName);
911             if (a != null) {
912                 map.addActionForKeyStroke(bindings[i].key, a);
913             }
914         }
915     }
916
917     /**
918      * Returns true if <code>klass</code> is NOT a JTextComponent and it or
919      * one of its superclasses (stoping at JTextComponent) overrides
920      * <code>processInputMethodEvent</code>. It is assumed this will be
921      * invoked from within a <code>doPrivileged</code>, and it is also
922      * assumed <code>klass</code> extends <code>JTextComponent</code>.
923      */

924     private static Boolean JavaDoc isProcessInputMethodEventOverridden(Class JavaDoc klass) {
925         if (klass == JTextComponent JavaDoc.class) {
926             return Boolean.FALSE;
927         }
928         Boolean JavaDoc retValue = (Boolean JavaDoc)overrideMap.get(klass.getName());
929
930         if (retValue != null) {
931             return retValue;
932         }
933         Boolean JavaDoc sOverriden = isProcessInputMethodEventOverridden(
934                                        klass.getSuperclass());
935
936         if (sOverriden.booleanValue()) {
937             // If our superclass has overriden it, then by definition klass
938
// overrides it.
939
overrideMap.put(klass.getName(), sOverriden);
940             return sOverriden;
941         }
942         // klass's superclass didn't override it, check for an override in
943
// klass.
944
try {
945             Class JavaDoc[] classes = new Class JavaDoc[1];
946             classes[0] = InputMethodEvent.class;
947
948             Method JavaDoc m = klass.getDeclaredMethod("processInputMethodEvent",
949                                                classes);
950             retValue = Boolean.TRUE;
951         } catch (NoSuchMethodException JavaDoc nsme) {
952             retValue = Boolean.FALSE;
953         }
954         overrideMap.put(klass.getName(), retValue);
955         return retValue;
956     }
957     
958     /**
959      * Fetches the current color used to render the
960      * caret.
961      *
962      * @return the color
963      */

964     public Color getCaretColor() {
965         return caretColor;
966     }
967
968     /**
969      * Sets the current color used to render the caret.
970      * Setting to <code>null</code> effectively restores the default color.
971      * Setting the color results in a PropertyChange event ("caretColor")
972      * being fired.
973      *
974      * @param c the color
975      * @see #getCaretColor
976      * @beaninfo
977      * description: the color used to render the caret
978      * bound: true
979      * preferred: true
980      */

981     public void setCaretColor(Color c) {
982         Color old = caretColor;
983         caretColor = c;
984         firePropertyChange("caretColor", old, caretColor);
985     }
986
987     /**
988      * Fetches the current color used to render the
989      * selection.
990      *
991      * @return the color
992      */

993     public Color getSelectionColor() {
994         return selectionColor;
995     }
996
997     /**
998      * Sets the current color used to render the selection.
999      * Setting the color to <code>null</code> is the same as setting
1000     * <code>Color.white</code>. Setting the color results in a
1001     * PropertyChange event ("selectionColor").
1002     *
1003     * @param c the color
1004     * @see #getSelectionColor
1005     * @beaninfo
1006     * description: color used to render selection background
1007