KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > text > FlowView


1 /*
2  * @(#)FlowView.java 1.46 05/08/12
3  *
4  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing.text;
8
9 import java.awt.*;
10 import javax.swing.event.*;
11 import javax.swing.SizeRequirements JavaDoc;
12
13 /**
14  * A View that tries to flow it's children into some
15  * partially constrained space. This can be used to
16  * build things like paragraphs, pages, etc. The
17  * flow is made up of the following pieces of functionality.
18  * <ul>
19  * <li>A logical set of child views, which as used as a
20  * layout pool from which a physical view is formed.
21  * <li>A strategy for translating the logical view to
22  * a physical (flowed) view.
23  * <li>Constraints for the strategy to work against.
24  * <li>A physical structure, that represents the flow.
25  * The children of this view are where the pieces of
26  * of the logical views are placed to create the flow.
27  * </ul>
28  *
29  * @author Timothy Prinzing
30  * @version 1.46 08/12/05
31  * @see View
32  */

33 public abstract class FlowView extends BoxView JavaDoc {
34
35     private final static FlowStrategy STRATEGY = new FlowStrategy();
36     
37     /**
38      * Constructs a FlowView for the given element.
39      *
40      * @param elem the element that this view is responsible for
41      * @param axis may be either View.X_AXIS or View.Y_AXIS
42      */

43     public FlowView(Element JavaDoc elem, int axis) {
44     super(elem, axis);
45     layoutSpan = Integer.MAX_VALUE;
46     strategy = STRATEGY;
47     }
48
49     /**
50      * Fetches the axis along which views should be
51      * flowed. By default, this will be the axis
52      * orthogonal to the axis along which the flow
53      * rows are tiled (the axis of the default flow
54      * rows themselves). This is typically used
55      * by the <code>FlowStrategy</code>.
56      */

57     public int getFlowAxis() {
58     if (getAxis() == Y_AXIS) {
59         return X_AXIS;
60     }
61     return Y_AXIS;
62     }
63
64     /**
65      * Fetch the constraining span to flow against for
66      * the given child index. This is called by the
67      * FlowStrategy while it is updating the flow.
68      * A flow can be shaped by providing different values
69      * for the row constraints. By default, the entire
70      * span inside of the insets along the flow axis
71      * is returned.
72      *
73      * @param index the index of the row being updated.
74      * This should be a value >= 0 and < getViewCount().
75      * @see #getFlowStart
76      */

77     public int getFlowSpan(int index) {
78     return layoutSpan;
79     }
80
81     /**
82      * Fetch the location along the flow axis that the
83      * flow span will start at. This is called by the
84      * FlowStrategy while it is updating the flow.
85      * A flow can be shaped by providing different values
86      * for the row constraints.
87
88      * @param index the index of the row being updated.
89      * This should be a value >= 0 and < getViewCount().
90      * @see #getFlowSpan
91      */

92     public int getFlowStart(int index) {
93     return 0;
94     }
95
96     /**
97      * Create a View that should be used to hold a
98      * a rows worth of children in a flow. This is
99      * called by the FlowStrategy when new children
100      * are added or removed (i.e. rows are added or
101      * removed) in the process of updating the flow.
102      */

103     protected abstract View JavaDoc createRow();
104     
105     // ---- BoxView methods -------------------------------------
106

107     /**
108      * Loads all of the children to initialize the view.
109      * This is called by the <code>setParent</code> method.
110      * This is reimplemented to not load any children directly
111      * (as they are created in the process of formatting).
112      * If the layoutPool variable is null, an instance of
113      * LogicalView is created to represent the logical view
114      * that is used in the process of formatting.
115      *
116      * @param f the view factory
117      */

118     protected void loadChildren(ViewFactory JavaDoc f) {
119     if (layoutPool == null) {
120         layoutPool = new LogicalView(getElement());
121     }
122         layoutPool.setParent(this);
123
124         // This synthetic insertUpdate call gives the strategy a chance
125
// to initialize.
126
strategy.insertUpdate( this, null, null );
127     }
128
129     /**
130      * Fetches the child view index representing the given position in
131      * the model.
132      *
133      * @param pos the position >= 0
134      * @return index of the view representing the given position, or
135      * -1 if no view represents that position
136      */

137     protected int getViewIndexAtPosition(int pos) {
138     if (pos >= getStartOffset() && (pos < getEndOffset())) {
139         for(int counter = getViewCount() - 1; counter >= 0; counter--) {
140         View JavaDoc v = getView(counter);
141         if(pos >= v.getStartOffset() &&
142            pos < v.getEndOffset()) {
143             return counter;
144         }
145         }
146     }
147     return -1;
148     }
149
150     /**
151      * Lays out the children. If the span along the flow
152      * axis has changed, layout is marked as invalid which
153      * which will cause the superclass behavior to recalculate
154      * the layout along the box axis. The FlowStrategy.layout
155      * method will be called to rebuild the flow rows as
156      * appropriate. If the height of this view changes
157      * (determined by the perferred size along the box axis),
158      * a preferenceChanged is called. Following all of that,
159      * the normal box layout of the superclass is performed.
160      *
161      * @param width the width to lay out against >= 0. This is
162      * the width inside of the inset area.
163      * @param height the height to lay out against >= 0 This
164      * is the height inside of the inset area.
165      */

166     protected void layout(int width, int height) {
167     final int faxis = getFlowAxis();
168     int newSpan;
169     if (faxis == X_AXIS) {
170         newSpan = (int)width;
171     } else {
172         newSpan = (int)height;
173     }
174     if (layoutSpan != newSpan) {
175         layoutChanged(faxis);
176         layoutChanged(getAxis());
177         layoutSpan = newSpan;
178     }
179
180     // repair the flow if necessary
181
if (! isLayoutValid(faxis)) {
182         final int heightAxis = getAxis();
183         int oldFlowHeight = (int)((heightAxis == X_AXIS)? getWidth() : getHeight());
184         strategy.layout(this);
185         int newFlowHeight = (int) getPreferredSpan(heightAxis);
186         if (oldFlowHeight != newFlowHeight) {
187         View JavaDoc p = getParent();
188         if (p != null) {
189             p.preferenceChanged(this, (heightAxis == X_AXIS), (heightAxis == Y_AXIS));
190         }
191
192                 // PENDING(shannonh)
193
// Temporary fix for 4250847
194
// Can be removed when TraversalContext is added
195
Component host = getContainer();
196         if (host != null) {
197             //nb idk 12/12/2001 host should not be equal to null. We need to add assertion here
198
host.repaint();
199         }
200         }
201     }
202
203     super.layout(width, height);
204     }
205
206     /**
207      * Calculate equirements along the minor axis. This
208      * is implemented to forward the request to the logical
209      * view by calling getMinimumSpan, getPreferredSpan, and
210      * getMaximumSpan on it.
211      */

212     protected SizeRequirements JavaDoc calculateMinorAxisRequirements(int axis, SizeRequirements JavaDoc r) {
213     if (r == null) {
214         r = new SizeRequirements JavaDoc();
215     }
216     float pref = layoutPool.getPreferredSpan(axis);
217     float min = layoutPool.getMinimumSpan(axis);
218         // Don't include insets, Box.getXXXSpan will include them.
219
r.minimum = (int)min;
220     r.preferred = Math.max(r.minimum, (int) pref);
221     r.maximum = Integer.MAX_VALUE;
222     r.alignment = 0.5f;
223     return r;
224     }
225
226     // ---- View methods ----------------------------------------------------
227

228     /**
229      * Gives notification that something was inserted into the document
230      * in a location that this view is responsible for.
231      *
232      * @param changes the change information from the associated document
233      * @param a the current allocation of the view
234      * @param f the factory to use to rebuild if the view has children
235      * @see View#insertUpdate
236      */

237     public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory JavaDoc f) {
238     layoutPool.insertUpdate(changes, a, f);
239     strategy.insertUpdate(this, changes, getInsideAllocation(a));
240     }
241
242     /**
243      * Gives notification that something was removed from the document
244      * in a location that this view is responsible for.
245      *
246      * @param changes the change information from the associated document
247      * @param a the current allocation of the view
248      * @param f the factory to use to rebuild if the view has children
249      * @see View#removeUpdate
250      */

