Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

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/Factories.h"
00009 
00010 //! Holds some utility classes and functions for BehaviorSwitchControl which shouldn't be stored in a templated class
00011 class BehaviorSwitchControlBase : public ControlBase {
00012 public:
00013   //! A simple utility class to allow the BehaviorSwitchControl's to be able to deactivate the current behavior when a new one becomes active
00014   /*! Most behaviors are either major actions which you'll only want one of active
00015    *  at a time, or else their background monitors of some sort, that can run in different
00016    *  combinations.  Think radio buttons vs. checkboxes.  This will help you implement the
00017    *  "radio button" style... just assign all the behaviors to the same group, they will
00018    *  automatically use it to turn the previous behavior off when a new one becomes active.\n
00019    *  Pass NULL instead of one of these to get checkbox-style. */
00020   class BehaviorGroup : public ReferenceCounter {
00021   public:
00022     BehaviorGroup() : curBehavior(NULL), members() { } //!< contructor
00023     ~BehaviorGroup() { if(curBehavior!=NULL) curBehavior->stop(); } //!< destructor, will stop the current behavior if it was a one-shot
00024     BehaviorBase * curBehavior; //!< pointer to current behavior
00025     std::set<BehaviorSwitchControlBase*> members; //!< set of members of the group
00026   private:
00027     BehaviorGroup(const BehaviorGroup&); //!< shouldn't be called
00028     BehaviorGroup operator=(const BehaviorGroup&); //!< shouldn't be called
00029   };
00030   
00031   
00032   //! constructor
00033   BehaviorSwitchControlBase(const std::string& n, BehaviorBase* beh, BehaviorGroup* bg=NULL)
00034     : ControlBase(n), behgrp(NULL), mybeh(beh)
00035   {
00036     if(mybeh!=NULL) {
00037       mybeh->addReference();
00038       mybeh->setName(n);
00039       if(mybeh->isActive())
00040         mybeh->addReference();
00041     }
00042     setGroup(bg);
00043   }
00044   
00045   //! constructor, behavior must not be NULL
00046   BehaviorSwitchControlBase(BehaviorBase* beh, BehaviorGroup* bg=NULL)
00047     : ControlBase(beh->getName()), behgrp(NULL), mybeh(beh)
00048   {
00049     mybeh->addReference();
00050     if(mybeh->isActive())
00051       mybeh->addReference();
00052     setGroup(bg);
00053   }
00054 
00055   //! destructor
00056   virtual ~BehaviorSwitchControlBase() {
00057     //cout << "~BehaviorSwitchControlBase(): " << getName() << endl;
00058     stop();
00059     setGroup(NULL);
00060     if(mybeh!=NULL)
00061       mybeh->removeReference();
00062     mybeh=NULL;
00063   }
00064 
00065   //! activates the behavior, handy for making start-up behaviors that you can turn off again with the Controller
00066   /*! If you start twice without stopping (ie it's already running), shouldn't do anything */
00067   virtual BehaviorSwitchControlBase* start() { if(!isRunning()) { stopother(); startmine(); } return this; }
00068 
00069   //! stops the behavior
00070   virtual BehaviorSwitchControlBase* stop() { if(isRunning()) stopother(); return this; }
00071 
00072   //! toggles the behavior
00073   virtual BehaviorSwitchControlBase* toggle() { if(isRunning()) stopother(); else { stopother(); startmine(); } return this; }
00074 
00075   virtual ControlBase * takeInput(const std::string& msg);
00076   
00077   //! Reassigns the behavior group, pass NULL to remove from group.
00078   /*! If this behavior is active and the new group already has an active behavior, the new group's active behavior is stopped first. */
00079   virtual void setGroup(BehaviorGroup* bg);
00080   
00081   //! tells the current behavior (if there is one) to stop then loads its own
00082   /*! @return NULL unless there are submenus */
00083   virtual ControlBase * activate(MC_ID display, Socket * gui);
00084 
00085   //! adds a status to the name: - if in memory, # if running
00086   virtual std::string getName() const;
00087   
00088   virtual std::string getDescription() const;
00089   
00090   //! Returns true if the associated behavior is running
00091   virtual bool isRunning() const;
00092   
00093 protected:
00094   //! Stops the "other" guy's behavior - if ::behgrp is NULL, stops ourselves
00095   virtual void stopother();
00096   
00097   //! Starts our behavior
00098   virtual void startmine();
00099   
00100   //! updates other members in the group that the current behavior stopped -- do not call if behgrp is NULL
00101   virtual void notifyGroupMembers();
00102   
00103   //! called by notifyGroupMembers if #mybeh was destructed when stopped
00104   virtual void behaviorStopped() {}
00105 
00106   BehaviorGroup * behgrp; //!< the behavior group this belongs to.  Uses this to track the "current" behavior
00107   BehaviorBase* mybeh; //!< used to store the behavior.  If retained and non-NULL, will be valid.  However, if not retained, only valid if equals behgrp->curBehavior
00108 
00109 private:
00110   BehaviorSwitchControlBase(const BehaviorSwitchControlBase&); //!< shouldn't copy these
00111   BehaviorSwitchControlBase operator=(const BehaviorSwitchControlBase&); //!< shouldn't assign these
00112 };
00113 
00114 
00115 
00116 
00117 //! Allows proper switching between major behaviors, calling doStart and doStop
00118 template < class B, class Al = typename Factory0Arg<B>::template Factory<B> >
00119 class BehaviorSwitchControl : public BehaviorSwitchControlBase {
00120 public:
00121   //! constructor, can use this to toggle a single behavior on and off
00122   BehaviorSwitchControl(const std::string& n, bool retain=false)
00123     : BehaviorSwitchControlBase(n,NULL,NULL), retained(retain), startref(NULL)
00124   {}
00125   //! constructor, if you want to use an already constructed behavior
00126   BehaviorSwitchControl(B* beh, BehaviorGroup* bg=NULL)
00127     : BehaviorSwitchControlBase(beh,bg), retained(true), startref(NULL)
00128   {}
00129   //! constructor, if you want to use an already constructed behavior, but unretain it if it's stopped (if not retaining, will start @a beh if it's not already started)
00130   BehaviorSwitchControl(const std::string& n, B* beh, BehaviorGroup* bg=NULL, bool retain=false)
00131     : BehaviorSwitchControlBase(n,beh,bg), retained(retain), startref(NULL)
00132   {
00133     if(!retained) {
00134       // have to make sure behavior is started to maintain invariants
00135       if(!mybeh->isActive()) {
00136         startmine();
00137       }
00138       mybeh->removeReference(); //cancels reference from BehaviorSwitchControlBase's constructor
00139     }
00140   }
00141   //! constructor, needs to know what group its in and whether to retain its behavior
00142   BehaviorSwitchControl(const std::string& n, BehaviorGroup* bg, bool retain=false)
00143     : BehaviorSwitchControlBase(n,NULL,bg), retained(retain), startref(NULL)
00144   {}
00145   
00146   //! destructor
00147   virtual ~BehaviorSwitchControl() {
00148     stop();
00149     setGroup(NULL);
00150     if(mybeh!=NULL && retained)
00151       mybeh->removeReference();
00152     mybeh=NULL;
00153   }
00154 
00155   virtual std::string getName() const {
00156     if(!isValid())
00157       return ControlBase::getName();
00158     else
00159       return BehaviorSwitchControlBase::getName();
00160   }
00161   virtual std::string getDescription() const {
00162     if(!isValid() || mybeh->getDescription().size()==0)
00163       return B::getClassDescription();
00164     else
00165       return BehaviorSwitchControlBase::getDescription();
00166   }
00167   
00168 protected:
00169 
00170   virtual void startmine() {
00171     if(!retained) {
00172       Al allocator;
00173       mybeh=allocator();
00174       mybeh->setName(getName());
00175     } else {
00176       if(mybeh==NULL) {
00177         Al allocator;
00178         mybeh=allocator();
00179         mybeh->setName(getName());
00180         mybeh->addReference();
00181       }
00182     }
00183     startref=mybeh;
00184     startref->addReference();
00185     BehaviorSwitchControlBase::startmine();
00186   }
00187 
00188   //! adds a check to see if behavior has stopped itself -- if so, remove startref
00189   virtual bool isRunning() const {
00190     if(BehaviorSwitchControlBase::isRunning())
00191       return true;
00192     else if(startref!=NULL) 
00193       const_cast<BehaviorSwitchControl<B,Al>*>(this)->stopother();
00194     return false;
00195   }   
00196   
00197   //! Returns true if mybeh is pointing to a valid object
00198   virtual bool isValid() const {
00199     if(isRunning())
00200       return true;
00201     return retained;
00202   }
00203 
00204   virtual void behaviorStopped() {
00205     if(!retained)
00206       mybeh=NULL;
00207     if(startref!=NULL) {
00208       startref->removeReference();
00209       startref=NULL;
00210     }
00211   }
00212   
00213   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
00214   BehaviorBase * startref; //!< true if a reference was added (and still current) from calling doStart
00215   
00216 private:
00217   BehaviorSwitchControl(const BehaviorSwitchControl&); //!< shouldn't call this
00218   BehaviorSwitchControl operator=(const BehaviorSwitchControl&); //!<shouldn't call this
00219 };
00220 
00221 /*! @file
00222  * @brief Describes BehaviorSwitchControl<BEH> and its common superclass BehaviorSwitchControlBase - a control for turning behaviors on and off
00223  * @author ejt (Creator)
00224  */
00225 
00226 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:36 2016 by Doxygen 1.6.3