| /* |
| * 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; |
| } |
| |
| } |