Files
EMARS/mars/venus/RepeatButton.java
T
adolphenom 0da1c5dcca Source code of MARS Assembler
First commit of the 4.5 version (latest version available)
2014-12-21 12:49:28 +01:00

339 lines
8.6 KiB
Java

package mars.venus;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;
///////////////////////////// CREDIT /////////////////////////////////////
// http://forums.sun.com/thread.jspa?threadID=499183&messageID=2505646
// bsampieri, 4 March 2004
// Java Developer Forum, Useful Code of the Day: Button Fires Events While Held
// Adopted/adapted by DPS 20 July 2008
//
// This is NOT one of the MARS buttons! It is a subclass of JButton that can
// be used to create buttons that fire events after being held down for a
// specified period of time and at a specified rate.
/**
* <code>RepeatButton</code> is a <code>JButton</code> which contains a timer
* for firing events while the button is held down. There is a default
* initial delay of 300ms before the first event is fired and a 60ms delay
* between subsequent events. When the user holds the button down and moves
* the mouse out from over the button, the timer stops, but if the user moves
* the mouse back over the button without having released the mouse button,
* the timer starts up again at the same delay rate. If the enabled state is
* changed while the timer is active, it will be stopped.
*
* NOTE: The normal button behavior is that the action event is fired after
* the button is released. It may be important to konw then that this is
* still the case. So in effect, listeners will get 1 more event then what
* the internal timer fires. It's not a "bug", per se, just something to be
* aware of. There seems to be no way to suppress the final event from
* firing anyway, except to process all ActionListeners internally. But
* realistically, it probably doesn't matter.
*/
public class RepeatButton extends JButton
implements ActionListener, MouseListener {
/**
* The pressed state for this button.
*/
private boolean pressed = false;
/**
* Flag to indicate that the button should fire events when held.
* If false, the button is effectively a plain old JButton, but
* there may be times when this feature might wish to be disabled.
*/
private boolean repeatEnabled = true;
/**
* The hold-down timer for this button.
*/
private Timer timer = null;
/**
* The initial delay for this button. Hold-down time before first
* timer firing. In milliseconds.
*/
private int initialDelay = 300;
/**
* The delay between timer firings for this button once the delay
* period is past. In milliseconds.
*/
private int delay = 60;
/**
* Holder of the modifiers used when the mouse pressed the button.
* This is used for subsequently fired action events. This may change
* after mouse pressed if the user moves the mouse out, releases a key
* and then moves the mouse back in.
*/
private int modifiers = 0;
/**
* Creates a button with no set text or icon.
*/
public RepeatButton() {
super();
init();
}
/**
* Creates a button where properties are taken from the Action supplied.
*
* @param a the button action
*/
public RepeatButton(Action a) {
super(a);
init();
}
/**
* Creates a button with an icon.
*
* @param icon the button icon
*/
public RepeatButton(Icon icon) {
super(icon);
init();
}
/**
* Creates a button with text.
*
* @param text the button text
*/
public RepeatButton(String text) {
super(text);
init();
}
/**
* Creates a button with initial text and an icon.
*
* @param text the button text
* @param icon the button icon
*/
public RepeatButton(String text, Icon icon) {
super(text, icon);
init();
}
/**
* Initializes the button.
*/
private void init() {
this.addMouseListener(this);
// initialize timers for button holding...
this.timer = new Timer(this.delay, this);
this.timer.setRepeats(true);
}
/**
* Gets the delay for the timer of this button.
*
* @return the delay
*/
public int getDelay() {
return this.delay;
}
/**
* Set the delay for the timer of this button.
*
* @param d the delay
*/
public void setDelay(int d) {
this.delay = d;
}
/**
* Gets the initial delay for the timer of this button.
*
* @return the initial delay
*/
public int getInitialDelay() {
return this.initialDelay;
}
/**
* Sets the initial delay for the timer of this button.
*
* @param d the initial delay
*/
public void setInitialDelay(int d) {
this.initialDelay = d;
}
/**
* Checks if the button should fire events when held. If false, the
* button is effectively a plain old JButton, but there may be times
* when this feature might wish to be disabled.
*
* @return if true, the button should fire events when held
*/
public boolean isRepeatEnabled() {
return this.repeatEnabled;
}
/**
* Sets if the button should fire events when held. If false, the
* button is effectively a plain old JButton, but there may be times
* when this feature might wish to be disabled. If false, it will
* also stop the timer if it's running.
*
* @param en if true, the button should fire events when held
*/
public void setRepeatEnabled(boolean en) {
if(!en) {
this.pressed = false;
if(timer.isRunning()) {
timer.stop();
}
}
this.repeatEnabled = en;
}
/**
* Sets the enabled state of this button. Overridden to stop the timer
* if it's running.
*
* @param en if true, enables the button
*/
public void setEnabled(boolean en) {
if(en != super.isEnabled()) {
this.pressed = false;
if(timer.isRunning()) {
timer.stop();
}
}
super.setEnabled(en);
}
/**
* Handle action events. OVERRIDE THIS IN SUBCLASS!
*
* @param ae the action event
*/
public void actionPerformed(ActionEvent ae) {
// process events only from this components
if(ae.getSource() == this.timer) {
ActionEvent event = new ActionEvent(
this, ActionEvent.ACTION_PERFORMED,
super.getActionCommand(), this.modifiers);
super.fireActionPerformed(event);
}
// testing code...
else if(testing && ae.getSource() == this) {
System.out.println(ae.getActionCommand());
}
}
/**
* Handle mouse clicked events.
*
* @param me the mouse event
*/
public void mouseClicked(MouseEvent me) {
// process events only from this components
if(me.getSource() == this) {
this.pressed = false;
if(this.timer.isRunning()) {
this.timer.stop();
}
}
}
/**
* Handle mouse pressed events.
*
* @param me the mouse event
*/
public void mousePressed(MouseEvent me) {
// process events only from this components
if(me.getSource() == this && this.isEnabled() && this.isRepeatEnabled()) {
this.pressed = true;
if(!this.timer.isRunning()) {
this.modifiers = me.getModifiers();
this.timer.setInitialDelay(this.initialDelay);
this.timer.start();
}
}
}
/**
* Handle mouse released events.
*
* @param me the mouse event
*/
public void mouseReleased(MouseEvent me) {
// process events only from this components
if(me.getSource() == this) {
this.pressed = false;
if(this.timer.isRunning()) {
this.timer.stop();
}
}
}
/**
* Handle mouse entered events.
*
* @param me the mouse event
*/
public void mouseEntered(MouseEvent me) {
// process events only from this components
if(me.getSource() == this && this.isEnabled() && this.isRepeatEnabled()) {
if(this.pressed && !this.timer.isRunning()) {
this.modifiers = me.getModifiers();
this.timer.setInitialDelay(this.delay);
this.timer.start();
}
}
}
/**
* Handle mouse exited events.
*
* @param me the mouse event
*/
public void mouseExited(MouseEvent me) {
// process events only from this components
if(me.getSource() == this) {
if(this.timer.isRunning()) {
this.timer.stop();
}
}
}
/**
* Testing flag. Set in main method.
*/
private static boolean testing = false;
/**
* Main method, for testing. Creates a frame with both styles of menu.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
testing = true;
JFrame f = new JFrame("RepeatButton Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
RepeatButton b = new RepeatButton("hold me");
b.setActionCommand("test");
b.addActionListener(b);
p.add(b);
f.getContentPane().add(p);
f.pack();
f.setVisible(true);
}
}