/* * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. */package javax.swing.text; import java.awt.*;import java.util.Vector;import javax.swing.event.*;import javax.swing.SizeRequirements; /** * A View that tries to flow it's children into some * partially constrained space. This can be used to * build things like paragraphs, pages, etc. The * flow is made up of the following pieces of functionality. * <ul> * <li>A logical set of child views, which as used as a * layout pool from which a physical view is formed. * <li>A strategy for translating the logical view to * a physical (flowed) view. * <li>Constraints for the strategy to work against. * <li>A physical structure, that represents the flow. * The children of this view are where the pieces of * of the logical views are placed to create the flow. * </ul> * * @author Timothy Prinzing * @see View * @since 1.3 */public abstract class FlowView extends BoxView { /** * Constructs a FlowView for the given element. * * @param elem the element that this view is responsible for * @param axis may be either View.X_AXIS or View.Y_AXIS */ public FlowView(Element elem, int axis) { super(elem, axis); layoutSpan = Integer.MAX_VALUE; strategy = new FlowStrategy(); } /** * Fetches the axis along which views should be * flowed. By default, this will be the axis * orthogonal to the axis along which the flow * rows are tiled (the axis of the default flow * rows themselves). This is typically used * by the <code>FlowStrategy</code>. */ public int getFlowAxis() { if (getAxis() == Y_AXIS) { return X_AXIS; } return Y_AXIS; } /** * Fetch the constraining span to flow against for * the given child index. This is called by the * FlowStrategy while it is updating the flow. * A flow can be shaped by providing different values * for the row constraints. By default, the entire * span inside of the insets along the flow axis * is returned. * * @param index the index of the row being updated. * This should be a value >= 0 and < getViewCount(). * @see #getFlowStart */ public int getFlowSpan(int index) { return layoutSpan; } /** * Fetch the location along the flow axis that the * flow span will start at. This is called by the * FlowStrategy while it is updating the flow. * A flow can be shaped by providing different values * for the row constraints. * @param index the index of the row being updated. * This should be a value >= 0 and < getViewCount(). * @see #getFlowSpan */ public int getFlowStart(int index) { return 0; } /** * Create a View that should be used to hold a * a rows worth of children in a flow. This is * called by the FlowStrategy when new children * are added or removed (i.e. rows are added or * removed) in the process of updating the flow. */ protected abstract View createRow(); // ---- BoxView methods ------------------------------------- /** * Loads all of the children to initialize the view. * This is called by the <code>setParent</code> method. * This is reimplemented to not load any children directly * (as they are created in the process of formatting). * If the layoutPool variable is null, an instance of * LogicalView is created to represent the logical view * that is used in the process of formatting. * * @param f the view factory */ protected void loadChildren(ViewFactory f) { if (layoutPool == null) { layoutPool = new LogicalView(getElement()); } layoutPool.setParent(this); // This synthetic insertUpdate call gives the strategy a chance // to initialize. strategy.insertUpdate(this, null, null); } /** * Fetches the child view index representing the given position in * the model. * * @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) { if (pos >= getStartOffset() && (pos < getEndOffset())) { for (int counter = 0; counter < getViewCount(); counter++) { View v = getView(counter); if(pos >= v.getStartOffset() && pos < v.getEndOffset()) { return counter; } } } return -1; } /** * Lays out the children. If the span along the flow * axis has changed, layout is marked as invalid which * which will cause the superclass behavior to recalculate * the layout along the box axis. The FlowStrategy.layout * method will be called to rebuild the flow rows as * appropriate. If the height of this view changes * (determined by the perferred size along the box axis), * a preferenceChanged is called. Following all of that, * the normal box layout of the superclass is performed. * * @param width the width to lay out against >= 0. This is * the width inside of the inset area. * @param height the height to lay out against >= 0 This * is the height inside of the inset area. */ protected void layout(int width, int height) { final int faxis = getFlowAxis(); int newSpan; if (faxis == X_AXIS) { newSpan = width; } else { newSpan = height; } if (layoutSpan != newSpan) { layoutChanged(faxis); layoutChanged(getAxis()); layoutSpan = newSpan; } // repair the flow if necessary if (! isLayoutValid(faxis)) { final int heightAxis = getAxis(); int oldFlowHeight = (heightAxis == X_AXIS)? getWidth() : getHeight(); strategy.layout(this); int newFlowHeight = (int) getPreferredSpan(heightAxis); if (oldFlowHeight != newFlowHeight) { View p = getParent(); if (p != null) { p.preferenceChanged(this, (heightAxis == X_AXIS), (heightAxis == Y_AXIS)); } // PENDING(shannonh) // Temporary fix for 4250847 // Can be removed when TraversalContext is added Component host = getContainer(); if (host != null) { //nb idk 12/12/2001 host should not be equal to null. We need to add assertion here host.repaint(); } } } super.layout(width, height); } /** * Calculate equirements along the minor axis. This * is implemented to forward the request to the logical * view by calling getMinimumSpan, getPreferredSpan, and * getMaximumSpan on it. */ protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { if (r == null) { r = new SizeRequirements(); } float pref = layoutPool.getPreferredSpan(axis); float min = layoutPool.getMinimumSpan(axis); // Don't include insets, Box.getXXXSpan will include them. r.minimum = (int)min; r.preferred = Math.max(r.minimum, (int) pref); r.maximum = Integer.MAX_VALUE; r.alignment = 0.5f; return r; } // ---- View methods ---------------------------------------------------- /** * Gives notification that something was inserted into the document * in a location that this view is responsible for. * * @param changes the change information from the associated document * @param a the current allocation of the view * @param f the factory to use to rebuild if the view has children * @see View#insertUpdate */ public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) { layoutPool.insertUpdate(changes, a, f); strategy.insertUpdate(this, changes, getInsideAllocation(a)); } /** * Gives notification that something was removed from the document * in a location that this view is responsible for. * * @param changes the change information from the associated document * @param a the current allocation of the view * @param f the factory to use to rebuild if the view has children * @see View#removeUpdate */ public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) { layoutPool.removeUpdate(changes, a, f); strategy.removeUpdate(this, changes, getInsideAllocation(a)); } /** * Gives notification from the document that attributes were changed * in a location that this view is responsible for. * * @param changes the change information from the associated document * @param a the current allocation of the view * @param f the factory to use to rebuild if the view has children * @see View#changedUpdate */ public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory f) { layoutPool.changedUpdate(changes, a, f); strategy.changedUpdate(this, changes, getInsideAllocation(a)); } /** {@inheritDoc} */ public void setParent(View parent) { super.setParent(parent); if (parent == null && layoutPool != null ) { layoutPool.setParent(null); } } // --- variables ----------------------------------------------- /** * Default constraint against which the flow is * created against. */ protected int layoutSpan; /** * These are the views that represent the child elements * of the element this view represents (The logical view * to translate to a physical view). These are not * directly children of this view. These are either * placed into the rows directly or used for the purpose * of breaking into smaller chunks, to form the physical * view. */ protected View layoutPool; /** * The behavior for keeping the flow updated. By * default this is a singleton shared by all instances * of FlowView (FlowStrategy is stateless). Subclasses * can create an alternative strategy, which might keep * state. */ protected FlowStrategy strategy; /** * Strategy for maintaining the physical form * of the flow. The default implementation is * completely stateless, and recalculates the * entire flow if the layout is invalid on the * given FlowView. Alternative strategies can * be implemented by subclassing, and might * perform incrementatal repair to the layout * or alternative breaking behavior. * @since 1.3 */ public static class FlowStrategy { Position damageStart = null; Vector<View> viewBuffer; void addDamage(FlowView fv, int offset) { if (offset >= fv.getStartOffset() && offset < fv.getEndOffset()) { if (damageStart == null || offset < damageStart.getOffset()) { try { damageStart = fv.getDocument().createPosition(offset); } catch (BadLocationException e) { // shouldn't happen since offset is inside view bounds assert(false); } } } } void unsetDamage() { damageStart = null; } /** * Gives notification that something was inserted into the document * in a location that the given flow view is responsible for. The * strategy should update the appropriate changed region (which * depends upon the strategy used for repair). * * @param e the change information from the associated document * @param alloc the current allocation of the view inside of the insets. * This value will be null if the view has not yet been displayed. * @see View#insertUpdate */ public void insertUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { // FlowView.loadChildren() makes a synthetic call into this, // passing null as e if (e != null) { addDamage(fv, e.getOffset()); } if (alloc != null) { Component host = fv.getContainer(); if (host != null) { host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); } } else { fv.preferenceChanged(null, true, true); } } /** * Gives notification that something was removed from the document * in a location that the given flow view is responsible for. * * @param e the change information from the associated document * @param alloc the current allocation of the view inside of the insets. * @see View#removeUpdate */ public void removeUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { addDamage(fv, e.getOffset()); if (alloc != null) { Component host = fv.getContainer(); if (host != null) { host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); } } else { fv.preferenceChanged(null, true, true); } } /** * Gives notification from the document that attributes were changed * in a location that this view is responsible for. * * @param fv the <code>FlowView</code> containing the changes * @param e the <code>DocumentEvent</code> describing the changes * done to the Document * @param alloc Bounds of the View * @see View#changedUpdate */ public void changedUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { addDamage(fv, e.getOffset()); if (alloc != null) { Component host = fv.getContainer(); if (host != null) { host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); } } else { fv.preferenceChanged(null, true, true); } } /** * This method gives flow strategies access to the logical * view of the FlowView. */ protected View getLogicalView(FlowView fv) { return fv.layoutPool; } /** * Update the flow on the given FlowView. By default, this causes * all of the rows (child views) to be rebuilt to match the given * constraints for each row. This is called by a FlowView.layout * to update the child views in the flow. * * @param fv the view to reflow */ public void layout(FlowView fv) { View pool = getLogicalView(fv); int rowIndex, p0; int p1 = fv.getEndOffset(); if (fv.majorAllocValid) { if (damageStart == null) { return; } // In some cases there's no view at position damageStart, so // step back and search again. See 6452106 for details. int offset = damageStart.getOffset(); while ((rowIndex = fv.getViewIndexAtPosition(offset)) < 0) { offset--; } if (rowIndex > 0) { rowIndex--; } p0 = fv.getView(rowIndex).getStartOffset(); } else { rowIndex = 0; p0 = fv.getStartOffset(); } reparentViews(pool, p0); viewBuffer = new Vector<View>(10, 10); int rowCount = fv.getViewCount(); while (p0 < p1) { View row; if (rowIndex >= rowCount) { row = fv.createRow(); fv.append(row); } else { row = fv.getView(rowIndex); } p0 = layoutRow(fv, rowIndex, p0); rowIndex++; } viewBuffer = null; if (rowIndex < rowCount) { fv.replace(rowIndex, rowCount - rowIndex, null); } unsetDamage(); } /** * Creates a row of views that will fit within the * layout span of the row. This is called by the layout method. * This is implemented to fill the row by repeatedly calling * the createView method until the available span has been * exhausted, a forced break was encountered, or the createView * method returned null. If the remaining span was exhaused, * the adjustRow method will be called to perform adjustments * to the row to try and make it fit into the given span. * * @param rowIndex the index of the row to fill in with views. The * row is assumed to be empty on entry. * @param pos The current position in the children ofLines 1–500 of 871. Load more
/* * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. */ package javax.swing.text; import java.awt.*; import java.util.Vector; import javax.swing.event.*; import javax.swing.SizeRequirements; /** * A View that tries to flow it's children into some * partially constrained space. This can be used to * build things like paragraphs, pages, etc. The * flow is made up of the following pieces of functionality. * <ul> * <li>A logical set of child views, which as used as a * layout pool from which a physical view is formed. * <li>A strategy for translating the logical view to * a physical (flowed) view. * <li>Constraints for the strategy to work against. * <li>A physical structure, that represents the flow. * The children of this view are where the pieces of * of the logical views are placed to create the flow. * </ul> * * @author Timothy Prinzing * @see View * @since 1.3 */ public abstract class FlowView extends BoxView { /** * Constructs a FlowView for the given element. * * @param elem the element that this view is responsible for * @param axis may be either View.X_AXIS or View.Y_AXIS */ public FlowView(Element elem, int axis) { super(elem, axis); layoutSpan = Integer.MAX_VALUE; strategy = new FlowStrategy(); } /** * Fetches the axis along which views should be * flowed. By default, this will be the axis * orthogonal to the axis along which the flow * rows are tiled (the axis of the default flow * rows themselves). This is typically used * by the <code>FlowStrategy</code>. */ public int getFlowAxis() { if (getAxis() == Y_AXIS) { return X_AXIS; } return Y_AXIS; } /** * Fetch the constraining span to flow against for * the given child index. This is called by the * FlowStrategy while it is updating the flow. * A flow can be shaped by providing different values * for the row constraints. By default, the entire * span inside of the insets along the flow axis * is returned. * * @param index the index of the row being updated. * This should be a value >= 0 and < getViewCount(). * @see #getFlowStart */ public int getFlowSpan(int index) { return layoutSpan; } /** * Fetch the location along the flow axis that the * flow span will start at. This is called by the * FlowStrategy while it is updating the flow. * A flow can be shaped by providing different values * for the row constraints. * @param index the index of the row being updated. * This should be a value >= 0 and < getViewCount(). * @see #getFlowSpan */ public int getFlowStart(int index) { return 0; } /** * Create a View that should be used to hold a * a rows worth of children in a flow. This is * called by the FlowStrategy when new children * are added or removed (i.e. rows are added or * removed) in the process of updating the flow. */ protected abstract View createRow(); // ---- BoxView methods ------------------------------------- /** * Loads all of the children to initialize the view. * This is called by the <code>setParent</code> method. * This is reimplemented to not load any children directly * (as they are created in the process of formatting). * If the layoutPool variable is null, an instance of * LogicalView is created to represent the logical view * that is used in the process of formatting. * * @param f the view factory */ protected void loadChildren(ViewFactory f) { if (layoutPool == null) { layoutPool = new LogicalView(getElement()); } layoutPool.setParent(this); // This synthetic insertUpdate call gives the strategy a chance // to initialize. strategy.insertUpdate(this, null, null); } /** * Fetches the child view index representing the given position in * the model. * * @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) { if (pos >= getStartOffset() && (pos < getEndOffset())) { for (int counter = 0; counter < getViewCount(); counter++) { View v = getView(counter); if(pos >= v.getStartOffset() && pos < v.getEndOffset()) { return counter; } } } return -1; } /** * Lays out the children. If the span along the flow * axis has changed, layout is marked as invalid which * which will cause the superclass behavior to recalculate * the layout along the box axis. The FlowStrategy.layout * method will be called to rebuild the flow rows as * appropriate. If the height of this view changes * (determined by the perferred size along the box axis), * a preferenceChanged is called. Following all of that, * the normal box layout of the superclass is performed. * * @param width the width to lay out against >= 0. This is * the width inside of the inset area. * @param height the height to lay out against >= 0 This * is the height inside of the inset area. */ protected void layout(int width, int height) { final int faxis = getFlowAxis(); int newSpan; if (faxis == X_AXIS) { newSpan = width; } else { newSpan = height; } if (layoutSpan != newSpan) { layoutChanged(faxis); layoutChanged(getAxis()); layoutSpan = newSpan; } // repair the flow if necessary if (! isLayoutValid(faxis)) { final int heightAxis = getAxis(); int oldFlowHeight = (heightAxis == X_AXIS)? getWidth() : getHeight(); strategy.layout(this); int newFlowHeight = (int) getPreferredSpan(heightAxis); if (oldFlowHeight != newFlowHeight) { View p = getParent(); if (p != null) { p.preferenceChanged(this, (heightAxis == X_AXIS), (heightAxis == Y_AXIS)); } // PENDING(shannonh) // Temporary fix for 4250847 // Can be removed when TraversalContext is added Component host = getContainer(); if (host != null) { //nb idk 12/12/2001 host should not be equal to null. We need to add assertion here host.repaint(); } } } super.layout(width, height); } /** * Calculate equirements along the minor axis. This * is implemented to forward the request to the logical * view by calling getMinimumSpan, getPreferredSpan, and * getMaximumSpan on it. */ protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { if (r == null) { r = new SizeRequirements(); } float pref = layoutPool.getPreferredSpan(axis); float min = layoutPool.getMinimumSpan(axis); // Don't include insets, Box.getXXXSpan will include them. r.minimum = (int)min; r.preferred = Math.max(r.minimum, (int) pref); r.maximum = Integer.MAX_VALUE; r.alignment = 0.5f; return r; } // ---- View methods ---------------------------------------------------- /** * Gives notification that something was inserted into the document * in a location that this view is responsible for. * * @param changes the change information from the associated document * @param a the current allocation of the view * @param f the factory to use to rebuild if the view has children * @see View#insertUpdate */ public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) { layoutPool.insertUpdate(changes, a, f); strategy.insertUpdate(this, changes, getInsideAllocation(a)); } /** * Gives notification that something was removed from the document * in a location that this view is responsible for. * * @param changes the change information from the associated document * @param a the current allocation of the view * @param f the factory to use to rebuild if the view has children * @see View#removeUpdate */ public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) { layoutPool.removeUpdate(changes, a, f); strategy.removeUpdate(this, changes, getInsideAllocation(a)); } /** * Gives notification from the document that attributes were changed * in a location that this view is responsible for. * * @param changes the change information from the associated document * @param a the current allocation of the view * @param f the factory to use to rebuild if the view has children * @see View#changedUpdate */ public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory f) { layoutPool.changedUpdate(changes, a, f); strategy.changedUpdate(this, changes, getInsideAllocation(a)); } /** {@inheritDoc} */ public void setParent(View parent) { super.setParent(parent); if (parent == null && layoutPool != null ) { layoutPool.setParent(null); } } // --- variables ----------------------------------------------- /** * Default constraint against which the flow is * created against. */ protected int layoutSpan; /** * These are the views that represent the child elements * of the element this view represents (The logical view * to translate to a physical view). These are not * directly children of this view. These are either * placed into the rows directly or used for the purpose * of breaking into smaller chunks, to form the physical * view. */ protected View layoutPool; /** * The behavior for keeping the flow updated. By * default this is a singleton shared by all instances * of FlowView (FlowStrategy is stateless). Subclasses * can create an alternative strategy, which might keep * state. */ protected FlowStrategy strategy; /** * Strategy for maintaining the physical form * of the flow. The default implementation is * completely stateless, and recalculates the * entire flow if the layout is invalid on the * given FlowView. Alternative strategies can * be implemented by subclassing, and might * perform incrementatal repair to the layout * or alternative breaking behavior. * @since 1.3 */ public static class FlowStrategy { Position damageStart = null; Vector<View> viewBuffer; void addDamage(FlowView fv, int offset) { if (offset >= fv.getStartOffset() && offset < fv.getEndOffset()) { if (damageStart == null || offset < damageStart.getOffset()) { try { damageStart = fv.getDocument().createPosition(offset); } catch (BadLocationException e) { // shouldn't happen since offset is inside view bounds assert(false); } } } } void unsetDamage() { damageStart = null; } /** * Gives notification that something was inserted into the document * in a location that the given flow view is responsible for. The * strategy should update the appropriate changed region (which * depends upon the strategy used for repair). * * @param e the change information from the associated document * @param alloc the current allocation of the view inside of the insets. * This value will be null if the view has not yet been displayed. * @see View#insertUpdate */ public void insertUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { // FlowView.loadChildren() makes a synthetic call into this, // passing null as e if (e != null) { addDamage(fv, e.getOffset()); } if (alloc != null) { Component host = fv.getContainer(); if (host != null) { host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); } } else { fv.preferenceChanged(null, true, true); } } /** * Gives notification that something was removed from the document * in a location that the given flow view is responsible for. * * @param e the change information from the associated document * @param alloc the current allocation of the view inside of the insets. * @see View#removeUpdate */ public void removeUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { addDamage(fv, e.getOffset()); if (alloc != null) { Component host = fv.getContainer(); if (host != null) { host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); } } else { fv.preferenceChanged(null, true, true); } } /** * Gives notification from the document that attributes were changed * in a location that this view is responsible for. * * @param fv the <code>FlowView</code> containing the changes * @param e the <code>DocumentEvent</code> describing the changes * done to the Document * @param alloc Bounds of the View * @see View#changedUpdate */ public void changedUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { addDamage(fv, e.getOffset()); if (alloc != null) { Component host = fv.getContainer(); if (host != null) { host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); } } else { fv.preferenceChanged(null, true, true); } } /** * This method gives flow strategies access to the logical * view of the FlowView. */ protected View getLogicalView(FlowView fv) { return fv.layoutPool; } /** * Update the flow on the given FlowView. By default, this causes * all of the rows (child views) to be rebuilt to match the given * constraints for each row. This is called by a FlowView.layout * to update the child views in the flow. * * @param fv the view to reflow */ public void layout(FlowView fv) { View pool = getLogicalView(fv); int rowIndex, p0; int p1 = fv.getEndOffset(); if (fv.majorAllocValid) { if (damageStart == null) { return; } // In some cases there's no view at position damageStart, so // step back and search again. See 6452106 for details. int offset = damageStart.getOffset(); while ((rowIndex = fv.getViewIndexAtPosition(offset)) < 0) { offset--; } if (rowIndex > 0) { rowIndex--; } p0 = fv.getView(rowIndex).getStartOffset(); } else { rowIndex = 0; p0 = fv.getStartOffset(); } reparentViews(pool, p0); viewBuffer = new Vector<View>(10, 10); int rowCount = fv.getViewCount(); while (p0 < p1) { View row; if (rowIndex >= rowCount) { row = fv.createRow(); fv.append(row); } else { row = fv.getView(rowIndex); } p0 = layoutRow(fv, rowIndex, p0); rowIndex++; } viewBuffer = null; if (rowIndex < rowCount) { fv.replace(rowIndex, rowCount - rowIndex, null); } unsetDamage(); } /** * Creates a row of views that will fit within the * layout span of the row. This is called by the layout method. * This is implemented to fill the row by repeatedly calling * the createView method until the available span has been * exhausted, a forced break was encountered, or the createView * method returned null. If the remaining span was exhaused, * the adjustRow method will be called to perform adjustments * to the row to try and make it fit into the given span. * * @param rowIndex the index of the row to fill in with views. The * row is assumed to be empty on entry. * @param pos The current position in the children of