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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* PlainView.java --
2
   Copyright (C) 2004, 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.Component;
43
import java.awt.Font;
44
import java.awt.FontMetrics;
45
import java.awt.Graphics;
46
import java.awt.Rectangle;
47
import java.awt.Shape;
48
 
49
import javax.swing.SwingConstants;
50
import javax.swing.event.DocumentEvent;
51
import javax.swing.event.DocumentEvent.ElementChange;
52
 
53
public class PlainView extends View implements TabExpander
54
{
55
  Color selectedColor;
56
  Color unselectedColor;
57
 
58
  /**
59
   * The color that is used to draw disabled text fields.
60
   */
61
  Color disabledColor;
62
 
63
  Font font;
64
 
65
  /** The length of the longest line in the Document **/
66
  float maxLineLength = -1;
67
 
68
  /** The longest line in the Document **/
69
  Element longestLine = null;
70
 
71
  protected FontMetrics metrics;
72
 
73
  /**
74
   * The instance returned by {@link #getLineBuffer()}.
75
   */
76
  private transient Segment lineBuffer;
77
 
78
  public PlainView(Element elem)
79
  {
80
    super(elem);
81
  }
82
 
83
  /**
84
   * @since 1.4
85
   */
86
  protected void updateMetrics()
87
  {
88
    Component component = getContainer();
89
    Font font = component.getFont();
90
 
91
    if (this.font != font)
92
      {
93
        this.font = font;
94
        metrics = component.getFontMetrics(font);
95
      }
96
  }
97
 
98
  /**
99
   * @since 1.4
100
   */
101
  protected Rectangle lineToRect(Shape a, int line)
102
  {
103
    // Ensure metrics are up-to-date.
104
    updateMetrics();
105
 
106
    Rectangle rect = a.getBounds();
107
    int fontHeight = metrics.getHeight();
108
    return new Rectangle(rect.x, rect.y + (line * fontHeight),
109
                         rect.width, fontHeight);
110
  }
111
 
112
  public Shape modelToView(int position, Shape a, Position.Bias b)
113
    throws BadLocationException
114
  {
115
    // Ensure metrics are up-to-date.
116
    updateMetrics();
117
 
118
    Document document = getDocument();
119
 
120
    // Get rectangle of the line containing position.
121
    int lineIndex = getElement().getElementIndex(position);
122
    Rectangle rect = lineToRect(a, lineIndex);
123
 
124
    // Get the rectangle for position.
125
    Element line = getElement().getElement(lineIndex);
126
    int lineStart = line.getStartOffset();
127
    Segment segment = getLineBuffer();
128
    document.getText(lineStart, position - lineStart, segment);
129
    int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
130
                                               this, lineStart);
131
 
132
    // Calc the real rectangle.
133
    rect.x += xoffset;
134
    rect.width = 1;
135
    rect.height = metrics.getHeight();
136
 
137
    return rect;
138
  }
139
 
140
  protected void drawLine(int lineIndex, Graphics g, int x, int y)
141
  {
142
    try
143
      {
144
        metrics = g.getFontMetrics();
145
        // FIXME: Selected text are not drawn yet.
146
        Element line = getElement().getElement(lineIndex);
147
        drawUnselectedText(g, x, y, line.getStartOffset(), line.getEndOffset());
148
        //drawSelectedText(g, , , , );
149
      }
150
    catch (BadLocationException e)
151
      {
152
        AssertionError ae = new AssertionError("Unexpected bad location");
153
        ae.initCause(e);
154
        throw ae;
155
      }
156
  }
157
 
158
  protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
159
    throws BadLocationException
160
  {
161
    g.setColor(selectedColor);
162
    Segment segment = getLineBuffer();
163
    getDocument().getText(p0, p1 - p0, segment);
164
    return Utilities.drawTabbedText(segment, x, y, g, this, 0);
165
  }
166
 
167
  protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
168
    throws BadLocationException
169
  {
170
    JTextComponent textComponent = (JTextComponent) getContainer();
171
    if (textComponent.isEnabled())
172
      g.setColor(unselectedColor);
173
    else
174
      g.setColor(disabledColor);
175
 
176
    Segment segment = getLineBuffer();
177
    getDocument().getText(p0, p1 - p0, segment);
178
    return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
179
  }
