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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* DefaultCaret.java --
2
   Copyright (C) 2002, 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
package javax.swing.text;
39
 
40
import java.awt.Graphics;
41
import java.awt.Point;
42
import java.awt.Rectangle;
43
import java.awt.event.ActionEvent;
44
import java.awt.event.ActionListener;
45
import java.awt.event.FocusEvent;
46
import java.awt.event.FocusListener;
47
import java.awt.event.MouseEvent;
48
import java.awt.event.MouseListener;
49
import java.awt.event.MouseMotionListener;
50
import java.beans.PropertyChangeEvent;
51
import java.beans.PropertyChangeListener;
52
import java.util.EventListener;
53
 
54
import javax.swing.JComponent;
55
import javax.swing.SwingUtilities;
56
import javax.swing.Timer;
57
import javax.swing.event.ChangeEvent;
58
import javax.swing.event.ChangeListener;
59
import javax.swing.event.DocumentEvent;
60
import javax.swing.event.DocumentListener;
61
import javax.swing.event.EventListenerList;
62
 
63
/**
64
 * The default implementation of the {@link Caret} interface.
65
 *
66
 * @author orgininal author unknown
67
 * @author Roman Kennke (roman@kennke.org)
68
 */
69
public class DefaultCaret extends Rectangle
70
  implements Caret, FocusListener, MouseListener, MouseMotionListener
