Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
command.cpp
Go to the documentation of this file.
1/*
2 Command - 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
33#include "lib/error.hpp"
34#include "lib/symbol.hpp"
35#include "lib/format-string.hpp"
42#include "lib/util.hpp"
43
44#include <utility>
45#include <sstream>
46#include <string>
47
48using std::ostringstream;
49using std::string;
50using std::move;
51using util::_Fmt;
52
53
54namespace lumiera {
55namespace error {
56 LUMIERA_ERROR_DEFINE (INVALID_COMMAND, "Unknown or insufficiently defined command");
57 LUMIERA_ERROR_DEFINE (DUPLICATE_COMMAND, "Attempt to redefine an already existing command definition");
58 LUMIERA_ERROR_DEFINE (INVALID_ARGUMENTS, "Arguments provided for binding doesn't match stored command function parameters");
59 LUMIERA_ERROR_DEFINE (UNBOUND_ARGUMENTS, "Command mutation functor not yet usable, because arguments aren't bound");
60 LUMIERA_ERROR_DEFINE (MISSING_MEMENTO, "Undo functor not yet usable, because no undo state has been captured");
61}}
62
63namespace steam {
64namespace control {
65 namespace error = lumiera::error;
66
67
68 namespace { // some common error checks...
69
70 void
72 {
73 REQUIRE (handle);
74 if (!handle->isValid())
75 throw error::Invalid (operation_descr+" an undefined command"
76 , LERR_(INVALID_COMMAND));
77 }
78
79 void
80 ___check_isBound (const Command *handle)
81 {
82 REQUIRE (handle);
83 if (!handle->canExec())
84 throw error::State ("Lifecycle error: command arguments not bound"
85 , LERR_(UNBOUND_ARGUMENTS));
86 }
87
88 void
89 ___check_canUndo (const Command *handle)
90 {
91 REQUIRE (handle);
92 if (!handle->canUndo())
93 throw error::State ("Lifecycle error: command has not yet captured UNDO information"
94 , LERR_(UNBOUND_ARGUMENTS));
95 }
96
97 }
98
99
100
101
104
105
108
109
110
111
119 Command
121 {
122 Command cmd = CommandRegistry::instance().queryIndex (cmdID);
123 if (!cmd)
124 throw error::Invalid(_Fmt("Command \"%s\" not found") % cmdID
125 , LERR_(INVALID_COMMAND));
126
127 ENSURE (cmdID == CommandRegistry::instance().findDefinition(cmd));
128 return cmd;
129 }
130
131
139 Command
141 {
142 Command cmd = CommandRegistry::instance().queryIndex (cmdID);
143 return cmd? cmd.newInstance()
144 : Command{};
145 }
146
147
149 Command
151 {
152 return CommandRegistry::instance().queryIndex (cmdID);
153 }
154
155
161 void
163 {
165
166 if (this->isValid())
167 duplicate_detected (cmdID);
168
170 if (cmdID)
171 {
172 CommandRegistry::instance().track (cmdID, *this);
173 impl().cmdID = cmdID;
174 }
175
176 TRACE (command, "%s defined OK", cStr(*this));
177 }
178
179
182 Command
184 {
186
187 ___check_notBottom (this,"Cloning");
188 if (registry.queryIndex (newCmdID))
190
192 cloneDefinition.activate (move (registry.createCloneImpl(this->impl())), newCmdID);
194 return cloneDefinition;
195 }
196
197
199 Command
201 {
202 ___check_notBottom (this,"Cloning");
204 shared_ptr<CommandImpl> cloneImpl = registry.createCloneImpl(this->impl());
205
206 Command clone;
207 clone.activate (move (cloneImpl));
208 ENSURE (clone);
209 return clone;
210 }
211
212
226
227
228
229 void
231 {
232 throw error::Logic (_Fmt("Unable to store %s as new command. "
233 "ID \"%s\" is already in use")
234 % *this
235 % newCmdID
236 , LERR_(DUPLICATE_COMMAND));
237 }
238
239
240 bool
242 {
243 return CommandRegistry::instance().remove (cmdID);
244 }
245
246
250 void
252 {
253 ___check_notBottom (this, "Binding arguments of");
254 _Handle::impl().setArguments(args);
255 }
256
257
263 void
265 {
266 ___check_notBottom (this, "Binding arguments of");
267 _Handle::impl().setArguments(paramData);
268 }
269
270
278 Command&
280 {
281 ___check_notBottom (this, "Un-binding arguments of");
282 _Handle::impl().discardArguments();
283 return *this;
284 }
285
286
288 size_t
290 {
291 return CommandRegistry::instance().index_size();
292 }
293
294
295
297 size_t
299 {
300 return CommandRegistry::instance().instance_count();
301 }
302
303
304
305 namespace {
306 inline bool
308 {
309 return com.isValid();
310 }
311
312 inline Command
314 {
315 return CommandRegistry::instance().queryIndex (id);
316 }
317 }
318
319
327 {
328 if (!was_activated (prototype_))
330 }
331
332
339 bool
341 {
342 return (was_activated (prototype_))
343 and (prototype_ == registered_for (this->id_))
344 ;
345 }
346
347
348
349 bool
351 {
352 return isValid()
353 and impl().canExec();
354 }
355
356
357 bool
359 {
360 return isValid()
361 and impl().canUndo();
362 }
363
364
365 Symbol
367 {
368 return isValid()? impl().cmdID
370 }
371
372
378 bool
380 {
381 return not CommandRegistry::instance().findDefinition (*this);
382 }
383
384
385
386
389 Command::operator string() const
390 {
391 ostringstream repr;
393 repr << "Command(\""<<getID()<<"\") ";
394 if (!isValid())
395 repr << "NIL";
396 else
397 if (canUndo())
398 repr << "{undo}";
399 else
400 if (canExec())
401 repr << "{exec}";
402 else
403 repr << "{def}";
404
405 return repr.str();
406 }
407
408
409
410
413 {
414 ___check_notBottom (this,"Invoking");
415 ___check_isBound (this);
416
417 string cmdName{*this};
419 return execPattern.exec (thisCommand, cmdName);
420 }
421
422
425 {
426 ___check_notBottom (this,"UNDOing");
427 ___check_canUndo (this);
428
429 string cmdName{*this};
431 return execPattern.undo (thisCommand, cmdName);
432 }
433
434
440
441
447
448
454
455
458 {
459 ___check_notBottom (this,"Accessing");
460 return impl().getDefaultHandlingPattern();
461 }
462
463
466 {
467 ___check_notBottom (this, "Configuring");
468 return impl().setHandlingPattern(pattID);
469 }
470
471
472
473
474
475}} // namespace steam::control
Access point to singletons and other kinds of dependencies designated by type.
Definition depend.hpp:281
CommandImpl & impl() const
Definition handle.hpp:149
Handle & activate(CommandImpl *impl, DEL whenDead)
Activation of the handle by the managing service.
Definition handle.hpp:112
Inline string literal.
Definition symbol.hpp:78
Token or Atom with distinct identity.
Definition symbol.hpp:120
static Symbol FAILURE
Definition symbol.hpp:125
shared_ptr< XX > create(ARGS &&...args)
object-like record of data.
Definition record.hpp:142
bool isValid() const
is this a valid command definition? especially.
Definition command.cpp:340
~CommandDef()
when starting a CommandDef, we immediately place a yet empty Command object into the index,...
Definition command.cpp:326
Visitor to support creating a CommandImpl clone.
Steam-Layer Command implementation.
Registry managing command implementation objects (Singleton).
static lib::Depend< CommandRegistry > instance
storage for the singleton factory used to access CommandRegistry
Command queryIndex(Symbol cmdID)
query the command index by ID
shared_ptr< CommandImpl > createCloneImpl(CommandImpl const &refObject)
create an allocation for holding a clone of the given CommandImpl data.
Definition command.cpp:219
Handle object representing a single Command instance to be used by client code.
Definition command.hpp:120
ExecResult execSync()
invoke using a default "synchronous" execution pattern
Definition command.cpp:450
void duplicate_detected(Symbol) const
Definition command.cpp:230
HandlingPattern::ID setHandlingPattern(HandlingPattern::ID)
define a handling pattern to be used by default
Definition command.cpp:465
static Command maybeGetNewInstance(Symbol cmdID)
try to access an existing command definition and immediately create a new clone copy by calling newIn...
Definition command.cpp:140
bool isAnonymous() const
Definition command.cpp:379
static size_t definition_count()
Definition command.cpp:289
static Command fetchDef(Symbol cmdID)
Definition command.cpp:150
Command & unbind()
discard any argument data previously bound.
Definition command.cpp:279
void activate(shared_ptr< CommandImpl > &&, Symbol cmdID=0)
Definition command.cpp:162
void setArguments(Arguments &)
Definition command.cpp:251
Command newInstance() const
create independent (anonymous) clone copy of this command
Definition command.cpp:200
Symbol getID() const noexcept
Definition command.cpp:366
static Command get(Symbol cmdID)
Access existing command for use.
Definition command.cpp:120
HandlingPattern::ID getDefaultHandlingPattern() const
Definition command.cpp:457
static bool remove(Symbol cmdID)
Definition command.cpp:241
Command storeDef(Symbol newCmdID) const
create a clone definition
Definition command.cpp:183
static size_t instance_count()
Definition command.cpp:298
Result (Status) of command execution.
Interface: Operation Skeleton how to invoke or undo a command.
static HandlingPattern const & get(ID id)
retrieve the pre-configured pattern
A front-end for using printf-style formatting.
Actually defining a command and binding it to execution parameters.
Helper for creating an implementation clone, based on the visitor pattern.
Top level of the command implementation.
Managing command definitions and the storage of individual command objects.
Steam-Layer command frontend.
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition error.h:71
Lumiera error handling (C++ interface).
#define LERR_(_NAME_)
Definition error.hpp:45
Front-end for printf-style string template interpolation.
Pre-defined command execution skeletons.
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
LumieraError< LERR_(STATE)> State
Definition error.hpp:209
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
LumieraError< LERR_(INVALID)> Invalid
Definition error.hpp:211
Lumiera public interface.
Definition advice.hpp:102
void ___check_notBottom(const Command *handle, lib::Literal operation_descr)
Definition command.cpp:71
void ___check_isBound(const Command *handle)
Definition command.cpp:80
void ___check_canUndo(const Command *handle)
Definition command.cpp:89
Steam-Layer implementation namespace root.
Marker types to indicate a literal string and a Symbol.
CStr cStr(std::string const &rendered)
convenience shortcut: forced conversion to c-String via string.
Definition symbol.hpp:60
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...