aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/text/AsyncBoxView.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/text/AsyncBoxView.java')
-rw-r--r--libjava/classpath/javax/swing/text/AsyncBoxView.java1480
1 files changed, 0 insertions, 1480 deletions
diff --git a/libjava/classpath/javax/swing/text/AsyncBoxView.java b/libjava/classpath/javax/swing/text/AsyncBoxView.java
deleted file mode 100644
index aca77aa..0000000
--- a/libjava/classpath/javax/swing/text/AsyncBoxView.java
+++ /dev/null
@@ -1,1480 +0,0 @@
-/* AsyncBoxView.java -- A box view that performs layout asynchronously
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath 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 for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package javax.swing.text;
-
-import java.awt.Component;
-import java.awt.Graphics;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.util.ArrayList;
-
-import javax.swing.event.DocumentEvent;
-import javax.swing.text.Position.Bias;
-
-/**
- * A {@link View} implementation that lays out its child views in a box, either
- * vertically or horizontally. The difference to {@link BoxView} is that the
- * layout is performed in an asynchronous manner. This helps to keep the
- * eventqueue free from non-GUI related tasks.
- *
- * This view is currently not used in standard text components. In order to
- * use it you would have to implement a special {@link EditorKit} with a
- * {@link ViewFactory} that returns this view. For example:
- *
- * <pre>
- * static class AsyncEditorKit extends StyledEditorKit implements ViewFactory
- * {
- * public View create(Element el)
- * {
- * if (el.getName().equals(AbstractDocument.SectionElementName))
- * return new AsyncBoxView(el, View.Y_AXIS);
- * return super.getViewFactory().create(el);
- * }
- * public ViewFactory getViewFactory() {
- * return this;
- * }
- * }
- * </pre>
- *
- * @author Roman Kennke (kennke@aicas.com)
- *
- * @since 1.3
- */
-public class AsyncBoxView
- extends View
-{
-
- /**
- * Manages the effective position of child views. That keeps the visible
- * layout stable while the AsyncBoxView might be changing until the layout
- * thread decides to publish the new layout.
- */
- public class ChildLocator
- {
-
- /**
- * The last valid location.
- */
- protected ChildState lastValidOffset;
-
- /**
- * The last allocation.
- */
- protected Rectangle lastAlloc;
-
- /**
- * A Rectangle used for child allocation calculation to avoid creation
- * of lots of garbage Rectangle objects.
- */
- protected Rectangle childAlloc;
-
- /**
- * Creates a new ChildLocator.
- */
- public ChildLocator()
- {
- lastAlloc = new Rectangle();
- childAlloc = new Rectangle();
- }
-
- /**
- * Receives notification that a child has changed. This is called by
- * child state objects that have changed it's major span.
- *
- * This sets the {@link #lastValidOffset} field to <code>cs</code> if
- * the new child state's view start offset is smaller than the start offset
- * of the current child state's view or when <code>lastValidOffset</code>
- * is <code>null</code>.
- *
- * @param cs the child state object that has changed
- */
- public synchronized void childChanged(ChildState cs)
- {
- if (lastValidOffset == null
- || cs.getChildView().getStartOffset()
- < lastValidOffset.getChildView().getStartOffset())
- {
- lastValidOffset = cs;
- }
- }
-
- /**
- * Returns the view index of the view that occupies the specified area, or
- * <code>-1</code> if there is no such child view.
- *
- * @param x the x coordinate (relative to <code>a</code>)
- * @param y the y coordinate (relative to <code>a</code>)
- * @param a the current allocation of this view
- *
- * @return the view index of the view that occupies the specified area, or
- * <code>-1</code> if there is no such child view
- */
- public int getViewIndexAtPoint(float x, float y, Shape a)
- {
- setAllocation(a);
- float targetOffset = (getMajorAxis() == X_AXIS) ? x - lastAlloc.x
- : y - lastAlloc.y;
- int index = getViewIndexAtVisualOffset(targetOffset);
- return index;
- }
-
- /**
- * Returns the current allocation for a child view. This updates the
- * offsets for all children <em>before</em> the requested child view.
- *
- * @param index the index of the child view
- * @param a the current allocation of this view
- *
- * @return the current allocation for a child view
- */
- public synchronized Shape getChildAllocation(int index, Shape a)
- {
- if (a == null)
- return null;
- setAllocation(a);
- ChildState cs = getChildState(index);
- if (cs.getChildView().getStartOffset()
- > lastValidOffset.getChildView().getStartOffset())
- {
- updateChildOffsetsToIndex(index);
- }
- Shape ca = getChildAllocation(index);
- return ca;
- }
-
- /**
- * Paints all child views.
- *
- * @param g the graphics context to use
- */
- public synchronized void paintChildren(Graphics g)
- {
- Rectangle clip = g.getClipBounds();
- float targetOffset = (getMajorAxis() == X_AXIS) ? clip.x - lastAlloc.x
- : clip.y - lastAlloc.y;
- int index = getViewIndexAtVisualOffset(targetOffset);
- int n = getViewCount();
- float offs = getChildState(index).getMajorOffset();
- for (int i = index; i < n; i++)
- {
- ChildState cs = getChildState(i);
- cs.setMajorOffset(offs);
- Shape ca = getChildAllocation(i);
- if (ca.intersects(clip))
- {
- synchronized (cs)
- {
- View v = cs.getChildView();
- v.paint(g, ca);
- }
- }
- else
- {
- // done painting intersection
- break;
- }
- offs += cs.getMajorSpan();
- }
- }
-
- /**
- * Returns the current allocation of the child view with the specified
- * index. Note that this will <em>not</em> update any location information.
- *
- * @param index the index of the requested child view
- *
- * @return the current allocation of the child view with the specified
- * index
- */
- protected Shape getChildAllocation(int index)
- {
- ChildState cs = getChildState(index);
- if (! cs.isLayoutValid())
- cs.run();
-
- if (getMajorAxis() == X_AXIS)
- {
- childAlloc.x = lastAlloc.x + (int) cs.getMajorOffset();
- childAlloc.y = lastAlloc.y + (int) cs.getMinorOffset();
- childAlloc.width = (int) cs.getMajorSpan();
- childAlloc.height = (int) cs.getMinorSpan();
- }
- else
- {
- childAlloc.y = lastAlloc.y + (int) cs.getMajorOffset();
- childAlloc.x = lastAlloc.x + (int) cs.getMinorOffset();
- childAlloc.height = (int) cs.getMajorSpan();
- childAlloc.width = (int) cs.getMinorSpan();
- }
- return childAlloc;
- }
-
- /**
- * Sets the current allocation for this view.
- *
- * @param a the allocation to set
- */
- protected void setAllocation(Shape a)
- {
- if (a instanceof Rectangle)
- lastAlloc.setBounds((Rectangle) a);
- else
- lastAlloc.setBounds(a.getBounds());
-
- setSize(lastAlloc.width, lastAlloc.height);
- }
-
- /**
- * Returns the index of the view at the specified offset along the major
- * layout axis.
- *
- * @param targetOffset the requested offset
- *
- * @return the index of the view at the specified offset along the major
- * layout axis
- */
- protected int getViewIndexAtVisualOffset(float targetOffset)
- {
- int n = getViewCount();
- if (n > 0)
- {
- if (lastValidOffset == null)
- lastValidOffset = getChildState(0);
- if (targetOffset > majorSpan)
- return 0;
- else if (targetOffset > lastValidOffset.getMajorOffset())
- return updateChildOffsets(targetOffset);
- else
- {
- float offs = 0f;
- for (int i = 0; i < n; i++)
- {
- ChildState cs = getChildState(i);
- float nextOffs = offs + cs.getMajorSpan();
- if (targetOffset < nextOffs)
- return i;
- offs = nextOffs;
- }
- }
- }
- return n - 1;
- }
-
- /**
- * Updates all the child view offsets up to the specified targetOffset.
- *
- * @param targetOffset the offset up to which the child view offsets are
- * updated
- *
- * @return the index of the view at the specified offset
- */
- private int updateChildOffsets(float targetOffset)
- {
- int n = getViewCount();
- int targetIndex = n - 1;
- int pos = lastValidOffset.getChildView().getStartOffset();
- int startIndex = getViewIndexAtPosition(pos, Position.Bias.Forward);
- float start = lastValidOffset.getMajorOffset();
- float lastOffset = start;
- for (int i = startIndex; i < n; i++)
- {
- ChildState cs = getChildState(i);
- cs.setMajorOffset(lastOffset);
- lastOffset += cs.getMajorSpan();
- if (targetOffset < lastOffset)
- {
- targetIndex = i;
- lastValidOffset = cs;
- break;
- }
- }
- return targetIndex;
- }
-
- /**
- * Updates the offsets of the child views up to the specified index.
- *
- * @param index the index up to which the offsets are updated
- */
- private void updateChildOffsetsToIndex(int index)
- {
- int pos = lastValidOffset.getChildView().getStartOffset();
- int startIndex = getViewIndexAtPosition(pos, Position.Bias.Forward);
- float lastOffset = lastValidOffset.getMajorOffset();
- for (int i = startIndex; i <= index; i++)
- {
- ChildState cs = getChildState(i);
- cs.setMajorOffset(lastOffset);
- lastOffset += cs.getMajorSpan();
- }
- }
- }
-
- /**
- * Represents the layout state of a child view.
- */
- public class ChildState
- implements Runnable
- {
-
- /**
- * The child view for this state record.
- */
- private View childView;
-
- /**
- * Indicates if the minor axis requirements of this child view are valid
- * or not.
- */
- private boolean minorValid;
-
- /**
- * Indicates if the major axis requirements of this child view are valid
- * or not.
- */
- private boolean majorValid;
-
- /**
- * Indicates if the current child size is valid. This is package private
- * to avoid synthetic accessor method.
- */
- boolean childSizeValid;
-
- /**
- * The child views minimumSpan. This is package private to avoid accessor
- * method.
- */
- float minimum;
-
- /**
- * The child views preferredSpan. This is package private to avoid accessor
- * method.
- */
- float preferred;
-
- /**
- * The current span of the child view along the major axis.
- */
- private float majorSpan;
-
- /**
- * The current offset of the child view along the major axis.
- */
- private float majorOffset;
-
- /**
- * The current span of the child view along the minor axis.
- */
- private float minorSpan;
-
- /**
- * The current offset of the child view along the major axis.
- */
- private float minorOffset;
-
- /**
- * The child views maximumSpan.
- */
- private float maximum;
-
- /**
- * Creates a new <code>ChildState</code> object for the specified child
- * view.
- *
- * @param view the child view for which to create the state record
- */
- public ChildState(View view)
- {
- childView = view;
- }
-
- /**
- * Returns the child view for which this <code>ChildState</code> represents
- * the layout state.
- *
- * @return the child view for this child state object
- */
- public View getChildView()
- {
- return childView;
- }
-
- /**
- * Returns <code>true</code> if the current layout information is valid,
- * <code>false</code> otherwise.
- *
- * @return <code>true</code> if the current layout information is valid,
- * <code>false</code> otherwise
- */
- public boolean isLayoutValid()
- {
- return minorValid && majorValid && childSizeValid;
- }
-
- /**
- * Performs the layout update for the child view managed by this
- * <code>ChildState</code>.
- */
- public void run()
- {
- Document doc = getDocument();
- if (doc instanceof AbstractDocument)
- {
- AbstractDocument abstractDoc = (AbstractDocument) doc;
- abstractDoc.readLock();
- }
-
- try
- {
-
- if (!(minorValid && majorValid && childSizeValid)
- && childView.getParent() == AsyncBoxView.this)
- {
- synchronized(AsyncBoxView.this)
- {
- changing = this;
- }
- update();
- synchronized(AsyncBoxView.this)
- {
- changing = null;
- }
- // Changing the major axis may cause the minor axis
- // requirements to have changed, so we need to do this again.
- update();
- }
- }
- finally
- {
- if (doc instanceof AbstractDocument)
- {
- AbstractDocument abstractDoc = (AbstractDocument) doc;
- abstractDoc.readUnlock();
- }
- }
- }
-
- /**
- * Performs the actual update after the run methods has made its checks
- * and locked the document.
- */
- private void update()
- {
- int majorAxis = getMajorAxis();
- boolean minorUpdated = false;
- synchronized (this)
- {
- if (! minorValid)
- {
- int minorAxis = getMinorAxis();
- minimum = childView.getMinimumSpan(minorAxis);
- preferred = childView.getPreferredSpan(minorAxis);
- maximum = childView.getMaximumSpan(minorAxis);
- minorValid = true;
- minorUpdated = true;
- }
- }
- if (minorUpdated)
- minorRequirementChange(this);
-
- boolean majorUpdated = false;
- float delta = 0.0F;
- synchronized (this)
- {
- if (! majorValid)
- {
- float oldSpan = majorSpan;
- majorSpan = childView.getPreferredSpan(majorAxis);
- delta = majorSpan - oldSpan;
- majorValid = true;
- majorUpdated = true;
- }
- }
- if (majorUpdated)
- {
- majorRequirementChange(this, delta);
- locator.childChanged(this);
- }
-
- synchronized (this)
- {
- if (! childSizeValid)
- {
- float w;
- float h;
- if (majorAxis == X_AXIS)
- {
- w = majorSpan;
- h = getMinorSpan();
- }
- else
- {
- w = getMinorSpan();
- h = majorSpan;
- }
- childSizeValid = true;
- childView.setSize(w, h);
- }
- }
- }
-
- /**
- * Returns the span of the child view along the minor layout axis.
- *
- * @return the span of the child view along the minor layout axis
- */
- public float getMinorSpan()
- {
- float retVal;
- if (maximum < minorSpan)
- retVal = maximum;
- else
- retVal = Math.max(minimum, minorSpan);
- return retVal;
- }
-
- /**
- * Returns the offset of the child view along the minor layout axis.
- *
- * @return the offset of the child view along the minor layout axis
- */
- public float getMinorOffset()
- {
- float retVal;
- if (maximum < minorSpan)
- {
- float align = childView.getAlignment(getMinorAxis());
- retVal = ((minorSpan - maximum) * align);
- }
- else
- retVal = 0f;
-
- return retVal;
- }
-
- /**
- * Returns the span of the child view along the major layout axis.
- *
- * @return the span of the child view along the major layout axis
- */
-
- public float getMajorSpan()
- {
- return majorSpan;
- }
-
- /**
- * Returns the offset of the child view along the major layout axis.
- *
- * @return the offset of the child view along the major layout axis
- */
- public float getMajorOffset()
- {
- return majorOffset;
- }
-
- /**
- * Sets the offset of the child view along the major layout axis. This
- * should only be called by the ChildLocator of that child view.
- *
- * @param offset the offset to set
- */
- public void setMajorOffset(float offset)
- {
- majorOffset = offset;
- }
-
- /**
- * Mark the preferences changed for that child. This forwards to
- * {@link AsyncBoxView#preferenceChanged}.
- *
- * @param width <code>true</code> if the width preference has changed
- * @param height <code>true</code> if the height preference has changed
- */
- public void preferenceChanged(boolean width, boolean height)
- {
- if (getMajorAxis() == X_AXIS)
- {
- if (width)
- majorValid = false;
- if (height)
- minorValid = false;
- }
- else
- {
- if (width)
- minorValid = false;
- if (height)
- majorValid = false;
- }
- childSizeValid = false;
- }
- }
-
- /**
- * Flushes the requirements changes upwards asynchronously.
- */
- private class FlushTask implements Runnable
- {
- /**
- * Starts the flush task. This obtains a readLock on the document
- * and then flushes all the updates using
- * {@link AsyncBoxView#flushRequirementChanges()} after updating the
- * requirements.
- */
- public void run()
- {
- try
- {
- // Acquire a lock on the document.
- Document doc = getDocument();
- if (doc instanceof AbstractDocument)
- {
- AbstractDocument abstractDoc = (AbstractDocument) doc;
- abstractDoc.readLock();
- }
-
- int n = getViewCount();
- if (minorChanged && (n > 0))
- {
- LayoutQueue q = getLayoutQueue();
- ChildState min = getChildState(0);
- ChildState pref = getChildState(0);
- for (int i = 1; i < n; i++)
- {
- ChildState cs = getChildState(i);
- if (cs.minimum > min.minimum)
- min = cs;
- if (cs.preferred > pref.preferred)
- pref = cs;
- }
- synchronized (AsyncBoxView.this)
- {
- minReq = min;
- prefReq = pref;
- }
- }
-
- flushRequirementChanges();
- }
- finally
- {
- // Release the lock on the document.
- Document doc = getDocument();
- if (doc instanceof AbstractDocument)
- {
- AbstractDocument abstractDoc = (AbstractDocument) doc;
- abstractDoc.readUnlock();
- }
- }
- }
-
- }
-
- /**
- * The major layout axis.
- */
- private int majorAxis;
-
- /**
- * The top inset.
- */
- private float topInset;
-
- /**
- * The bottom inset.
- */
- private float bottomInset;
-
- /**
- * The left inset.
- */
- private float leftInset;
-
- /**
- * Indicates if the major span should be treated as beeing estimated or not.
- */
- private boolean estimatedMajorSpan;
-
- /**
- * The right inset.
- */
- private float rightInset;
-
- /**
- * The children and their layout statistics.
- */
- private ArrayList childStates;
-
- /**
- * The currently changing child state. May be null if there is no child state
- * updating at the moment. This is package private to avoid a synthetic
- * accessor method inside ChildState.
- */
- ChildState changing;
-
- /**
- * Represents the minimum requirements. This is used in
- * {@link #getMinimumSpan(int)}.
- */
- ChildState minReq;
-
- /**
- * Represents the minimum requirements. This is used in
- * {@link #getPreferredSpan(int)}.
- */
- ChildState prefReq;
-
- /**
- * Indicates that the major axis requirements have changed.
- */
- private boolean majorChanged;
-
- /**
- * Indicates that the minor axis requirements have changed. This is package
- * private to avoid synthetic accessor method.
- */
- boolean minorChanged;
-
- /**
- * The current span along the major layout axis. This is package private to
- * avoid synthetic accessor method.
- */
- float majorSpan;
-
- /**
- * The current span along the minor layout axis. This is package private to
- * avoid synthetic accessor method.
- */
- float minorSpan;
-
- /**
- * This tasked is placed on the layout queue to flush updates up to the
- * parent view.
- */
- private Runnable flushTask;
-
- /**
- * The child locator for this view.
- */
- protected ChildLocator locator;
-
- /**
- * Creates a new <code>AsyncBoxView</code> that represents the specified
- * element and layouts its children along the specified axis.
- *
- * @param elem the element
- * @param axis the layout axis
- */
- public AsyncBoxView(Element elem, int axis)
- {
- super(elem);
- majorAxis = axis;
- childStates = new ArrayList();
- flushTask = new FlushTask();
- locator = new ChildLocator();
- minorSpan = Short.MAX_VALUE;
- }
-
- /**
- * Returns the major layout axis.
- *
- * @return the major layout axis
- */
- public int getMajorAxis()
- {
- return majorAxis;
- }
-
- /**
- * Returns the minor layout axis, that is the axis orthogonal to the major
- * layout axis.
- *
- * @return the minor layout axis
- */
- public int getMinorAxis()
- {
- return majorAxis == X_AXIS ? Y_AXIS : X_AXIS;
- }
-
- /**
- * Returns the view at the specified <code>index</code>.
- *
- * @param index the index of the requested child view
- *
- * @return the view at the specified <code>index</code>
- */
- public View getView(int index)
- {
- View view = null;
- synchronized(childStates)
- {
- if ((index >= 0) && (index < childStates.size()))
- {
- ChildState cs = (ChildState) childStates.get(index);
- view = cs.getChildView();
- }
- }
- return view;
- }
-
- /**
- * Returns the number of child views.
- *
- * @return the number of child views
- */
- public int getViewCount()
- {
- synchronized(childStates)
- {
- return childStates.size();
- }
- }
-
- /**
- * Returns the view index of the child view that represents the specified
- * model position.
- *
- * @param pos the model position for which we search the view index
- * @param bias the bias
- *
- * @return the view index of the child view that represents the specified
- * model position
- */
- public int getViewIndex(int pos, Position.Bias bias)
- {
- int retVal = -1;
-
- if (bias == Position.Bias.Backward)
- pos = Math.max(0, pos - 1);
-
- // TODO: A possible optimization would be to implement a binary search
- // here.
- int numChildren = childStates.size();
- if (numChildren > 0)
- {
- for (int i = 0; i < numChildren; ++i)
- {
- View child = ((ChildState) childStates.get(i)).getChildView();
- if (child.getStartOffset() <= pos && child.getEndOffset() > pos)
- {
- retVal = i;
- break;
- }
- }
- }
- return retVal;
- }
-
- /**
- * Returns the top inset.
- *
- * @return the top inset
- */
- public float getTopInset()
- {
- return topInset;
- }
-
- /**
- * Sets the top inset.
- *
- * @param top the top inset
- */
- public void setTopInset(float top)
- {
- topInset = top;
- }
-
- /**
- * Returns the bottom inset.
- *
- * @return the bottom inset
- */
- public float getBottomInset()
- {
- return bottomInset;
- }
-
- /**
- * Sets the bottom inset.
- *
- * @param bottom the bottom inset
- */
- public void setBottomInset(float bottom)
- {
- bottomInset = bottom;
- }
-
- /**
- * Returns the left inset.
- *
- * @return the left inset
- */
- public float getLeftInset()
- {
- return leftInset;
- }
-
- /**
- * Sets the left inset.
- *
- * @param left the left inset
- */
- public void setLeftInset(float left)
- {
- leftInset = left;
- }
-
- /**
- * Returns the right inset.
- *
- * @return the right inset
- */
- public float getRightInset()
- {
- return rightInset;
- }
-
- /**
- * Sets the right inset.
- *
- * @param right the right inset
- */
- public void setRightInset(float right)
- {
- rightInset = right;
- }
-
- /**
- * Loads the child views of this view. This is triggered by
- * {@link #setParent(View)}.
- *
- * @param f the view factory to build child views with
- */
- protected void loadChildren(ViewFactory f)
- {
- 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);
- }
- }
-
- /**
- * Returns the span along an axis that is taken up by the insets.
- *
- * @param axis the axis
- *
- * @return the span along an axis that is taken up by the insets
- *
- * @since 1.4
- */
- protected float getInsetSpan(int axis)
- {
- float span;
- if (axis == X_AXIS)
- span = leftInset + rightInset;
- else
- span = topInset + bottomInset;
- return span;
- }
-
- /**
- * Sets the <code>estimatedMajorSpan</code> property that determines if
- * the major span should be treated as beeing estimated.
- *
- * @param estimated if the major span should be treated as estimated or not
- *
- * @since 1.4
- */
- protected void setEstimatedMajorSpan(boolean estimated)
- {
- estimatedMajorSpan = estimated;
- }
-
- /**
- * Determines whether the major span should be treated as estimated or as
- * beeing accurate.
- *
- * @return <code>true</code> if the major span should be treated as
- * estimated, <code>false</code> if the major span should be treated
- * as accurate
- *
- * @since 1.4
- */
- protected boolean getEstimatedMajorSpan()
- {
- return estimatedMajorSpan;
- }
-
- /**
- * Receives notification from the child states that the requirements along
- * the minor axis have changed.
- *
- * @param cs the child state from which this notification is messaged
- */
- protected synchronized void minorRequirementChange(ChildState cs)
- {
- minorChanged = true;
- }
-
- /**
- * Receives notification from the child states that the requirements along
- * the major axis have changed.
- *
- * @param cs the child state from which this notification is messaged
- */
- protected void majorRequirementChange(ChildState cs, float delta)
- {
- if (! estimatedMajorSpan)
- majorSpan += delta;
- majorChanged = true;
- }
-
- /**
- * Sets the parent for this view. This calls loadChildren if
- * <code>parent</code> is not <code>null</code> and there have not been any
- * child views initializes.
- *
- * @param parent the new parent view; <code>null</code> if this view is
- * removed from the view hierarchy
- *
- * @see View#setParent(View)
- */
- public void setParent(View parent)
- {
- super.setParent(parent);
- if ((parent != null) && (getViewCount() == 0))
- {
- ViewFactory f = getViewFactory();
- loadChildren(f);
- }
- }
-
- /**
- * Sets the size of this view. This is ususally called before {@link #paint}
- * is called to make sure the view has a valid layout.
- *
- * This implementation queues layout requests for every child view if the
- * minor axis span has changed. (The major axis span is requested to never
- * change for this view).
- *
- * @param width the width of the view
- * @param height the height of the view
- */
- public void setSize(float width, float height)
- {
- float targetSpan;
- if (majorAxis == X_AXIS)
- targetSpan = height - getTopInset() - getBottomInset();
- else
- targetSpan = width - getLeftInset() - getRightInset();
-
- if (targetSpan != minorSpan)
- {
- minorSpan = targetSpan;
-
- int n = getViewCount();
- LayoutQueue q = getLayoutQueue();
- for (int i = 0; i < n; i++)
- {
- ChildState cs = getChildState(i);
- cs.childSizeValid = false;
- q.addTask(cs);
- }
- q.addTask(flushTask);
- }
- }
-
- /**
- * Replaces child views with new child views.
- *
- * This creates ChildState objects for all the new views and adds layout
- * requests for them to the layout queue.
- *
- * @param offset the offset at which to remove/insert
- * @param length the number of child views to remove
- * @param views the new child views to insert
- */
- public void replace(int offset, int length, View[] views)
- {
- synchronized(childStates)
- {
- LayoutQueue q = getLayoutQueue();
- for (int i = 0; i < length; i++)
- childStates.remove(offset);
-
- for (int i = views.length - 1; i >= 0; i--)
- childStates.add(offset, createChildState(views[i]));
-
- // We need to go through the new child states _after_ they have been
- // added to the childStates list, otherwise the layout tasks may find
- // an incomplete child list. That means we have to loop through
- // them again, but what else can we do?
- if (views.length != 0)
- {
- for (int i = 0; i < views.length; i++)
- {
- ChildState cs = (ChildState) childStates.get(i + offset);
- cs.getChildView().setParent(this);
- q.addTask(cs);
- }
- q.addTask(flushTask);
- }
- }
- }
-
- /**
- * Paints the view. This requests the {@link ChildLocator} to paint the views
- * after setting the allocation on it.
- *
- * @param g the graphics context to use
- * @param s the allocation for this view
- */
- public void paint(Graphics g, Shape s)
- {
- synchronized (locator)
- {
- locator.setAllocation(s);
- locator.paintChildren(g);
- }
- }
-
- /**
- * Returns the preferred span of this view along the specified layout axis.
- *
- * @return the preferred span of this view along the specified layout axis
- */
- public float getPreferredSpan(int axis)
- {
- float retVal;
- if (majorAxis == axis)
- retVal = majorSpan;
-
- else if (prefReq != null)
- {
- View child = prefReq.getChildView();
- retVal = child.getPreferredSpan(axis);
- }
-
- // If we have no layout information yet, then return insets + 30 as
- // an estimation.
- else
- {
- if (axis == X_AXIS)
- retVal = getLeftInset() + getRightInset() + 30;
- else
- retVal = getTopInset() + getBottomInset() + 30;
- }
- return retVal;
- }
-
- /**
- * Maps a model location to view coordinates.
- *
- * @param pos the model location
- * @param a the current allocation of this view
- * @param b the bias
- *
- * @return the view allocation for the specified model location
- */
- public Shape modelToView(int pos, Shape a, Bias b)
- throws BadLocationException
- {
- int index = getViewIndexAtPosition(pos, b);
- Shape ca = locator.getChildAllocation(index, a);
-
- ChildState cs = getChildState(index);
- synchronized (cs)
- {
- View cv = cs.getChildView();
- Shape v = cv.modelToView(pos, ca, b);
- return v;
- }
- }
-
- /**
- * Maps view coordinates to a model location.
- *
- * @param x the x coordinate (relative to <code>a</code>)
- * @param y the y coordinate (relative to <code>a</code>)
- * @param b holds the bias of the model location on method exit
- *
- * @return the model location for the specified view location
- */
- public int viewToModel(float x, float y, Shape a, Bias[] b)
- {
- int pos;
- int index;
- Shape ca;
-
- synchronized (locator)
- {
- index = locator.getViewIndexAtPoint(x, y, a);
- ca = locator.getChildAllocation(index, a);
- }
-
- ChildState cs = getChildState(index);
- synchronized (cs)
- {
- View v = cs.getChildView();
- pos = v.viewToModel(x, y, ca, b);
- }
- return pos;
- }
-
- /**
- * Returns the child allocation for the child view with the specified
- * <code>index</code>.
- *
- * @param index the index of the child view
- * @param a the current allocation of this view
- *
- * @return the allocation of the child view
- */
- public Shape getChildAllocation(int index, Shape a)
- {
- Shape ca = locator.getChildAllocation(index, a);
- return ca;
- }
-
- /**
- * Returns the maximum span of this view along the specified axis.
- * This is implemented to return the <code>preferredSpan</code> for the
- * major axis (that means the box can't be resized along the major axis) and
- * {@link Short#MAX_VALUE} for the minor axis.
- *
- * @param axis the axis
- *
- * @return the maximum span of this view along the specified axis
- */
- public float getMaximumSpan(int axis)
- {
- float max;
- if (axis == majorAxis)
- max = getPreferredSpan(axis);
- else
- max = Short.MAX_VALUE;
- return max;
- }
-
- /**
- * Returns the minimum span along the specified axis.
- */
- public float getMinimumSpan(int axis)
- {
- float min;
- if (axis == majorAxis)
- min = getPreferredSpan(axis);
- else
- {
- if (minReq != null)
- {
- View child = minReq.getChildView();
- min = child.getMinimumSpan(axis);
- }
- else
- {
- // No layout information yet. Return insets + 5 as some kind of
- // estimation.
- if (axis == X_AXIS)
- min = getLeftInset() + getRightInset() + 5;
- else
- min = getTopInset() + getBottomInset() + 5;
- }
- }
- return min;
- }
-
- /**
- * Receives notification that one of the child views has changed its
- * layout preferences along one or both axis.
- *
- * This queues a layout request for that child view if necessary.
- *
- * @param view the view that has changed its preferences
- * @param width <code>true</code> if the width preference has changed
- * @param height <code>true</code> if the height preference has changed
- */
- public synchronized void preferenceChanged(View view, boolean width,
- boolean height)
- {
- if (view == null)
- getParent().preferenceChanged(this, width, height);
- else
- {
- if (changing != null)
- {
- View cv = changing.getChildView();
- if (cv == view)
- {
- changing.preferenceChanged(width, height);
- return;
- }
- }
- int index = getViewIndexAtPosition(view.getStartOffset(),
- Position.Bias.Forward);
- ChildState cs = getChildState(index);
- cs.preferenceChanged(width, height);
- LayoutQueue q = getLayoutQueue();
- q.addTask(cs);
- q.addTask(flushTask);
- }
- }
-
- /**
- * Updates the layout for this view. This is implemented to trigger
- * {@link ChildLocator#childChanged} for the changed view, if there is
- * any.
- *
- * @param ec the element change, may be <code>null</code> if there were
- * no changes to the element of this view
- * @param e the document event
- * @param a the current allocation of this view
- */
- protected void updateLayout(DocumentEvent.ElementChange ec,
- DocumentEvent e, Shape a)
- {
- if (ec != null)
- {
- int index = Math.max(ec.getIndex() - 1, 0);
- ChildState cs = getChildState(index);
- locator.childChanged(cs);
- }
- }
-
-
- /**
- * Returns the <code>ChildState</code> object associated with the child view
- * at the specified <code>index</code>.
- *
- * @param index the index of the child view for which to query the state
- *
- * @return the child state for the specified child view
- */
- protected ChildState getChildState(int index) {
- synchronized (childStates)
- {
- return (ChildState) childStates.get(index);
- }
- }
-
- /**
- * Returns the <code>LayoutQueue</code> used for layouting the box view.
- * This simply returns {@link LayoutQueue#getDefaultQueue()}.
- *
- * @return the <code>LayoutQueue</code> used for layouting the box view
- */
- protected LayoutQueue getLayoutQueue()
- {
- return LayoutQueue.getDefaultQueue();
- }
-
- /**
- * Returns the child view index of the view that represents the specified
- * position in the document model.
- *
- * @param pos the position in the model
- * @param b the bias
- *
- * @return the child view index of the view that represents the specified
- * position in the document model
- */
- protected synchronized int getViewIndexAtPosition(int pos, Position.Bias b)
- {
- if (b == Position.Bias.Backward)
- pos = Math.max(0, pos - 1);
- Element elem = getElement();
- return elem.getElementIndex(pos);
- }
-
- /**
- * Creates a <code>ChildState</code> object for the specified view.
- *
- * @param v the view for which to create a child state object
- *
- * @return the created child state
- */
- protected ChildState createChildState(View v)
- {
- return new ChildState(v);
- }
-
- /**
- * Flushes the requirements changes upwards to the parent view. This is
- * called from the layout thread.
- */
- protected synchronized void flushRequirementChanges()
- {
- if (majorChanged || minorChanged)
- {
- View p = getParent();
- if (p != null)
- {
- boolean horizontal;
- boolean vertical;
- if (majorAxis == X_AXIS)
- {
- horizontal = majorChanged;
- vertical = minorChanged;
- }
- else
- {
- vertical = majorChanged;
- horizontal = minorChanged;
- }
-
- p.preferenceChanged(this, horizontal, vertical);
- majorChanged = false;
- minorChanged = false;
-
- Component c = getContainer();
- if (c != null)
- c.repaint();
- }
- }
- }
-}