Homepage Demos Overview Downloads Tutorials Reference
Credits

ControlBase.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_ControlBase_h
00003 #define INCLUDED_ControlBase_h
00004 
00005 #include "Events/EventBase.h"
00006 #include "Motion/MotionManager.h"
00007 #include "SoundPlay/SoundManager.h"
00008 #include "Shared/Config.h"
00009 #include "Wireless/Socket.h"
00010 #include <string>
00011 #include <vector>
00012 
00013 //! Base class for all items in the Controller hierarchy.
00014 /*! These are similar to behaviors in that they can do processing and
00015  *  are told when to start and stop.
00016  *
00017  *  However, the important difference is that these have to follow a
00018  *  much tighter set of guidelines for a more refined purpose - user
00019  *  interface.  Controls do not directly receive events - the
00020  *  Controller will process events for them and call the appropriate
00021  *  functions at the appropriate times.  Controls are expected to fit
00022  *  into a heirarchical scheme, where each control (except the root)
00023  *  has a parent which created it, and may return its own children
00024  *  where appropriate.
00025  *
00026  *  Controls can be very powerful, and a class can be both a behavior
00027  *  and a control.  This allows integrated user interface to
00028  *  controlling a complex behavior.  Some controls may simply need
00029  *  EventListener access instead to perform a few tricks.  Mix and
00030  *  match as you see fit.  (multiple inheritance can be nice if it's
00031  *  planned for, as these have been)
00032  *
00033  *  This base class will do most of the work of maintaining submenus
00034  *  for you, and will call appropriate virtual functions which you are
00035  *  expected to override.  Controls generally live in
00036  *  <tt>Behaviors/Controls/</tt> as the Controller itself is a
00037  *  behavior, and these controls merely its tools.
00038  *
00039  *  The ControlBase pointers which are returned at various points are the
00040  *  responsibility of the creator.  Controller will not delete them upon
00041  *  deactivation.
00042  *
00043  *  GUI Theory: \n
00044  *  There are 3 levels to the user interface.
00045  *  -# Robot/Local: Uses the buttons for input, and LEDs and sounds for immediate feedback.  No external resources needed
00046  *  -# Text: Uses a console to display/request information.
00047  *  -# GUI: Uses a graphical interface on a desktop machine
00048  *
00049  *  Obviously, higher levels require more technological resources, which also
00050  *  means there's more to go wrong and debug.  However, another important
00051  *  distinction between the first level and the others is that the first level
00052  *  does not require the user to lose direct contact with the robot.  Requiring
00053  *  the user to move back and forth from robot to computer can be much more
00054  *  frustrating than decoding LED signals or press head buttons.  There are also
00055  *  safety issues when triggering behaviors remotely if the robot is out of
00056  *  immediate reach.  But of course, having a GUI and text output is extremely
00057  *  valuable in terms of ease of use and efficiency.
00058  *
00059  *  So, the lesson is to try to support all 3 levels so that your interfaces
00060  *  will be robust and efficient in a variety of environments.  You'll thank
00061  *  yourself when you're demoing on the road and you can't get wavelan up, or
00062  *  the guest machine you're supposed to use doesn't have Java, or whatever.
00063  *
00064  * @todo ControlBase's should use ReferenceCounter so memory management is not an issue
00065  * @see Controller, NullControl */
00066 class ControlBase {
00067 public:
00068   
00069   //! @name Constructors/Destructors
00070 
00071   ControlBase() : name("(null name)"), description(), hilights(), options(), doRewrite(false), display_id(MotionManager::invalid_MC_ID), gui_comm(NULL) {} //!< Contructor
00072   ControlBase(const std::string& n) : name(n), description(), hilights(), options(), doRewrite(false), display_id(MotionManager::invalid_MC_ID), gui_comm(NULL) {} //!< Contructor, initializes with a name
00073   ControlBase(const std::string& n, const std::string& d) : name(n), description(d), hilights(), options(), doRewrite(false), display_id(MotionManager::invalid_MC_ID), gui_comm(NULL) {} //!< Contructor, initializes with a name
00074 
00075   //! Destructor
00076   virtual ~ControlBase() {
00077     //    deactivate();
00078     //cout << "~ControlBase(): " << name << endl;
00079     clearSlots();
00080   }
00081 
00082   //@}
00083 
00084   //! You probably want to override some of these, call the ControlBase functions from your code if you want default sound effects (or look in Config::controller_config).
00085   //! @name Controller Functions
00086 
00087   //! Called when the control is activated (or the control system is reactivating)
00088   /*! Takes the id number of a LedMC which the control should use, maintained by Controller.
00089    *  Controls share the display which is passed, and may use the socket @a gui to communicate with the GUI controller, if it is connected.
00090    *  @return a ControlBase pointer.  Return: @li @a this if the control should stay active (if it's not a one-shot command) @li @c NULL to return to parent @li other address to spawn a child control*/
00091   virtual ControlBase * activate(MotionManager::MC_ID disp_id, Socket * gui);
00092   virtual void pause();      //!< called when a control is being overriden by a child, or the control system is deactivating (e-stop being turned off)
00093   virtual void refresh();    //!< called when the child has deactivated and this control should refresh its display, or some other event (such as the user pressing the refresh button) has happened to cause a refresh to be needed
00094   virtual void deactivate(); //!< called when this control is being popped from the control stack
00095 
00096   //! when the user has trigger an "open selection" - default is to return the hilighted control*/
00097   /*! The value which is returned is then activate()ed and pushed on the Controller's stack*/
00098   virtual ControlBase * doSelect();
00099   //! when the user wants to increment the control - default is to hilight the first non-null slot after the last hilight, and return @c this
00100   /*! The value which is returned is then activate()ed and pushed on the Controller's stack, so you probably want to return @c this */
00101   virtual ControlBase * doNextItem();
00102   //! when the user wants to decrement the control - default is to hilight the last non-null slot before the first hilight, and return @c this
00103   /*! The value which is returned is then activate()ed and pushed on the Controller's stack, so you probably want to return @c this */
00104   virtual ControlBase * doPrevItem();
00105   //! when the user wants to cancel - you should almost always return NULL now unless you need to override the cancel in order to confirm something (e.g. "Save changes?")
00106   /*! The value which is returned is then activate()ed and pushed on the Controller's stack, you probably want to return @c NULL */
00107   virtual ControlBase * doCancel();
00108   //! prompt the user for text input on the current input device (cin, tekkotsu console (sout), or GUI)
00109   /*! The value which is returned is then activate()ed and pushed on the Controller's stack, so you probably want to return @c this */
00110   virtual ControlBase * doReadStdIn(const std::string& prompt=std::string());
00111   //! called when the user has supplied a text string (may or may not have been prompted by doReadStdIn()!  May not even be active yet - the user can direct the same input to a set of hilighted menus)
00112   /*! The value which is returned is then activate()ed and pushed on the Controller's stack*/
00113   virtual ControlBase * takeInput(const std::string& msg); 
00114   //! may be called before takeInput to verify this Control can make sense of msg
00115   virtual bool validInput(const std::string& msg); 
00116   //@}
00117   
00118   //! @name Accessors
00119 
00120   virtual ControlBase& setName(const std::string& n) { name=n; return *this; } //!< sets the name of the control
00121   virtual std::string getName() const { return name; } //!< returns the name of the control
00122 
00123   virtual ControlBase& setDescription(const std::string d) { description=d; return *this; } //!< sets the description of the control
00124   virtual std::string getDescription() const { return description; } //!< returns a short description of what the control does
00125 
00126   const std::vector<ControlBase*>& getSlots() const { return options; } //!< returns the vector of sub-controls
00127   std::string getSlotName(unsigned int i) const; //!< returns the string that will appear in slot @a i
00128   unsigned int slotsSize() const { return options.size(); } //!< returns the number of options available
00129   void setSlot(unsigned int i,ControlBase* o); //!< sets @a i'th element of #options to @a o
00130   void pushSlot(ControlBase* o); //!< sets next unused element of #options to @a o
00131   void clearSlots(); //!< deletes each slot item and clears the slots
00132 
00133   virtual const std::vector<unsigned int>& getHilights() const { return hilights; } //!< returns a vector of the indicies of hilighted slots
00134   virtual void setHilights(const std::vector<unsigned int>& hi); //!< sets the hilighted slots
00135   virtual void hilightFirst(); //!< sets the hilight to the first non-null slot
00136 
00137   virtual MotionManager::MC_ID getDisplay() { return display_id; } //!< returns display being used
00138   virtual ControlBase& setDisplay(MotionManager::MC_ID d) { display_id=d; return *this; } //!< sets display to use
00139 
00140   //@}
00141 
00142 protected:
00143     
00144   //! clears the display (if use_VT100 is on)
00145   virtual void clearMenu();
00146 
00147   //! returns the average of the hilighted indicies - used to know to play the "next" sound, or the "prev" sound when the hilight changes
00148   float hilightsAvg() const;
00149 
00150   std::string name; //!< the name of this control
00151   std::string description; //!< the description of this control
00152   std::vector<unsigned int> hilights; //!< keep sorted - index(es) of current selection - can have multiple if using GUI
00153   std::vector<ControlBase*> options; //!< vector of controls to select from
00154   bool doRewrite; //!< toggles using VT100 codes to reposition the cursor at the beginning of the menu
00155                   /*!< we don't always want to do this, any time someone else might have written to
00156                    *   the display we set this to false so we don't overwrite it. */
00157 
00158   MotionManager::MC_ID display_id; //!< LedMC to use for displaying selection
00159   Socket * gui_comm; //!< socket to communicate with the GUI, if it is connected
00160   
00161 private:
00162   ControlBase(const ControlBase&); //!< you can override, but don't call this...
00163   ControlBase& operator=(const ControlBase&); //!< you can override, but don't call this...
00164 };
00165 
00166 /*! @file
00167  * @brief Defines ControlBase from which all items in the control system should inherit
00168  * @author ejt (Creator)
00169  *
00170  * $Author: ejt $
00171  * $Name: tekkotsu-2_1 $
00172  * $Revision: 1.20 $
00173  * $State: Exp $
00174  * $Date: 2004/02/18 21:11:25 $
00175  */
00176 #endif

Tekkotsu v2.1
Generated Tue Mar 16 23:19:13 2004 by Doxygen 1.3.5