1420 lines · 48.8 KB · Java
RawDownload
                if (cv == child) {                    // size was being changed on the child, no need to                    // queue work for it.                    changing.preferenceChanged(width, height);                    return;                }            }            int index = getViewIndex(child.getStartOffset(),                                     Position.Bias.Forward);            ChildState cs = getChildState(index);            cs.preferenceChanged(width, height);            LayoutQueue q = getLayoutQueue();            q.addTask(cs);            q.addTask(flushTask);        }    }     /**     * Sets the size of the view.  This should cause     * layout of the view if the view caches any layout     * information.     * <p>     * Since the major axis is updated asynchronously and should be     * the sum of the tiled children the call is ignored for the major     * axis.  Since the minor axis is flexible, work is queued to resize     * the children if the minor span changes.     *     * @param width the width >= 0     * @param height the height >= 0     */    public void setSize(float width, float height) {        setSpanOnAxis(X_AXIS, width);        setSpanOnAxis(Y_AXIS, height);    }     /**     * Retrieves the size of the view along an axis.     *     * @param axis may be either <code>View.X_AXIS</code> or     *          <code>View.Y_AXIS</code>     * @return the current span of the view along the given axis, >= 0     */    float getSpanOnAxis(int axis) {        if (axis == getMajorAxis()) {            return majorSpan;        }        return minorSpan;    }     /**     * Sets the size of the view along an axis.  Since the major     * axis is updated asynchronously and should be the sum of the     * tiled children the call is ignored for the major axis.  Since     * the minor axis is flexible, work is queued to resize the     * children if the minor span changes.     *     * @param axis may be either <code>View.X_AXIS</code> or     *          <code>View.Y_AXIS</code>     * @param span the span to layout to >= 0     */    void setSpanOnAxis(int axis, float span) {        float margin = getInsetSpan(axis);        if (axis == getMinorAxis()) {            float targetSpan = span - margin;            if (targetSpan != minorSpan) {                minorSpan = targetSpan;                 // mark all of the ChildState instances as needing to                // resize the child, and queue up work to fix them.                int n = getViewCount();                if (n != 0) {                    LayoutQueue q = getLayoutQueue();                    for (int i = 0; i < n; i++) {                        ChildState cs = getChildState(i);                        cs.childSizeValid = false;                        q.addTask(cs);                    }                    q.addTask(flushTask);                }            }        } else {            // along the major axis the value is ignored            // unless the estimatedMajorSpan property is            // true.            if (estimatedMajorSpan) {                majorSpan = span - margin;            }        }    }     /**     * Render the view using the given allocation and     * rendering surface.     * <p>     * This is implemented to determine whether or not the     * desired region to be rendered (i.e. the unclipped     * area) is up to date or not.  If up-to-date the children     * are rendered.  If not up-to-date, a task to build     * the desired area is placed on the layout queue as     * a high priority task.  This keeps by event thread     * moving by rendering if ready, and postponing until     * a later time if not ready (since paint requests     * can be rescheduled).     *     * @param g the rendering surface to use     * @param alloc the allocated region to render into     * @see View#paint     */    public void paint(Graphics g, Shape alloc) {        synchronized (locator) {            locator.setAllocation(alloc);            locator.paintChildren(g);        }    }     /**     * Determines the preferred span for this view along an     * axis.     *     * @param axis may be either View.X_AXIS or View.Y_AXIS     * @return   the span the view would like to be rendered into >= 0.     *           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.     * @exception IllegalArgumentException for an invalid axis type     */    public float getPreferredSpan(int axis) {        float margin = getInsetSpan(axis);        if (axis == this.axis) {            return majorSpan + margin;        }        if (prefRequest != null) {            View child = prefRequest.getChildView();            return child.getPreferredSpan(axis) + margin;        }         // nothing is known about the children yet        return margin + 30;    }     /**     * Determines the minimum span for this view along an     * axis.     *     * @param axis may be either View.X_AXIS or View.Y_AXIS     * @return  the span the view would like to be rendered into >= 0.     *           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.     * @exception IllegalArgumentException for an invalid axis type     */    public float getMinimumSpan(int axis) {        if (axis == this.axis) {            return getPreferredSpan(axis);        }        if (minRequest != null) {            View child = minRequest.getChildView();            return child.getMinimumSpan(axis);        }         // nothing is known about the children yet        if (axis == X_AXIS) {            return getLeftInset() + getRightInset() + 5;        } else {            return getTopInset() + getBottomInset() + 5;        }    }     /**     * Determines the maximum span for this view along an     * axis.     *     * @param axis may be either View.X_AXIS or View.Y_AXIS     * @return   the span the view would like to be rendered into >= 0.     *           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.     * @exception IllegalArgumentException for an invalid axis type     */    public float getMaximumSpan(int axis) {        if (axis == this.axis) {            return getPreferredSpan(axis);        }        return Integer.MAX_VALUE;    }      /**     * Returns the number of views in this view.  Since     * the default is to not be a composite view this     * returns 0.     *     * @return the number of views >= 0     * @see View#getViewCount     */    public int getViewCount() {        synchronized(stats) {            return stats.size();        }    }     /**     * Gets the nth child view.  Since there are no     * children by default, this returns null.     *     * @param n the number of the view to get, >= 0 && < getViewCount()     * @return the view     */    public View getView(int n) {        ChildState cs = getChildState(n);        if (cs != null) {            return cs.getChildView();        }        return null;    }     /**     * 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 null since the     * default is to not have any child views.     *     * @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) {        Shape ca = locator.getChildAllocation(index, a);        return ca;    }     /**     * Returns the child view index representing the given position in     * the model.  By default a view has no children so this is implemented     * to return -1 to indicate there is no valid child index for any     * position.     *     * @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) {        return getViewIndexAtPosition(pos, b);    }     /**     * 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 the bias toward the previous character or the     *  next character represented by the offset, in case the     *  position is a boundary of two views.     * @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 pos, Shape a, Position.Bias b) throws BadLocationException {        int index = getViewIndex(pos, b);        Shape ca = locator.getChildAllocation(index, a);         // forward to the child view, and make sure we don't        // interact with the layout thread by synchronizing        // on the child state.        ChildState cs = getChildState(index);        synchronized (cs) {            View cv = cs.getChildView();            Shape v = cv.modelToView(pos, ca, b);            return v;        }    }     /**     * Provides a mapping from the view coordinate space to the logical     * coordinate space of the model.  The biasReturn argument will be     * filled in to indicate that the point given is closer to the next     * character in the model or the previous character in the model.     * <p>     * This is expected to be called by the GUI thread, holding a     * read-lock on the associated model.  It is implemented to     * locate the child view and determine it's allocation with a     * lock on the ChildLocator object, and to call viewToModel     * on the child view with a lock on the ChildState object     * to avoid interaction with the layout thread.     *     * @param x the X coordinate >= 0     * @param y the Y coordinate >= 0     * @param a the allocated region to render into     * @return the location within the model that best represents the     *  given point in the view >= 0.  The biasReturn argument will be     * filled in to indicate that the point given is closer to the next     * character in the model or the previous character in the model.     */    public int viewToModel(float x, float y, Shape a, Position.Bias[] biasReturn) {        int pos;    // return position        int index;  // child index to forward to        Shape ca;   // child allocation         // locate the child view and it's allocation so that        // we can forward to it.  Make sure the layout thread        // doesn't change anything by trying to flush changes        // to the parent while the GUI thread is trying to        // find the child and it's allocation.        synchronized (locator) {            index = locator.getViewIndexAtPoint(x, y, a);            ca = locator.getChildAllocation(index, a);        }         // forward to the child view, and make sure we don't        // interact with the layout thread by synchronizing        // on the child state.        ChildState cs = getChildState(index);        synchronized (cs) {            View v = cs.getChildView();            pos = v.viewToModel(x, y, ca, biasReturn);        }        return pos;    }     /**     * 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 one of the following:     *  <ul>     *  <code>SwingConstants.WEST</code>     *  <code>SwingConstants.EAST</code>     *  <code>SwingConstants.NORTH</code>     *  <code>SwingConstants.SOUTH</code>     *  </ul>     * @param biasRet an array contain 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     */    public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,                                         int direction,                                         Position.Bias[] biasRet)                                                  throws BadLocationException {        return Utilities.getNextVisualPositionFrom(                            this, pos, b, a, direction, biasRet);    }     // --- variables -----------------------------------------     /**     * The major axis against which the children are     * tiled.     */    int axis;     /**     * The children and their layout statistics.     */    List<ChildState> stats;     /**     * Current span along the major axis.  This     * is also the value returned by getMinimumSize,     * getPreferredSize, and getMaximumSize along     * the major axis.     */    float majorSpan;     /**     * Is the span along the major axis estimated?     */    boolean estimatedMajorSpan;     /**     * Current span along the minor axis.  This     * is what layout was done against (i.e. things     * are flexible in this direction).     */    float minorSpan;     /**     * Object that manages the offsets of the     * children.  All locking for management of     * child locations is on this object.     */    protected ChildLocator locator;     float topInset;    float bottomInset;    float leftInset;    float rightInset;     ChildState minRequest;    ChildState prefRequest;    boolean majorChanged;    boolean minorChanged;    Runnable flushTask;     /**     * Child that is actively changing size.  This often     * causes a preferenceChanged, so this is a cache to     * possibly speed up the marking the state.  It also     * helps flag an opportunity to avoid adding to flush     * task to the layout queue.     */    ChildState changing;     /**     * A class to manage the effective position of the     * child views in a localized area while changes are     * being made around the localized area.  The AsyncBoxView     * may be continuously changing, but the visible area     * needs to remain fairly stable until the layout thread     * decides to publish an update to the parent.     * @since 1.3     */    public class ChildLocator {         /**         * construct a child locator.         */        public ChildLocator() {            lastAlloc = new Rectangle();            childAlloc = new Rectangle();        }         /**         * Notification that a child changed.  This can effect         * whether or not new offset calculations are needed.         * This is called by a ChildState object that has         * changed it's major span.  This can therefore be         * called by multiple threads.         */        public synchronized void childChanged(ChildState cs) {            if (lastValidOffset == null) {                lastValidOffset = cs;            } else if (cs.getChildView().getStartOffset() <                       lastValidOffset.getChildView().getStartOffset()) {                lastValidOffset = cs;            }        }         /**         * Paint the children that intersect the clip area.         */        public synchronized void paintChildren(Graphics g) {            Rectangle clip = g.getClipBounds();            float targetOffset = (axis == 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 (intersectsClip(ca, clip)) {                    synchronized (cs) {                        View v = cs.getChildView();                        v.paint(g, ca);                    }                } else {                    // done painting intersection                    break;                }                offs += cs.getMajorSpan();            }        }         /**         * Fetch the allocation to use for a child view.         * This will update the offsets for all children         * not yet updated before the given index.         */        public synchronized Shape getChildAllocation(int index, Shape a) {            if (a == null) {                return null;            }            setAllocation(a);            ChildState cs = getChildState(index);            if (lastValidOffset == null) {                lastValidOffset = getChildState(0);            }            if (cs.getChildView().getStartOffset() >                lastValidOffset.getChildView().getStartOffset()) {                // offsets need to be updated                updateChildOffsetsToIndex(index);            }            Shape ca = getChildAllocation(index);            return ca;        } 

Lines 501–1000 of 1420. Previous lines