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

Tekkotsu v2.4.1
Generated Tue Aug 16 16:32:46 2005 by Doxygen 1.4.4