Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / javax / swing / text / DefaultCaret.java
blobf2a68c00db1df16d503b6680ceca86c78c7a0fc6
1 /* DefaultCaret.java --
2 Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
38 package javax.swing.text;
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;
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;
63 /**
64 * The default implementation of the {@link Caret} interface.
66 * @author orgininal author unknown
67 * @author Roman Kennke (roman@kennke.org)
69 public class DefaultCaret extends Rectangle
70 implements Caret, FocusListener, MouseListener, MouseMotionListener
73 /**
74 * Controls the blinking of the caret.
76 * @author Roman Kennke (kennke@aicas.com)
77 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
79 private class BlinkTimerListener implements ActionListener
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.
87 boolean ignoreNextEvent;
89 /**
90 * Receives notification when the blink timer fires and updates the visible
91 * state of the caret.
93 * @param event the action event
95 public void actionPerformed(ActionEvent event)
97 if (ignoreNextEvent)
98 ignoreNextEvent = false;
99 else
101 visible = !visible;
102 repaint();
108 * Listens for changes in the text component's document and updates the
109 * caret accordingly.
111 * @author Roman Kennke (kennke@aicas.com)
113 private class DocumentHandler implements DocumentListener
116 * Receives notification that some text attributes have changed. No action
117 * is taken here.
119 * @param event the document event
121 public void changedUpdate(DocumentEvent event)
123 // Nothing to do here.
127 * Receives notification that some text has been inserted from the text
128 * component. The caret is moved forward accordingly.
130 * @param event the document event
132 public void insertUpdate(DocumentEvent event)
134 if (policy == ALWAYS_UPDATE ||
135 (SwingUtilities.isEventDispatchThread() &&
136 policy == UPDATE_WHEN_ON_EDT))
138 int dot = getDot();
139 setDot(dot + event.getLength());
144 * Receives notification that some text has been removed into the text
145 * component. The caret is moved backwards accordingly.
147 * @param event the document event
149 public void removeUpdate(DocumentEvent event)
151 if (policy == ALWAYS_UPDATE
152 || (SwingUtilities.isEventDispatchThread()
153 && policy == UPDATE_WHEN_ON_EDT))
155 int dot = getDot();
156 setDot(dot - event.getLength());
158 else if (policy == NEVER_UPDATE
159 || (! SwingUtilities.isEventDispatchThread()
160 && policy == UPDATE_WHEN_ON_EDT))
162 int docLength = event.getDocument().getLength();
163 if (getDot() > docLength)
164 setDot(docLength);
170 * Listens for property changes on the text document. This is used to add and
171 * remove our document listener, if the document of the text component has
172 * changed.
174 * @author Roman Kennke (kennke@aicas.com)
176 private class PropertyChangeHandler implements PropertyChangeListener
180 * Receives notification when a property has changed on the text component.
181 * This adds/removes our document listener from the text component's
182 * document when the document changes.
184 * @param e the property change event
186 public void propertyChange(PropertyChangeEvent e)
188 if (e.getPropertyName().equals("document"))
190 Document oldDoc = (Document) e.getOldValue();
191 oldDoc.removeDocumentListener(documentListener);
192 Document newDoc = (Document) e.getNewValue();
193 newDoc.addDocumentListener(documentListener);
199 /** The serialization UID (compatible with JDK1.5). */
200 private static final long serialVersionUID = 4325555698756477346L;
203 * Indicates the Caret position should always be updated after Document
204 * changes even if the updates are not performed on the Event Dispatching
205 * thread.
207 * @since 1.5
209 public static final int ALWAYS_UPDATE = 2;
212 * Indicates the Caret position should not be changed unless the Document
213 * length becomes less than the Caret position, in which case the Caret
214 * is moved to the end of the Document.
216 * @since 1.5
218 public static final int NEVER_UPDATE = 1;
220 /**
221 * Indicates the Caret position should be updated only if Document changes
222 * are made on the Event Dispatcher thread.
224 * @since 1.5
226 public static final int UPDATE_WHEN_ON_EDT = 0;
228 /** Keeps track of the current update policy **/
229 int policy = UPDATE_WHEN_ON_EDT;
232 * The <code>ChangeEvent</code> that is fired by {@link #fireStateChanged()}.
234 protected ChangeEvent changeEvent = new ChangeEvent(this);
237 * Stores all registered event listeners.
239 protected EventListenerList listenerList = new EventListenerList();
242 * Our document listener.
244 DocumentListener documentListener;
247 * Our property listener.
249 PropertyChangeListener propertyChangeListener;
252 * The text component in which this caret is installed.
254 private JTextComponent textComponent;
257 * Indicates if the selection should be visible or not.
259 private boolean selectionVisible = true;
262 * The blink rate of this <code>Caret</code>.
264 private int blinkRate = 500;
267 * The current dot position.
269 private int dot = 0;
272 * The current mark position.
274 private int mark = 0;
277 * The current visual caret position.
279 private Point magicCaretPosition = null;
282 * Indicates if this <code>Caret</code> is currently visible or not. This is
283 * package private to avoid an accessor method.
285 boolean visible = false;
288 * The current highlight entry.
290 private Object highlightEntry;
292 private Timer blinkTimer;
294 private BlinkTimerListener blinkListener;
297 * Creates a new <code>DefaultCaret</code> instance.
299 public DefaultCaret()
301 // Nothing to do here.
305 * Sets the Caret update policy.
307 * @param policy the new policy. Valid values are:
308 * ALWAYS_UPDATE: always update the Caret position, even when Document
309 * updates don't occur on the Event Dispatcher thread.
310 * NEVER_UPDATE: don't update the Caret position unless the Document
311 * length becomes less than the Caret position (then update the
312 * Caret to the end of the Document).
313 * UPDATE_WHEN_ON_EDT: update the Caret position when the
314 * Document updates occur on the Event Dispatcher thread. This is the
315 * default.
317 * @since 1.5
318 * @throws IllegalArgumentException if policy is not one of the above.
320 public void setUpdatePolicy (int policy)
322 if (policy != ALWAYS_UPDATE && policy != NEVER_UPDATE
323 && policy != UPDATE_WHEN_ON_EDT)
324 throw new
325 IllegalArgumentException
326 ("policy must be ALWAYS_UPDATE, NEVER__UPDATE, or UPDATE_WHEN_ON_EDT");
327 this.policy = policy;
331 * Gets the caret update policy.
333 * @return the caret update policy.
334 * @since 1.5
336 public int getUpdatePolicy ()
338 return policy;
342 * Moves the caret position when the mouse is dragged over the text
343 * component, modifying the selection accordingly.
345 * @param event the <code>MouseEvent</code> describing the drag operation
347 public void mouseDragged(MouseEvent event)
349 moveCaret(event);
353 * Indicates a mouse movement over the text component. Does nothing here.
355 * @param event the <code>MouseEvent</code> describing the mouse operation
357 public void mouseMoved(MouseEvent event)
359 // Nothing to do here.
363 * When the click is received from Button 1 then the following actions
364 * are performed here:
366 * <ul>
367 * <li>If we receive a double click, the caret position (dot) is set
368 * to the position associated to the mouse click and the word at
369 * this location is selected. If there is no word at the pointer
370 * the gap is selected instead.</li>
371 * <li>If we receive a triple click, the caret position (dot) is set
372 * to the position associated to the mouse click and the line at
373 * this location is selected.</li>
374 * </ul>
376 * @param event the <code>MouseEvent</code> describing the click operation
378 public void mouseClicked(MouseEvent event)
380 int count = event.getClickCount();
382 if (count >= 2)
384 int newDot = getComponent().viewToModel(event.getPoint());
385 JTextComponent t = getComponent();
389 if (count == 3)
390 t.select(Utilities.getRowStart(t, newDot), Utilities.getRowEnd(t, newDot));
391 else
393 int nextWord = Utilities.getNextWord(t, newDot);
395 // When the mouse points at the offset of the first character
396 // in a word Utilities().getPreviousWord will not return that
397 // word but we want to select that. We have to use
398 // Utilities.nextWord() to get it.
399 if (newDot == nextWord)
400 t.select(nextWord, Utilities.getNextWord(t, nextWord));
401 else
403 int previousWord = Utilities.getPreviousWord(t, newDot);
404 int previousWordEnd = Utilities.getWordEnd(t, previousWord);
406 // If the user clicked in the space between two words,
407 // then select the space.
408 if (newDot >= previousWordEnd && newDot <= nextWord)
409 t.select(previousWordEnd, nextWord);
410 // Otherwise select the word under the mouse pointer.
411 else
412 t.select(previousWord, previousWordEnd);
416 catch(BadLocationException ble)
418 // TODO: Swallowing ok here?
421 dot = newDot;
427 * Indicates that the mouse has entered the text component. Nothing is done
428 * here.
430 * @param event the <code>MouseEvent</code> describing the mouse operation
432 public void mouseEntered(MouseEvent event)
434 // Nothing to do here.
438 * Indicates that the mouse has exited the text component. Nothing is done
439 * here.
441 * @param event the <code>MouseEvent</code> describing the mouse operation
443 public void mouseExited(MouseEvent event)
445 // Nothing to do here.
449 * If the button 1 is pressed, the caret position is updated to the
450 * position of the mouse click and the text component requests the input
451 * focus if it is enabled. If the SHIFT key is held down, the caret will
452 * be moved, which might select the text between the old and new location.
454 * @param event the <code>MouseEvent</code> describing the press operation
456 public void mousePressed(MouseEvent event)
458 if (event.isShiftDown())
459 moveCaret(event);
460 else
461 positionCaret(event);
465 * Indicates that a mouse button has been released on the text component.
466 * Nothing is done here.
468 * @param event the <code>MouseEvent</code> describing the mouse operation
470 public void mouseReleased(MouseEvent event)
472 // Nothing to do here.
476 * Sets the caret to <code>visible</code> if the text component is editable.
478 * @param event the <code>FocusEvent</code>
480 public void focusGained(FocusEvent event)
482 setVisible(true);
483 updateTimerStatus();
487 * Sets the caret to <code>invisible</code>.
489 * @param event the <code>FocusEvent</code>
491 public void focusLost(FocusEvent event)
493 if (event.isTemporary() == false)
495 setVisible(false);
496 // Stop the blinker, if running.
497 if (blinkTimer != null && blinkTimer.isRunning())
498 blinkTimer.stop();
503 * Install (if not present) and start the timer, if the caret must blink. The
504 * caret does not blink if it is invisible, or the component is disabled or
505 * not editable.
507 private void updateTimerStatus()
509 if (textComponent.isEnabled() && textComponent.isEditable())
511 if (blinkTimer == null)
512 initBlinkTimer();
513 if (!blinkTimer.isRunning())
514 blinkTimer.start();
516 else
518 if (blinkTimer != null)
519 blinkTimer.stop();
524 * Moves the caret to the position specified in the <code>MouseEvent</code>.
525 * This will cause a selection if the dot and mark are different.
527 * @param event the <code>MouseEvent</code> from which to fetch the position
529 protected void moveCaret(MouseEvent event)
531 int newDot = getComponent().viewToModel(event.getPoint());
532 moveDot(newDot);
536 * Repositions the caret to the position specified in the
537 * <code>MouseEvent</code>.
539 * @param event the <code>MouseEvent</code> from which to fetch the position
541 protected void positionCaret(MouseEvent event)
543 int newDot = getComponent().viewToModel(event.getPoint());
544 setDot(newDot);
548 * Deinstalls this <code>Caret</code> from the specified
549 * <code>JTextComponent</code>. This removes any listeners that have been
550 * registered by this <code>Caret</code>.
552 * @param c the text component from which to install this caret
554 public void deinstall(JTextComponent c)
556 textComponent.removeFocusListener(this);
557 textComponent.removeMouseListener(this);
558 textComponent.removeMouseMotionListener(this);
559 textComponent.getDocument().removeDocumentListener(documentListener);
560 documentListener = null;
561 textComponent.removePropertyChangeListener(propertyChangeListener);
562 propertyChangeListener = null;
563 textComponent = null;
565 // Deinstall blink timer if present.
566 if (blinkTimer != null)
567 blinkTimer.stop();
568 blinkTimer = null;
572 * Installs this <code>Caret</code> on the specified
573 * <code>JTextComponent</code>. This registers a couple of listeners
574 * on the text component.
576 * @param c the text component on which to install this caret
578 public void install(JTextComponent c)
580 textComponent = c;
581 textComponent.addFocusListener(this);
582 textComponent.addMouseListener(this);
583 textComponent.addMouseMotionListener(this);
584 propertyChangeListener = new PropertyChangeHandler();
585 textComponent.addPropertyChangeListener(propertyChangeListener);
586 documentListener = new DocumentHandler();
587 textComponent.getDocument().addDocumentListener(documentListener);
589 repaint();
593 * Sets the current visual position of this <code>Caret</code>.
595 * @param p the Point to use for the saved location. May be <code>null</code>
596 * to indicate that there is no visual location
598 public void setMagicCaretPosition(Point p)
600 magicCaretPosition = p;
604 * Returns the current visual position of this <code>Caret</code>.
606 * @return the current visual position of this <code>Caret</code>
608 * @see #setMagicCaretPosition
610 public Point getMagicCaretPosition()
612 return magicCaretPosition;
616 * Returns the current position of the <code>mark</code>. The
617 * <code>mark</code> marks the location in the <code>Document</code> that
618 * is the end of a selection. If there is no selection, the <code>mark</code>
619 * is the same as the <code>dot</code>.
621 * @return the current position of the mark
623 public int getMark()
625 return mark;
628 private void clearHighlight()
630 Highlighter highlighter = textComponent.getHighlighter();
632 if (highlighter == null)
633 return;
635 if (selectionVisible)
639 if (highlightEntry == null)
640 highlightEntry = highlighter.addHighlight(0, 0, getSelectionPainter());
641 else
642 highlighter.changeHighlight(highlightEntry, 0, 0);
644 catch (BadLocationException e)
646 // This should never happen.
647 throw new InternalError();
650 else
652 if (highlightEntry != null)
654 highlighter.removeHighlight(highlightEntry);
655 highlightEntry = null;
660 private void handleHighlight()
662 Highlighter highlighter = textComponent.getHighlighter();
664 if (highlighter == null)
665 return;
667 int p0 = Math.min(dot, mark);
668 int p1 = Math.max(dot, mark);
670 if (selectionVisible)
674 if (highlightEntry == null)
675 highlightEntry = highlighter.addHighlight(p0, p1, getSelectionPainter());
676 else
677 highlighter.changeHighlight(highlightEntry, p0, p1);
679 catch (BadLocationException e)
681 // This should never happen.
682 throw new InternalError();
685 else
687 if (highlightEntry != null)
689 highlighter.removeHighlight(highlightEntry);
690 highlightEntry = null;
696 * Sets the visiblity state of the selection.
698 * @param v <code>true</code> if the selection should be visible,
699 * <code>false</code> otherwise
701 public void setSelectionVisible(boolean v)
703 if (selectionVisible == v)
704 return;
706 selectionVisible = v;
707 handleHighlight();
708 repaint();
712 * Returns <code>true</code> if the selection is currently visible,
713 * <code>false</code> otherwise.
715 * @return <code>true</code> if the selection is currently visible,
716 * <code>false</code> otherwise
718 public boolean isSelectionVisible()
720 return selectionVisible;
724 * Causes the <code>Caret</code> to repaint itself.
726 protected final void repaint()
728 getComponent().repaint(x, y, width, height);
732 * Paints this <code>Caret</code> using the specified <code>Graphics</code>
733 * context.
735 * @param g the graphics context to use
737 public void paint(Graphics g)
739 JTextComponent comp = getComponent();
740 if (comp == null)
741 return;
743 // Make sure the dot has a sane position.
744 dot = Math.min(dot, textComponent.getDocument().getLength());
745 dot = Math.max(dot, 0);
747 Rectangle rect = null;
751 rect = textComponent.modelToView(dot);
753 catch (BadLocationException e)
755 AssertionError ae;
756 ae = new AssertionError("Unexpected bad caret location: " + dot);
757 ae.initCause(e);
758 throw ae;
761 if (rect == null)
762 return;
764 // Check if paint has possibly been called directly, without a previous
765 // call to damage(). In this case we need to do some cleanup first.
766 if ((x != rect.x) || (y != rect.y))
768 repaint(); // Erase previous location of caret.
769 x = rect.x;
770 y = rect.y;
771 width = 1;
772 height = rect.height;
775 // Now draw the caret on the new position if visible.
776 if (visible)
778 g.setColor(textComponent.getCaretColor());
779 g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height);
784 * Returns all registered event listeners of the specified type.
786 * @param listenerType the type of listener to return
788 * @return all registered event listeners of the specified type
790 public EventListener[] getListeners(Class listenerType)
792 return listenerList.getListeners(listenerType);
796 * Registers a {@link ChangeListener} that is notified whenever that state
797 * of this <code>Caret</code> changes.
799 * @param listener the listener to register to this caret
801 public void addChangeListener(ChangeListener listener)
803 listenerList.add(ChangeListener.class, listener);
807 * Removes a {@link ChangeListener} from the list of registered listeners.
809 * @param listener the listener to remove
811 public void removeChangeListener(ChangeListener listener)
813 listenerList.remove(ChangeListener.class, listener);
817 * Returns all registered {@link ChangeListener}s of this <code>Caret</code>.
819 * @return all registered {@link ChangeListener}s of this <code>Caret</code>
821 public ChangeListener[] getChangeListeners()
823 return (ChangeListener[]) getListeners(ChangeListener.class);
827 * Notifies all registered {@link ChangeListener}s that the state
828 * of this <code>Caret</code> has changed.
830 protected void fireStateChanged()
832 ChangeListener[] listeners = getChangeListeners();
834 for (int index = 0; index < listeners.length; ++index)
835 listeners[index].stateChanged(changeEvent);
839 * Returns the <code>JTextComponent</code> on which this <code>Caret</code>
840 * is installed.
842 * @return the <code>JTextComponent</code> on which this <code>Caret</code>
843 * is installed
845 protected final JTextComponent getComponent()
847 return textComponent;
851 * Returns the blink rate of this <code>Caret</code> in milliseconds.
852 * A value of <code>0</code> means that the caret does not blink.
854 * @return the blink rate of this <code>Caret</code> or <code>0</code> if
855 * this caret does not blink
857 public int getBlinkRate()
859 return blinkRate;
863 * Sets the blink rate of this <code>Caret</code> in milliseconds.
864 * A value of <code>0</code> means that the caret does not blink.
866 * @param rate the new blink rate to set
868 public void setBlinkRate(int rate)
870 if (blinkTimer != null)
871 blinkTimer.setDelay(rate);
872 blinkRate = rate;
876 * Returns the current position of this <code>Caret</code> within the
877 * <code>Document</code>.
879 * @return the current position of this <code>Caret</code> within the
880 * <code>Document</code>
882 public int getDot()
884 return dot;
888 * Moves the <code>dot</code> location without touching the
889 * <code>mark</code>. This is used when making a selection.
891 * @param dot the location where to move the dot
893 * @see #setDot(int)
895 public void moveDot(int dot)
897 if (dot >= 0)
899 Document doc = textComponent.getDocument();
900 if (doc != null)
901 this.dot = Math.min(dot, doc.getLength());
902 this.dot = Math.max(this.dot, 0);
904 handleHighlight();
905 adjustVisibility(this);
906 appear();
911 * Sets the current position of this <code>Caret</code> within the
912 * <code>Document</code>. This also sets the <code>mark</code> to the new
913 * location.
915 * @param dot
916 * the new position to be set
917 * @see #moveDot(int)
919 public void setDot(int dot)
921 if (dot >= 0)
923 Document doc = textComponent.getDocument();
924 if (doc != null)
925 this.dot = Math.min(dot, doc.getLength());
926 this.dot = Math.max(this.dot, 0);
927 this.mark = this.dot;
929 clearHighlight();
930 adjustVisibility(this);
931 appear();
936 * Show the caret (may be hidden due blinking) and adjust the timer not to
937 * hide it (possibly immediately).
939 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
941 void appear()
943 // All machinery is only required if the carret is blinking.
944 if (blinkListener != null)
946 blinkListener.ignoreNextEvent = true;
948 // If the caret is visible, erase the current position by repainting
949 // over.
950 if (visible)
951 repaint();
953 // Draw the caret in the new position.
954 visible = true;
956 Rectangle area = null;
957 int dot = getDot();
960 area = getComponent().modelToView(dot);
962 catch (BadLocationException e)
964 AssertionError ae;
965 ae = new AssertionError("Unexpected bad caret location: " + dot);
966 ae.initCause(e);
967 throw ae;
969 if (area != null)
970 damage(area);
972 repaint();
976 * Returns <code>true</code> if this <code>Caret</code> is currently visible,
977 * and <code>false</code> if it is not.
979 * @return <code>true</code> if this <code>Caret</code> is currently visible,
980 * and <code>false</code> if it is not
982 public boolean isVisible()
984 return visible;
988 * Sets the visibility state of the caret. <code>true</code> shows the
989 * <code>Caret</code>, <code>false</code> hides it.
991 * @param v the visibility to set
993 public void setVisible(boolean v)
995 if (v != visible)
997 visible = v;
998 updateTimerStatus();
999 Rectangle area = null;
1000 int dot = getDot();
1003 area = getComponent().modelToView(dot);
1005 catch (BadLocationException e)
1007 AssertionError ae;
1008 ae = new AssertionError("Unexpected bad caret location: " + dot);
1009 ae.initCause(e);
1010 throw ae;
1012 if (area != null)
1013 damage(area);
1018 * Returns the {@link Highlighter.HighlightPainter} that should be used
1019 * to paint the selection.
1021 * @return the {@link Highlighter.HighlightPainter} that should be used
1022 * to paint the selection
1024 protected Highlighter.HighlightPainter getSelectionPainter()
1026 return DefaultHighlighter.DefaultPainter;
1030 * Updates the carets rectangle properties to the specified rectangle and
1031 * repaints the caret.
1033 * @param r the rectangle to set as the caret rectangle
1035 protected void damage(Rectangle r)
1037 if (r == null)
1038 return;
1039 x = r.x;
1040 y = r.y;
1041 width = 1;
1042 // height is normally set in paint and we leave it untouched. However, we
1043 // must set a valid value here, since otherwise the painting mechanism
1044 // sets a zero clip and never calls paint.
1045 if (height <= 0)
1046 height = getComponent().getHeight();
1047 repaint();
1051 * Adjusts the text component so that the caret is visible. This default
1052 * implementation simply calls
1053 * {@link JComponent#scrollRectToVisible(Rectangle)} on the text component.
1054 * Subclasses may wish to change this.
1056 protected void adjustVisibility(Rectangle rect)
1058 getComponent().scrollRectToVisible(rect);
1062 * Initializes the blink timer.
1064 private void initBlinkTimer()
1066 // Setup the blink timer.
1067 blinkListener = new BlinkTimerListener();
1068 blinkTimer = new Timer(getBlinkRate(), blinkListener);
1069 blinkTimer.setRepeats(true);