Homepage Demos Overview Downloads Tutorials Reference
Credits
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Search

BehaviorSwitchControl.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_BehaviorSwitchControl_h_
00003 #define INCLUDED_BehaviorSwitchControl_h_
00004 
00005 #include "ControlBase.h"
00006 #include "Behaviors/BehaviorBase.h"
00007 #include "Shared/ReferenceCounter.h"
00008 #include "Shared/Factory.h"
00009 #include "Shared/debuget.h"
00010 
00011 //! Holds some utility classes and functions for BehaviorSwitchControl which shouldn't be stored in a templated class
00012 class BehaviorSwitchControlBase : public ControlBase {
00013 public:
00014   //! A simple utility class to allow the BehaviorSwitchControl's to be able to deactivate the current behavior when a new one becomes active
00015   /*! Most behaviors are either major actions which you'll only want one of active
00016    *  at a time, or else their background monitors of some sort, that can run in different
00017    *  combinations.  Think radio buttons vs. checkboxes.  This will help you implement the
00018    *  "radio button" style... just assign all the behaviors to the same group, they will
00019    *  automatically use it to turn the previous behavior off when a new one becomes active.\n
00020    *  Pass NULL instead of one of these to get checkbox-style. */
00021   class BehaviorGroup : public ReferenceCounter {
00022   public:
00023     BehaviorGroup() : curBehavior(NULL) { } //!< contructor
00024     ~BehaviorGroup() { if(curBehavior!=NULL) curBehavior->DoStop(); } //!< destructor, will stop the current behavior if it was a one-shot
00025     BehaviorBase * curBehavior; //!< pointer to current behavior
00026   private:
00027     BehaviorGroup(const BehaviorGroup&); //!< shouldn't be called
00028     BehaviorGroup operator=(const BehaviorGroup&); //!< shouldn't be called
00029   };
00030   
00031   //! constructor
00032   BehaviorSwitchControlBase(const std::string& n, BehaviorGroup* bg, bool retain)
00033     : ControlBase(n), retained(true), behgrp(bg) {
00034     retained=retain;
00035     if(behgrp!=NULL)
00036       behgrp->AddReference();
00037   }
00038 
00039   //! destructor
00040   virtual ~BehaviorSwitchControlBase() {
00041     if(behgrp!=NULL)
00042       behgrp->RemoveReference();
00043   }
00044 
00045   //! activates the behavior, handy for making start-up behaviors that you can turn off again with the Controller
00046   /*! If you start twice without stopping (ie it's already running), shouldn't do anything */
00047   virtual BehaviorSwitchControlBase* start()=0;
00048   virtual BehaviorSwitchControlBase* stop()=0; //!< stops the behavior
00049   virtual BehaviorSwitchControlBase* toggle()=0; //!< toggles the behavior
00050 
00051   //! tells the current behavior (if there is one) to stop then loads its own
00052   /*! @return NULL unless there are submenus */
00053   virtual ControlBase * activate(MotionManager::MC_ID display, Socket * gui) {
00054     if(slotsSize()==0) {
00055       toggle();
00056       return NULL;
00057     } else
00058       return ControlBase::activate(display,gui);
00059   }
00060 
00061 protected:
00062   bool retained; //!< true if the behavior should be generated once and retained after DoStop.  Otherwise, a new one is generated each time it is started
00063   BehaviorGroup * behgrp; //!< the behavior group this belongs to.  Uses this to track the "current" behavior
00064 
00065 private:
00066   BehaviorSwitchControlBase(const BehaviorSwitchControlBase&); //!< shouldn't copy these
00067   BehaviorSwitchControlBase operator=(const BehaviorSwitchControlBase&); //!< shouldn't assign these
00068 };
00069 
00070 
00071 
00072 
00073 //! Allows proper switching between major behaviors, calling DoStart and DoStop
00074 template < class B, class Al = Factory< B > >
00075 class BehaviorSwitchControl : public BehaviorSwitchControlBase {
00076 public:
00077   //! constructor, can use this to toggle a single behavior on and off
00078   BehaviorSwitchControl(const std::string& n, bool retain=false)
00079     : BehaviorSwitchControlBase(n,NULL,retain), mybeh(NULL) {}
00080   //! constructor, if you want to use an already constructed behavior, can pass NULL for behavior group
00081   BehaviorSwitchControl(const std::string& n, B* beh, BehaviorGroup* bg=NULL)
00082     : BehaviorSwitchControlBase(n,bg,true), mybeh(beh) {
00083     retained=true;
00084     if(mybeh!=NULL)
00085       mybeh->AddReference();
00086   }
00087   //! constructor, needs to know what group its in and whether to retain its behavior
00088   BehaviorSwitchControl(const std::string& n, BehaviorGroup* bg, bool retain=false)
00089     : BehaviorSwitchControlBase(n,bg,retain), mybeh(NULL) {}
00090   
00091   //! destructor
00092   virtual ~BehaviorSwitchControl() {
00093     stop();
00094     if(mybeh!=NULL && retained)
00095       mybeh->RemoveReference();
00096   }
00097 
00098   virtual BehaviorSwitchControl<B,Al>* start() { if(!isRunning()) { stopother(); startmine(); } return this; }
00099 
00100   virtual BehaviorSwitchControl<B,Al>* stop() { if(isRunning()) stopother(); return this; }
00101 
00102   virtual BehaviorSwitchControl<B,Al>* toggle() { if(isRunning()) stopother(); else { stopother(); startmine(); } return this; }
00103 
00104   //! adds a status to the name: - if in memory, # if running
00105   virtual std::string getName() const {
00106     if(!isValid())//(mybeh==NULL || !retained && (behgrp==NULL || behgrp->curBehavior!=mybeh))
00107       return ControlBase::getName();
00108     else
00109       return (mybeh->isActive()?'#':'-')+mybeh->getName();
00110   }
00111   virtual std::string getDescription() const {
00112     if(!isValid() || mybeh->getDescription().size()==0)//(mybeh==NULL || !retained && (behgrp==NULL || behgrp->curBehavior!=mybeh))
00113       return B::getClassDescription();
00114     else
00115       return mybeh->getDescription();
00116   }
00117   
00118 
00119 protected:
00120 
00121   //! Stops the "other" guy's behavior - if ::behgrp is NULL, stops ourselves
00122   virtual void stopother() {
00123     if(behgrp==NULL) {
00124       if(mybeh!=NULL) {
00125         if(mybeh->isActive()) {
00126           mybeh->DoStop();
00127           if(!retained)
00128             mybeh=NULL;
00129         } else
00130           ASSERT(retained,"null group, non-null not retained beh, not active, did you call inherited DoStart/DoStop in your Behavior?");
00131       }
00132     } else if(behgrp->curBehavior!=NULL) {
00133       behgrp->curBehavior->DoStop();
00134       behgrp->curBehavior=NULL;
00135     }
00136   }
00137 
00138   //! Starts our behavior
00139   virtual void startmine() {
00140     if(!retained) {
00141       mybeh=Al::construct();
00142       if(behgrp!=NULL)
00143         behgrp->curBehavior=mybeh;
00144     } else {
00145       if(mybeh==NULL) {
00146         mybeh=Al::construct();
00147         mybeh->AddReference();
00148       }
00149       if(behgrp!=NULL)
00150         behgrp->curBehavior=mybeh;
00151     }
00152     mybeh->DoStart();
00153   }
00154 
00155   //! Returns true if the associated behavior is running
00156   virtual bool isRunning() const {
00157     if(mybeh==NULL) //not created or has been destroyed, definitely not running
00158       return false;
00159     // so, beh has been created (but may have been stopped by another in the group)
00160     if(behgrp==NULL) //no group
00161       return mybeh->isActive(); //just check active flag (is valid object, we would have set it to NULL if we stopped it ourselves)
00162     // so, we're in a group, someone else could have stopped us
00163     return (behgrp->curBehavior==mybeh); //all we can see is if the current behavior is ours.  If it is, it'll be active
00164   }
00165 
00166   //! Returns true if mybeh is pointing to a valid object
00167   virtual bool isValid() const {
00168     if(isRunning())
00169       return true;
00170     return retained;
00171   }
00172 
00173   B* mybeh; //!< used to store the behavior.  If retained and non-NULL, will be valid.  However, if not retained, only valid if equals behgrp->curBehavior
00174 
00175 private:
00176   BehaviorSwitchControl(const BehaviorSwitchControl&); //!< shouldn't call this
00177   BehaviorSwitchControl operator=(const BehaviorSwitchControl&); //!<shouldn't call this
00178 };
00179 
00180 /*! @file
00181  * @brief Defines BehaviorSwitchControl and the BehaviorSwitch namespace - a control for turning behaviors on and off
00182  * @author ejt (Creator)
00183  *
00184  * $Author: ejt $
00185  * $Name: tekkotsu-1_4_1 $
00186  * $Revision: 1.7 $
00187  * $State: Exp $
00188  * $Date: 2003/06/10 00:53:47 $
00189  */
00190 
00191 #endif

Tekkotsu v1.4
Generated Sat Jul 19 00:06:29 2003 by Doxygen 1.3.2