LCOV - code coverage report
Current view: top level - source/tools/atlas/GameInterface - CommandProc.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 2 0.0 %
Date: 2023-01-19 00:18:29 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2009 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #ifndef INCLUDED_COMMANDPROC
      19             : #define INCLUDED_COMMANDPROC
      20             : 
      21             : #include <string>
      22             : #include <list>
      23             : #include <map>
      24             : 
      25             : #include "SharedMemory.h"
      26             : 
      27             : namespace AtlasMessage
      28             : {
      29             : 
      30           0 : struct Command
      31             : {
      32           0 :     virtual ~Command() {}
      33             :     virtual void Do() = 0;
      34             :     virtual void Undo() = 0;
      35             :     virtual void Redo() = 0;
      36             :     virtual void Merge(Command* prev) = 0;
      37             :     virtual const char* GetType() const = 0;
      38             : };
      39             : 
      40             : class CommandProc
      41             : {
      42             : public:
      43             :     CommandProc();
      44             :     ~CommandProc();
      45             : 
      46             :     // Should be called before shutting down, so it can free
      47             :     // references to entities/etc that are stored in commands
      48             :     void Destroy();
      49             : 
      50             :     void Submit(Command* cmd);
      51             : 
      52             :     void Undo();
      53             :     void Redo();
      54             :     void Merge();
      55             : 
      56             : private:
      57             :     std::list<Command*> m_Commands;
      58             :     typedef std::list<Command*>::iterator cmdIt;
      59             :     // The 'current' command is the latest one which has been executed
      60             :     // (ignoring any that have been undone)
      61             :     cmdIt m_CurrentCommand;
      62             : };
      63             : 
      64             : typedef Command* (*cmdHandler)(const void*);
      65             : typedef std::map<std::string, cmdHandler> cmdHandlers;
      66             : extern cmdHandlers& GetCmdHandlers();
      67             : 
      68             : CommandProc& GetCommandProc();
      69             : 
      70             : /*
      71             : We want the command handler implementations to be as pretty as possible - so let people write
      72             : 
      73             :     BEGIN_COMMAND(CommandName)
      74             :     {
      75             :         int member;
      76             :         cCommandName() { ... }  // } both are optional; neither may
      77             :         ~cCommandName() { ... } // }   make use of this->msg
      78             : 
      79             :         void Do() { ... interact with this->msg ... }
      80             :         void Undo() { ... }
      81             :         void Redo() { ... }
      82             : 
      83             :         void MergeIntoPrevious(cCommandName* prev) { ... } // iff this command is a mergeable one
      84             :     };
      85             :     END_COMMAND(CommandName)
      86             : 
      87             : which looks almost exactly like a class definition, and is about the simplest
      88             : system I can find.
      89             : 
      90             : 
      91             : The following macros convert that into:
      92             : 
      93             :     class cCommandName_base : public Command
      94             :     {
      95             :     protected:
      96             :         // Storage for data passed into this command
      97             :         dCommandName* msg;
      98             :     public:
      99             :         // Ensure msg is initialised to something 'safe'
     100             :         cCommandName_base : msg(NULL) {}
     101             : 
     102             :         // MergeIntoPrevious should be overridden by mergeable commands, and implemented
     103             :         // to update 'prev' to include the effects of 'this'. (A subclass overriding
     104             :         // any function named 'MergeIntoPrevious' will hide this function, even if
     105             :         // the types differ.)
     106             :         void MergeIntoPrevious(void*) { ...error - needs to be overridden... }
     107             :     };
     108             : 
     109             :     // Use 'struct' for automatic publicness - we want users to write as little as possible
     110             :     struct cCommandName : public cCommandName_base
     111             :     {
     112             :         // (user's command code - mostly overriding virtual methods from Command)
     113             :     }
     114             : 
     115             :     // Subclass the command to add things which require knowledge of the
     116             :     // complete class definition
     117             :     class cCommandName_sub : public cCommandName
     118             :     {
     119             :     public:
     120             :         cCommandName_sub(dCommandName *data) { ...set msg... }
     121             :         ~cCommandName_sub() { ...clear msg... }
     122             : 
     123             :         // Implement the relevant virtual methods from the Command base class,
     124             :         // with automatic casting to the correct types and stuff
     125             :         virtual void Merge(Command* prev) { ...call MergeIntoPrevious... }
     126             :         virtual const char* GetType() const { return "CommandName"; }
     127             : 
     128             :         // Factory method for creating an instance of this class, casting the
     129             :         // data pointer into the right form (to avoid forcing the generic
     130             :         // command-handling support code to worry about the types)
     131             :         static Command* Create(const void* data) { ...return new cCommandName_sub... }
     132             :     };
     133             : 
     134             :     // Register.cpp wants to get that Create method, but it doesn't want to
     135             :     // load all the class definitions; so define a simple method that just
     136             :     // returns the address of Create
     137             :     cmdHandler cCommandName_create()
     138             :     {
     139             :         return &cCommandName_sub::Create;
     140             :     }
     141             : 
     142             : // (TODO: make sure this stays in sync with the code below)
     143             : 
     144             : */
     145             : 
     146             : #define BEGIN_COMMAND(t) \
     147             :     class c##t##_base : public Command \
     148             :     { \
     149             :     protected: \
     150             :         d##t* msg; \
     151             :     public: \
     152             :         c##t##_base() : msg(NULL) {} \
     153             :         void MergeIntoPrevious(void*) { debug_warn(L"MergeIntoPrevious unimplemented in command " WIDEN(#t)); } \
     154             :     }; \
     155             :     struct c##t : public c##t##_base
     156             : 
     157             : #define END_COMMAND(t) \
     158             :     class c##t##_sub : public c##t \
     159             :     { \
     160             :     public: \
     161             :         c##t##_sub(d##t* data) \
     162             :         { \
     163             :             msg = data; \
     164             :         } \
     165             :         ~c##t##_sub() \
     166             :         { \
     167             :             /* (msg was allocated in mDoCommand(), using SHAREABLE_NEW) */ \
     168             :             AtlasMessage::ShareableDelete(msg); \
     169             :             msg = NULL; \
     170             :         } \
     171             :         virtual void Merge(Command* prev) { MergeIntoPrevious(static_cast<c##t##_sub*>(prev)); } \
     172             :         virtual const char* GetType() const { return #t; } \
     173             :         static Command* Create(const void* data) \
     174             :         { \
     175             :             return new c##t##_sub (reinterpret_cast<d##t*>(const_cast<void*>(data))); \
     176             :         } \
     177             :     }; \
     178             :     cmdHandler c##t##_create() \
     179             :     { \
     180             :         return &c##t##_sub ::Create; \
     181             :     }
     182             : 
     183             : 
     184             : }
     185             : 
     186             : #endif // INCLUDED_COMMANDPROC

Generated by: LCOV version 1.13