251     public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory JavaDoc f) {
252     layoutPool.removeUpdate(changes, a, f);
253     strategy.removeUpdate(this, changes, getInsideAllocation(a));
254     }
255
256     /**
257      * Gives notification from the document that attributes were changed
258      * in a location that this view is responsible for.
259      *
260      * @param changes the change information from the associated document
261      * @param a the current allocation of the view
262      * @param f the factory to use to rebuild if the view has children
263      * @see View#changedUpdate
264      */

265     public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory JavaDoc f) {
266     layoutPool.changedUpdate(changes, a, f);
267     strategy.changedUpdate(this, changes, getInsideAllocation(a));
268     }
269
270     /** {@inheritDoc} */
271     public void setParent(View JavaDoc parent) {
272     super.setParent(parent);
273         if (parent == null
274                 && layoutPool != null ) {
275             layoutPool.setParent(null);
276         }
277     }
278
279     // --- variables -----------------------------------------------
280

281     /**
282      * Default constraint against which the flow is
283      * created against.
284      */

285     protected int layoutSpan;
286
287     /**
288      * These are the views that represent the child elements
289      * of the element this view represents (The logical view
290      * to translate to a physical view). These are not
291      * directly children of this view. These are either
292      * placed into the rows directly or used for the purpose
293      * of breaking into smaller chunks, to form the physical
294      * view.
295      */

