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)
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
59 #ifndef CONTROL_COMMAND_H
60 #define CONTROL_COMMAND_H
61 
62 #include "lib/error.hpp"
63 #include "lib/symbol.hpp"
64 #include "steam/common.hpp"
69 #include "lib/diff/gen-node.hpp"
70 #include "lib/handle.hpp"
71 
72 #include <string>
73 
74 
75 namespace lumiera {
76 namespace error {
77  LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS);
78  LUMIERA_ERROR_DECLARE (INVALID_COMMAND);
79  LUMIERA_ERROR_DECLARE (DUPLICATE_COMMAND);
80  LUMIERA_ERROR_DECLARE (INVALID_ARGUMENTS);
81  LUMIERA_ERROR_DECLARE (MISSING_MEMENTO);
82 }}
83 
84 namespace steam {
85 namespace control {
86 
87  using std::string;
88  using lib::Symbol;
89  using std::shared_ptr;
90  using lib::meta::Tuple;
91  using lib::meta::Types;
92 
93  using FuncPtr = void*;
94 
95  class CommandDef;
96  class CommandImpl;
97 
98 
115  class Command
116  : public AcceptAnyBinding<Command // accepts arbitrary bind(..) calls (with runtime check)
117  , Command& // (return value of bind() functions is *this)
118  , lib::Handle<CommandImpl> // actually implemented as ref counting Handle
119  > //
120  {
122 
123  public:
124  /* === command registry === */
125  static Command get (Symbol cmdID);
126  static bool remove (Symbol cmdID);
127 
129  Command storeDef (Symbol newCmdID) const;
130  Command newInstance () const;
131 
132  static Command maybeGetNewInstance (Symbol cmdID);
133 
134 
135  Command (Symbol cmdID) { *this = get (cmdID); }
136  Command() { }
137  ~Command();
138 
139  // default copy acceptable
140  Command (Command &&) = default;
141  Command (Command const&) = default;
142  Command& operator= (Command &&) = default;
143  Command& operator= (Command const&) = default;
144 
145 
146 
147  /* === command lifecycle === */
148 
149  template<typename...TYPES>
150  Command& bindArg (std::tuple<TYPES...> const&);
151 
152  Command& bindArg (lib::diff::Rec const&);
153 
154  Command& unbind();
155 
156 
157  ExecResult operator() () ;
158  ExecResult exec () ;
159  ExecResult undo () ;
160 
161 
166  ExecResult exec (HandlingPattern const& execPattern);
167  ExecResult exec (HandlingPattern::ID);
168 
169  ExecResult undo (HandlingPattern const& execPattern);
170  ExecResult undo (HandlingPattern::ID);
171 
173  ExecResult execSync ();
174 
176  HandlingPattern::ID getDefaultHandlingPattern() const;
177 
180  HandlingPattern::ID setHandlingPattern (HandlingPattern::ID);
181 
182 
183 
184  /* === diagnostics === */
185 
186  static size_t definition_count();
187  static size_t instance_count();
188 
189  bool canExec() const;
190  bool canUndo() const;
191 
192  static bool defined (Symbol cmdID);
193  static bool canExec (Symbol cmdID);
194  static bool canUndo (Symbol cmdID);
195 
196  void duplicate_detected (Symbol) const;
197 
198  Symbol getID() const noexcept;
199  bool isAnonymous() const;
200 
201  operator string() const;
202  friend bool operator== (Command const&, Command const&);
203  friend bool operator< (Command const&, Command const&);
204 
205 
206  protected:
207  static Command fetchDef (Symbol cmdID);
208  void activate (shared_ptr<CommandImpl> &&, Symbol cmdID =0);
209 
210  friend class CommandDef; //...invoking those two functions during definition stage
211 
212 
213  private:
214  void setArguments (Arguments&);
215  void setArguments (lib::diff::Rec const&);
216  };
217 
218 
219 
220 
221 
222  inline ExecResult
223  Command::operator() ()
224  {
225  return exec (getDefaultHandlingPattern());
226  }
227 
228  inline ExecResult
229  Command::exec ()
230  {
231  return exec (getDefaultHandlingPattern());
232  }
233 
234  inline ExecResult
235  Command::undo ()
236  {
237  return undo (getDefaultHandlingPattern());
238  }
239 
240 
241  template<typename...TYPES>
242  inline Command&
243  Command::bindArg (std::tuple<TYPES...> const& tuple)
244  {
245  TypedArguments<std::tuple<TYPES...>> args(tuple);
246  this->setArguments (args);
247  return *this;
248  }
249 
250 
251  inline Command&
252  Command::bindArg (lib::diff::Rec const& paramData)
253  {
254  this->setArguments (paramData);
255  return *this;
256  }
257 
258 
259 
260 
261  /* == state predicate shortcuts == */
262 
263  inline bool
264  Command::defined (Symbol cmdID)
265  {
266  return fetchDef(cmdID).isValid();
267  }
268 
269 
270 #define _FAILSAFE_COMMAND_QUERY(_ID_, _QUERY_) \
271  try \
272  { \
273  return Command::get(_ID_)._QUERY_; \
274  } \
275  catch(lumiera::error::Invalid&) \
276  { \
277  lumiera_error(); /* ignore errorstate */ \
278  return false; \
279  }
280 
281 
282  inline bool
283  Command::canExec (Symbol cmdID)
284  {
285  _FAILSAFE_COMMAND_QUERY (cmdID, canExec() );
286  }
287 
288 
289  inline bool
290  Command::canUndo (Symbol cmdID)
291  {
292  _FAILSAFE_COMMAND_QUERY (cmdID, canUndo() );
293  }
294 
295 #undef _FAILSAFE_COMMAND_QUERY
296 
297 
298 
299 
300  inline bool
301  operator== (Command const& c1, Command const& c2)
302  {
303  return (!c1 && !c2)
304  || ( c1 && c2 && (&c1.impl() == &c2.impl()));
305  }
306 
307  inline bool
308  operator!= (Command const& c1, Command const& c2)
309  {
310  return not (c1 == c2);
311  }
312 
314  inline bool
315  operator< (Command const& c1, Command const& c2)
316  {
317  return (!c1 && c2)
318  || ( c1 && c2 && (&c1.impl() < &c2.impl()));
319  }
320 
321 
322 
323 
324 }} // namespace steam::control
325 #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:62
Steam-Layer implementation namespace root.
bool operator<(Command const &c1, Command const &c2)
allow for sets and associative containers
Definition: command.hpp:315
Metaprogramming with tuples-of-types and the std::tuple record.
Token or Atom with distinct identity.
Definition: symbol.hpp:117
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:136
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:115
Lumiera public interface.
Definition: advice.cpp:104
A generic opaque handle to an implementation entity, including lifecycle management.
object-like record of data.
Definition: record.hpp:141
Interface: Operation Skeleton how to invoke or undo a command.