--- /dev/null 2014-07-07 11:17:24.879339622 +0400 +++ new/test/java/awt/event/helpers/lwcomponents/LWButton.java 2014-07-08 15:16:25.000000000 +0400 @@ -0,0 +1,418 @@ +/* + * 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 Button 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.

+ * + * 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)

+ *

    + *
  1. Focus: Indicates that the LWButton has the focus. + *
  2. Mouse Over: Indicates that the mouse is over the component. + *
  3. Mouse Pressed: Indicates that the mouse has been pressed. + *
+ * + * 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 processEvent + // 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 null 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; + } + +}