2017-03-08 04:25:33 +01:00
|
|
|
/*
|
2017-03-18 01:55:45 +01:00
|
|
|
CommandSetup - Implementation of command registration and instance management
|
2017-03-08 04:25:33 +01:00
|
|
|
|
|
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2017, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of
|
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
* *****************************************************/
|
|
|
|
|
|
|
|
|
|
|
2017-03-18 01:55:45 +01:00
|
|
|
/** @file command-setup.cpp
|
2017-03-08 04:25:33 +01:00
|
|
|
** Implementation details of instance management for command invocation by the GUI.
|
|
|
|
|
**
|
2017-03-18 01:55:45 +01:00
|
|
|
** @see command-setup.hpp
|
|
|
|
|
** @see command-instance-manager.hpp
|
|
|
|
|
** @see TODO_CommandInstanceManager_test
|
2017-03-08 04:25:33 +01:00
|
|
|
** @see command.hpp
|
|
|
|
|
** @see command-registry.hpp
|
|
|
|
|
**
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/error.hpp"
|
|
|
|
|
//#include "lib/symbol.hpp"
|
2017-03-18 05:28:56 +01:00
|
|
|
#include "include/logging.h"
|
2017-03-08 04:25:33 +01:00
|
|
|
//#include "lib/format-string.hpp"
|
2017-03-18 03:20:05 +01:00
|
|
|
#include "proc/control/command-setup.hpp"
|
2017-03-08 04:25:33 +01:00
|
|
|
#include "proc/control/command-instance-manager.hpp"
|
2017-03-18 05:28:56 +01:00
|
|
|
#include "proc/control/command-def.hpp"
|
|
|
|
|
//#include "lib/util.hpp"
|
2017-03-08 04:25:33 +01:00
|
|
|
|
2017-03-18 04:40:16 +01:00
|
|
|
|
2017-03-08 04:25:33 +01:00
|
|
|
//#include <string>
|
2017-03-18 04:40:16 +01:00
|
|
|
#include <tuple>
|
|
|
|
|
#include <utility>
|
2017-03-08 04:25:33 +01:00
|
|
|
|
|
|
|
|
//using std::string;
|
2017-03-18 04:40:16 +01:00
|
|
|
using std::tuple;
|
2017-03-18 05:28:56 +01:00
|
|
|
using std::get;
|
2017-03-18 03:52:18 +01:00
|
|
|
using std::function;
|
2017-03-18 04:40:16 +01:00
|
|
|
using std::move;
|
2017-03-18 05:28:56 +01:00
|
|
|
using lib::Symbol;
|
2017-03-08 04:25:33 +01:00
|
|
|
//using util::cStr;
|
|
|
|
|
//using util::_Fmt;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace proc {
|
|
|
|
|
namespace control {
|
|
|
|
|
namespace error = lumiera::error;
|
|
|
|
|
|
|
|
|
|
|
2017-03-18 04:40:16 +01:00
|
|
|
namespace { // implementation details of command setup...
|
|
|
|
|
|
2017-03-18 05:28:56 +01:00
|
|
|
using CmdDefEntry = std::tuple<Symbol, DefinitionClosure>;
|
2017-03-18 04:40:16 +01:00
|
|
|
|
|
|
|
|
std::deque<CmdDefEntry> pendingCmdDefinitions;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}//(End) implementation details
|
2017-03-08 04:25:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** storage for.... */
|
|
|
|
|
|
|
|
|
|
|
2017-03-18 03:20:05 +01:00
|
|
|
CommandSetup::~CommandSetup() { }
|
|
|
|
|
|
2017-03-18 04:40:16 +01:00
|
|
|
/** Start a command setup for defining a Proc-Layer command with the given cmdID */
|
2017-03-18 03:20:05 +01:00
|
|
|
CommandSetup::CommandSetup(Literal cmdID)
|
|
|
|
|
: cmdID_(cmdID)
|
|
|
|
|
{ }
|
2017-03-18 03:52:18 +01:00
|
|
|
|
|
|
|
|
|
2017-03-18 04:40:16 +01:00
|
|
|
/**
|
|
|
|
|
* @param definitionBlock anything assignable to `function<void(CommandDef&)>`
|
|
|
|
|
* @remarks this operation is intended for a very specific usage pattern, as established
|
|
|
|
|
* by the macro #COMMAND_DEFINITION. The purpose is to feed a given code block
|
|
|
|
|
* into the hidden queue for command definitions, from where it will be issued
|
|
|
|
|
* at the lifecycle event ON_BASIC_INIT (typically at start of application `main()`).
|
|
|
|
|
* On invocation, the code block is provided with an still unbound CommandDef object,
|
|
|
|
|
* which has been registered under the Command-ID as stored in this CommandSetup object.
|
|
|
|
|
* The assumption is that this _definition closure_ will care to define the command,
|
|
|
|
|
* state capturing and undo operations for the command definition in question. Thus,
|
|
|
|
|
* the result of invoking this closure will be to store a complete command prototype
|
|
|
|
|
* into the proc::control::CommandRegistry.
|
|
|
|
|
* @note this operation works by side-effect; the given argument is fed into a hidden static
|
|
|
|
|
* queue, but not stored within the object instance.
|
|
|
|
|
* @warning invoking this assignment _several times on the same CommandSetup object_ will likely
|
|
|
|
|
* lead to an invalid state, causing the Lumiera application to fail on start-up. The
|
|
|
|
|
* reason for this is the fact that CommandDef rejects duplicate command definitions.
|
|
|
|
|
* Moreover, please note that invoking this operation at any point _after_ the
|
|
|
|
|
* lifecycle event ON_BASIC_INIT will likely have no effect at all, since the
|
|
|
|
|
* given closure will then just sit in the static queue and never be invoked.
|
|
|
|
|
*/
|
2017-03-18 03:52:18 +01:00
|
|
|
CommandSetup&
|
2017-03-18 04:40:16 +01:00
|
|
|
CommandSetup::operator= (DefinitionClosure definitionBlock)
|
2017-03-18 03:52:18 +01:00
|
|
|
{
|
2017-03-18 04:40:16 +01:00
|
|
|
if (not definitionBlock)
|
|
|
|
|
throw error::Invalid ("unbound function/closure provided for CommandSetup"
|
|
|
|
|
, error::LUMIERA_ERROR_BOTTOM_VALUE);
|
|
|
|
|
|
2017-03-18 05:28:56 +01:00
|
|
|
pendingCmdDefinitions.emplace_front (Symbol(cmdID_), move(definitionBlock));
|
2017-03-18 04:40:16 +01:00
|
|
|
return *this;
|
2017-03-18 03:52:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-03-18 05:28:56 +01:00
|
|
|
size_t
|
|
|
|
|
CommandSetup::invokeDefinitionClosures()
|
|
|
|
|
{
|
|
|
|
|
size_t cnt=0;
|
|
|
|
|
while (not pendingCmdDefinitions.empty())
|
|
|
|
|
{
|
|
|
|
|
CmdDefEntry& entry = pendingCmdDefinitions.back();
|
|
|
|
|
Symbol& cmdID{get<Symbol>(entry)};
|
|
|
|
|
DefinitionClosure& buildDefinition{get<DefinitionClosure> (entry)};
|
|
|
|
|
|
|
|
|
|
INFO (command, "defining Command(%s)...", cmdID.c());
|
|
|
|
|
CommandDef def(cmdID);
|
|
|
|
|
buildDefinition(def);
|
|
|
|
|
++cnt;
|
|
|
|
|
pendingCmdDefinitions.pop_back();
|
|
|
|
|
}
|
|
|
|
|
return cnt;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 03:52:18 +01:00
|
|
|
size_t
|
|
|
|
|
CommandSetup::pendingCnt()
|
|
|
|
|
{
|
2017-03-18 04:40:16 +01:00
|
|
|
return pendingCmdDefinitions.size();
|
2017-03-18 03:52:18 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-18 03:20:05 +01:00
|
|
|
|
2017-03-08 04:25:33 +01:00
|
|
|
// emit dtors of embedded objects here....
|
|
|
|
|
CommandInstanceManager::~CommandInstanceManager() { }
|
|
|
|
|
|
|
|
|
|
CommandInstanceManager::CommandInstanceManager() { }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** more to come here...*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}} // namespace proc::control
|