180
 
181
  public void paint(Graphics g, Shape s)
182
  {
183
    // Ensure metrics are up-to-date.
184
    updateMetrics();
185
 
186
    JTextComponent textComponent = (JTextComponent) getContainer();
187
 
188
    g.setFont(textComponent.getFont());
189
    selectedColor = textComponent.getSelectedTextColor();
190
    unselectedColor = textComponent.getForeground();
191
    disabledColor = textComponent.getDisabledTextColor();
192
 
193
    Rectangle rect = s.getBounds();
194
 
195
    // FIXME: Text may be scrolled.
196
    Document document = textComponent.getDocument();
197
    Element root = document.getDefaultRootElement();
198
    int y = rect.y;
199
 
200
    for (int i = 0; i < root.getElementCount(); i++)
201
      {
202
        drawLine(i, g, rect.x, y);
203
        y += metrics.getHeight();
204
      }
205
  }
206
 
207
  /**
208
   * Returns the tab size of a tab.  Checks the Document's
209
   * properties for PlainDocument.tabSizeAttribute and returns it if it is
210
   * defined, otherwise returns 8.
211
   *
212
   * @return the tab size.
213
   */
214
  protected int getTabSize()
215
  {
216
    Object tabSize = getDocument().getProperty(PlainDocument.tabSizeAttribute);
217
    if (tabSize == null)
218
      return 8;
219
    return ((Integer)tabSize).intValue();
220
  }
221
 
222
  /**
223
   * Returns the next tab stop position after a given reference position.
224
   *
225
   * This implementation ignores the <code>tabStop</code> argument.
226
   *
227
   * @param x the current x position in pixels
228
   * @param tabStop the position within the text stream that the tab occured at
229
   */
230
  public float nextTabStop(float x, int tabStop)
231
  {
232
    float tabSizePixels = getTabSize() * metrics.charWidth('m');
233
    return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
234
  }
235
 
236
  /**
237
   * Returns the length of the longest line, used for getting the span
238
   * @return the length of the longest line
239
   */
240
  float determineMaxLineLength()
241
  {
242
    // if the longest line is cached, return the cached value
243
    if (maxLineLength != -1)
244
      return maxLineLength;
245
 
246
    // otherwise we have to go through all the lines and find it
247
    Element el = getElement();
248
    Segment seg = getLineBuffer();
249
    float span = 0;
250
    for (int i = 0; i < el.getElementCount(); i++)
251
      {
252
        Element child = el.getElement(i);
253
        int start = child.getStartOffset();
254
        int end = child.getEndOffset();
255
        try
256
          {
257
            el.getDocument().getText(start, end - start, seg);
258
          }
259
        catch (BadLocationException ex)
260
          {
261
            AssertionError ae = new AssertionError("Unexpected bad location");
262
            ae.initCause(ex);
263
            throw ae;
264
          }
265
 
266
        if (seg == null || seg.array == null || seg.count == 0)
267
          continue;
268
 
269
        int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
270
        if (width > span)
271
          {
272
            longestLine = child;
273
            span = width;
274
          }
275
      }
276
    maxLineLength = span;
277
    return maxLineLength;
278
  }
279
 
280
  public float getPreferredSpan(int axis)
281
  {
282
    if (axis != X_AXIS && axis != Y_AXIS)
283
      throw new IllegalArgumentException();
284
 
285
    // make sure we have the metrics
286
    updateMetrics();
287
 
288
    float span = 0;
289
    Element el = getElement();
290
 
291
    switch (axis)
292
      {
293
      case X_AXIS:
294
        span = determineMaxLineLength();
295
      case Y_AXIS:
296
      default:
297
        span = metrics.getHeight() * el.getElementCount();
298
        break;
299
      }
300
    return span;
301
  }
302
 
303
  /**
304
   * Maps coordinates from the <code>View</code>'s space into a position
305
   * in the document model.
306
   *
307
   * @param x the x coordinate in the view space
308
   * @param y the y coordinate in the view space
309
   * @param a the allocation of this <code>View</code>
310
   * @param b the bias to use
311
   *
312
   * @return the position in the document that corresponds to the screen
313
   *         coordinates <code>x, y</code>
314
   */
