/***************************************************************** JADE - Java Agent DEvelopment Framework is a framework to develop multi-agent systems in compliance with the FIPA specifications. Copyright (C) 2000 CSELT S.p.A. GNU Lesser General Public License 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, version 2.1 of the License. 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 jade.gui; // Import required java classes import java.util.Vector; // Import required Jade classes import jade.core.*; import jade.core.behaviours.*; /** When a program instantiates a GUI, the Java programming language starts a new thread, different from the Agent thread. The Agent thread generally is active because it has its tasks to perform and also the GUI thread is active, in respect to the Agent thread, because its behaviour depends on the user actions (e.g. pressing a button, using the nemu bar,...) and not only on the agent task. Therefore, an appropriate mechanism is needed to manage the interaction between these two active threads. It is not a good practice allowing one thread to just call the method of another thread because of the difference in the thread space. What should be done, instead is one thread requesting the other to execute a method, each thread in its one execution space. Since its common to have an agent with a GUI, this class is for this purpose. This class extends the <code>jade.core.Agent </code> class: at the start-up it instantiate ad ad-hoc behaviour that manages a queue of <code>jade.gui.GuiEvent</code>,event objects that can be received by other threads. A thread (in particular a GUI)to notify an event to an Agent should create a new Object of type <code>jade.gui.GuiEvent</code>and pass it as a parameter to the call of the method <code>postGuiEvent</code> of the <code>jade.gui.GuiAgent</code> object. Notice that an object of type <code>GuiEvent</code> has two mandatory attributes and an optional list of parameters that can be added to the event object. After the method <code>postGuiEvent</code> is called,the agent reacts by waking up all its active behaviours, and in particular the one that causes the Agent thread to execute the method <code>onGuiEvent</code>. @see jade.core.Agent @see jade.gui.GuiEvent @author Giovanni Caire - CSELT S.p.A. @version $Date: 2005-04-15 17:45:02 +0200 (ven, 15 apr 2005) $ $Revision: 5669 $ */ public abstract class GuiAgent extends Agent { private static final long serialVersionUID = 3487495895819010L; /** @serial */ private Vector guiEventQueue; /** @serial */ private Boolean guiEventQueueLock; //////////////////////// // GUI HANDLER BEHAVIOUR private class GuiHandlerBehaviour extends SimpleBehaviour { private static final long serialVersionUID = 3487495895819011L; protected GuiHandlerBehaviour() { super(GuiAgent.this); } public void action() { if (!guiEventQueue.isEmpty()) { GuiEvent ev = null; synchronized(guiEventQueueLock) { try { ev = (GuiEvent) guiEventQueue.elementAt(0); guiEventQueue.removeElementAt(0); } catch (ArrayIndexOutOfBoundsException ex) { ex.printStackTrace(); // Should never happen } /*#DOTNET_INCLUDE_BEGIN catch (Exception exc) { ev = null; guiEventQueue.removeElementAt(0); } #DOTNET_INCLUDE_END*/ } //#DOTNET_EXCLUDE_BEGIN onGuiEvent(ev); //#DOTNET_EXCLUDE_END /*#DOTNET_INCLUDE_BEGIN if (ev != null) onGuiEvent(ev); else block(); #DOTNET_INCLUDE_END*/ } else block(); } public boolean done() { return(false); } } /** Default constructor. */ public GuiAgent() { super(); guiEventQueue = new Vector(); guiEventQueueLock = new Boolean(true); // Add the GUI handler behaviour Behaviour b = new GuiHandlerBehaviour(); addBehaviour(b); } /** Posts an event from the GUI thread to the agent event queue. @param e The GUI event to post. */ public void postGuiEvent(GuiEvent e) { synchronized(guiEventQueueLock) { guiEventQueue.addElement( (Object) e ); doWake(); } } ///////////////////////////////////////////////////////////////////////// // METHODS TO POST PREDEFINED EXIT AND CLOSEGUI EVENTS IN GUI EVENT QUEUE /*public void postExitEvent(Object g) { GuiEvent e = new GuiEvent(g, GuiEvent.EXIT); postGuiEvent(e); } public void postCloseGuiEvent(Object g) { GuiEvent e = new GuiEvent(g, GuiEvent.CLOSEGUI); postGuiEvent(e); }*/ /** Abstract method to handle posted GUI events. Subclasses of <code>GuiAgent</code> will implement their own reactions to GUI events starting with this method. @param ev The GUI event to handle. */ protected abstract void onGuiEvent(GuiEvent ev); }