296     protected View JavaDoc layoutPool;
297
298     /**
299      * The behavior for keeping the flow updated. By
300      * default this is a singleton shared by all instances
301      * of FlowView (FlowStrategy is stateless). Subclasses
302      * can create an alternative strategy, which might keep
303      * state.
304      */

305     protected FlowStrategy strategy;
306
307     /**
308      * Strategy for maintaining the physical form
309      * of the flow. The default implementation is
310      * completely stateless, and recalculates the
311      * entire flow if the layout is invalid on the
312      * given FlowView. Alternative strategies can
313      * be implemented by subclassing, and might
314      * perform incrementatal repair to the layout
315      * or alternative breaking behavior.
316      */

317     public static class FlowStrategy {
318
319     /**
320      * Gives notification that something was inserted into the document
321      * in a location that the given flow view is responsible for. The
322      * strategy should update the appropriate changed region (which
323      * depends upon the strategy used for repair).
324      *
325      * @param e the change information from the associated document
326      * @param alloc the current allocation of the view inside of the insets.
327      * This value will be null if the view has not yet been displayed.
328      * @see View#insertUpdate
329      */

330         public void insertUpdate(FlowView JavaDoc fv, DocumentEvent e, Rectangle alloc) {
331         if (alloc != null) {
332         Component host = fv.getContainer();
333         if (host != null) {
334             host.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
335         }
336         } else {
337         fv.preferenceChanged(null, true, true);
338         }
339     }
340
341     /**
342      * Gives notification that something was removed from the document
343      * in a location that the given flow view is responsible for.
344      *
345      * @param e the change information from the associated document
346      * @param alloc the current allocation of the view inside of the insets.
347      * @see View#removeUpdate
348      */

349         public void removeUpdate(FlowView JavaDoc fv, DocumentEvent e, Rectangle alloc) {
350         if (alloc != null) {
351         Component host = fv.getContainer();
352         if (host != null) {
353             host.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
354         }
355         } else {
356         fv.preferenceChanged(null, true, true);
357         }
358     }
359
360     /**
361      * Gives notification from the document that attributes were changed
362      * in a location that this view is responsible for.
363      *
364          * @param fv the <code>FlowView</code> containing the changes
365          * @param e the <code>DocumentEvent</code> describing the changes
366          * done to the Document
367          * @param alloc Bounds of the View
368      * @see View#changedUpdate
369      */

370         public void changedUpdate(FlowView JavaDoc fv, DocumentEvent e, Rectangle alloc) {
371         if (alloc != null) {
372         Component host = fv.getContainer();
373         if (host != null) {
374             host.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
375         }
376         } else {
377         fv.preferenceChanged(null, true, true);
378         }
379     }
380
381     /**
382      * This method gives flow strategies access to the logical
383      * view of the FlowView.
384      */

385     protected View JavaDoc getLogicalView(FlowView JavaDoc fv) {
386         return fv.layoutPool;
387     }
388
389     /**
390      * Update the flow on the given FlowView. By default, this causes
391      * all of the rows (child views) to be rebuilt to match the given
392      * constraints for each row. This is called by a FlowView.layout
393      * to update the child views in the flow.
394      *
395      * @param fv the view to reflow
396      */

397     public void layout(FlowView JavaDoc fv) {
398         int p0 = fv.getStartOffset();
399         int p1 = fv.getEndOffset();
400
401         // we want to preserve all views from the logicalView from being
402
// removed
403
View JavaDoc lv = getLogicalView(fv);
404         int n = lv.getViewCount();
405         for( int i = 0; i < n; i++ ) {
406         View JavaDoc v = lv.getView(i);
407         v.setParent(lv);
408         }
409         fv.removeAll();
410         for (int rowIndex = 0; p0 < p1; rowIndex++) {
411         View JavaDoc row = fv.createRow();
412         fv.append(row);
413         
414         // layout the row to the current span. If nothing fits,
415
// force something.
416
int next = layoutRow(fv, rowIndex, p0);
417         if (row.getViewCount() == 0) {
418             row.append(createView(fv, p0, Integer.MAX_VALUE, rowIndex));
419             next = row.getEndOffset();
420         }
421         if (next <= p0) {
422             throw new StateInvariantError JavaDoc("infinite loop in formatting");
423         } else {
424             p0 = next;
425         }
426         }
427     }
428
429     /**
430      * Creates a row of views that will fit within the
431      * layout span of the row. This is called by the layout method.
432      * This is implemented to fill the row by repeatedly calling
433      * the createView method until the available span has been
434      * exhausted, a forced break was encountered, or the createView
435      * method returned null. If the remaining span was exhaused,
436      * the adjustRow method will be called to perform adjustments
437      * to the row to try and make it fit into the given span.
438      *
439      * @param rowIndex the index of the row to fill in with views. The
440      * row is assumed to be empty on entry.
441      * @param pos The current position in the children of
442      * this views element from which to start.
443      * @return the position to start the next row
444      */

445     protected int layoutRow(FlowView JavaDoc fv, int rowIndex, int pos) {
446         View JavaDoc row = fv.getView(rowIndex);
447         int x = fv.getFlowStart(rowIndex);
448         int spanLeft = fv.getFlowSpan(rowIndex);
449         int end = fv.getEndOffset();
450         TabExpander JavaDoc te = (fv instanceof TabExpander JavaDoc) ? (TabExpander JavaDoc)fv : null;
451
452         // Indentation.
453
int preX = x;
454         int availableSpan = spanLeft;
455         preX = x;
456         
457         final int flowAxis = fv.getFlowAxis();
458         boolean forcedBreak = false;
459         while (pos < end && spanLeft >= 0) {
460         View JavaDoc v = createView(fv, pos, spanLeft, rowIndex);
461         if ((v == null)
462                     || (spanLeft == 0
463                         && v.getPreferredSpan(flowAxis) > 0)) {
464             break;
465         }
466         
467         int chunkSpan;
468         if ((flowAxis == X_AXIS) && (v instanceof TabableView JavaDoc)) {
469             chunkSpan = (int) ((TabableView JavaDoc)v).getTabbedSpan(x, te);
470         } else {
471             chunkSpan = (int) v.getPreferredSpan(flowAxis);
472         }
473
474         // If a forced break is necessary, break
475
if (v.getBreakWeight(flowAxis, pos, spanLeft) >= ForcedBreakWeight) {
476             int n = row.getViewCount();
477             if (n > 0) {
478             /* If this is a forced break and it's not the only view
479              * the view should be replaced with a call to breakView.
480              * If it's it only view, it should be used directly. In
481              * either case no more children should be added beyond this
482              * view.
483              */

484             v = v.breakView(flowAxis, pos, x, spanLeft);
485             if (v != null) {
486                 if ((flowAxis == X_AXIS) && (v instanceof TabableView JavaDoc)) {
487                 chunkSpan = (int) ((TabableView JavaDoc)v).getTabbedSpan(x, te);
488                 } else {
489                 chunkSpan = (int) v.getPreferredSpan(flowAxis);
490                 }
491             } else {
492                 chunkSpan = 0;
493             }
494             }
495             forcedBreak = true;
496         }
497         
498         spanLeft -= chunkSpan;
499         x += chunkSpan;
500         if (v != null) {
501             row.append(v);
502             pos = v.getEndOffset();
503         }
504         if (forcedBreak) {
505             break;
506         }
507         
508         }
509         if (spanLeft < 0) {
510         // This row is too long and needs to be adjusted.
511
adjustRow(fv, rowIndex, availableSpan, preX);
512         } else if (row.getViewCount() == 0) {
513         // Impossible spec... put in whatever is left.
514
View JavaDoc v = createView(fv, pos, Integer.MAX_VALUE, rowIndex);
515         row.append(v);
516         }
517         return row.getEndOffset();
518     }
519
520     /**
521      * Adjusts the given row if possible to fit within the
522      * layout span. By default this will try to find the
523      * highest break weight possible nearest the end of
524      * the row. If a forced break is encountered, the
525      * break will be positioned there.
526      *
527      * @param rowIndex the row to adjust to the current layout
528      * span.
529      * @param desiredSpan the current layout span >= 0
530      * @param x the location r starts at.
531      */

532         protected void adjustRow(FlowView JavaDoc fv, int rowIndex, int desiredSpan, int x) {
533         final int flowAxis = fv.getFlowAxis();
534         View JavaDoc r = fv.getView(rowIndex);
535         int n = r.getViewCount();
536         int span = 0;
537         int bestWeight = BadBreakWeight;
538         int bestSpan = 0;
539         int bestIndex = -1;
540         int bestOffset = 0;
541         View JavaDoc v;
542         for (int i = 0; i < n; i++) {
543         v = r.getView(i);
544         int spanLeft = desiredSpan - span;
545         
546         int w = v.getBreakWeight(flowAxis, x + span, spanLeft);
547         if ((w >= bestWeight) && (w > BadBreakWeight)) {
548             bestWeight = w;
549             bestIndex = i;
550             bestSpan = span;
551             if (w >= ForcedBreakWeight) {
552             // it's a forced break, so there is
553
// no point in searching further.
554
break;
555             }
556         }
557         span += v.getPreferredSpan(flowAxis);
558         }
559         if (bestIndex < 0) {
560         // there is nothing that can be broken, leave
561
// it in it's current state.
562
return;
563         }
564
565         // Break the best candidate view, and patch up the row.
566
int spanLeft = desiredSpan - bestSpan;
567         v = r.getView(bestIndex);
568         v = v.breakView(flowAxis, v.getStartOffset(), x + bestSpan, spanLeft);
569         View JavaDoc[] va = new View JavaDoc[1];
570         va[0] = v;
571         View JavaDoc lv = getLogicalView(fv);
572         for (int i = bestIndex; i < n; i++) {
573         View JavaDoc tmpView = r.getView(i);
574         if (contains(lv,tmpView)) {
575             tmpView.setParent(lv);
576         } else if (tmpView.getViewCount() > 0) {
577             recursiveReparent(tmpView, lv);
578         }
579         }
580         r.replace(bestIndex, n - bestIndex, va);
581     }
582
583     private void recursiveReparent(View JavaDoc v, View JavaDoc logicalView) {
584         int n = v.getViewCount();
585         for (int i = 0; i < n; i++) {
586         View JavaDoc tmpView = v.getView(i);
587         if (contains(logicalView,tmpView)) {
588             tmpView.setParent(logicalView);
589         } else {
590             recursiveReparent(tmpView, logicalView);
591         }
592         }
593     }
594
595     private boolean contains(View JavaDoc logicalView, View JavaDoc v) {
596         int n = logicalView.getViewCount();
597         for (int i = 0; i < n; i++) {
598         if (logicalView.getView(i) == v) {
599             return true;
600         }
601         }
602         return false;
603     }
604
605     /**
606      * Creates a view that can be used to represent the current piece
607      * of the flow. This can be either an entire view from the
608      * logical view, or a fragment of the logical view.
609      *
610      * @param fv the view holding the flow
611      * @param startOffset the start location for the view being created
612      * @param spanLeft the about of span left to fill in the row
613      * @param rowIndex the row the view will be placed into
614      */

615     protected View JavaDoc createView(FlowView JavaDoc fv, int startOffset, int spanLeft, int rowIndex) {
616         // Get the child view that contains the given starting position
617
View JavaDoc lv = getLogicalView(fv);
618         int childIndex = lv.getViewIndex(startOffset, Position.Bias.Forward);
619         View JavaDoc v = lv.getView(childIndex);
620         if (startOffset==v.getStartOffset()) {
621         // return the entire view
622
return v;
623         }
624         
625         // return a fragment.
626
v = v.createFragment(startOffset, v.getEndOffset());
627         return v;
628     }
629     }
630
631     /**
632      * This class can be used to represent a logical view for
633      * a flow. It keeps the children updated to reflect the state
634      * of the model, gives the logical child views access to the
635      * view hierarchy, and calculates a preferred span. It doesn't
636      * do any rendering, layout, or model/view translation.
637      */

