diff --git a/doc/devel/draw/CommandImpl-1.svg b/doc/devel/draw/CommandImpl-1.svg index 1ebb5963c..5e4bc6b1d 100644 --- a/doc/devel/draw/CommandImpl-1.svg +++ b/doc/devel/draw/CommandImpl-1.svg @@ -28,12 +28,12 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1.4142136" - inkscape:cx="601.93284" - inkscape:cy="351.50263" + inkscape:cx="410.87417" + inkscape:cy="293.93224" inkscape:document-units="px" inkscape:current-layer="svg2" inkscape:window-width="1668" - inkscape:window-height="1016" + inkscape:window-height="1020" inkscape:window-x="0" inkscape:window-y="0" width="800px" @@ -65,6 +65,22 @@ + + + CommandDef + x="677" + y="-79.5" /> start( slot ) Player (interface) - play() GUI (Plugin) + x="174.71809" + y="79.693436">GUI Proc (or Backend?) + sodipodi:role="line">Proc-Layer Proxy<Player> start(...) Command + x="269.46484" + y="240.8103" /> Handle<CommandImpl> yields has_a + x="992.078" + y="41" /> Display (iface) + x="835.5" + y="54.5">Display (iface) Proxy<Display> + x="336.36804" + y="31.810305" /> + x="470.0473" + y="130.3103" /> CommandImpl CommandRegistry CommandImpl CommandImpl open(...) + sodipodi:role="line">xxx(...) close() + x="353.36804" + y="95.242737" + style="font-size:8px;font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">sss() getHandle(slot) + y="64.81031" + x="353.36804" + sodipodi:role="line" + id="tspan2741">Command::get("name") getHandle(slot) getHandle(slot) - yields CL Interface - pause() - stop() - use_display (slot) dispatch toGTK main thread... exec(..) undo(..) bind(..) Index basic def undo def Command Command + id="g2665" + transform="translate(-3.5140952e-2,-159.6897)"> ArgumentHolder + transform="translate(-3.5140952e-2,-119.50726)"> getHandle(slot) + transform="translate(70.675549,-274.241)"> @@ -1501,24 +1450,24 @@ id="rect16814" width="70.181519" height="20" - x="470" - y="330" + x="469.96484" + y="170.3103" inkscape:export-filename="/home/hiv/devel/lumi/wiki/draw/PlayerArch1.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90" /> CommandImpl Command Impl + + CommandDefinition ("name1") .operation (func1) .captureUndo (func2) .undoOperation (func3) .bind (...) + + mutation functor + + undo functor + + + closure + + + arg + + + + arg + + + + arg + + + + arg + + + memento + + + + ProcDispatcher + + HandlingPattern diff --git a/src/lib/handle.hpp b/src/lib/handle.hpp index 54bff4c89..948130ac8 100644 --- a/src/lib/handle.hpp +++ b/src/lib/handle.hpp @@ -44,7 +44,7 @@ #define LIB_HANDLE_H #include "lib/nobug-init.hpp" -#include "lib/sync.hpp" +#include "lib/bool-checkable.hpp" #include @@ -61,13 +61,14 @@ namespace lib { * and managing its lifecycle. Usually such a handle is created by * an service interface and \link #activate activated \endlink by * setting up the link to some internal implementation object. - * This setup can only be done by a friend or derived class, + * This setup can only be done by a friend or derived class, //////////////////////////TODO: that was the intention. Why didn't this work out as expected? * while client code is free to copy and store handle objects. * Finally, any handle can be closed, thereby decrementing * the use count. */ template class Handle + : public lib::BoolCheckable > { protected: typedef std::tr1::shared_ptr SmPtr; @@ -115,11 +116,8 @@ namespace lib { void close () { smPtr_.reset(); } - typedef SmPtr Handle::*__unspecified_bool_type; - - /** implicit conversion to "bool" */ - operator __unspecified_bool_type() const { return smPtr_? &Handle::smPtr_ : 0; } // never throws - bool operator! () const { return !bool(smPtr_); } // ditto + /** implicit conversion to bool (BoolCheckable) */ + bool isValid() const { return bool(smPtr_);} diff --git a/src/proc/control/command-def.hpp b/src/proc/control/command-def.hpp index c310a531f..43603bfe1 100644 --- a/src/proc/control/command-def.hpp +++ b/src/proc/control/command-def.hpp @@ -191,7 +191,7 @@ namespace control { : public lib::BoolCheckable { Symbol id_; - Command& prototype_; + Command prototype_; public: CommandDef (Symbol cmdID) diff --git a/src/proc/control/command-impl.cpp b/src/proc/control/command-impl.cpp index 39cb0b290..a2aed63c3 100644 --- a/src/proc/control/command-impl.cpp +++ b/src/proc/control/command-impl.cpp @@ -47,6 +47,20 @@ namespace control { /** */ + template + void + CommandImpl::bindArg (Tuple const&) + { + UNIMPLEMENTED ("actually bind arguments, maybe create ArgumentHolder"); + } + + + void + CommandImpl::exec (HandlingPattern const& execPattern) + { + UNIMPLEMENTED ("actually invoke the command"); + } + diff --git a/src/proc/control/command-registry.hpp b/src/proc/control/command-registry.hpp index 1b398c0f2..5cadf66fe 100644 --- a/src/proc/control/command-registry.hpp +++ b/src/proc/control/command-registry.hpp @@ -39,6 +39,8 @@ //#include "pre.hpp" #include "lib/error.hpp" +#include "lib/singleton.hpp" +#include "lib/sync.hpp" //#include "lib/bool-checkable.hpp" //#include "proc/control/command-closure.hpp" //#include "proc/control/memento-tie.hpp" @@ -60,14 +62,67 @@ namespace control { * TODO type comment */ class CommandRegistry + : lib::Sync<> { public: + static lumiera::Singleton instance; + + + /** register a command (Frontend) under the given ID + * @return either the new command, or an already existing + * command registerd under the given ID*/ + static Command& + track (Symbol cmdID, Command& commandHandle) + { + return instance().putIndex (cmdID, commandHandle); + } + + + /** set up a new command implementation frame */ + static CommandImpl* + newCommandImpl () + { + return instance().createImpl(); + } + + + /** discard an command implementation frame */ + static void + killCommandImpl (CommandImpl* entry) + { + ///////////////////////////////////////////////TODO: clean behaviour while in App shutdown (Ticket #196) + instance().removeImpl(entry); + } + + + private: + CommandImpl* + createImpl () + { + Lock sync(this); + UNIMPLEMENTED ("set up a new impl instance located within the instance table"); + } + + void + removeImpl (CommandImpl* entry) + { + UNIMPLEMENTED ("remove entry from instance table"); + } + + Command& + putIndex (Symbol cmdID, Command& commandHandle) + { + Lock sync(this); + UNIMPLEMENTED ("place a commandHandle into the command index, or return the command already registered there"); + } }; // inline ostream& operator<< (ostream& os, Mutation const& muta) { return os << string(muta); } + /** storage for the singleton factory used to access CommandRegistry */ + lumiera::Singleton CommandRegistry::instance; } // namespace control diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index bc9f1fba6..4a2ead3f7 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -48,10 +48,17 @@ namespace control { LUMIERA_ERROR_DEFINE (UNBOUND_ARGUMENTS, "Command mutation functor not yet usable, because arguments aren't bound"); LUMIERA_ERROR_DEFINE (MISSING_MEMENTO, "Undo functor not yet usable, because no undo state has been captured"); - + Command::~Command() { } + + /** @internal to be invoked by #fetchDef */ + Command::Command (CommandImpl* pImpl) + { + Handle::activate (pImpl, CommandRegistry::killCommandImpl); + } + /** */ Command& @@ -64,7 +71,14 @@ namespace control { Command& Command::fetchDef (Symbol cmdID) { - UNIMPLEMENTED ("fetch an command prototype from the registry, create if necessary"); + Command* cmd = CommandRegistry::queryIndex (cmdID); + if (cmd) + ////////////////////////////////////////////////////////////////////////TODO: race + return *cmd; + + Command newDefinition (CommandRegistry::newCommandImpl()); + + return CommandRegistry::track (cmdID, newDefinition); } diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index e07653b93..5be5474c8 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -67,9 +67,10 @@ namespace control { * @todo Type-comment */ class Command - : public com::ArgumentBinder > - ////////////////////////////////////////////////////////////////TODO: inherit from lib/handle + : public com::ArgumentBinder // actually implemented as ref counting Handle + > > { public: @@ -112,10 +113,21 @@ namespace control { bool canUndo() const; protected: - static Command& fetchDef (Symbol cmdID); + static Command& fetchDef (Symbol cmdID); + + friend class CommandDef; + + + private: + /** Commands can only be created through the framework + * (by setting up an CommandDef), thus ensuring there's + * always a corresponding CommandImpl within the registry. + * @note the copy operations are public though + * @see Command#fetchDef + * @see CommandDef + */ + Command (CommandImpl* pImpl); - friend class CommandDef; - }; ////////////////TODO currently just fleshing out the API....