71
{
72
 
73
  /**
74
   * Controls the blinking of the caret.
75
   *
76
   * @author Roman Kennke (kennke@aicas.com)
77
   * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
78
   */
79
  private class BlinkTimerListener implements ActionListener
80
  {
81
    /**
82
     * Forces the next event to be ignored. The next event should be ignored
83
     * if we force the caret to appear. We do not know how long will it take
84
     * to fire the comming event; this may be near immediately. Better to leave
85
     * the caret visible one iteration longer.
86
     */
87
    boolean ignoreNextEvent;
88
 
89
    /**
90
     * Receives notification when the blink timer fires and updates the visible
91
     * state of the caret.
92
     *
93
     * @param event the action event
94
     */
95
    public void actionPerformed(ActionEvent event)
96
    {
97
      if (ignoreNextEvent)
98
        ignoreNextEvent = false;
99
      else
100
        {
101
          visible = !visible;
102
          repaint();
103
        }
104
    }
105
  }
106
 
107
  /**
108
   * Listens for changes in the text component's document and updates the
109
   * caret accordingly.
110
   *
111
   * @author Roman Kennke (kennke@aicas.com)
112
   */
113
  private class DocumentHandler implements DocumentListener
114
  {
115
    /**
116
     * Receives notification that some text attributes have changed. No action
117
     * is taken here.
118
     *
119
     * @param event the document event
120
     */
121
    public void changedUpdate(DocumentEvent event)
122
    {
123
      // Nothing to do here.
124
    }
125
 
126
    /**
127
     * Receives notification that some text has been inserted from the text
128
     * component. The caret is moved forward accordingly.
129
     *
130
     * @param event the document event
131
     */
132
    public void insertUpdate(DocumentEvent event)
133
    {
134
      if (policy == ALWAYS_UPDATE ||
135
          (SwingUtilities.isEventDispatchThread() &&
136
           policy == UPDATE_WHEN_ON_EDT))
137
        {
138
          int dot = getDot();
139
          setDot(dot + event.getLength());
140
        }
141
    }
142
 
143
    /**
144
     * Receives notification that some text has been removed into the text
145
     * component. The caret is moved backwards accordingly.
146
     *
147
     * @param event the document event
148
     */
149
    public void removeUpdate(DocumentEvent event)
150
    {
151
      if (policy == ALWAYS_UPDATE ||
152
          (SwingUtilities.isEventDispatchThread() &&
153
           policy == UPDATE_WHEN_ON_EDT))
154
        {
155
          int dot = getDot();
156
          setDot(dot - event.getLength());
157
        }
158
      else if (policy == NEVER_UPDATE)
159
        {
160
          int docLength = event.getDocument().getLength();
161
          if (getDot() > docLength)
162
            setDot(docLength);
163
        }
164
    }
165
  }
166
 
167
  /**
168
   * Listens for property changes on the text document. This is used to add and
169
   * remove our document listener, if the document of the text component has
170
   * changed.
171
   *
172
   * @author Roman Kennke (kennke@aicas.com)
173
   */
174
  private class PropertyChangeHandler implements PropertyChangeListener
175
  {
176
 
177
    /**
178
     * Receives notification when a property has changed on the text component.
179
     * This adds/removes our document listener from the text component's
180
     * document when the document changes.
181
     *
182
     * @param e the property change event
183
     */
184
    public void propertyChange(PropertyChangeEvent e)
185
    {
186
      if (e.getPropertyName().equals("document"))
187
        {
188
          Document oldDoc = (Document) e.getOldValue();
189
          oldDoc.removeDocumentListener(documentListener);
190
          Document newDoc = (Document) e.getNewValue();
191
          newDoc.addDocumentListener(documentListener);
192
        }
193
    }
194
 
195
  }
196
 
197
  /** The serialization UID (compatible with JDK1.5). */
198
  private static final long serialVersionUID = 4325555698756477346L;
199
 
200
  /**
201
   * Indicates the Caret position should always be updated after Document
202
   * changes even if the updates are not performed on the Event Dispatching
203
   * thread.
204
   *
205
   * @since 1.5
206
   */
207
  public static final int ALWAYS_UPDATE = 2;
208
 
209
  /**
210
   * Indicates the Caret position should not be changed unless the Document
211
   * length becomes less than the Caret position, in which case the Caret
212
   * is moved to the end of the Document.
213
   *
214
   * @since 1.5
215
   */
216
  public static final int NEVER_UPDATE = 1;
217
 
218
  /**
219
   * Indicates the Caret position should be updated only if Document changes
220
   * are made on the Event Dispatcher thread.
221
   *
222
   * @since 1.5
223
   */
224
  public static final int UPDATE_WHEN_ON_EDT = 0;
225
 
226
  /** Keeps track of the current update policy **/
227
  int policy = UPDATE_WHEN_ON_EDT;
228
 
229
  /**
230
   * The <code>ChangeEvent</code> that is fired by {@link #fireStateChanged()}.
231
   */
232
  protected ChangeEvent changeEvent = new ChangeEvent(this);
233
 
234
  /**
235
   * Stores all registered event listeners.
236
   */
237
  protected EventListenerList listenerList = new EventListenerList();
238
 
239
  /**
240
   * Our document listener.
241
   */
242
  DocumentListener documentListener;
243
 
244
  /**
245
   * Our property listener.
246
   */
247
  PropertyChangeListener propertyChangeListener;
248
 
249
  /**
250
   * The text component in which this caret is installed.
251
   */
252
  private JTextComponent textComponent;
253
 
254
  /**
255
   * Indicates if the selection should be visible or not.
256
   */
257
  private boolean selectionVisible = true;
258
 
259
  /**
260
   * The blink rate of this <code>Caret</code>.
261
   */
262
  private int blinkRate = 500;
263
 
264
  /**
265
   * The current dot position.
266
   */
267
  private int dot = 0;
268
 
269
  /**
270
   * The current mark position.
271
   */
272
  private int mark = 0;
273
 
274
  /**
275
   * The current visual caret position.
276
   */
277
  private Point magicCaretPosition = null;
278
 
279
  /**
280
   * Indicates if this <code>Caret</code> is currently visible or not. This is
281
   * package private to avoid an accessor method.
282
   */
283
  boolean visible = false;
284
 
285
  /**
286
   * The current highlight entry.
287
   */
288
  private Object highlightEntry;
289
 
290
  private Timer blinkTimer;
291
 
292
  private BlinkTimerListener blinkListener;
293
 
294
  /**
295
   * Creates a new <code>DefaultCaret</code> instance.
296
   */
297
  public DefaultCaret()
298
  {
299
    // Nothing to do here.
300
  }
301
 
302
  /**
303
   * Sets the Caret update policy.
304
   *
305
   * @param policy the new policy.  Valid values are:
306
   * ALWAYS_UPDATE: always update the Caret position, even when Document
307
   * updates don't occur on the Event Dispatcher thread.
308
   * NEVER_UPDATE: don't update the Caret position unless the Document
309
   * length becomes less than the Caret position (then update the
310
   * Caret to the end of the Document).
311
   * UPDATE_WHEN_ON_EDT: update the Caret position when the
312
   * Document updates occur on the Event Dispatcher thread.  This is the
313
   * default.
314
   *
315
   * @since 1.5
316
   * @throws IllegalArgumentException if policy is not one of the above.
317
   */
318
  public void setUpdatePolicy (int policy)
319
  {
320
    if (policy != ALWAYS_UPDATE && policy != NEVER_UPDATE
321
        && policy != UPDATE_WHEN_ON_EDT)
322
      throw new
323
        IllegalArgumentException
324
        ("policy must be ALWAYS_UPDATE, NEVER__UPDATE, or UPDATE_WHEN_ON_EDT");
325
    this.policy = policy;
326
  }
327
 
328
  /**
329
   * Gets the caret update policy.
330
   *
331
   * @return the caret update policy.
332
   * @since 1.5
333
   */
334
  public int getUpdatePolicy ()
335
  {
336
    return policy;
337
  }
338
 
339
  /**
340
   * Moves the caret position when the mouse is dragged over the text
341
   * component, modifying the selection accordingly.
342
   *
343
   * @param event the <code>MouseEvent</code> describing the drag operation
344
   */
345
  public void mouseDragged(MouseEvent event)
346
  {
347
    moveCaret(event);
348
  }
349
 
350
  /**
351
   * Indicates a mouse movement over the text component. Does nothing here.
352
   *
353
   * @param event the <code>MouseEvent</code> describing the mouse operation
354
   */
355
  public void mouseMoved(MouseEvent event)
356
  {
357
    // Nothing to do here.
358
  }
359
 
360
  /**
361
   * When the click is received from Button 1 then the following actions
362
   * are performed here:
363
   *
364
   * <ul>
365
   * <li>If we receive a double click, the caret position (dot) is set
366
   *   to the position associated to the mouse click and the word at
367
   *   this location is selected.</li>
368
   * <li>If we receive a triple click, the caret position (dot) is set
369
   *   to the position associated to the mouse click and the line at
370
   *   this location is selected.</li>
371
   * </ul>
372
   *
373
   * @param event the <code>MouseEvent</code> describing the click operation
374
   */
375
  public void mouseClicked(MouseEvent event)
376
  {
377
    // TODO: Implement double- and triple-click behaviour here.
378
  }
379
 
380
  /**
381
   * Indicates that the mouse has entered the text component. Nothing is done
382
   * here.
383
   *
384
   * @param event the <code>MouseEvent</code> describing the mouse operation
385
   */
386
  public void mouseEntered(MouseEvent event)
387
  {
388
    // Nothing to do here.
389
  }
390
 
391
  /**
392
   * Indicates that the mouse has exited the text component. Nothing is done
393
   * here.
394
   *
395
   * @param event the <code>MouseEvent</code> describing the mouse operation
396
   */
397
  public void mouseExited(MouseEvent event)
398
  {
399
    // Nothing to do here.
400
  }
401
 
402
  /**
403
   * If the button 1 is pressed, the caret position is updated to the
404
   * position of the mouse click and the text component requests the input
405
   * focus if it is enabled. If the SHIFT key is held down, the caret will
406
   * be moved, which might select the text between the old and new location.
407
   *
408
   * @param event the <code>MouseEvent</code> describing the press operation
409
   */
410
  public void mousePressed(MouseEvent event)
411
  {
412
    positionCaret(event);
413
  }
414
 
415
  /**
416
   * Indicates that a mouse button has been released on the text component.
417
   * Nothing is done here.
418
   *
419
   * @param event the <code>MouseEvent</code> describing the mouse operation
420
   */
421
  public void mouseReleased(MouseEvent event)
422
  {
423
    // Nothing to do here.
424
  }
425
 
426
  /**
427
   * Sets the caret to <code>visible</code> if the text component is editable.
428
   *
429
   * @param event the <code>FocusEvent</code>
430
   */
431
  public void focusGained(FocusEvent event)
432
  {
433
    setVisible(true);
434
  }
435
 
436
  /**
437
   * Sets the caret to <code>invisible</code>.
438
   *
439
   * @param event the <code>FocusEvent</code>
440
   */
441
  public void focusLost(FocusEvent event)
442
  {
443
    if (event.isTemporary() == false)
444
      setVisible(false);
445
  }
446
 
447
  /**
448
   * Moves the caret to the position specified in the <code>MouseEvent</code>.
449
   * This will cause a selection if the dot and mark are different.
450
   *
451
   * @param event the <code>MouseEvent</code> from which to fetch the position
452
   */
453
  protected void moveCaret(MouseEvent event)
454
  {
455
    int newDot = getComponent().viewToModel(event.getPoint());
456
    moveDot(newDot);
457
  }
458
 
459
  /**
460
   * Repositions the caret to the position specified in the
461
   * <code>MouseEvent</code>.
462
   *
463
   * @param event the <code>MouseEvent</code> from which to fetch the position
464
   */
465
  protected void positionCaret(MouseEvent event)
466
  {
467
    int newDot = getComponent().viewToModel(event.getPoint());
468
    setDot(newDot);
469
  }
470
 
471
  /**
472
   * Deinstalls this <code>Caret</code> from the specified
473
   * <code>JTextComponent</code>. This removes any listeners that have been
474
   * registered by this <code>Caret</code>.
475
   *
476
   * @param c the text component from which to install this caret
477
   */
478
  public void deinstall(JTextComponent c)
479
  {
480
    textComponent.removeFocusListener(this);
481
    textComponent.removeMouseListener(this);
482
    textComponent.removeMouseMotionListener(this);
483
    textComponent.getDocument().removeDocumentListener(documentListener);
484
    documentListener = null;
485
    textComponent.removePropertyChangeListener(propertyChangeListener);
486
    propertyChangeListener = null;
487
    textComponent = null;
488
 
489
    // Deinstall blink timer if present.
490
    if (blinkTimer != null)
491
      blinkTimer.stop();
492
    blinkTimer = null;
493
  }
494
 
495
  /**
496
   * Installs this <code>Caret</code> on the specified
497
   * <code>JTextComponent</code>. This registers a couple of listeners
498
   * on the text component.
499
   *
500
   * @param c the text component on which to install this caret
501
   */
502
  public void install(JTextComponent c)
503
  {
504
    textComponent = c;
505
    textComponent.addFocusListener(this);
506
    textComponent.addMouseListener(this);
507
    textComponent.addMouseMotionListener(this);
508
    propertyChangeListener = new PropertyChangeHandler();
509
    textComponent.addPropertyChangeListener(propertyChangeListener);
510
    documentListener = new DocumentHandler();
511
    textComponent.getDocument().addDocumentListener(documentListener);
512
 
513
    repaint();
514
  }
515
 
516
  /**
517
   * Sets the current visual position of this <code>Caret</code>.
518
   *
519
   * @param p the Point to use for the saved location. May be <code>null</code>
520
   *        to indicate that there is no visual location
521
   */
522
  public void setMagicCaretPosition(Point p)
523
  {
524
    magicCaretPosition = p;
525
  }
526
 
527
  /**
528
   * Returns the current visual position of this <code>Caret</code>.
529
   *
530
   * @return the current visual position of this <code>Caret</code>
531
   *
532
   * @see #setMagicCaretPosition
533
   */
534
  public Point getMagicCaretPosition()
535
  {
536
    return magicCaretPosition;
537
  }
538
 
539
  /**
540
   * Returns the current position of the <code>mark</code>. The
541
   * <code>mark</code> marks the location in the <code>Document</code> that
542
   * is the end of a selection. If there is no selection, the <code>mark</code>
543
   * is the same as the <code>dot</code>.
544
   *
545
   * @return the current position of the mark
546
   */
547
  public int getMark()
548
  {
549
    return mark;
550
  }
551
 
552
  private void handleHighlight()
553
  {
554
    Highlighter highlighter = textComponent.getHighlighter();
555
 
556
    if (highlighter == null)
557
      return;
558
 
559
    int p0 = Math.min(dot, mark);
560
    int p1 = Math.max(dot, mark);
561
 
562
    if (selectionVisible && p0 != p1)
563
      {
564
        try
565
          {
566
            if (highlightEntry == null)
567
              highlightEntry = highlighter.addHighlight(p0, p1, getSelectionPainter());
568
            else
569
              highlighter.changeHighlight(highlightEntry, p0, p1);
570
          }
571
        catch (BadLocationException e)
572
          {
573
            // This should never happen.
574
            throw new InternalError();
575
          }
576
      }
577
    else
578
      {
579
        if (highlightEntry != null)
580
          {
581
            highlighter.removeHighlight(highlightEntry);
582
            highlightEntry = null;
583
          }
584
      }
585
  }
586
 
587
  /**
588
   * Sets the visiblity state of the selection.
589
   *
590
   * @param v <code>true</code> if the selection should be visible,
591
   *        <code>false</code> otherwise
592
   */
593
  public void setSelectionVisible(boolean v)
594
  {
595
    if (selectionVisible == v)
596
      return;
597
 
598
    selectionVisible = v;
599
    handleHighlight();
600
    repaint();
601
  }
602
 
603
  /**
604
   * Returns <code>true</code> if the selection is currently visible,
605
   * <code>false</code> otherwise.
606
   *
607
   * @return <code>true</code> if the selection is currently visible,
608
   *         <code>false</code> otherwise
609
   */
610
  public boolean isSelectionVisible()
611
  {
612
    return selectionVisible;
613
  }
614
 
615
  /**
616
   * Causes the <code>Caret</code> to repaint itself.
617
   */
618
  protected final void repaint()
619
  {
620
    getComponent().repaint(x, y, width, height);
621
  }
622
 
623
  /**
624
   * Paints this <code>Caret</code> using the specified <code>Graphics</code>
625
   * context.
626
   *
627
   * @param g the graphics context to use
628
   */
629
  public void paint(Graphics g)
630
  {
631
    JTextComponent comp = getComponent();
632
    if (comp == null)
633
      return;
634
 
635
    int dot = getDot();
636
    Rectangle rect = null;
637
 
638
    try
639
      {
640
        rect = textComponent.modelToView(dot);
641
      }
642
    catch (BadLocationException e)
643
      {
644
        assert false : "Unexpected bad caret location: " + dot;
645
        return;
646
      }
647
 
648
    if (rect == null)
649
      return;
650
 
651
    // Check if paint has possibly been called directly, without a previous
652
    // call to damage(). In this case we need to do some cleanup first.
653
    if ((x != rect.x) || (y != rect.y))
654
      {
655
        repaint(); // Erase previous location of caret.
656
        x = rect.x;
657
        y = rect.y;
658
        width = 1;
659
        height = rect.height;
660
      }
661
 
662
    // Now draw the caret on the new position if visible.
663
    if (visible)
664
      {
665
        g.setColor(textComponent.getCaretColor());
666
        g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height);
667
      }
668
  }
