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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [swing/] [text/] [CompositeView.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* CompositeView.java -- An abstract view that manages child views
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.Insets;
42
import java.awt.Rectangle;
43
import java.awt.Shape;
44
 
45
import javax.swing.SwingConstants;
46
 
47
/**
48
 * An abstract base implementation of {@link View} that manages child
49
 * <code>View</code>s.
50
 *
51
 * @author Roman Kennke (roman@kennke.org)
52
 */
53
public abstract class CompositeView
54
  extends View
55
{
56
 
57
  /**
58
   * The child views of this <code>CompositeView</code>.
59
   */
60
  View[] children;
61
 
62
  /**
63
   * The allocation of this <code>View</code> minus its insets. This is
64
   * initialized in {@link #getInsideAllocation} and reused and modified in
65
   * {@link #childAllocation(int, Rectangle)}.
66
   */
67
  Rectangle insideAllocation;
68
 
69
  /**
70
   * The insets of this <code>CompositeView</code>. This is initialized
71
   * in {@link #setInsets}.
72
   */
73
  Insets insets;
74
 
75
  /**
76
   * Creates a new <code>CompositeView</code> for the given
77
   * <code>Element</code>.
78
   *
79
   * @param element the element that is rendered by this CompositeView
80
   */
81
  public CompositeView(Element element)
82
  {
83
    super(element);
84
    children = new View[0];
85
    insets = new Insets(0, 0, 0, 0);
86
  }
87
 
88
  /**
89
   * Loads the child views of this <code>CompositeView</code>. This method
90
   * is called from {@link #setParent} to initialize the child views of
91
   * this composite view.
92
   *
93
   * @param f the view factory to use for creating new child views
94
   *
95
   * @see #setParent
96
   */
97
  protected void loadChildren(ViewFactory f)
98
  {
99
    Element el = getElement();
100
    int count = el.getElementCount();
101
    View[] newChildren = new View[count];
102
    for (int i = 0; i < count; ++i)
103
      {
104
        Element child = el.getElement(i);
105
        View view = f.create(child);
106
        newChildren[i] = view;
107
      }
108
    replace(0, getViewCount(), newChildren);
109
  }
110
 
111
  /**
112
   * Sets the parent of this <code>View</code>.
113
   * In addition to setting the parent, this calls {@link #loadChildren}, if
114
   * this <code>View</code> does not already have its children initialized.
115
   *
116
   * @param parent the parent to set
117
   */
118
  public void setParent(View parent)
119
  {
120
    super.setParent(parent);
121
    if (parent != null && ((children == null) || children.length == 0))
122
      loadChildren(getViewFactory());
123
  }
124
 
125
  /**
126
   * Returns the number of child views.
127
   *
128
   * @return the number of child views
129
   */
130
  public int getViewCount()
131
  {
132
    return children.length;
133
  }
134
 
135
  /**
136
   * Returns the child view at index <code>n</code>.
137
   *
138
   * @param n the index of the requested child view
139
   *
140
   * @return the child view at index <code>n</code>
141
   */
142
  public View getView(int n)
143
  {
144
    return children[n];
145
  }
146
 
147
  /**
148
   * Replaces child views by some other child views. If there are no views to
149
   * remove (<code>length == 0</code>), the result is a simple insert, if
150
   * there are no children to add (<code>view == null</code>) the result
151
   * is a simple removal.
152
   *
153
   * @param offset the start offset from where to remove children
154
   * @param length the number of children to remove
155
   * @param views the views that replace the removed children
156
   */
157
  public void replace(int offset, int length, View[] views)
158
  {
159
    // Check for null views to add.
160
    for (int i = 0; i < views.length; ++i)
161
      if (views[i] == null)
162
        throw new NullPointerException("Added views must not be null");
163
 
164
    int endOffset = offset + length;
165
 
166
    // First we set the parent of the removed children to null.
167
    for (int i = offset; i < endOffset; ++i)
168
      children[i].setParent(null);
169
 
170
    View[] newChildren = new View[children.length - length + views.length];
171
    System.arraycopy(children, 0, newChildren, 0, offset);
172
    System.arraycopy(views, 0, newChildren, offset, views.length);
173
    System.arraycopy(children, offset + length, newChildren,
174
                     offset + views.length,
175
                     children.length - (offset + length));
176
    children = newChildren;
177
 
178
    // Finally we set the parent of the added children to this.
179
    for (int i = 0; i < views.length; ++i)
180
      views[i].setParent(this);
181
  }
182
 
183
  /**
184
   * Returns the allocation for the specified child <code>View</code>.
185
   *
186
   * @param index the index of the child view
187
   * @param a the allocation for this view
188
   *
189
   * @return the allocation for the specified child <code>View</code>
190
   */
191
  public Shape getChildAllocation(int index, Shape a)
192
  {
193
    Rectangle r = getInsideAllocation(a);
194
    childAllocation(index, r);
195
    return r;
196
  }
197
 
198
  /**
199
   * Maps a position in the document into the coordinate space of the View.
200
   * The output rectangle usually reflects the font height but has a width
201
   * of zero.
202
   *
203
   * @param pos the position of the character in the model
204
   * @param a the area that is occupied by the view
205
   * @param bias either {@link Position.Bias#Forward} or
206
   *        {@link Position.Bias#Backward} depending on the preferred
207
   *        direction bias. If <code>null</code> this defaults to
208
   *        <code>Position.Bias.Forward</code>
209
   *
210
   * @return a rectangle that gives the location of the document position
211
   *         inside the view coordinate space
212
   *
213
   * @throws BadLocationException if <code>pos</code> is invalid
214
   * @throws IllegalArgumentException if b is not one of the above listed
215
   *         valid values
216
   */
217
  public Shape modelToView(int pos, Shape a, Position.Bias bias)
218
    throws BadLocationException
219
  {
220
    int childIndex = getViewIndex(pos, bias);
221
    if (childIndex != -1)
222
      {
223
        View child = getView(childIndex);
224
        Rectangle r = a.getBounds();
225
        childAllocation(childIndex, r);
226
        Shape result = child.modelToView(pos, r, bias);
227
        if (result == null)
228
          throw new AssertionError("" + child.getClass().getName()
229
                                   + ".modelToView() must not return null");
230
        return result;
231
      }
232
    else
233
      throw new BadLocationException("No child view for the specified location",
234
                                     pos);
235
  }
236
 
237
  /**
238
   * Maps a region in the document into the coordinate space of the View.
239
   *
240
   * @param p1 the beginning position inside the document
241
   * @param b1 the direction bias for the beginning position
242
   * @param p2 the end position inside the document
243
   * @param b2 the direction bias for the end position
244
   * @param a the area that is occupied by the view
245
   *
246
   * @return a rectangle that gives the span of the document region
247
   *         inside the view coordinate space
248
   *
249
   * @throws BadLocationException if <code>p1</code> or <code>p2</code> are
250
   *         invalid
251
   * @throws IllegalArgumentException if b1 or b2 is not one of the above
252
   *         listed valid values
253
   */
254
  public Shape modelToView(int p1, Position.Bias b1,
255
                           int p2, Position.Bias b2, Shape a)
256
    throws BadLocationException
257
  {
258
    // TODO: This is most likely not 100% ok, figure out what else is to
259
    // do here.
260
    return super.modelToView(p1, b1, p2, b2, a);
261
  }
262
 
263
  /**
264
   * Maps coordinates from the <code>View</code>'s space into a position
265
   * in the document model.
266
   *
267
   * @param x the x coordinate in the view space, x >= 0
268
   * @param y the y coordinate in the view space, y >= 0
269
   * @param a the allocation of this <code>View</code>
270
   * @param b the bias to use
271
   *
272
   * @return the position in the document that corresponds to the screen
273
   *         coordinates <code>x, y</code> >= 0
274
   */
275
  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
276
  {
277
    if (x >= 0 && y >= 0)
278
      {
279
        Rectangle r = getInsideAllocation(a);
280
        View view = getViewAtPoint((int) x, (int) y, r);
281
        return view.viewToModel(x, y, a, b);
282
      }
283
    return 0;
284
  }
285
 
286
  /**
287
   * Returns the next model location that is visible in eiter north / south
288
   * direction or east / west direction. This is used to determine the placement
289
   * of the caret when navigating around the document with the arrow keys. This
290
   * is a convenience method for {@link #getNextNorthSouthVisualPositionFrom}
291
   * and {@link #getNextEastWestVisualPositionFrom}.
292
   *
293
   * @param pos
294
   *          the model position to start search from
295
   * @param b
296
   *          the bias for <code>pos</code>
297
   * @param a
298
   *          the allocated region for this view
299
   * @param direction
300
   *          the direction from the current position, can be one of the
301
   *          following:
302
   *          <ul>
303
   *          <li>{@link SwingConstants#WEST}</li>
304
   *          <li>{@link SwingConstants#EAST}</li>
305
   *          <li>{@link SwingConstants#NORTH}</li>
306
   *          <li>{@link SwingConstants#SOUTH}</li>
307
   *          </ul>
308
   * @param biasRet
309
   *          the bias of the return value gets stored here
310
   * @return the position inside the model that represents the next visual
311
   *         location
312
   * @throws BadLocationException
313
   *           if <code>pos</code> is not a valid location inside the document
314
   *           model
315
   * @throws IllegalArgumentException
316
   *           if <code>direction</code> is invalid
317
   */
318
  public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
319
                                       int direction, Position.Bias[] biasRet)
320
    throws BadLocationException
321
  {
322
    int retVal = -1;
323
    switch (direction)
324
      {
325
      case SwingConstants.WEST:
326
      case SwingConstants.EAST:
327
        retVal = getNextEastWestVisualPositionFrom(pos, b, a, direction,
328
                                                   biasRet);
329
        break;
330
      case SwingConstants.NORTH:
331
      case SwingConstants.SOUTH:
332
        retVal = getNextNorthSouthVisualPositionFrom(pos, b, a, direction,
333
                                                     biasRet);
334
        break;
335
      default:
336
        throw new IllegalArgumentException("Illegal value for direction.");
337
      }
338
    return retVal;
339
  }
340
 
341
  /**
342
   * Returns the index of the child view that represents the specified
343
   * model location.
344
   *
345
   * @param pos the model location for which to determine the child view index
346
   * @param b the bias to be applied to <code>pos</code>
347
   *
348
   * @return the index of the child view that represents the specified
349
   *         model location
350
   */
351
  public int getViewIndex(int pos, Position.Bias b)
352
  {
353
    // FIXME: Handle bias somehow.
354
    return getViewIndexAtPosition(pos);
355
  }
356
 
357
  /**
358
   * Returns <code>true</code> if the specified point lies before the
359
   * given <code>Rectangle</code>, <code>false</code> otherwise.
360
   *
361
   * &quot;Before&quot; is typically defined as being to the left or above.
362
   *
363
   * @param x the X coordinate of the point
364
   * @param y the Y coordinate of the point
365
   * @param r the rectangle to test the point against
366
   *
367
   * @return <code>true</code> if the specified point lies before the
368
   *         given <code>Rectangle</code>, <code>false</code> otherwise
369
   */
370
  protected abstract boolean isBefore(int x, int y, Rectangle r);
371
 
372
  /**
373
   * Returns <code>true</code> if the specified point lies after the
374
   * given <code>Rectangle</code>, <code>false</code> otherwise.
375
   *
376
   * &quot;After&quot; is typically defined as being to the right or below.
377
   *
378
   * @param x the X coordinate of the point
379
   * @param y the Y coordinate of the point
380
   * @param r the rectangle to test the point against
381
   *
382
   * @return <code>true</code> if the specified point lies after the
383
   *         given <code>Rectangle</code>, <code>false</code> otherwise
384
   */
385
  protected abstract boolean isAfter(int x, int y, Rectangle r);
386
 
387
  /**
388
   * Returns the child <code>View</code> at the specified location.
389
   *
390
   * @param x the X coordinate
391
   * @param y the Y coordinate
392
   * @param r the inner allocation of this <code>BoxView</code> on entry,
393
   *        the allocation of the found child on exit
394
   *
395
   * @return the child <code>View</code> at the specified location
396
   */
397
  protected abstract View getViewAtPoint(int x, int y, Rectangle r);
398
 
399
  /**
400
   * Computes the allocation for a child <code>View</code>. The parameter
401
   * <code>a</code> stores the allocation of this <code>CompositeView</code>
402
   * and is then adjusted to hold the allocation of the child view.
403
   *
404
   * @param index the index of the child <code>View</code>
405
   * @param a the allocation of this <code>CompositeView</code> before the
406
   *        call, the allocation of the child on exit
407
   */
408
  protected abstract void childAllocation(int index, Rectangle a);
409
 
410
  /**
411
   * Returns the child <code>View</code> that contains the given model
412
   * position. The given <code>Rectangle</code> gives the parent's allocation
413
   * and is changed to the child's allocation on exit.
414
   *
415
   * @param pos the model position to query the child <code>View</code> for
416
   * @param a the parent allocation on entry and the child allocation on exit
417
   *
418
   * @return the child view at the given model position
419
   */
420
  protected View getViewAtPosition(int pos, Rectangle a)
421
  {
422
    int i = getViewIndexAtPosition(pos);
423
    View view = children[i];
424
    childAllocation(i, a);
425
    return view;
426
  }
427
 
428
  /**
429
   * Returns the index of the child <code>View</code> for the given model
430
   * position.
431
   *
432
   * @param pos the model position for whicht the child <code>View</code> is
433
   *        queried
434
   *
435
   * @return the index of the child <code>View</code> for the given model
436
   *         position
437
   */
438
  protected int getViewIndexAtPosition(int pos)
439
  {
440
    int index = -1;
441
    for (int i = 0; i < children.length; i++)
442
      {
443
        if (children[i].getStartOffset() <= pos
444
            && children[i].getEndOffset() > pos)
445
          {
446
            index = i;
447
            break;
448
          }
449
      }
450
    return index;
451
  }
452
 
453
  /**
454
   * Returns the allocation that is given to this <code>CompositeView</code>
455
   * minus this <code>CompositeView</code>'s insets.
456
   *
457
   * Also this translates from an immutable allocation to a mutable allocation
458
   * that is typically reused and further narrowed, like in
459
   * {@link #childAllocation}.
460
   *
461
   * @param a the allocation given to this <code>CompositeView</code>
462
   *
463
   * @return the allocation that is given to this <code>CompositeView</code>
464
   *         minus this <code>CompositeView</code>'s insets or
465
   *         <code>null</code> if a was <code>null</code>
466
   */
467
  protected Rectangle getInsideAllocation(Shape a)
468
  {
469
    if (a == null)
470
      return null;
471
 
472
    Rectangle alloc = a.getBounds();
473
    // Initialize the inside allocation rectangle. This is done inside
474
    // a synchronized block in order to avoid multiple threads creating
475
    // this instance simultanously.
476
    Rectangle inside;
477
    synchronized(this)
478
      {
479
        inside = insideAllocation;
480
        if (inside == null)
481
          {
482
            inside = new Rectangle();
483
            insideAllocation = inside;
484
          }
485
      }
486
    inside.x = alloc.x + insets.left;
487
    inside.y = alloc.y + insets.top;
488
    inside.width = alloc.width - insets.left - insets.right;
489
    inside.height = alloc.height - insets.top - insets.bottom;
490
    return inside;
491
  }
492
 
493
  /**
494
   * Sets the insets defined by attributes in <code>attributes</code>. This
495
   * queries the attribute keys {@link StyleConstants#SpaceAbove},
496
   * {@link StyleConstants#SpaceBelow}, {@link StyleConstants#LeftIndent} and
497
   * {@link StyleConstants#RightIndent} and calls {@link #setInsets} to
498
   * actually set the insets on this <code>CompositeView</code>.
499
   *
500
   * @param attributes the attributes from which to query the insets
501
   */
502
  protected void setParagraphInsets(AttributeSet attributes)
503
  {
504
    Float l = (Float) attributes.getAttribute(StyleConstants.LeftIndent);
505
    short left = 0;
506
    if (l != null)
507
      left = l.shortValue();
508
    Float r = (Float) attributes.getAttribute(StyleConstants.RightIndent);
509
    short right = 0;
510
    if (r != null)
511
      right = r.shortValue();
512
    Float t = (Float) attributes.getAttribute(StyleConstants.SpaceAbove);
513
    short top = 0;
514
    if (t != null)
515
      top = t.shortValue();
516
    Float b = (Float) attributes.getAttribute(StyleConstants.SpaceBelow);
517
    short bottom = 0;
518
    if (b != null)
519
      bottom = b.shortValue();
520
    setInsets(top, left, bottom, right);
521
  }
522
 
523
  /**
524
   * Sets the insets of this <code>CompositeView</code>.
525
   *
526
   * @param top the top inset
527
   * @param left the left inset
528
   * @param bottom the bottom inset
529
   * @param right the right inset
530
   */
531
  protected void setInsets(short top, short left, short bottom, short right)
532
  {
533
    insets.top = top;
534
    insets.left = left;
535
    insets.bottom = bottom;
536
    insets.right = right;
537
  }
538
 
539
  /**
540
   * Returns the left inset of this <code>CompositeView</code>.
541
   *
542
   * @return the left inset of this <code>CompositeView</code>
543
   */
544
  protected short getLeftInset()
545
  {
546
    return (short) insets.left;
547
  }
548
 
549
  /**
550
   * Returns the right inset of this <code>CompositeView</code>.
551
   *
552
   * @return the right inset of this <code>CompositeView</code>
553
   */
554
  protected short getRightInset()
555
  {
556
    return (short) insets.right;
557
  }
558
 
559
  /**
560
   * Returns the top inset of this <code>CompositeView</code>.
561
   *
562
   * @return the top inset of this <code>CompositeView</code>
563
   */
564
  protected short getTopInset()
565
  {
566
    return (short) insets.top;
567
  }
568
 
569
  /**
570
   * Returns the bottom inset of this <code>CompositeView</code>.
571
   *
572
   * @return the bottom inset of this <code>CompositeView</code>
573
   */
574
  protected short getBottomInset()
575
  {
576
    return (short) insets.bottom;
577
  }
578
 
579
  /**
580
   * Returns the next model location that is visible in north or south
581
   * direction.
582
   * This is used to determine the
583
   * placement of the caret when navigating around the document with
584
   * the arrow keys.
585
   *
586
   * @param pos the model position to start search from
587
   * @param b the bias for <code>pos</code>
588
   * @param a the allocated region for this view
589
   * @param direction the direction from the current position, can be one of
590
   *        the following:
591
   *        <ul>
592
   *        <li>{@link SwingConstants#NORTH}</li>
593
   *        <li>{@link SwingConstants#SOUTH}</li>
594
   *        </ul>
595
   * @param biasRet the bias of the return value gets stored here
596
   *
597
   * @return the position inside the model that represents the next visual
598
   *         location
599
   *
600
   * @throws BadLocationException if <code>pos</code> is not a valid location
601
   *         inside the document model
602
   * @throws IllegalArgumentException if <code>direction</code> is invalid
603
   */
604
  protected int getNextNorthSouthVisualPositionFrom(int pos, Position.Bias b,
605
                                                    Shape a, int direction,
606
                                                    Position.Bias[] biasRet)
607
    throws BadLocationException
608
  {
609
    // FIXME: Implement this correctly.
610
    return pos;
611
  }
612
 
613
  /**
614
   * Returns the next model location that is visible in east or west
615
   * direction.
616
   * This is used to determine the
617
   * placement of the caret when navigating around the document with
618
   * the arrow keys.
619
   *
620
   * @param pos the model position to start search from
621
   * @param b the bias for <code>pos</code>
622
   * @param a the allocated region for this view
623
   * @param direction the direction from the current position, can be one of
624
   *        the following:
625
   *        <ul>
626
   *        <li>{@link SwingConstants#EAST}</li>
627
   *        <li>{@link SwingConstants#WEST}</li>
628
   *        </ul>
629
   * @param biasRet the bias of the return value gets stored here
630
   *
631
   * @return the position inside the model that represents the next visual
632
   *         location
633
   *
634
   * @throws BadLocationException if <code>pos</code> is not a valid location
635
   *         inside the document model
636
   * @throws IllegalArgumentException if <code>direction</code> is invalid
637
   */
638
  protected int getNextEastWestVisualPositionFrom(int pos, Position.Bias b,
639
                                                  Shape a, int direction,
640
                                                  Position.Bias[] biasRet)
641
    throws BadLocationException
642
  {
643
    // FIXME: Implement this correctly.
644
    return pos;
645
  }
646
 
647
  /**
648
   * Determines if the next view in horinzontal direction is located to
649
   * the east or west of the view at position <code>pos</code>. Usually
650
   * the <code>View</code>s are laid out from the east to the west, so
651
   * we unconditionally return <code>false</code> here. Subclasses that
652
   * support bidirectional text may wish to override this method.
653
   *
654
   * @param pos the position in the document
655
   * @param bias the bias to be applied to <code>pos</code>
656
   *
657
   * @return <code>true</code> if the next <code>View</code> is located
658
   *         to the EAST, <code>false</code> otherwise
659
   */
660
  protected boolean flipEastAndWestAtEnds(int pos, Position.Bias bias)
661
  {
662
    return false;
663
  }
664
 
665
  /**
666
   * Returns the document position that is (visually) nearest to the given
667
   * document position <code>pos</code> in the given direction <code>d</code>.
668
   *
669
   * @param c the text component
670
   * @param pos the document position
671
   * @param b the bias for <code>pos</code>
672
   * @param d the direction, must be either {@link SwingConstants#NORTH},
673
   *        {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
674
   *        {@link SwingConstants#EAST}
675
   * @param biasRet an array of {@link Position.Bias} that can hold at least
676
   *        one element, which is filled with the bias of the return position
677
   *        on method exit
678
   *
679
   * @return the document position that is (visually) nearest to the given
680
   *         document position <code>pos</code> in the given direction
681
   *         <code>d</code>
682
   *
683
   * @throws BadLocationException if <code>pos</code> is not a valid offset in
684
   *         the document model
685
   */
686
  public int getNextVisualPositionFrom(JTextComponent c, int pos,
687
                                       Position.Bias b, int d,
688
                                       Position.Bias[] biasRet)
689
    throws BadLocationException
690
  {
691
    // TODO: Implement this properly.
692
    throw new AssertionError("Not implemented yet.");
693
  }
694
}

powered by: WebSVN 2.1.0

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