OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [text/] [FlowView.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* FlowView.java -- A composite View
2
   Copyright (C) 2005  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing.text;
40
 
41
import java.awt.Component;
42
import java.awt.Graphics;
43
import java.awt.Rectangle;
44
import java.awt.Shape;
45
 
46
import javax.swing.SizeRequirements;
47
import javax.swing.event.DocumentEvent;
48
 
49
/**
50
 * A <code>View</code> that can flows it's children into it's layout space.
51
 *
52
 * The <code>FlowView</code> manages a set of logical views (that are
53
 * the children of the {@link #layoutPool} field). These are translated
54
 * at layout time into a set of physical views. These are the views that
55
 * are managed as the real child views. Each of these child views represents
56
 * a row and are laid out within a box using the superclasses behaviour.
57
 * The concrete implementation of the rows must be provided by subclasses.
58
 *
59
 * @author Roman Kennke (roman@kennke.org)
60
 */
61
public abstract class FlowView extends BoxView
62
{
63
  /**
64
   * A strategy for translating the logical views of a <code>FlowView</code>
65
   * into the real views.
66
   */
67
  public static class FlowStrategy
68
  {
69
    /**
70
     * Creates a new instance of <code>FlowStragegy</code>.
71
     */
72
    public FlowStrategy()
73
    {
74
      // Nothing to do here.
75
    }
76
 
77
    /**
78
     * Receives notification from a <code>FlowView</code> that some content
79
     * has been inserted into the document at a location that the
80
     * <code>FlowView</code> is responsible for.
81
     *
82
     * The default implementation simply calls {@link #layout}.
83
     *
84
     * @param fv the flow view that sends the notification
85
     * @param e the document event describing the change
86
     * @param alloc the current allocation of the flow view
87
     */
88
    public void insertUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
89
    {
90
      if (alloc == null)
91
        {
92
          fv.layoutChanged(X_AXIS);
93
          fv.layoutChanged(Y_AXIS);
94
        }
95
      else
96
        {
97
          Component host = fv.getContainer();
98
          if (host != null)
99
            host.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
100
        }
101
    }
102
 
103
    /**
104
     * Receives notification from a <code>FlowView</code> that some content
105
     * has been removed from the document at a location that the
106
     * <code>FlowView</code> is responsible for.
107
     *
108
     * The default implementation simply calls {@link #layout}.
109
     *
110
     * @param fv the flow view that sends the notification
111
     * @param e the document event describing the change
112
     * @param alloc the current allocation of the flow view
113
     */
114
    public void removeUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
115
    {
116
      if (alloc == null)
117
        {
118
          fv.layoutChanged(X_AXIS);
119
          fv.layoutChanged(Y_AXIS);
120
        }
121
      else
122
        {
123
          Component host = fv.getContainer();
124
          if (host != null)
125
            host.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
126
        }
127
    }
128
 
129
    /**
130
     * Receives notification from a <code>FlowView</code> that some attributes
131
     * have changed in the document at a location that the
132
     * <code>FlowView</code> is responsible for.
133
     *
134
     * The default implementation simply calls {@link #layout}.
135
     *
136
     * @param fv the flow view that sends the notification
137
     * @param e the document event describing the change
138
     * @param alloc the current allocation of the flow view
139
     */
140
    public void changedUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
141
    {
142
      if (alloc == null)
143
        {
144
          fv.layoutChanged(X_AXIS);
145
          fv.layoutChanged(Y_AXIS);
146
        }
147
      else
148
        {
149
          Component host = fv.getContainer();
150
          if (host != null)
151
            host.repaint(alloc.x, alloc.y, alloc.width, alloc.height);
152
        }
153
    }
154
 
155
    /**
156
     * Returns the logical view of the managed <code>FlowView</code>.
157
     *
158
     * @param fv the flow view for which to return the logical view
159
     *
160
     * @return the logical view of the managed <code>FlowView</code>
161
     */
162
    protected View getLogicalView(FlowView fv)
163
    {
164
      return fv.layoutPool;
165
    }
166
 
167
    /**
168
     * Performs the layout for the whole view. By default this rebuilds
169
     * all the physical views from the logical views of the managed FlowView.
170
     *
171
     * This is called by {@link FlowView#layout} to update the layout of
172
     * the view.
173
     *
174
     * @param fv the flow view for which we perform the layout
175
     */
176
    public void layout(FlowView fv)
177
    {
178
      int start = fv.getStartOffset();
179
      int end = fv.getEndOffset();
180
 
181
      // Preserve the views from the logical view from beeing removed.
182
      View lv = getLogicalView(fv);
183
      int viewCount = lv.getViewCount();
184
      for (int i = 0; i < viewCount; i++)
185
        {
186
          View v = lv.getView(i);
187
          v.setParent(lv);
188
        }
189
 
190
      // Then remove all views from the flow view.
191
      fv.removeAll();
192
 
193
      for (int rowIndex = 0; start < end; rowIndex++)
194
        {
195
          View row = fv.createRow();
196
          fv.append(row);
197
          int next = layoutRow(fv, rowIndex, start);
198
          if (row.getViewCount() == 0)
199
            {
200
              row.append(createView(fv, start, Integer.MAX_VALUE, rowIndex));
201
              next = row.getEndOffset();
202
            }
203
          if (start < next)
204
            start = next;
205
          else
206
            assert false: "May not happen";
207
        }
208
    }
209
 
210
    /**
211
     * Lays out one row of the flow view. This is called by {@link #layout} to
212
     * fill one row with child views until the available span is exhausted. The
213
     * default implementation fills the row by calling
214
     * {@link #createView(FlowView, int, int, int)} until the available space is
215
     * exhausted, a forced break is encountered or there are no more views in
216
     * the logical view. If the available space is exhausted,
217
     * {@link #adjustRow(FlowView, int, int, int)} is called to fit the row into
218
     * the available span.
219
     *
220
     * @param fv the flow view for which we perform the layout
221
     * @param rowIndex the index of the row
222
     * @param pos the model position for the beginning of the row
223
     * @return the start position of the next row
224
     */
225
    protected int layoutRow(FlowView fv, int rowIndex, int pos)
226
    {
227
      View row = fv.getView(rowIndex);
228
      int axis = fv.getFlowAxis();
229
      int span = fv.getFlowSpan(rowIndex);
230
      int x = fv.getFlowStart(rowIndex);
231
      int end = fv.getEndOffset();
232
 
233
      // Needed for adjusting indentation in adjustRow().
234
      int preX = x;
235
      int availableSpan = span;
236
 
237
      TabExpander tabExp = fv instanceof TabExpander ? (TabExpander) fv : null;
238
 
239
      boolean forcedBreak = false;
240
      while (pos < end && span >= 0)
241
        {
242
          View view = createView(fv, pos, span, rowIndex);
243
          if (view == null
244
              || (span == 0 && view.getPreferredSpan(axis) > 0))
245
            break;
246
 
247
          int viewSpan;
248
          if (axis == X_AXIS && view instanceof TabableView)
249
            viewSpan = (int) ((TabableView) view).getTabbedSpan(x, tabExp);
250
          else
251
            viewSpan = (int) view.getPreferredSpan(axis);
252
 
253
          // Break if the line if the view does not fit in this row or the
254
          // line just must be broken.
255
          int breakWeight = view.getBreakWeight(axis, pos, span);
256
          if (breakWeight >= ForcedBreakWeight)
257
            {
258
              int rowViewCount = row.getViewCount();
259
              if (rowViewCount > 0)
260
                {
261
                  view = view.breakView(axis, pos, x, span);
262
                  if (view != null)
263
                    {
264
                      if (axis == X_AXIS && view instanceof TabableView)
265
                        viewSpan =
266
                          (int) ((TabableView) view).getTabbedSpan(x, tabExp);
267
                      else
268
                        viewSpan = (int) view.getPreferredSpan(axis);
269
                    }
270
                  else
271
                    viewSpan = 0;
272
                }
273
              forcedBreak = true;
274
            }
275
          span -= viewSpan;
276
          x += viewSpan;
277
          if (view != null)
278
            {
279
              row.append(view);
280
              pos = view.getEndOffset();
281
            }
282
          if (forcedBreak)
283
            break;
284
        }
285
 
286
      if (span < 0)
287
        adjustRow(fv, rowIndex, availableSpan, preX);
288
      else if (row.getViewCount() == 0)
289
        {
290
          View view = createView(fv, pos, Integer.MAX_VALUE, rowIndex);
291
          row.append(view);
292
        }
293
      return row.getEndOffset();
294
    }
295
 
296
    /**
297
     * Creates physical views that form the rows of the flow view. This
298
     * can be an entire view from the logical view (if it fits within the
299
     * available span), a fragment of such a view (if it doesn't fit in the
300
     * available span and can be broken down) or <code>null</code> (if it does
301
     * not fit in the available span and also cannot be broken down).
302
     *
303
     * The default implementation fetches the logical view at the specified
304
     * <code>startOffset</code>. If that view has a different startOffset than
305
     * specified in the argument, a fragment is created using
306
     * {@link View#createFragment(int, int)} that has the correct startOffset
307
     * and the logical view's endOffset.
308
     *
309
     * @param fv the flow view
310
     * @param startOffset the start offset for the view to be created
311
     * @param spanLeft the available span
312
     * @param rowIndex the index of the row
313
     *
314
     * @return a view to fill the row with, or <code>null</code> if there
315
     *         is no view or view fragment that fits in the available span
316
     */
317
    protected View createView(FlowView fv, int startOffset, int spanLeft,
318
                              int rowIndex)
319
    {
320
       View logicalView = getLogicalView(fv);
321
       int index = logicalView.getViewIndex(startOffset,
322
                                            Position.Bias.Forward);
323
       View retVal = logicalView.getView(index);
324
       if (retVal.getStartOffset() != startOffset)
325
         retVal = retVal.createFragment(startOffset, retVal.getEndOffset());
326
       return retVal;
327
    }
328
 
329
    /**
330
     * Tries to adjust the specified row to fit within the desired span. The
331
     * default implementation iterates through the children of the specified
332
     * row to find the view that has the highest break weight and - if there
333
     * is more than one view with such a break weight - which is nearest to
334
     * the end of the row. If there is such a view that has a break weight >
335
     * {@link View#BadBreakWeight}, this view is broken using the
336
     * {@link View#breakView(int, int, float, float)} method and this view and
337
     * all views after the now broken view are replaced by the broken view.
338
     *
339
     * @param fv the flow view
340
     * @param rowIndex the index of the row to be adjusted
341
     * @param desiredSpan the layout span
342
     * @param x the X location at which the row starts
343
     */
344
    protected void adjustRow(FlowView fv, int rowIndex, int desiredSpan, int x) {
345
      // Determine the last view that has the highest break weight.
346
      int axis = fv.getFlowAxis();
347
      View row = fv.getView(rowIndex);
348
      int count = row.getViewCount();
349
      int breakIndex = -1;
350
      int breakWeight = BadBreakWeight;
351
      int breakSpan = 0;
352
      int currentSpan = 0;
353
      for (int i = 0; i < count; ++i)
354
        {
355
          View view = row.getView(i);
356
          int spanLeft = desiredSpan - currentSpan;
357
          int weight = view.getBreakWeight(axis, x + currentSpan, spanLeft);
358
          if (weight >= breakWeight && weight > BadBreakWeight)
359
            {
360
              breakIndex = i;
361
              breakSpan = currentSpan;
362
              breakWeight = weight;
363
              if (weight >= ForcedBreakWeight)
364
                // Don't search further.
365
                break;
366
            }
367
          currentSpan += view.getPreferredSpan(axis);
368
        }
369
 
370
      // If there is a potential break location found, break the row at
371
      // this location.
372
      if (breakIndex >= 0)
373
        {
374
          int spanLeft = desiredSpan - breakSpan;
375
          View toBeBroken = row.getView(breakIndex);
376
          View brokenView = toBeBroken.breakView(axis,
377
                                                 toBeBroken.getStartOffset(),
378
                                                 x + breakSpan, spanLeft);
379
          View lv = getLogicalView(fv);
380
          for (int i = breakIndex; i < count; i++)
381
            {
382
              View tmp = row.getView(i);
383
              if (contains(lv, tmp))
384
                tmp.setParent(lv);
385
              else if (tmp.getViewCount() > 0)
386
                reparent(tmp, lv);
387
            }
388
          row.replace(breakIndex, count - breakIndex,
389
                      new View[]{ brokenView });
390
        }
391
 
392
    }
393
 
394
    /**
395
     * Helper method to determine if one view contains another as child.
396
     */
397
    private boolean contains(View view, View child)
398
    {
399
      boolean ret = false;
400
      int n  = view.getViewCount();
401
      for (int i = 0; i < n && ret == false; i++)
402
        {
403
          if (view.getView(i) == child)
404
            ret = true;
405
        }
406
      return ret;
407
    }
408
 
409
    /**
410
     * Helper method that reparents the <code>view</code> and all of its
411
     * decendents to the <code>parent</code> (the logical view).
412
     *
413
     * @param view the view to reparent
414
     * @param parent the new parent
415
     */
416
    private void reparent(View view, View parent)
417
    {
418
      int n = view.getViewCount();
419
      for (int i = 0; i < n; i++)
420
        {
421
          View tmp = view.getView(i);
422
          if (contains(parent, tmp))
423
            tmp.setParent(parent);
424
          else
425
            reparent(tmp, parent);
426
        }
427
    }
428
  }
429
 
430
  /**
431
   * This special subclass of <code>View</code> is used to represent
432
   * the logical representation of this view. It does not support any
433
   * visual representation, this is handled by the physical view implemented
434
   * in the <code>FlowView</code>.
435
   */
436
  class LogicalView extends CompositeView
437
  {
438
    /**
439
     * Creates a new LogicalView instance.
440
     */
441
    LogicalView(Element el)
442
    {
443
      super(el);
444
    }
445
 
446
    /**
447
     * Overridden to return the attributes of the parent
448
     * (== the FlowView instance).
449
     */
450
    public AttributeSet getAttributes()
451
    {
452
      View p = getParent();
453
      return p != null ? p.getAttributes() : null;
454
    }
455
 
456
    protected void childAllocation(int index, Rectangle a)
457
    {
458
      // Nothing to do here (not visual).
459
    }
460
 
461
    protected View getViewAtPoint(int x, int y, Rectangle r)
462
    {
463
      // Nothing to do here (not visual).
464
      return null;
465
    }
466
 
467
    protected boolean isAfter(int x, int y, Rectangle r)
468
    {
469
      // Nothing to do here (not visual).
470
      return false;
471
    }
472
 
473
    protected boolean isBefore(int x, int y, Rectangle r)
474
    {
475
      // Nothing to do here (not visual).
476
      return false;
477
    }
478
 
479
    public float getPreferredSpan(int axis)
480
    {
481
      float max = 0;
482
      float pref = 0;
483
      int n = getViewCount();
484
      for (int i = 0; i < n; i++)
485
        {
486
          View v = getView(i);
487
          pref += v.getPreferredSpan(axis);
488
          if (v.getBreakWeight(axis, 0, Integer.MAX_VALUE)
489
              >= ForcedBreakWeight)
490
            {
491
              max = Math.max(max, pref);
492
              pref = 0;
493
            }
494
        }
495
      max = Math.max(max, pref);
496
      return max;
497
    }
498
 
499
    public float getMinimumSpan(int axis)
500
    {
501
      float max = 0;
502
      float min = 0;
503
      boolean wrap = true;
504
      int n = getViewCount();
505
      for (int i = 0; i < n; i++)
506
        {
507
          View v = getView(i);
508
          if (v.getBreakWeight(axis, 0, Integer.MAX_VALUE)
509
              == BadBreakWeight)
510
            {
511
              min += v.getPreferredSpan(axis);
512
              wrap = false;
513
            }
514
          else if (! wrap)
515
            {
516
              max = Math.max(min, max);
517
              wrap = true;
518
              min = 0;
519
            }
520
        }
521
      max = Math.max(max, min);
522
      return max;
523
    }
524
 
525
    public void paint(Graphics g, Shape s)
526
    {
527
      // Nothing to do here (not visual).
528
    }
529
 
530
    /**
531
     * Overridden to handle possible leaf elements.
532
     */
533
    protected void loadChildren(ViewFactory f)
534
    {
535
      Element el = getElement();
536
      if (el.isLeaf())
537
        {
538
          View v = new LabelView(el);
539
          append(v);
540
        }
541
      else
542
        super.loadChildren(f);
543
    }
544
 
545
    /**
546
     * Overridden to reparent the children to this logical view, in case
547
     * they have been parented by a row.
548
     */
549
    protected void forwardUpdateToView(View v, DocumentEvent e, Shape a,
550
                                       ViewFactory f)
551
    {
552
      v.setParent(this);
553
      super.forwardUpdateToView(v, e, a, f);
554
    }
555
 
556
    /**
557
     * Overridden to handle possible leaf element.
558
     */
559
    protected int getViewIndexAtPosition(int pos)
560
    {
561
      int index = 0;
562
      if (! getElement().isLeaf())
563
        index = super.getViewIndexAtPosition(pos);
564
      return index;
565
    }
566
  }
567
 
568
  /**
569
   * The shared instance of FlowStrategy.
570
   */
571
  static final FlowStrategy sharedStrategy = new FlowStrategy();
572
 
573
  /**
574
   * The span of the <code>FlowView</code> that should be flowed.
575
   */
576
  protected int layoutSpan;
577
 
578
  /**
579
   * Represents the logical child elements of this view, encapsulated within
580
   * one parent view (an instance of a package private <code>LogicalView</code>
581
   * class). These will be translated to a set of real views that are then
582
   * displayed on screen. This translation is performed by the inner class
583
   * {@link FlowStrategy}.
584
   */
585
  protected View layoutPool;
586
 
587
  /**
588
   * The <code>FlowStrategy</code> to use for translating between the
589
   * logical and physical view.
590
   */
591
  protected FlowStrategy strategy;
592
 
593
  /**
594
   * Creates a new <code>FlowView</code> for the given
595
   * <code>Element</code> and <code>axis</code>.
596
   *
597
   * @param element the element that is rendered by this FlowView
598
   * @param axis the axis along which the view is tiled, either
599
   *        <code>View.X_AXIS</code> or <code>View.Y_AXIS</code>, the flow
600
   *        axis is orthogonal to this one
601
   */
602
  public FlowView(Element element, int axis)
603
  {
604
    super(element, axis);
605
    strategy = sharedStrategy;
606
    layoutSpan = Short.MAX_VALUE;
607
  }
608
 
609
  /**
610
   * Returns the axis along which the view should be flowed. This is
611
   * orthogonal to the axis along which the boxes are tiled.
612
   *
613
   * @return the axis along which the view should be flowed
614
   */
615
  public int getFlowAxis()
616
  {
617
    int axis = getAxis();
618
    int flowAxis;
619
 
620
    if (axis == X_AXIS)
621
      flowAxis = Y_AXIS;
622
    else
623
      flowAxis = X_AXIS;
624
 
625
    return flowAxis;
626
 
627
  }
628
 
629
  /**
630
   * Returns the span of the flow for the specified child view. A flow
631
   * layout can be shaped by providing different span values for different
632
   * child indices. The default implementation returns the entire available
633
   * span inside the view.
634
   *
635
   * @param index the index of the child for which to return the span
636
   *
637
   * @return the span of the flow for the specified child view
638
   */
639
  public int getFlowSpan(int index)
640
  {
641
    return layoutSpan;
642
  }
643
 
644
  /**
645
   * Returns the location along the flow axis where the flow span starts
646
   * given a child view index. The flow can be shaped by providing
647
   * different values here.
648
   *
649
   * @param index the index of the child for which to return the flow location
650
   *
651
   * @return the location along the flow axis where the flow span starts
652
   */
653
  public int getFlowStart(int index)
654
  {
655
    return 0;
656
  }
657
 
658
  /**
659
   * Creates a new view that represents a row within a flow.
660
   *
661
   * @return a view for a new row
662
   */
663
  protected abstract View createRow();
664
 
665
  /**
666
   * Loads the children of this view. The <code>FlowView</code> does not
667
   * directly load its children. Instead it creates a logical view
668
   * ({@link #layoutPool}) which is filled by the logical child views.
669
   * The real children are created at layout time and each represent one
670
   * row.
671
   *
672
   * This method is called by {@link View#setParent} in order to initialize
673
   * the view.
674
   *
675
   * @param vf the view factory to use for creating the child views
676
   */
677
  protected void loadChildren(ViewFactory vf)
678
  {
679
    if (layoutPool == null)
680
      {
681
        layoutPool = new LogicalView(getElement());
682
      }
683
    layoutPool.setParent(this);
684
    // Initialize the flow strategy.
685
    strategy.insertUpdate(this, null, null);
686
  }
687
 
688
  /**
689
   * Performs the layout of this view. If the span along the flow axis changed,
690
   * this first calls {@link FlowStrategy#layout} in order to rebuild the
691
   * rows of this view. Then the superclass's behaviour is called to arrange
692
   * the rows within the box.
693
   *
694
   * @param width the width of the view
695
   * @param height the height of the view
696
   */
697
  protected void layout(int width, int height)
698
  {
699
    int flowAxis = getFlowAxis();
700
    int span;
701
    if (flowAxis == X_AXIS)
702
      span = (int) width;
703
    else
704
      span = (int) height;
705
 
706
    if (layoutSpan != span)
707
      {
708
        layoutChanged(flowAxis);
709
        layoutChanged(getAxis());
710
        layoutSpan = span;
711
      }
712
 
713
    if (! isLayoutValid(flowAxis))
714
      {
715
        int axis = getAxis();
716
        int oldSpan = axis == X_AXIS ? getWidth() : getHeight();
717
        strategy.layout(this);
718
        int newSpan = (int) getPreferredSpan(axis);
719
        if (oldSpan != newSpan)
720
          {
721
            View parent = getParent();
722
            if (parent != null)
723
              parent.preferenceChanged(this, axis == X_AXIS, axis == Y_AXIS);
724
          }
725
      }
726
 
727
    super.layout(width, height);
728
  }
729
 
730
  /**
731
   * Receice notification that some content has been inserted in the region
732
   * that this view is responsible for. This calls
733
   * {@link FlowStrategy#insertUpdate}.
734
   *
735
   * @param changes the document event describing the changes
736
   * @param a the current allocation of the view
737
   * @param vf the view factory that is used for creating new child views
738
   */
739
  public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
740
  {
741
    // First we must send the insertUpdate to the logical view so it can
742
    // be updated accordingly.
743
    layoutPool.insertUpdate(changes, a, vf);
744
    strategy.insertUpdate(this, changes, getInsideAllocation(a));
745
  }
746
 
747
  /**
748
   * Receice notification that some content has been removed from the region
749
   * that this view is responsible for. This calls
750
   * {@link FlowStrategy#removeUpdate}.
751
   *
752
   * @param changes the document event describing the changes
753
   * @param a the current allocation of the view
754
   * @param vf the view factory that is used for creating new child views
755
   */
756
  public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
757
  {
758
    layoutPool.removeUpdate(changes, a, vf);
759
    strategy.removeUpdate(this, changes, getInsideAllocation(a));
760
  }
761
 
762
  /**
763
   * Receice notification that some attributes changed in the region
764
   * that this view is responsible for. This calls
765
   * {@link FlowStrategy#changedUpdate}.
766
   *
767
   * @param changes the document event describing the changes
768
   * @param a the current allocation of the view
769
   * @param vf the view factory that is used for creating new child views
770
   */
771
  public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
772
  {
773
    layoutPool.changedUpdate(changes, a, vf);
774
    strategy.changedUpdate(this, changes, getInsideAllocation(a));
775
  }
776
 
777
  /**
778
   * Returns the index of the child <code>View</code> for the given model
779
   * position.
780
   *
781
   * This is implemented to iterate over the children of this
782
   * view (the rows) and return the index of the first view that contains
783
   * the given position.
784
   *
785
   * @param pos the model position for whicht the child <code>View</code> is
786
   *        queried
787
   *
788
   * @return the index of the child <code>View</code> for the given model
789
   *         position
790
   */
791
  protected int getViewIndexAtPosition(int pos)
792
  {
793
    // First make sure we have a valid layout.
794
    if (!isAllocationValid())
795
      layout(getWidth(), getHeight());
796
 
797
    int count = getViewCount();
798
    int result = -1;
799
 
800
    for (int i = 0; i < count; ++i)
801
      {
802
        View child = getView(i);
803
        int start = child.getStartOffset();
804
        int end = child.getEndOffset();
805
        if (start <= pos && end > pos)
806
          {
807
            result = i;
808
            break;
809
          }
810
      }
811
    return result;
812
  }
813
 
814
  /**
815
   * Calculates the size requirements of this <code>BoxView</code> along
816
   * its minor axis, that is the axis opposite to the axis specified in the
817
   * constructor.
818
   *
819
   * This is overridden and forwards the request to the logical view.
820
   *
821
   * @param axis the axis that is examined
822
   * @param r the <code>SizeRequirements</code> object to hold the result,
823
   *        if <code>null</code>, a new one is created
824
   *
825
   * @return the size requirements for this <code>BoxView</code> along
826
   *         the specified axis
827
   */
828
  protected SizeRequirements calculateMinorAxisRequirements(int axis,
829
                                                            SizeRequirements r)
830
  {
831
    SizeRequirements res = r;
832
    if (res == null)
833
      res = new SizeRequirements();
834
    res.minimum = (int) layoutPool.getMinimumSpan(axis);
835
    res.preferred = Math.max(res.minimum,
836
                             (int) layoutPool.getPreferredSpan(axis));
837
    res.maximum = Integer.MAX_VALUE;
838
    res.alignment = 0.5F;
839
    return res;
840
  }
841
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.