Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

command.H

Go to the documentation of this file.
00001 #ifndef COMMAND_H_IS_INCLUDED
00002 #define COMMAND_H_IS_INCLUDED
00003 
00004 /*!
00005  *  \file command.H
00006  *  \brief Contains the definition of the COMMAND class.  A class representing a
00007  *  command that can be done and undone.  Some derived classes are also defined
00008  *  here.
00009  *
00010  *  \sa command.C
00011  *
00012  */
00013 
00014 #include "geom/geom.H"
00015 #include "disp/view.H"
00016 #include "std/ref.H" // for REFcounter
00017 
00018 class COMMAND;
00019 typedef const COMMAND CCOMMAND;
00020 MAKE_PTR_BASEC(COMMAND);
00021 typedef const COMMANDptr CCOMMANDptr;
00022 
00023 /*!
00024  *  \brief Base class for "commands" that can be executed 
00025  *  (COMMAND::doit()) and undone (COMMAND::undoit()).
00026  *
00027  *  A COMMAND can be in one of 3 possible states:
00028  *  
00029  *  - done:   doit() was executed.
00030  *  - undone: undoit() was executed after doit().
00031  *  - clear:  neither doit() nor undoit() have been called.
00032  *  
00033  *  For many types of commands, there is no difference
00034  *  between 'undone' and 'clear'. An example of where the two
00035  *  WOULD be different is a command that generates a portion
00036  *  of mesh in doit(), but in undoit() simply hides the
00037  *  portion of mesh instead of destroying it. That way,
00038  *  redoing the command by calling doit() after undoit()
00039  *  would be relatively lightweight: the portion of mesh
00040  *  would be unhidden rather than regenerated.
00041  *  
00042  *  The virtual method COMMAND::clear() is used to transition
00043  *  from state 'undone' to state 'clear'; e.g. the mesh
00044  *  generation command in the example above would delete the
00045  *  region of mesh in clear(), returning the command (and the
00046  *  mesh) to its initial state before the first doit() was
00047  *  executed. Most derived classes will not need to override
00048  *  COMMAND::clear().
00049  *  
00050  *  The following are the actions that can be taken from
00051  *  each state:
00052  *  
00053  *    state: 'clear'
00054  *      doit()   changes state to 'done'
00055  *      undoit() is a no-op
00056  *      clear()  is a no-op
00057  *  
00058  *    state: 'done'
00059  *      doit()   is a no-op
00060  *      undoit() changes state to 'undone'
00061  *      clear()  is an invalid action
00062  *  
00063  *    state: 'undone'
00064  *      doit()   changes state to 'done'
00065  *      undoit() is a no-op
00066  *      clear()  changes state to 'clear'
00067  *  
00068  */
00069 class COMMAND : public REFcounter {
00070    
00071    public:
00072 
00073       //! \name Run-Time Type Id
00074       //@{
00075       
00076       DEFINE_RTTI_METHODS_BASE("COMMAND", CCOMMAND*);
00077       
00078       //@}
00079       
00080       //! \name Constructors
00081       //@{
00082    
00083       COMMAND(bool done=false): _is_done(done), _is_undone(false) {}
00084       
00085       //@}
00086    
00087       //! \name Accessors
00088       //@{
00089    
00090       //! \brief Neither doit() nor undoit() have been called.
00091       bool is_clear()      const   { return !(_is_done || _is_undone); }
00092    
00093       //! \brief doit() was called most recently.
00094       bool is_done()       const   { return _is_done; } 
00095    
00096       //! \brief undoit() was called most recently, after doit().
00097       bool is_undone()     const   { return _is_undone; }
00098       
00099       //@}
00100    
00101       //! \name Command Virtual Methods
00102       //@{
00103    
00104       //! \brief Execute the command.
00105       //! \return \c true on success.
00106       //! If the command is already done, this is a no-op and still returns \c true.
00107       virtual bool doit();
00108    
00109       //! \brief Undo the command.
00110       //! \return \c true on success.
00111       //! If the command is already undone, this is a no-op and still returns \c true.
00112       virtual bool undoit();
00113    
00114       //! \brief After doit() and undoit() were called, restore things to the way
00115       //! they were before (may be a no-op for most derived classes).
00116       virtual bool clear();
00117       
00118       //@}
00119    
00120       //! \name Diagnostic
00121       //@{
00122    
00123       virtual void print() const { cerr << class_name() << " "; }
00124       
00125       //@}
00126 
00127    protected:
00128       
00129       bool _is_done;       //!< \brief \c true if doit() was executed most recently.
00130       bool _is_undone;     //!< \brief \c true if undoit() was executed most recently.
00131       
00132 };
00133 
00134 MAKE_PTR_SUBC(UNDO_CMD,COMMAND);
00135 
00136 /*!
00137  *  \brief Given some command, UNDO_CMD performs the reverse operation.
00138  *
00139  */
00140 class UNDO_CMD : public COMMAND {
00141    
00142    public:
00143    
00144       //! \name Constructors
00145       //@{
00146    
00147       UNDO_CMD(const COMMANDptr& c) : _cmd(c) {}
00148       
00149       //@}
00150    
00151       //! \name Run-Time Type Id
00152       //@{
00153    
00154       DEFINE_RTTI_METHODS3("UNDO_CMD", UNDO_CMD*, COMMAND, CCOMMAND*);
00155       
00156       //@}
00157    
00158       //! \name Command Virtual Methods
00159       //@{
00160    
00161       virtual bool doit();
00162       virtual bool undoit();
00163       virtual bool clear();
00164       
00165       //@}
00166    
00167       //! \name Diagnostic
00168       //@{
00169    
00170       virtual void print() const {
00171          cerr << class_name() << ": { ";
00172          if (_cmd) _cmd->print();
00173          cerr << " } ";
00174       }
00175       
00176       //@}
00177    
00178    protected:
00179       
00180       COMMANDptr   _cmd;
00181    
00182 };
00183 
00184 MAKE_PTR_SUBC(DISPLAY_CMD,COMMAND);
00185 
00186 /*!
00187  *  \brief Put a GEL or GELs in the WORLD's display list.
00188  *
00189  *  \question Should this class be moved to a different header (since it is a
00190  *  concrete COMMAND rather than an abstract command)?
00191  *
00192  */
00193 class DISPLAY_CMD : public COMMAND {
00194    
00195    public:
00196    
00197       //! \name Constructors
00198       //@{
00199    
00200       DISPLAY_CMD(CGELptr&  gel ) : _gels(gel)  {}
00201       DISPLAY_CMD(CGELlist& gels) : _gels(gels) {}
00202       
00203       //@}
00204    
00205       //! \name Run-Time Type Id
00206       //@{
00207    
00208       DEFINE_RTTI_METHODS3("DISPLAY_CMD", DISPLAY_CMD*, COMMAND, CCOMMAND*);
00209       
00210       //@}
00211    
00212       //! \name Command Virtual Methods
00213       //@{
00214    
00215       virtual bool doit();
00216       virtual bool undoit();
00217       
00218       //@}
00219    
00220       //! \name Diagnostic
00221       //@{
00222    
00223       virtual void print() const {
00224          cerr << class_name() << " { ";
00225          for (int i=0; i<_gels.num(); i++)
00226             cerr << _gels[i]->class_name() << " ";
00227          cerr << " } ";
00228       }
00229       
00230       //@}
00231    
00232    protected:
00233       
00234       GELlist  _gels;
00235 
00236 };
00237 
00238 MAKE_PTR_SUBC(UNDISPLAY_CMD, UNDO_CMD);
00239 
00240 /*!
00241  *  \brief Remove a GEL or GELs from the WORLD's display list.
00242  *
00243  *  \question Should this class be moved to a different header (since it is a
00244  *  concrete COMMAND rather than an abstract command)?
00245  *
00246  */
00247 class UNDISPLAY_CMD : public UNDO_CMD {
00248  public:
00249 
00250    //! \name Constructors
00251    //@{
00252 
00253    UNDISPLAY_CMD(CGELptr&  gel ) : UNDO_CMD(new DISPLAY_CMD(gel))  {}
00254    UNDISPLAY_CMD(CGELlist& gels) : UNDO_CMD(new DISPLAY_CMD(gels)) {}
00255    
00256    //@}
00257 
00258    //! \name Run-Time Type Id
00259    //@{
00260 
00261    DEFINE_RTTI_METHODS3("UNDISPLAY_CMD", UNDISPLAY_CMD*, UNDO_CMD, CCOMMAND*);
00262    
00263    //@}
00264 
00265 };
00266 
00267 MAKE_PTR_SUBC(MULTI_CMD,COMMAND);
00268 
00269 /*!
00270  *  \brief Perform multiple commands at once.
00271  *
00272  */
00273 class MULTI_CMD : public COMMAND {
00274    
00275    public:
00276 
00277       //! \name Run-Time Type Id
00278       //@{
00279    
00280       DEFINE_RTTI_METHODS3("MULTI_CMD", MULTI_CMD*, COMMAND, CCOMMAND*);
00281       
00282       //@}
00283       
00284       //! \name COMMAND List Operations
00285       //@{
00286    
00287       CLIST<COMMANDptr>& commands() const  { return _commands; }
00288       bool         is_empty()       const  { return _commands.empty(); }
00289    
00290       void         add(CCOMMANDptr& cmd)   { _commands += cmd; }
00291       void         rem(CCOMMANDptr& cmd)   { _commands -= cmd; }
00292       COMMANDptr   pop()                   { return _commands.pop(); }
00293    
00294       CCOMMANDptr& last()          const   { return _commands.last(); }
00295       
00296       //@}
00297    
00298       //! \name Command Virtual Methods
00299       //@{
00300    
00301       virtual bool doit();
00302       virtual bool undoit();
00303       virtual bool clear();
00304       
00305       //@}
00306    
00307       //! \name Diagnostic
00308       //@{
00309    
00310       virtual void print() const {
00311          cerr << class_name() << " { ";
00312          for (int i=0; i<_commands.num(); i++)
00313             _commands[i]->print();
00314          cerr << " } ";
00315       }
00316       
00317       //@}
00318 
00319    protected:
00320       
00321       LIST<COMMANDptr> _commands;
00322 
00323 };
00324 
00325 #endif // COMMAND_H_IS_INCLUDED
00326 
00327 /* end of file command.H */

Generated on Mon Sep 18 11:39:29 2006 for jot by  doxygen 1.4.4