/*
* 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.
*/
/**
* <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
*/
/**
* Constructs a <code>CompositeView</code> for the given element.
*
* @param elem the element this view is responsible for
*/
super(elem);
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
*/
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) {
for (int i = 0; i < n; i++) {
}
}
}
// --- 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
*/
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>
*/
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)
*/
// make sure an array exists
}
// update parent reference on removed views
// in FlowView.java view might be referenced
// from two super-views as a child. see logicalView
}
}
// update the array
// need to grow the array
} else {
// patch the existing array
}
// update parent reference on added views
}
}
/**
* 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
*/
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
*/
return null;
}
testPos < v.getEndOffset()) {
if (childShape == null) {
// We are likely invalid, fail.
return null;
}
if(++vIndex < getViewCount()) {
}
}
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 {
return a;
}
return a;
}
// Range contained in one view
}
// Straddles some views.
int viewCount = getViewCount();
int counter = 0;
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 == v0) {
getBounds();
}
else {
}
// Views entirely covered by range.
}
// End view.
}
else {
}
}
else {
}
}
return retRect;
}
counter++;
}
}
/**
* 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
*/
// point is before the range represented
int retValue = -1;
try {
} catch (BadLocationException ble) { }
catch (IllegalArgumentException iae) { }
if(retValue == -1) {
retValue = getStartOffset();
}
return retValue;
// point is after the range represented.
int retValue = -1;
try {
} catch (BadLocationException ble) { }
catch (IllegalArgumentException iae) { }
if(retValue == -1) {
// NOTE: this could actually use end offset with backward.
}
return retValue;
} else {
// locate the child and pass along the request
if (v != null) {
}
}
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}.
*
* @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>
* <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
* @exception IllegalArgumentException if <code>direction</code> is invalid
*/
throws BadLocationException {
switch (direction) {
case NORTH:
biasRet);
case SOUTH:
biasRet);
case EAST:
biasRet);
case WEST:
biasRet);
default:
}
}
/**
* 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
*/
pos -= 1;
}
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
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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.
*/
/**
* 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
*/
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
*/
}
/**
* 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>
*/
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.
if (a instanceof Rectangle) {
} else {
}
childAlloc.x += getLeftInset();
childAlloc.y += getTopInset();
return childAlloc;
}
return null;
}
/**
* Sets the insets from the paragraph attributes specified in
* the given attributes.
*
* @param attr the attributes
*/
// 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.
}
/**
* 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
*/
}
/**
* 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
*/
throws BadLocationException {
return Utilities.getNextVisualPositionFrom(
}
/**
* 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
*/
Shape a,
int direction,
throws BadLocationException {
return Utilities.getNextVisualPositionFrom(
}
/**
* 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
*/
return false;
}
// ---- member variables ---------------------------------------------
private int nchildren;
private short left;
private short right;
private short top;
private short bottom;
}