Lumiera  0.pre.03
»edit your freedom«
command.hpp
Go to the documentation of this file.
1 /*
2  COMMAND.hpp - Key abstraction for steam/edit operations and UNDO management
3 
4  Copyright (C) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
68 #ifndef CONTROL_COMMAND_H
69 #define CONTROL_COMMAND_H
70 
71 #include "lib/error.hpp"
72 #include "lib/symbol.hpp"
73 #include "steam/common.hpp"
78 #include "lib/diff/gen-node.hpp"
79 #include "lib/handle.hpp"
80 
81 #include <string>
82 
83 
84 namespace lumiera {
85 namespace error {
86  LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS);
87  LUMIERA_ERROR_DECLARE (INVALID_COMMAND);
88  LUMIERA_ERROR_DECLARE (DUPLICATE_COMMAND);
89  LUMIERA_ERROR_DECLARE (INVALID_ARGUMENTS);
90  LUMIERA_ERROR_DECLARE (MISSING_MEMENTO);
91 }}
92 
93 namespace steam {
94 namespace control {
95 
96  using std::string;
97  using lib::Symbol;
98  using std::shared_ptr;
99  using lib::meta::Tuple;
100  using lib::meta::Types;
101 
102  using FuncPtr = void*;
103 
104  class CommandDef;
105  class CommandImpl;
106 
107 
124  class Command
125  : public AcceptAnyBinding<Command // accepts arbitrary bind(..) calls (with runtime check)
126  , Command& // (return value of bind() functions is *this)
127  , lib::Handle<CommandImpl> // actually implemented as ref counting Handle
128  > //
129  {
131 
132  public:
133  /* === command registry === */
134  static Command get (Symbol cmdID);
135  static bool remove (Symbol cmdID);
136 
138  Command storeDef (Symbol newCmdID) const;
139  Command newInstance () const;
140 
141  static Command maybeGetNewInstance (Symbol cmdID);
142 
143 
144  Command (Symbol cmdID) { *this = get (cmdID); }
145  Command() { }
146  ~Command();
147 
148  // default copy acceptable
149  Command (Command &&) = default;
150  Command (Command const&) = default;
151  Command& operator= (Command &&) = default;
152  Command& operator= (Command const&) = default;
153 
154 
155 
156  /* === command lifecycle === */
157 
158  template<typename...TYPES>
159  Command& bindArg (std::tuple<TYPES...> const&);
160 
161  Command& bindArg (lib::diff::Rec const&);
162 
163  Command& unbind();
164 
165 
166  ExecResult operator() () ;
167  ExecResult exec () ;
168  ExecResult undo () ;
169 
170 
175  ExecResult exec (HandlingPattern const& execPattern);
176  ExecResult exec (HandlingPattern::ID);
177 
178  ExecResult undo (HandlingPattern const& execPattern);
179  ExecResult undo (HandlingPattern::ID);
180 
182  ExecResult execSync ();
183 
185  HandlingPattern::ID getDefaultHandlingPattern() const;
186 
189  HandlingPattern::ID setHandlingPattern (HandlingPattern::ID);
190 
191 
192 
193  /* === diagnostics === */
194 
195  static size_t definition_count();
196  static size_t instance_count();
197 
198  bool canExec() const;
199  bool canUndo() const;
200 
201  static bool defined (Symbol cmdID);
202  static bool canExec (Symbol cmdID);
203  static bool canUndo (Symbol cmdID);
204 
205  void duplicate_detected (Symbol) const;
206 
207  Symbol getID() const noexcept;
208  bool isAnonymous() const;
209 
210  operator string() const;
211  friend bool operator== (Command const&, Command const&);
212  friend bool operator< (Command const&, Command const&);
213 
214 
215  protected:
216  static Command fetchDef (Symbol cmdID);
217  void activate (shared_ptr<CommandImpl> &&, Symbol cmdID =0);
218 
219  friend class CommandDef; //...invoking those two functions during definition stage
220 
221 
222  private:
223  void setArguments (Arguments&);
224  void setArguments (lib::diff::Rec const&);
225  };
226 
227 
228 
229 
230 
231  inline ExecResult
232  Command::operator() ()
233  {
234  return exec (getDefaultHandlingPattern());
235  }
236 
237  inline ExecResult
238  Command::exec ()
239  {
240  return exec (getDefaultHandlingPattern());
241  }
242 
243  inline ExecResult
244  Command::undo ()
245  {
246  return undo (getDefaultHandlingPattern());
247  }
248 
249 
250  template<typename...TYPES>
251  inline Command&
252  Command::bindArg (std::tuple<TYPES...> const& tuple)
253  {
254  TypedArguments<std::tuple<TYPES...>> args(tuple);
255  this->setArguments (args);
256  return *this;
257  }
258 
259 
260  inline Command&
261  Command::bindArg (lib::diff::Rec const& paramData)
262  {
263  this->setArguments (paramData);
264  return *this;
265  }
266 
267 
268 
269 
270  /* == state predicate shortcuts == */
271 
272  inline bool
273  Command::defined (Symbol cmdID)
274  {
275  return fetchDef(cmdID).isValid();
276  }
277 
278 
279 #define _FAILSAFE_COMMAND_QUERY(_ID_, _QUERY_) \
280  try \
281  { \
282  return Command::get(_ID_)._QUERY_; \
283  } \
284  catch(lumiera::error::Invalid&) \
285  { \
286  lumiera_error(); /* ignore errorstate */ \
287  return false; \
288  }
289 
290 
291  inline bool
292  Command::canExec (Symbol cmdID)
293  {
294  _FAILSAFE_COMMAND_QUERY (cmdID, canExec() );
295  }
296 
297 
298  inline bool
299  Command::canUndo (Symbol cmdID)
300  {
301  _FAILSAFE_COMMAND_QUERY (cmdID, canUndo() );
302  }
303 
304 #undef _FAILSAFE_COMMAND_QUERY
305 
306 
307 
308 
309  inline bool
310  operator== (Command const& c1, Command const& c2)
311  {
312  return (!c1 && !c2)
313  || ( c1 && c2 && (&c1.impl() == &c2.impl()));
314  }
315 
316  inline bool
317  operator!= (Command const& c1, Command const& c2)
318  {
319  return not (c1 == c2);
320  }
321 
323  inline bool
324  operator< (Command const& c1, Command const& c2)
325  {
326  return (!c1 && c2)
327  || ( c1 && c2 && (&c1.impl() < &c2.impl()));
328  }
329 
330 
331 
332 
333 }} // namespace steam::control
334 #endif
Helper class used solely for defining a Command-Object.
Basic set of definitions and includes commonly used together.
typename BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
Implementation helper to bind Steam-Layer commands with arbitrary argument tuples.
Mixin-templates providing arbitrary function call operators and argument binding functions.
#define LUMIERA_ERROR_DECLARE(err)
Forward declare an error constant.
Definition: error.h:71
Steam-Layer implementation namespace root.
bool operator<(Command const &c1, Command const &c2)
allow for sets and associative containers
Definition: command.hpp:324
Metaprogramming with tuples-of-types and the std::tuple record.
Token or Atom with distinct identity.
Definition: symbol.hpp:126
Helper Template for control::Command, mix-in complete set of bind(...) functions. ...
Marker types to indicate a literal string and a Symbol.
Result (Status) of command execution.
Command()
undefined command
Definition: command.hpp:145
Generic building block for tree shaped (meta)data structures.
Pre-defined command execution skeletons.
Lumiera error handling (C++ interface).
Handle object representing a single Command instance to be used by client code.
Definition: command.hpp:124
Lumiera public interface.
Definition: advice.cpp:113
A generic opaque handle to an implementation entity, including lifecycle management.
object-like record of data.
Definition: record.hpp:150
Interface: Operation Skeleton how to invoke or undo a command.