669
 
670
  /**
671
   * Returns all registered event listeners of the specified type.
672
   *
673
   * @param listenerType the type of listener to return
674
   *
675
   * @return all registered event listeners of the specified type
676
   */
677
  public EventListener[] getListeners(Class listenerType)
678
  {
679
    return listenerList.getListeners(listenerType);
680
  }
681
 
682
  /**
683
   * Registers a {@link ChangeListener} that is notified whenever that state
684
   * of this <code>Caret</code> changes.
685
   *
686
   * @param listener the listener to register to this caret
687
   */
688
  public void addChangeListener(ChangeListener listener)
689
  {
690
    listenerList.add(ChangeListener.class, listener);
691
  }
692
 
693
  /**
694
   * Removes a {@link ChangeListener} from the list of registered listeners.
695
   *
696
   * @param listener the listener to remove
697
   */
698
  public void removeChangeListener(ChangeListener listener)
699
  {
700
    listenerList.remove(ChangeListener.class, listener);
701
  }
702
 
703
  /**
704
   * Returns all registered {@link ChangeListener}s of this <code>Caret</code>.
705
   *
706
   * @return all registered {@link ChangeListener}s of this <code>Caret</code>
707
   */
708
  public ChangeListener[] getChangeListeners()
709
  {
710
    return (ChangeListener[]) getListeners(ChangeListener.class);
711
  }
