/* * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.swing.text; import java.awt.*;import java.awt.event.*;import java.awt.datatransfer.*;import java.beans.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.*;import javax.swing.*;import javax.swing.event.*;import javax.swing.plaf.*;import java.util.EventListener;import sun.swing.SwingUtilities2; /** * A default implementation of Caret. The caret is rendered as * a vertical line in the color specified by the CaretColor property * of the associated JTextComponent. It can blink at the rate specified * by the BlinkRate property. * <p> * This implementation expects two sources of asynchronous notification. * The timer thread fires asynchronously, and causes the caret to simply * repaint the most recent bounding box. The caret also tracks change * as the document is modified. Typically this will happen on the * event dispatch thread as a result of some mouse or keyboard event. * The caret behavior on both synchronous and asynchronous documents updates * is controlled by <code>UpdatePolicy</code> property. The repaint of the * new caret location will occur on the event thread in any case, as calls to * <code>modelToView</code> are only safe on the event thread. * <p> * The caret acts as a mouse and focus listener on the text component * it has been installed in, and defines the caret semantics based upon * those events. The listener methods can be reimplemented to change the * semantics. * By default, the first mouse button will be used to set focus and caret * position. Dragging the mouse pointer with the first mouse button will * sweep out a selection that is contiguous in the model. If the associated * text component is editable, the caret will become visible when focus * is gained, and invisible when focus is lost. * <p> * The Highlighter bound to the associated text component is used to * render the selection by default. * Selection appearance can be customized by supplying a * painter to use for the highlights. By default a painter is used that * will render a solid color as specified in the associated text component * in the <code>SelectionColor</code> property. This can easily be changed * by reimplementing the * {@link #getSelectionPainter getSelectionPainter} * method. * <p> * A customized caret appearance can be achieved by reimplementing * the paint method. If the paint method is changed, the damage method * should also be reimplemented to cause a repaint for the area needed * to render the caret. The caret extends the Rectangle class which * is used to hold the bounding box for where the caret was last rendered. * This enables the caret to repaint in a thread-safe manner when the * caret moves without making a call to modelToView which is unstable * between model updates and view repair (i.e. the order of delivery * to DocumentListeners is not guaranteed). * <p> * The magic caret position is set to null when the caret position changes. * A timer is used to determine the new location (after the caret change). * When the timer fires, if the magic caret position is still null it is * reset to the current caret position. Any actions that change * the caret position and want the magic caret position to remain the * same, must remember the magic caret position, change the cursor, and * then set the magic caret position to its original value. This has the * benefit that only actions that want the magic caret position to persist * (such as open/down) need to know about it. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @author Timothy Prinzing * @see Caret */public class DefaultCaret extends Rectangle implements Caret, FocusListener, MouseListener, MouseMotionListener { /** * Indicates that the caret position is to be updated only when * document changes are performed on the Event Dispatching Thread. * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int UPDATE_WHEN_ON_EDT = 0; /** * Indicates that the caret should remain at the same * absolute position in the document regardless of any document * updates, except when the document length becomes less than * the current caret position due to removal. In that case the caret * position is adjusted to the end of the document. * * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int NEVER_UPDATE = 1; /** * Indicates that the caret position is to be <b>always</b> * updated accordingly to the document changes regardless whether * the document updates are performed on the Event Dispatching Thread * or not. * * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int ALWAYS_UPDATE = 2; /** * Constructs a default caret. */ public DefaultCaret() { } /** * Sets the caret movement policy on the document updates. Normally * the caret updates its absolute position within the document on * insertions occurred before or at the caret position and * on removals before the caret position. 'Absolute position' * means here the position relative to the start of the document. * For example if * a character is typed within editable text component it is inserted * at the caret position and the caret moves to the next absolute * position within the document due to insertion and if * <code>BACKSPACE</code> is typed then caret decreases its absolute * position due to removal of a character before it. Sometimes * it may be useful to turn off the caret position updates so that * the caret stays at the same absolute position within the * document position regardless of any document updates. * <p> * The following update policies are allowed: * <ul> * <li><code>NEVER_UPDATE</code>: the caret stays at the same * absolute position in the document regardless of any document * updates, except when document length becomes less than * the current caret position due to removal. In that case caret * position is adjusted to the end of the document. * The caret doesn't try to keep itself visible by scrolling * the associated view when using this policy. </li> * <li><code>ALWAYS_UPDATE</code>: the caret always tracks document * changes. For regular changes it increases its position * if an insertion occurs before or at its current position, * and decreases position if a removal occurs before * its current position. For undo/redo updates it is always * moved to the position where update occurred. The caret * also tries to keep itself visible by calling * <code>adjustVisibility</code> method.</li> * <li><code>UPDATE_WHEN_ON_EDT</code>: acts like <code>ALWAYS_UPDATE</code> * if the document updates are performed on the Event Dispatching Thread * and like <code>NEVER_UPDATE</code> if updates are performed on * other thread. </li> * </ul> <p> * The default property value is <code>UPDATE_WHEN_ON_EDT</code>. * * @param policy one of the following values : <code>UPDATE_WHEN_ON_EDT</code>, * <code>NEVER_UPDATE</code>, <code>ALWAYS_UPDATE</code> * @throws IllegalArgumentException if invalid value is passed * * @see #getUpdatePolicy * @see #adjustVisibility * @see #UPDATE_WHEN_ON_EDT * @see #NEVER_UPDATE * @see #ALWAYS_UPDATE * * @since 1.5 */ public void setUpdatePolicy(int policy) { updatePolicy = policy; } /** * Gets the caret movement policy on document updates. * * @return one of the following values : <code>UPDATE_WHEN_ON_EDT</code>, * <code>NEVER_UPDATE</code>, <code>ALWAYS_UPDATE</code> * * @see #setUpdatePolicy * @see #UPDATE_WHEN_ON_EDT * @see #NEVER_UPDATE * @see #ALWAYS_UPDATE * * @since 1.5 */ public int getUpdatePolicy() { return updatePolicy; } /** * Gets the text editor component that this caret is * is bound to. * * @return the component */ protected final JTextComponent getComponent() { return component; } /** * Cause the caret to be painted. The repaint * area is the bounding box of the caret (i.e. * the caret rectangle or <em>this</em>). * <p> * This method is thread safe, although most Swing methods * are not. Please see * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How * to Use Threads</A> for more information. */ protected final synchronized void repaint() { if (component != null) { component.repaint(x, y, width, height); } } /** * Damages the area surrounding the caret to cause * it to be repainted in a new location. If paint() * is reimplemented, this method should also be * reimplemented. This method should update the * caret bounds (x, y, width, and height). * * @param r the current location of the caret * @see #paint */ protected synchronized void damage(Rectangle r) { if (r != null) { int damageWidth = getCaretWidth(r.height); x = r.x - 4 - (damageWidth >> 1); y = r.y; width = 9 + damageWidth; height = r.height; repaint(); } } /** * Scrolls the associated view (if necessary) to make * the caret visible. Since how this should be done * is somewhat of a policy, this method can be * reimplemented to change the behavior. By default * the scrollRectToVisible method is called on the * associated component. * * @param nloc the new position to scroll to */ protected void adjustVisibility(Rectangle nloc) { if(component == null) { return; } if (SwingUtilities.isEventDispatchThread()) { component.scrollRectToVisible(nloc); } else { SwingUtilities.invokeLater(new SafeScroller(nloc)); } } /** * Gets the painter for the Highlighter. * * @return the painter */ protected Highlighter.HighlightPainter getSelectionPainter() { return DefaultHighlighter.DefaultPainter; } /** * Tries to set the position of the caret from * the coordinates of a mouse event, using viewToModel(). * * @param e the mouse event */ protected void positionCaret(MouseEvent e) { Point pt = new Point(e.getX(), e.getY()); Position.Bias[] biasRet = new Position.Bias[1]; int pos = component.getUI().viewToModel(component, pt, biasRet); if(biasRet[0] == null) biasRet[0] = Position.Bias.Forward; if (pos >= 0) { setDot(pos, biasRet[0]); } } /** * Tries to move the position of the caret from * the coordinates of a mouse event, using viewToModel(). * This will cause a selection if the dot and mark * are different. * * @param e the mouse event */ protected void moveCaret(MouseEvent e) { Point pt = new Point(e.getX(), e.getY()); Position.Bias[] biasRet = new Position.Bias[1]; int pos = component.getUI().viewToModel(component, pt, biasRet); if(biasRet[0] == null) biasRet[0] = Position.Bias.Forward; if (pos >= 0) { moveDot(pos, biasRet[0]); } } // --- FocusListener methods -------------------------- /** * Called when the component containing the caret gains * focus. This is implemented to set the caret to visible * if the component is editable. * * @param e the focus event * @see FocusListener#focusGained */ public void focusGained(FocusEvent e) { if (component.isEnabled()) { if (component.isEditable()) { setVisible(true); } setSelectionVisible(true); } } /** * Called when the component containing the caret loses * focus. This is implemented to set the caret to visibility * to false. * * @param e the focus event * @see FocusListener#focusLost */ public void focusLost(FocusEvent e) { setVisible(false); setSelectionVisible(ownsSelection || e.isTemporary()); } /** * Selects word based on the MouseEvent */ private void selectWord(MouseEvent e) { if (selectedWordEvent != null && selectedWordEvent.getX() == e.getX() && selectedWordEvent.getY() == e.getY()) { //we already done selection for this return; } Action a = null; ActionMap map = getComponent().getActionMap(); if (map != null) { a = map.get(DefaultEditorKit.selectWordAction); } if (a == null) { if (selectWord == null) { selectWord = new DefaultEditorKit.SelectWordAction(); } a = selectWord; } a.actionPerformed(new ActionEvent(getComponent(), ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers())); selectedWordEvent = e; } // --- MouseListener methods ----------------------------------- /** * Called when the mouse is clicked. If the click was generated * from button1, a double click selects a word, * and a triple click the current line. * * @param e the mouse event * @see MouseListener#mouseClicked */ public void mouseClicked(MouseEvent e) { int nclicks = SwingUtilities2.getAdjustedClickCount(getComponent(), e); if (! e.isConsumed()) { if (SwingUtilities.isLeftMouseButton(e)) { // mouse 1 behavior if(nclicks == 1) { selectedWordEvent = null; } else if(nclicks == 2 && SwingUtilities2.canEventAccessSystemClipboard(e)) { selectWord(e); selectedWordEvent = null; } else if(nclicks == 3 && SwingUtilities2.canEventAccessSystemClipboard(e)) { Action a = null; ActionMap map = getComponent().getActionMap(); if (map != null) { a = map.get(DefaultEditorKit.selectLineAction); } if (a == null) { if (selectLine == null) { selectLine = new DefaultEditorKit.SelectLineAction(); } a = selectLine; } a.actionPerformed(new ActionEvent(getComponent(), ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers())); } } else if (SwingUtilities.isMiddleMouseButton(e)) { // mouse 2 behavior if (nclicks == 1 && component.isEditable() && component.isEnabled() && SwingUtilities2.canEventAccessSystemClipboard(e)) { // paste system selection, if it exists JTextComponent c = (JTextComponent) e.getSource(); if (c != null) { try { Toolkit tk = c.getToolkit(); Clipboard buffer = tk.getSystemSelection(); if (buffer != null) { // platform supports system selections, update it. adjustCaret(e); TransferHandler th = c.getTransferHandler(); if (th != null) { Transferable trans = null; try { trans = buffer.getContents(null); } catch (IllegalStateException ise) { // clipboard was unavailable UIManager.getLookAndFeel().provideErrorFeedback(c); } if (trans != null) { th.importData(c, trans); } } adjustFocus(true); } } catch (HeadlessException he) { // do nothing... there is no system clipboard } } } } } } /** * If button 1 is pressed, this is implemented to * request focus on the associated text component, * and to set the caret position. If the shift key is held down, * the caret will be moved, potentially resulting in a selection, * otherwise the * caret position will be set to the new location. If the component * is not enabled, there will be no request for focus. * * @param e the mouse event * @see MouseListener#mousePressed */ public void mousePressed(MouseEvent e) { int nclicks = SwingUtilities2.getAdjustedClickCount(getComponent(), e); if (SwingUtilities.isLeftMouseButton(e)) { if (e.isConsumed()) { shouldHandleRelease = true; } else { shouldHandleRelease = false; adjustCaretAndFocus(e); if (nclicks == 2 && SwingUtilities2.canEventAccessSystemClipboard(e)) { selectWord(e); } } } } Lines 1–500 of 1914. Load more
/* * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.text; import java.awt.*; import java.awt.event.*; import java.awt.datatransfer.*; import java.beans.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.plaf.*; import java.util.EventListener; import sun.swing.SwingUtilities2; /** * A default implementation of Caret. The caret is rendered as * a vertical line in the color specified by the CaretColor property * of the associated JTextComponent. It can blink at the rate specified * by the BlinkRate property. * <p> * This implementation expects two sources of asynchronous notification. * The timer thread fires asynchronously, and causes the caret to simply * repaint the most recent bounding box. The caret also tracks change * as the document is modified. Typically this will happen on the * event dispatch thread as a result of some mouse or keyboard event. * The caret behavior on both synchronous and asynchronous documents updates * is controlled by <code>UpdatePolicy</code> property. The repaint of the * new caret location will occur on the event thread in any case, as calls to * <code>modelToView</code> are only safe on the event thread. * <p> * The caret acts as a mouse and focus listener on the text component * it has been installed in, and defines the caret semantics based upon * those events. The listener methods can be reimplemented to change the * semantics. * By default, the first mouse button will be used to set focus and caret * position. Dragging the mouse pointer with the first mouse button will * sweep out a selection that is contiguous in the model. If the associated * text component is editable, the caret will become visible when focus * is gained, and invisible when focus is lost. * <p> * The Highlighter bound to the associated text component is used to * render the selection by default. * Selection appearance can be customized by supplying a * painter to use for the highlights. By default a painter is used that * will render a solid color as specified in the associated text component * in the <code>SelectionColor</code> property. This can easily be changed * by reimplementing the * {@link #getSelectionPainter getSelectionPainter} * method. * <p> * A customized caret appearance can be achieved by reimplementing * the paint method. If the paint method is changed, the damage method * should also be reimplemented to cause a repaint for the area needed * to render the caret. The caret extends the Rectangle class which * is used to hold the bounding box for where the caret was last rendered. * This enables the caret to repaint in a thread-safe manner when the * caret moves without making a call to modelToView which is unstable * between model updates and view repair (i.e. the order of delivery * to DocumentListeners is not guaranteed). * <p> * The magic caret position is set to null when the caret position changes. * A timer is used to determine the new location (after the caret change). * When the timer fires, if the magic caret position is still null it is * reset to the current caret position. Any actions that change * the caret position and want the magic caret position to remain the * same, must remember the magic caret position, change the cursor, and * then set the magic caret position to its original value. This has the * benefit that only actions that want the magic caret position to persist * (such as open/down) need to know about it. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @author Timothy Prinzing * @see Caret */ public class DefaultCaret extends Rectangle implements Caret, FocusListener, MouseListener, MouseMotionListener { /** * Indicates that the caret position is to be updated only when * document changes are performed on the Event Dispatching Thread. * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int UPDATE_WHEN_ON_EDT = 0; /** * Indicates that the caret should remain at the same * absolute position in the document regardless of any document * updates, except when the document length becomes less than * the current caret position due to removal. In that case the caret * position is adjusted to the end of the document. * * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int NEVER_UPDATE = 1; /** * Indicates that the caret position is to be <b>always</b> * updated accordingly to the document changes regardless whether * the document updates are performed on the Event Dispatching Thread * or not. * * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int ALWAYS_UPDATE = 2; /** * Constructs a default caret. */ public DefaultCaret() { } /** * Sets the caret movement policy on the document updates. Normally * the caret updates its absolute position within the document on * insertions occurred before or at the caret position and * on removals before the caret position. 'Absolute position' * means here the position relative to the start of the document. * For example if * a character is typed within editable text component it is inserted * at the caret position and the caret moves to the next absolute * position within the document due to insertion and if * <code>BACKSPACE</code> is typed then caret decreases its absolute * position due to removal of a character before it. Sometimes * it may be useful to turn off the caret position updates so that * the caret stays at the same absolute position within the * document position regardless of any document updates. * <p> * The following update policies are allowed: * <ul> * <li><code>NEVER_UPDATE</code>: the caret stays at the same * absolute position in the document regardless of any document * updates, except when document length becomes less than * the current caret position due to removal. In that case caret * position is adjusted to the end of the document. * The caret doesn't try to keep itself visible by scrolling * the associated view when using this policy. </li> * <li><code>ALWAYS_UPDATE</code>: the caret always tracks document * changes. For regular changes it increases its position * if an insertion occurs before or at its current position, * and decreases position if a removal occurs before * its current position. For undo/redo updates it is always * moved to the position where update occurred. The caret * also tries to keep itself visible by calling * <code>adjustVisibility</code> method.</li> * <li><code>UPDATE_WHEN_ON_EDT</code>: acts like <code>ALWAYS_UPDATE</code> * if the document updates are performed on the Event Dispatching Thread * and like <code>NEVER_UPDATE</code> if updates are performed on * other thread. </li> * </ul> <p> * The default property value is <code>UPDATE_WHEN_ON_EDT</code>. * * @param policy one of the following values : <code>UPDATE_WHEN_ON_EDT</code>, * <code>NEVER_UPDATE</code>, <code>ALWAYS_UPDATE</code> * @throws IllegalArgumentException if invalid value is passed * * @see #getUpdatePolicy * @see #adjustVisibility * @see #UPDATE_WHEN_ON_EDT * @see #NEVER_UPDATE * @see #ALWAYS_UPDATE * * @since 1.5 */ public void setUpdatePolicy(int policy) { updatePolicy = policy; } /** * Gets the caret movement policy on document updates. * * @return one of the following values : <code>UPDATE_WHEN_ON_EDT</code>, * <code>NEVER_UPDATE</code>, <code>ALWAYS_UPDATE</code> * * @see #setUpdatePolicy * @see #UPDATE_WHEN_ON_EDT * @see #NEVER_UPDATE * @see #ALWAYS_UPDATE * * @since 1.5 */ public int getUpdatePolicy() { return updatePolicy; } /** * Gets the text editor component that this caret is * is bound to. * * @return the component */ protected final JTextComponent getComponent() { return component; } /** * Cause the caret to be painted. The repaint * area is the bounding box of the caret (i.e. * the caret rectangle or <em>this</em>). * <p> * This method is thread safe, although most Swing methods * are not. Please see * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How * to Use Threads</A> for more information. */ protected final synchronized void repaint() { if (component != null) { component.repaint(x, y, width, height); } } /** * Damages the area surrounding the caret to cause * it to be repainted in a new location. If paint() * is reimplemented, this method should also be * reimplemented. This method should update the * caret bounds (x, y, width, and height). * * @param r the current location of the caret * @see #paint */ protected synchronized void damage(Rectangle r) { if (r != null) { int damageWidth = getCaretWidth(r.height); x = r.x - 4 - (damageWidth >> 1); y = r.y; width = 9 + damageWidth; height = r.height; repaint(); } } /** * Scrolls the associated view (if necessary) to make * the caret visible. Since how this should be done * is somewhat of a policy, this method can be * reimplemented to change the behavior. By default * the scrollRectToVisible method is called on the * associated component. * * @param nloc the new position to scroll to */ protected void adjustVisibility(Rectangle nloc) { if(component == null) { return; } if (SwingUtilities.isEventDispatchThread()) { component.scrollRectToVisible(nloc); } else { SwingUtilities.invokeLater(new SafeScroller(nloc)); } } /** * Gets the painter for the Highlighter. * * @return the painter */ protected Highlighter.HighlightPainter getSelectionPainter() { return DefaultHighlighter.DefaultPainter; } /** * Tries to set the position of the caret from * the coordinates of a mouse event, using viewToModel(). * * @param e the mouse event */ protected void positionCaret(MouseEvent e) { Point pt = new Point(e.getX(), e.getY()); Position.Bias[] biasRet = new Position.Bias[1]; int pos = component.getUI().viewToModel(component, pt, biasRet); if(biasRet[0] == null) biasRet[0] = Position.Bias.Forward; if (pos >= 0) { setDot(pos, biasRet[0]); } } /** * Tries to move the position of the caret from * the coordinates of a mouse event, using viewToModel(). * This will cause a selection if the dot and mark * are different. * * @param e the mouse event */ protected void moveCaret(MouseEvent e) { Point pt = new Point(e.getX(), e.getY()); Position.Bias[] biasRet = new Position.Bias[1]; int pos = component.getUI().viewToModel(component, pt, biasRet); if(biasRet[0] == null) biasRet[0] = Position.Bias.Forward; if (pos >= 0) { moveDot(pos, biasRet[0]); } } // --- FocusListener methods -------------------------- /** * Called when the component containing the caret gains * focus. This is implemented to set the caret to visible * if the component is editable. * * @param e the focus event * @see FocusListener#focusGained */ public void focusGained(FocusEvent e) { if (component.isEnabled()) { if (component.isEditable()) { setVisible(true); } setSelectionVisible(true); } } /** * Called when the component containing the caret loses * focus. This is implemented to set the caret to visibility * to false. * * @param e the focus event * @see FocusListener#focusLost */ public void focusLost(FocusEvent e) { setVisible(false); setSelectionVisible(ownsSelection || e.isTemporary()); } /** * Selects word based on the MouseEvent */ private void selectWord(MouseEvent e) { if (selectedWordEvent != null && selectedWordEvent.getX() == e.getX() && selectedWordEvent.getY() == e.getY()) { //we already done selection for this return; } Action a = null; ActionMap map = getComponent().getActionMap(); if (map != null) { a = map.get(DefaultEditorKit.selectWordAction); } if (a == null) { if (selectWord == null) { selectWord = new DefaultEditorKit.SelectWordAction(); } a = selectWord; } a.actionPerformed(new ActionEvent(getComponent(), ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers())); selectedWordEvent = e; } // --- MouseListener methods ----------------------------------- /** * Called when the mouse is clicked. If the click was generated * from button1, a double click selects a word, * and a triple click the current line. * * @param e the mouse event * @see MouseListener#mouseClicked */ public void mouseClicked(MouseEvent e) { int nclicks = SwingUtilities2.getAdjustedClickCount(getComponent(), e); if (! e.isConsumed()) { if (SwingUtilities.isLeftMouseButton(e)) { // mouse 1 behavior if(nclicks == 1) { selectedWordEvent = null; } else if(nclicks == 2 && SwingUtilities2.canEventAccessSystemClipboard(e)) { selectWord(e); selectedWordEvent = null; } else if(nclicks == 3 && SwingUtilities2.canEventAccessSystemClipboard(e)) { Action a = null; ActionMap map = getComponent().getActionMap(); if (map != null) { a = map.get(DefaultEditorKit.selectLineAction); } if (a == null) { if (selectLine == null) { selectLine = new DefaultEditorKit.SelectLineAction(); } a = selectLine; } a.actionPerformed(new ActionEvent(getComponent(), ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers())); } } else if (SwingUtilities.isMiddleMouseButton(e)) { // mouse 2 behavior if (nclicks == 1 && component.isEditable() && component.isEnabled() && SwingUtilities2.canEventAccessSystemClipboard(e)) { // paste system selection, if it exists JTextComponent c = (JTextComponent) e.getSource(); if (c != null) { try { Toolkit tk = c.getToolkit(); Clipboard buffer = tk.getSystemSelection(); if (buffer != null) { // platform supports system selections, update it. adjustCaret(e); TransferHandler th = c.getTransferHandler(); if (th != null) { Transferable trans = null; try { trans = buffer.getContents(null); } catch (IllegalStateException ise) { // clipboard was unavailable UIManager.getLookAndFeel().provideErrorFeedback(c); } if (trans != null) { th.importData(c, trans); } } adjustFocus(true); } } catch (HeadlessException he) { // do nothing... there is no system clipboard } } } } } } /** * If button 1 is pressed, this is implemented to * request focus on the associated text component, * and to set the caret position. If the shift key is held down, * the caret will be moved, potentially resulting in a selection, * otherwise the * caret position will be set to the new location. If the component * is not enabled, there will be no request for focus. * * @param e the mouse event * @see MouseListener#mousePressed */ public void mousePressed(MouseEvent e) { int nclicks = SwingUtilities2.getAdjustedClickCount(getComponent(), e); if (SwingUtilities.isLeftMouseButton(e)) { if (e.isConsumed()) { shouldHandleRelease = true; } else { shouldHandleRelease = false; adjustCaretAndFocus(e); if (nclicks == 2 && SwingUtilities2.canEventAccessSystemClipboard(e)) { selectWord(e); } } } }