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/] [GlyphView.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* GlyphView.java -- A view to render styled text
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.Color;
42
import java.awt.Font;
43
import java.awt.FontMetrics;
44
import java.awt.Graphics;
45
import java.awt.Rectangle;
46
import java.awt.Shape;
47
import java.awt.Toolkit;
48
import java.text.BreakIterator;
49
 
50
import javax.swing.SwingConstants;
51
import javax.swing.event.DocumentEvent;
52
import javax.swing.text.Position.Bias;
53
 
54
/**
55
 * Renders a run of styled text. This {@link View} subclass paints the
56
 * characters of the <code>Element</code> it is responsible for using
57
 * the style information from that <code>Element</code>.
58
 *
59
 * @author Roman Kennke (roman@kennke.org)
60
 */
61
public class GlyphView extends View implements TabableView, Cloneable
62
{
63
 
64
  /**
65
   * An abstract base implementation for a glyph painter for
66
   * <code>GlyphView</code>.
67
   */
68
  public abstract static class GlyphPainter
69
  {
70
    /**
71
     * Creates a new <code>GlyphPainer</code>.
72
     */
73
    public GlyphPainter()
74
    {
75
      // Nothing to do here.
76
    }
77
 
78
    /**
79
     * Returns the ascent of the font that is used by this glyph painter.
80
     *
81
     * @param v the glyph view
82
     *
83
     * @return the ascent of the font that is used by this glyph painter
84
     */
85
    public abstract float getAscent(GlyphView v);
86
 
87
    /**
88
     * Returns the descent of the font that is used by this glyph painter.
89
     *
90
     * @param v the glyph view
91
     *
92
     * @return the descent of the font that is used by this glyph painter
93
     */
94
    public abstract float getDescent(GlyphView v);
95
 
96
    /**
97
     * Returns the full height of the rendered text.
98
     *
99
     * @return the full height of the rendered text
100
     */
101
    public abstract float getHeight(GlyphView view);
102
 
103
    /**
104
     * Determines the model offset, so that the text between <code>p0</code>
105
     * and this offset fits within the span starting at <code>x</code> with
106
     * the length of <code>len</code>.
107
     *
108
     * @param v the glyph view
109
     * @param p0 the starting offset in the model
110
     * @param x the start location in the view
111
     * @param len the length of the span in the view
112
     */
113
    public abstract int getBoundedPosition(GlyphView v, int p0, float x,
114
                                           float len);
115
 
116
    /**
117
     * Paints the glyphs.
118
     *
119
     * @param view the glyph view to paint
120
     * @param g the graphics context to use for painting
121
     * @param a the allocation of the glyph view
122
     * @param p0 the start position (in the model) from which to paint
123
     * @param p1 the end position (in the model) to which to paint
124
     */
125
    public abstract void paint(GlyphView view, Graphics g, Shape a, int p0,
126
                               int p1);
127
 
128
    /**
129
     * Maps a position in the document into the coordinate space of the View.
130
     * The output rectangle usually reflects the font height but has a width
131
     * of zero.
132
     *
133
     * @param view the glyph view
134
     * @param pos the position of the character in the model
135
     * @param a the area that is occupied by the view
136
     * @param b either {@link Position.Bias#Forward} or
137
     *        {@link Position.Bias#Backward} depending on the preferred
138
     *        direction bias. If <code>null</code> this defaults to
139
     *        <code>Position.Bias.Forward</code>
140
     *
141
     * @return a rectangle that gives the location of the document position
142
     *         inside the view coordinate space
143
     *
144
     * @throws BadLocationException if <code>pos</code> is invalid
145
     * @throws IllegalArgumentException if b is not one of the above listed
146
     *         valid values
147
     */
148
    public abstract Shape modelToView(GlyphView view, int pos, Position.Bias b,
149
                                      Shape a)
150
      throws BadLocationException;
151
 
152
    /**
153
     * Maps a visual position into a document location.
154
     *
155
     * @param v the glyph view
156
     * @param x the X coordinate of the visual position
157
     * @param y the Y coordinate of the visual position
158
     * @param a the allocated region
159
     * @param biasRet filled with the bias of the model location on method exit
160
     *
161
     * @return the model location that represents the specified view location
162
     */
163
    public abstract int viewToModel(GlyphView v, float x, float y, Shape a,
164
                                    Position.Bias[] biasRet);
165
 
166
    /**
167
     * Determine the span of the glyphs from location <code>p0</code> to
168
     * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
169
     * then TABs are expanded using this <code>TabExpander</code>.
170
     * The parameter <code>x</code> is the location at which the view is
171
     * located (this is important when using TAB expansion).
172
     *
173
     * @param view the glyph view
174
     * @param p0 the starting location in the document model
175
     * @param p1 the end location in the document model
176
     * @param te the tab expander to use
177
     * @param x the location at which the view is located
178
     *
179
     * @return the span of the glyphs from location <code>p0</code> to
180
     *         location <code>p1</code>, possibly using TAB expansion
181
     */
182
    public abstract float getSpan(GlyphView view, int p0, int p1,
183
                                  TabExpander te, float x);
184
 
185
 
186
    /**
187
     * Returns the model location that should be used to place a caret when
188
     * moving the caret through the document.
189
     *
190
     * @param v the glyph view
191
     * @param pos the current model location
192
     * @param b the bias for <code>p</code>
193
     * @param a the allocated region for the glyph view
194
     * @param direction the direction from the current position; Must be one of
195
     *        {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
196
     *        {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
197
     * @param biasRet filled with the bias of the resulting location when method
198
     *        returns
199
     *
200
     * @return the location within the document that should be used to place the
201
     *         caret when moving the caret around the document
202
     *
203
     * @throws BadLocationException if <code>pos</code> is an invalid model
204
     *         location
205
     * @throws IllegalArgumentException if <code>d</code> is invalid
206
     */
207
    public int getNextVisualPositionFrom(GlyphView v, int pos, Position.Bias b,
208
                                         Shape a, int direction,
209
                                         Position.Bias[] biasRet)
210
      throws BadLocationException
211
 
212
    {
213
      int result = pos;
214
      switch (direction)
215
      {
216
        case SwingConstants.EAST:
217
          result = pos + 1;
218
          break;
219
        case SwingConstants.WEST:
220
          result = pos - 1;
221
          break;
222
        case SwingConstants.NORTH:
223
        case SwingConstants.SOUTH:
224
        default:
225
          // This should be handled in enclosing view, since the glyph view
226
          // does not layout vertically.
227
          break;
228
      }
229
      return result;
230
    }
231
 
232
    /**
233
     * Returns a painter that can be used to render the specified glyph view.
234
     * If this glyph painter is stateful, then it should return a new instance.
235
     * However, if this painter is stateless it should return itself. The
236
     * default behaviour is to return itself.
237
     *
238
     * @param v the glyph view for which to create a painter
239
     * @param p0 the start offset of the rendered area
240
     * @param p1 the end offset of the rendered area
241
     *
242
     * @return a painter that can be used to render the specified glyph view
243
     */
244
    public GlyphPainter getPainter(GlyphView v, int p0, int p1)
245
    {
246
      return this;
247
    }
248
  }
249
 
250
  /**
251
   * The default <code>GlyphPainter</code> used in <code>GlyphView</code>.
252
   */
253
  static class DefaultGlyphPainter extends GlyphPainter
254
  {
255
    /**
256
     * Returns the full height of the rendered text.
257
     *
258
     * @return the full height of the rendered text
259
     */
260
    public float getHeight(GlyphView view)
261
    {
262
      Font font = view.getFont();
263
      FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
264
      float height = metrics.getHeight();
265
      return height;
266
    }
267
 
268
    /**
269
     * Paints the glyphs.
270
     *
271
     * @param view the glyph view to paint
272
     * @param g the graphics context to use for painting
273
     * @param a the allocation of the glyph view
274
     * @param p0 the start position (in the model) from which to paint
275
     * @param p1 the end position (in the model) to which to paint
276
     */
277
    public void paint(GlyphView view, Graphics g, Shape a, int p0,
278
                      int p1)
279
    {
280
      int height = (int) getHeight(view);
281
      Segment txt = view.getText(p0, p1);
282
      Rectangle bounds = a.getBounds();
283
 
284
      TabExpander tabEx = null;
285
      View parent = view.getParent();
286
      if (parent instanceof TabExpander)
287
        tabEx = (TabExpander) parent;
288
 
289
      // Fill the background of the text run.
290
      Color background = view.getBackground();
291
      g.setColor(background);
292
      int width = Utilities.getTabbedTextWidth(txt, g.getFontMetrics(),
293
                                               bounds.x, tabEx, txt.offset);
294
      g.fillRect(bounds.x, bounds.y, width, height);
295
 
296
      // Draw the actual text.
297
      g.setColor(view.getForeground());
298
      g.setFont(view.getFont());
299
      if (view.isSuperscript())
300
        // TODO: Adjust font for superscripting.
301
        Utilities.drawTabbedText(txt, bounds.x, bounds.y - height / 2, g, tabEx,
302
                                   txt.offset);
303
      else if (view.isSubscript())
304
        // TODO: Adjust font for subscripting.
305
        Utilities.drawTabbedText(txt, bounds.x, bounds.y + height / 2, g, tabEx,
306
                                 txt.offset);
307
      else
308
        Utilities.drawTabbedText(txt, bounds.x, bounds.y, g, tabEx,
309
                                 txt.offset);
310
 
311
      if (view.isStikeThrough())
312
        {
313
          int strikeHeight = (int) (getAscent(view) / 2);
314
          g.drawLine(bounds.x, bounds.y + strikeHeight, bounds.height + width,
315
                     bounds.y + strikeHeight);
316
        }
317
      if (view.isUnderline())
318
        {
319
          int lineHeight = (int) getAscent(view);
320
          g.drawLine(bounds.x, bounds.y + lineHeight, bounds.height + width,
321
                     bounds.y + lineHeight);
322
        }
323
    }
324
 
325
    /**
326
     * Maps a position in the document into the coordinate space of the View.
327
     * The output rectangle usually reflects the font height but has a width
328
     * of zero.
329
     *
330
     * @param view the glyph view
331
     * @param pos the position of the character in the model
332
     * @param a the area that is occupied by the view
333
     * @param b either {@link Position.Bias#Forward} or
334
     *        {@link Position.Bias#Backward} depending on the preferred
335
     *        direction bias. If <code>null</code> this defaults to
336
     *        <code>Position.Bias.Forward</code>
337
     *
338
     * @return a rectangle that gives the location of the document position
339
     *         inside the view coordinate space
340
     *
341
     * @throws BadLocationException if <code>pos</code> is invalid
342
     * @throws IllegalArgumentException if b is not one of the above listed
343
     *         valid values
344
     */
345
    public Shape modelToView(GlyphView view, int pos, Position.Bias b,
346
                             Shape a)
347
      throws BadLocationException
348
    {
349
      Element el = view.getElement();
350
      Font font = view.getFont();
351
      FontMetrics fm = view.getContainer().getFontMetrics(font);
352
      Segment txt = view.getText(el.getStartOffset(), pos);
353
      int width = fm.charsWidth(txt.array, txt.offset, txt.count);
354
      int height = fm.getHeight();
355
      Rectangle bounds = a.getBounds();
356
      Rectangle result = new Rectangle(bounds.x + width, bounds.y,
357
                                       bounds.x + width, height);
358
      return result;
359
    }
360
 
361
    /**
362
     * Determine the span of the glyphs from location <code>p0</code> to
363
     * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
364
     * then TABs are expanded using this <code>TabExpander</code>.
365
     * The parameter <code>x</code> is the location at which the view is
366
     * located (this is important when using TAB expansion).
367
     *
368
     * @param view the glyph view
369
     * @param p0 the starting location in the document model
370
     * @param p1 the end location in the document model
371
     * @param te the tab expander to use
372
     * @param x the location at which the view is located
373
     *
374
     * @return the span of the glyphs from location <code>p0</code> to
375
     *         location <code>p1</code>, possibly using TAB expansion
376
     */
377
    public float getSpan(GlyphView view, int p0, int p1,
378
                         TabExpander te, float x)
379
    {
380
      Element el = view.getElement();
381
      Font font = view.getFont();
382
      FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
383
      Segment txt = view.getText(p0, p1);
384
      int span = Utilities.getTabbedTextWidth(txt, fm, (int) x, te, p0);
385
      return span;
386
    }
387
 
388
    /**
389
     * Returns the ascent of the text run that is rendered by this
390
     * <code>GlyphPainter</code>.
391
     *
392
     * @param v the glyph view
393
     *
394
     * @return the ascent of the text run that is rendered by this
395
     *         <code>GlyphPainter</code>
396
     *
397
     * @see FontMetrics#getAscent()
398
     */
399
    public float getAscent(GlyphView v)
400
    {
401
      Font font = v.getFont();
402
      FontMetrics fm = v.getContainer().getFontMetrics(font);
403
      return fm.getAscent();
404
    }
405
 
406
    /**
407
     * Returns the descent of the text run that is rendered by this
408
     * <code>GlyphPainter</code>.
409
     *
410
     * @param v the glyph view
411
     *
412
     * @return the descent of the text run that is rendered by this
413
     *         <code>GlyphPainter</code>
414
     *
415
     * @see FontMetrics#getDescent()
416
     */
417
    public float getDescent(GlyphView v)
418
    {
419
      Font font = v.getFont();
420
      FontMetrics fm = v.getContainer().getFontMetrics(font);
421
      return fm.getDescent();
422
    }
423
 
424
    /**
425
     * Determines the model offset, so that the text between <code>p0</code>
426
     * and this offset fits within the span starting at <code>x</code> with
427
     * the length of <code>len</code>.
428
     *
429
     * @param v the glyph view
430
     * @param p0 the starting offset in the model
431
     * @param x the start location in the view
432
     * @param len the length of the span in the view
433
     */
434
    public int getBoundedPosition(GlyphView v, int p0, float x, float len)
435
    {
436
      TabExpander te = v.getTabExpander();
437
      Segment txt = v.getText(p0, v.getEndOffset());
438
      Font font = v.getFont();
439
      FontMetrics fm = v.getContainer().getFontMetrics(font);
440
      int pos = Utilities.getTabbedTextOffset(txt, fm, (int) x,
441
                                              (int) (x + len), te, p0, false);
442
      return pos;
443
    }
444
 
445
    /**
446
     * Maps a visual position into a document location.
447
     *
448
     * @param v the glyph view
449
     * @param x the X coordinate of the visual position
450
     * @param y the Y coordinate of the visual position
451
     * @param a the allocated region
452
     * @param biasRet filled with the bias of the model location on method exit
453
     *
454
     * @return the model location that represents the specified view location
455
     */
456
    public int viewToModel(GlyphView v, float x, float y, Shape a,
457
                           Bias[] biasRet)
458
    {
459
      Rectangle b = a.getBounds();
460
      int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
461
      return pos;
462
    }
463
  }
464
 
465
  /**
466
   * The GlyphPainer used for painting the glyphs.
467
   */
468
  GlyphPainter glyphPainter;
469
 
470
  /**
471
   * The start offset within the document for this view.
472
   */
473
  int startOffset;
474
 
475
  /**
476
   * The end offset within the document for this view.
477
   */
478
  int endOffset;
479
 
480
  /**
481
   * Creates a new <code>GlyphView</code> for the given <code>Element</code>.
482
   *
483
   * @param element the element that is rendered by this GlyphView
484
   */
485
  public GlyphView(Element element)
486
  {
487
    super(element);
488
    startOffset = element.getStartOffset();
489
    endOffset = element.getEndOffset();
490
  }
491
 
492
  /**
493
   * Returns the <code>GlyphPainter</code> that is used by this
494
   * <code>GlyphView</code>. If no <code>GlyphPainer</code> has been installed
495
   * <code>null</code> is returned.
496
   *
497
   * @return the glyph painter that is used by this
498
   *         glyph view or <code>null</code> if no glyph painter has been
499
   *         installed
500
   */
501
  public GlyphPainter getGlyphPainter()
502
  {
503
    return glyphPainter;
504
  }
505
 
506
  /**
507
   * Sets the {@link GlyphPainter} to be used for this <code>GlyphView</code>.
508
   *
509
   * @param painter the glyph painter to be used for this glyph view
510
   */
511
  public void setGlyphPainter(GlyphPainter painter)
512
  {
513
    glyphPainter = painter;
514
  }
515
 
516
  /**
517
   * Checks if a <code>GlyphPainer</code> is installed. If this is not the
518
   * case, a default painter is installed.
519
   */
520
  protected void checkPainter()
521
  {
522
    if (glyphPainter == null)
523
      glyphPainter = new DefaultGlyphPainter();
524
  }
525
 
526
  /**
527
   * Renders the <code>Element</code> that is associated with this
528
   * <code>View</code>.
529
   *
530
   * @param g the <code>Graphics</code> context to render to
531
   * @param a the allocated region for the <code>Element</code>
532
   */
533
  public void paint(Graphics g, Shape a)
534
  {
535
    Element el = getElement();
536
    checkPainter();
537
    getGlyphPainter().paint(this, g, a, el.getStartOffset(),
538
                            el.getEndOffset());
539
  }
540
 
541
 
542
  /**
543
   * Returns the preferred span of the content managed by this
544
   * <code>View</code> along the specified <code>axis</code>.
545
   *
546
   * @param axis the axis
547
   *
548
   * @return the preferred span of this <code>View</code>.
549
   */
550
  public float getPreferredSpan(int axis)
551
  {
552
    float span = 0;
553
    checkPainter();
554
    GlyphPainter painter = getGlyphPainter();
555
    if (axis == X_AXIS)
556
      {
557
        Element el = getElement();
558
        TabExpander tabEx = null;
559
        View parent = getParent();
560
        if (parent instanceof TabExpander)
561
          tabEx = (TabExpander) parent;
562
        span = painter.getSpan(this, getStartOffset(), getEndOffset(),
563
                               tabEx, 0.F);
564
      }
565
    else
566
      span = painter.getHeight(this);
567
    return span;
568
  }
569
 
570
  /**
571
   * Maps a position in the document into the coordinate space of the View.
572
   * The output rectangle usually reflects the font height but has a width
573
   * of zero.
574
   *
575
   * @param pos the position of the character in the model
576
   * @param a the area that is occupied by the view
577
   * @param b either {@link Position.Bias#Forward} or
578
   *        {@link Position.Bias#Backward} depending on the preferred
579
   *        direction bias. If <code>null</code> this defaults to
580
   *        <code>Position.Bias.Forward</code>
581
   *
582
   * @return a rectangle that gives the location of the document position
583
   *         inside the view coordinate space
584
   *
585
   * @throws BadLocationException if <code>pos</code> is invalid
586
   * @throws IllegalArgumentException if b is not one of the above listed
587
   *         valid values
588
   */
589
  public Shape modelToView(int pos, Shape a, Position.Bias b)
590
    throws BadLocationException
591
  {
592
    GlyphPainter p = getGlyphPainter();
593
    return p.modelToView(this, pos, b, a);
594
  }
595
 
596
  /**
597
   * Maps coordinates from the <code>View</code>'s space into a position
598
   * in the document model.
599
   *
600
   * @param x the x coordinate in the view space
601
   * @param y the y coordinate in the view space
602
   * @param a the allocation of this <code>View</code>
603
   * @param b the bias to use
604
   *
605
   * @return the position in the document that corresponds to the screen
606
   *         coordinates <code>x, y</code>
607
   */
608
  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
609
  {
610
    checkPainter();
611
    GlyphPainter painter = getGlyphPainter();
612
    return painter.viewToModel(this, x, y, a, b);
613
  }
614
 
615
  /**
616
   * Return the {@link TabExpander} to use.
617
   *
618
   * @return the {@link TabExpander} to use
619
   */
620
  public TabExpander getTabExpander()
621
  {
622
    TabExpander te = null;
623
    View parent = getParent();
624
 
625
    if (parent instanceof TabExpander)
626
      te = (TabExpander) parent;
627
 
628
    return te;
629
  }
630
 
631
  /**
632
   * Returns the preferred span of this view for tab expansion.
633
   *
634
   * @param x the location of the view
635
   * @param te the tab expander to use
636
   *
637
   * @return the preferred span of this view for tab expansion
638
   */
639
  public float getTabbedSpan(float x, TabExpander te)
640
  {
641
    Element el = getElement();
642
    return getGlyphPainter().getSpan(this, el.getStartOffset(),
643
                                     el.getEndOffset(), te, x);
644
  }
645
 
646
  /**
647
   * Returns the span of a portion of the view. This is used in TAB expansion
648
   * for fragments that don't contain TABs.
649
   *
650
   * @param p0 the start index
651
   * @param p1 the end index
652
   *
653
   * @return the span of the specified portion of the view
654
   */
655
  public float getPartialSpan(int p0, int p1)
656
  {
657
    Element el = getElement();
658
    Document doc = el.getDocument();
659
    Segment seg = new Segment();
660
    try
661
      {
662
        doc.getText(p0, p1 - p0, seg);
663
      }
664
    catch (BadLocationException ex)
665
      {
666
        AssertionError ae;
667
        ae = new AssertionError("BadLocationException must not be thrown "
668
                                + "here");
669
        ae.initCause(ex);
670
        throw ae;
671
      }
672
    FontMetrics fm = null; // Fetch font metrics somewhere.
673
    return Utilities.getTabbedTextWidth(seg, fm, 0, null, p0);
674
  }
675
 
676
  /**
677
   * Returns the start offset in the document model of the portion
678
   * of text that this view is responsible for.
679
   *
680
   * @return the start offset in the document model of the portion
681
   *         of text that this view is responsible for
682
   */
683
  public int getStartOffset()
684
  {
685
    return startOffset;
686
  }
687
 
688
  /**
689
   * Returns the end offset in the document model of the portion
690
   * of text that this view is responsible for.
691
   *
692
   * @return the end offset in the document model of the portion
693
   *         of text that this view is responsible for
694
   */
695
  public int getEndOffset()
696
  {
697
    return endOffset;
698
  }
699
 
700
  /**
701
   * Returns the text segment that this view is responsible for.
702
   *
703
   * @param p0 the start index in the document model
704
   * @param p1 the end index in the document model
705
   *
706
   * @return the text segment that this view is responsible for
707
   */
708
  public Segment getText(int p0, int p1)
709
  {
710
    Segment txt = new Segment();
711
    try
712
      {
713
        getDocument().getText(p0, p1 - p0, txt);
714
      }
715
    catch (BadLocationException ex)
716
      {
717
        AssertionError ae;
718
        ae = new AssertionError("BadLocationException should not be "
719
                                + "thrown here. p0 = " + p0 + ", p1 = " + p1);
720
        ae.initCause(ex);
721
        throw ae;
722
      }
723
 
724
    return txt;
725
  }
726
 
727
  /**
728
   * Returns the font for the text run for which this <code>GlyphView</code>
729
   * is responsible.
730
   *
731
   * @return the font for the text run for which this <code>GlyphView</code>
732
   *         is responsible
733
   */
734
  public Font getFont()
735
  {
736
    Element el = getElement();
737
    AttributeSet atts = el.getAttributes();
738
    String family = StyleConstants.getFontFamily(atts);
739
    int size = StyleConstants.getFontSize(atts);
740
    int style = Font.PLAIN;
741
    if (StyleConstants.isBold(atts))
742
        style |= Font.BOLD;
743
    if (StyleConstants.isItalic(atts))
744
      style |= Font.ITALIC;
745
    Font font = new Font(family, style, size);
746
    return font;
747
  }
748
 
749
  /**
750
   * Returns the foreground color which should be used to paint the text.
751
   * This is fetched from the associated element's text attributes using
752
   * {@link StyleConstants#getForeground}.
753
   *
754
   * @return the foreground color which should be used to paint the text
755
   */
756
  public Color getForeground()
757
  {
758
    Element el = getElement();
759
    AttributeSet atts = el.getAttributes();
760
    return StyleConstants.getForeground(atts);
761
  }
762
 
763
  /**
764
   * Returns the background color which should be used to paint the text.
765
   * This is fetched from the associated element's text attributes using
766
   * {@link StyleConstants#getBackground}.
767
   *
768
   * @return the background color which should be used to paint the text
769
   */
770
  public Color getBackground()
771
  {
772
    Element el = getElement();
773
    AttributeSet atts = el.getAttributes();
774
    return StyleConstants.getBackground(atts);
775
  }
776
 
777
  /**
778
   * Determines whether the text should be rendered strike-through or not. This
779
   * is determined using the method
780
   * {@link StyleConstants#isStrikeThrough(AttributeSet)} on the element of
781
   * this view.
782
   *
783
   * @return whether the text should be rendered strike-through or not
784
   */
785
  public boolean isStikeThrough()
786
  {
787
    Element el = getElement();
788
    AttributeSet atts = el.getAttributes();
789
    return StyleConstants.isStrikeThrough(atts);
790
  }
791
 
792
  /**
793
   * Determines whether the text should be rendered as subscript or not. This
794
   * is determined using the method
795
   * {@link StyleConstants#isSubscript(AttributeSet)} on the element of
796
   * this view.
797
   *
798
   * @return whether the text should be rendered as subscript or not
799
   */
800
  public boolean isSubscript()
801
  {
802
    Element el = getElement();
803
    AttributeSet atts = el.getAttributes();
804
    return StyleConstants.isSubscript(atts);
805
  }
806
 
807
  /**
808
   * Determines whether the text should be rendered as superscript or not. This
809
   * is determined using the method
810
   * {@link StyleConstants#isSuperscript(AttributeSet)} on the element of
811
   * this view.
812
   *
813
   * @return whether the text should be rendered as superscript or not
814
   */
815
  public boolean isSuperscript()
816
  {
817
    Element el = getElement();
818
    AttributeSet atts = el.getAttributes();
819
    return StyleConstants.isSuperscript(atts);
820
  }
821
 
822
  /**
823
   * Determines whether the text should be rendered as underlined or not. This
824
   * is determined using the method
825
   * {@link StyleConstants#isUnderline(AttributeSet)} on the element of
826
   * this view.
827
   *
828
   * @return whether the text should be rendered as underlined or not
829
   */
830
  public boolean isUnderline()
831
  {
832
    Element el = getElement();
833
    AttributeSet atts = el.getAttributes();
834
    return StyleConstants.isUnderline(atts);
835
  }
836
 
837
  /**
838
   * Creates and returns a shallow clone of this GlyphView. This is used by
839
   * the {@link #createFragment} and {@link #breakView} methods.
840
   *
841
   * @return a shallow clone of this GlyphView
842
   */
843
  protected final Object clone()
844
  {
845
    try
846
      {
847
        return super.clone();
848
      }
849
    catch (CloneNotSupportedException ex)
850
      {
851
        AssertionError err = new AssertionError("CloneNotSupportedException "
852
                                                + "must not be thrown here");
853
        err.initCause(ex);
854
        throw err;
855
      }
856
  }
857
 
858
  /**
859
   * Tries to break the view near the specified view span <code>len</code>.
860
   * The glyph view can only be broken in the X direction. For Y direction it
861
   * returns itself.
862
   *
863
   * @param axis the axis for breaking, may be {@link View#X_AXIS} or
864
   *        {@link View#Y_AXIS}
865
   * @param p0 the model location where the fragment should start
866
   * @param pos the view position along the axis where the fragment starts
867
   * @param len the desired length of the fragment view
868
   *
869
   * @return the fragment view, or <code>this</code> if breaking was not
870
   *         possible
871
   */
872
  public View breakView(int axis, int p0, float pos, float len)
873
  {
874
    if (axis == Y_AXIS)
875
      return this;
876
 
877
    checkPainter();
878
    GlyphPainter painter = getGlyphPainter();
879
    int breakLocation = painter.getBoundedPosition(this, p0, pos, len);
880
    // Try to find a suitable line break.
881
    BreakIterator lineBreaker = BreakIterator.getLineInstance();
882
    Segment txt = new Segment();
883
    try
884
      {
885
        getDocument().getText(getStartOffset(), getEndOffset(), txt);
886
      }
887
    catch (BadLocationException ex)
888
      {
889
        AssertionError err = new AssertionError("BadLocationException must not "
890
                                                + "be thrown here.");
891
        err.initCause(ex);
892
        throw err;
893
      }
894
    lineBreaker.setText(txt);
895
    int goodBreakLocation = lineBreaker.previous();
896
    if (goodBreakLocation != BreakIterator.DONE)
897
      breakLocation = goodBreakLocation;
898
 
899
    View brokenView = createFragment(p0, breakLocation);
900
    return brokenView;
901
  }
902
 
903
  /**
904
   * Determines how well the specified view location is suitable for inserting
905
   * a line break. If <code>axis</code> is <code>View.Y_AXIS</code>, then
906
   * this method forwards to the superclass, if <code>axis</code> is
907
   * <code>View.X_AXIS</code> then this method returns
908
   * {@link View#ExcellentBreakWeight} if there is a suitable break location
909
   * (usually whitespace) within the specified view span, or
910
   * {@link View#GoodBreakWeight} if not.
911
   *
912
   * @param axis the axis along which the break weight is requested
913
   * @param pos the starting view location
914
   * @param len the length of the span at which the view should be broken
915
   *
916
   * @return the break weight
917
   */
918
  public int getBreakWeight(int axis, float pos, float len)
919
  {
920
    int weight;
921
    if (axis == Y_AXIS)
922
      weight = super.getBreakWeight(axis, pos, len);
923
    else
924
      {
925
        // Determine the model locations at pos and pos + len.
926
        int spanX = (int) getPreferredSpan(X_AXIS);
927
        int spanY = (int) getPreferredSpan(Y_AXIS);
928
        Rectangle dummyAlloc = new Rectangle(0, 0, spanX, spanY);
929
        Position.Bias[] biasRet = new Position.Bias[1];
930
        int offset1 = viewToModel(pos, spanY / 2, dummyAlloc, biasRet);
931
        int offset2 = viewToModel(pos, spanY / 2, dummyAlloc, biasRet);
932
        Segment txt = getText(offset1, offset2);
933
        BreakIterator lineBreaker = BreakIterator.getLineInstance();
934
        lineBreaker.setText(txt);
935
        int breakLoc = lineBreaker.previous();
936
        if (breakLoc == offset1)
937
          weight = View.BadBreakWeight;
938
        else if(breakLoc ==  BreakIterator.DONE)
939
          weight = View.GoodBreakWeight;
940
        else
941
          weight = View.ExcellentBreakWeight;
942
      }
943
    return weight;
944
  }
945
 
946
  /**
947
   * Receives notification that some text attributes have changed within the
948
   * text fragment that this view is responsible for. This calls
949
   * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
950
   * both width and height.
951
   *
952
   * @param e the document event describing the change; not used here
953
   * @param a the view allocation on screen; not used here
954
   * @param vf the view factory; not used here
955
   */
956
  public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
957
  {
958
    getParent().preferenceChanged(this, true, true);
959
  }
960
 
961
  /**
962
   * Receives notification that some text has been inserted within the
963
   * text fragment that this view is responsible for. This calls
964
   * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
965
   * width.
966
   *
967
   * @param e the document event describing the change; not used here
968
   * @param a the view allocation on screen; not used here
969
   * @param vf the view factory; not used here
970
   */
971
  public void insertUpdate(DocumentEvent e, Shape a, ViewFactory vf)
972
  {
973
    getParent().preferenceChanged(this, true, false);
974
  }
975
 
976
  /**
977
   * Receives notification that some text has been removed within the
978
   * text fragment that this view is responsible for. This calls
979
   * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
980
   * width.
981
   *
982
   * @param e the document event describing the change; not used here
983
   * @param a the view allocation on screen; not used here
984
   * @param vf the view factory; not used here
985
   */
986
  public void removeUpdate(DocumentEvent e, Shape a, ViewFactory vf)
987
  {
988
    getParent().preferenceChanged(this, true, false);
989
  }
990
 
991
  /**
992
   * Creates a fragment view of this view that starts at <code>p0</code> and
993
   * ends at <code>p1</code>.
994
   *
995
   * @param p0 the start location for the fragment view
996
   * @param p1 the end location for the fragment view
997
   *
998
   * @return the fragment view
999
   */
1000
  public View createFragment(int p0, int p1)
1001
  {
1002
    GlyphView fragment = (GlyphView) clone();
1003
    fragment.startOffset = p0;
1004
    fragment.endOffset = p1;
1005
    return fragment;
1006
  }
1007
 
1008
  /**
1009
   * Returns the alignment of this view along the specified axis. For the Y
1010
   * axis this is <code>(height - descent) / height</code> for the used font,
1011
   * so that it is aligned along the baseline.
1012
   * For the X axis the superclass is called.
1013
   */
1014
  public float getAlignment(int axis)
1015
  {
1016
    float align;
1017
    if (axis == Y_AXIS)
1018
      {
1019
        checkPainter();
1020
        GlyphPainter painter = getGlyphPainter();
1021
        float height = painter.getHeight(this);
1022
        float descent = painter.getDescent(this);
1023
        align = (height - descent) / height;
1024
      }
1025
    else
1026
      align = super.getAlignment(axis);
1027
 
1028
    return align;
1029
  }
1030
 
1031
  /**
1032
   * Returns the model location that should be used to place a caret when
1033
   * moving the caret through the document.
1034
   *
1035
   * @param pos the current model location
1036
   * @param bias the bias for <code>p</code>
1037
   * @param a the allocated region for the glyph view
1038
   * @param direction the direction from the current position; Must be one of
1039
   *        {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
1040
   *        {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
1041
   * @param biasRet filled with the bias of the resulting location when method
1042
   *        returns
1043
   *
1044
   * @return the location within the document that should be used to place the
1045
   *         caret when moving the caret around the document
1046
   *
1047
   * @throws BadLocationException if <code>pos</code> is an invalid model
1048
   *         location
1049
   * @throws IllegalArgumentException if <code>d</code> is invalid
1050
   */
1051
  public int getNextVisualPositionFrom(int pos, Position.Bias bias, Shape a,
1052
                                       int direction, Position.Bias[] biasRet)
1053
    throws BadLocationException
1054
  {
1055
    checkPainter();
1056
    GlyphPainter painter = getGlyphPainter();
1057
    return painter.getNextVisualPositionFrom(this, pos, bias, a, direction,
1058
                                             biasRet);
1059
  }
1060
 
1061
  /**
1062
   * Returns the document position that is (visually) nearest to the given
1063
   * document position <code>pos</code> in the given direction <code>d</code>.
1064
   *
1065
   * @param c the text component
1066
   * @param pos the document position
1067
   * @param b the bias for <code>pos</code>
1068
   * @param d the direction, must be either {@link SwingConstants#NORTH},
1069
   *        {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
1070
   *        {@link SwingConstants#EAST}
1071
   * @param biasRet an array of {@link Position.Bias} that can hold at least
1072
   *        one element, which is filled with the bias of the return position
1073
   *        on method exit
1074
   *
1075
   * @return the document position that is (visually) nearest to the given
1076
   *         document position <code>pos</code> in the given direction
1077
   *         <code>d</code>
1078
   *
1079
   * @throws BadLocationException if <code>pos</code> is not a valid offset in
1080
   *         the document model
1081
   */
1082
  public int getNextVisualPositionFrom(JTextComponent c, int pos,
1083
                                       Position.Bias b, int d,
1084
                                       Position.Bias[] biasRet)
1085
    throws BadLocationException
1086
  {
1087
    // TODO: Implement this properly.
1088
    throw new AssertionError("Not implemented yet.");
1089
  }
1090
}

powered by: WebSVN 2.1.0

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