View Javadoc
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 &lt;= the preferred span which in turn
69      will be &lt;= 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      */
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      */
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      */
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      */
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      */
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      */
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      */
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 &gt;= 0.0 and &lt;= 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      */
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      */
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      */
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 &gt;= 0
354      * @see View#getViewCount
355      */
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, &gt;= 0 &amp;&amp; &lt; getViewCount()
365      * @return the view
366      */
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      */
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      */
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 &gt;= 0
396      * @param v the view
397      * @see #replace
398      * @since 1.3
399      */
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      */
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 &gt;= 0 and &lt;= getViewCount
431      * @param length the number of existing child views to remove
432      *   This should be a value &gt;= 0 and &lt;= (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      */
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 &gt;= 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      */
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, &gt;= 0 &amp;&amp; &lt;
464      *          <code>getViewCount()</code>
465      * @param a  the allocation to this view
466      * @return the allocation to the child
467      */
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 &gt;=0.  If the value is -1, a position
480      * will be calculated automatically.  If the value &lt; -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      */
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 (&gt;=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      */
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 (&gt;=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 (&gt;=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      */
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 &gt;= 0
664      * @param y the Y coordinate &gt;= 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 &gt;= 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      */
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      */
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      */
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      */
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      */
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 &gt;= 0
812      * @see View#getStartOffset
813      */
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 &gt;= 0
823      * @see View#getEndOffset
824      */
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      */
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      */
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      */
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 &gt;= 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 &gt;= 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 &gt;= 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      */
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 &gt;= 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 &gt; 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      */
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 &gt;= 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 &gt;= 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      */
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      */
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 &gt;= 0
994      * @param height the height &gt;= 0
995      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      * Forwards the <code>DocumentEvent</code> to the give child view.  This
1203      * simply messages the view with a call to <code>insertUpdate</code>,
1204      * <code>removeUpdate</code>, or <code>changedUpdate</code> depending
1205      * upon the type of the event.  This is called by
1206      * {@link #forwardUpdate forwardUpdate} to forward
1207      * the event to children that need it.
1208      *
1209      * @param v the child view to forward the event to
1210      * @param e the change information from the associated document
1211      * @param a the current allocation of the view
1212      * @param f the factory to use to rebuild if the view has children
1213      * @see #forwardUpdate
1214      * @since 1.3
1215      */
1216     protected void forwardUpdateToView(View v, DocumentEvent e,
1217                                            Shape a, ViewFactory f) {
1218         DocumentEvent.EventType type = e.getType();
1219         if (type == DocumentEvent.EventType.INSERT) {
1220             v.insertUpdate(e, a, f);
1221         } else if (type == DocumentEvent.EventType.REMOVE) {
1222             v.removeUpdate(e, a, f);
1223         } else {
1224             v.changedUpdate(e, a, f);
1225         }
1226     }
1227 
1228     /**
1229      * Updates the layout in response to receiving notification of
1230      * change from the model.  This is implemented to call
1231      * <code>preferenceChanged</code> to reschedule a new layout
1232      * if the <code>ElementChange</code> record is not <code>null</code>.
1233      *
1234      * @param ec changes to the element this view is responsible
1235      *  for (may be <code>null</code> if there were no changes)
1236      * @param e the change information from the associated document
1237      * @param a the current allocation of the view
1238      * @see #insertUpdate
1239      * @see #removeUpdate
1240      * @see #changedUpdate
1241      * @since 1.3
1242      */
1243     protected void updateLayout(DocumentEvent.ElementChange ec,
1244                                     DocumentEvent e, Shape a) {
1245         if ((ec != null) && (a != null)) {
1246             // should damage more intelligently
1247             preferenceChanged(null, true, true);
1248             Container host = getContainer();
1249             if (host != null) {
1250                 host.repaint();
1251             }
1252         }
1253     }
1254 
1255     /**
1256      * The weight to indicate a view is a bad break
1257      * opportunity for the purpose of formatting.  This
1258      * value indicates that no attempt should be made to
1259      * break the view into fragments as the view has
1260      * not been written to support fragmenting.
1261      *
1262      * @see #getBreakWeight
1263      * @see #GoodBreakWeight
1264      * @see #ExcellentBreakWeight
1265      * @see #ForcedBreakWeight
1266      */
1267     public static final int BadBreakWeight = 0;
1268 
1269     /**
1270      * The weight to indicate a view supports breaking,
1271      * but better opportunities probably exist.
1272      *
1273      * @see #getBreakWeight
1274      * @see #BadBreakWeight
1275      * @see #ExcellentBreakWeight
1276      * @see #ForcedBreakWeight
1277      */
1278     public static final int GoodBreakWeight = 1000;
1279 
1280     /**
1281      * The weight to indicate a view supports breaking,
1282      * and this represents a very attractive place to
1283      * break.
1284      *
1285      * @see #getBreakWeight
1286      * @see #BadBreakWeight
1287      * @see #GoodBreakWeight
1288      * @see #ForcedBreakWeight
1289      */
1290     public static final int ExcellentBreakWeight = 2000;
1291 
1292     /**
1293      * The weight to indicate a view supports breaking,
1294      * and must be broken to be represented properly
1295      * when placed in a view that formats its children
1296      * by breaking them.
1297      *
1298      * @see #getBreakWeight
1299      * @see #BadBreakWeight
1300      * @see #GoodBreakWeight
1301      * @see #ExcellentBreakWeight
1302      */
1303     public static final int ForcedBreakWeight = 3000;
1304 
1305     /**
1306      * Axis for format/break operations.
1307      */
1308     public static final int X_AXIS = HORIZONTAL;
1309 
1310     /**
1311      * Axis for format/break operations.
1312      */
1313     public static final int Y_AXIS = VERTICAL;
1314 
1315     /**
1316      * Provides a mapping from the document model coordinate space
1317      * to the coordinate space of the view mapped to it. This is
1318      * implemented to default the bias to <code>Position.Bias.Forward</code>
1319      * which was previously implied.
1320      *
1321      * @param pos the position to convert &gt;= 0
1322      * @param a the allocated region in which to render
1323      * @return the bounding box of the given position is returned
1324      * @exception BadLocationException  if the given position does
1325      *   not represent a valid location in the associated document
1326      * @see View#modelToView
1327      * @deprecated
1328      */
1329     @Deprecated
1330     public Shape modelToView(int pos, Shape a) throws BadLocationException {
1331         return modelToView(pos, a, Position.Bias.Forward);
1332     }
1333 
1334 
1335     /**
1336      * Provides a mapping from the view coordinate space to the logical
1337      * coordinate space of the model.
1338      *
1339      * @param x the X coordinate &gt;= 0
1340      * @param y the Y coordinate &gt;= 0
1341      * @param a the allocated region in which to render
1342      * @return the location within the model that best represents the
1343      *  given point in the view &gt;= 0
1344      * @see View#viewToModel
1345      * @deprecated
1346      */
1347     @Deprecated
1348     public int viewToModel(float x, float y, Shape a) {
1349         sharedBiasReturn[0] = Position.Bias.Forward;
1350         return viewToModel(x, y, a, sharedBiasReturn);
1351     }
1352 
1353     // static argument available for viewToModel calls since only
1354     // one thread at a time may call this method.
1355     static final Position.Bias[] sharedBiasReturn = new Position.Bias[1];
1356 
1357     private View parent;
1358     private Element elem;
1359 
1360     /**
1361      * The index of the first child view to be notified.
1362      */
1363     int firstUpdateIndex;
1364 
1365     /**
1366      * The index of the last child view to be notified.
1367      */
1368     int lastUpdateIndex;
1369 
1370 };