638     static class LogicalView extends CompositeView JavaDoc {
639
640     LogicalView(Element JavaDoc elem) {
641         super(elem);
642     }
643
644         protected int getViewIndexAtPosition(int pos) {
645         Element JavaDoc elem = getElement();
646         if (elem.isLeaf()) {
647         return 0;
648         }
649         return super.getViewIndexAtPosition(pos);
650     }
651     
652         protected void loadChildren(ViewFactory JavaDoc f) {
653         Element JavaDoc elem = getElement();
654         if (elem.isLeaf()) {
655         View JavaDoc v = new LabelView JavaDoc(elem);
656         append(v);
657         } else {
658         super.loadChildren(f);
659         }
660     }
661
662     /**
663      * Fetches the attributes to use when rendering. This view
664      * isn't directly responsible for an element so it returns
665      * the outer classes attributes.
666      */

667         public AttributeSet JavaDoc getAttributes() {
668         View JavaDoc p = getParent();
669         return (p != null) ? p.getAttributes() : null;
670     }
671
672     /**
673      * Determines the preferred span for this view along an
674      * axis.
675      *
676      * @param axis may be either View.X_AXIS or View.Y_AXIS
677      * @return the span the view would like to be rendered into.
678      * Typically the view is told to render into the span
679      * that is returned, although there is no guarantee.
680      * The parent may choose to resize or break the view.
681      * @see View#getPreferredSpan
682      */

683         public float getPreferredSpan(int axis) {
684         float maxpref = 0;
685         float pref = 0;
686         int n = getViewCount();
687         for (int i = 0; i < n; i++) {
688         View JavaDoc v = getView(i);
689         pref += v.getPreferredSpan(axis);
690         if (v.getBreakWeight(axis, 0, Integer.MAX_VALUE) >= ForcedBreakWeight) {
691             maxpref = Math.max(maxpref, pref);
692             pref = 0;
693         }
694         }
695         maxpref = Math.max(maxpref, pref);
696         return maxpref;
697     }
698
699     /**
700      * Determines the minimum span for this view along an
701      * axis. The is implemented to find the minimum unbreakable
702      * span.
703      *
704      * @param axis may be either View.X_AXIS or View.Y_AXIS
705      * @return the span the view would like to be rendered into.
706      * Typically the view is told to render into the span
707      * that is returned, although there is no guarantee.
708      * The parent may choose to resize or break the view.
709      * @see View#getPreferredSpan
710      */

711         public float getMinimumSpan(int axis) {
712         float maxmin = 0;
713         float min = 0;
714         boolean nowrap = false;
715         int n = getViewCount();
716         for (int i = 0; i < n; i++) {
717         View JavaDoc v = getView(i);
718         if (v.getBreakWeight(axis, 0, Integer.MAX_VALUE) == BadBreakWeight) {
719             min += v.getPreferredSpan(axis);
720             nowrap = true;
721         } else if (nowrap) {
722             maxmin = Math.max(min, maxmin);
723             nowrap = false;
724             min = 0;
725         }
726         }
727         maxmin = Math.max(maxmin, min);
728         return maxmin;
729     }
730
731     /**
732      * Forward the DocumentEvent to the given child view. This
733      * is implemented to reparent the child to the logical view
734      * (the children may have been parented by a row in the flow
735      * if they fit without breaking) and then execute the superclass
736      * behavior.
737      *
738      * @param v the child view to forward the event to.
739      * @param e the change information from the associated document
740      * @param a the current allocation of the view
741      * @param f the factory to use to rebuild if the view has children
742      * @see #forwardUpdate
743      * @since 1.3
744      */

745         protected void forwardUpdateToView(View JavaDoc v, DocumentEvent e,
746                        Shape a, ViewFactory JavaDoc f) {
747         v.setParent(this);
748         super.forwardUpdateToView(v, e, a, f);
749     }
750
751     // The following methods don't do anything useful, they
752
// simply keep the class from being abstract.
753

754     /**
755      * Renders using the given rendering surface and area on that
756      * surface. This is implemented to do nothing, the logical
757      * view is never visible.
758      *
759      * @param g the rendering surface to use
760      * @param allocation the allocated region to render into
761      * @see View#paint
762      */

763         public void paint(Graphics g, Shape allocation) {
764     }
765
766     /**
767      * Tests whether a point lies before the rectangle range.
768      * Implemented to return false, as hit detection is not
769      * performed on the logical view.
770      *
771      * @param x the X coordinate >= 0
772      * @param y the Y coordinate >= 0
773      * @param alloc the rectangle
774      * @return true if the point is before the specified range
775      */

776         protected boolean isBefore(int x, int y, Rectangle alloc) {
777         return false;
778     }
779
780     /**
781      * Tests whether a point lies after the rectangle range.
782      * Implemented to return false, as hit detection is not
783      * performed on the logical view.
784      *
785      * @param x the X coordinate >= 0
786      * @param y the Y coordinate >= 0
787      * @param alloc the rectangle
788      * @return true if the point is after the specified range
789      */

790         protected boolean isAfter(int x, int y, Rectangle alloc) {
791         return false;
792     }
793
794     /**
795      * Fetches the child view at the given point.
796      * Implemented to return null, as hit detection is not
797      * performed on the logical view.
798      *
799      * @param x the X coordinate >= 0
800      * @param y the Y coordinate >= 0
801      * @param alloc the parent's allocation on entry, which should
802      * be changed to the child's allocation on exit
803      * @return the child view
804      */

805         protected View JavaDoc getViewAtPoint(int x, int y, Rectangle alloc) {
806         return null;
807     }
808
809     /**
810      * Returns the allocation for a given child.
811      * Implemented to do nothing, as the logical view doesn't
812      * perform layout on the children.
813      *
814      * @param index the index of the child, >= 0 && < getViewCount()
815      * @param a the allocation to the interior of the box on entry,
816      * and the allocation of the child view at the index on exit.
817      */

818         protected void childAllocation(int index, Rectangle a) {
819     }
820     }
821
822
823 }
824
Popular Tags