712
 
713
  /**
714
   * Notifies all registered {@link ChangeListener}s that the state
715
   * of this <code>Caret</code> has changed.
716
   */
717
  protected void fireStateChanged()
718
  {
719
    ChangeListener[] listeners = getChangeListeners();
720
 
721
    for (int index = 0; index < listeners.length; ++index)
722
      listeners[index].stateChanged(changeEvent);
723
  }
724
 
725
  /**
726
   * Returns the <code>JTextComponent</code> on which this <code>Caret</code>
727
   * is installed.
728
   *
729
   * @return the <code>JTextComponent</code> on which this <code>Caret</code>
730
   *         is installed
731
   */
732
  protected final JTextComponent getComponent()
733
  {
734
    return textComponent;
735
  }
736
 
737
  /**
738
   * Returns the blink rate of this <code>Caret</code> in milliseconds.
739
   * A value of <code>0</code> means that the caret does not blink.
740
   *
741
   * @return the blink rate of this <code>Caret</code> or <code>0</code> if
742
   *         this caret does not blink
743
   */
744
  public int getBlinkRate()
745
  {
746
    return blinkRate;
747
  }
748
 
749
  /**
750
   * Sets the blink rate of this <code>Caret</code> in milliseconds.
751
   * A value of <code>0</code> means that the caret does not blink.
752
   *
753
   * @param rate the new blink rate to set
754
   */
