blob: 866844e1ce70d47c2b5d6222b39e3773c46d22df [file] [log] [blame]
/*
* 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;
}
}