/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* <p>
* 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
* <code>JTextComponent</code>.
* <p>
* Most state is held in the associated <code>JTextComponent</code>
* 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.
* <p>
* This class also provides some concurrency support if the
* <code>Document</code> associated with the JTextComponent is a subclass of
* <code>AbstractDocument</code>. Access to the View (or View hierarchy) is
* serialized between any thread mutating the model and the Swing
* translation, etc). <em>Any access to the root view should first
* acquire a read-lock on the AbstractDocument and release that lock
* in a finally block.</em>
* <p>
* 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).
* <p>
* To build a view of the model, one of the following strategies
* can be employed.
* <ol>
* <li>
* 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.
* <li>
* 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.
* </ol>
* <p>
* <strong>Warning:</strong>
* 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 JavaBeans<sup><font size="-2">TM</font></sup>
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @author Timothy Prinzing
* @author Shannon Hickey (drag and drop)
*/
/**
* Creates a new UI.
*/
public BasicTextUI() {
painted = false;
}
/**
* 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();
}
/**
* 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();
}
/**
* 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
*/
if (index >= 0) {
}
return nm;
}
/**
* 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.
* <p>
* 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 <code>.keyBindings</code>. The type is expected
* to be <code>JTextComponent.KeyBinding[]</code>.
*
* @return the keymap
* @see #getKeymapName
* @see javax.swing.text.JTextComponent
*/
prefix + ".keyBindings");
}
}
return map;
}
/**
* 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
*
* @param evt the property change event
*/
}
}
/**
* Updates the background of the text component based on whether the
*
* @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.
return;
}
if (background instanceof UIResource) {
/* 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;
}
if (!c.isEnabled()) {
}
}
}
}
}
}
/**
* 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
*/
/**
* Initializes component properties, such as 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
*/
protected void installDefaults()
{
if ((f == null) || (f instanceof UIResource)) {
}
}
}
}
if ((s == null) || (s instanceof UIResource)) {
}
}
}
if ((b == null) || (b instanceof UIResource)) {
}
}
updateCursor();
}
private void installDefaults2() {
caret = createCaret();
}
}
}
}
/**
* Sets the component properties that have not been explicitly overridden
* to {@code null}. A property is considered overridden if its current
* value is not a {@code UIResource}.
*
* @see #installDefaults
* @see #uninstallUI
*/
protected void uninstallDefaults()
{
}
}
}
}
}
}
}
}
}
}
}
/**
* Installs listeners for the UI.
*/
protected void installListeners() {
}
/**
* Uninstalls listeners for the UI.
*/
protected void uninstallListeners() {
}
protected void installKeyboardActions() {
// backward compatibility support... keymaps for the UI
// are now installed in the more friendly input map.
km);
}
}
updateFocusAcceleratorBinding(false);
}
/**
* Get the InputMap to use for the UI.
*/
getPropertyPrefix() + ".focusInputMap");
}
return map;
}
/**
* Invoked when the focus accelerator changes, this will update the
* key bindings as necessary.
*/
}
if (accelerator != '\0') {
km.put(KeyStroke.getKeyStroke(accelerator, BasicLookAndFeel.getFocusAcceleratorKeyMask()), "requestFocus");
}
}
}
}
/**
* 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
*/
void updateFocusTraversalKeys() {
/*
* Fix for 4514331 Non-editable JTextArea and similar
* should allow Tab to keyboard - accessibility
*/
&& editorKit instanceof DefaultEditorKit) {
if (editor.isEditable()) {
} else {
}
"focusTraversalKeysForward",
"focusTraversalKeysBackward",
}
}
/**
* As needed updates cursor for the target editor.
*/
private void updateCursor() {
if ((! editor.isCursorSet())
}
}
/**
* Returns the <code>TransferHandler</code> that will be installed if
* their isn't one installed on the <code>JTextComponent</code>.
*/
return defaultTransferHandler;
}
/**
* Fetch an action map to use.
*/
map = createActionMap();
}
}
/*
* 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.
*
*/
}
}
}
}
return componentMap;
}
/**
* Create a default action map. This is basically the
* set of actions found exported by the component.
*/
//System.out.println("building map for UI: " + getPropertyPrefix());
for (int i = 0; i < n; i++) {
//System.out.println(" " + a.getValue(Action.NAME));
}
return map;
}
protected void uninstallKeyboardActions() {
}
/**
* 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
*/
}
/**
* 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;
}
/**
* 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.
*/
protected void modelChanged() {
// create a view hierarchy
}
/**
* 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
*/
painted = false;
editor.revalidate();
}
/**
* 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.
* <ol>
* <li>
* If the component is marked as opaque, the background
* is painted in the current background color of the
* component.
* <li>
* The highlights (if any) are painted.
* <li>
* The view hierarchy is painted.
* <li>
* The caret is painted.
* </ol>
*
* @param g the graphics context
*/
painted = true;
// paint the background
paintBackground(g);
}
// paint the highlights
if (highlighter != null) {
highlighter.paint(g);
}
// paint the view hierarchy
}
// paint the caret
}
}
}
// --- ComponentUI methods --------------------------------------------
/**
* Installs the UI for a component. This does the following
* things.
* <ol>
* <li>
* Sets the associated component to opaque if the opaque property
* has not already been set by the client program. This will cause the
* component's background color to be painted.
* <li>
* Installs the default caret and highlighter into the
* associated component. These properties are only set if their
* current value is either {@code null} or an instance of
* {@link UIResource}.
* <li>
* Attaches to the editor and model. If there is no
* model, a default one is created.
* <li>
* Creates the view factory and the view hierarchy used
* to represent the model.
* </ol>
*
* @param c the editor component
* @see ComponentUI#installUI
*/
if (c instanceof JTextComponent) {
editor = (JTextComponent) c;
// common case is background painted... this can
// easily be changed by subclasses or from outside
// of the component.
// install defaults
// attach to the model and editor
// no model, create a default one. This will
// fire a notification to the updateHandler
// which takes care of the rest.
} else {
modelChanged();
}
// install keymap
// by default, use default LayoutManger implementation that
// will position the components associated with a View object.
}
} else {
throw new Error("TextUI needs JTextComponent");
}
}
/**
* 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
// view part
painted = false;
c.removeAll();
if (lm instanceof UIResource) {
}
// controller part
}
/**
* 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.
* <p>
* <em>NOTE:</em> NOTE: Superclass is also not thread-safe in its
* rendering of the background, although that is not an issue with the
* default rendering.
*/
paint(g, 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 (doc instanceof AbstractDocument) {
}
try {
paintSafely(g);
} finally {
if (doc instanceof AbstractDocument) {
}
}
}
}
/**
* 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
*/
if (doc instanceof AbstractDocument) {
}
try {
}
// Probably haven't been layed out yet, force some sort of
// initial sizing.
}
} finally {
if (doc instanceof AbstractDocument) {
}
}
return d;
}
/**
* Gets the minimum size for the editor component.
*
* @param c the editor component
* @return the size
*/
if (doc instanceof AbstractDocument) {
}
try {
} finally {
if (doc instanceof AbstractDocument) {
}
}
return d;
}
/**
* Gets the maximum size for the editor component.
*
* @param c the editor component
* @return the size
*/
if (doc instanceof AbstractDocument) {
}
try {
} finally {
if (doc instanceof AbstractDocument) {
}
}
return d;
}
// ---- TextUI methods -------------------------------------------
/**
* 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
*/
return alloc;
}
return null;
}
/**
* 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
*/
}
/**
* 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
*/
public Rectangle modelToView(JTextComponent tc, int pos, Position.Bias bias) throws BadLocationException {
if (doc instanceof AbstractDocument) {
}
try {
if (s != null) {
return s.getBounds();
}
}
} finally {
if (doc instanceof AbstractDocument) {
}
}
return null;
}
/**
* 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
*/
}
/**
* 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;
if (doc instanceof AbstractDocument) {
}
try {
}
} finally {
if (doc instanceof AbstractDocument) {
}
}
return offs;
}
/**
* {@inheritDoc}
*/
throws BadLocationException{
if (doc instanceof AbstractDocument) {
}
try {
if (painted) {
}
biasRet);
}
} finally {
if (doc instanceof AbstractDocument) {
}
}
return -1;
}
/**
* 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
*/
}
/**
* 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) {
if (doc instanceof AbstractDocument) {
}
try {
} catch (BadLocationException e) {
} finally {
if (doc instanceof AbstractDocument) {
}
}
}
}
}
/**
* 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;
}
/**
* 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.
* <p>
* <font color=red><b>NOTE:</b>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!
* </font>
*
* @param tc the text component for which this UI is installed
* @return the view
* @see TextUI#getRootView
*/
return rootView;
}
/**
* 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;
}
if (doc instanceof AbstractDocument) {
}
try {
} finally {
if (doc instanceof AbstractDocument) {
}
}
}
return tt;
}
// --- ViewFactory methods ------------------------------
/**
* 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;
}
/**
* 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;
}
super(type);
}
super(name);
}
}
// ----- member variables ---------------------------------------
transient boolean painted;
/**
* Root view that acts as a gateway between the component
* and the View hierarchy.
*/
RootView() {
super(null);
}
// get rid of back reference so that the old
// hierarchy can be garbage collected.
}
if (v != null) {
v.setParent(this);
}
view = v;
}
/**
* Fetches the attributes to use when rendering. At the root
* level there are no attributes. If an attribute is resolved
* up the view hierarchy this is the end of the line.
*/
return null;
}
/**
* Determines the preferred span for this view along an axis.
*
* @param axis may be either X_AXIS or Y_AXIS
* @return the span the view would like to be rendered into.
* Typically the view is told to render into the span
* that is returned, although there is no guarantee.
* The parent may choose to resize or break the view.
*/
}
return 10;
}
/**
* Determines the minimum span for this view along an axis.
*
* @param axis may be either X_AXIS or Y_AXIS
* @return the span the view would like to be rendered into.
* Typically the view is told to render into the span
* that is returned, although there is no guarantee.
* The parent may choose to resize or break the view.
*/
}
return 10;
}
/**
* Determines the maximum span for this view along an axis.
*
* @param axis may be either X_AXIS or Y_AXIS
* @return the span the view would like to be rendered into.
* Typically the view is told to render into the span
* that is returned, although there is no guarantee.
* The parent may choose to resize or break the view.
*/
}
/**
* Specifies that a preference has changed.
* Child views can call this on the parent to indicate that
* the preference has changed. The root view routes this to
* invalidate on the hosting component.
* <p>
* This can be called on a different thread from the
* event dispatching thread and is basically unsafe to
* propagate into the component. To make this safe,
* the operation is transferred over to the event dispatching
* thread for completion. It is a design goal that all view
* methods be safe to call without concern for concurrency,
* and this behavior helps make that true.
*
* @param child the child view
* @param width true if the width preference has changed
* @param height true if the height preference has changed
*/
editor.revalidate();
}
/**
* Determines the desired alignment for this view along an axis.
*
* @param axis may be either X_AXIS or Y_AXIS
* @return the desired alignment, where 0.0 indicates the origin
* and 1.0 the full span away from the origin
*/
}
return 0;
}
/**
* Renders the view.
*
* @param g the graphics context
* @param allocation the region to render into
*/
}
}
/**
* Sets the view parent.
*
* @param parent the parent view
*/
throw new Error("Can't set parent on root view");
}
/**
* Returns the number of views in this view. Since
* this view simply wraps the root of the view hierarchy
* it has exactly one child.
*
* @return the number of views
* @see #getView
*/
public int getViewCount() {
return 1;
}
/**
* Gets the n-th view in this container.
*
* @param n the number of the view to get
* @return the view
*/
return view;
}
/**
* Returns the child view index representing the given position in
* the model. This is implemented to return the index of the only
* child.
*
* @param pos the position >= 0
* @return index of the view representing the given position, or
* -1 if no view represents that position
* @since 1.3
*/
return 0;
}
/**
* Fetches the allocation for the given child view.
* This enables finding out where various views
* are located, without assuming the views store
* their location. This returns the given allocation
* since this view simply acts as a gateway between
* the view hierarchy and the associated component.
*
* @param index the index of the child
* @param a the allocation to this view.
* @return the allocation to the child
*/
return a;
}
/**
* Provides a mapping from the document model coordinate space
* to the coordinate space of the view mapped to it.
*
* @param pos the position to convert
* @param a the allocated region to render into
* @return the bounding box of the given position
*/
}
return null;
}
/**
* Provides a mapping from the document model coordinate space
* to the coordinate space of the view mapped to it.
*
* @param p0 the position to convert >= 0
* @param b0 the bias toward the previous character or the
* next character represented by p0, in case the
* position is a boundary of two views.
* @param p1 the position to convert >= 0
* @param b1 the bias toward the previous character or the
* next character represented by p1, in case the
* position is a boundary of two views.
* @param a the allocated region to render into
* @return the bounding box of the given position is returned
* @exception BadLocationException if the given position does
* not represent a valid location in the associated document
* @exception IllegalArgumentException for an invalid bias argument
* @see View#viewToModel
*/
public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a) throws BadLocationException {
}
return null;
}
/**
* Provides a mapping from the view coordinate space to the logical
* coordinate space of the model.
*
* @param x x coordinate of the view location to convert
* @param y y coordinate of the view location to convert
* @param a the allocated region to render into
* @return the location within the model that best represents the
* given point in the view
*/
return retValue;
}
return -1;
}
/**
* Provides a way to determine the next visually represented model
* location that one might place a caret. Some views may not be visible,
* they might not be in the same order found in the model, or they just
* might not allow access to some of the locations in the model.
*
* @param pos the position to convert >= 0
* @param a the allocated region to render into
* @param direction the direction from the current position that can
* be thought of as the arrow keys typically found on a keyboard.
* This may be SwingConstants.WEST, SwingConstants.EAST,
* SwingConstants.NORTH, or SwingConstants.SOUTH.
* @return the location within the model that best represents the next
* location visual position.
* @exception BadLocationException
* @exception IllegalArgumentException for an invalid direction
*/
int direction,
throws BadLocationException {
if(nextPos != -1) {
}
else {
biasRet[0] = b;
}
}
return pos;
}
/**
* Gives notification that something was inserted into the document
* in a location that this view is responsible for.
*
* @param e the change information from the associated document
* @param a the current allocation of the view
* @param f the factory to use to rebuild if the view has children
*/
view.insertUpdate(e, a, f);
}
}
/**
* Gives notification that something was removed from the document
* in a location that this view is responsible for.
*
* @param e the change information from the associated document
* @param a the current allocation of the view
* @param f the factory to use to rebuild if the view has children
*/
view.removeUpdate(e, a, f);
}
}
/**
* Gives notification from the document that attributes were changed
* in a location that this view is responsible for.
*
* @param e the change information from the associated document
* @param a the current allocation of the view
* @param f the factory to use to rebuild if the view has children
*/
view.changedUpdate(e, a, f);
}
}
/**
* Returns the document model underlying the view.
*
* @return the model
*/
return editor.getDocument();
}
/**
* Returns the starting offset into the model for this view.
*
* @return the starting offset
*/
public int getStartOffset() {
return view.getStartOffset();
}
return getElement().getStartOffset();
}
/**
* Returns the ending offset into the model for this view.
*
* @return the ending offset
*/
public int getEndOffset() {
return view.getEndOffset();
}
return getElement().getEndOffset();
}
/**
* Gets the element that this view is mapped to.
*
* @return the view
*/
return view.getElement();
}
}
/**
* Breaks this view on the given axis at the given length.
*
* @param axis may be either X_AXIS or Y_AXIS
* @param len specifies where a break is desired in the span
* @param the current allocation of the view
* @return the fragment of the view that represents the given span
* if the view can be broken, otherwise null
*/
throw new Error("Can't break root view");
}
/**
* Determines the resizability of the view along the
* given axis. A value of 0 or less is not resizable.
*
* @param axis may be either X_AXIS or Y_AXIS
* @return the weight
*/
}
return 0;
}
/**
* Sets the view size.
*
* @param width the width
* @param height the height
*/
}
}
/**
* Fetches the container hosting the view. This is useful for
* things like scheduling a repaint, finding out the host
* components font, etc. The default implementation
* of this is to forward the query to the parent view.
*
* @return the container
*/
return editor;
}
/**
* Fetches the factory to be used for building the
* various view fragments that make up the view that
* represents the model. This is what determines
* how the model will be represented. This is implemented
* to fetch the factory provided by the associated
* EditorKit unless that is null, in which case this
* simply returns the BasicTextUI itself which allows
* subclasses to implement a simple factory directly without
* creating extra objects.
*
* @return the factory
*/
if (f != null) {
return f;
}
return BasicTextUI.this;
}
}
/**
* Handles updates from various places. If the model is changed,
* this class unregisters as a listener to the old model and
* registers with the new model. If the document model changes,
* the change is forwarded to the root view. If the focus
* accelerator changes, a new keystroke is registered to request
* focus.
*/
class UpdateHandler implements PropertyChangeListener, DocumentListener, LayoutManager2, UIResource {
// --- PropertyChangeListener methods -----------------------
/**
* This method gets called when a bound property is changed.
* We are looking for document changes on the editor.
*/
i18nView = false;
}
if ("document" == propertyName) {
modelChanged();
return;
}
}
modelChanged();
}
if ("focusAccelerator" == propertyName) {
} else if ("componentOrientation" == propertyName) {
// Changes in ComponentOrientation require the views to be
// rebuilt.
modelChanged();
} else if ("font" == propertyName) {
modelChanged();
} else if ("dropLocation" == propertyName) {
} else if ("editable" == propertyName) {
updateCursor();
modelChanged();
}
}
private void dropIndexChanged() {
return;
}
if (dropLocation == null) {
}
} else {
dropCaret = new BasicCaret();
dropCaret.setVisible(true);
}
dropLocation.getBias());
}
}
// --- DocumentListener methods -----------------------
/**
* The insert notification. Gets sent to the root of the view structure
* that represents the portion of the model being represented by the
* editor. The factory is added as an argument to the update so that
* the views can update themselves in a dynamic (not hardcoded) way.
*
* @param e The change notification from the currently associated
* document.
* @see DocumentListener#insertUpdate
*/
if (o instanceof Boolean) {
// i18n flag changed, rebuild the view
modelChanged();
return;
}
}
// normal insert update
}
/**
* The remove notification. Gets sent to the root of the view structure
* that represents the portion of the model being represented by the
* editor. The factory is added as an argument to the update so that
* the views can update themselves in a dynamic (not hardcoded) way.
*
* @param e The change notification from the currently associated
* document.
* @see DocumentListener#removeUpdate
*/
}
/**
* The change notification. Gets sent to the root of the view structure
* that represents the portion of the model being represented by the
* editor. The factory is added as an argument to the update so that
* the views can update themselves in a dynamic (not hardcoded) way.
*
* @param e The change notification from the currently associated
* document.
* @see DocumentListener#changedUpdate(DocumentEvent)
*/
}
// --- LayoutManager2 methods --------------------------------
/**
* Adds the specified component with the specified name to
* the layout.
* @param name the component name
* @param comp the component to be added
*/
// not supported
}
/**
* Removes the specified component from the layout.
* @param comp the component to be removed
*/
if (constraints != null) {
// remove the constraint record
}
}
/**
* Calculates the preferred size dimensions for the specified
* panel given the components in the specified parent container.
* @param parent the component to be laid out
*
* @see #minimumLayoutSize
*/
// should not be called (JComponent uses UI instead)
return null;
}
/**
* Calculates the minimum size dimensions for the specified
* panel given the components in the specified parent container.
* @param parent the component to be laid out
* @see #preferredLayoutSize
*/
// should not be called (JComponent uses UI instead)
return null;
}
/**
* Lays out the container in the specified panel. This is
* implemented to position all components that were added
* with a View object as a constraint. The current allocation
* of the associated View is used as the location of the
* component.
* <p>
* A read-lock is acquired on the document to prevent the
* view tree from being modified while the layout process
* is active.
*
* @param parent the component which needs to be laid out
*/
if (doc instanceof AbstractDocument) {
}
try {
while (components.hasMoreElements()) {
}
}
} finally {
if (doc instanceof AbstractDocument) {
}
}
}
}
}
/**
* Find the Shape representing the given view.
*/
int pos = v.getStartOffset();
}
}
/**
* Adds the specified component to the layout, using the specified
* constraint object. We only store those components that were added
* with a constraint that is of type View.
*
* @param comp the component to be added
*/
if (constraint instanceof View) {
if (constraints == null) {
}
}
}
/**
* Returns the maximum size of this component.
* @see java.awt.Component#getMinimumSize()
* @see java.awt.Component#getPreferredSize()
* @see LayoutManager
*/
// should not be called (JComponent uses UI instead)
return null;
}
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
return 0.5f;
}
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
return 0.5f;
}
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
*/
}
/**
* The "layout constraints" for the LayoutManager2 implementation.
* These are View objects for those components that are represented
* by a View in the View tree.
*/
private boolean i18nView = false;
}
/**
* Wrapper for text actions to return isEnabled false in case editor is non editable
*/
}
/**
* The operation to perform when this action is triggered.
*
* @param e the action event
*/
}
public boolean isEnabled() {
}
}
/**
* Registered in the ActionMap.
*/
}
public boolean isEnabled() {
return editor.isEditable();
}
}
synchronized(DragListener.class) {
get(DragListener.class);
listener = new DragListener();
}
return listener;
}
}
/**
* Listens for mouse events for the purposes of detecting drag gestures.
* BasicTextUI will maintain one of these per AppContext.
*/
implements BeforeDrag {
private boolean dragStarted;
dragStarted = true;
}
if (c.getDragEnabled()) {
dragStarted = false;
e.consume();
}
}
}
if (c.getDragEnabled()) {
if (dragStarted) {
e.consume();
}
}
}
if (c.getDragEnabled()) {
e.consume();
}
}
}
/**
* Determines if the following are true:
* <ul>
* <li>the component is enabled
* <li>the press event is located over a selection
* </ul>
*/
if (c.isEnabled()) {
int pos = c.viewToModel(p);
return true;
}
}
}
return false;
}
}
private boolean shouldRemove;
private int p0;
private int p1;
/**
* Whether or not this is a drop using
* <code>DropMode.INSERT</code>.
*/
private boolean modeBetween = false;
/**
* Whether or not this is a drop.
*/
private boolean isDrop = false;
/**
* The drop action.
*/
/**
* The drop bias.
*/
/**
* Try to find a flavor that can be used to import a Transferable.
* The set of usable flavors are tried in the following order:
* <ol>
* <li>First, an attempt is made to find a flavor matching the content type
* of the EditorKit for the component.
* <li>Third, an attempt to find a flavor representing a String reference
* in the same VM is made.
* <li>Lastly, DataFlavor.stringFlavor is searched for.
* </ol>
*/
if (c instanceof JEditorPane) {
return flavors[i];
plainFlavor = flavors[i];
stringFlavor = flavors[i];
}
}
if (plainFlavor != null) {
return plainFlavor;
return refFlavor;
} else if (stringFlavor != null) {
return stringFlavor;
}
return null;
}
return flavors[i];
stringFlavor = flavors[i];
}
}
return refFlavor;
} else if (stringFlavor != null) {
return stringFlavor;
}
return null;
}
/**
* Import the given stream data into the text component.
*/
throws BadLocationException, IOException {
if (useRead) {
int startPosition = c.getSelectionStart();
int endPosition = c.getSelectionEnd();
if (length > 0) {
}
} else {
char[] buff = new char[1024];
int nch;
boolean lastWasCR = false;
int last;
// Read in a block at a time, mapping \r\n to \n, as well as single
// \r to \n.
}
last = 0;
case '\r':
if (lastWasCR) {
if (counter == 0) {
} else {
}
} else {
lastWasCR = true;
}
break;
case '\n':
if (lastWasCR) {
}
// else nothing to do, can skip \r, next write will
// write \n
lastWasCR = false;
}
break;
default:
if (lastWasCR) {
if (counter == 0) {
} else {
}
lastWasCR = false;
}
break;
}
}
if (lastWasCR) {
}
} else {
}
}
}
if (lastWasCR) {
}
}
}
// --- TransferHandler methods ------------------------------------
/**
* This is the type of transfer actions supported by the source. Some models are
* not mutable, so a transfer operation of COPY only should
* be advertised in that case.
*
* @param c The component holding the data to be transfered. This
* argument is provided to enable sharing of TransferHandlers by
* multiple components.
* @return This is implemented to return NONE if the component is a JPasswordField
* since exporting data via user gestures is not allowed. If the text component is
* editable, COPY_OR_MOVE is returned, otherwise just COPY is allowed.
*/
if (c instanceof JPasswordField &&
c.getClientProperty("JPasswordField.cutCopyAllowed") !=
return NONE;
}
}
/**
* Create a Transferable to use as the source for a data transfer.
*
* @param comp The component holding the data to be transfered. This
* argument is provided to enable sharing of TransferHandlers by
* multiple components.
* @return The representation of the data to be transfered.
*
*/
shouldRemove = true;
}
/**
* This method is called after data has been exported. This method should remove
* the data that was transfered if the action was MOVE.
*
* @param source The component that was the source of the data.
* @param data The data that was transferred or possibly null
* if the action is <code>NONE</code>.
* @param action The actual action that was performed.
*/
// only remove the text if shouldRemove has not been set to
// false by importData and only if the action is a move
t.removeText();
}
exportComp = null;
}
if (isDrop) {
}
try {
return super.importData(support);
} finally {
isDrop = false;
modeBetween = false;
dropAction = MOVE;
}
}
/**
* This method causes a transfer to a component from a clipboard or a
* DND drop operation. The Transferable represents the data to be
* imported into the component.
*
* @param comp The component to receive the transfer. This
* argument is provided to enable sharing of TransferHandlers by
* multiple components.
* @param t The data to import
* @return true if the data was inserted into the component, false otherwise.
*/
int pos = modeBetween
// if we are importing to the same component that we exported from
// then don't actually do anything if the drop location is inside
// the drag location and set shouldRemove to false so that exportDone
// knows not to remove any data
shouldRemove = false;
return true;
}
boolean imported = false;
if (importFlavor != null) {
try {
boolean useRead = false;
if (comp instanceof JEditorPane) {
useRead = true;
}
}
ic.endComposition();
}
if (modeBetween) {
if (caret instanceof DefaultCaret) {
} else {
c.setCaretPosition(pos);
}
}
handleReaderImport(r, c, useRead);
if (isDrop) {
c.requestFocus();
if (caret instanceof DefaultCaret) {
} else {
}
}
imported = true;
} catch (UnsupportedFlavorException ufe) {
} catch (BadLocationException ble) {
} catch (IOException ioe) {
}
}
return imported;
}
/**
* This method indicates if a component would accept an import of the given
* set of data flavors prior to actually attempting to import it.
*
* @param comp The component to receive the transfer. This
* argument is provided to enable sharing of TransferHandlers by
* multiple components.
* @param flavors The data formats available
* @return true if the data can be inserted into the component, false otherwise.
*/
if (!(c.isEditable() && c.isEnabled())) {
return false;
}
}
/**
* A possible implementation of the Transferable interface
* for text components. For a JEditorPane with a rich set
* of EditorKit implementations, conversions could be made
* giving a wider set of formats. This is implemented to
* (if that is not the active format) since that can be
* extracted from other formats.
*/
this.c = c;
try {
plainData = c.getSelectedText();
if (c instanceof JEditorPane) {
return;
}
} else {
}
}
} catch (BadLocationException ble) {
} catch (IOException ioe) {
}
}
void removeText() {
try {
} catch (BadLocationException e) {
}
}
}
// ---- EditorKit other than plain or HTML text -----------------------
/**
* is supported through the "richer flavors" part of BasicTransferable.
*/
return null;
}
try {
return flavors;
} catch (ClassNotFoundException cle) {
// fall through to unsupported (should not happen)
}
return null;
}
/**
* The only richer format supported is the file list flavor
*/
return null;
}
return richText;
return new StringReader(richText);
return new StringBufferInputStream(richText);
}
throw new UnsupportedFlavorException(flavor);
}
}
}
}