755
  public void setBlinkRate(int rate)
756
  {
757
    if (blinkTimer != null)
758
      blinkTimer.setDelay(rate);
759
    blinkRate = rate;
760
  }
761
 
762
  /**
763
   * Returns the current position of this <code>Caret</code> within the
764
   * <code>Document</code>.
765
   *
766
   * @return the current position of this <code>Caret</code> within the
767
   *         <code>Document</code>
768
   */
769
  public int getDot()
770
  {
771
    return dot;
772
  }
773
 
774
  /**
775
   * Moves the <code>dot</code> location without touching the
776
   * <code>mark</code>. This is used when making a selection.
777
   *
778
   * @param dot the location where to move the dot
779
   *
780
   * @see #setDot(int)
781
   */
782
  public void moveDot(int dot)
783
  {
784
    if (dot >= 0)
785
      {
786
        this.dot = dot;
787
        handleHighlight();
788
        adjustVisibility(this);
789
        appear();
790
      }
791
  }
792
 
793
  /**
794
   * Sets the current position of this <code>Caret</code> within the
795
   * <code>Document</code>. This also sets the <code>mark</code> to the new
796
   * location.
797
   *
798
   * @param dot
799
   *          the new position to be set
800
   * @see #moveDot(int)
801
   */
802
  public void setDot(int dot)
