You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
803 lines
30 KiB
803 lines
30 KiB
/*
|
|
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
package javax.swing.text;
|
|
|
|
import java.util.Vector;
|
|
import java.awt.*;
|
|
import javax.swing.event.*;
|
|
import javax.swing.SwingConstants;
|
|
|
|
/**
|
|
* <code>CompositeView</code> is an abstract <code>View</code>
|
|
* implementation which manages one or more child views.
|
|
* (Note that <code>CompositeView</code> is intended
|
|
* for managing relatively small numbers of child views.)
|
|
* <code>CompositeView</code> is intended to be used as
|
|
* a starting point for <code>View</code> implementations,
|
|
* such as <code>BoxView</code>, that will contain child
|
|
* <code>View</code>s. Subclasses that wish to manage the
|
|
* collection of child <code>View</code>s should use the
|
|
* {@link #replace} method. As <code>View</code> invokes
|
|
* <code>replace</code> during <code>DocumentListener</code>
|
|
* notification, you normally won't need to directly
|
|
* invoke <code>replace</code>.
|
|
*
|
|
* <p>While <code>CompositeView</code>
|
|
* does not impose a layout policy on its child <code>View</code>s,
|
|
* it does allow for inseting the child <code>View</code>s
|
|
* it will contain. The insets can be set by either
|
|
* {@link #setInsets} or {@link #setParagraphInsets}.
|
|
*
|
|
* <p>In addition to the abstract methods of
|
|
* {@link javax.swing.text.View},
|
|
* subclasses of <code>CompositeView</code> will need to
|
|
* override:
|
|
* <ul>
|
|
* <li>{@link #isBefore} - Used to test if a given
|
|
* <code>View</code> location is before the visual space
|
|
* of the <code>CompositeView</code>.
|
|
* <li>{@link #isAfter} - Used to test if a given
|
|
* <code>View</code> location is after the visual space
|
|
* of the <code>CompositeView</code>.
|
|
* <li>{@link #getViewAtPoint} - Returns the view at
|
|
* a given visual location.
|
|
* <li>{@link #childAllocation} - Returns the bounds of
|
|
* a particular child <code>View</code>.
|
|
* <code>getChildAllocation</code> will invoke
|
|
* <code>childAllocation</code> after offseting
|
|
* the bounds by the <code>Inset</code>s of the
|
|
* <code>CompositeView</code>.
|
|
* </ul>
|
|
*
|
|
* @author Timothy Prinzing
|
|
*/
|
|
public abstract class CompositeView extends View {
|
|
|
|
/**
|
|
* Constructs a <code>CompositeView</code> for the given element.
|
|
*
|
|
* @param elem the element this view is responsible for
|
|
*/
|
|
public CompositeView(Element elem) {
|
|
super(elem);
|
|
children = new View[1];
|
|
nchildren = 0;
|
|
childAlloc = new Rectangle();
|
|
}
|
|
|
|
/**
|
|
* Loads all of the children to initialize the view.
|
|
* This is called by the {@link #setParent}
|
|
* method. Subclasses can reimplement this to initialize
|
|
* their child views in a different manner. The default
|
|
* implementation creates a child view for each
|
|
* child element.
|
|
*
|
|
* @param f the view factory
|
|
* @see #setParent
|
|
*/
|
|
protected void loadChildren(ViewFactory f) {
|
|
if (f == null) {
|
|
// No factory. This most likely indicates the parent view
|
|
// has changed out from under us, bail!
|
|
return;
|
|
}
|
|
Element e = getElement();
|
|
int n = e.getElementCount();
|
|
if (n > 0) {
|
|
View[] added = new View[n];
|
|
for (int i = 0; i < n; i++) {
|
|
added[i] = f.create(e.getElement(i));
|
|
}
|
|
replace(0, 0, added);
|
|
}
|
|
}
|
|
|
|
// --- View methods ---------------------------------------------
|
|
|
|
/**
|
|
* Sets the parent of the view.
|
|
* This is reimplemented to provide the superclass
|
|
* behavior as well as calling the <code>loadChildren</code>
|
|
* method if this view does not already have children.
|
|
* The children should not be loaded in the
|
|
* constructor because the act of setting the parent
|
|
* may cause them to try to search up the hierarchy
|
|
* (to get the hosting <code>Container</code> for example).
|
|
* If this view has children (the view is being moved
|
|
* from one place in the view hierarchy to another),
|
|
* the <code>loadChildren</code> method will not be called.
|
|
*
|
|
* @param parent the parent of the view, <code>null</code> if none
|
|
*/
|
|
public void setParent(View parent) {
|
|
super.setParent(parent);
|
|
if ((parent != null) && (nchildren == 0)) {
|
|
ViewFactory f = getViewFactory();
|
|
loadChildren(f);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the number of child views of this view.
|
|
*
|
|
* @return the number of views >= 0
|
|
* @see #getView
|
|
*/
|
|
public int getViewCount() {
|
|
return nchildren;
|
|
}
|
|
|
|
/**
|
|
* Returns the n-th view in this container.
|
|
*
|
|
* @param n the number of the desired view, >= 0 && < getViewCount()
|
|
* @return the view at index <code>n</code>
|
|
*/
|
|
public View getView(int n) {
|
|
return children[n];
|
|
}
|
|
|
|
/**
|
|
* Replaces child views. If there are no views to remove
|
|
* this acts as an insert. If there are no views to
|
|
* add this acts as a remove. Views being removed will
|
|
* have the parent set to <code>null</code>,
|
|
* and the internal reference to them removed so that they
|
|
* may be garbage collected.
|
|
*
|
|
* @param offset the starting index into the child views to insert
|
|
* the new views; >= 0 and <= getViewCount
|
|
* @param length the number of existing child views to remove;
|
|
* this should be a value >= 0 and <= (getViewCount() - offset)
|
|
* @param views the child views to add; this value can be
|
|
* <code>null</code>
|
|
* to indicate no children are being added (useful to remove)
|
|
*/
|
|
public void replace(int offset, int length, View[] views) {
|
|
// make sure an array exists
|
|
if (views == null) {
|
|
views = ZERO;
|
|
}
|
|
|
|
// update parent reference on removed views
|
|
for (int i = offset; i < offset + length; i++) {
|
|
if (children[i].getParent() == this) {
|
|
// in FlowView.java view might be referenced
|
|
// from two super-views as a child. see logicalView
|
|
children[i].setParent(null);
|
|
}
|
|
children[i] = null;
|
|
}
|
|
|
|
// update the array
|
|
int delta = views.length - length;
|
|
int src = offset + length;
|
|
int nmove = nchildren - src;
|
|
int dest = src + delta;
|
|
if ((nchildren + delta) >= children.length) {
|
|
// need to grow the array
|
|
int newLength = Math.max(2*children.length, nchildren + delta);
|
|
View[] newChildren = new View[newLength];
|
|
System.arraycopy(children, 0, newChildren, 0, offset);
|
|
System.arraycopy(views, 0, newChildren, offset, views.length);
|
|
System.arraycopy(children, src, newChildren, dest, nmove);
|
|
children = newChildren;
|
|
} else {
|
|
// patch the existing array
|
|
System.arraycopy(children, src, children, dest, nmove);
|
|
System.arraycopy(views, 0, children, offset, views.length);
|
|
}
|
|
nchildren = nchildren + delta;
|
|
|
|
// update parent reference on added views
|
|
for (int i = 0; i < views.length; i++) {
|
|
views[i].setParent(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches the allocation for the given child view to
|
|
* render into. This enables finding out where various views
|
|
* are located.
|
|
*
|
|
* @param index the index of the child, >= 0 && < getViewCount()
|
|
* @param a the allocation to this view
|
|
* @return the allocation to the child
|
|
*/
|
|
public Shape getChildAllocation(int index, Shape a) {
|
|
Rectangle alloc = getInsideAllocation(a);
|
|
childAllocation(index, alloc);
|
|
return alloc;
|
|
}
|
|
|
|
/**
|
|
* 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 >= 0
|
|
* @param a the allocated region to render into
|
|
* @param b a bias value of either <code>Position.Bias.Forward</code>
|
|
* or <code>Position.Bias.Backward</code>
|
|
* @return the bounding box of the given position
|
|
* @exception BadLocationException if the given position does
|
|
* not represent a valid location in the associated document
|
|
* @see View#modelToView
|
|
*/
|
|
public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
|
|
boolean isBackward = (b == Position.Bias.Backward);
|
|
int testPos = (isBackward) ? Math.max(0, pos - 1) : pos;
|
|
if(isBackward && testPos < getStartOffset()) {
|
|
return null;
|
|
}
|
|
int vIndex = getViewIndexAtPosition(testPos);
|
|
if ((vIndex != -1) && (vIndex < getViewCount())) {
|
|
View v = getView(vIndex);
|
|
if(v != null && testPos >= v.getStartOffset() &&
|
|
testPos < v.getEndOffset()) {
|
|
Shape childShape = getChildAllocation(vIndex, a);
|
|
if (childShape == null) {
|
|
// We are likely invalid, fail.
|
|
return null;
|
|
}
|
|
Shape retShape = v.modelToView(pos, childShape, b);
|
|
if(retShape == null && v.getEndOffset() == pos) {
|
|
if(++vIndex < getViewCount()) {
|
|
v = getView(vIndex);
|
|
retShape = v.modelToView(pos, getChildAllocation(vIndex, a), b);
|
|
}
|
|
}
|
|
return retShape;
|
|
}
|
|
}
|
|
throw new BadLocationException("Position not represented by view",
|
|
pos);
|
|
}
|
|
|
|
/**
|
|
* 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; either
|
|
* <code>Position.Bias.Forward</code> or
|
|
* <code>Position.Bias.Backward</code>
|
|
* @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 {
|
|
if (p0 == getStartOffset() && p1 == getEndOffset()) {
|
|
return a;
|
|
}
|
|
Rectangle alloc = getInsideAllocation(a);
|
|
Rectangle r0 = new Rectangle(alloc);
|
|
View v0 = getViewAtPosition((b0 == Position.Bias.Backward) ?
|
|
Math.max(0, p0 - 1) : p0, r0);
|
|
Rectangle r1 = new Rectangle(alloc);
|
|
View v1 = getViewAtPosition((b1 == Position.Bias.Backward) ?
|
|
Math.max(0, p1 - 1) : p1, r1);
|
|
if (v0 == v1) {
|
|
if (v0 == null) {
|
|
return a;
|
|
}
|
|
// Range contained in one view
|
|
return v0.modelToView(p0, b0, p1, b1, r0);
|
|
}
|
|
// Straddles some views.
|
|
int viewCount = getViewCount();
|
|
int counter = 0;
|
|
while (counter < viewCount) {
|
|
View v;
|
|
// Views may not be in same order as model.
|
|
// v0 or v1 may be null if there is a gap in the range this
|
|
// view contains.
|
|
if ((v = getView(counter)) == v0 || v == v1) {
|
|
View endView;
|
|
Rectangle retRect;
|
|
Rectangle tempRect = new Rectangle();
|
|
if (v == v0) {
|
|
retRect = v0.modelToView(p0, b0, v0.getEndOffset(),
|
|
Position.Bias.Backward, r0).
|
|
getBounds();
|
|
endView = v1;
|
|
}
|
|
else {
|
|
retRect = v1.modelToView(v1.getStartOffset(),
|
|
Position.Bias.Forward,
|
|
p1, b1, r1).getBounds();
|
|
endView = v0;
|
|
}
|
|
|
|
// Views entirely covered by range.
|
|
while (++counter < viewCount &&
|
|
(v = getView(counter)) != endView) {
|
|
tempRect.setBounds(alloc);
|
|
childAllocation(counter, tempRect);
|
|
retRect.add(tempRect);
|
|
}
|
|
|
|
// End view.
|
|
if (endView != null) {
|
|
Shape endShape;
|
|
if (endView == v1) {
|
|
endShape = v1.modelToView(v1.getStartOffset(),
|
|
Position.Bias.Forward,
|
|
p1, b1, r1);
|
|
}
|
|
else {
|
|
endShape = v0.modelToView(p0, b0, v0.getEndOffset(),
|
|
Position.Bias.Backward, r0);
|
|
}
|
|
if (endShape instanceof Rectangle) {
|
|
retRect.add((Rectangle)endShape);
|
|
}
|
|
else {
|
|
retRect.add(endShape.getBounds());
|
|
}
|
|
}
|
|
return retRect;
|
|
}
|
|
counter++;
|
|
}
|
|
throw new BadLocationException("Position not represented by view", p0);
|
|
}
|
|
|
|
/**
|
|
* 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 >= 0
|
|
* @param y y coordinate of the view location to convert >= 0
|
|
* @param a the allocated region to render into
|
|
* @param bias either <code>Position.Bias.Forward</code> or
|
|
* <code>Position.Bias.Backward</code>
|
|
* @return the location within the model that best represents the
|
|
* given point in the view >= 0
|
|
* @see View#viewToModel
|
|
*/
|
|
public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) {
|
|
Rectangle alloc = getInsideAllocation(a);
|
|
if (isBefore((int) x, (int) y, alloc)) {
|
|
// point is before the range represented
|
|
int retValue = -1;
|
|
|
|
try {
|
|
retValue = getNextVisualPositionFrom(-1, Position.Bias.Forward,
|
|
a, EAST, bias);
|
|
} catch (BadLocationException ble) { }
|
|
catch (IllegalArgumentException iae) { }
|
|
if(retValue == -1) {
|
|
retValue = getStartOffset();
|
|
bias[0] = Position.Bias.Forward;
|
|
}
|
|
return retValue;
|
|
} else if (isAfter((int) x, (int) y, alloc)) {
|
|
// point is after the range represented.
|
|
int retValue = -1;
|
|
try {
|
|
retValue = getNextVisualPositionFrom(-1, Position.Bias.Forward,
|
|
a, WEST, bias);
|
|
} catch (BadLocationException ble) { }
|
|
catch (IllegalArgumentException iae) { }
|
|
|
|
if(retValue == -1) {
|
|
// NOTE: this could actually use end offset with backward.
|
|
retValue = getEndOffset() - 1;
|
|
bias[0] = Position.Bias.Forward;
|
|
}
|
|
return retValue;
|
|
} else {
|
|
// locate the child and pass along the request
|
|
View v = getViewAtPoint((int) x, (int) y, alloc);
|
|
if (v != null) {
|
|
return v.viewToModel(x, y, alloc, bias);
|
|
}
|
|
}
|
|
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.
|
|
* This is a convenience method for {@link #getNextNorthSouthVisualPositionFrom}
|
|
* and {@link #getNextEastWestVisualPositionFrom}.
|
|
* This method enables specifying a position to convert
|
|
* within the range of >=0. If the value is -1, a position
|
|
* will be calculated automatically. If the value < -1,
|
|
* the {@code BadLocationException} will be thrown.
|
|
*
|
|
* @param pos the position to convert
|
|
* @param b a bias value of either <code>Position.Bias.Forward</code>
|
|
* or <code>Position.Bias.Backward</code>
|
|
* @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 one of the following:
|
|
* <ul>
|
|
* <li><code>SwingConstants.WEST</code>
|
|
* <li><code>SwingConstants.EAST</code>
|
|
* <li><code>SwingConstants.NORTH</code>
|
|
* <li><code>SwingConstants.SOUTH</code>
|
|
* </ul>
|
|
* @param biasRet an array containing the bias that was checked
|
|
* @return the location within the model that best represents the next
|
|
* location visual position
|
|
* @exception BadLocationException the given position is not a valid
|
|
* position within the document
|
|
* @exception IllegalArgumentException if <code>direction</code> is invalid
|
|
*/
|
|
public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
|
|
int direction, Position.Bias[] biasRet)
|
|
throws BadLocationException {
|
|
if (pos < -1) {
|
|
throw new BadLocationException("invalid position", pos);
|
|
}
|
|
Rectangle alloc = getInsideAllocation(a);
|
|
|
|
switch (direction) {
|
|
case NORTH:
|
|
return getNextNorthSouthVisualPositionFrom(pos, b, a, direction,
|
|
biasRet);
|
|
case SOUTH:
|
|
return getNextNorthSouthVisualPositionFrom(pos, b, a, direction,
|
|
biasRet);
|
|
case EAST:
|
|
return getNextEastWestVisualPositionFrom(pos, b, a, direction,
|
|
biasRet);
|
|
case WEST:
|
|
return getNextEastWestVisualPositionFrom(pos, b, a, direction,
|
|
biasRet);
|
|
default:
|
|
throw new IllegalArgumentException("Bad direction: " + direction);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the child view index representing the given
|
|
* position in the model. This is implemented to call the
|
|
* <code>getViewIndexByPosition</code>
|
|
* method for backward compatibility.
|
|
*
|
|
* @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
|
|
*/
|
|
public int getViewIndex(int pos, Position.Bias b) {
|
|
if(b == Position.Bias.Backward) {
|
|
pos -= 1;
|
|
}
|
|
if ((pos >= getStartOffset()) && (pos < getEndOffset())) {
|
|
return getViewIndexAtPosition(pos);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// --- local methods ----------------------------------------------------
|
|
|
|
|
|
/**
|
|
* Tests whether a point lies before the rectangle range.
|
|
*
|
|
* @param x the X coordinate >= 0
|
|
* @param y the Y coordinate >= 0
|
|
* @param alloc the rectangle
|
|
* @return true if the point is before the specified range
|
|
*/
|
|
protected abstract boolean isBefore(int x, int y, Rectangle alloc);
|
|
|
|
/**
|
|
* Tests whether a point lies after the rectangle range.
|
|
*
|
|
* @param x the X coordinate >= 0
|
|
* @param y the Y coordinate >= 0
|
|
* @param alloc the rectangle
|
|
* @return true if the point is after the specified range
|
|
*/
|
|
protected abstract boolean isAfter(int x, int y, Rectangle alloc);
|
|
|
|
/**
|
|
* Fetches the child view at the given coordinates.
|
|
*
|
|
* @param x the X coordinate >= 0
|
|
* @param y the Y coordinate >= 0
|
|
* @param alloc the parent's allocation on entry, which should
|
|
* be changed to the child's allocation on exit
|
|
* @return the child view
|
|
*/
|
|
protected abstract View getViewAtPoint(int x, int y, Rectangle alloc);
|
|
|
|
/**
|
|
* Returns the allocation for a given child.
|
|
*
|
|
* @param index the index of the child, >= 0 && < getViewCount()
|
|
* @param a the allocation to the interior of the box on entry,
|
|
* and the allocation of the child view at the index on exit.
|
|
*/
|
|
protected abstract void childAllocation(int index, Rectangle a);
|
|
|
|
/**
|
|
* Fetches the child view that represents the given position in
|
|
* the model. This is implemented to fetch the view in the case
|
|
* where there is a child view for each child element.
|
|
*
|
|
* @param pos the position >= 0
|
|
* @param a the allocation to the interior of the box on entry,
|
|
* and the allocation of the view containing the position on exit
|
|
* @return the view representing the given position, or
|
|
* <code>null</code> if there isn't one
|
|
*/
|
|
protected View getViewAtPosition(int pos, Rectangle a) {
|
|
int index = getViewIndexAtPosition(pos);
|
|
if ((index >= 0) && (index < getViewCount())) {
|
|
View v = getView(index);
|
|
if (a != null) {
|
|
childAllocation(index, a);
|
|
}
|
|
return v;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Fetches the child view index representing the given position in
|
|
* the model. This is implemented to fetch the view in the case
|
|
* where there is a child view for each child element.
|
|
*
|
|
* @param pos the position >= 0
|
|
* @return index of the view representing the given position, or
|
|
* -1 if no view represents that position
|
|
*/
|
|
protected int getViewIndexAtPosition(int pos) {
|
|
Element elem = getElement();
|
|
return elem.getElementIndex(pos);
|
|
}
|
|
|
|
/**
|
|
* Translates the immutable allocation given to the view
|
|
* to a mutable allocation that represents the interior
|
|
* allocation (i.e. the bounds of the given allocation
|
|
* with the top, left, bottom, and right insets removed.
|
|
* It is expected that the returned value would be further
|
|
* mutated to represent an allocation to a child view.
|
|
* This is implemented to reuse an instance variable so
|
|
* it avoids creating excessive Rectangles. Typically
|
|
* the result of calling this method would be fed to
|
|
* the <code>childAllocation</code> method.
|
|
*
|
|
* @param a the allocation given to the view
|
|
* @return the allocation that represents the inside of the
|
|
* view after the margins have all been removed; if the
|
|
* given allocation was <code>null</code>,
|
|
* the return value is <code>null</code>
|
|
*/
|
|
protected Rectangle getInsideAllocation(Shape a) {
|
|
if (a != null) {
|
|
// get the bounds, hopefully without allocating
|
|
// a new rectangle. The Shape argument should
|
|
// not be modified... we copy it into the
|
|
// child allocation.
|
|
Rectangle alloc;
|
|
if (a instanceof Rectangle) {
|
|
alloc = (Rectangle) a;
|
|
} else {
|
|
alloc = a.getBounds();
|
|
}
|
|
|
|
childAlloc.setBounds(alloc);
|
|
childAlloc.x += getLeftInset();
|
|
childAlloc.y += getTopInset();
|
|
childAlloc.width -= getLeftInset() + getRightInset();
|
|
childAlloc.height -= getTopInset() + getBottomInset();
|
|
return childAlloc;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Sets the insets from the paragraph attributes specified in
|
|
* the given attributes.
|
|
*
|
|
* @param attr the attributes
|
|
*/
|
|
protected void setParagraphInsets(AttributeSet attr) {
|
|
// Since version 1.1 doesn't have scaling and assumes
|
|
// a pixel is equal to a point, we just cast the point
|
|
// sizes to integers.
|
|
top = (short) StyleConstants.getSpaceAbove(attr);
|
|
left = (short) StyleConstants.getLeftIndent(attr);
|
|
bottom = (short) StyleConstants.getSpaceBelow(attr);
|
|
right = (short) StyleConstants.getRightIndent(attr);
|
|
}
|
|
|
|
/**
|
|
* Sets the insets for the view.
|
|
*
|
|
* @param top the top inset >= 0
|
|
* @param left the left inset >= 0
|
|
* @param bottom the bottom inset >= 0
|
|
* @param right the right inset >= 0
|
|
*/
|
|
protected void setInsets(short top, short left, short bottom, short right) {
|
|
this.top = top;
|
|
this.left = left;
|
|
this.right = right;
|
|
this.bottom = bottom;
|
|
}
|
|
|
|
/**
|
|
* Gets the left inset.
|
|
*
|
|
* @return the inset >= 0
|
|
*/
|
|
protected short getLeftInset() {
|
|
return left;
|
|
}
|
|
|
|
/**
|
|
* Gets the right inset.
|
|
*
|
|
* @return the inset >= 0
|
|
*/
|
|
protected short getRightInset() {
|
|
return right;
|
|
}
|
|
|
|
/**
|
|
* Gets the top inset.
|
|
*
|
|
* @return the inset >= 0
|
|
*/
|
|
protected short getTopInset() {
|
|
return top;
|
|
}
|
|
|
|
/**
|
|
* Gets the bottom inset.
|
|
*
|
|
* @return the inset >= 0
|
|
*/
|
|
protected short getBottomInset() {
|
|
return bottom;
|
|
}
|
|
|
|
/**
|
|
* Returns the next visual position for the cursor, in either the
|
|
* north or south direction.
|
|
*
|
|
* @param pos the position to convert >= 0
|
|
* @param b a bias value of either <code>Position.Bias.Forward</code>
|
|
* or <code>Position.Bias.Backward</code>
|
|
* @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 one of the following:
|
|
* <ul>
|
|
* <li><code>SwingConstants.NORTH</code>
|
|
* <li><code>SwingConstants.SOUTH</code>
|
|
* </ul>
|
|
* @param biasRet an array containing the bias that was checked
|
|
* @return the location within the model that best represents the next
|
|
* north or south location
|
|
* @exception BadLocationException
|
|
* @exception IllegalArgumentException if <code>direction</code> is invalid
|
|
* @see #getNextVisualPositionFrom
|
|
*
|
|
* @return the next position west of the passed in position
|
|
*/
|
|
protected int getNextNorthSouthVisualPositionFrom(int pos, Position.Bias b,
|
|
Shape a, int direction,
|
|
Position.Bias[] biasRet)
|
|
throws BadLocationException {
|
|
return Utilities.getNextVisualPositionFrom(
|
|
this, pos, b, a, direction, biasRet);
|
|
}
|
|
|
|
/**
|
|
* Returns the next visual position for the cursor, in either the
|
|
* east or west direction.
|
|
*
|
|
* @param pos the position to convert >= 0
|
|
* @param b a bias value of either <code>Position.Bias.Forward</code>
|
|
* or <code>Position.Bias.Backward</code>
|
|
* @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 one of the following:
|
|
* <ul>
|
|
* <li><code>SwingConstants.WEST</code>
|
|
* <li><code>SwingConstants.EAST</code>
|
|
* </ul>
|
|
* @param biasRet an array containing the bias that was checked
|
|
* @return the location within the model that best represents the next
|
|
* west or east location
|
|
* @exception BadLocationException
|
|
* @exception IllegalArgumentException if <code>direction</code> is invalid
|
|
* @see #getNextVisualPositionFrom
|
|
*/
|
|
protected int getNextEastWestVisualPositionFrom(int pos, Position.Bias b,
|
|
Shape a,
|
|
int direction,
|
|
Position.Bias[] biasRet)
|
|
throws BadLocationException {
|
|
return Utilities.getNextVisualPositionFrom(
|
|
this, pos, b, a, direction, biasRet);
|
|
}
|
|
|
|
/**
|
|
* Determines in which direction the next view lays.
|
|
* Consider the <code>View</code> at index n. Typically the
|
|
* <code>View</code>s are layed out from left to right,
|
|
* so that the <code>View</code> to the EAST will be
|
|
* at index n + 1, and the <code>View</code> to the WEST
|
|
* will be at index n - 1. In certain situations,
|
|
* such as with bidirectional text, it is possible
|
|
* that the <code>View</code> to EAST is not at index n + 1,
|
|
* but rather at index n - 1, or that the <code>View</code>
|
|
* to the WEST is not at index n - 1, but index n + 1.
|
|
* In this case this method would return true, indicating the
|
|
* <code>View</code>s are layed out in descending order.
|
|
* <p>
|
|
* This unconditionally returns false, subclasses should override this
|
|
* method if there is the possibility for laying <code>View</code>s in
|
|
* descending order.
|
|
*
|
|
* @param position position into the model
|
|
* @param bias either <code>Position.Bias.Forward</code> or
|
|
* <code>Position.Bias.Backward</code>
|
|
* @return false
|
|
*/
|
|
protected boolean flipEastAndWestAtEnds(int position,
|
|
Position.Bias bias) {
|
|
return false;
|
|
}
|
|
|
|
|
|
// ---- member variables ---------------------------------------------
|
|
|
|
|
|
private static View[] ZERO = new View[0];
|
|
|
|
private View[] children;
|
|
private int nchildren;
|
|
private short left;
|
|
private short right;
|
|
private short top;
|
|
private short bottom;
|
|
private Rectangle childAlloc;
|
|
}
|