30 import java.awt.datatransfer.*;
31 import java.awt.im.InputContext;
32 import java.beans.*;
33 import java.io.*;
34 import javax.swing.*;
35 import javax.swing.plaf.*;
36 import javax.swing.text.*;
37 import javax.swing.event.*;
38 import javax.swing.border.Border;
39 import javax.swing.plaf.UIResource;
40 import javax.swing.plaf.synth.SynthUI;
41 import sun.swing.DefaultLookup;
42 import sun.awt.AppContext;
43 import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag;
44
45 /**
46 * <p>
47 * Basis of a text components look-and-feel. This provides the
48 * basic editor view and controller services that may be useful
49 * when creating a look-and-feel for an extension of
50 * <code>JTextComponent</code>.
51 * <p>
52 * Most state is held in the associated <code>JTextComponent</code>
53 * as bound properties, and the UI installs default values for the
54 * various properties. This default will install something for
55 * all of the properties. Typically, a LAF implementation will
56 * do more however. At a minimum, a LAF would generally install
57 * key bindings.
58 * <p>
59 * This class also provides some concurrency support if the
60 * <code>Document</code> associated with the JTextComponent is a subclass of
61 * <code>AbstractDocument</code>. Access to the View (or View hierarchy) is
62 * serialized between any thread mutating the model and the Swing
63 * event thread (which is expected to render, do model/view coordinate
64 * translation, etc). <em>Any access to the root view should first
65 * acquire a read-lock on the AbstractDocument and release that lock
66 * in a finally block.</em>
67 * <p>
68 * An important method to define is the {@link #getPropertyPrefix} method
69 * which is used as the basis of the keys used to fetch defaults
70 * from the UIManager. The string should reflect the type of
71 * TextUI (eg. TextField, TextArea, etc) without the particular
72 * LAF part of the name (eg Metal, Motif, etc).
73 * <p>
74 * To build a view of the model, one of the following strategies
75 * can be employed.
76 * <ol>
77 * <li>
78 * One strategy is to simply redefine the
79 * ViewFactory interface in the UI. By default, this UI itself acts
80 * as the factory for View implementations. This is useful
81 * for simple factories. To do this reimplement the
82 * {@link #create} method.
83 * <li>
84 * A common strategy for creating more complex types of documents
85 * is to have the EditorKit implementation return a factory. Since
86 * the EditorKit ties all of the pieces necessary to maintain a type
87 * of document, the factory is typically an important part of that
88 * and should be produced by the EditorKit implementation.
89 * </ol>
90 * <p>
91 * <strong>Warning:</strong>
92 * Serialized objects of this class will not be compatible with
93 * future Swing releases. The current serialization support is
94 * appropriate for short term storage or RMI between applications running
95 * the same version of Swing. As of 1.4, support for long term storage
96 * of all JavaBeans™
97 * has been added to the <code>java.beans</code> package.
98 * Please see {@link java.beans.XMLEncoder}.
99 *
100 * @author Timothy Prinzing
101 * @author Shannon Hickey (drag and drop)
102 */
103 @SuppressWarnings("serial") // Same-version serialization only
104 public abstract class BasicTextUI extends TextUI implements ViewFactory {
105 private static final int DEFAULT_CARET_MARGIN = 1;
106
107 /**
108 * Creates a new UI.
109 */
110 public BasicTextUI() {
111 painted = false;
112 }
113
114 /**
115 * Creates the object to use for a caret. By default an
116 * instance of BasicCaret is created. This method
117 * can be redefined to provide something else that implements
145 */
146 protected String getKeymapName() {
147 String nm = getClass().getName();
148 int index = nm.lastIndexOf('.');
149 if (index >= 0) {
150 nm = nm.substring(index+1, nm.length());
151 }
152 return nm;
153 }
154
155 /**
156 * Creates the keymap to use for the text component, and installs
157 * any necessary bindings into it. By default, the keymap is
158 * shared between all instances of this type of TextUI. The
159 * keymap has the name defined by the getKeymapName method. If the
160 * keymap is not found, then DEFAULT_KEYMAP from JTextComponent is used.
161 * <p>
162 * The set of bindings used to create the keymap is fetched
163 * from the UIManager using a key formed by combining the
164 * {@link #getPropertyPrefix} method
165 * and the string <code>.keyBindings</code>. The type is expected
166 * to be <code>JTextComponent.KeyBinding[]</code>.
167 *
168 * @return the keymap
169 * @see #getKeymapName
170 * @see javax.swing.text.JTextComponent
171 */
172 protected Keymap createKeymap() {
173 String nm = getKeymapName();
174 Keymap map = JTextComponent.getKeymap(nm);
175 if (map == null) {
176 Keymap parent = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
177 map = JTextComponent.addKeymap(nm, parent);
178 String prefix = getPropertyPrefix();
179 Object o = DefaultLookup.get(editor, this,
180 prefix + ".keyBindings");
181 if ((o != null) && (o instanceof JTextComponent.KeyBinding[])) {
182 JTextComponent.KeyBinding[] bindings = (JTextComponent.KeyBinding[]) o;
183 JTextComponent.loadKeymap(map, bindings, getComponent().getActions());
184 }
185 }
186 return map;
560 forwardTraversalKeys);
561 LookAndFeel.installProperty(editor,
562 "focusTraversalKeysBackward",
563 backwardTraversalKeys);
564 }
565
566 }
567
568 /**
569 * As needed updates cursor for the target editor.
570 */
571 private void updateCursor() {
572 if ((! editor.isCursorSet())
573 || editor.getCursor() instanceof UIResource) {
574 Cursor cursor = (editor.isEditable()) ? textCursor : null;
575 editor.setCursor(cursor);
576 }
577 }
578
579 /**
580 * Returns the <code>TransferHandler</code> that will be installed if
581 * their isn't one installed on the <code>JTextComponent</code>.
582 */
583 TransferHandler getTransferHandler() {
584 return defaultTransferHandler;
585 }
586
587 /**
588 * Fetch an action map to use.
589 */
590 ActionMap getActionMap() {
591 String mapName = getPropertyPrefix() + ".actionMap";
592 ActionMap map = (ActionMap)UIManager.get(mapName);
593
594 if (map == null) {
595 map = createActionMap();
596 if (map != null) {
597 UIManager.getLookAndFeelDefaults().put(mapName, map);
598 }
599 }
600 ActionMap componentMap = new ActionMapUIResource();
601 componentMap.put("requestFocus", new FocusAction());
2225 int p0 = Math.min(dot, mark);
2226 int p1 = Math.max(dot, mark);
2227 if ((pos >= p0) && (pos < p1)) {
2228 return true;
2229 }
2230 }
2231 }
2232 return false;
2233 }
2234 }
2235
2236 static class TextTransferHandler extends TransferHandler implements UIResource {
2237
2238 private JTextComponent exportComp;
2239 private boolean shouldRemove;
2240 private int p0;
2241 private int p1;
2242
2243 /**
2244 * Whether or not this is a drop using
2245 * <code>DropMode.INSERT</code>.
2246 */
2247 private boolean modeBetween = false;
2248
2249 /**
2250 * Whether or not this is a drop.
2251 */
2252 private boolean isDrop = false;
2253
2254 /**
2255 * The drop action.
2256 */
2257 private int dropAction = MOVE;
2258
2259 /**
2260 * The drop bias.
2261 */
2262 private Position.Bias dropBias;
2263
2264 /**
2265 * Try to find a flavor that can be used to import a Transferable.
2434 * @param comp The component holding the data to be transfered. This
2435 * argument is provided to enable sharing of TransferHandlers by
2436 * multiple components.
2437 * @return The representation of the data to be transfered.
2438 *
2439 */
2440 protected Transferable createTransferable(JComponent comp) {
2441 exportComp = (JTextComponent)comp;
2442 shouldRemove = true;
2443 p0 = exportComp.getSelectionStart();
2444 p1 = exportComp.getSelectionEnd();
2445 return (p0 != p1) ? (new TextTransferable(exportComp, p0, p1)) : null;
2446 }
2447
2448 /**
2449 * This method is called after data has been exported. This method should remove
2450 * the data that was transfered if the action was MOVE.
2451 *
2452 * @param source The component that was the source of the data.
2453 * @param data The data that was transferred or possibly null
2454 * if the action is <code>NONE</code>.
2455 * @param action The actual action that was performed.
2456 */
2457 protected void exportDone(JComponent source, Transferable data, int action) {
2458 // only remove the text if shouldRemove has not been set to
2459 // false by importData and only if the action is a move
2460 if (shouldRemove && action == MOVE) {
2461 TextTransferable t = (TextTransferable)data;
2462 t.removeText();
2463 }
2464
2465 exportComp = null;
2466 }
2467
2468 public boolean importData(TransferSupport support) {
2469 isDrop = support.isDrop();
2470
2471 if (isDrop) {
2472 modeBetween =
2473 ((JTextComponent)support.getComponent()).getDropMode() == DropMode.INSERT;
2474
|
30 import java.awt.datatransfer.*;
31 import java.awt.im.InputContext;
32 import java.beans.*;
33 import java.io.*;
34 import javax.swing.*;
35 import javax.swing.plaf.*;
36 import javax.swing.text.*;
37 import javax.swing.event.*;
38 import javax.swing.border.Border;
39 import javax.swing.plaf.UIResource;
40 import javax.swing.plaf.synth.SynthUI;
41 import sun.swing.DefaultLookup;
42 import sun.awt.AppContext;
43 import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag;
44
45 /**
46 * <p>
47 * Basis of a text components look-and-feel. This provides the
48 * basic editor view and controller services that may be useful
49 * when creating a look-and-feel for an extension of
50 * {@code JTextComponent}.
51 * <p>
52 * Most state is held in the associated {@code JTextComponent}
53 * as bound properties, and the UI installs default values for the
54 * various properties. This default will install something for
55 * all of the properties. Typically, a LAF implementation will
56 * do more however. At a minimum, a LAF would generally install
57 * key bindings.
58 * <p>
59 * This class also provides some concurrency support if the
60 * {@code Document} associated with the JTextComponent is a subclass of
61 * {@code AbstractDocument}. Access to the View (or View hierarchy) is
62 * serialized between any thread mutating the model and the Swing
63 * event thread (which is expected to render, do model/view coordinate
64 * translation, etc). <em>Any access to the root view should first
65 * acquire a read-lock on the AbstractDocument and release that lock
66 * in a finally block.</em>
67 * <p>
68 * An important method to define is the {@link #getPropertyPrefix} method
69 * which is used as the basis of the keys used to fetch defaults
70 * from the UIManager. The string should reflect the type of
71 * TextUI (eg. TextField, TextArea, etc) without the particular
72 * LAF part of the name (eg Metal, Motif, etc).
73 * <p>
74 * To build a view of the model, one of the following strategies
75 * can be employed.
76 * <ol>
77 * <li>
78 * One strategy is to simply redefine the
79 * ViewFactory interface in the UI. By default, this UI itself acts
80 * as the factory for View implementations. This is useful
81 * for simple factories. To do this reimplement the
82 * {@link #create} method.
83 * <li>
84 * A common strategy for creating more complex types of documents
85 * is to have the EditorKit implementation return a factory. Since
86 * the EditorKit ties all of the pieces necessary to maintain a type
87 * of document, the factory is typically an important part of that
88 * and should be produced by the EditorKit implementation.
89 * </ol>
90 * <p>
91 * <strong>Warning:</strong>
92 * Serialized objects of this class will not be compatible with
93 * future Swing releases. The current serialization support is
94 * appropriate for short term storage or RMI between applications running
95 * the same version of Swing. As of 1.4, support for long term storage
96 * of all JavaBeans™
97 * has been added to the {@code java.beans} package.
98 * Please see {@link java.beans.XMLEncoder}.
99 *
100 * @author Timothy Prinzing
101 * @author Shannon Hickey (drag and drop)
102 */
103 @SuppressWarnings("serial") // Same-version serialization only
104 public abstract class BasicTextUI extends TextUI implements ViewFactory {
105 private static final int DEFAULT_CARET_MARGIN = 1;
106
107 /**
108 * Creates a new UI.
109 */
110 public BasicTextUI() {
111 painted = false;
112 }
113
114 /**
115 * Creates the object to use for a caret. By default an
116 * instance of BasicCaret is created. This method
117 * can be redefined to provide something else that implements
145 */
146 protected String getKeymapName() {
147 String nm = getClass().getName();
148 int index = nm.lastIndexOf('.');
149 if (index >= 0) {
150 nm = nm.substring(index+1, nm.length());
151 }
152 return nm;
153 }
154
155 /**
156 * Creates the keymap to use for the text component, and installs
157 * any necessary bindings into it. By default, the keymap is
158 * shared between all instances of this type of TextUI. The
159 * keymap has the name defined by the getKeymapName method. If the
160 * keymap is not found, then DEFAULT_KEYMAP from JTextComponent is used.
161 * <p>
162 * The set of bindings used to create the keymap is fetched
163 * from the UIManager using a key formed by combining the
164 * {@link #getPropertyPrefix} method
165 * and the string {@code .keyBindings}. The type is expected
166 * to be {@code JTextComponent.KeyBinding[]}.
167 *
168 * @return the keymap
169 * @see #getKeymapName
170 * @see javax.swing.text.JTextComponent
171 */
172 protected Keymap createKeymap() {
173 String nm = getKeymapName();
174 Keymap map = JTextComponent.getKeymap(nm);
175 if (map == null) {
176 Keymap parent = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
177 map = JTextComponent.addKeymap(nm, parent);
178 String prefix = getPropertyPrefix();
179 Object o = DefaultLookup.get(editor, this,
180 prefix + ".keyBindings");
181 if ((o != null) && (o instanceof JTextComponent.KeyBinding[])) {
182 JTextComponent.KeyBinding[] bindings = (JTextComponent.KeyBinding[]) o;
183 JTextComponent.loadKeymap(map, bindings, getComponent().getActions());
184 }
185 }
186 return map;
560 forwardTraversalKeys);
561 LookAndFeel.installProperty(editor,
562 "focusTraversalKeysBackward",
563 backwardTraversalKeys);
564 }
565
566 }
567
568 /**
569 * As needed updates cursor for the target editor.
570 */
571 private void updateCursor() {
572 if ((! editor.isCursorSet())
573 || editor.getCursor() instanceof UIResource) {
574 Cursor cursor = (editor.isEditable()) ? textCursor : null;
575 editor.setCursor(cursor);
576 }
577 }
578
579 /**
580 * Returns the {@code TransferHandler} that will be installed if
581 * their isn't one installed on the {@code JTextComponent}.
582 */
583 TransferHandler getTransferHandler() {
584 return defaultTransferHandler;
585 }
586
587 /**
588 * Fetch an action map to use.
589 */
590 ActionMap getActionMap() {
591 String mapName = getPropertyPrefix() + ".actionMap";
592 ActionMap map = (ActionMap)UIManager.get(mapName);
593
594 if (map == null) {
595 map = createActionMap();
596 if (map != null) {
597 UIManager.getLookAndFeelDefaults().put(mapName, map);
598 }
599 }
600 ActionMap componentMap = new ActionMapUIResource();
601 componentMap.put("requestFocus", new FocusAction());
2225 int p0 = Math.min(dot, mark);
2226 int p1 = Math.max(dot, mark);
2227 if ((pos >= p0) && (pos < p1)) {
2228 return true;
2229 }
2230 }
2231 }
2232 return false;
2233 }
2234 }
2235
2236 static class TextTransferHandler extends TransferHandler implements UIResource {
2237
2238 private JTextComponent exportComp;
2239 private boolean shouldRemove;
2240 private int p0;
2241 private int p1;
2242
2243 /**
2244 * Whether or not this is a drop using
2245 * {@code DropMode.INSERT}.
2246 */
2247 private boolean modeBetween = false;
2248
2249 /**
2250 * Whether or not this is a drop.
2251 */
2252 private boolean isDrop = false;
2253
2254 /**
2255 * The drop action.
2256 */
2257 private int dropAction = MOVE;
2258
2259 /**
2260 * The drop bias.
2261 */
2262 private Position.Bias dropBias;
2263
2264 /**
2265 * Try to find a flavor that can be used to import a Transferable.
2434 * @param comp The component holding the data to be transfered. This
2435 * argument is provided to enable sharing of TransferHandlers by
2436 * multiple components.
2437 * @return The representation of the data to be transfered.
2438 *
2439 */
2440 protected Transferable createTransferable(JComponent comp) {
2441 exportComp = (JTextComponent)comp;
2442 shouldRemove = true;
2443 p0 = exportComp.getSelectionStart();
2444 p1 = exportComp.getSelectionEnd();
2445 return (p0 != p1) ? (new TextTransferable(exportComp, p0, p1)) : null;
2446 }
2447
2448 /**
2449 * This method is called after data has been exported. This method should remove
2450 * the data that was transfered if the action was MOVE.
2451 *
2452 * @param source The component that was the source of the data.
2453 * @param data The data that was transferred or possibly null
2454 * if the action is {@code NONE}.
2455 * @param action The actual action that was performed.
2456 */
2457 protected void exportDone(JComponent source, Transferable data, int action) {
2458 // only remove the text if shouldRemove has not been set to
2459 // false by importData and only if the action is a move
2460 if (shouldRemove && action == MOVE) {
2461 TextTransferable t = (TextTransferable)data;
2462 t.removeText();
2463 }
2464
2465 exportComp = null;
2466 }
2467
2468 public boolean importData(TransferSupport support) {
2469 isDrop = support.isDrop();
2470
2471 if (isDrop) {
2472 modeBetween =
2473 ((JTextComponent)support.getComponent()).getDropMode() == DropMode.INSERT;
2474
|