1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing.text; 26 27 import java.awt.*; 28 import javax.swing.SwingConstants; 29 import javax.swing.event.*; 30 31 /** 32 * <p> 33 * A very important part of the text package is the <code>View</code> class. 34 * As the name suggests it represents a view of the text model, 35 * or a piece of the text model. 36 * It is this class that is responsible for the look of the text component. 37 * The view is not intended to be some completely new thing that one must 38 * learn, but rather is much like a lightweight component. 39 * <p> 40 By default, a view is very light. It contains a reference to the parent 41 view from which it can fetch many things without holding state, and it 42 contains a reference to a portion of the model (<code>Element</code>). 43 A view does not 44 have to exactly represent an element in the model, that is simply a typical 45 and therefore convenient mapping. A view can alternatively maintain a couple 46 of Position objects to maintain its location in the model (i.e. represent 47 a fragment of an element). This is typically the result of formatting where 48 views have been broken down into pieces. The convenience of a substantial 49 relationship to the element makes it easier to build factories to produce the 50 views, and makes it easier to keep track of the view pieces as the model is 51 changed and the view must be changed to reflect the model. Simple views 52 therefore represent an Element directly and complex views do not. 53 <p> 54 A view has the following responsibilities: 55 <dl> 56 57 <dt><b>Participate in layout.</b> 58 <dd> 59 <p>The view has a <code>setSize</code> method which is like 60 <code>doLayout</code> and <code>setSize</code> in <code>Component</code> combined. 61 The view has a <code>preferenceChanged</code> method which is 62 like <code>invalidate</code> in <code>Component</code> except that one can 63 invalidate just one axis 64 and the child requesting the change is identified. 65 <p>A View expresses the size that it would like to be in terms of three 66 values, a minimum, a preferred, and a maximum span. Layout in a view is 67 can be done independently upon each axis. For a properly functioning View 68 implementation, the minimum span will be <= the preferred span which in turn 69 will be <= the maximum span. 70 </p> 71 <p style="text-align:center"><img src="doc-files/View-flexibility.jpg" 72 alt="The above text describes this graphic."> 73 <p>The minimum set of methods for layout are: 74 <ul> 75 <li>{@link #getMinimumSpan(int) getMinimumSpan} 76 <li>{@link #getPreferredSpan(int) getPreferredSpan} 77 <li>{@link #getMaximumSpan(int) getMaximumSpan} 78 <li>{@link #getAlignment(int) getAlignment} 79 <li>{@link #preferenceChanged(javax.swing.text.View, boolean, boolean) preferenceChanged} 80 <li>{@link #setSize(float, float) setSize} 81 </ul> 82 83 <p>The <code>setSize</code> method should be prepared to be called a number of times 84 (i.e. It may be called even if the size didn't change). 85 The <code>setSize</code> method 86 is generally called to make sure the View layout is complete prior to trying 87 to perform an operation on it that requires an up-to-date layout. A view's 88 size should <em>always</em> be set to a value within the minimum and maximum 89 span specified by that view. Additionally, the view must always call the 90 <code>preferenceChanged</code> method on the parent if it has changed the 91 values for the 92 layout it would like, and expects the parent to honor. The parent View is 93 not required to recognize a change until the <code>preferenceChanged</code> 94 has been sent. 95 This allows parent View implementations to cache the child requirements if 96 desired. The calling sequence looks something like the following: 97 </p> 98 <p style="text-align:center"> 99 <img src="doc-files/View-layout.jpg" 100 alt="Sample calling sequence between parent view and child view: 101 setSize, getMinimum, getPreferred, getMaximum, getAlignment, setSize"> 102 <p>The exact calling sequence is up to the layout functionality of 103 the parent view (if the view has any children). The view may collect 104 the preferences of the children prior to determining what it will give 105 each child, or it might iteratively update the children one at a time. 106 </p> 107 108 <dt><b>Render a portion of the model.</b> 109 <dd> 110 <p>This is done in the paint method, which is pretty much like a component 111 paint method. Views are expected to potentially populate a fairly large 112 tree. A <code>View</code> has the following semantics for rendering: 113 </p> 114 <ul> 115 <li>The view gets its allocation from the parent at paint time, so it 116 must be prepared to redo layout if the allocated area is different from 117 what it is prepared to deal with. 118 <li>The coordinate system is the same as the hosting <code>Component</code> 119 (i.e. the <code>Component</code> returned by the 120 {@link #getContainer getContainer} method). 121 This means a child view lives in the same coordinate system as the parent 122 view unless the parent has explicitly changed the coordinate system. 123 To schedule itself to be repainted a view can call repaint on the hosting 124 <code>Component</code>. 125 <li>The default is to <em>not clip</em> the children. It is more efficient 126 to allow a view to clip only if it really feels it needs clipping. 127 <li>The <code>Graphics</code> object given is not initialized in any way. 128 A view should set any settings needed. 129 <li>A <code>View</code> is inherently transparent. While a view may render into its 130 entire allocation, typically a view does not. Rendering is performed by 131 traversing down the tree of <code>View</code> implementations. 132 Each <code>View</code> is responsible 133 for rendering its children. This behavior is depended upon for thread 134 safety. While view implementations do not necessarily have to be implemented 135 with thread safety in mind, other view implementations that do make use of 136 concurrency can depend upon a tree traversal to guarantee thread safety. 137 <li>The order of views relative to the model is up to the implementation. 138 Although child views will typically be arranged in the same order that they 139 occur in the model, they may be visually arranged in an entirely different 140 order. View implementations may have Z-Order associated with them if the 141 children are overlapping. 142 </ul> 143 <p>The methods for rendering are: 144 <ul> 145 <li>{@link #paint(java.awt.Graphics, java.awt.Shape) paint} 146 </ul> 147 148 <dt><b>Translate between the model and view coordinate systems.</b> 149 <dd> 150 <p>Because the view objects are produced from a factory and therefore cannot 151 necessarily be counted upon to be in a particular pattern, one must be able 152 to perform translation to properly locate spatial representation of the model. 153 The methods for doing this are: 154 <ul> 155 <li>{@link #modelToView(int, javax.swing.text.Position.Bias, int, javax.swing.text.Position.Bias, java.awt.Shape) modelToView} 156 <li>{@link #viewToModel(float, float, java.awt.Shape, javax.swing.text.Position.Bias[]) viewToModel} 157 <li>{@link #getDocument() getDocument} 158 <li>{@link #getElement() getElement} 159 <li>{@link #getStartOffset() getStartOffset} 160 <li>{@link #getEndOffset() getEndOffset} 161 </ul> 162 <p>The layout must be valid prior to attempting to make the translation. 163 The translation is not valid, and must not be attempted while changes 164 are being broadcasted from the model via a <code>DocumentEvent</code>. 165 </p> 166 167 <dt><b>Respond to changes from the model.</b> 168 <dd> 169 <p>If the overall view is represented by many pieces (which is the best situation 170 if one want to be able to change the view and write the least amount of new code), 171 it would be impractical to have a huge number of <code>DocumentListener</code>s. 172 If each 173 view listened to the model, only a few would actually be interested in the 174 changes broadcasted at any given time. Since the model has no knowledge of 175 views, it has no way to filter the broadcast of change information. The view 176 hierarchy itself is instead responsible for propagating the change information. 177 At any level in the view hierarchy, that view knows enough about its children to 178 best distribute the change information further. Changes are therefore broadcasted 179 starting from the root of the view hierarchy. 180 The methods for doing this are: 181 <ul> 182 <li>{@link #insertUpdate insertUpdate} 183 <li>{@link #removeUpdate removeUpdate} 184 <li>{@link #changedUpdate changedUpdate} 185 </ul> 186 <p> 187 </dl> 188 * 189 * @author Timothy Prinzing 190 */ 191 public abstract class View implements SwingConstants { 192 193 /** 194 * Creates a new <code>View</code> object. 195 * 196 * @param elem the <code>Element</code> to represent 197 */ View(Element elem)198 public View(Element elem) { 199 this.elem = elem; 200 } 201 202 /** 203 * Returns the parent of the view. 204 * 205 * @return the parent, or <code>null</code> if none exists 206 */ getParent()207 public View getParent() { 208 return parent; 209 } 210 211 /** 212 * Returns a boolean that indicates whether 213 * the view is visible or not. By default 214 * all views are visible. 215 * 216 * @return always returns true 217 */ isVisible()218 public boolean isVisible() { 219 return true; 220 } 221 222 223 /** 224 * Determines the preferred span for this view along an 225 * axis. 226 * 227 * @param axis may be either <code>View.X_AXIS</code> or 228 * <code>View.Y_AXIS</code> 229 * @return the span the view would like to be rendered into. 230 * Typically the view is told to render into the span 231 * that is returned, although there is no guarantee. 232 * The parent may choose to resize or break the view 233 * @see View#getPreferredSpan 234 */ getPreferredSpan(int axis)235 public abstract float getPreferredSpan(int axis); 236 237 /** 238 * Determines the minimum span for this view along an 239 * axis. 240 * 241 * @param axis may be either <code>View.X_AXIS</code> or 242 * <code>View.Y_AXIS</code> 243 * @return the minimum span the view can be rendered into 244 * @see View#getPreferredSpan 245 */ getMinimumSpan(int axis)246 public float getMinimumSpan(int axis) { 247 int w = getResizeWeight(axis); 248 if (w == 0) { 249 // can't resize 250 return getPreferredSpan(axis); 251 } 252 return 0; 253 } 254 255 /** 256 * Determines the maximum span for this view along an 257 * axis. 258 * 259 * @param axis may be either <code>View.X_AXIS</code> or 260 * <code>View.Y_AXIS</code> 261 * @return the maximum span the view can be rendered into 262 * @see View#getPreferredSpan 263 */ getMaximumSpan(int axis)264 public float getMaximumSpan(int axis) { 265 int w = getResizeWeight(axis); 266 if (w == 0) { 267 // can't resize 268 return getPreferredSpan(axis); 269 } 270 return Integer.MAX_VALUE; 271 } 272 273 /** 274 * Child views can call this on the parent to indicate that 275 * the preference has changed and should be reconsidered 276 * for layout. By default this just propagates upward to 277 * the next parent. The root view will call 278 * <code>revalidate</code> on the associated text component. 279 * 280 * @param child the child view 281 * @param width true if the width preference has changed 282 * @param height true if the height preference has changed 283 * @see javax.swing.JComponent#revalidate 284 */ preferenceChanged(View child, boolean width, boolean height)285 public void preferenceChanged(View child, boolean width, boolean height) { 286 View parent = getParent(); 287 if (parent != null) { 288 parent.preferenceChanged(this, width, height); 289 } 290 } 291 292 /** 293 * Determines the desired alignment for this view along an 294 * axis. The desired alignment is returned. This should be 295 * a value >= 0.0 and <= 1.0, where 0 indicates alignment at 296 * the origin and 1.0 indicates alignment to the full span 297 * away from the origin. An alignment of 0.5 would be the 298 * center of the view. 299 * 300 * @param axis may be either <code>View.X_AXIS</code> or 301 * <code>View.Y_AXIS</code> 302 * @return the value 0.5 303 */ getAlignment(int axis)304 public float getAlignment(int axis) { 305 return 0.5f; 306 } 307 308 /** 309 * Renders using the given rendering surface and area on that 310 * surface. The view may need to do layout and create child 311 * views to enable itself to render into the given allocation. 312 * 313 * @param g the rendering surface to use 314 * @param allocation the allocated region to render into 315 */ paint(Graphics g, Shape allocation)316 public abstract void paint(Graphics g, Shape allocation); 317 318 /** 319 * Establishes the parent view for this view. This is 320 * guaranteed to be called before any other methods if the 321 * parent view is functioning properly. This is also 322 * the last method called, since it is called to indicate 323 * the view has been removed from the hierarchy as 324 * well. When this method is called to set the parent to 325 * null, this method does the same for each of its children, 326 * propagating the notification that they have been 327 * disconnected from the view tree. If this is 328 * reimplemented, <code>super.setParent()</code> should 329 * be called. 330 * 331 * @param parent the new parent, or <code>null</code> if the view is 332 * being removed from a parent 333 */ setParent(View parent)334 public void setParent(View parent) { 335 // if the parent is null then propogate down the view tree 336 if (parent == null) { 337 for (int i = 0; i < getViewCount(); i++) { 338 if (getView(i).getParent() == this) { 339 // in FlowView.java view might be referenced 340 // from two super-views as a child. see logicalView 341 getView(i).setParent(null); 342 } 343 } 344 } 345 this.parent = parent; 346 } 347 348 /** 349 * Returns the number of views in this view. Since 350 * the default is to not be a composite view this 351 * returns 0. 352 * 353 * @return the number of views >= 0 354 * @see View#getViewCount 355 */ getViewCount()356 public int getViewCount() { 357 return 0; 358 } 359 360 /** 361 * Gets the <i>n</i>th child view. Since there are no 362 * children by default, this returns <code>null</code>. 363 * 364 * @param n the number of the view to get, >= 0 && < getViewCount() 365 * @return the view 366 */ getView(int n)367 public View getView(int n) { 368 return null; 369 } 370 371 372 /** 373 * Removes all of the children. This is a convenience 374 * call to <code>replace</code>. 375 * 376 * @since 1.3 377 */ removeAll()378 public void removeAll() { 379 replace(0, getViewCount(), null); 380 } 381 382 /** 383 * Removes one of the children at the given position. 384 * This is a convenience call to <code>replace</code>. 385 * @since 1.3 386 */ remove(int i)387 public void remove(int i) { 388 replace(i, 1, null); 389 } 390 391 /** 392 * Inserts a single child view. This is a convenience 393 * call to <code>replace</code>. 394 * 395 * @param offs the offset of the view to insert before >= 0 396 * @param v the view 397 * @see #replace 398 * @since 1.3 399 */ insert(int offs, View v)400 public void insert(int offs, View v) { 401 View[] one = new View[1]; 402 one[0] = v; 403 replace(offs, 0, one); 404 } 405 406 /** 407 * Appends a single child view. This is a convenience 408 * call to <code>replace</code>. 409 * 410 * @param v the view 411 * @see #replace 412 * @since 1.3 413 */ append(View v)414 public void append(View v) { 415 View[] one = new View[1]; 416 one[0] = v; 417 replace(getViewCount(), 0, one); 418 } 419 420 /** 421 * Replaces child views. If there are no views to remove 422 * this acts as an insert. If there are no views to 423 * add this acts as a remove. Views being removed will 424 * have the parent set to <code>null</code>, and the internal reference 425 * to them removed so that they can be garbage collected. 426 * This is implemented to do nothing, because by default 427 * a view has no children. 428 * 429 * @param offset the starting index into the child views to insert 430 * the new views. This should be a value >= 0 and <= getViewCount 431 * @param length the number of existing child views to remove 432 * This should be a value >= 0 and <= (getViewCount() - offset). 433 * @param views the child views to add. This value can be 434 * <code>null</code> to indicate no children are being added 435 * (useful to remove). 436 * @since 1.3 437 */ replace(int offset, int length, View[] views)438 public void replace(int offset, int length, View[] views) { 439 } 440 441 /** 442 * Returns the child view index representing the given position in 443 * the model. By default a view has no children so this is implemented 444 * to return -1 to indicate there is no valid child index for any 445 * position. 446 * 447 * @param pos the position >= 0 448 * @return index of the view representing the given position, or 449 * -1 if no view represents that position 450 * @since 1.3 451 */ getViewIndex(int pos, Position.Bias b)452 public int getViewIndex(int pos, Position.Bias b) { 453 return -1; 454 } 455 456 /** 457 * Fetches the allocation for the given child view. 458 * This enables finding out where various views 459 * are located, without assuming how the views store 460 * their location. This returns <code>null</code> since the 461 * default is to not have any child views. 462 * 463 * @param index the index of the child, >= 0 && < 464 * <code>getViewCount()</code> 465 * @param a the allocation to this view 466 * @return the allocation to the child 467 */ getChildAllocation(int index, Shape a)468 public Shape getChildAllocation(int index, Shape a) { 469 return null; 470 } 471 472 /** 473 * Provides a way to determine the next visually represented model 474 * location at which one might place a caret. 475 * Some views may not be visible, 476 * they might not be in the same order found in the model, or they just 477 * might not allow access to some of the locations in the model. 478 * This method enables specifying a position to convert 479 * within the range of >=0. If the value is -1, a position 480 * will be calculated automatically. If the value < -1, 481 * the {@code BadLocationException} will be thrown. 482 * 483 * @param pos the position to convert 484 * @param a the allocated region in which to render 485 * @param direction the direction from the current position that can 486 * be thought of as the arrow keys typically found on a keyboard. 487 * This will be one of the following values: 488 * <ul> 489 * <li>SwingConstants.WEST 490 * <li>SwingConstants.EAST 491 * <li>SwingConstants.NORTH 492 * <li>SwingConstants.SOUTH 493 * </ul> 494 * @return the location within the model that best represents the next 495 * location visual position 496 * @exception BadLocationException the given position is not a valid 497 * position within the document 498 * @exception IllegalArgumentException if <code>direction</code> 499 * doesn't have one of the legal values above 500 */ getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet)501 public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, 502 int direction, Position.Bias[] biasRet) 503 throws BadLocationException { 504 if (pos < -1) { 505 // -1 is a reserved value, see the code below 506 throw new BadLocationException("Invalid position", pos); 507 } 508 509 biasRet[0] = Position.Bias.Forward; 510 switch (direction) { 511 case NORTH: 512 case SOUTH: 513 { 514 if (pos == -1) { 515 pos = (direction == NORTH) ? Math.max(0, getEndOffset() - 1) : 516 getStartOffset(); 517 break; 518 } 519 JTextComponent target = (JTextComponent) getContainer(); 520 Caret c = (target != null) ? target.getCaret() : null; 521 // YECK! Ideally, the x location from the magic caret position 522 // would be passed in. 523 Point mcp; 524 if (c != null) { 525 mcp = c.getMagicCaretPosition(); 526 } 527 else { 528 mcp = null; 529 } 530 int x; 531 if (mcp == null) { 532 Rectangle loc = target.modelToView(pos); 533 x = (loc == null) ? 0 : loc.x; 534 } 535 else { 536 x = mcp.x; 537 } 538 if (direction == NORTH) { 539 pos = Utilities.getPositionAbove(target, pos, x); 540 } 541 else { 542 pos = Utilities.getPositionBelow(target, pos, x); 543 } 544 } 545 break; 546 case WEST: 547 if(pos == -1) { 548 pos = Math.max(0, getEndOffset() - 1); 549 } 550 else { 551 pos = Math.max(0, pos - 1); 552 } 553 break; 554 case EAST: 555 if(pos == -1) { 556 pos = getStartOffset(); 557 } 558 else { 559 pos = Math.min(pos + 1, getDocument().getLength()); 560 } 561 break; 562 default: 563 throw new IllegalArgumentException("Bad direction: " + direction); 564 } 565 return pos; 566 } 567 568 /** 569 * Provides a mapping, for a given character, 570 * from the document model coordinate space 571 * to the view coordinate space. 572 * 573 * @param pos the position of the desired character (>=0) 574 * @param a the area of the view, which encompasses the requested character 575 * @param b the bias toward the previous character or the 576 * next character represented by the offset, in case the 577 * position is a boundary of two views; <code>b</code> will have one 578 * of these values: 579 * <ul> 580 * <li> <code>Position.Bias.Forward</code> 581 * <li> <code>Position.Bias.Backward</code> 582 * </ul> 583 * @return the bounding box, in view coordinate space, 584 * of the character at the specified position 585 * @exception BadLocationException if the specified position does 586 * not represent a valid location in the associated document 587 * @exception IllegalArgumentException if <code>b</code> is not one of the 588 * legal <code>Position.Bias</code> values listed above 589 * @see View#viewToModel 590 */ modelToView(int pos, Shape a, Position.Bias b)591 public abstract Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException; 592 593 /** 594 * Provides a mapping, for a given region, 595 * from the document model coordinate space 596 * to the view coordinate space. The specified region is 597 * created as a union of the first and last character positions. 598 * 599 * @param p0 the position of the first character (>=0) 600 * @param b0 the bias of the first character position, 601 * toward the previous character or the 602 * next character represented by the offset, in case the 603 * position is a boundary of two views; <code>b0</code> will have one 604 * of these values: 605 * <ul style="list-style-type:none"> 606 * <li> <code>Position.Bias.Forward</code> 607 * <li> <code>Position.Bias.Backward</code> 608 * </ul> 609 * @param p1 the position of the last character (>=0) 610 * @param b1 the bias for the second character position, defined 611 * one of the legal values shown above 612 * @param a the area of the view, which encompasses the requested region 613 * @return the bounding box which is a union of the region specified 614 * by the first and last character positions 615 * @exception BadLocationException if the given position does 616 * not represent a valid location in the associated document 617 * @exception IllegalArgumentException if <code>b0</code> or 618 * <code>b1</code> are not one of the 619 * legal <code>Position.Bias</code> values listed above 620 * @see View#viewToModel 621 */ modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a)622 public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a) throws BadLocationException { 623 Shape s0 = modelToView(p0, a, b0); 624 Shape s1; 625 if (p1 == getEndOffset()) { 626 try { 627 s1 = modelToView(p1, a, b1); 628 } catch (BadLocationException ble) { 629 s1 = null; 630 } 631 if (s1 == null) { 632 // Assume extends left to right. 633 Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : 634 a.getBounds(); 635 s1 = new Rectangle(alloc.x + alloc.width - 1, alloc.y, 636 1, alloc.height); 637 } 638 } 639 else { 640 s1 = modelToView(p1, a, b1); 641 } 642 Rectangle r0 = s0.getBounds(); 643 Rectangle r1 = (s1 instanceof Rectangle) ? (Rectangle) s1 : 644 s1.getBounds(); 645 if (r0.y != r1.y) { 646 // If it spans lines, force it to be the width of the view. 647 Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : 648 a.getBounds(); 649 r0.x = alloc.x; 650 r0.width = alloc.width; 651 } 652 r0.add(r1); 653 return r0; 654 } 655 656 /** 657 * Provides a mapping from the view coordinate space to the logical 658 * coordinate space of the model. The <code>biasReturn</code> 659 * argument will be filled in to indicate that the point given is 660 * closer to the next character in the model or the previous 661 * character in the model. 662 * 663 * @param x the X coordinate >= 0 664 * @param y the Y coordinate >= 0 665 * @param a the allocated region in which to render 666 * @return the location within the model that best represents the 667 * given point in the view >= 0. The <code>biasReturn</code> 668 * argument will be 669 * filled in to indicate that the point given is closer to the next 670 * character in the model or the previous character in the model. 671 */ viewToModel(float x, float y, Shape a, Position.Bias[] biasReturn)672 public abstract int viewToModel(float x, float y, Shape a, Position.Bias[] biasReturn); 673 674 /** 675 * Gives notification that something was inserted into 676 * the document in a location that this view is responsible for. 677 * To reduce the burden to subclasses, this functionality is 678 * spread out into the following calls that subclasses can 679 * reimplement: 680 * <ol> 681 * <li>{@link #updateChildren updateChildren} is called 682 * if there were any changes to the element this view is 683 * responsible for. If this view has child views that are 684 * represent the child elements, then this method should do 685 * whatever is necessary to make sure the child views correctly 686 * represent the model. 687 * <li>{@link #forwardUpdate forwardUpdate} is called 688 * to forward the DocumentEvent to the appropriate child views. 689 * <li>{@link #updateLayout updateLayout} is called to 690 * give the view a chance to either repair its layout, to reschedule 691 * layout, or do nothing. 692 * </ol> 693 * 694 * @param e the change information from the associated document 695 * @param a the current allocation of the view 696 * @param f the factory to use to rebuild if the view has children 697 * @see View#insertUpdate 698 */ insertUpdate(DocumentEvent e, Shape a, ViewFactory f)699 public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) { 700 if (getViewCount() > 0) { 701 Element elem = getElement(); 702 DocumentEvent.ElementChange ec = e.getChange(elem); 703 if (ec != null) { 704 if (! updateChildren(ec, e, f)) { 705 // don't consider the element changes they 706 // are for a view further down. 707 ec = null; 708 } 709 } 710 forwardUpdate(ec, e, a, f); 711 updateLayout(ec, e, a); 712 } 713 } 714 715 /** 716 * Gives notification that something was removed from the document 717 * in a location that this view is responsible for. 718 * To reduce the burden to subclasses, this functionality is 719 * spread out into the following calls that subclasses can 720 * reimplement: 721 * <ol> 722 * <li>{@link #updateChildren updateChildren} is called 723 * if there were any changes to the element this view is 724 * responsible for. If this view has child views that are 725 * represent the child elements, then this method should do 726 * whatever is necessary to make sure the child views correctly 727 * represent the model. 728 * <li>{@link #forwardUpdate forwardUpdate} is called 729 * to forward the DocumentEvent to the appropriate child views. 730 * <li>{@link #updateLayout updateLayout} is called to 731 * give the view a chance to either repair its layout, to reschedule 732 * layout, or do nothing. 733 * </ol> 734 * 735 * @param e the change information from the associated document 736 * @param a the current allocation of the view 737 * @param f the factory to use to rebuild if the view has children 738 * @see View#removeUpdate 739 */ removeUpdate(DocumentEvent e, Shape a, ViewFactory f)740 public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) { 741 if (getViewCount() > 0) { 742 Element elem = getElement(); 743 DocumentEvent.ElementChange ec = e.getChange(elem); 744 if (ec != null) { 745 if (! updateChildren(ec, e, f)) { 746 // don't consider the element changes they 747 // are for a view further down. 748 ec = null; 749 } 750 } 751 forwardUpdate(ec, e, a, f); 752 updateLayout(ec, e, a); 753 } 754 } 755 756 /** 757 * Gives notification from the document that attributes were changed 758 * in a location that this view is responsible for. 759 * To reduce the burden to subclasses, this functionality is 760 * spread out into the following calls that subclasses can 761 * reimplement: 762 * <ol> 763 * <li>{@link #updateChildren updateChildren} is called 764 * if there were any changes to the element this view is 765 * responsible for. If this view has child views that are 766 * represent the child elements, then this method should do 767 * whatever is necessary to make sure the child views correctly 768 * represent the model. 769 * <li>{@link #forwardUpdate forwardUpdate} is called 770 * to forward the DocumentEvent to the appropriate child views. 771 * <li>{@link #updateLayout updateLayout} is called to 772 * give the view a chance to either repair its layout, to reschedule 773 * layout, or do nothing. 774 * </ol> 775 * 776 * @param e the change information from the associated document 777 * @param a the current allocation of the view 778 * @param f the factory to use to rebuild if the view has children 779 * @see View#changedUpdate 780 */ changedUpdate(DocumentEvent e, Shape a, ViewFactory f)781 public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) { 782 if (getViewCount() > 0) { 783 Element elem = getElement(); 784 DocumentEvent.ElementChange ec = e.getChange(elem); 785 if (ec != null) { 786 if (! updateChildren(ec, e, f)) { 787 // don't consider the element changes they 788 // are for a view further down. 789 ec = null; 790 } 791 } 792 forwardUpdate(ec, e, a, f); 793 updateLayout(ec, e, a); 794 } 795 } 796 797 /** 798 * Fetches the model associated with the view. 799 * 800 * @return the view model, <code>null</code> if none 801 * @see View#getDocument 802 */ getDocument()803 public Document getDocument() { 804 return elem.getDocument(); 805 } 806 807 /** 808 * Fetches the portion of the model for which this view is 809 * responsible. 810 * 811 * @return the starting offset into the model >= 0 812 * @see View#getStartOffset 813 */ getStartOffset()814 public int getStartOffset() { 815 return elem.getStartOffset(); 816 } 817 818 /** 819 * Fetches the portion of the model for which this view is 820 * responsible. 821 * 822 * @return the ending offset into the model >= 0 823 * @see View#getEndOffset 824 */ getEndOffset()825 public int getEndOffset() { 826 return elem.getEndOffset(); 827 } 828 829 /** 830 * Fetches the structural portion of the subject that this 831 * view is mapped to. The view may not be responsible for the 832 * entire portion of the element. 833 * 834 * @return the subject 835 * @see View#getElement 836 */ getElement()837 public Element getElement() { 838 return elem; 839 } 840 841 /** 842 * Fetch a <code>Graphics</code> for rendering. 843 * This can be used to determine 844 * font characteristics, and will be different for a print view 845 * than a component view. 846 * 847 * @return a <code>Graphics</code> object for rendering 848 * @since 1.3 849 */ getGraphics()850 public Graphics getGraphics() { 851 // PENDING(prinz) this is a temporary implementation 852 Component c = getContainer(); 853 return c.getGraphics(); 854 } 855 856 /** 857 * Fetches the attributes to use when rendering. By default 858 * this simply returns the attributes of the associated element. 859 * This method should be used rather than using the element 860 * directly to obtain access to the attributes to allow 861 * view-specific attributes to be mixed in or to allow the 862 * view to have view-specific conversion of attributes by 863 * subclasses. 864 * Each view should document what attributes it recognizes 865 * for the purpose of rendering or layout, and should always 866 * access them through the <code>AttributeSet</code> returned 867 * by this method. 868 */ getAttributes()869 public AttributeSet getAttributes() { 870 return elem.getAttributes(); 871 } 872 873 /** 874 * Tries to break this view on the given axis. This is 875 * called by views that try to do formatting of their 876 * children. For example, a view of a paragraph will 877 * typically try to place its children into row and 878 * views representing chunks of text can sometimes be 879 * broken down into smaller pieces. 880 * <p> 881 * This is implemented to return the view itself, which 882 * represents the default behavior on not being 883 * breakable. If the view does support breaking, the 884 * starting offset of the view returned should be the 885 * given offset, and the end offset should be less than 886 * or equal to the end offset of the view being broken. 887 * 888 * @param axis may be either <code>View.X_AXIS</code> or 889 * <code>View.Y_AXIS</code> 890 * @param offset the location in the document model 891 * that a broken fragment would occupy >= 0. This 892 * would be the starting offset of the fragment 893 * returned 894 * @param pos the position along the axis that the 895 * broken view would occupy >= 0. This may be useful for 896 * things like tab calculations 897 * @param len specifies the distance along the axis 898 * where a potential break is desired >= 0 899 * @return the fragment of the view that represents the 900 * given span, if the view can be broken. If the view 901 * doesn't support breaking behavior, the view itself is 902 * returned. 903 * @see ParagraphView 904 */ breakView(int axis, int offset, float pos, float len)905 public View breakView(int axis, int offset, float pos, float len) { 906 return this; 907 } 908 909 /** 910 * Creates a view that represents a portion of the element. 911 * This is potentially useful during formatting operations 912 * for taking measurements of fragments of the view. If 913 * the view doesn't support fragmenting (the default), it 914 * should return itself. 915 * 916 * @param p0 the starting offset >= 0. This should be a value 917 * greater or equal to the element starting offset and 918 * less than the element ending offset. 919 * @param p1 the ending offset > p0. This should be a value 920 * less than or equal to the elements end offset and 921 * greater than the elements starting offset. 922 * @return the view fragment, or itself if the view doesn't 923 * support breaking into fragments 924 * @see LabelView 925 */ createFragment(int p0, int p1)926 public View createFragment(int p0, int p1) { 927 return this; 928 } 929 930 /** 931 * Determines how attractive a break opportunity in 932 * this view is. This can be used for determining which 933 * view is the most attractive to call <code>breakView</code> 934 * on in the process of formatting. A view that represents 935 * text that has whitespace in it might be more attractive 936 * than a view that has no whitespace, for example. The 937 * higher the weight, the more attractive the break. A 938 * value equal to or lower than <code>BadBreakWeight</code> 939 * should not be considered for a break. A value greater 940 * than or equal to <code>ForcedBreakWeight</code> should 941 * be broken. 942 * <p> 943 * This is implemented to provide the default behavior 944 * of returning <code>BadBreakWeight</code> unless the length 945 * is greater than the length of the view in which case the 946 * entire view represents the fragment. Unless a view has 947 * been written to support breaking behavior, it is not 948 * attractive to try and break the view. An example of 949 * a view that does support breaking is <code>LabelView</code>. 950 * An example of a view that uses break weight is 951 * <code>ParagraphView</code>. 952 * 953 * @param axis may be either <code>View.X_AXIS</code> or 954 * <code>View.Y_AXIS</code> 955 * @param pos the potential location of the start of the 956 * broken view >= 0. This may be useful for calculating tab 957 * positions 958 * @param len specifies the relative length from <em>pos</em> 959 * where a potential break is desired >= 0 960 * @return the weight, which should be a value between 961 * ForcedBreakWeight and BadBreakWeight 962 * @see LabelView 963 * @see ParagraphView 964 * @see #BadBreakWeight 965 * @see #GoodBreakWeight 966 * @see #ExcellentBreakWeight 967 * @see #ForcedBreakWeight 968 */ getBreakWeight(int axis, float pos, float len)969 public int getBreakWeight(int axis, float pos, float len) { 970 if (len > getPreferredSpan(axis)) { 971 return GoodBreakWeight; 972 } 973 return BadBreakWeight; 974 } 975 976 /** 977 * Determines the resizability of the view along the 978 * given axis. A value of 0 or less is not resizable. 979 * 980 * @param axis may be either <code>View.X_AXIS</code> or 981 * <code>View.Y_AXIS</code> 982 * @return the weight 983 */ getResizeWeight(int axis)984 public int getResizeWeight(int axis) { 985 return 0; 986 } 987 988 /** 989 * Sets the size of the view. This should cause 990 * layout of the view along the given axis, if it 991 * has any layout duties. 992 * 993 * @param width the width >= 0 994 * @param height the height >= 0 995 */ setSize(float width, float height)996 public void setSize(float width, float height) { 997 } 998 999 /** 1000 * Fetches the container hosting the view. This is useful for 1001 * things like scheduling a repaint, finding out the host 1002 * components font, etc. The default implementation 1003 * of this is to forward the query to the parent view. 1004 * 1005 * @return the container, <code>null</code> if none 1006 */ getContainer()1007 public Container getContainer() { 1008 View v = getParent(); 1009 return (v != null) ? v.getContainer() : null; 1010 } 1011 1012 /** 1013 * Fetches the <code>ViewFactory</code> implementation that is feeding 1014 * the view hierarchy. Normally the views are given this 1015 * as an argument to updates from the model when they 1016 * are most likely to need the factory, but this 1017 * method serves to provide it at other times. 1018 * 1019 * @return the factory, <code>null</code> if none 1020 */ getViewFactory()1021 public ViewFactory getViewFactory() { 1022 View v = getParent(); 1023 return (v != null) ? v.getViewFactory() : null; 1024 } 1025 1026 /** 1027 * Returns the tooltip text at the specified location. The default 1028 * implementation returns the value from the child View identified by 1029 * the passed in location. 1030 * 1031 * @since 1.4 1032 * @see JTextComponent#getToolTipText 1033 */ getToolTipText(float x, float y, Shape allocation)1034 public String getToolTipText(float x, float y, Shape allocation) { 1035 int viewIndex = getViewIndex(x, y, allocation); 1036 if (viewIndex >= 0) { 1037 allocation = getChildAllocation(viewIndex, allocation); 1038 Rectangle rect = (allocation instanceof Rectangle) ? 1039 (Rectangle)allocation : allocation.getBounds(); 1040 if (rect.contains(x, y)) { 1041 return getView(viewIndex).getToolTipText(x, y, allocation); 1042 } 1043 } 1044 return null; 1045 } 1046 1047 /** 1048 * Returns the child view index representing the given position in 1049 * the view. This iterates over all the children returning the 1050 * first with a bounds that contains <code>x</code>, <code>y</code>. 1051 * 1052 * @param x the x coordinate 1053 * @param y the y coordinate 1054 * @param allocation current allocation of the View. 1055 * @return index of the view representing the given location, or 1056 * -1 if no view represents that position 1057 * @since 1.4 1058 */ getViewIndex(float x, float y, Shape allocation)1059 public int getViewIndex(float x, float y, Shape allocation) { 1060 for (int counter = getViewCount() - 1; counter >= 0; counter--) { 1061 Shape childAllocation = getChildAllocation(counter, allocation); 1062 1063 if (childAllocation != null) { 1064 Rectangle rect = (childAllocation instanceof Rectangle) ? 1065 (Rectangle)childAllocation : childAllocation.getBounds(); 1066 1067 if (rect.contains(x, y)) { 1068 return counter; 1069 } 1070 } 1071 } 1072 return -1; 1073 } 1074 1075 /** 1076 * Updates the child views in response to receiving notification 1077 * that the model changed, and there is change record for the 1078 * element this view is responsible for. This is implemented 1079 * to assume the child views are directly responsible for the 1080 * child elements of the element this view represents. The 1081 * <code>ViewFactory</code> is used to create child views for each element 1082 * specified as added in the <code>ElementChange</code>, starting at the 1083 * index specified in the given <code>ElementChange</code>. The number of 1084 * child views representing the removed elements specified are 1085 * removed. 1086 * 1087 * @param ec the change information for the element this view 1088 * is responsible for. This should not be <code>null</code> if 1089 * this method gets called 1090 * @param e the change information from the associated document 1091 * @param f the factory to use to build child views 1092 * @return whether or not the child views represent the 1093 * child elements of the element this view is responsible 1094 * for. Some views create children that represent a portion 1095 * of the element they are responsible for, and should return 1096 * false. This information is used to determine if views 1097 * in the range of the added elements should be forwarded to 1098 * or not 1099 * @see #insertUpdate 1100 * @see #removeUpdate 1101 * @see #changedUpdate 1102 * @since 1.3 1103 */ updateChildren(DocumentEvent.ElementChange ec, DocumentEvent e, ViewFactory f)1104 protected boolean updateChildren(DocumentEvent.ElementChange ec, 1105 DocumentEvent e, ViewFactory f) { 1106 Element[] removedElems = ec.getChildrenRemoved(); 1107 Element[] addedElems = ec.getChildrenAdded(); 1108 View[] added = null; 1109 if (addedElems != null) { 1110 added = new View[addedElems.length]; 1111 for (int i = 0; i < addedElems.length; i++) { 1112 added[i] = f.create(addedElems[i]); 1113 } 1114 } 1115 int nremoved = 0; 1116 int index = ec.getIndex(); 1117 if (removedElems != null) { 1118 nremoved = removedElems.length; 1119 } 1120 replace(index, nremoved, added); 1121 return true; 1122 } 1123 1124 /** 1125 * Forwards the given <code>DocumentEvent</code> to the child views 1126 * that need to be notified of the change to the model. 1127 * If there were changes to the element this view is 1128 * responsible for, that should be considered when 1129 * forwarding (i.e. new child views should not get 1130 * notified). 1131 * 1132 * @param ec changes to the element this view is responsible 1133 * for (may be <code>null</code> if there were no changes). 1134 * @param e the change information from the associated document 1135 * @param a the current allocation of the view 1136 * @param f the factory to use to rebuild if the view has children 1137 * @see #insertUpdate 1138 * @see #removeUpdate 1139 * @see #changedUpdate 1140 * @since 1.3 1141 */ forwardUpdate(DocumentEvent.ElementChange ec, DocumentEvent e, Shape a, ViewFactory f)1142 protected void forwardUpdate(DocumentEvent.ElementChange ec, 1143 DocumentEvent e, Shape a, ViewFactory f) { 1144 calculateUpdateIndexes(e); 1145 1146 int hole0 = lastUpdateIndex + 1; 1147 int hole1 = hole0; 1148 Element[] addedElems = (ec != null) ? ec.getChildrenAdded() : null; 1149 if ((addedElems != null) && (addedElems.length > 0)) { 1150 hole0 = ec.getIndex(); 1151 hole1 = hole0 + addedElems.length - 1; 1152 } 1153 1154 // forward to any view not in the forwarding hole 1155 // formed by added elements (i.e. they will be updated 1156 // by initialization. 1157 for (int i = firstUpdateIndex; i <= lastUpdateIndex; i++) { 1158 if (! ((i >= hole0) && (i <= hole1))) { 1159 View v = getView(i); 1160 if (v != null) { 1161 Shape childAlloc = getChildAllocation(i, a); 1162 forwardUpdateToView(v, e, childAlloc, f); 1163 } 1164 } 1165 } 1166 } 1167 1168 /** 1169 * Calculates the first and the last indexes of the child views 1170 * that need to be notified of the change to the model. 1171 * @param e the change information from the associated document 1172 */ calculateUpdateIndexes(DocumentEvent e)1173 void calculateUpdateIndexes(DocumentEvent e) { 1174 int pos = e.getOffset(); 1175 firstUpdateIndex = getViewIndex(pos, Position.Bias.Forward); 1176 if (firstUpdateIndex == -1 && e.getType() == DocumentEvent.EventType.REMOVE && 1177 pos >= getEndOffset()) { 1178 // Event beyond our offsets. We may have represented this, that is 1179 // the remove may have removed one of our child Elements that 1180 // represented this, so, we should forward to last element. 1181 firstUpdateIndex = getViewCount() - 1; 1182 } 1183 lastUpdateIndex = firstUpdateIndex; 1184 View v = (firstUpdateIndex >= 0) ? getView(firstUpdateIndex) : null; 1185 if (v != null) { 1186 if ((v.getStartOffset() == pos) && (pos > 0)) { 1187 // If v is at a boundary, forward the event to the previous 1188 // view too. 1189 firstUpdateIndex = Math.max(firstUpdateIndex - 1, 0); 1190 } 1191 } 1192 if (e.getType() != DocumentEvent.EventType.REMOVE) { 1193 lastUpdateIndex = getViewIndex(pos + e.getLength(), Position.Bias.Forward); 1194 if (lastUpdateIndex < 0) { 1195 lastUpdateIndex = getViewCount() - 1; 1196 } 1197 } 1198 firstUpdateIndex = Math.max(firstUpdateIndex, 0); 1199 } 1200 1201 /** 1202 * Updates the view to reflect the changes. 1203 */ updateAfterChange()1204 void updateAfterChange() { 1205 // Do nothing by default. Should be overridden in subclasses, if any. 1206 } 1207 1208 /** 1209 * Forwards the <code>DocumentEvent</code> to the give child view. This 1210 * simply messages the view with a call to <code>insertUpdate</code>, 1211 * <code>removeUpdate</code>, or <code>changedUpdate</code> depending 1212 * upon the type of the event. This is called by 1213 * {@link #forwardUpdate forwardUpdate} to forward 1214 * the event to children that need it. 1215 * 1216 * @param v the child view to forward the event to 1217 * @param e the change information from the associated document 1218 * @param a the current allocation of the view 1219 * @param f the factory to use to rebuild if the view has children 1220 * @see #forwardUpdate 1221 * @since 1.3 1222 */ forwardUpdateToView(View v, DocumentEvent e, Shape a, ViewFactory f)1223 protected void forwardUpdateToView(View v, DocumentEvent e, 1224 Shape a, ViewFactory f) { 1225 DocumentEvent.EventType type = e.getType(); 1226 if (type == DocumentEvent.EventType.INSERT) { 1227 v.insertUpdate(e, a, f); 1228 } else if (type == DocumentEvent.EventType.REMOVE) { 1229 v.removeUpdate(e, a, f); 1230 } else { 1231 v.changedUpdate(e, a, f); 1232 } 1233 } 1234 1235 /** 1236 * Updates the layout in response to receiving notification of 1237 * change from the model. This is implemented to call 1238 * <code>preferenceChanged</code> to reschedule a new layout 1239 * if the <code>ElementChange</code> record is not <code>null</code>. 1240 * 1241 * @param ec changes to the element this view is responsible 1242 * for (may be <code>null</code> if there were no changes) 1243 * @param e the change information from the associated document 1244 * @param a the current allocation of the view 1245 * @see #insertUpdate 1246 * @see #removeUpdate 1247 * @see #changedUpdate 1248 * @since 1.3 1249 */ updateLayout(DocumentEvent.ElementChange ec, DocumentEvent e, Shape a)1250 protected void updateLayout(DocumentEvent.ElementChange ec, 1251 DocumentEvent e, Shape a) { 1252 if ((ec != null) && (a != null)) { 1253 // should damage more intelligently 1254 preferenceChanged(null, true, true); 1255 Container host = getContainer(); 1256 if (host != null) { 1257 host.repaint(); 1258 } 1259 } 1260 } 1261 1262 /** 1263 * The weight to indicate a view is a bad break 1264 * opportunity for the purpose of formatting. This 1265 * value indicates that no attempt should be made to 1266 * break the view into fragments as the view has 1267 * not been written to support fragmenting. 1268 * 1269 * @see #getBreakWeight 1270 * @see #GoodBreakWeight 1271 * @see #ExcellentBreakWeight 1272 * @see #ForcedBreakWeight 1273 */ 1274 public static final int BadBreakWeight = 0; 1275 1276 /** 1277 * The weight to indicate a view supports breaking, 1278 * but better opportunities probably exist. 1279 * 1280 * @see #getBreakWeight 1281 * @see #BadBreakWeight 1282 * @see #ExcellentBreakWeight 1283 * @see #ForcedBreakWeight 1284 */ 1285 public static final int GoodBreakWeight = 1000; 1286 1287 /** 1288 * The weight to indicate a view supports breaking, 1289 * and this represents a very attractive place to 1290 * break. 1291 * 1292 * @see #getBreakWeight 1293 * @see #BadBreakWeight 1294 * @see #GoodBreakWeight 1295 * @see #ForcedBreakWeight 1296 */ 1297 public static final int ExcellentBreakWeight = 2000; 1298 1299 /** 1300 * The weight to indicate a view supports breaking, 1301 * and must be broken to be represented properly 1302 * when placed in a view that formats its children 1303 * by breaking them. 1304 * 1305 * @see #getBreakWeight 1306 * @see #BadBreakWeight 1307 * @see #GoodBreakWeight 1308 * @see #ExcellentBreakWeight 1309 */ 1310 public static final int ForcedBreakWeight = 3000; 1311 1312 /** 1313 * Axis for format/break operations. 1314 */ 1315 public static final int X_AXIS = HORIZONTAL; 1316 1317 /** 1318 * Axis for format/break operations. 1319 */ 1320 public static final int Y_AXIS = VERTICAL; 1321 1322 /** 1323 * Provides a mapping from the document model coordinate space 1324 * to the coordinate space of the view mapped to it. This is 1325 * implemented to default the bias to <code>Position.Bias.Forward</code> 1326 * which was previously implied. 1327 * 1328 * @param pos the position to convert >= 0 1329 * @param a the allocated region in which to render 1330 * @return the bounding box of the given position is returned 1331 * @exception BadLocationException if the given position does 1332 * not represent a valid location in the associated document 1333 * @see View#modelToView 1334 * @deprecated 1335 */ 1336 @Deprecated modelToView(int pos, Shape a)1337 public Shape modelToView(int pos, Shape a) throws BadLocationException { 1338 return modelToView(pos, a, Position.Bias.Forward); 1339 } 1340 1341 1342 /** 1343 * Provides a mapping from the view coordinate space to the logical 1344 * coordinate space of the model. 1345 * 1346 * @param x the X coordinate >= 0 1347 * @param y the Y coordinate >= 0 1348 * @param a the allocated region in which to render 1349 * @return the location within the model that best represents the 1350 * given point in the view >= 0 1351 * @see View#viewToModel 1352 * @deprecated 1353 */ 1354 @Deprecated viewToModel(float x, float y, Shape a)1355 public int viewToModel(float x, float y, Shape a) { 1356 sharedBiasReturn[0] = Position.Bias.Forward; 1357 return viewToModel(x, y, a, sharedBiasReturn); 1358 } 1359 1360 // static argument available for viewToModel calls since only 1361 // one thread at a time may call this method. 1362 static final Position.Bias[] sharedBiasReturn = new Position.Bias[1]; 1363 1364 private View parent; 1365 private Element elem; 1366 1367 /** 1368 * The index of the first child view to be notified. 1369 */ 1370 int firstUpdateIndex; 1371 1372 /** 1373 * The index of the last child view to be notified. 1374 */ 1375 int lastUpdateIndex; 1376 1377 }; 1378