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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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