FileDocCategorySizeDatePackage
BasicTextUI.javaAPI DocJava SE 6 API91700Tue Jun 10 00:26:48 BST 2008javax.swing.plaf.basic

BasicTextUI

public abstract class BasicTextUI extends TextUI implements ViewFactory

Basis of a text components look-and-feel. This provides the basic editor view and controller services that may be useful when creating a look-and-feel for an extension of JTextComponent.

Most state is held in the associated JTextComponent as bound properties, and the UI installs default values for the various properties. This default will install something for all of the properties. Typically, a LAF implementation will do more however. At a minimum, a LAF would generally install key bindings.

This class also provides some concurrency support if the Document associated with the JTextComponent is a subclass of AbstractDocument. Access to the View (or View hierarchy) is serialized between any thread mutating the model and the Swing event thread (which is expected to render, do model/view coordinate translation, etc). Any access to the root view should first acquire a read-lock on the AbstractDocument and release that lock in a finally block.

An important method to define is the {@link #getPropertyPrefix} method which is used as the basis of the keys used to fetch defaults from the UIManager. The string should reflect the type of TextUI (eg. TextField, TextArea, etc) without the particular LAF part of the name (eg Metal, Motif, etc).

To build a view of the model, one of the following strategies can be employed.

  1. One strategy is to simply redefine the ViewFactory interface in the UI. By default, this UI itself acts as the factory for View implementations. This is useful for simple factories. To do this reimplement the {@link #create} method.
  2. A common strategy for creating more complex types of documents is to have the EditorKit implementation return a factory. Since the EditorKit ties all of the pieces necessary to maintain a type of document, the factory is typically an important part of that and should be produced by the EditorKit implementation.

Warning: Serialized objects of this class will not be compatible with future Swing releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Swing. As of 1.4, support for long term storage of all JavaBeansTM has been added to the java.beans package. Please see {@link java.beans.XMLEncoder}.

author
Timothy Prinzing
author
Shannon Hickey (drag and drop)
version
1.120 08/25/06

Fields Summary
private static BasicCursor
textCursor
private static final EditorKit
defaultKit
transient JTextComponent
editor
transient boolean
painted
transient RootView
rootView
transient UpdateHandler
updateHandler
private static final TransferHandler
defaultTransferHandler
private final DragListener
dragListener
private static final Position$Bias[]
discardBias
private DefaultCaret
dropCaret
Constructors Summary
public BasicTextUI()
Creates a new UI.

        painted = false;
    
Methods Summary
public javax.swing.text.Viewcreate(javax.swing.text.Element elem)
Creates a view for an element. If a subclass wishes to directly implement the factory producing the view(s), it should reimplement this method. By default it simply returns null indicating it is unable to represent the element.

param
elem the element
return
the view

        return null;
    
public javax.swing.text.Viewcreate(javax.swing.text.Element elem, int p0, int p1)
Creates a view for an element. If a subclass wishes to directly implement the factory producing the view(s), it should reimplement this method. By default it simply returns null indicating it is unable to represent the part of the element.

param
elem the element
param
p0 the starting offset >= 0
param
p1 the ending offset >= p0
return
the view

        return null;
    
javax.swing.ActionMapcreateActionMap()
Create a default action map. This is basically the set of actions found exported by the component.

	ActionMap map = new ActionMapUIResource();
	Action[] actions = editor.getActions();
	//System.out.println("building map for UI: " + getPropertyPrefix());
	int n = actions.length;
	for (int i = 0; i < n; i++) {
	    Action a = actions[i];
	    map.put(a.getValue(Action.NAME), a);
	    //System.out.println("  " + a.getValue(Action.NAME));
	}
        map.put(TransferHandler.getCutAction().getValue(Action.NAME),
                TransferHandler.getCutAction());
        map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
                TransferHandler.getCopyAction());
        map.put(TransferHandler.getPasteAction().getValue(Action.NAME),
                TransferHandler.getPasteAction());
	return map;
    
protected javax.swing.text.CaretcreateCaret()
Creates the object to use for a caret. By default an instance of BasicCaret is created. This method can be redefined to provide something else that implements the InputPosition interface or a subclass of JCaret.

return
the caret object

        return new BasicCaret();
    
protected javax.swing.text.HighlightercreateHighlighter()
Creates the object to use for adding highlights. By default an instance of BasicHighlighter is created. This method can be redefined to provide something else that implements the Highlighter interface or a subclass of DefaultHighlighter.

return
the highlighter

        return new BasicHighlighter();
    
protected javax.swing.text.KeymapcreateKeymap()
Creates the keymap to use for the text component, and installs any necessary bindings into it. By default, the keymap is shared between all instances of this type of TextUI. The keymap has the name defined by the getKeymapName method. If the keymap is not found, then DEFAULT_KEYMAP from JTextComponent is used.

The set of bindings used to create the keymap is fetched from the UIManager using a key formed by combining the {@link #getPropertyPrefix} method and the string .keyBindings. The type is expected to be JTextComponent.KeyBinding[].

return
the keymap
see
#getKeymapName
see
javax.swing.text.JTextComponent

	String nm = getKeymapName();
	Keymap map = JTextComponent.getKeymap(nm);
	if (map == null) {
	    Keymap parent = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
	    map = JTextComponent.addKeymap(nm, parent);
	    String prefix = getPropertyPrefix();
	    Object o = DefaultLookup.get(editor, this,
                prefix + ".keyBindings");
	    if ((o != null) && (o instanceof JTextComponent.KeyBinding[])) {
		JTextComponent.KeyBinding[] bindings = (JTextComponent.KeyBinding[]) o;
		JTextComponent.loadKeymap(map, bindings, getComponent().getActions());
	    }
	}
	return map;
    
public voiddamageRange(javax.swing.text.JTextComponent tc, int p0, int p1)
Causes the portion of the view responsible for the given part of the model to be repainted. Does nothing if the view is not currently painted.

param
tc the text component for which this UI is installed
param
p0 the beginning of the range >= 0
param
p1 the end of the range >= p0
see
TextUI#damageRange

	damageRange(tc, p0, p1, Position.Bias.Forward, Position.Bias.Backward);
    
public voiddamageRange(javax.swing.text.JTextComponent t, int p0, int p1, javax.swing.text.Position$Bias p0Bias, javax.swing.text.Position$Bias p1Bias)
Causes the portion of the view responsible for the given part of the model to be repainted.

param
p0 the beginning of the range >= 0
param
p1 the end of the range >= p0

        if (painted) {
            Rectangle alloc = getVisibleEditorRect();
            if (alloc != null) {
                Document doc = t.getDocument();
                if (doc instanceof AbstractDocument) {
                    ((AbstractDocument)doc).readLock();
                }
                try {
                    rootView.setSize(alloc.width, alloc.height);
                    Shape toDamage = rootView.modelToView(p0, p0Bias,
                            p1, p1Bias, alloc);
                    Rectangle rect = (toDamage instanceof Rectangle) ?
                            (Rectangle)toDamage : toDamage.getBounds();
                    editor.repaint(rect.x, rect.y, rect.width, rect.height);
                } catch (BadLocationException e) {
                } finally {
                    if (doc instanceof AbstractDocument) {
                        ((AbstractDocument)doc).readUnlock();
                    }
                }
            }
        }
    
javax.swing.ActionMapgetActionMap()
Fetch an action map to use.

	String mapName = getPropertyPrefix() + ".actionMap";
	ActionMap map = (ActionMap)UIManager.get(mapName);

	if (map == null) {
	    map = createActionMap();
	    if (map != null) {
		UIManager.getLookAndFeelDefaults().put(mapName, map);
	    }
	}
        ActionMap componentMap = new ActionMapUIResource();
        componentMap.put("requestFocus", new FocusAction());
	/* 
	 * fix for bug 4515750 
	 * JTextField & non-editable JTextArea bind return key - default btn not accessible
	 *
	 * Wrap the return action so that it is only enabled when the
	 * component is editable. This allows the default button to be
	 * processed when the text component has focus and isn't editable.
	 * 
	 */
	if (getEditorKit(editor) instanceof DefaultEditorKit) {
	    if (map != null) {
		Object obj = map.get(DefaultEditorKit.insertBreakAction);
		if (obj != null  
		    && obj instanceof DefaultEditorKit.InsertBreakAction) {
		    Action action =  new TextActionWrapper((TextAction)obj);
		    componentMap.put(action.getValue(Action.NAME),action);
		}
	    }
	}
        if (map != null) {
            componentMap.setParent(map);
        }
	return componentMap;
    
protected final javax.swing.text.JTextComponentgetComponent()
Fetches the text component associated with this UI implementation. This will be null until the ui has been installed.

return
the editor component

        return editor;
    
private static javax.swing.plaf.basic.BasicTextUI$DragListenergetDragListener()

        synchronized(DragListener.class) {
            DragListener listener =
                (DragListener)AppContext.getAppContext().
                    get(DragListener.class);

            if (listener == null) {
                listener = new DragListener();
                AppContext.getAppContext().put(DragListener.class, listener);
            }

            return listener;
        }
    
public javax.swing.text.EditorKitgetEditorKit(javax.swing.text.JTextComponent tc)
Fetches the EditorKit for the UI.

param
tc the text component for which this UI is installed
return
the editor capabilities
see
TextUI#getEditorKit

        return defaultKit;
    
javax.swing.InputMapgetInputMap()
Get the InputMap to use for the UI.

	InputMap map = new InputMapUIResource();

	InputMap shared = 
	    (InputMap)DefaultLookup.get(editor, this,
            getPropertyPrefix() + ".focusInputMap");
	if (shared != null) {
	    map.setParent(shared);
	}
	return map;
    
protected java.lang.StringgetKeymapName()
Fetches the name of the keymap that will be installed/used by default for this UI. This is implemented to create a name based upon the classname. The name is the the name of the class with the package prefix removed.

return
the name

	String nm = getClass().getName();
	int index = nm.lastIndexOf('.");
	if (index >= 0) {
	    nm = nm.substring(index+1, nm.length());
	}
	return nm;
    
public java.awt.DimensiongetMaximumSize(javax.swing.JComponent c)
Gets the maximum size for the editor component.

param
c the editor component
return
the size

	Document doc = editor.getDocument();
        Insets i = c.getInsets();
	Dimension d = new Dimension();
	if (doc instanceof AbstractDocument) {
	    ((AbstractDocument)doc).readLock();
	}
	try {
	    d.width = (int) Math.min((long) rootView.getMaximumSpan(View.X_AXIS) + 
				     (long) i.left + (long) i.right, Integer.MAX_VALUE);
	    d.height = (int) Math.min((long) rootView.getMaximumSpan(View.Y_AXIS) + 
				      (long) i.top + (long) i.bottom, Integer.MAX_VALUE);
	} finally {
	    if (doc instanceof AbstractDocument) {
		((AbstractDocument)doc).readUnlock();
	    }
	}
        return d;
    
public java.awt.DimensiongetMinimumSize(javax.swing.JComponent c)
Gets the minimum size for the editor component.

param
c the editor component
return
the size

	Document doc = editor.getDocument();
        Insets i = c.getInsets();
	Dimension d = new Dimension();
	if (doc instanceof AbstractDocument) {
	    ((AbstractDocument)doc).readLock();
	}
	try {
	    d.width = (int) rootView.getMinimumSpan(View.X_AXIS) + i.left + i.right;
	    d.height = (int)  rootView.getMinimumSpan(View.Y_AXIS) + i.top + i.bottom;
	} finally {
	    if (doc instanceof AbstractDocument) {
		((AbstractDocument)doc).readUnlock();
	    }
	}
        return d;
    
public intgetNextVisualPositionFrom(javax.swing.text.JTextComponent t, int pos, javax.swing.text.Position$Bias b, int direction, javax.swing.text.Position$Bias[] biasRet)
{@inheritDoc}

	Document doc = editor.getDocument();
	if (doc instanceof AbstractDocument) {
	    ((AbstractDocument)doc).readLock();
	}
	try {
	    if (painted) {
		Rectangle alloc = getVisibleEditorRect();
                if (alloc != null) {
                    rootView.setSize(alloc.width, alloc.height);
                }
		return rootView.getNextVisualPositionFrom(pos, b, alloc, direction,
							  biasRet);
	    }
	} finally {
	    if (doc instanceof AbstractDocument) {
		((AbstractDocument)doc).readUnlock();
	    }
	}
	return -1;
    
public java.awt.DimensiongetPreferredSize(javax.swing.JComponent c)
Gets the preferred size for the editor component. If the component has been given a size prior to receiving this request, it will set the size of the view hierarchy to reflect the size of the component before requesting the preferred size of the view hierarchy. This allows formatted views to format to the current component size before answering the request. Other views don't care about currently formatted size and give the same answer either way.

param
c the editor component
return
the size

	Document doc = editor.getDocument();
	Insets i = c.getInsets();
	Dimension d = c.getSize();

	if (doc instanceof AbstractDocument) {
	    ((AbstractDocument)doc).readLock();
	}
	try {
	    if ((d.width > (i.left + i.right)) && (d.height > (i.top + i.bottom))) {
		rootView.setSize(d.width - i.left - i.right, d.height - i.top - i.bottom);
	    }
            else if (d.width == 0 && d.height == 0) {
                // Probably haven't been layed out yet, force some sort of
                // initial sizing.
                rootView.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE);
            }
	    d.width = (int) Math.min((long) rootView.getPreferredSpan(View.X_AXIS) +
				     (long) i.left + (long) i.right, Integer.MAX_VALUE);
	    d.height = (int) Math.min((long) rootView.getPreferredSpan(View.Y_AXIS) +
				      (long) i.top + (long) i.bottom, Integer.MAX_VALUE);
	} finally {
	    if (doc instanceof AbstractDocument) {
		((AbstractDocument)doc).readUnlock();
	    }
	}
	return d;
    
protected abstract java.lang.StringgetPropertyPrefix()
Gets the name used as a key to look up properties through the UIManager. This is used as a prefix to all the standard text properties.

return
the name

public javax.swing.text.ViewgetRootView(javax.swing.text.JTextComponent tc)
Fetches a View with the allocation of the associated text component (i.e. the root of the hierarchy) that can be traversed to determine how the model is being represented spatially.

NOTE:The View hierarchy can be traversed from the root view, and other things can be done as well. Things done in this way cannot be protected like simple method calls through the TextUI. Therefore, proper operation in the presence of concurrency must be arranged by any logic that calls this method!

param
tc the text component for which this UI is installed
return
the view
see
TextUI#getRootView

        return rootView;
    
public java.lang.StringgetToolTipText(javax.swing.text.JTextComponent t, java.awt.Point pt)
Returns the string to be used as the tooltip at the passed in location. This forwards the method onto the root View.

see
javax.swing.text.JTextComponent#getToolTipText
see
javax.swing.text.View#getToolTipText
since
1.4

        if (!painted) {
            return null;
        }
        Document doc = editor.getDocument();
        String tt = null;
        Rectangle alloc = getVisibleEditorRect();

        if (alloc != null) {
            if (doc instanceof AbstractDocument) {
                ((AbstractDocument)doc).readLock();
            }
            try {
                tt = rootView.getToolTipText(pt.x, pt.y, alloc);
            } finally {
                if (doc instanceof AbstractDocument) {
                    ((AbstractDocument)doc).readUnlock();
                }
            }
        }
        return tt;
    
javax.swing.TransferHandlergetTransferHandler()
Returns the TransferHandler that will be installed if their isn't one installed on the JTextComponent.

        return defaultTransferHandler;
    
protected java.awt.RectanglegetVisibleEditorRect()
Gets the allocation to give the root View. Due to an unfortunate set of historical events this method is inappropriately named. The Rectangle returned has nothing to do with visibility. The component must have a non-zero positive size for this translation to be computed.

return
the bounding box for the root view

	Rectangle alloc = editor.getBounds();
	if ((alloc.width > 0) && (alloc.height > 0)) {
	    alloc.x = alloc.y = 0;
	    Insets insets = editor.getInsets();
	    alloc.x += insets.left;
	    alloc.y += insets.top;
	    alloc.width -= insets.left + insets.right;
	    alloc.height -= insets.top + insets.bottom;
	    return alloc;
	}
	return null;
    
protected voidinstallDefaults()
Initializes component properties, e.g. font, foreground, background, caret color, selection color, selected text color, disabled text color, and border color. The font, foreground, and background properties are only set if their current value is either null or a UIResource, other properties are set if the current value is null.

see
#uninstallDefaults
see
#installUI

        String prefix = getPropertyPrefix();
        Font f = editor.getFont();
        if ((f == null) || (f instanceof UIResource)) {
            editor.setFont(UIManager.getFont(prefix + ".font"));
        }

        Color bg = editor.getBackground();
        if ((bg == null) || (bg instanceof UIResource)) {
            editor.setBackground(UIManager.getColor(prefix + ".background"));
        }
        
        Color fg = editor.getForeground();
        if ((fg == null) || (fg instanceof UIResource)) {
            editor.setForeground(UIManager.getColor(prefix + ".foreground"));
        }

        Color color = editor.getCaretColor();
        if ((color == null) || (color instanceof UIResource)) {
            editor.setCaretColor(UIManager.getColor(prefix + ".caretForeground"));
        }

        Color s = editor.getSelectionColor();
        if ((s == null) || (s instanceof UIResource)) {
            editor.setSelectionColor(UIManager.getColor(prefix + ".selectionBackground"));
        }

        Color sfg = editor.getSelectedTextColor();
        if ((sfg == null) || (sfg instanceof UIResource)) {
            editor.setSelectedTextColor(UIManager.getColor(prefix + ".selectionForeground"));
        }

        Color dfg = editor.getDisabledTextColor();
        if ((dfg == null) || (dfg instanceof UIResource)) {
            editor.setDisabledTextColor(UIManager.getColor(prefix + ".inactiveForeground"));
        }

        Border b = editor.getBorder();
        if ((b == null) || (b instanceof UIResource)) {
            editor.setBorder(UIManager.getBorder(prefix + ".border"));
        }

        Insets margin = editor.getMargin();
        if (margin == null || margin instanceof UIResource) {
            editor.setMargin(UIManager.getInsets(prefix + ".margin"));
        }

        updateCursor();
    
private voidinstallDefaults2()

	editor.addMouseListener(dragListener);
	editor.addMouseMotionListener(dragListener);
	
        String prefix = getPropertyPrefix();

        Caret caret = editor.getCaret();
        if (caret == null || caret instanceof UIResource) {
            caret = createCaret();
            editor.setCaret(caret);
        
            int rate = DefaultLookup.getInt(getComponent(), this, prefix + ".caretBlinkRate", 500);
            caret.setBlinkRate(rate);
        }

        Highlighter highlighter = editor.getHighlighter();
        if (highlighter == null || highlighter instanceof UIResource) {
            editor.setHighlighter(createHighlighter());
        }

	TransferHandler th = editor.getTransferHandler();
	if (th == null || th instanceof UIResource) {
	    editor.setTransferHandler(getTransferHandler());
	}
    
protected voidinstallKeyboardActions()

	// backward compatibility support... keymaps for the UI
	// are now installed in the more friendly input map.
        editor.setKeymap(createKeymap()); 

        InputMap km = getInputMap();
	if (km != null) {
	    SwingUtilities.replaceUIInputMap(editor, JComponent.WHEN_FOCUSED,
					     km);
	}
	
	ActionMap map = getActionMap();
	if (map != null) {
	    SwingUtilities.replaceUIActionMap(editor, map);
	}

	updateFocusAcceleratorBinding(false);
    
protected voidinstallListeners()
Installs listeners for the UI.

    
public voidinstallUI(javax.swing.JComponent c)
Installs the UI for a component. This does the following things.
  1. Set the associated component to opaque (can be changed easily by a subclass or on JTextComponent directly), which is the most common case. This will cause the component's background color to be painted.
  2. Install the default caret and highlighter into the associated component.
  3. Attach to the editor and model. If there is no model, a default one is created.
  4. create the view factory and the view hierarchy used to represent the model.

param
c the editor component
see
ComponentUI#installUI

        if (c instanceof JTextComponent) {
            editor = (JTextComponent) c;

            // install defaults
            installDefaults();
            installDefaults2();

            // common case is background painted... this can
            // easily be changed by subclasses or from outside
            // of the component.
            LookAndFeel.installProperty(editor, "opaque", Boolean.TRUE);
            LookAndFeel.installProperty(editor, "autoscrolls", Boolean.TRUE);

            // attach to the model and editor
            editor.addPropertyChangeListener(updateHandler);
            Document doc = editor.getDocument();
            if (doc == null) {
                // no model, create a default one.  This will
                // fire a notification to the updateHandler 
                // which takes care of the rest. 
                editor.setDocument(getEditorKit(editor).createDefaultDocument());
            } else {
                doc.addDocumentListener(updateHandler);
                modelChanged();
            }

            // install keymap
            installListeners();
            installKeyboardActions();

	    LayoutManager oldLayout = editor.getLayout();
	    if ((oldLayout == null) || (oldLayout instanceof UIResource)) {
		// by default, use default LayoutManger implementation that
		// will position the components associated with a View object.
		editor.setLayout(updateHandler);
	    }

            updateBackground(editor);
        } else {
            throw new Error("TextUI needs JTextComponent");
        }
    
protected voidmodelChanged()
Flags model changes. This is called whenever the model has changed. It is implemented to rebuild the view hierarchy to represent the default root element of the associated model.

        // create a view hierarchy
        ViewFactory f = rootView.getViewFactory();
        Document doc = editor.getDocument();
        Element elem = doc.getDefaultRootElement();
        setView(f.create(elem));
    
public java.awt.RectanglemodelToView(javax.swing.text.JTextComponent tc, int pos)
Converts the given location in the model to a place in the view coordinate system. The component must have a non-zero positive size for this translation to be computed.

param
tc the text component for which this UI is installed
param
pos the local location in the model to translate >= 0
return
the coordinates as a rectangle, null if the model is not painted
exception
BadLocationException if the given position does not represent a valid location in the associated document
see
TextUI#modelToView

	return modelToView(tc, pos, Position.Bias.Forward);
    
public java.awt.RectanglemodelToView(javax.swing.text.JTextComponent tc, int pos, javax.swing.text.Position$Bias bias)
Converts the given location in the model to a place in the view coordinate system. The component must have a non-zero positive size for this translation to be computed.

param
tc the text component for which this UI is installed
param
pos the local location in the model to translate >= 0
return
the coordinates as a rectangle, null if the model is not painted
exception
BadLocationException if the given position does not represent a valid location in the associated document
see
TextUI#modelToView

	Document doc = editor.getDocument();
	if (doc instanceof AbstractDocument) {
	    ((AbstractDocument)doc).readLock();
	}
	try {
	    Rectangle alloc = getVisibleEditorRect();
	    if (alloc != null) {
		rootView.setSize(alloc.width, alloc.height);
		Shape s = rootView.modelToView(pos, alloc, bias);
		if (s != null) {
		  return s.getBounds();
		}
	    }
	} finally {
	    if (doc instanceof AbstractDocument) {
		((AbstractDocument)doc).readUnlock();
	    }
	}
	return null;
    
public final voidpaint(java.awt.Graphics g, javax.swing.JComponent c)
Paints the interface. This is routed to the paintSafely method under the guarantee that the model won't change from the view of this thread while it's rendering (if the associated model is derived from AbstractDocument). This enables the model to potentially be updated asynchronously.

param
g the graphics context
param
c the editor component

	if ((rootView.getViewCount() > 0) && (rootView.getView(0) != null)) {
	    Document doc = editor.getDocument();
	    if (doc instanceof AbstractDocument) {
		((AbstractDocument)doc).readLock();
	    }
	    try {
		paintSafely(g);
	    } finally {
		if (doc instanceof AbstractDocument) {
		    ((AbstractDocument)doc).readUnlock();
		}
	    }
	}
    
protected voidpaintBackground(java.awt.Graphics g)
Paints a background for the view. This will only be called if isOpaque() on the associated component is true. The default is to paint the background color of the component.

param
g the graphics context

        g.setColor(editor.getBackground());
        g.fillRect(0, 0, editor.getWidth(), editor.getHeight());
    
protected voidpaintSafely(java.awt.Graphics g)
Paints the interface safely with a guarantee that the model won't change from the view of this thread. This does the following things, rendering from back to front.
  1. If the component is marked as opaque, the background is painted in the current background color of the component.
  2. The highlights (if any) are painted.
  3. The view hierarchy is painted.
  4. The caret is painted.

param
g the graphics context

	painted = true;
	Highlighter highlighter = editor.getHighlighter();
	Caret caret = editor.getCaret();
	
	// paint the background
	if (editor.isOpaque()) {
	    paintBackground(g);
	}
	
	// paint the highlights
	if (highlighter != null) {
	    highlighter.paint(g);
	}

	// paint the view hierarchy
	Rectangle alloc = getVisibleEditorRect();
        if (alloc != null) {
            rootView.paint(g, alloc);
        }
        
	// paint the caret
	if (caret != null) {
	    caret.paint(g);
	}

        if (dropCaret != null) {
            dropCaret.paint(g);
        }
    
protected voidpropertyChange(java.beans.PropertyChangeEvent evt)
This method gets called when a bound property is changed on the associated JTextComponent. This is a hook which UI implementations may change to reflect how the UI displays bound properties of JTextComponent subclasses. This is implemented to do nothing (i.e. the response to properties in JTextComponent itself are handled prior to calling this method). This implementation updates the background of the text component if the editable and/or enabled state changes.

param
evt the property change event

        if (evt.getPropertyName().equals("editable") ||
                evt.getPropertyName().equals("enabled")) {
            
            updateBackground((JTextComponent)evt.getSource());
        }
    
protected final voidsetView(javax.swing.text.View v)
Sets the current root of the view hierarchy and calls invalidate(). If there were any child components, they will be removed (i.e. there are assumed to have come from components embedded in views).

param
v the root view

        rootView.setView(v);
        painted = false;
        editor.revalidate();
        editor.repaint();
    
protected voiduninstallDefaults()
Sets the component properties that haven't been explicitly overridden to null. A property is considered overridden if its current value is not a UIResource.

see
#installDefaults
see
#uninstallUI

	editor.removeMouseListener(dragListener);
	editor.removeMouseMotionListener(dragListener);

        if (editor.getCaretColor() instanceof UIResource) {
            editor.setCaretColor(null);
        }
                                                                                         
        if (editor.getSelectionColor() instanceof UIResource) {
            editor.setSelectionColor(null);
        }

        if (editor.getDisabledTextColor() instanceof UIResource) {
            editor.setDisabledTextColor(null);
        }

        if (editor.getSelectedTextColor() instanceof UIResource) {
            editor.setSelectedTextColor(null);
        }

        if (editor.getBorder() instanceof UIResource) {
            editor.setBorder(null);
        }

        if (editor.getMargin() instanceof UIResource) {
            editor.setMargin(null);
        }

        if (editor.getCaret() instanceof UIResource) {
            editor.setCaret(null);
        }

        if (editor.getHighlighter() instanceof UIResource) {
            editor.setHighlighter(null);
        }

	if (editor.getTransferHandler() instanceof UIResource) {
	    editor.setTransferHandler(null);
	}

        if (editor.getCursor() instanceof UIResource) {
            editor.setCursor(null);
        }
    
protected voiduninstallKeyboardActions()

        editor.setKeymap(null);
	SwingUtilities.replaceUIInputMap(editor, JComponent.
					 WHEN_IN_FOCUSED_WINDOW, null);
	SwingUtilities.replaceUIActionMap(editor, null);
    
protected voiduninstallListeners()
Uninstalls listeners for the UI.

    
public voiduninstallUI(javax.swing.JComponent c)
Deinstalls the UI for a component. This removes the listeners, uninstalls the highlighter, removes views, and nulls out the keymap.

param
c the editor component
see
ComponentUI#uninstallUI

        // detach from the model
        editor.removePropertyChangeListener(updateHandler);
        editor.getDocument().removeDocumentListener(updateHandler);

        // view part
        painted = false;
        uninstallDefaults();
        rootView.setView(null);
        c.removeAll();
	LayoutManager lm = c.getLayout();
	if (lm instanceof UIResource) {
	    c.setLayout(null);
	}

        // controller part
        uninstallKeyboardActions();
        uninstallListeners();

        editor = null;
    
public voidupdate(java.awt.Graphics g, javax.swing.JComponent c)
Superclass paints background in an uncontrollable way (i.e. one might want an image tiled into the background). To prevent this from happening twice, this method is reimplemented to simply paint.

NOTE: Superclass is also not thread-safe in it's rendering of the background, although that's not an issue with the default rendering.

	paint(g, c);
    
private voidupdateBackground(javax.swing.text.JTextComponent c)
Updates the background of the text component based on whether the text component is editable and/or enabled.

param
c the JTextComponent that needs its background color updated

        // This is a temporary workaround.
        // This code does not correctly deal with Synth (Synth doesn't use
        // properties like this), nor does it deal with the situation where
        // the developer grabs the color from a JLabel and sets it as
        // the background for a JTextArea in all look and feels. The problem
        // scenario results if the Color obtained for the Label and TextArea
        // is ==, which is the case for the windows look and feel.
        // Until an appropriate solution is found, the code is being
        // reverted to what it was before the original fix.
        if (this instanceof sun.swing.plaf.synth.SynthUI ||
                (c instanceof JTextArea)) {
            return;
        }
        Color background = c.getBackground();
        if (background instanceof UIResource) {
            String prefix = getPropertyPrefix();

            Color disabledBG =
                DefaultLookup.getColor(c, this, prefix + ".disabledBackground", null);
            Color inactiveBG =
                DefaultLookup.getColor(c, this, prefix + ".inactiveBackground", null);
            Color bg =
                DefaultLookup.getColor(c, this, prefix + ".background", null);

            /* In an ideal situation, the following check would not be necessary
             * and we would replace the color any time the previous color was a
             * UIResouce. However, it turns out that there is existing code that
             * uses the following inadvisable pattern to turn a text area into
             * what appears to be a multi-line label:
             *
             * JLabel label = new JLabel();
             * JTextArea area = new JTextArea();
             * area.setBackground(label.getBackground());
             * area.setEditable(false);
             *
             * JLabel's default background is a UIResource. As such, just
             * checking for UIResource would have us always changing the
             * background away from what the developer wanted.
             *
             * Therefore, for JTextArea/JEditorPane, we'll additionally check
             * that the color we're about to replace matches one that was
             * installed by us from the UIDefaults.
             */
            if ((c instanceof JTextArea || c instanceof JEditorPane)
                    && background != disabledBG
                    && background != inactiveBG
                    && background != bg) {

                return;
            }

            Color newColor = null;
            if (!c.isEnabled()) {
                newColor = disabledBG;
            }
            if (newColor == null && !c.isEditable()) {
                newColor = inactiveBG;
            }
            if (newColor == null) {
                newColor = bg;
            }
            if (newColor != null && newColor != background) {
                c.setBackground(newColor);
            }
        }
    
private voidupdateCursor()
As needed updates cursor for the target editor.

        if ((! editor.isCursorSet())
               || editor.getCursor() instanceof UIResource) {
            Cursor cursor = (editor.isEditable()) ? textCursor : null;
            editor.setCursor(cursor);
        }
    
voidupdateFocusAcceleratorBinding(boolean changed)
Invoked when the focus accelerator changes, this will update the key bindings as necessary.

	char accelerator = editor.getFocusAccelerator();

	if (changed || accelerator != '\0") {
	    InputMap km = SwingUtilities.getUIInputMap
		        (editor, JComponent.WHEN_IN_FOCUSED_WINDOW);

	    if (km == null && accelerator != '\0") {
		km = new ComponentInputMapUIResource(editor);
		SwingUtilities.replaceUIInputMap(editor, JComponent.
						 WHEN_IN_FOCUSED_WINDOW, km);
		ActionMap am = getActionMap();
		SwingUtilities.replaceUIActionMap(editor, am);
	    }
	    if (km != null) {
		km.clear();
		if (accelerator != '\0") {
		    km.put(KeyStroke.getKeyStroke(accelerator,
						  ActionEvent.ALT_MASK),
			   "requestFocus");
		}
	    }
	}
    
voidupdateFocusTraversalKeys()
Invoked when editable property is changed. removing 'TAB' and 'SHIFT-TAB' from traversalKeysSet in case editor is editable adding 'TAB' and 'SHIFT-TAB' to traversalKeysSet in case editor is non editable

	/*
	 * Fix for 4514331 Non-editable JTextArea and similar 
	 * should allow Tab to keyboard - accessibility 
	 */
	EditorKit editorKit = getEditorKit(editor);
	if ( editorKit != null
	     && editorKit instanceof DefaultEditorKit) {
	    Set storedForwardTraversalKeys = editor.
		getFocusTraversalKeys(KeyboardFocusManager.
				      FORWARD_TRAVERSAL_KEYS);
	    Set storedBackwardTraversalKeys = editor.
		getFocusTraversalKeys(KeyboardFocusManager.
				      BACKWARD_TRAVERSAL_KEYS);
	    Set forwardTraversalKeys = 
		new HashSet(storedForwardTraversalKeys);
	    Set backwardTraversalKeys = 
		new HashSet(storedBackwardTraversalKeys);
	    if (editor.isEditable()) {
		forwardTraversalKeys.
		    remove(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
		backwardTraversalKeys.
		    remove(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 
						  InputEvent.SHIFT_MASK));
	    } else {
		forwardTraversalKeys.add(KeyStroke.
					 getKeyStroke(KeyEvent.VK_TAB, 0));
		backwardTraversalKeys.
		    add(KeyStroke.
			getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK));
	    }
            LookAndFeel.installProperty(editor,
                                        "focusTraversalKeysForward",
					 forwardTraversalKeys);
            LookAndFeel.installProperty(editor,
                                        "focusTraversalKeysBackward",
					 backwardTraversalKeys);
	}

    
public intviewToModel(javax.swing.text.JTextComponent tc, java.awt.Point pt)
Converts the given place in the view coordinate system to the nearest representative location in the model. The component must have a non-zero positive size for this translation to be computed.

param
tc the text component for which this UI is installed
param
pt the location in the view to translate. This should be in the same coordinate system as the mouse events.
return
the offset from the start of the document >= 0, -1 if not painted
see
TextUI#viewToModel

	return viewToModel(tc, pt, discardBias);
    
public intviewToModel(javax.swing.text.JTextComponent tc, java.awt.Point pt, javax.swing.text.Position$Bias[] biasReturn)
Converts the given place in the view coordinate system to the nearest representative location in the model. The component must have a non-zero positive size for this translation to be computed.

param
tc the text component for which this UI is installed
param
pt the location in the view to translate. This should be in the same coordinate system as the mouse events.
return
the offset from the start of the document >= 0, -1 if the component doesn't yet have a positive size.
see
TextUI#viewToModel

	int offs = -1;
	Document doc = editor.getDocument();
	if (doc instanceof AbstractDocument) {
	    ((AbstractDocument)doc).readLock();
	}
	try {
	    Rectangle alloc = getVisibleEditorRect();
	    if (alloc != null) {
		rootView.setSize(alloc.width, alloc.height);
		offs = rootView.viewToModel(pt.x, pt.y, alloc, biasReturn);
	    }
	} finally {
	    if (doc instanceof AbstractDocument) {
		((AbstractDocument)doc).readUnlock();
	    }
	}
        return offs;