/* Part of the G4P library for Processing http://www.lagers.org.uk/g4p/index.html http://sourceforge.net/projects/g4p/files/?source=navbar Copyright (c) 2012 Peter Lager This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package automenta.vivisect.gui; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.Method; import javax.swing.Timer; import processing.core.PApplet; /** * This class is used to trigger events at user defined intervals. The event will * call a user defined method/function. The only restriction is that the method * used has a single parameter of type GTimer and returns void eg <br> * <pre> * void fireBall(GTimer timer){ ... } * </pre><br> * * Each timer object must have its own handler * * It has no visible GUI representation so will not appear in the GUI. * * @author Peter Lager * */ public class GTimer implements GConstantsInternal { /* This must be set by the constructor */ protected PApplet app; /* The object to handle the event */ protected Object eventHandlerObject = null; /* The method in eventHandlerObject to execute */ protected Method eventHandlerMethod = null; /* the name of the method to handle the event */ protected String eventHandlerMethodName; // The number of repeats i.e. events to be fired. protected int nrepeats = -1; protected Timer timer = null; /** * Create the GTimer object with this ctor. * * 'methodName' is the method/function to be called every 'interval' * milliseconds. 'obj' is the object that contains the method/function * 'methodName' * * For most users 'methodName' will be in their main sketch so this * parameter has the same value as 'theApplet' * * @param theApplet a reference to the PApplet object (invariably <b>this</b>) * @param obj the object that has the method to be executed (likely to be <b>this</b>) * @param methodName the name of the method to be called by the timer * @param delay the initial delay and the time (in millisecs) between function calls */ public GTimer(PApplet theApplet, Object obj, String methodName, int delay){ this(theApplet, obj, methodName, delay, delay); } /** * Create the GTimer object with this ctor. * * 'methodName' is the method/function to be called every 'interval' * milliseconds. 'obj' is the object that contains the method/function * 'methodName' * * For most users 'methodName' will be in their main sketch so this * parameter has the same value as 'theApplet' * * @param theApplet a reference to the PApplet object (invariably <b>this</b>) * @param obj the object that has the method to be executed (likely to be <b>this</b>) * @param methodName the name of the method to be called by the timer * @param delay the time (in millisecs) between function calls * @param initDelay the initial delay (in millisecs) */ public GTimer(PApplet theApplet, Object obj, String methodName, int delay, int initDelay){ app = theApplet; createEventHandler(obj, methodName); // If we have something to handle the event then create the Timer if(eventHandlerObject != null){ timer = new Timer(delay, new ActionListener(){ public void actionPerformed(ActionEvent e) { fireEvent(); } }); timer.setInitialDelay(initDelay); timer.setDelay(delay); timer.stop(); } } /** * See if 'obj' has a method called 'methodName' that has a single parameter of type * GTimer and if so keep a reference to it. * * @param obj * @param methodName */ protected void createEventHandler(Object handlerObj, String methodName){ try{ eventHandlerMethod = handlerObj.getClass().getMethod(methodName, new Class<?>[] { GTimer.class } ); eventHandlerObject = handlerObj; eventHandlerMethodName = methodName; } catch (Exception e) { GMessenger.message(NONEXISTANT, new Object[] {this, methodName, new Class<?>[] { GTimer.class }}); eventHandlerObject = null; } } /** * Attempt to fire an event for this timer. This will call the * method/function defined in the ctor. */ protected void fireEvent(){ if(eventHandlerMethod != null){ try { eventHandlerMethod.invoke(eventHandlerObject, this); if(--nrepeats == 0) stop(); } catch (Exception e) { GMessenger.message(EXCP_IN_HANDLER, new Object[] {eventHandlerObject, eventHandlerMethodName, e } ); System.out.println("Disabling " + eventHandlerMethod.getName() + " due to an unknown error"); eventHandlerMethod = null; eventHandlerObject = null; } } } /** * Start the timer (call the method forever) */ public void start(){ this.nrepeats = -1; if(timer != null) timer.start(); } /** * Start the timer and call the method for the number of * times indicated by nrepeats * If nrepeats is <=0 then repeat forever * * @param nrepeats */ public void start(int nrepeats){ this.nrepeats = nrepeats; if(timer != null) timer.start(); } /** * Stop the timer (can be restarted with start() method) */ public void stop(){ if(timer != null) timer.stop(); } /** * Is the timer running? * @return true if running */ public boolean isRunning(){ if(timer != null) return timer.isRunning(); else return false; } /** * Set the interval between events * @param interval delay between events in milliseconds */ public void setInterval(int interval){ if(timer != null) timer.setDelay(interval); } /** * Set the delay before the first event is triggered * @param initDelay initial delay in milliseconds */ public void setInitialDelay(int initDelay){ if(timer != null) timer.setInitialDelay(initDelay); } /** * Sets the initial delay and the interval between events. <br> * This is equivalent to calling both - <br> * <pre> * setInterval(delay); * setInitialDelay(delay); * </pre><br> * @param delay initial delay and interval in milliseconds */ public void setDelay(int delay){ if(timer != null){ timer.setInitialDelay(delay); timer.setDelay(delay); } } /** * Get the interval time (milliseconds) between * events. * @return interval in millsecs or -1 if the timer failed to * be created. */ public int getInterval(){ if(timer != null) return timer.getDelay(); else return -1; } /** * Get the initial delay time (milliseconds). * @return initial delay in millsecs or -1 if the timer failed to * be created. */ public int getInitialDelay(){ if(timer != null) return timer.getInitialDelay(); else return -1; } /** * See if the GTimer object has been created successfully * @return true if successful */ public boolean isValid(){ return (eventHandlerObject != null && timer != null); } }