/*
* Copyright (c) 2009 Kathryn Huxtable and Kenneth Orr.
*
* This file is part of the SeaGlass Pluggable Look and Feel.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id: SeaGlassTextFieldUI.java 1595 2011-08-09 20:33:48Z rosstauscher@gmx.de $
*/
package com.seaglasslookandfeel.ui;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTextFieldUI;
import javax.swing.plaf.synth.ColorType;
import javax.swing.plaf.synth.Region;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthStyle;
import javax.swing.text.AbstractDocument;
import javax.swing.text.Caret;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.View;
import sun.swing.SwingUtilities2;
import com.seaglasslookandfeel.SeaGlassContext;
import com.seaglasslookandfeel.SeaGlassLookAndFeel;
import com.seaglasslookandfeel.SeaGlassRegion;
import com.seaglasslookandfeel.SeaGlassStyle;
import com.seaglasslookandfeel.SeaGlassSynthPainterImpl;
import com.seaglasslookandfeel.component.SeaGlassBorder;
import com.seaglasslookandfeel.state.SearchFieldHasPopupState;
import com.seaglasslookandfeel.state.State;
import com.seaglasslookandfeel.state.TextFieldIsSearchState;
/**
* Sea Glass TextField UI delegate.
*
* <p>Based on SynthTextFieldUI, but we need to set preferred sizes and handle
* search fields.</p>
*/
public class SeaGlassTextFieldUI extends BasicTextFieldUI implements SeaglassUI, FocusListener {
private static final State isSearchField = new TextFieldIsSearchState();
private static final State hasPopupMenu = new SearchFieldHasPopupState();
private TextFieldBorder textFieldBorder;
private MouseAdapter mouseListener;
private boolean isCancelArmed;
private SynthStyle style;
private SynthStyle findStyle;
private SynthStyle cancelStyle;
private String placeholderText;
private Color placeholderColor;
private ActionListener findAction;
private JPopupMenu findPopup;
private ActionListener cancelAction;
private int searchIconWidth;
private int popupIconWidth;
private int cancelIconWidth;
private int searchLeftInnerMargin;
private int searchRightInnerMargin;
/**
* Creates a new SeaGlassTextFieldUI object.
*/
public SeaGlassTextFieldUI() {
super();
}
/**
* Creates a UI for a JTextField.
*
* @param c the text field
*
* @return the UI
*/
public static ComponentUI createUI(JComponent c) {
return new SeaGlassTextFieldUI();
}
/**
* DOCUMENT ME!
*
* @param c DOCUMENT ME!
*/
private void updateStyle(JTextComponent c) {
SeaGlassContext context = getContext(c, ENABLED);
SynthStyle oldStyle = style;
style = SeaGlassLookAndFeel.updateStyle(context, this);
updateSearchStyle(c, context, getPropertyPrefix());
if (style != oldStyle) {
updateStyle(c, context, getPropertyPrefix());
if (oldStyle != null) {
uninstallKeyboardActions();
installKeyboardActions();
}
}
context.dispose();
context = getContext(c, SeaGlassRegion.SEARCH_FIELD_FIND_BUTTON, ENABLED);
findStyle = SeaGlassLookAndFeel.updateStyle(context, this);
context.dispose();
context = getContext(c, SeaGlassRegion.SEARCH_FIELD_CANCEL_BUTTON, ENABLED);
cancelStyle = SeaGlassLookAndFeel.updateStyle(context, this);
context.dispose();
}
/**
* Sea Glass code to support the search JTextField.variant.
*
* @param c the JTextField component.
* @param context the SeaGlassContext.
* @param prefix the control prefix, e.g. "TextField",
* "FormattedTextField", or "PasswordField".
*/
private void updateSearchStyle(JTextComponent c, SeaGlassContext context, String prefix) {
searchIconWidth = 0;
Object o = style.get(context, prefix + ".searchIconWidth");
if (o != null && o instanceof Integer) {
searchIconWidth = (Integer) o;
}
popupIconWidth = 0;
o = style.get(context, prefix + ".popupIconWidth");
if (o != null && o instanceof Integer) {
popupIconWidth = (Integer) o;
}
cancelIconWidth = 0;
o = style.get(context, prefix + ".cancelIconWidth");
if (o != null && o instanceof Integer) {
cancelIconWidth = (Integer) o;
}
searchLeftInnerMargin = 0;
o = style.get(context, prefix + ".searchLeftInnerMargin");
if (o != null && o instanceof Integer) {
searchLeftInnerMargin = (Integer) o;
}
searchRightInnerMargin = 0;
o = style.get(context, prefix + ".searchRightInnerMargin");
if (o != null && o instanceof Integer) {
searchRightInnerMargin = (Integer) o;
}
placeholderColor = Color.GRAY;
o = style.get(context, "placeholderTextColor");
if (o != null && o instanceof Color) {
placeholderColor = (Color) o;
}
Border border = c.getBorder();
if (border == null || border instanceof UIResource && !(border instanceof TextFieldBorder)) {
c.setBorder(createTextFieldBorder(context));
}
if (isSearchField.isInState(c)) {
o = c.getClientProperty("JTextField.Search.PlaceholderText");
if (o != null && o instanceof String) {
placeholderText = (String) o;
} else if (placeholderText != null) {
placeholderText = null;
}
o = c.getClientProperty("JTextField.Search.FindAction");
if (o != null && o instanceof ActionListener) {
if (findAction == null) {
findAction = (ActionListener) o;
}
}
o = c.getClientProperty("JTextField.Search.FindPopup");
if (o != null && o instanceof JPopupMenu) {
if (findPopup == null) {
findPopup = (JPopupMenu) o;
}
}
o = c.getClientProperty("JTextField.Search.CancelAction");
if (o != null && o instanceof ActionListener) {
if (cancelAction == null) {
cancelAction = (ActionListener) o;
}
}
installMouseListeners();
} else {
placeholderText = null;
if (findAction != null) {
findAction = null;
}
if (findPopup != null) {
findPopup = null;
}
if (cancelAction != null) {
cancelAction = null;
}
uninstallMouseListeners();
}
}
/**
* Private method to update styles.
*
* @param c the JTextField component.
* @param context the SeaGlassContext.
* @param prefix the control prefix, e.g. "TextField",
* "FormattedTextField", or "PasswordField".
*/
static void updateStyle(JTextComponent c, SeaGlassContext context, String prefix) {
SeaGlassStyle style = (SeaGlassStyle) context.getStyle();
Color color = c.getCaretColor();
if (color == null || color instanceof UIResource) {
c.setCaretColor((Color) style.get(context, prefix + ".caretForeground"));
}
Color fg = c.getForeground();
if (fg == null || fg instanceof UIResource) {
fg = style.getColorForState(context, ColorType.TEXT_FOREGROUND);
if (fg != null) {
c.setForeground(fg);
}
}
Object ar = style.get(context, prefix + ".caretAspectRatio");
if (ar instanceof Number) {
c.putClientProperty("caretAspectRatio", ar);
}
context.setComponentState(SELECTED | FOCUSED);
Color s = c.getSelectionColor();
if (s == null || s instanceof UIResource) {
c.setSelectionColor(style.getColor(context, ColorType.TEXT_BACKGROUND));
}
Color sfg = c.getSelectedTextColor();
if (sfg == null || sfg instanceof UIResource) {
c.setSelectedTextColor(style.getColor(context, ColorType.TEXT_FOREGROUND));
}
context.setComponentState(DISABLED);
Color dfg = c.getDisabledTextColor();
if (dfg == null || dfg instanceof UIResource) {
c.setDisabledTextColor(style.getColor(context, ColorType.TEXT_FOREGROUND));
}
Insets margin = c.getMargin();
if (margin == null || margin instanceof UIResource) {
margin = (Insets) style.get(context, prefix + ".margin");
if (margin == null) {
// Some places assume margins are non-null.
margin = SeaGlassLookAndFeel.EMPTY_UIRESOURCE_INSETS;
}
c.setMargin(margin);
}
Caret caret = c.getCaret();
if (caret instanceof UIResource) {
Object o = style.get(context, prefix + ".caretBlinkRate");
if (o != null && o instanceof Integer) {
Integer rate = (Integer) o;
caret.setBlinkRate(rate.intValue());
}
}
}
/**
* @see SeaglassUI#getContext(javax.swing.JComponent)
*/
public SeaGlassContext getContext(JComponent c) {
return getContext(c, getComponentState(c));
}
/**
* DOCUMENT ME!
*
* @param c DOCUMENT ME!
* @param state DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private SeaGlassContext getContext(JComponent c, int state) {
return SeaGlassContext.getContext(SeaGlassContext.class, c, SeaGlassLookAndFeel.getRegion(c), style, state);
}
/**
* DOCUMENT ME!
*
* @param c DOCUMENT ME!
* @param region DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private SeaGlassContext getContext(JComponent c, Region region) {
return getContext(c, region, getComponentState(c, region));
}
/**
* DOCUMENT ME!
*
* @param c DOCUMENT ME!
* @param region DOCUMENT ME!
* @param state DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private SeaGlassContext getContext(JComponent c, Region region, int state) {
SynthStyle style = findStyle;
if (region == SeaGlassRegion.SEARCH_FIELD_CANCEL_BUTTON) {
style = cancelStyle;
}
return SeaGlassContext.getContext(SeaGlassContext.class, c, region, style, state);
}
/**
* DOCUMENT ME!
*
* @param c DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private int getComponentState(JComponent c) {
int state = SeaGlassLookAndFeel.getComponentState(c);
return state;
}
/**
* DOCUMENT ME!
*
* @param c DOCUMENT ME!
* @param region DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private int getComponentState(JComponent c, Region region) {
if (region == SeaGlassRegion.SEARCH_FIELD_CANCEL_BUTTON && c.isEnabled()) {
if (((JTextComponent) c).getText().length() == 0) {
return DISABLED;
} else if (isCancelArmed) {
return PRESSED;
}
return ENABLED;
}
return SeaGlassLookAndFeel.getComponentState(c);
}
/**
* @see javax.swing.plaf.basic.BasicTextUI#update(java.awt.Graphics, javax.swing.JComponent)
*/
public void update(Graphics g, JComponent c) {
SeaGlassContext context = getContext(c);
SeaGlassLookAndFeel.update(context, g);
paintBackground(context, g, c);
paint(context, g);
context.dispose();
}
/**
* Paints the interface. This is routed to the paintSafely method under the
* guarantee that the model won't change from the view of this thread while
* it's rendering (if the associated model is derived from
* AbstractDocument). This enables the model to potentially be updated
* asynchronously.
*
* @param context DOCUMENT ME!
* @param g DOCUMENT ME!
*/
protected void paint(SeaGlassContext context, Graphics g) {
JTextComponent c = getComponent();
super.paint(g, c);
}
/**
* DOCUMENT ME!
*
* @param context DOCUMENT ME!
* @param g DOCUMENT ME!
* @param c DOCUMENT ME!
*/
void paintBackground(SeaGlassContext context, Graphics g, JComponent c) {
context.getPainter().paintTextFieldBackground(context, g, 0, 0, c.getWidth(), c.getHeight());
// If necessary, paint the placeholder text.
if (placeholderText != null && ((JTextComponent) c).getText().length() == 0 && !c.hasFocus()) {
paintPlaceholderText(context, g, c);
}
}
/**
* @see SeaglassUI#paintBorder(javax.swing.plaf.synth.SynthContext,
* java.awt.Graphics, int, int, int, int)
*/
public void paintBorder(SynthContext context, Graphics g, int x, int y, int w, int h) {
((SeaGlassContext) context).getPainter().paintTextFieldBorder(context, g, x, y, w, h);
JTextComponent c = getComponent();
if (isSearchField.isInState(c)) {
paintSearchButton(g, c, SeaGlassRegion.SEARCH_FIELD_FIND_BUTTON);
paintSearchButton(g, c, SeaGlassRegion.SEARCH_FIELD_CANCEL_BUTTON);
}
}
/**
* @see javax.swing.plaf.basic.BasicTextUI#paintBackground(java.awt.Graphics)
*/
protected void paintBackground(Graphics g) {
// Overridden to do nothing, all our painting is done from update/paint.
}
/**
* DOCUMENT ME!
*
* @param context DOCUMENT ME!
* @param g DOCUMENT ME!
* @param c DOCUMENT ME!
*/
protected void paintPlaceholderText(SeaGlassContext context, Graphics g, JComponent c) {
g.setColor(placeholderColor);
g.setFont(c.getFont());
Rectangle innerArea = SwingUtilities.calculateInnerArea(c, null);
Rectangle cancelBounds = getCancelButtonBounds();
context.getStyle().getGraphicsUtils(context).paintText(context, g, getPlaceholderText(g, innerArea.width + cancelBounds.width),
innerArea.x,
innerArea.y, -1);
}
/**
* Get the placeholder text, clipped if necessary.
*
* @param g fm the font metrics to compute size with.
* @param availTextWidth the available space to display the title in.
*
* @return the text, clipped to fit the available space.
*/
private String getPlaceholderText(Graphics g, int availTextWidth) {
JTextComponent c = getComponent();
FontMetrics fm = SwingUtilities2.getFontMetrics(c, g);
return SwingUtilities2.clipStringIfNecessary(c, fm, placeholderText, availTextWidth);
}
/**
* DOCUMENT ME!
*
* @param g DOCUMENT ME!
* @param c DOCUMENT ME!
* @param region DOCUMENT ME!
*/
protected void paintSearchButton(Graphics g, JTextComponent c, Region region) {
Rectangle bounds;
if (region == SeaGlassRegion.SEARCH_FIELD_FIND_BUTTON) {
bounds = getFindButtonBounds();
} else {
bounds = getCancelButtonBounds();
}
SeaGlassContext subcontext = getContext(c, region);
SeaGlassLookAndFeel.updateSubregion(subcontext, g, bounds);
SeaGlassSynthPainterImpl painter = (SeaGlassSynthPainterImpl) subcontext.getPainter();
painter.paintSearchButtonForeground(subcontext, g, bounds.x, bounds.y, bounds.width, bounds.height);
subcontext.dispose();
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
protected Rectangle getFindButtonBounds() {
JTextComponent c = getComponent();
final int x = c.getHeight() / 2 - 6;
final int y = c.getHeight() / 2 - 6;
return new Rectangle(x, y, 22, 17);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
protected Rectangle getCancelButtonBounds() {
JTextComponent c = getComponent();
final int x = c.getWidth() - c.getHeight() / 2 - 9;
final int y = c.getHeight() / 2 - 8;
return new Rectangle(x, y, 17, 17);
}
/**
* This method gets called when a bound property is changed on the
* associated JTextComponent. This is a hook which UI implementations may
* change to reflect how the UI displays bound properties of JTextComponent
* subclasses. This is implemented to do nothing (i.e. the response to
* properties in JTextComponent itself are handled prior to calling this
* method).
*
* @param evt the property change event
*/
protected void propertyChange(PropertyChangeEvent evt) {
if (SeaGlassLookAndFeel.shouldUpdateStyle(evt)) {
updateStyle((JTextComponent) evt.getSource());
}
super.propertyChange(evt);
}
/**
* @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent)
*/
public void focusGained(FocusEvent e) {
getComponent().repaint();
}
/**
* @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent)
*/
public void focusLost(FocusEvent e) {
getComponent().repaint();
}
/**
* @see javax.swing.plaf.basic.BasicTextUI#installDefaults()
*/
protected void installDefaults() {
// Installs the text cursor on the component
super.installDefaults();
JTextComponent c = getComponent();
updateStyle(c);
c.addFocusListener(this);
}
/**
* @see javax.swing.plaf.basic.BasicTextUI#uninstallDefaults()
*/
protected void uninstallDefaults() {
JTextComponent c = getComponent();
SeaGlassContext context = getContext(c, ENABLED);
// Remove the search border, if present.
Border border = c.getBorder();
if (border instanceof TextFieldBorder) {
c.setBorder(null);
}
c.putClientProperty("caretAspectRatio", null);
c.removeFocusListener(this);
style.uninstallDefaults(context);
context.dispose();
style = null;
super.uninstallDefaults();
}
/**
* @see javax.swing.plaf.basic.BasicTextUI#uninstallListeners()
*/
@Override
protected void uninstallListeners() {
super.uninstallListeners();
uninstallMouseListeners();
}
/**
* DOCUMENT ME!
*/
private void installMouseListeners() {
if (mouseListener == null) {
mouseListener = createMouseListener();
getComponent().addMouseListener(mouseListener);
getComponent().addMouseMotionListener(mouseListener);
}
}
/**
* DOCUMENT ME!
*/
private void uninstallMouseListeners() {
if (mouseListener != null) {
getComponent().removeMouseListener(mouseListener);
getComponent().removeMouseMotionListener(mouseListener);
mouseListener = null;
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
protected MouseAdapter createMouseListener() {
if (mouseListener == null) {
mouseListener = new MouseButtonListener();
}
return mouseListener;
}
/**
* @see javax.swing.plaf.basic.BasicTextUI#installUI(javax.swing.JComponent)
*/
public void installUI(JComponent c) {
super.installUI(c);
updateStyle((JTextComponent) c);
}
/**
* DOCUMENT ME!
*
* @param context DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
protected TextFieldBorder createTextFieldBorder(SeaGlassContext context) {
if (textFieldBorder == null) {
textFieldBorder = new TextFieldBorder(this, context.getStyle().getInsets(context, null));
}
return textFieldBorder;
}
/**
* @see javax.swing.plaf.basic.BasicTextUI#getPreferredSize(javax.swing.JComponent)
*/
public Dimension getPreferredSize(JComponent c) {
// The following code has been derived from BasicTextUI.
Document doc = ((JTextComponent) c).getDocument();
Insets i = c.getInsets();
Dimension d = c.getSize();
View rootView = getRootView((JTextComponent) c);
if (doc instanceof AbstractDocument) {
((AbstractDocument) doc).readLock();
}
try {
if ((d.width > (i.left + i.right)) && (d.height > (i.top + i.bottom))) {
rootView.setSize(d.width - i.left - i.right, d.height - i.top - i.bottom);
} else if (d.width == 0 && d.height == 0) {
// Probably haven't been layed out yet, force some sort of
// initial sizing.
rootView.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
d.width = (int) Math.min((long) rootView.getPreferredSpan(View.X_AXIS) + (long) i.left + (long) i.right, Integer.MAX_VALUE);
d.height = (int) Math.min((long) rootView.getPreferredSpan(View.Y_AXIS) + (long) i.top + (long) i.bottom, Integer.MAX_VALUE);
} finally {
if (doc instanceof AbstractDocument) {
((AbstractDocument) doc).readUnlock();
}
}
// Fix: The preferred width is always two pixels too small on a Mac.
d.width += 2;
// We'd like our heights to be odd by default.
if ((d.height & 1) == 0) {
d.height--;
}
return d;
}
/**
* DOCUMENT ME!
*/
private void doFind() {
if (findAction != null) {
fireAction(findAction);
}
doPopup();
}
/**
* DOCUMENT ME!
*/
private void doCancel() {
// Erase the text in the search field.
getComponent().setText("");
if (cancelAction != null) {
fireAction(cancelAction);
}
}
/**
* DOCUMENT ME!
*/
private void doPopup() {
if (findPopup != null) {
JTextComponent c = getComponent();
findPopup.pack();
// The "-1" just snugs us up a bit under the text field.
findPopup.show(c, 0, c.getHeight() - 1);
// Set focus back to the text field.
// TODO Fix caret positioning, selection, etc.
c.requestFocusInWindow();
}
}
/**
* DOCUMENT ME!
*
* @param action DOCUMENT ME!
*/
protected void fireAction(ActionListener action) {
int modifiers = 0;
AWTEvent currentEvent = EventQueue.getCurrentEvent();
if (currentEvent instanceof InputEvent) {
modifiers = ((InputEvent) currentEvent).getModifiers();
} else if (currentEvent instanceof ActionEvent) {
modifiers = ((ActionEvent) currentEvent).getModifiers();
}
ActionEvent e = new ActionEvent(getComponent(), ActionEvent.ACTION_PERFORMED, getComponent().getText(),
EventQueue.getMostRecentEventTime(), modifiers);
action.actionPerformed(e);
}
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision$, $Date$
*/
protected class TextFieldBorder extends SeaGlassBorder {
private static final long serialVersionUID = -3475926670707905862L;
/**
* Creates a new TextFieldBorder object.
*
* @param ui DOCUMENT ME!
* @param insets DOCUMENT ME!
*/
public TextFieldBorder(SeaglassUI ui, Insets insets) {
super(ui, insets);
}
/**
* Reinitialize the insets parameter with this Border's current Insets.
*
* @param c the component for which this border insets value
* applies
* @param insets the object to be reinitialized
*
* @return DOCUMENT ME!
*/
public Insets getBorderInsets(Component c, Insets insets) {
if (insets == null) {
insets = new Insets(0, 0, 0, 0);
}
super.getBorderInsets(c, insets);
if (c instanceof JComponent && isSearchField.isInState((JComponent) c)) {
insets.left += searchIconWidth + searchLeftInnerMargin;
if (hasPopupMenu.isInState((JComponent) c)) {
insets.left += popupIconWidth;
}
insets.right += cancelIconWidth + searchRightInnerMargin;
}
return insets;
}
}
/**
* Track mouse clicks and moves.
*/
protected class MouseButtonListener extends MouseAdapter {
/** DOCUMENT ME! */
protected transient int currentMouseX;
/** DOCUMENT ME! */
protected transient int currentMouseY;
/**
* Creates a new MouseButtonListener object.
*/
public MouseButtonListener() {
isCancelArmed = false;
}
/**
* @see java.awt.event.MouseAdapter#mouseReleased(java.awt.event.MouseEvent)
*/
public void mouseReleased(MouseEvent e) {
if (isCancelArmed) {
isCancelArmed = false;
if (isOverCancelButton()) {
doCancel();
}
getComponent().repaint();
}
}
/**
* @see java.awt.event.MouseAdapter#mouseDragged(java.awt.event.MouseEvent)
*/
public void mouseDragged(MouseEvent e) {
currentMouseX = e.getX();
currentMouseY = e.getY();
if (isCancelArmed && !isOverCancelButton()) {
isCancelArmed = false;
getComponent().repaint();
}
}
/**
* @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
*/
public void mousePressed(MouseEvent e) {
if (!SwingUtilities.isLeftMouseButton(e) || !getComponent().isEnabled()) {
return;
}
currentMouseX = e.getX();
currentMouseY = e.getY();
if (isOverFindButton()) {
doFind();
}
if (isOverCancelButton()) {
isCancelArmed = true;
getComponent().repaint();
} else if (isCancelArmed) {
isCancelArmed = false;
getComponent().repaint();
}
}
/**
* {@inheritDoc}
*/
@Override
public void mouseMoved(MouseEvent e) {
currentMouseX = e.getX();
currentMouseY = e.getY();
Cursor cursorToUse = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
if (isOverCancelButton() || isOverFindButton()) {
cursorToUse = Cursor.getDefaultCursor();
}
JComponent c = (JComponent) e.getSource();
if (!cursorToUse.equals(c.getCursor())) {
c.setCursor(cursorToUse);
}
super.mouseMoved(e);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private boolean isOverFindButton() {
return getFindButtonBounds().contains(currentMouseX, currentMouseY);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isOverCancelButton() {
return getCancelButtonBounds().contains(currentMouseX, currentMouseY);
}
}
}