History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/text/View.java (1 of 18352 files). Show all

Unified · Split

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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t