/*
* Copyright (c) 2002-2015, JIDE Software Inc. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package jidefx.utils;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.ButtonBase;
import javafx.scene.input.MouseEvent;
import javafx.util.Duration;
/**
* {@code AutoRepeatButtonUtils} is a utility class which can make a button automatically trigger action events
* continuously. To enable this feature on any button, just call AutoRepeatButtonUtils.install(button) or
* AutoRepeatButtonUtils.install(button, initialDelay, interval).
*/
public class AutoRepeatButtonUtils {
public final static String AUTO_REPEAT = "AutoRepeat"; //NON-NLS
public final static String CLIENT_PROPERTY_AUTO_REPEAT = "AutoRepeat.AutoRepeatButtonUtils"; //NON-NLS
public final static Duration DEFAULT_DELAY = Duration.millis(100);
public final static Duration DEFAULT_INITIAL_DELAY = Duration.millis(500);
private Timeline _timer = null;
private ButtonBase _button;
private EventHandler<MouseEvent> _mouseEventEventHandler;
/**
* Enable auto-repeat feature on the button. By default, it will delay for 500 ms and then repeat every 50 ms.
*
* @param button the button.
*/
public static void install(ButtonBase button) {
uninstall(button);
new AutoRepeatButtonUtils().installListeners(button, DEFAULT_INITIAL_DELAY, DEFAULT_DELAY);
}
/**
* Enable auto-repeat feature on the button.
*
* @param button the button.
* @param initialDelay the initial delay. It is from the time mouse is pressed to the first action event.
* @param interval the interval between action events.
*/
public static void install(ButtonBase button, Duration initialDelay, Duration interval) {
uninstall(button);
new AutoRepeatButtonUtils().installListeners(button, initialDelay, interval);
}
/**
* Disabled the auto-repeat feature on the button which called install before.
*
* @param button the button that has auto-repeat feature.
*/
public static void uninstall(ButtonBase button) {
Object clientProperty = button.getProperties().get(CLIENT_PROPERTY_AUTO_REPEAT);
if (clientProperty instanceof AutoRepeatButtonUtils) {
((AutoRepeatButtonUtils) clientProperty).uninstallListeners();
}
}
protected void installListeners(ButtonBase button, Duration initialDelay, Duration interval) {
_button = button;
button.getProperties().put(CLIENT_PROPERTY_AUTO_REPEAT, this);
if (_mouseEventEventHandler == null) {
_mouseEventEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.getEventType() == MouseEvent.MOUSE_PRESSED) {
_timer.play();
}
else if (event.getEventType() == MouseEvent.MOUSE_EXITED) {
_timer.stop();
}
else if (event.getEventType() == MouseEvent.MOUSE_RELEASED) {
_timer.stop();
}
}
};
}
button.addEventHandler(MouseEvent.ANY, _mouseEventEventHandler);
_timer = new Timeline(new KeyFrame(interval, new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
EventHandler<ActionEvent> action = _button.getOnAction();
if (action != null) action.handle(new ActionEvent());
}
}));
_timer.setDelay(initialDelay);
_timer.setCycleCount(Animation.INDEFINITE);
}
protected void uninstallListeners() {
if (_button != null) {
_button.getProperties().put(CLIENT_PROPERTY_AUTO_REPEAT, null);
if (_mouseEventEventHandler != null) _button.removeEventHandler(MouseEvent.ANY, _mouseEventEventHandler);
_button = null;
}
if (_timer != null) {
_timer.stop();
_timer = null;
}
}
}