3789983e89
Reviewed-by: darcy, ihse
419 lines
12 KiB
Java
419 lines
12 KiB
Java
/*
|
|
* Copyright (c) 2001, 2014, 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.
|
|
*
|
|
* 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 test.java.awt.event.helpers.lwcomponents;
|
|
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
|
|
/**
|
|
* Lightweight <i>Button</i> component with some nice features. This
|
|
* component provides the capabilities of Buttons, namely that you it
|
|
* displays a label string and, when clicked, causes the
|
|
* ActionListener method to be called.<p>
|
|
*
|
|
* The look of the button is a little unusual. There are three
|
|
* rectangles drawn at the border that indicate various states
|
|
* of the button. These are (listed from outside in)<p>
|
|
* <ol>
|
|
* <li><b>Focus</b>: Indicates that the LWButton has the focus.
|
|
* <li><b>Mouse Over</b>: Indicates that the mouse is over the component.
|
|
* <li><b>Mouse Pressed</b>: Indicates that the mouse has been pressed.
|
|
* </ol>
|
|
*
|
|
* In addition, when the button has been activated (mouse clicked or
|
|
* via keyboard activation) the button flashes briefly.
|
|
*/
|
|
|
|
public class LWButton extends LWComponent {
|
|
|
|
/*
|
|
* The button's Label.
|
|
* If Label is not specified it will default to "".
|
|
* @serial
|
|
* @see getLabel()
|
|
* @see setLabel()
|
|
*/
|
|
private String label;
|
|
private boolean isInClick = false;
|
|
|
|
private static final String base = "LWButton";
|
|
private static int nameCounter = 0;
|
|
|
|
private transient ActionListener actionListener;
|
|
|
|
/*
|
|
* The action to be performaed once a button has been
|
|
* pressed.
|
|
* actionCommand can be null.
|
|
* @serial
|
|
* @see getActionCommand()
|
|
* @see setActionCommand()
|
|
*/
|
|
String actionCommand;
|
|
|
|
Color colMousePressed;
|
|
|
|
public LWButton() { this(""); }
|
|
|
|
public LWButton(String label) {
|
|
this(label, Color.red, Color.green, Color.white);
|
|
}
|
|
|
|
/**
|
|
* Initialize the LWButton, fully specifying all parameters.
|
|
* @param label The string to display.
|
|
* @param fgnd The color to draw the label in.
|
|
* @param bkgnd The color of the button itself.
|
|
* @param mousePressed The Color of the MousePressed rectangle.
|
|
*/
|
|
public LWButton(String label, Color fgnd, Color bkgnd, Color mousePressed) {
|
|
super();
|
|
this.label = label;
|
|
setBackground(fgnd);
|
|
setForeground(bkgnd);
|
|
colMousePressed = mousePressed;
|
|
setName(makeComponentName());
|
|
|
|
enableEvents( AWTEvent.MOUSE_EVENT_MASK
|
|
| AWTEvent.KEY_EVENT_MASK
|
|
| AWTEvent.ACTION_EVENT_MASK);
|
|
setEnabled(true);
|
|
}
|
|
|
|
/**
|
|
* Make the component flash briefly.
|
|
*/
|
|
public void flash() {
|
|
isInClick = true;
|
|
repaint();
|
|
|
|
class unClicker implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
try { Thread.sleep(100); } catch (InterruptedException ee) {}
|
|
isInClick = false;
|
|
repaint();
|
|
}
|
|
}
|
|
try {
|
|
unClicker uc = new unClicker();
|
|
new Thread(uc).start();
|
|
} catch (Exception e) {
|
|
// In case we're in an applet and the security has not been
|
|
// turned off (in which case we can't start a new thread)
|
|
// we can catch that and set the flag back to how it should be.
|
|
isInClick = false;
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the MousePressed color (the color shown in the MousePressed rectangle
|
|
* when the mouse is over the component).
|
|
* @param c The color of the MousePressed rectangle.
|
|
*/
|
|
public void setMousePressedColor(Color c) { colMousePressed = c; }
|
|
|
|
/**
|
|
* Get the MousePressed color.
|
|
* @return The color of the MousePressed rectangle.
|
|
*/
|
|
public Color getMousePressedColor() { return colMousePressed; }
|
|
|
|
/**
|
|
* Used to dispatch out the ActionEvent for a corresponding InputEvent.
|
|
* @param e The InputEvent that is causing the ActionEvent dispatch.
|
|
*/
|
|
private void sendActionEvent(InputEvent e) {
|
|
|
|
int modifiers = e.getModifiers();
|
|
int aModifiers = 0;
|
|
|
|
if ((modifiers & MouseEvent.SHIFT_MASK) != 0) {
|
|
aModifiers |= ActionEvent.SHIFT_MASK;
|
|
}
|
|
if ((modifiers & MouseEvent.CTRL_MASK) != 0) {
|
|
aModifiers |= ActionEvent.CTRL_MASK;
|
|
}
|
|
if ((modifiers & MouseEvent.META_MASK) != 0) {
|
|
aModifiers |= ActionEvent.META_MASK;
|
|
}
|
|
if ((modifiers & MouseEvent.ALT_MASK) != 0) {
|
|
aModifiers |= ActionEvent.ALT_MASK;
|
|
}
|
|
|
|
ActionEvent ae = new ActionEvent(this,
|
|
ActionEvent.ACTION_PERFORMED,
|
|
actionCommand,
|
|
aModifiers);
|
|
// XXX: What's the right way to send out the ActionEvent?
|
|
// My assumption was to put it into the system event queue
|
|
// and the it will be dispatched back into <i>processEvent</i>
|
|
// for us. However this doesn't happen...?
|
|
if (actionListener != null) {
|
|
actionListener.actionPerformed(ae);
|
|
}
|
|
//Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ae);
|
|
}
|
|
|
|
/**
|
|
* Set whether the component is enabled ({@code true}) or not.
|
|
* @param enabled If {@code true}, the component is to be enabled.
|
|
*/
|
|
@Override
|
|
public void setEnabled(boolean enabled) {
|
|
super.setEnabled(enabled);
|
|
|
|
if (enabled) {
|
|
enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
|
|
} else {
|
|
disableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
|
|
}
|
|
repaint(1);
|
|
}
|
|
|
|
/**
|
|
* Indicates that LWButton component can receive focus.
|
|
* @return {@code true} if the LWButton component can receive focus
|
|
*/
|
|
@Override
|
|
public boolean isFocusTraversable() { return true; }
|
|
|
|
/**
|
|
* Construct a name for this component. Called by getName() when the
|
|
* name is null.
|
|
*/
|
|
String makeComponentName() {
|
|
synchronized (getClass()) {
|
|
return base + nameCounter++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle painting the enabled version of the component.
|
|
*
|
|
* ASSUMES: g.color may be changed
|
|
*/
|
|
@Override
|
|
public void paint(Graphics g) {
|
|
|
|
super.paint(g);
|
|
restrictGraphicsToClientArea(g);
|
|
|
|
Dimension dim = getClientSize();
|
|
|
|
int s = Math.min(dim.width - 1, dim.height - 1);
|
|
|
|
if (isInClick) {
|
|
g.setColor(Color.white);
|
|
} else {
|
|
g.setColor(getBackground());
|
|
}
|
|
|
|
// In jdk 1.2 (pre-release) there was a bug using clearRect
|
|
// to paint the background of a lightweight.
|
|
//g.clearRect(loc.x, loc.y, dim.width, dim.height);
|
|
g.fillRect(0, 0, dim.width, dim.height);
|
|
|
|
if (mouseB1Pressed) {
|
|
g.setColor(colMousePressed);
|
|
//LWComponent.traceMsg("paint mousePressed " + this.toString());
|
|
g.drawRect(1, 1, dim.width - 3, dim.height - 3);
|
|
}
|
|
|
|
Font f = getFont();
|
|
if (f != null) {
|
|
FontMetrics fm = getFontMetrics(f);
|
|
g.setColor(getForeground());
|
|
g.drawString(label,
|
|
s/2 - fm.stringWidth(label)/2,
|
|
s/2 + fm.getMaxDescent());
|
|
}
|
|
|
|
unrestrictGraphicsFromClientArea(g);
|
|
}
|
|
|
|
@Override
|
|
public Dimension getPreferredSize() {
|
|
Font f = getFont();
|
|
if (f != null) {
|
|
FontMetrics fm = getFontMetrics(f);
|
|
int max = Math.max(fm.stringWidth(label) + 40, fm.getHeight() + 40);
|
|
return new Dimension(max, max);
|
|
} else {
|
|
return new Dimension(100, 100);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Dimension getMinimumSize() {
|
|
return getPreferredSize();
|
|
}
|
|
|
|
/**
|
|
* Get the text displayed in the LWButton.
|
|
* @return the text displayed in the LWButton
|
|
*/
|
|
public String getText() { return label; }
|
|
|
|
/**
|
|
* Set the text displayed in the LWButton.
|
|
* @param s The text to be displayed.
|
|
*/
|
|
public void setText(String s) {
|
|
Font f = getFont();
|
|
int oWidth = 0;
|
|
int oHeight = 0;
|
|
int nWidth = 0;
|
|
int nHeight = 0;
|
|
int invalidated = 0;
|
|
FontMetrics fm = null;
|
|
|
|
if (f != null) {
|
|
fm = getFontMetrics(f);
|
|
oWidth = fm.stringWidth(label);
|
|
oHeight = fm.getHeight();
|
|
}
|
|
|
|
this.label = s;
|
|
|
|
if (f != null) {
|
|
nWidth = fm.stringWidth(label);
|
|
nHeight = fm.getHeight();
|
|
|
|
if ((nWidth > oWidth) || (nHeight > oHeight)) {
|
|
invalidate();
|
|
invalidated = 1;
|
|
}
|
|
}
|
|
|
|
if (invalidated == 0) {
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the command name for the action event fired
|
|
* by this button. By default this action command is
|
|
* set to match the label of the button.
|
|
* @param command A string used to set the button's
|
|
* action command.
|
|
* If the string is <code>null</code> then the action command
|
|
* is set to match the label of the button.
|
|
* @see java.awt.event.ActionEvent
|
|
* @since JDK1.1
|
|
*/
|
|
public void setActionCommand(String command) {
|
|
actionCommand = command;
|
|
}
|
|
|
|
/**
|
|
* Returns the command name of the action event fired by this button.
|
|
* If the command name is {@code null} (default) then this method
|
|
* returns the label of the button.
|
|
*
|
|
* @return the command name of the action event fired by this button
|
|
* or the label of the button (in case of {@code null})
|
|
*/
|
|
public String getActionCommand() {
|
|
return (actionCommand == null? label : actionCommand);
|
|
}
|
|
|
|
/**
|
|
* Add the specified action listener to receive action events from
|
|
* this button. Action events occur when a user presses or releases
|
|
* the mouse over this button.
|
|
* @param l the action listener.
|
|
* @see java.awt.event.ActionListener
|
|
* @see #removeActionListener
|
|
* @since JDK1.1
|
|
*/
|
|
public synchronized void addActionListener(ActionListener l) {
|
|
actionListener = AWTEventMulticaster.add(actionListener, l);
|
|
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
|
|
}
|
|
|
|
/**
|
|
* Remove the specified action listener so that it no longer
|
|
* receives action events from this button. Action events occur
|
|
* when a user presses or releases the mouse over this button.
|
|
* @param l the action listener.
|
|
* @see java.awt.event.ActionListener
|
|
* @see #addActionListener
|
|
* @since JDK1.1
|
|
*/
|
|
public synchronized void removeActionListener(ActionListener l) {
|
|
actionListener = AWTEventMulticaster.remove(actionListener, l);
|
|
}
|
|
|
|
@Override
|
|
protected void processKeyEvent(KeyEvent e) {
|
|
super.processKeyEvent(e);
|
|
if (!isEnabled()) { return; }
|
|
switch(e.getID()) {
|
|
case KeyEvent.KEY_TYPED:
|
|
switch (e.getKeyCode()) {
|
|
case KeyEvent.VK_ENTER:
|
|
case KeyEvent.VK_SPACE:
|
|
flash();
|
|
sendActionEvent(e);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void processMouseEvent(MouseEvent e) {
|
|
super.processMouseEvent(e);
|
|
if (!isEnabled()) { return; }
|
|
switch(e.getID()) {
|
|
case MouseEvent.MOUSE_PRESSED:
|
|
requestFocus();
|
|
repaint();
|
|
break;
|
|
case MouseEvent.MOUSE_RELEASED:
|
|
repaint();
|
|
break;
|
|
case MouseEvent.MOUSE_CLICKED:
|
|
if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) {
|
|
flash();
|
|
sendActionEvent(e);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the parameter string representing the state of this
|
|
* button. This string is useful for debugging.
|
|
* @return the parameter string of this button.
|
|
*/
|
|
@Override
|
|
protected String paramString() {
|
|
return super.paramString() + ", label = " + label;
|
|
}
|
|
|
|
}
|