315
  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
316
  {
317
    Rectangle rec = a.getBounds();
318
    Document doc = getDocument();
319
    Element root = doc.getDefaultRootElement();
320
 
321
    // PlainView doesn't support line-wrapping so we can find out which
322
    // Element was clicked on just by the y-position    
323
    int lineClicked = (int) (y - rec.y) / metrics.getHeight();
324
    if (lineClicked >= root.getElementCount())
325
      return getEndOffset() - 1;
326
 
327
    Element line = root.getElement(lineClicked);
328
    Segment s = getLineBuffer();
329
    int start = line.getStartOffset();
330
    // We don't want the \n at the end of the line.
331
    int end = line.getEndOffset() - 1;
332
    try
333
      {
334
        doc.getText(start, end - start, s);
335
      }
336
    catch (BadLocationException ble)
337
      {
338
        AssertionError ae = new AssertionError("Unexpected bad location");
339
        ae.initCause(ble);
340
        throw ae;
341
      }
342
 
343
    int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start);
344
    return Math.max (0, pos);
345
  }
346
 
347
  /**
348
   * Since insertUpdate and removeUpdate each deal with children
349
   * Elements being both added and removed, they both have to perform
350
   * the same checks.  So they both simply call this method.
351
   * @param changes the DocumentEvent for the changes to the Document.
352
   * @param a the allocation of the View.
353
   * @param f the ViewFactory to use for rebuilding.
354
   */
355
  protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f)
356
  {
357
    Element el = getElement();
358
    ElementChange ec = changes.getChange(el);
359
 
360
    // If ec is null then no lines were added or removed, just 
361
    // repaint the changed line
362
    if (ec == null)
363
      {
364
        int line = getElement().getElementIndex(changes.getOffset());
365
        damageLineRange(line, line, a, getContainer());
366
        return;
367
      }
368
 
369
    Element[] removed = ec.getChildrenRemoved();
370
    Element[] newElements = ec.getChildrenAdded();
371
 
372
    // If no Elements were added or removed, we just want to repaint
373
    // the area containing the line that was modified
374
    if (removed == null && newElements == null)
375
      {
376
        int line = getElement().getElementIndex(changes.getOffset());
377
        damageLineRange(line, line, a, getContainer());
378
        return;
379
      }
380
 
381
    // Check to see if we removed the longest line, if so we have to
382
    // search through all lines and find the longest one again
383
    if (removed != null)
384
      {
385
        for (int i = 0; i < removed.length; i++)
386
          if (removed[i].equals(longestLine))
387
            {
388
              // reset maxLineLength and search through all lines for longest one
389
              maxLineLength = -1;
390
              determineMaxLineLength();
391
              ((JTextComponent)getContainer()).repaint();
392
              return;
393
            }
394
      }
395
 
396
    // If we've reached here, that means we haven't removed the longest line
397
    if (newElements == null)
398
      {
399
        // No lines were added, just repaint the container and exit
400
        ((JTextComponent)getContainer()).repaint();
401
        return;
402
      }
403
 
404
    //  Make sure we have the metrics
405
    updateMetrics();
406
 
407
    // If we've reached here, that means we haven't removed the longest line
408
    // and we have added at least one line, so we have to check if added lines
409
    // are longer than the previous longest line        
410
    Segment seg = getLineBuffer();
411
    float longestNewLength = 0;
412
    Element longestNewLine = null;
413
 
414
    // Loop through the added lines to check their length
415
    for (int i = 0; i < newElements.length; i++)
416
      {
417
        Element child = newElements[i];
418
        int start = child.getStartOffset();
419
        int end = child.getEndOffset();
420
        try
421
          {
422
            el.getDocument().getText(start, end - start, seg);
423
          }
424
        catch (BadLocationException ex)
425
          {
426
            AssertionError ae = new AssertionError("Unexpected bad location");
427
            ae.initCause(ex);
428
            throw ae;
429
          }
430
 
431
        if (seg == null || seg.array == null || seg.count == 0)
432
          continue;
433
 
434
        int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
435
        if (width > longestNewLength)
436
          {
437
            longestNewLine = child;
438
            longestNewLength = width;
439
          }
440
      }
441
 
442
    // Check if the longest of the new lines is longer than our previous
443
    // longest line, and if so update our values
444
    if (longestNewLength > maxLineLength)
445
      {
446
        maxLineLength = longestNewLength;
447
        longestLine = longestNewLine;
448
      }
449
    // Repaint the container
450
    ((JTextComponent)getContainer()).repaint();
451
  }