803
  {
804
    if (dot >= 0)
805
      {
806
        this.mark = dot;
807
        this.dot = dot;
808
        handleHighlight();
809
        adjustVisibility(this);
810
        appear();
811
      }
812
  }
813
 
814
  /**
815
   * Show the caret (may be hidden due blinking) and adjust the timer not to
816
   * hide it (possibly immediately).
817
   *
818
   * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
819
   */
820
  void appear()
821
  {
822
    // All machinery is only required if the carret is blinking.
823
    if (blinkListener != null)
824
      {
825
        blinkListener.ignoreNextEvent = true;
826
 
827
        // If the caret is visible, erase the current position by repainting
828
        // over.
829
        if (visible)
830
          repaint();
831
 
832
        // Draw the caret in the new position.
833
        visible = true;
834
 
835
        Rectangle area = null;
836
        try
837
          {
838
            area = getComponent().modelToView(getDot());
839
          }
840
        catch (BadLocationException ex)
841
          {
842
            assert false : "Unexpected bad caret location: " + getDot();
843
          }
844
        if (area != null)
845
          damage(area);
846
      }
847
    repaint();
848
  }
849
 
850
  /**
851
   * Returns <code>true</code> if this <code>Caret</code> is currently visible,
852
   * and <code>false</code> if it is not.
853
   *
854
   * @return <code>true</code> if this <code>Caret</code> is currently visible,
855
   *         and <code>false</code> if it is not
856
   */
