< prev index next >

src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java

Print this page




  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&trade;
  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&trade;
  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 


< prev index next >