452
 
453
  /**
454
   * This method is called when something is inserted into the Document
455
   * that this View is displaying.
456
   *
457
   * @param changes the DocumentEvent for the changes.
458
   * @param a the allocation of the View
459
   * @param f the ViewFactory used to rebuild
460
   */
461
  public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f)
462
  {
463
    updateDamage(changes, a, f);
464
  }
465
 
466
  /**
467
   * This method is called when something is removed from the Document
468
   * that this View is displaying.
469
   *
470
   * @param changes the DocumentEvent for the changes.
471
   * @param a the allocation of the View
472
   * @param f the ViewFactory used to rebuild
473
   */
474
  public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f)
475
  {
476
    updateDamage(changes, a, f);
477
  }
478
 
479
  /**
480
   * This method is called when attributes were changed in the
481
   * Document in a location that this view is responsible for.
482
   */
483
  public void changedUpdate (DocumentEvent changes, Shape a, ViewFactory f)
484
  {
485
    updateDamage(changes, a, f);
486
  }
487
 
488
  /**
489
   * Repaint the given line range.  This is called from insertUpdate,
490
   * changedUpdate, and removeUpdate when no new lines were added
491
   * and no lines were removed, to repaint the line that was
492
   * modified.
493
   *
494
   * @param line0 the start of the range
495
   * @param line1 the end of the range
496
   * @param a the rendering region of the host
497
   * @param host the Component that uses this View (used to call repaint
498
   * on that Component)
499
   *
500
   * @since 1.4
501
   */
502
  protected void damageLineRange (int line0, int line1, Shape a, Component host)
503
  {
504
    if (a == null)
505
      return;
506
 
507
    Rectangle rec0 = lineToRect(a, line0);
508
    Rectangle rec1 = lineToRect(a, line1);
509
 
510
    if (rec0 == null || rec1 == null)
511
      // something went wrong, repaint the entire host to be safe
512
      host.repaint();
513
    else
514
      {
515
        Rectangle repaintRec = rec0.union(rec1);
516
        host.repaint();
517
      }
518
  }
519
 
520
  /**
521
   * Provides a {@link Segment} object, that can be used to fetch text from
522
   * the document.
523
   *
524
   * @returna {@link Segment} object, that can be used to fetch text from
525
   *          the document
526
   */
527
  protected Segment getLineBuffer()
528
  {
529
    if (lineBuffer == null)
530
      lineBuffer = new Segment();
531
    return lineBuffer;
532
  }
533
 
534
  /**
535
   * Returns the document position that is (visually) nearest to the given
536
   * document position <code>pos</code> in the given direction <code>d</code>.
537
   *
538
   * @param c the text component
539
   * @param pos the document position
540
   * @param b the bias for <code>pos</code>
541
   * @param d the direction, must be either {@link SwingConstants#NORTH},
542
   *        {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
543
   *        {@link SwingConstants#EAST}
544
   * @param biasRet an array of {@link Position.Bias} that can hold at least
545
   *        one element, which is filled with the bias of the return position
546
   *        on method exit
547
   *
548
   * @return the document position that is (visually) nearest to the given
549
   *         document position <code>pos</code> in the given direction
550
   *         <code>d</code>
551
   *
552
   * @throws BadLocationException if <code>pos</code> is not a valid offset in
553
   *         the document model
554
   */
555
  public int getNextVisualPositionFrom(JTextComponent c, int pos,
556
                                       Position.Bias b, int d,
557
                                       Position.Bias[] biasRet)
558
    throws BadLocationException
559
  {
560
    // TODO: Implement this properly.
561
    throw new AssertionError("Not implemented yet.");
562
  }
563
}
564
 

powered by: WebSVN 2.1.0

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