857
  public boolean isVisible()
858
  {
859
    return visible;
860
  }
861
 
862
  /**
863
   * Sets the visibility state of the caret. <code>true</code> shows the
864
   * <code>Caret</code>, <code>false</code> hides it.
865
   *
866
   * @param v the visibility to set
867
   */
868
  public void setVisible(boolean v)
869
  {
870
    if (v != visible)
871
      {
872
        visible = v;
873
        if (visible)
874
          if (textComponent.isEnabled() && textComponent.isEditable())
875
            {
876
              if (blinkTimer == null)
877
                initBlinkTimer();
878
              blinkTimer.start();
879
            }
880
        else
881
          {
882
            if (blinkTimer != null)
883
              blinkTimer.stop();
884
          }
885
        Rectangle area = null;
886
        try
887
          {
888
            area = getComponent().modelToView(getDot());
889
          }
890
        catch (BadLocationException ex)
891
          {
892
            assert false: "Unexpected bad caret location: " + getDot();
893
          }
894
        if (area != null)
895
          damage(area);
896
      }
897
  }
898
 
899
  /**
900
   * Returns the {@link Highlighter.HighlightPainter} that should be used
901
   * to paint the selection.
902
   *
903
   * @return the {@link Highlighter.HighlightPainter} that should be used
904
   *         to paint the selection
905
   */
906
  protected Highlighter.HighlightPainter getSelectionPainter()
907
  {
908
    return DefaultHighlighter.DefaultPainter;
909
  }
910
 
911
  /**
912
   * Updates the carets rectangle properties to the specified rectangle and
913
   * repaints the caret.
914
   *
915
   * @param r the rectangle to set as the caret rectangle
916
   */
917
  protected void damage(Rectangle r)
918
  {
919
    if (r == null)
920
      return;
921
    x = r.x;
922
    y = r.y;
923
    width = 1;
924
    // height is normally set in paint and we leave it untouched. However, we
925
    // must set a valid value here, since otherwise the painting mechanism
926
    // sets a zero clip and never calls paint.
927
    if (height <= 0)
928
      height = getComponent().getHeight();
929
    repaint();
930
  }
931
 
932
  /**
933
   * Adjusts the text component so that the caret is visible. This default
934
   * implementation simply calls
935
   * {@link JComponent#scrollRectToVisible(Rectangle)} on the text component.
936
   * Subclasses may wish to change this.
937
   */
938
  protected void adjustVisibility(Rectangle rect)
939
  {
940
    getComponent().scrollRectToVisible(rect);
941
  }
942
 
943
  /**
944
   * Initializes the blink timer.
945
   */
946
  private void initBlinkTimer()
947
  {
948
    // Setup the blink timer.
949
    blinkListener = new BlinkTimerListener();
950
    blinkTimer = new Timer(getBlinkRate(), blinkListener);
951
    blinkTimer.setRepeats(true);
952
  }
953
}

powered by: WebSVN 2.1.0

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