Source Code Cross Referenced for GapBoxView.java in  » IDE-Netbeans » editor » org » netbeans » lib » editor » view » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » editor » org.netbeans.lib.editor.view 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.lib.editor.view;
0043:
0044:        import java.awt.Component;
0045:        import java.awt.Graphics;
0046:        import java.awt.Rectangle;
0047:        import java.awt.Shape;
0048:        import java.util.ArrayList;
0049:        import java.util.List;
0050:        import javax.swing.event.DocumentEvent;
0051:        import javax.swing.text.BadLocationException;
0052:        import javax.swing.text.Document;
0053:        import javax.swing.text.Element;
0054:        import javax.swing.text.Position;
0055:        import javax.swing.text.View;
0056:        import javax.swing.text.ViewFactory;
0057:        import org.netbeans.editor.view.spi.EstimatedSpanView;
0058:        import org.netbeans.editor.view.spi.ViewInsets;
0059:        import org.netbeans.editor.view.spi.ViewLayoutState;
0060:        import org.netbeans.lib.editor.util.swing.ElementUtilities;
0061:
0062:        /**
0063:         * Composite view implementation inspired
0064:         * by the {@link javax.swing.text.AsyncBoxView}
0065:         * holding its children in <code>GapObjectArray</code>
0066:         * and capable of posting complex layout changes
0067:         * into a separate layout thread.
0068:         * <br>
0069:         * This implementation is synchronous by default
0070:         * but it contains hooks where the asynchronous behavior
0071:         * can be installed.
0072:         *
0073:         * <p>
0074:         * The operation of this view relies on the presence
0075:         * of {@link LockView} under the root view in the view hierarchy.
0076:         * <br>
0077:         * All the view operation is expected to be single-threaded.
0078:         * <br>
0079:         * The view can only work with document instances
0080:         * extending {@link javax.swing.text.AbstractDocument}
0081:         * <br>
0082:         * The view effectively only operates with preferred spans
0083:         * of its children. However it can be extended
0084:         * to consider minimum and maximum spans as well
0085:         * if the particular layout algorithm would require it.
0086:         *
0087:         * <p>
0088:         * This view implementation separates information
0089:         * related to its children from the information required
0090:         * for its own operation. The children are kept in a separate object.
0091:         * <br>
0092:         * The view allows to release its children after the layout information
0093:         * for the whole view was determined but the view is not actively
0094:         * being rendered. Releasing of the children saves memory
0095:         * without loosing valuable information
0096:         * about view's own layout.
0097:         * <br>
0098:         * The view does not initialize its children
0099:         * upon call to {@link #setParent(javax.swing.text.View)}
0100:         * thus saving memory and cpu time.
0101:         * Only if it was previously asked for some information
0102:         * related to children (e.g. <code>getViewCount()</code>)
0103:         * or for preferred, minimum or maximum span of this view
0104:         * it will initialize them during <code>setParent()</code>.
0105:         * Once the parent view was set then the children
0106:         * are populated immediately once anyone asks
0107:         * for children related information or for spans.
0108:         *
0109:         * <p>
0110:         * The view can be constructed and work with element parameter being null.
0111:         * <br>
0112:         * The following things need to be ensured when using the view in such setup:
0113:         * <ul>
0114:         *   <li> <code>getDocument()</code>,
0115:         *        <code>getStartOffset()</code>,
0116:         *        <code>getEndOffset()</code>,
0117:         *        <code>getAttributes()</code>
0118:         *           must be overriden to not delegate to element.
0119:         *
0120:         *   <li> <code>insertUpdate()</code> and <code>removeUpdate()</code>
0121:         *       methods will not find any element changes.
0122:         *
0123:         *   <li> <code>reloadChildren()</code> should be revisited
0124:         *       whether it will create possible children in a proper way.
0125:         *
0126:         * </ul>
0127:         * 
0128:         * <p>
0129:         * Various constraints for using of this view implementation:
0130:         * <ul>
0131:         *   <li> setParent() implementations of the views being added
0132:         *      to this view are allowed to trigger
0133:         *      <code>ViewLayoutState.Parent.majorAxisPreferenceChanged()</code>
0134:         *      synchronously.
0135:         *   <li> setParent() implementations of the views being added
0136:         *      to this view are not allowed to add or remove another children
0137:         *      synchronously.
0138:         * </ul>
0139:         *
0140:         * @author Miloslav Metelka
0141:         * @version 1.00
0142:         */
0143:
0144:        public class GapBoxView extends View implements  ViewLayoutState.Parent,
0145:                ViewLayoutState, EstimatedSpanView {
0146:
0147:            private static final boolean debugRebuild = Boolean
0148:                    .getBoolean("netbeans.debug.editor.view.rebuild"); // NOI18N
0149:
0150:            /**
0151:             * Bit value in <code>statusBits</code> determining
0152:             * whether X_AXIS is the major axis.
0153:             * <br>
0154:             * If this flag is not set then Y_AXIS
0155:             * is the major axis.
0156:             */
0157:            private static final int X_MAJOR_AXIS_BIT = 1;
0158:
0159:            /**
0160:             * Bit value in <code>statusBits</code> determining
0161:             * whether the major axis of this view
0162:             * is orthogonal to the major axis of the layout state
0163:             * that this view acts like.
0164:             */
0165:            private static final int MAJOR_AXES_ORTHOGONAL_BIT = 2;
0166:
0167:            /**
0168:             * Bit value in <code>statusBits</code> determining
0169:             * whether preference for this view changed along the major axis.
0170:             */
0171:            private static final int MAJOR_AXIS_PREFERENCE_CHANGED_BIT = 4;
0172:
0173:            /**
0174:             * Bit value in <code>statusBits</code> determining
0175:             * whether preference for this view changed along the minor axis.
0176:             */
0177:            private static final int MINOR_AXIS_PREFERENCE_CHANGED_BIT = 8;
0178:
0179:            /**
0180:             * Bit value in <code>statusBits</code> determining
0181:             * whether complete layout of the children has to be done
0182:             * during the next layout update of the children.
0183:             */
0184:            private static final int CHILDREN_LAYOUT_NECESSARY_BIT = 16;
0185:
0186:            /**
0187:             * Bit value in <code>statusBits</code> determining
0188:             * whether there are any pending repaint requests from children
0189:             * to be processed.
0190:             */
0191:            private static final int REPAINT_PENDING_BIT = 32;
0192:
0193:            /**
0194:             * Bit value in <code>statusBits</code> determining
0195:             * whether more than one view along the major axis
0196:             * needs to be repainted. The first view to repaint
0197:             * is determined by <code>firstRepaintChildIndex</code>.
0198:             * The whole area starting with the first view
0199:             * to repaint till the end of the view will be repainted.
0200:             */
0201:            private static final int REPAINT_TILL_END_BIT = 64;
0202:
0203:            /**
0204:             * Bit value in <code>statusBits</code> determining
0205:             * whether the preferred, minimum and maximum
0206:             * spans along the axes are estimated instead
0207:             * of measured exactly.
0208:             */
0209:            private static final int ESTIMATED_SPAN_BIT = 128;
0210:
0211:            /**
0212:             * Bit value in <code>statusBits</code> determining
0213:             * whether the updateLayout() is currently being executed.
0214:             */
0215:            private static final int UPDATE_LAYOUT_IN_PROGRESS = 256;
0216:
0217:            /**
0218:             * Bit value in <code>statusBits</code> determining
0219:             * whether this view is actively acting as layout state
0220:             * i.e. if it has parent view being instance
0221:             * of <code>ViewLayoutState.Parent</code>.
0222:             */
0223:            private static final int ACTIVE_LAYOUT_STATE = 512;
0224:
0225:            // Bits related to this view acting as layout state follow
0226:
0227:            /**
0228:             * Bit value in <code>statusBits</code> determining
0229:             * whether the x is the major axis of this view
0230:             * participating as implementation of ViewLayoutState.
0231:             */
0232:            private static final int LAYOUT_STATE_X_MAJOR_AXIS_BIT = (ACTIVE_LAYOUT_STATE << 1);
0233:
0234:            /**
0235:             * Bit value in <code>statusBits</code> determining
0236:             * that size of the view needs to be set again
0237:             * by <code>View.setSize()</code>
0238:             */
0239:            private static final int LAYOUT_STATE_VIEW_SIZE_INVALID_BIT = (LAYOUT_STATE_X_MAJOR_AXIS_BIT << 1);
0240:
0241:            /**
0242:             * Last bit in <code>statusBits</code> used for operation
0243:             * of this view. Subclasses may use higher bits if they want.
0244:             */
0245:            protected static final int GAP_BOX_VIEW_LAST_USED_STATUS_BIT = LAYOUT_STATE_VIEW_SIZE_INVALID_BIT;
0246:
0247:            /**
0248:             * Bit composition in <code>statusBits</code> determining
0249:             * whether any of the parameters affecting layout have
0250:             * changed and need to be updated.
0251:             */
0252:            private static final int LAYOUT_STATE_ANY_INVALID = MAJOR_AXIS_PREFERENCE_CHANGED_BIT
0253:                    | MINOR_AXIS_PREFERENCE_CHANGED_BIT
0254:                    | LAYOUT_STATE_VIEW_SIZE_INVALID_BIT | REPAINT_PENDING_BIT;
0255:
0256:            /**
0257:             * Composition of the bits forming the status of this view.
0258:             */
0259:            private int statusBits; // 16 bytes View + 4 = 20 bytes
0260:
0261:            /**
0262:             * Maintainer of </code>ViewLayoutState</code> children.
0263:             */
0264:            private GapBoxViewChildren children; // 20 + 4 = 24 bytes
0265:
0266:            /**
0267:             * Raw offset along the major axis of this view 
0268:             * when acting as layout state.
0269:             */
0270:            private double layoutStateMajorAxisRawOffset; // 24 + 8 = 32 bytes
0271:
0272:            /**
0273:             * Raw index of this view in its parent
0274:             * when acting as layout state.
0275:             */
0276:            private int viewRawIndex; // 32 + 4 = 36 bytes
0277:
0278:            /**
0279:             * Cached preferred span along the major axis useful when this view acts
0280:             * as layout state. Its value gets updated during layout update.
0281:             * <br>
0282:             * This is also the value returned by getMinimumSize(),
0283:             * getPreferredSize(), and getMaximumSize() along
0284:             * the major axis if the children are not present.
0285:             * <br>
0286:             * The value does include insets.
0287:             * <br>
0288:             * <code>float</code> is chosen as the view most typically
0289:             * has major axes orthogonal (see isMajorAxesOrthogonal()).
0290:             */
0291:            private float lastMajorAxisPreferredSpan; // 36 + 4 = 40 bytes
0292:
0293:            /**
0294:             * Cached preferred span along the minor axis.
0295:             * <br>
0296:             * This is also the value returned by getMinimumSize(),
0297:             * getPreferredSize(), and getMaximumSize() along
0298:             * the major axis if the children are not present.
0299:             * <br>
0300:             * The value does include insets.
0301:             */
0302:            private float lastMinorAxisPreferredSpan; // 40 + 4 = 44 bytes
0303:
0304:            /**
0305:             * Current span along the minor axis as set by <code>setSize()</code>.
0306:             * <br>
0307:             * The value does include insets.
0308:             */
0309:            private float minorAxisAssignedSpan; // 44 + 4 = 48 bytes
0310:
0311:            /**
0312:             * Construct a composite box view over the given element.
0313:             *
0314:             * @param elem the element of the model to represent.
0315:             * @param majorAxis the axis to tile along.  This can be
0316:             *  either X_AXIS or Y_AXIS.
0317:             */
0318:            public GapBoxView(Element elem, int majorAxis) {
0319:                super (elem);
0320:
0321:                if (majorAxis == View.X_AXIS) {
0322:                    setStatusBits(X_MAJOR_AXIS_BIT);
0323:                } // by default there should be no bits set
0324:            }
0325:
0326:            /**
0327:             * Determines the preferred span for this view along an
0328:             * axis.
0329:             *
0330:             * @param axis may be either View.X_AXIS or View.Y_AXIS
0331:             * @return   the span the view would like to be rendered into &gt;= 0.
0332:             *           Typically the view is told to render into the span
0333:             *           that is returned, although there is no guarantee.
0334:             *           The parent may choose to resize or break the view.
0335:             * @exception IllegalArgumentException for an invalid axis type
0336:             */
0337:            public float getPreferredSpan(int axis) {
0338:                //        assert ViewUtilities.isAxisValid(axis);
0339:
0340:                return (axis == getMajorAxis()) ? (float) getMajorAxisPreferredSpan()
0341:                        : getMinorAxisPreferredSpan();
0342:            }
0343:
0344:            /**
0345:             * Determines the minimum span for this view along an
0346:             * axis.
0347:             *
0348:             * @param axis may be either <code>View.X_AXIS</code> or
0349:             *		<code>View.Y_AXIS</code>
0350:             * @return  the minimum span the view can be rendered into
0351:             */
0352:            public @Override
0353:            float getMinimumSpan(int axis) {
0354:                // If the following implementation gets overriden the view should
0355:                // consider additional caching variables because it's acting
0356:                // as a layout state.
0357:                return getPreferredSpan(axis); // getResizeWeight() not reflected
0358:            }
0359:
0360:            /**
0361:             * Determines the maximum span for this view along an
0362:             * axis.
0363:             *
0364:             * @param axis may be either <code>View.X_AXIS</code> or
0365:             *		<code>View.Y_AXIS</code>
0366:             * @return  the maximum span the view can be rendered into
0367:             */
0368:            public @Override
0369:            float getMaximumSpan(int axis) {
0370:                // If the following implementation gets overriden the view should
0371:                // consider additional caching variables because it's acting
0372:                // as a layout state.
0373:                return getPreferredSpan(axis); // getResizeWeight() not reflected
0374:            }
0375:
0376:            public @Override
0377:            float getAlignment(int axis) {
0378:                return 0.0f;
0379:            }
0380:
0381:            /**
0382:             * Get the insets.
0383:             * The default implementation here only returns null
0384:             * but it can be redefined by subclasses.
0385:             * @return insets of this view or null for no insets.
0386:             */
0387:            public ViewInsets getInsets() {
0388:                return null;
0389:            }
0390:
0391:            /**
0392:             * Get current preferred span along the major axis.
0393:             */
0394:            final double getMajorAxisPreferredSpan() {
0395:                return (children != null) ? children
0396:                        .getMajorAxisPreferredSpan()
0397:                        + getMajorAxisInsetSpan() : lastMajorAxisPreferredSpan; // if no children then use cached value
0398:            }
0399:
0400:            final float getMinorAxisPreferredSpan() {
0401:                return (children != null) ? children
0402:                        .getMinorAxisPreferredSpan()
0403:                        + getMinorAxisInsetSpan() : lastMinorAxisPreferredSpan;
0404:            }
0405:
0406:            /**
0407:             * Get span along minor axis assigned to this view
0408:             * by calling <code>View.setSize()</code> on it.
0409:             */
0410:            final float getMinorAxisAssignedSpan() {
0411:                return minorAxisAssignedSpan;
0412:            }
0413:
0414:            /**
0415:             * Fetch the major axis (the axis the children
0416:             * are tiled along).  This will have a value of
0417:             * either X_AXIS or Y_AXIS.
0418:             */
0419:            public final int getMajorAxis() {
0420:                return isXMajorAxis() ? View.X_AXIS : View.Y_AXIS;
0421:            }
0422:
0423:            /**
0424:             * Fetch the minor axis (the axis orthoginal
0425:             * to the tiled axis).  This will have a value of
0426:             * either X_AXIS or Y_AXIS.
0427:             */
0428:            public final int getMinorAxis() {
0429:                return isXMajorAxis() ? View.Y_AXIS : View.X_AXIS;
0430:            }
0431:
0432:            /**
0433:             * Return true if X is major axis or false if Y is major axis.
0434:             */
0435:            final boolean isXMajorAxis() {
0436:                return isStatusBitsNonZero(X_MAJOR_AXIS_BIT);
0437:            }
0438:
0439:            /**
0440:             * Test whether the major axis of this view
0441:             * is orthogonal to the major axis of the layout state
0442:             * that this view acts like.
0443:             *
0444:             * @return true if the axes are orthogonal (which is more common case)
0445:             *  or false if the axes are equal.
0446:             *  <br>
0447:             *  For example if a line view extends GapBoxView
0448:             *  then it has X as the major axis but it has an Y layout state
0449:             *  major axis (when acting as layout state for a document view)
0450:             *  so this method would return true in this case.
0451:             */
0452:            final boolean isMajorAxesOrthogonal() {
0453:                return isStatusBitsNonZero(MAJOR_AXES_ORTHOGONAL_BIT);
0454:            }
0455:
0456:            /**
0457:             * Returns the number of child views of this view.
0458:             *
0459:             * @return the number of views &gt;= 0
0460:             * @see #getView(int)
0461:             */
0462:            public @Override
0463:            int getViewCount() {
0464:                return getChildren().getChildCount();
0465:            }
0466:
0467:            /**
0468:             * Returns the view in this container with the particular index.
0469:             *
0470:             * @param index index of the desired view, &gt;= 0 and &lt; getViewCount()
0471:             * @return the view at index <code>index</code>
0472:             */
0473:            public @Override
0474:            View getView(int index) {
0475:                return getChild(index).getView();
0476:            }
0477:
0478:            /*
0479:             * Replaces child views.  If there are no views to remove
0480:             * this acts as an insert.  If there are no views to
0481:             * add this acts as a remove.  Views being removed will
0482:             * have the parent set to <code>null</code>,
0483:             * and the internal reference to them removed so that they
0484:             * may be garbage collected.
0485:             * 
0486:             * <p>
0487:             * It is necessary to call <code>updateLayout()</code>
0488:             * on this view at some point later so that the possible
0489:             * layout changes are done.
0490:             *
0491:             * @param index the starting index into the child views >= 0
0492:             * @param length the number of existing views to replace >= 0
0493:             * @param views the child views to insert
0494:             */
0495:            public @Override
0496:            void replace(int index, int length, View[] views) {
0497:                if (length < 0) {
0498:                    throw new IllegalArgumentException("length=" + length
0499:                            + " < 0"); // NOI18N
0500:                }
0501:
0502:                if (length == 0 && (views == null || views.length == 0)) { // nothing to do
0503:                    return;
0504:                }
0505:
0506:                // make sure that the children are populated
0507:                GapBoxViewChildren ch = getChildren();
0508:
0509:                // Handle raplace in children only if either length > 0
0510:                // or insertLength > 0 or both are > 0
0511:                ch.replace(index, length, views);
0512:            }
0513:
0514:            /**
0515:             * Get minimum number of children that must be added at once
0516:             * by replace() so that the addition is treated as a lengthy
0517:             * operation which means that all the added children will
0518:             * have the estimated span flag turned on and
0519:             * {@link #scheduleResetChildrenEstimatedSpan(int)}
0520:             * will be called to walk through the added children
0521:             * and reset their estimated span to false.
0522:             */
0523:            protected int getReplaceEstimatedThreshold() {
0524:                return Integer.MAX_VALUE;
0525:            }
0526:
0527:            public final boolean isEstimatedSpan() {
0528:                return isStatusBitsNonZero(ESTIMATED_SPAN_BIT);
0529:            }
0530:
0531:            public void setEstimatedSpan(boolean estimatedSpan) {
0532:                if (isEstimatedSpan() != estimatedSpan) { // really changed
0533:                    if (estimatedSpan) {
0534:                        setStatusBits(ESTIMATED_SPAN_BIT);
0535:                    } else {
0536:                        clearStatusBits(ESTIMATED_SPAN_BIT);
0537:
0538:                        // If children exist make sure the task is scheduled to update them
0539:                        if (children != null) {
0540:                            int viewCount = getViewCount();
0541:                            if (viewCount > 0) {
0542:                                resetEstimatedSpan(0, viewCount); // reset all children
0543:                            }
0544:                        }
0545:                    }
0546:
0547:                }
0548:            }
0549:
0550:            /**
0551:             * Set estimated span flag to false on the given children views.
0552:             * <br>
0553:             * This method is called from both <code>setEstimatedSpan()</code>
0554:             * and from <code>children.replace()</code> if the number of added
0555:             * children exceeds threshold count.
0556:             * <br>
0557:             * Subclasses may want to do this on the background.
0558:             */
0559:            protected void resetEstimatedSpan(int childIndex, int count) {
0560:                while (--count >= 0) {
0561:                    ViewLayoutState child = getChild(childIndex);
0562:                    View childView = child.getView();
0563:                    if (childView instanceof  EstimatedSpanView) {
0564:                        ((EstimatedSpanView) childView).setEstimatedSpan(false);
0565:                    }
0566:                    childIndex++;
0567:                }
0568:            }
0569:
0570:            /**
0571:             * Remove the child views in the given index range
0572:             * and let the default building mechanism to build the child views.
0573:             *
0574:             * <p>
0575:             * It is necessary to call <code>updateLayout()</code>
0576:             * on this view at some point later so that the possible
0577:             * layout changes are done.
0578:             *
0579:             * @param index index of the first child view to be rebuilt
0580:             * @param count number of chilren in the children array to be rebuilt.
0581:             *   If <code>index + count<code> is past the end of the children available
0582:             *   the value of count will be decreased accordingly.
0583:             */
0584:            public void rebuild(int index, int count) {
0585:                if (count != 0) {
0586:                    int startOffset = (index == 0) ? -1 : getView(index - 1)
0587:                            .getEndOffset();
0588:                    int viewCount = getViewCount();
0589:                    int endIndex = Math.min(index + count, viewCount);
0590:                    int endOffset = (endIndex == viewCount) ? -1 : getView(
0591:                            endIndex).getStartOffset();
0592:
0593:                    if (debugRebuild) {
0594:                        /*DEBUG*/System.err
0595:                                .println("GapBoxView.rebuild(): index="
0596:                                        + index // NOI18N
0597:                                        + ", count="
0598:                                        + count // NOI18N
0599:                                        + ", so=" + startOffset + ", eo="
0600:                                        + endOffset // NOI18N
0601:                                );
0602:                    }
0603:
0604:                    reloadChildren(index, count, startOffset, endOffset);
0605:                }
0606:            }
0607:
0608:            /**
0609:             * Rebuild based on specification of the offset range.
0610:             *
0611:             * @param startOffset starting offset of the area in which the views
0612:             *  should be rebuilt.
0613:             * @param endOffset ending offset of the area in which the views
0614:             *  should be rebuilt.
0615:             */
0616:            public void offsetRebuild(int startOffset, int endOffset) {
0617:                int index = ViewUtilitiesImpl.findLowerViewIndex(this ,
0618:                        startOffset, false);
0619:                int count;
0620:                if (index == -1) { // no child views
0621:                    index = 0;
0622:                    count = 0;
0623:
0624:                } else { // child views exist
0625:                    count = ViewUtilitiesImpl.findUpperViewIndex(this ,
0626:                            endOffset, true)
0627:                            - index + 1;
0628:                }
0629:
0630:                rebuild(index, count);
0631:            }
0632:
0633:            /**
0634:             * Sets the parent of the view.
0635:             * The children are only initialized if someone
0636:             * has previously asked for information
0637:             * related to children (e.g. <code>getViewCount()</code>)
0638:             * or for preferred, minimum or maximum span of this view.
0639:             *
0640:             * @param parent the parent of the view, <code>null</code> if none
0641:             */
0642:            public @Override
0643:            void setParent(View parent) {
0644:                super .setParent(parent);
0645:
0646:                /* Make sure that the children get loaded.
0647:                 * It is necessary to do because children preferences will
0648:                 * define the preferences of the parent.
0649:                 */
0650:                if (parent != null) {
0651:                    if (parent instanceof  ViewLayoutState.Parent) {
0652:                        setStatusBits(ACTIVE_LAYOUT_STATE);
0653:                    } else {
0654:                        clearStatusBits(ACTIVE_LAYOUT_STATE);
0655:                    }
0656:
0657:                    // Resolving whether active layout state must be resolved prior getChildren()
0658:                    getChildren();
0659:
0660:                } else { // parent is being set to null
0661:                    releaseChildren();
0662:                    clearStatusBits(ACTIVE_LAYOUT_STATE);
0663:                }
0664:            }
0665:
0666:            public final boolean isActiveLayoutState() {
0667:                return isStatusBitsNonZero(ACTIVE_LAYOUT_STATE);
0668:            }
0669:
0670:            protected GapBoxViewChildren getChildren() {
0671:                if (children == null) {
0672:                    children = createChildren();
0673:
0674:                    // Possibly load the children
0675:                    View parent = getParent();
0676:                    if (parent != null) { // initialize with valid view factory only
0677:                        reloadChildren(0, 0, -1, -1);
0678:                    }
0679:                }
0680:
0681:                return children;
0682:            }
0683:
0684:            /**
0685:             * Get children or null if the children were not yet initialized.
0686:             */
0687:            protected final GapBoxViewChildren getChildrenNull() {
0688:                return children;
0689:            }
0690:
0691:            /**
0692:             * Ask for releasing of the children.
0693:             * The view will still remember the last allocated size
0694:             * and preferred, minimum and maximum spans.
0695:             * However various operations like painting or translations
0696:             * between model and visual positions will
0697:             * make the children to be loaded again.
0698:             */
0699:            public void releaseChildren() {
0700:                if (children != null) {
0701:                    unloadChildren();
0702:
0703:                    children.unload();
0704:                    children = null;
0705:                }
0706:            }
0707:
0708:            // Implements ViewLayoutState
0709:            public final View getView() {
0710:                return this ;
0711:            }
0712:
0713:            // Implements ViewLayoutState
0714:            public ViewLayoutState selectLayoutMajorAxis(int axis) {
0715:                //        assert ViewUtilities.isAxisValid(axis);
0716:
0717:                if (axis == View.X_AXIS) {
0718:                    setStatusBits(LAYOUT_STATE_X_MAJOR_AXIS_BIT);
0719:                } else { // y as layout major axis
0720:                    clearStatusBits(LAYOUT_STATE_X_MAJOR_AXIS_BIT);
0721:                }
0722:
0723:                // Determine whether major axis of this view
0724:                // is orthogonal to major axis for acting as layout state
0725:                if (axis == getMajorAxis()) { // major axes equal
0726:                    clearStatusBits(MAJOR_AXES_ORTHOGONAL_BIT);
0727:                } else { // major axes orthogonal
0728:                    setStatusBits(MAJOR_AXES_ORTHOGONAL_BIT);
0729:                }
0730:
0731:                return this ;
0732:            }
0733:
0734:            // Implements ViewLayoutState
0735:            public boolean isFlyweight() {
0736:                return false;
0737:            }
0738:
0739:            // Implements ViewLayoutState
0740:            public void updateLayout() {
0741:                if (isLayoutValid()) { // Nothing to do
0742:                    return;
0743:                }
0744:
0745:                if (isStatusBitsNonZero(UPDATE_LAYOUT_IN_PROGRESS)) {
0746:                    return;
0747:                }
0748:                setStatusBits(UPDATE_LAYOUT_IN_PROGRESS);
0749:
0750:                View parent = getParent();
0751:                if (parent == null) { // disconnected from hierarchy
0752:                    return;
0753:                }
0754:                ViewLayoutState.Parent lsParent = (parent instanceof  ViewLayoutState.Parent) ? (ViewLayoutState.Parent) parent
0755:                        : null;
0756:
0757:                // Make sure all individual pending children layout updates are addressed
0758:                children.childrenUpdateLayout();
0759:
0760:                // Layout the children if necessary
0761:                if (isChildrenLayoutNecessary()) {
0762:                    resetChildrenLayoutNecessary();
0763:
0764:                    children.childrenLayout(); // re-compute layout info for children
0765:                }
0766:
0767:                // Update cached variable corresponding to layout state major axis
0768:                boolean parentWillRepaint = false;
0769:
0770:                // Check whether preference did not change along a particular axis
0771:                // and if so message preferenceChanged to parent.
0772:                // Cache the following two vars before they get cleared in next section:
0773:                boolean majorAxisPreferenceChanged = isMajorAxisPreferenceChanged();
0774:                boolean minorAxisPreferenceChanged = isMinorAxisPreferenceChanged();
0775:                resetAxesPreferenceChanged();
0776:
0777:                if (majorAxisPreferenceChanged) {
0778:                    // Update the cached value for the major axis
0779:                    if (children != null) { // only if children exist
0780:                        double delta = updateLastMajorAxisPreferredSpan();
0781:                        if (delta != 0.0d && lsParent != null) {
0782:                            if (isMajorAxesOrthogonal()) {
0783:                                lsParent.minorAxisPreferenceChanged(this );
0784:                            } else {
0785:                                lsParent
0786:                                        .majorAxisPreferenceChanged(this , delta);
0787:                                parentWillRepaint = true;
0788:                            }
0789:                        }
0790:                    }
0791:                }
0792:
0793:                if (minorAxisPreferenceChanged) {
0794:                    // Update the cached value for the minor axis
0795:                    if (children != null) { // only if children exist
0796:                        double delta = updateLastMinorAxisPreferredSpan();
0797:                        if (delta != 0.0d && lsParent != null) {
0798:                            if (isMajorAxesOrthogonal()) {
0799:                                lsParent
0800:                                        .majorAxisPreferenceChanged(this , delta);
0801:                                parentWillRepaint = true;
0802:                            } else {
0803:                                lsParent.minorAxisPreferenceChanged(this );
0804:                            }
0805:                        }
0806:                    }
0807:                }
0808:
0809:                // If not active layout state propagate preference change upwards
0810:                // If this is active layout state then this was already propagated
0811:                // by marking itself as needing layout update which is now being
0812:                // updated.
0813:                if (majorAxisPreferenceChanged || minorAxisPreferenceChanged
0814:                        || !isActiveLayoutState()) {
0815:                    // Either of major or minor axis (or both) has changed
0816:                    boolean horizontalChange = false;
0817:                    boolean verticalChange = false;
0818:
0819:                    if (isXMajorAxis()) {
0820:                        horizontalChange = majorAxisPreferenceChanged;
0821:                        verticalChange = minorAxisPreferenceChanged;
0822:                    } else {
0823:                        horizontalChange = minorAxisPreferenceChanged;
0824:                        verticalChange = majorAxisPreferenceChanged;
0825:                    }
0826:
0827:                    parent.preferenceChanged(this , horizontalChange,
0828:                            verticalChange);
0829:                }
0830:
0831:                // Check whether size must be set on this view
0832:                if (isStatusBitsNonZero(LAYOUT_STATE_VIEW_SIZE_INVALID_BIT)) {
0833:                    clearStatusBits(LAYOUT_STATE_VIEW_SIZE_INVALID_BIT);
0834:
0835:                    if (lsParent != null) { // should only be done when having layout state parent
0836:                        float width;
0837:                        float height;
0838:                        float layoutStateMajorAxisSpan = getPreferredSpan(getLayoutStateMajorAxis());
0839:                        float layoutStateMinorAxisSpan = lsParent
0840:                                .getMinorAxisSpan(this );
0841:                        if (isXLayoutStateMajorAxis()) {
0842:                            width = layoutStateMajorAxisSpan;
0843:                            height = layoutStateMinorAxisSpan;
0844:                        } else {
0845:                            width = layoutStateMinorAxisSpan;
0846:                            height = layoutStateMajorAxisSpan;
0847:                        }
0848:
0849:                        setSize(width, height);
0850:                    }
0851:                }
0852:
0853:                if (children != null && isRepaintPending()) {
0854:                    if (!parentWillRepaint) {
0855:                        processRepaint(lsParent);
0856:                    }
0857:                    // After painting is finished reset the variables
0858:                    resetRepaintPending();
0859:                }
0860:
0861:                clearStatusBits(UPDATE_LAYOUT_IN_PROGRESS);
0862:
0863:                // Call recursively to make sure that there is no more work.
0864:                updateLayout();
0865:            }
0866:
0867:            /**
0868:             * Update the layout in response to receiving notification of
0869:             * change from the model.
0870:             *
0871:             * @param ec changes to the element this view is responsible
0872:             *  for (may be null if there were no changes).
0873:             * @param e the change information from the associated document
0874:             * @param a the current allocation of the view
0875:             * @see #insertUpdate
0876:             * @see #removeUpdate
0877:             * @see #changedUpdate
0878:             */
0879:            protected @Override
0880:            void updateLayout(DocumentEvent.ElementChange ec, DocumentEvent e,
0881:                    Shape a) {
0882:
0883:                //super.updateLayout(ec, e, a);
0884:            }
0885:
0886:            /**
0887:             * Called by children to mark layout of this view invalid.
0888:             * This only has effect if this view is active layout state.
0889:             */
0890:            public void layoutInvalid(ViewLayoutState child) {
0891:                int childIndex = children.getChildIndexNoCheck(child);
0892:                children.markLayoutInvalid(childIndex, 1);
0893:            }
0894:
0895:            protected void markLayoutInvalid() {
0896:                if (isActiveLayoutState()) {
0897:                    ((ViewLayoutState.Parent) getParent()).layoutInvalid(this );
0898:                } else { // not active layout state
0899:                    // Update layout immediately - subclasses can override
0900:                    directUpdateLayout();
0901:                }
0902:            }
0903:
0904:            /**
0905:             * This method is called when this view is not acting as active
0906:             * layout state and its layout becomes invalid.
0907:             * <br>
0908:             * By default the layout is updated immediately
0909:             * but subclasses may change that but they must ensure
0910:             * that the layout will be updated later.
0911:             */
0912:            protected void directUpdateLayout() {
0913:                updateLayout();
0914:            }
0915:
0916:            /**
0917:             * Process pending repaint requests from children.
0918:             * <br>
0919:             * Children are guaranteed to be non-null once this method gets called.
0920:             */
0921:            protected void processRepaint(ViewLayoutState.Parent lsParent) {
0922:                if (lsParent != null) { // parent view is ViewLayoutState.Parent
0923:                    int firstRepaintChildIndex = children
0924:                            .getFirstRepaintChildIndex();
0925:                    double majorAxisOffset = children
0926:                            .getMajorAxisOffset(firstRepaintChildIndex);
0927:                    double repaintMajorOffset;
0928:                    double repaintMajorSpan;
0929:                    float repaintMinorOffset;
0930:                    float repaintMinorSpan;
0931:                    if (isRepaintTillEnd()
0932:                            || firstRepaintChildIndex >= getViewCount() // bit strange but possible after last child remove
0933:                    ) {
0934:                        if (isMajorAxesOrthogonal()) {
0935:                            repaintMajorOffset = 0;
0936:                            repaintMajorSpan = 0; // till end of view's span in parent
0937:                            repaintMinorOffset = (float) majorAxisOffset;
0938:                            repaintMinorSpan = 0; // till parent view minor span end
0939:
0940:                        } else { // major axes equal
0941:                            repaintMajorOffset = majorAxisOffset;
0942:                            repaintMajorSpan = 0; // till end of view's span in parent
0943:                            repaintMinorOffset = 0;
0944:                            repaintMinorSpan = 0; // till parent view minor span end
0945:                        }
0946:
0947:                    } else { // repainting just single child that did not change major axis span
0948:                        double majorAxisSpan = getChild(firstRepaintChildIndex)
0949:                                .getLayoutMajorAxisPreferredSpan();
0950:                        if (isMajorAxesOrthogonal()) {
0951:                            repaintMajorOffset = 0;
0952:                            repaintMajorSpan = 0; // till end of view's span in parent
0953:                            repaintMinorOffset = (float) majorAxisOffset;
0954:                            repaintMinorSpan = (float) majorAxisSpan;
0955:
0956:                        } else { // major axes equal
0957:                            repaintMajorOffset = majorAxisOffset;
0958:                            repaintMajorSpan = majorAxisSpan;
0959:                            repaintMinorOffset = 0;
0960:                            repaintMinorSpan = 0; // till parent view minor span end
0961:                        }
0962:                    }
0963:
0964:                    lsParent.repaint(this , repaintMajorOffset,
0965:                            repaintMajorSpan, repaintMinorOffset,
0966:                            repaintMinorSpan);
0967:
0968:                } else { // do not know allocation here => repaint whole component
0969:                    Component c = getContainer();
0970:                    if (c != null) {
0971:                        c.repaint();
0972:                    }
0973:                }
0974:            }
0975:
0976:            /**
0977:             * Mark that the child with the given index should be repainted.
0978:             *
0979:             * @param childIndex index of child that should be marked for repaint.
0980:             * @param repaintTillEnd if set to true then all children following
0981:             *  the child should be repainted as well.
0982:             * @return true if lower child index was marked for repaint by this method
0983:             *  than there was before.
0984:             */
0985:            protected boolean markRepaint(int childIndex, boolean repaintTillEnd) {
0986:                boolean lowerIndexMarked = false;
0987:                if (children != null) {
0988:                    int firstRepaintChildIndex = children
0989:                            .getFirstRepaintChildIndex();
0990:                    if (!isRepaintTillEnd()) { // not repainting more yet
0991:                        if (firstRepaintChildIndex == -1) { // no repainting yet
0992:                            lowerIndexMarked = true;
0993:                            markRepaintPending();
0994:                            children.setFirstRepaintChildIndex(childIndex);
0995:                            if (repaintTillEnd) {
0996:                                setStatusBits(REPAINT_TILL_END_BIT);
0997:                            }
0998:
0999:                        } else if (firstRepaintChildIndex != childIndex) { // other child than first
1000:                            if (childIndex < firstRepaintChildIndex) {
1001:                                lowerIndexMarked = true;
1002:                                children.setFirstRepaintChildIndex(childIndex);
1003:                            }
1004:                            setStatusBits(REPAINT_TILL_END_BIT); // surely will repaint to end
1005:
1006:                        } else { // same child already scheduled for repaint
1007:                            if (repaintTillEnd) {
1008:                                setStatusBits(REPAINT_TILL_END_BIT);
1009:                            }
1010:                        }
1011:
1012:                    } else { // repaint more children already - firstRepaintChildIndex must be valid
1013:                        if (childIndex < firstRepaintChildIndex) {
1014:                            lowerIndexMarked = true;
1015:                            children.setFirstRepaintChildIndex(childIndex);
1016:                        }
1017:                    }
1018:                }
1019:
1020:                return lowerIndexMarked;
1021:            }
1022:
1023:            public final boolean isRepaintPending() {
1024:                return isStatusBitsNonZero(REPAINT_PENDING_BIT);
1025:            }
1026:
1027:            protected final void markRepaintPending() {
1028:                setStatusBits(REPAINT_PENDING_BIT);
1029:            }
1030:
1031:            protected void resetRepaintPending() {
1032:                if (children != null) {
1033:                    children.setFirstRepaintChildIndex(-1);
1034:                }
1035:                clearStatusBits(REPAINT_PENDING_BIT | REPAINT_TILL_END_BIT);
1036:            }
1037:
1038:            public final boolean isRepaintTillEnd() {
1039:                return isStatusBitsNonZero(REPAINT_TILL_END_BIT);
1040:            }
1041:
1042:            /**
1043:             * Test whether the preference along the layout state minor axis
1044:             * has really changed.
1045:             * <br>
1046:             * The default implementation only checks preferred span
1047:             * but the implementation reflecting minimum and maximum spans
1048:             * can extend this method.
1049:             *
1050:             * @return true if it has really changed or false if not.
1051:             */
1052:            protected boolean isLayoutMinorAxisPreferenceChanged(
1053:                    boolean majorAxesOrthogonal) {
1054:                double delta;
1055:                if (majorAxesOrthogonal) {
1056:                    // processing minor layout state axis but it's in fact major view axis
1057:                    delta = updateLastMajorAxisPreferredSpan();
1058:                } else { // major axes equal
1059:                    // processing minor layout state axis which is also minor view axis
1060:                    delta = updateLastMinorAxisPreferredSpan();
1061:                }
1062:
1063:                return (delta != 0.0d);
1064:            }
1065:
1066:            private double updateLastMinorAxisPreferredSpan() {
1067:                float currentMinorAxisPreferredSpan = children
1068:                        .getMinorAxisPreferredSpan();
1069:                double delta = currentMinorAxisPreferredSpan
1070:                        - lastMinorAxisPreferredSpan;
1071:                lastMinorAxisPreferredSpan = currentMinorAxisPreferredSpan;
1072:                return delta;
1073:            }
1074:
1075:            private double updateLastMajorAxisPreferredSpan() {
1076:                double currentMajorAxisPreferredSpan = children
1077:                        .getMajorAxisPreferredSpan();
1078:                double delta = currentMajorAxisPreferredSpan
1079:                        - lastMajorAxisPreferredSpan;
1080:                // Here the truncation occurs but if the major axes are orthogonal
1081:                // or if the spans are not big enough to exhaust float precision
1082:                // this should not hurt.
1083:                lastMajorAxisPreferredSpan = (float) currentMajorAxisPreferredSpan;
1084:                return delta;
1085:            }
1086:
1087:            // Implements ViewLayoutState
1088:            public boolean isLayoutValid() {
1089:                return !isStatusBitsNonZero(LAYOUT_STATE_ANY_INVALID)
1090:                        && (children == null || children
1091:                                .getUpdateLayoutChildCount() == 0);
1092:            }
1093:
1094:            // Implements ViewLayoutState
1095:            public double getLayoutMajorAxisPreferredSpan() {
1096:                return (isMajorAxesOrthogonal()) ? lastMinorAxisPreferredSpan
1097:                        : lastMajorAxisPreferredSpan;
1098:            }
1099:
1100:            // Implements ViewLayoutState
1101:            public float getLayoutMinorAxisPreferredSpan() {
1102:                return isMajorAxesOrthogonal() ? lastMajorAxisPreferredSpan
1103:                        : lastMinorAxisPreferredSpan;
1104:            }
1105:
1106:            // Implements ViewLayoutState
1107:            public float getLayoutMinorAxisMinimumSpan() {
1108:                // It has to be overriden if the layout state minimum span is maintained
1109:                return getLayoutMinorAxisPreferredSpan();
1110:            }
1111:
1112:            // Implements ViewLayoutState
1113:            public float getLayoutMinorAxisMaximumSpan() {
1114:                // It has to be overriden if the layout state maximum span is maintained
1115:                return getLayoutMinorAxisPreferredSpan();
1116:            }
1117:
1118:            // Implements ViewLayoutState
1119:            public float getLayoutMinorAxisAlignment() {
1120:                // Alignment is assumed not to change over time
1121:                // It needs to be cached if that's not true
1122:                return getAlignment(getLayoutStateMinorAxis());
1123:            }
1124:
1125:            // Implements ViewLayoutState
1126:            public double getLayoutMajorAxisRawOffset() {
1127:                return layoutStateMajorAxisRawOffset;
1128:            }
1129:
1130:            // Implements ViewLayoutState
1131:            public void setLayoutMajorAxisRawOffset(double majorAxisRawOffset) {
1132:                this .layoutStateMajorAxisRawOffset = majorAxisRawOffset;
1133:            }
1134:
1135:            protected final ViewLayoutState.Parent getLayoutStateParent() {
1136:                View parent = getParent();
1137:                return (parent instanceof  ViewLayoutState.Parent) ? ((ViewLayoutState.Parent) parent)
1138:                        : null;
1139:            }
1140:
1141:            protected final boolean isXLayoutStateMajorAxis() {
1142:                return (isStatusBitsNonZero(LAYOUT_STATE_X_MAJOR_AXIS_BIT));
1143:            }
1144:
1145:            protected final int getLayoutStateMajorAxis() {
1146:                return (isStatusBitsNonZero(LAYOUT_STATE_X_MAJOR_AXIS_BIT)) ? View.X_AXIS
1147:                        : View.Y_AXIS;
1148:            }
1149:
1150:            protected final int getLayoutStateMinorAxis() {
1151:                return (isStatusBitsNonZero(LAYOUT_STATE_X_MAJOR_AXIS_BIT)) ? View.Y_AXIS
1152:                        : View.X_AXIS;
1153:            }
1154:
1155:            // Implements ViewLayoutState
1156:            public int getViewRawIndex() {
1157:                return viewRawIndex;
1158:            }
1159:
1160:            // Implements ViewLayoutState
1161:            public void setViewRawIndex(int viewRawIndex) {
1162:                this .viewRawIndex = viewRawIndex;
1163:            }
1164:
1165:            // Implements ViewLayoutState
1166:            public void viewPreferenceChanged(boolean width, boolean height) {
1167:                markViewSizeInvalid();
1168:            }
1169:
1170:            // Implements ViewLayoutState
1171:            public void markViewSizeInvalid() {
1172:                setStatusBits(LAYOUT_STATE_VIEW_SIZE_INVALID_BIT);
1173:            }
1174:
1175:            // Implements ViewLayoutState.Parent
1176:            /**
1177:             * Preference of one of the children has changed along the major axis.
1178:             */
1179:            public void majorAxisPreferenceChanged(ViewLayoutState child,
1180:                    double majorAxisSpanDelta) {
1181:                int childIndex = getChildIndexNoCheck(child);
1182:                if (majorAxisSpanDelta != 0.0d) {
1183:                    // repaint till end as the children above the index get shifted
1184:                    markRepaint(childIndex, true);
1185:                    children.majorAxisPreferenceChanged(child, childIndex,
1186:                            majorAxisSpanDelta);
1187:
1188:                } else { // make sure that the child gets repainted
1189:                    markRepaint(childIndex, false);
1190:                }
1191:            }
1192:
1193:            // Implements ViewLayoutState.Parent
1194:            /**
1195:             * Preference of one of the children has changed along the minor axis.
1196:             */
1197:            public void minorAxisPreferenceChanged(ViewLayoutState child) {
1198:                int childIndex = getChildIndexNoCheck(child);
1199:                markRepaint(childIndex, false);
1200:                children.minorAxisPreferenceChanged(child, childIndex);
1201:            }
1202:
1203:            // Implements ViewLayoutState.Parent
1204:            /**
1205:             * Get span of the given child along the minor axis of this view.
1206:             */
1207:            public float getMinorAxisSpan(ViewLayoutState child) {
1208:                // Delegate to children
1209:                return getChildren().getMinorAxisSpan(child);
1210:            }
1211:
1212:            // Implements ViewLayoutState.Parent
1213:            public void repaint(ViewLayoutState child, double majorAxisOffset,
1214:                    double majorAxisSpan, float minorAxisOffset,
1215:                    float minorAxisSpan) {
1216:
1217:                int childIndex = getChildIndexNoCheck(child);
1218:                markRepaint(childIndex, false);
1219:            }
1220:
1221:            /**
1222:             * Test whether complete layout of the children necessary.
1223:             */
1224:            public final boolean isChildrenLayoutNecessary() {
1225:                return isStatusBitsNonZero(CHILDREN_LAYOUT_NECESSARY_BIT);
1226:            }
1227:
1228:            /**
1229:             * Mark that a complete layout of children is necessary.
1230:             * <br>
1231:             * This method does no scheduling of the children layout update.
1232:             */
1233:            public final void markChildrenLayoutNecessary() {
1234:                setStatusBits(CHILDREN_LAYOUT_NECESSARY_BIT);
1235:            }
1236:
1237:            final void resetChildrenLayoutNecessary() {
1238:                clearStatusBits(CHILDREN_LAYOUT_NECESSARY_BIT);
1239:            }
1240:
1241:            /**
1242:             * Child views can call this on the parent to indicate that
1243:             * the preference has changed and should be reconsidered
1244:             * for layout.  This is reimplemented to queue new work
1245:             * on the layout thread.  This method gets messaged from
1246:             * multiple threads via the children.
1247:             *
1248:             * @param childView the child view of this view or null to signal
1249:             *  change in this view. 
1250:             * @param width true if the width preference has changed
1251:             * @param height true if the height preference has changed
1252:             * @see javax.swing.JComponent#revalidate
1253:             */
1254:            public @Override
1255:            void preferenceChanged(View childView, boolean width, boolean height) {
1256:                if (childView == null) { // notify parent about this view change
1257:                    getParent().preferenceChanged(this , width, height);
1258:
1259:                } else { // Child of this view has changed
1260:                    // First find the index of the child view
1261:                    int index;
1262:                    // Try to cast the view to ViewLayoutState and find index that way 
1263:                    if (childView instanceof  ViewLayoutState) {
1264:                        // Trust the view to be really child of this view - check is done later
1265:                        index = getChildIndexNoCheck((ViewLayoutState) childView);
1266:                    } else { // child view not instance of ViewLayoutState
1267:                        // Use binary search to find the view
1268:                        index = getViewIndex(childView.getStartOffset());
1269:                    }
1270:
1271:                    ViewLayoutState child = getChild(index);
1272:                    if (child.getView() != childView) {
1273:                        int ind;
1274:                        for (ind = getViewCount() - 1; ind >= 0; ind--) {
1275:                            if (getView(ind) == childView) {
1276:                                break;
1277:                            }
1278:                        }
1279:                        if (ind == -1) {
1280:                            throw new IllegalArgumentException("childView=" // NOI18N
1281:                                    + childView + " not child of view " + this ); // NOI18N
1282:
1283:                        } else { // is child but at different index
1284:                            throw new IllegalStateException(
1285:                                    "Internal error. Child expected at index="
1286:                                            + index // NOI18N
1287:                                            + " but found at index=" + ind); // NOI18N
1288:                        }
1289:                    }
1290:
1291:                    // Mark the child as invalid
1292:                    child.viewPreferenceChanged(width, height);
1293:
1294:                    // Mark the layout of the child as invalid - this must be done
1295:                    // _after_ the real changes affecting child's layout were performed
1296:                    // because the layout may be directly updated
1297:                    // by the parent during the call of the following method.
1298:                    children.markLayoutInvalid(index, 1);
1299:                }
1300:            }
1301:
1302:            /**
1303:             * Sets the size of the view.  This should cause
1304:             * layout of the view if the view caches any layout
1305:             * information.
1306:             *
1307:             * <p>
1308:             * The propagation of this operation to child views
1309:             * can be done asynchronously if appropriate.
1310:             *
1311:             * @param width the width &gt;= 0
1312:             * @param height the height &gt;= 0
1313:             */
1314:            public @Override
1315:            void setSize(float width, float height) {
1316:                float targetMajorAxisSpan;
1317:                float targetMinorAxisSpan;
1318:                if (isXMajorAxis()) {
1319:                    targetMajorAxisSpan = width;
1320:                    targetMinorAxisSpan = height;
1321:                } else { // Y is major axis
1322:                    targetMajorAxisSpan = height;
1323:                    targetMinorAxisSpan = width;
1324:                }
1325:
1326:                // Span along major axis is ignored by default
1327:                setSpanOnMajorAxis(targetMajorAxisSpan);
1328:                setSpanOnMinorAxis(targetMinorAxisSpan);
1329:            }
1330:
1331:            protected void setSpanOnMajorAxis(float targetMajorAxisSpan) {
1332:                // along the major axis the value is ignored by default
1333:                // but subclasses doing e.g. line wrapping can override that
1334:            }
1335:
1336:            protected void setSpanOnMinorAxis(float targetMinorAxisSpan) {
1337:                if (targetMinorAxisSpan != minorAxisAssignedSpan) {
1338:                    minorAxisAssignedSpan = targetMinorAxisSpan;
1339:                    //float targetSpanNoInsets = targetMinorAxisSpan - getMinorAxisInsetSpan();
1340:
1341:                    // do not recompute children if estimated span or estimated change task running
1342:                    if (!isEstimatedSpan() && !isChildrenResizeDisabled()) {
1343:                        // mark all of the ViewLayoutState instances as needing to
1344:                        // resize the child.
1345:                        int viewCount = getViewCount();
1346:                        if (viewCount != 0) {
1347:                            markSizeInvalid(0, viewCount);
1348:                        }
1349:                    }
1350:                }
1351:            }
1352:
1353:            /**
1354:             * This method marks sizes of all the children as invalid
1355:             * so the next layout update will resize each children.
1356:             * <br>
1357:             * This is made as protected method since large complex views
1358:             * may consider this operation lengthy with certain amount
1359:             * of children so they may need to do this operation in background
1360:             * and delegate to this implementation for small amount 
1361:             * of children only.
1362:             *
1363:             * @param &gt;0 total number of child views of this view. It's given
1364:             *  as parameter because subclasses will typically decide their
1365:             *  behavior based on the total view count.
1366:             */
1367:            protected void markSizeInvalid(int childIndex, int count) {
1368:                while (--count >= 0) {
1369:                    ViewLayoutState child = getChild(childIndex);
1370:                    if (!child.isFlyweight()) {
1371:                        child.markViewSizeInvalid();
1372:                    }
1373:                    childIndex++;
1374:                }
1375:
1376:                // Mark the layout of the child as invalid - this must be done
1377:                // _after_ the real changes affecting child's layout were performed
1378:                // because the layout may be directly updated
1379:                // by the parent during the call of the following method.
1380:                children.markLayoutInvalid(childIndex, count);
1381:            }
1382:
1383:            /**
1384:             * Return true if the children should not be attempted to resize
1385:             * once <code>setSize()</code> is called on this view.
1386:             * <br>
1387:             * Turning this on may save considerable time but it should be only
1388:             * used if the views truly do not react on <code>setSize()</code>
1389:             * e.g. this should *not* be used if line-wrapping is turned on.
1390:             */
1391:            protected boolean isChildrenResizeDisabled() {
1392:                return false; // by default must resize children upon setSize() on view
1393:            }
1394:
1395:            /**
1396:             * Fetches the allocation for the given child view.
1397:             * This enables finding out where various views
1398:             * are located, without assuming the views store
1399:             * their location.  This returns null since the
1400:             * default is to not have any child views.
1401:             *
1402:             * @param index the index of the child, &gt;= 0 and &lt; getViewCount()
1403:             * @param a  the allocation to this view.
1404:             * @return the allocation to the child
1405:             */
1406:            public @Override
1407:            Shape getChildAllocation(int index, Shape a) {
1408:                if (a == null) {
1409:                    return null;
1410:                }
1411:
1412:                Rectangle alloc = reallocate(a); // returned rect can be modified
1413:                int this ViewAllocX = alloc.x;
1414:                int this ViewAllocY = alloc.y;
1415:
1416:                getChildren().getChildCoreAllocation(index, alloc); // alloc overwritten
1417:                alloc.x += this ViewAllocX;
1418:                alloc.y += this ViewAllocY;
1419:
1420:                // Add insets if necessary
1421:                ViewInsets insets = getInsets();
1422:                if (insets != null) {
1423:                    alloc.x += insets.getLeft();
1424:                    alloc.y += insets.getRight();
1425:                }
1426:
1427:                return alloc;
1428:            }
1429:
1430:            /**
1431:             * Fetches the child view index at the given point.
1432:             * This is called by the various View methods that
1433:             * need to calculate which child to forward a message
1434:             * to.
1435:             *
1436:             * @param x the X coordinate &gt;= 0
1437:             * @param y the Y coordinate &gt;= 0
1438:             * @param a the allocation to thid view
1439:             * @return index of the view that best represents the given visual
1440:             *   location or -1 if there are no children.
1441:             *   <br>
1442:             *   If the point is below the area of the first child view
1443:             *   then the index of the first child view is returned.
1444:             *   <br>
1445:             *   If the point is above the area of the last child view
1446:             *   then the index of the last child view is returned.
1447:             */
1448:            public int getViewIndexAtPoint(float x, float y, Shape a) {
1449:                Rectangle alloc = reallocate(a); // returned rect can be modified
1450:                x -= alloc.x;
1451:                y -= alloc.y;
1452:
1453:                // Subtract insets if necessary
1454:                ViewInsets insets = getInsets();
1455:                if (insets != null) {
1456:                    x -= insets.getLeft();
1457:                    y -= insets.getRight();
1458:                }
1459:
1460:                return getChildren().getChildIndexAtCorePoint(x, y);
1461:            }
1462:
1463:            /**
1464:             * Returns the child view index representing the given position in
1465:             * the model.
1466:             *
1467:             * @param offset the position >= 0.
1468:             * @param b either forward or backward bias.
1469:             * @return  index of the view representing the given position, or 
1470:             *   -1 if no view represents that position
1471:             */
1472:            public @Override
1473:            int getViewIndex(int offset, Position.Bias b) {
1474:                if (b == Position.Bias.Backward) {
1475:                    offset -= 1;
1476:                }
1477:
1478:                return getViewIndex(offset);
1479:            }
1480:
1481:            /**
1482:             * Returns the child view index representing the given position in
1483:             * the model.
1484:             *
1485:             * @param offset the position >= 0.
1486:             * @return  index of the view representing the given position, or 
1487:             *   -1 if no view represents that position
1488:             */
1489:            public int getViewIndex(int offset) {
1490:                return ViewUtilitiesImpl.findViewIndexBounded(this , offset);
1491:            }
1492:
1493:            /**
1494:             * Render the view using the given allocation and
1495:             * rendering surface.
1496:             *
1497:             * @param g the rendering surface to use
1498:             * @param a the allocated region to render into
1499:             * @see View#paint
1500:             */
1501:            public void paint(Graphics g, Shape a) {
1502:                Rectangle alloc = reallocate(a); // returned rect can be modified
1503:                getChildren().paintChildren(g, alloc);
1504:            }
1505:
1506:            /**
1507:             * Provides a mapping from the document model coordinate space
1508:             * to the coordinate space of the view mapped to it.
1509:             *
1510:             * @param pos the position to convert &gt;= 0
1511:             * @param a the allocated region to render into
1512:             * @param b the bias toward the previous character or the
1513:             *  next character represented by the offset, in case the
1514:             *  position is a boundary of two views.
1515:             * @return the bounding box of the given position is returned
1516:             * @exception BadLocationException  if the given position does
1517:             *   not represent a valid location in the associated document
1518:             * @exception IllegalArgumentException for an invalid bias argument
1519:             * @see View#viewToModel
1520:             */
1521:            public Shape modelToView(int pos, Shape a, Position.Bias b)
1522:                    throws BadLocationException {
1523:                int index = getViewIndex(pos, b);
1524:                if (index >= 0) {
1525:                    Shape ca = getChildAllocation(index, a);
1526:
1527:                    // forward to the child view
1528:                    ViewLayoutState child = getChild(index);
1529:                    View cv = child.getView();
1530:                    return cv.modelToView(pos, ca, b);
1531:                } else {
1532:                    throw new BadLocationException("Offset "
1533:                            + pos
1534:                            + " with bias "
1535:                            + b
1536:                            + " is outside of the view" //NOI18N
1537:                            + ", children = "
1538:                            + getViewCount() //NOI18N
1539:                            + (getViewCount() > 0 ? " covering offsets <"
1540:                                    + //NOI18N
1541:                                    getView(0).getStartOffset() + ", "
1542:                                    + //NOI18N
1543:                                    getView(getViewCount() - 1).getEndOffset()
1544:                                    + ">" : "") //NOI18N
1545:                    , pos);
1546:                }
1547:            }
1548:
1549:            /**
1550:             * Provides a mapping from the view coordinate space to the logical
1551:             * coordinate space of the model.  The biasReturn argument will be
1552:             * filled in to indicate that the point given is closer to the next
1553:             * character in the model or the previous character in the model.
1554:             * <p>
1555:             * This is expected to be called by the GUI thread, holding a
1556:             * read-lock on the associated model.  It is implemented to
1557:             * locate the child view and determine it's allocation with a
1558:             * lock on the ChildLocator object, and to call viewToModel
1559:             * on the child view with a lock on the ViewLayoutState object
1560:             * to avoid interaction with the layout thread.
1561:             *
1562:             * @param x the X coordinate &gt;= 0
1563:             * @param y the Y coordinate &gt;= 0
1564:             * @param a the allocated region to render into
1565:             * @return the location within the model that best represents the
1566:             *  given point in the view &gt;= 0.  The biasReturn argument will be
1567:             * filled in to indicate that the point given is closer to the next
1568:             * character in the model or the previous character in the model.
1569:             */
1570:            public int viewToModel(float x, float y, Shape a,
1571:                    Position.Bias[] biasReturn) {
1572:                int pos; // return position
1573:                int index; // child index to forward to
1574:                Shape ca; // child allocation
1575:
1576:                index = getViewIndexAtPoint(x, y, a);
1577:                index = Math.max(index, 0);
1578:                if (index < getViewCount()) {
1579:                    ca = getChildAllocation(index, a);
1580:
1581:                    // forward to the child view
1582:                    ViewLayoutState child = getChild(index);
1583:                    View v = child.getView();
1584:                    pos = v.viewToModel(x, y, ca, biasReturn);
1585:
1586:                } else { // at the end
1587:                    int endOff = getEndOffset();
1588:                    Document doc = getDocument();
1589:                    pos = (doc != null && doc.getLength() < endOff) ? doc
1590:                            .getLength() : endOff;
1591:                }
1592:
1593:                return pos;
1594:            }
1595:
1596:            /**
1597:             * Provides a way to determine the next visually represented model
1598:             * location that one might place a caret.  Some views may not be visible,
1599:             * they might not be in the same order found in the model, or they just
1600:             * might not allow access to some of the locations in the model.
1601:             *
1602:             * @param pos the position to convert &gt;= 0
1603:             * @param a the allocated region to render into
1604:             * @param direction the direction from the current position that can
1605:             *  be thought of as the arrow keys typically found on a keyboard;
1606:             *  this may be one of the following:
1607:             *  <ul>
1608:             *  <code>SwingConstants.WEST</code>
1609:             *  <code>SwingConstants.EAST</code>
1610:             *  <code>SwingConstants.NORTH</code>
1611:             *  <code>SwingConstants.SOUTH</code>
1612:             *  </ul>
1613:             * @param biasRet an array contain the bias that was checked
1614:             * @return the location within the model that best represents the next
1615:             *  location visual position
1616:             * @exception BadLocationException
1617:             * @exception IllegalArgumentException if <code>direction</code> is invalid
1618:             */
1619:            public @Override
1620:            int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
1621:                    int direction, Position.Bias[] biasRet)
1622:                    throws BadLocationException {
1623:
1624:                return ViewUtilitiesImpl.getNextVisualPositionFrom(this , pos,
1625:                        b, a, direction, biasRet);
1626:            }
1627:
1628:            /**
1629:             * Fetch the object representing the layout state of
1630:             * of the child at the given index.
1631:             *
1632:             * @param index the child index.
1633:             *   This must be a value &gt;= 0 and &lt; getViewCount().
1634:             * @throws IndexOutOfBoundsException in case the index was invalid.
1635:             */
1636:            protected final ViewLayoutState getChild(int index) {
1637:                return getChildren().getChild(index);
1638:            }
1639:
1640:            /**
1641:             * Get the index of the given child layout state in this view.
1642:             *
1643:             * @param child layout state which index in this view should be found.
1644:             * @return &gt;=0 integer index of the given child in this view.
1645:             *   Returns -1 if the given child is not present at the given index
1646:             *   in this view.
1647:             */
1648:            protected final int getChildIndex(ViewLayoutState child) {
1649:                return getChildren().getChildIndex(child);
1650:            }
1651:
1652:            /**
1653:             * Get the index of the given child layout state in this view.
1654:             *
1655:             * @param child layout state which index in this view should be found.
1656:             * @return &gt;=0 integer index of the given child in this view.
1657:             *   <b>Note:</b> This method does no checking whether the child
1658:             *   is really the child of this view.
1659:             */
1660:            protected final int getChildIndexNoCheck(ViewLayoutState child) {
1661:                return getChildren().getChildIndexNoCheck(child);
1662:            }
1663:
1664:            /**
1665:             * Can be overriden by subclasses to return
1666:             * a different children implementation.
1667:             */
1668:            protected GapBoxViewChildren createChildren() {
1669:                return new GapBoxViewChildren(this );
1670:            }
1671:
1672:            protected boolean useCustomReloadChildren() {
1673:                return (getElement() == null);
1674:            }
1675:
1676:            public @Override
1677:            void insertUpdate(DocumentEvent evt, Shape a, ViewFactory f) {
1678:                // #38993 - until parent is set - do not do anything
1679:                if (children == null && getParent() == null) {
1680:                    return;
1681:                }
1682:
1683:                if (useCustomReloadChildren()) {
1684:                    customInsertUpdate(evt, a, f);
1685:                } else { // custom insert update
1686:                    super .insertUpdate(evt, a, f); // default element-based update
1687:                }
1688:            }
1689:
1690:            protected void customInsertUpdate(DocumentEvent evt, Shape a,
1691:                    ViewFactory f) {
1692:                int[] offsetRange = getInsertUpdateRebuildOffsetRange(evt);
1693:                if (offsetRange != null) {
1694:                    offsetRebuild(offsetRange[0], offsetRange[1]);
1695:                } else {
1696:                    forwardUpdate(null, evt, a, f);
1697:                }
1698:            }
1699:
1700:            /**
1701:             * Get the offset area in which the views should be rebuilt
1702:             * in reaction to insert update in the underlying document.
1703:             *
1704:             * @param evt document event for the document modification.
1705:             * @return two-item integer array containing starting and ending offset
1706:             *  of the area to be rebuilt or <code>null</code> in case
1707:             *  no views should be rebuilt.
1708:             */
1709:            protected int[] getInsertUpdateRebuildOffsetRange(DocumentEvent evt) {
1710:                DocumentEvent.ElementChange lineChange = evt.getChange(evt
1711:                        .getDocument().getDefaultRootElement());
1712:                if (lineChange == null) {
1713:                    return null;
1714:                }
1715:
1716:                int startOffset = evt.getOffset();
1717:                int endOffset = startOffset + evt.getLength();
1718:                int[] offsetRange = new int[] { startOffset, endOffset };
1719:                Element[] addedLines = lineChange.getChildrenAdded();
1720:                ElementUtilities.updateOffsetRange(addedLines, offsetRange);
1721:                Element[] removedLines = lineChange.getChildrenRemoved();
1722:                ElementUtilities.updateOffsetRange(removedLines, offsetRange);
1723:                return offsetRange;
1724:            }
1725:
1726:            public @Override
1727:            void removeUpdate(DocumentEvent evt, Shape a, ViewFactory f) {
1728:                // #38993 - until parent is set - do not do anything
1729:                if (children == null && getParent() == null) {
1730:                    return;
1731:                }
1732:
1733:                if (useCustomReloadChildren()) {
1734:                    customRemoveUpdate(evt, a, f);
1735:                } else {
1736:                    super .removeUpdate(evt, a, f); // default element-based update
1737:                }
1738:            }
1739:
1740:            protected void customRemoveUpdate(DocumentEvent evt, Shape a,
1741:                    ViewFactory f) {
1742:                int[] offsetRange = getRemoveUpdateRebuildOffsetRange(evt);
1743:                if (offsetRange != null) {
1744:                    offsetRebuild(offsetRange[0], offsetRange[1]);
1745:                } else {
1746:                    forwardUpdate(null, evt, a, f);
1747:                }
1748:            }
1749:
1750:            /**
1751:             * Get the offset area in which the views should be rebuilt
1752:             * in reaction to insert update in the underlying document.
1753:             *
1754:             * @param evt document event for the document modification.
1755:             * @return two-item integer array containing starting and ending offset
1756:             *  of the area to be rebuilt or <code>null</code> in case
1757:             *  no views should be rebuilt.
1758:             */
1759:            protected int[] getRemoveUpdateRebuildOffsetRange(DocumentEvent evt) {
1760:                DocumentEvent.ElementChange lineChange = evt.getChange(evt
1761:                        .getDocument().getDefaultRootElement());
1762:                if (lineChange == null) {
1763:                    return null;
1764:                }
1765:
1766:                int startOffset = evt.getOffset();
1767:                int endOffset = startOffset;
1768:                int[] offsetRange = new int[] { startOffset, endOffset };
1769:                Element[] addedLines = lineChange.getChildrenAdded();
1770:                ElementUtilities.updateOffsetRange(addedLines, offsetRange);
1771:                Element[] removedLines = lineChange.getChildrenRemoved();
1772:                ElementUtilities.updateOffsetRange(removedLines, offsetRange);
1773:                return offsetRange;
1774:            }
1775:
1776:            public @Override
1777:            void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
1778:                // #38993 - until parent is set - do not do anything
1779:                if (children == null && getParent() == null) {
1780:                    return;
1781:                }
1782:
1783:                super .changedUpdate(e, a, f);
1784:            }
1785:
1786:            /**
1787:             * Load the children in the selected range of offsets.
1788:             * <br>
1789:             * Some implementations may reload all the present children if necessary.
1790:             *
1791:             * @param index index at which the views should be added/replaced.
1792:             * @param removeLength number of removed children views. It is useful
1793:             *  when rebuilding children for a portion of the view.
1794:             * @param startOffset starting offset of the loading. It can be -1
1795:             *  to indicate the loading from <code>View.getStartOffset()</code>.
1796:             * @param endOffset ending offset of the loading. It can be -1
1797:             *  to indicate the loading till <code>View.getEndOffset()</code>.
1798:             */
1799:            protected void reloadChildren(int index, int removeLength,
1800:                    int startOffset, int endOffset) {
1801:                if (useCustomReloadChildren()) {
1802:                    if (startOffset == -1) {
1803:                        startOffset = getStartOffset();
1804:                    }
1805:                    if (endOffset == -1) {
1806:                        endOffset = getEndOffset();
1807:                    }
1808:
1809:                    customReloadChildren(index, removeLength, startOffset,
1810:                            endOffset);
1811:
1812:                } else { // element load of children
1813:                    Element elem = getElement();
1814:                    int startIndex;
1815:                    if (startOffset == -1) {
1816:                        startIndex = 0;
1817:                    } else {
1818:                        if (index == 0) {
1819:                            if (startOffset != getStartOffset()) {
1820:                                throw new IllegalArgumentException(
1821:                                        "Invalid startOffset=" + startOffset); // NOI18N
1822:                            }
1823:                        } else {
1824:                            if (startOffset != getView(index - 1)
1825:                                    .getEndOffset()) {
1826:                                throw new IllegalArgumentException(
1827:                                        "Invalid startOffset=" + startOffset); // NOI18N
1828:                            }
1829:                        }
1830:                        startIndex = index;
1831:                    }
1832:
1833:                    int endIndex = (endOffset == -1) ? elem.getElementCount()
1834:                            : elem.getElementIndex(endOffset - 1) + 1;
1835:
1836:                    // TODO uncomment            assert (startIndex == index);
1837:
1838:                    elementReloadChildren(index, removeLength, endIndex
1839:                            - startIndex);
1840:                }
1841:            }
1842:
1843:            /**
1844:             * Loads child views by tracking child elements of the element
1845:             * this view was created for.
1846:             * @param index index at which the views should be added/replaced.
1847:             * @param removeLength number of removed children views. It is useful
1848:             *  when rebuilding children for a portion of the view.
1849:             * @param elementIndex index of the first child element for which
1850:             *  the view should be created
1851:             * @param elementCount number of elements for which the views should be created.
1852:             */
1853:            protected void elementReloadChildren(int index, int removeLength,
1854:                    int elementCount) {
1855:
1856:                Element e = getElement();
1857:                View[] added = null;
1858:
1859:                ViewFactory f = getViewFactory();
1860:                // Null view factory can mean that one of the grand parents is already disconnected
1861:                // from the view hierarchy. No added children for null factory.
1862:
1863:                if (f != null) {
1864:                    added = new View[elementCount];
1865:                    for (int i = 0; i < elementCount; i++) {
1866:                        added[i] = f.create(e.getElement(index + i));
1867:                    }
1868:
1869:                }
1870:
1871:                replace(index, removeLength, added);
1872:            }
1873:
1874:            /**
1875:             * Loads child views in a custom way.
1876:             *
1877:             * @param index index at which the views should be added/replaced.
1878:             * @param removeLength number of removed children views. It is useful
1879:             *  when rebuilding children for a portion of the view.
1880:             * @param startOffset starting offset from which the loading starts.
1881:             * @param endOffset ending offset where the loading ends.
1882:             */
1883:            protected void customReloadChildren(int index, int removeLength,
1884:                    int startOffset, int endOffset) {
1885:
1886:                View[] added = null;
1887:                ViewFactory f = getViewFactory();
1888:                // Null view factory can mean that one of the grand parents is already disconnected
1889:                // from the view hierarchy. No added children for null factory.
1890:
1891:                if (f != null) {
1892:                    Element elem = getElement();
1893:
1894:                    int elementCount = elem.getElementCount();
1895:                    int elementIndex = (elem != null) ? elem
1896:                            .getElementIndex(startOffset) : -1;
1897:                    if (elementIndex >= elementCount) {
1898:                        return; // Create no after last element
1899:                    }
1900:                    List childViews = new ArrayList();
1901:                    int viewCount = getViewCount();
1902:
1903:                    loop: while (startOffset < endOffset) {
1904:                        // Create custom child
1905:                        View childView = createCustomView(f, startOffset,
1906:                                endOffset, elementIndex);
1907:                        if (childView == null) {
1908:                            throw new IllegalStateException(
1909:                                    "No view created for area (" // NOI18N
1910:                                            + startOffset + ", "
1911:                                            + endOffset
1912:                                            + ")"); // NOI18N
1913:                        }
1914:
1915:                        // Assuming childView.getStartOffset() is at startOffset
1916:                        childViews.add(childView);
1917:
1918:                        // Update elementIndex
1919:                        int childViewEndOffset = childView.getEndOffset();
1920:                        while (childViewEndOffset > endOffset) {
1921:                            /*                    throw new IllegalStateException(
1922:                             "childViewEndOffset=" + childViewEndOffset // NOI18N
1923:                             + " > endOffset=" + endOffset // NOI18N
1924:                             );
1925:                             */
1926:                            /* The created child view interferes with a view
1927:                             * that is still present and which is not planned
1928:                             * to be removed.
1929:                             * This can happen e.g. when a fold hierarchy change
1930:                             * (caused by a document change) is fired
1931:                             * prior to the document change gets fired
1932:                             * to the view hierarchy.
1933:                             * The fix for that situation is to continue to remove
1934:                             * the present views until the end of the created view will match
1935:                             * a beginning of a present view.
1936:                             */
1937:                            if (index + removeLength >= viewCount) {
1938:                                // Should not happen but can't remove past the last view
1939:                                break;
1940:                            }
1941:                            endOffset = getView(index + removeLength)
1942:                                    .getEndOffset();
1943:                            removeLength++;
1944:                            if (debugRebuild) {
1945:                                /*DEBUG*/System.err
1946:                                        .println("GapBoxView.customReloadChildren(): Increased removeLength to " // NOI18N
1947:                                                + removeLength
1948:                                                + ", eo="
1949:                                                + endOffset // NOI18N
1950:                                        );
1951:                            }
1952:                        }
1953:
1954:                        Element childElem = elem.getElement(elementIndex);
1955:                        while (childElem.getEndOffset() <= childViewEndOffset) {
1956:                            elementIndex++;
1957:                            if (elementIndex == elementCount) {
1958:                                // #115034
1959:                                break loop;
1960:                            }
1961:                            childElem = elem.getElement(elementIndex);
1962:                        }
1963:
1964:                        startOffset = childViewEndOffset;
1965:                    }
1966:
1967:                    added = new View[childViews.size()];
1968:                    childViews.toArray(added);
1969:                }
1970:
1971:                replace(index, removeLength, added);
1972:            }
1973:
1974:            /**
1975:             * Create custom child view starting at <code>startOffset</code>.
1976:             *
1977:             * @param f view factory to be used.
1978:             * @param startOffset offset at which the created view must start.
1979:             * @param maxEndOffset maximum ending offset to which the created view
1980:             *  may span.
1981:             * @param elementIndex index of the child element that best represents
1982:             *  the startOffset. The element is child of the element that this view
1983:             *  is responsible for. If this view is not based by element then this
1984:             *  parameter will be -1.
1985:             */
1986:            protected View createCustomView(ViewFactory f, int startOffset,
1987:                    int maxEndOffset, int elementIndex) {
1988:
1989:                /*
1990:                 // Default implementation delegating to view factory
1991:                 // is here just to show the possible functionality
1992:                 // and clarify the variables
1993:
1994:                 View v;
1995:                 if (parentElement != null) {
1996:                 Element elem = parentElement.getElement(elementIndex);
1997:                 if (elem.getStartOffset() != startOffset) {
1998:                 throw new IllegalStateException("Not element boundary");
1999:                 }
2000:
2001:                 if (elem.getEndOffset() > maxEndOffset) {
2002:                 throw new IllegalStateException("Beyond maximum ending offset");
2003:                 }
2004:
2005:                 v = f.create(elem);
2006:
2007:                 } else { // no element - need more information
2008:                 return null;
2009:                 }
2010:                 */
2011:
2012:                return null;
2013:            }
2014:
2015:            /**
2016:             * Subclasses may override this method and deallocate resources
2017:             * bound to presence of children.
2018:             * <br>
2019:             * It's called by {@link #releaseChildren()} to unallocate
2020:             * the resources for children.
2021:             *
2022:             * <p>
2023:             * Once this method finishes all the children will
2024:             * be set null as a parent and the reference
2025:             * to children will be cleared.
2026:             */
2027:            protected void unloadChildren() {
2028:            }
2029:
2030:            /**
2031:             * New ViewLayoutState records are created through
2032:             * this method to allow subclasses the extend
2033:             * the ViewLayoutState records to do/hold more
2034:             */
2035:            protected ViewLayoutState createChild(View v) {
2036:                ViewLayoutState child;
2037:                if (v instanceof  ViewLayoutState) {
2038:                    child = (ViewLayoutState) v;
2039:                } else { // view does not implement ViewLayoutState
2040:                    child = createDefaultChild(v);
2041:                }
2042:                return child;
2043:            }
2044:
2045:            /**
2046:             * Return default implementation of the view layout state wrapper.
2047:             */
2048:            protected ViewLayoutState createDefaultChild(View v) {
2049:                return new SimpleViewLayoutState(v); // only handle preferred spans
2050:            }
2051:
2052:            protected final boolean isMajorAxisPreferenceChanged() {
2053:                return (isStatusBitsNonZero(MAJOR_AXIS_PREFERENCE_CHANGED_BIT));
2054:            }
2055:
2056:            protected void markMajorAxisPreferenceChanged() {
2057:                setStatusBits(MAJOR_AXIS_PREFERENCE_CHANGED_BIT);
2058:            }
2059:
2060:            protected final boolean isMinorAxisPreferenceChanged() {
2061:                return (isStatusBitsNonZero(MINOR_AXIS_PREFERENCE_CHANGED_BIT));
2062:            }
2063:
2064:            protected void markMinorAxisPreferenceChanged() {
2065:                setStatusBits(MINOR_AXIS_PREFERENCE_CHANGED_BIT);
2066:            }
2067:
2068:            protected final void resetAxesPreferenceChanged() {
2069:                clearStatusBits(MAJOR_AXIS_PREFERENCE_CHANGED_BIT
2070:                        | MINOR_AXIS_PREFERENCE_CHANGED_BIT);
2071:            }
2072:
2073:            /**
2074:             * Get the span along an axis that is taken up by the view insets.
2075:             *
2076:             * @param axis the axis to determine the total insets along,
2077:             *  either X_AXIS or Y_AXIS.
2078:             * @return span along the given axis taken up by view insets.
2079:             */
2080:            protected final float getInsetSpan(int axis) {
2081:                //        assert ViewUtilities.isAxisValid(axis);
2082:
2083:                ViewInsets insets = getInsets();
2084:                return (insets != null) ? ((axis == X_AXIS) ? insets
2085:                        .getLeftRight() : insets.getTopBottom()) : 0;
2086:            }
2087:
2088:            /**
2089:             * Get the span along major axis that is taken up by the view insets.
2090:             *
2091:             * @return span along major axis taken up by view insets.
2092:             */
2093:            protected final float getMajorAxisInsetSpan() {
2094:                ViewInsets insets = getInsets();
2095:                return (insets != null) ? (isXMajorAxis() ? insets
2096:                        .getLeftRight() : insets.getTopBottom()) : 0;
2097:            }
2098:
2099:            /**
2100:             * Get the span along minor axis that is taken up by the view insets.
2101:             *
2102:             * @return span along minor axis taken up by view insets.
2103:             */
2104:            protected final float getMinorAxisInsetSpan() {
2105:                ViewInsets insets = getInsets();
2106:                return (insets != null) ? (isXMajorAxis() ? insets
2107:                        .getTopBottom() : insets.getLeftRight()) : 0;
2108:            }
2109:
2110:            protected final int getStatusBits(int bits) {
2111:                return (statusBits & bits);
2112:            }
2113:
2114:            protected final boolean isStatusBitsNonZero(int bits) {
2115:                return (getStatusBits(bits) != 0);
2116:            }
2117:
2118:            protected final void setStatusBits(int bits) {
2119:                statusBits |= bits;
2120:            }
2121:
2122:            protected final void clearStatusBits(int bits) {
2123:                statusBits &= ~bits;
2124:            }
2125:
2126:            /**
2127:             * Reallocate the view to the new size given by the passed shape.
2128:             *
2129:             * @param a shape to which to reallocate the view.
2130:             * @return rectangle bounding the shape. The returned rectangle
2131:             *  can be mutated.
2132:             */
2133:            protected Rectangle reallocate(Shape a) {
2134:                Rectangle alloc = a.getBounds(); // makes a fresh rectangle instance
2135:
2136:                setSize(alloc.width, alloc.height); // set new size
2137:
2138:                return alloc;
2139:            }
2140:
2141:            // Implements FlyView.Parent
2142:            public int getStartOffset(int childViewIndex) {
2143:                return getChildren().getChildStartOffset(childViewIndex);
2144:            }
2145:
2146:            // Implements FlyView.Parent
2147:            public int getEndOffset(int childViewIndex) {
2148:                return getChildren().getChildEndOffset(childViewIndex);
2149:            }
2150:
2151:            public String childToString(int childIndex) {
2152:                StringBuffer sb = new StringBuffer();
2153:                appendChildToStringBuffer(sb, childIndex, 0);
2154:                return sb.toString();
2155:            }
2156:
2157:            public void appendChildToStringBuffer(StringBuffer sb,
2158:                    int childIndex, int indent) {
2159:                ViewLayoutState child = getChild(childIndex);
2160:                View childView = child.getView();
2161:                Document doc = getDocument();
2162:                boolean isFly = child.isFlyweight();
2163:                boolean isEstimated = (childView instanceof  EstimatedSpanView)
2164:                        && ((EstimatedSpanView) childView).isEstimatedSpan();
2165:                boolean layoutValid = child.isLayoutValid();
2166:                double offset = children.getMajorAxisOffset(childIndex);
2167:                boolean indexesDiffer = !isFly
2168:                        && (getChildIndexNoCheck(child) != childIndex);
2169:                boolean showRaw = false; // change for debugging purposes
2170:
2171:                sb.append((isFly ? 'F' : 'R')); // flyweight / regular NOI18N
2172:                sb.append(':');
2173:                if (indexesDiffer) {
2174:                    sb.append(" WRONG-INDEX=" + getChildIndexNoCheck(child)); // NOI18N
2175:                }
2176:                if (showRaw) {
2177:                    sb.append("rI=" + child.getViewRawIndex()); // NOI18N
2178:                }
2179:                sb.append('<');
2180:                appendOffsetInfo(sb, doc, childView.getStartOffset());
2181:                sb.append(',');
2182:                appendOffsetInfo(sb, doc, childView.getEndOffset());
2183:                sb.append('>');
2184:
2185:                sb.append(", major=").append(
2186:                        child.getLayoutMajorAxisPreferredSpan()); // NOI18N
2187:                sb.append("(off=").append(offset); // NOI18N
2188:
2189:                if (showRaw) {
2190:                    sb.append('(').append(child.getLayoutMajorAxisRawOffset())
2191:                            .append(')'); // NOI18N
2192:                }
2193:
2194:                sb.append("), minor[pref=").append(
2195:                        child.getLayoutMinorAxisPreferredSpan()); // NOI18N
2196:                sb.append(", min=").append(
2197:                        child.getLayoutMinorAxisMinimumSpan()); // NOI18N
2198:                sb.append(", max=").append(
2199:                        child.getLayoutMinorAxisMaximumSpan()); // NOI18N
2200:                sb.append("] "); // NOI18N
2201:                sb.append(isEstimated ? "E" : ""); // NOI18N
2202:                sb.append(layoutValid ? "" : "I"); // NOI18N
2203:
2204:                // Possibly add view description if GapBoxView
2205:                if (childView instanceof  GapBoxView) {
2206:                    sb.append("\n"); // NOI18N
2207:                    appendSpaces(sb, indent + 4);
2208:                    sb.append("VIEW: "); // NOI18N
2209:                    sb.append(childView.toString());
2210:                    sb.append(((GapBoxView) childView)
2211:                            .childrenToString(indent + 4));
2212:                }
2213:            }
2214:
2215:            private static void appendOffsetInfo(StringBuffer sb, Document doc,
2216:                    int offset) {
2217:                sb.append(offset);
2218:                sb.append('[');
2219:                // TODO - removed dependency on o.n.e.Utilities
2220:                sb.append(org.netbeans.editor.Utilities.debugPosition(
2221:                        (org.netbeans.editor.BaseDocument) doc, offset));
2222:                sb.append(']');
2223:            }
2224:
2225:            private static void appendSpaces(StringBuffer sb, int spaceCount) {
2226:                while (--spaceCount >= 0) {
2227:                    sb.append(' ');
2228:                }
2229:            }
2230:
2231:            public String childrenToString() {
2232:                return childrenToString(0);
2233:            }
2234:
2235:            public String childrenToString(int indent) {
2236:                StringBuffer sb = new StringBuffer();
2237:
2238:                int viewCount = getViewCount();
2239:                int totalDigitCount = Integer.toString(viewCount).length();
2240:                for (int i = 0; i < viewCount; i++) {
2241:                    sb.append('\n');
2242:                    String iToString = Integer.toString(i);
2243:                    appendSpaces(sb, indent
2244:                            + (totalDigitCount - iToString.length()));
2245:
2246:                    sb.append('[');
2247:                    sb.append(iToString);
2248:                    sb.append("]: "); // NOI18N
2249:                    appendChildToStringBuffer(sb, i, indent);
2250:                }
2251:
2252:                return sb.toString();
2253:            }
2254:
2255:            public @Override
2256:            String toString() {
2257:                // Must not return anything about children because
2258:                // that could cause them to be initialized (e.g. by getViewCount())
2259:                return "lastMajorAxisPreferredSpan="
2260:                        + lastMajorAxisPreferredSpan // NOI18N
2261:                        + ", lastMinorAxisPreferredSpan="
2262:                        + lastMinorAxisPreferredSpan // NOI18N
2263:                        + ", minorAxisAssignedSpan="
2264:                        + getMinorAxisAssignedSpan(); // NOI18N
2265:            }
2266:
2267:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.