From 2e4d74747e98437bf30e3ca5d1ae10588d227dfd Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 2 Jan 2016 19:16:37 +0100 Subject: [PATCH] implement logging overrides in the Test-Nexus implementation the actual functionality is forwareded to the base class, which is the regular Nexus Hub --- src/gui/ctrl/nexus.hpp | 7 +++ tests/gui/bus-term-test.cpp | 10 ++-- tests/gui/test/test-nexus.cpp | 88 +++++++++++++++++++++++++++++++++-- wiki/renderengine.html | 8 ++-- 4 files changed, 99 insertions(+), 14 deletions(-) diff --git a/src/gui/ctrl/nexus.hpp b/src/gui/ctrl/nexus.hpp index c0e1108f2..b99d604ec 100644 --- a/src/gui/ctrl/nexus.hpp +++ b/src/gui/ctrl/nexus.hpp @@ -84,6 +84,7 @@ namespace ctrl{ RoutingTable routingTable_; + protected: /** route mark messages down to the individual Tangible. * @note only messages to elements currently registered * in the routing table are dispatched. All other @@ -129,6 +130,12 @@ namespace ctrl{ } + size_t + size() const + { + return routingTable_.size(); + } + public: explicit Nexus (BusTerm& uplink_to_CoreService, ID identity =lib::idi::EntryID()) diff --git a/tests/gui/bus-term-test.cpp b/tests/gui/bus-term-test.cpp index 2683b2364..e27ae5b56 100644 --- a/tests/gui/bus-term-test.cpp +++ b/tests/gui/bus-term-test.cpp @@ -119,7 +119,7 @@ namespace test { MockElm mock(elmID); CHECK (nexusLog.verifyCall("routeAdd").on("TestNexus").arg(elmID,"MockElm") - .beforeEvent("TestNexus", "add route to bID-zeitgeist")); + .beforeEvent("TestNexus", "added route to bID-zeitgeist")); EventLog elmLog = mock.getLog(); CHECK (elmLog.verifyCall("ctor").on(&mock) @@ -137,10 +137,10 @@ namespace test { CHECK (elmLog.verifyEvent("collapsed")); CHECK (nexusLog.verifyCall("note").on("TestNexus").arg("zeitgeist", "collapse")); - // send a note down to the mock element - gui::test::Nexus::testUI().note (elmID, GenNode("Flash", 23)); + // send a state mark down to the mock element + gui::test::Nexus::testUI().mark (elmID, GenNode("Flash", 23)); CHECK (nexusLog.verifyCall("note").on("TestNexus").arg(elmID, "Flash") - .beforeEvent("TestNexus", "note to bID-zeitgeist")); + .beforeEvent("TestNexus", "mark to bID-zeitgeist")); CHECK (elmLog.verifyCall("doFlash").on("zeitgeist")); @@ -148,7 +148,7 @@ namespace test { mock.kill(); CHECK (elmLog.verifyEvent("destroy","zeitgeist")); CHECK (nexusLog.verifyCall("routeDetach").on("TestNexus").arg(elmID) - .beforeEvent("TestNexus", "remove route to bID-zeitgeist")); + .beforeEvent("TestNexus", "removed route to bID-zeitgeist")); gui::test::Nexus::testUI().note (elmID, GenNode("Flash", 88)); CHECK (nexusLog.verify("remove route to bID-zeitgeist") diff --git a/tests/gui/test/test-nexus.cpp b/tests/gui/test/test-nexus.cpp index bf60f3e60..9c8f01700 100644 --- a/tests/gui/test/test-nexus.cpp +++ b/tests/gui/test/test-nexus.cpp @@ -43,6 +43,7 @@ #include "lib/idi/entry-id.hpp" #include "lib/idi/genfunc.hpp" #include "lib/depend.hpp" +#include "lib/format-string.hpp" //#include "lib/util.hpp" #include @@ -57,6 +58,7 @@ using std::string; using lib::test::EventLog; using lib::diff::GenNode; using gui::ctrl::BusTerm; +using util::_Fmt; //using util::contains; //using util::isnil; @@ -65,6 +67,48 @@ namespace test{ namespace { // internal details + using lib::Variant; + using lib::diff::Rec; + using lib::diff::DataValues; + + using BusHub = gui::ctrl::Nexus; + + + /** helper to figure out if a command message + * is a binding or invocation message. + * @remarks from a design standpoint, this is ugly, + * since we're basically switching on type. + * Well -- we do it just for diagnostics here, + * so _look away please..._ + */ + inline bool + isCommandBinding (GenNode const& msg) + { + class CommandBindingDetector + : public Variant::Predicate + { + bool handle (Rec const&) override { return true; } + } + detector; + + return msg.data.accept (detector); + } + + inline string + invocationStage (GenNode const& msg) + { + return isCommandBinding(msg)? string("binding for") + : string("invoke"); + } + + inline string + renderBindingArgs (GenNode const& msg) + { + return isCommandBinding(msg)? "| " + string(msg.data.get()) + : ""; + } + + /** * @internal fake interface backbone and unit test rig * for simulated command and presentation state handling. @@ -75,7 +119,7 @@ namespace test{ * state messages */ class TestNexus - : public gui::ctrl::Nexus + : public BusHub { EventLog log_{this}; @@ -83,25 +127,59 @@ namespace test{ virtual void act (GenNode const& command) { - UNIMPLEMENTED("receive and handle command invocation"); + log_.call(this, "act", command); + BusHub::act (command); + log_.event("TestNexus", _Fmt("%s command \"%s\"%s") + % invocationStage(command) + % command.idi.getSym() + % renderBindingArgs(command)); } - virtual void note (ID subject, GenNode const& mark) override { - UNIMPLEMENTED ("receive and handle presentation state note messages."); + log_.call(this, "note", subject, mark); + BusHub::note (subject, mark); + log_.event("TestNexus", _Fmt("processed note from %s |%s") % subject % mark); } + virtual void + mark (ID subject, GenNode const& mark) override + { + log_.call(this, "mark", subject, mark); + BusHub::mark (subject, mark); + log_.event("TestNexus", _Fmt("delivered mark to %s |%s") % subject % mark); + } virtual operator string() const { return getID().getSym()+"."+lib::idi::instanceTypeID(this); } + virtual BusTerm& + routeAdd (ID identity, Tangible& newNode) override + { + log_.call(this, "routeAdd", identity, newNode); + BusHub::routeAdd (identity, newNode); + log_.event("TestNexus", _Fmt("added route to %s |%s| table-size=%2d") + % identity + % lib::idi::instanceTypeID(&newNode) + % BusHub::size()); + return *this; + } + + virtual void + routeDetach (ID node) noexcept override + { + log_.call(this, "routeDetach", node); + BusHub::routeDetach (node); + log_.event("TestNexus", _Fmt("removed route to %s | table-size=%2d") % node % BusHub::size()); + } + + public: TestNexus() - : Nexus(*this, lib::idi::EntryID("mock-UI")) + : BusHub(*this, lib::idi::EntryID("mock-UI")) { } // standard copy operations diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 41b3b0773..e19d78680 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2383,7 +2383,7 @@ On a second thought, the fact that the [[Bus-MObject|BusMO]] is rather void of a :sound mixing desks use list style arrangement, and this has proven to be quite viable, when combined with the ability to //send over// output from one mixer stripe to the input of another, allowing to build arbitrary complex filter matrices. On the other hand, organising a mix in //subgroups// can be considered best practice. This leads to arranging the pipes //as wood:// by default and on top level as list, optionally expanding into a subtree with automatic rooting, augmented by the ability to route any output to any input (cycles being detected and flagged as error). -
+
The question //how to connect the notion of an ''interface action'' to the notion of a ''command'' issued towards the [[session model|HighLevelModel]].//
 
 !prerequisites for issuing a command
@@ -2399,7 +2399,7 @@ Within the Lumiera architecture, with the very distinct separation between [[Ses
 ** the focus and current selection is relevant
 ** the user interaction might supply context by pointing at something
 ** the proximity of tangible interface elements might be sufficient to figure out missing parts
-** in fact it might be necessary to prepend the invocation of a detail parameter dialog to the command execution
+** in fact it might be necessary to intersperse the invocation of a detail parameter dialogue prior to command execution
 * and finally, after considering all these concerns, it is possible to wire a connection into the actual invocation point in UI
 This observation might be surprising; even while a given command is well defined, we can not just invoke it right away. The prevalence of all these intermediary complexities is what opens the necessity and the room for InteractionControl, which is a concern specific to human-computer interfaces. Faced with such a necessity, there are two fundamentally different approaches.
 !!!Binding close to the widget
@@ -2954,9 +2954,9 @@ From experiences with other middle scale projects, I prefer having the test code
 [img[Example: Interfaces/Namespaces of the ~Session-Subsystems|uml/fig130053.png]]
 
-
+
//A command in preparation of being issued from the UI.//
-The actual persistent operations on the session model are defined as DSL scripts acting on the session interface, and configured as a //command prototype.// Typically these need to be enriched with at least the actual subject to invoke this command on; many commands require additional parameters, e.g. some time or colour value. These actual invocation parameters need to be picked up from UI elements, and the process of preparing and outfitting a generic command with these actual values is tracked by an ''InvocationTrail handle''. When ready, finally this handle can be issued on any bus terminal, i.e. on any [[tangible interface element|UI-Element]].
+The actual persistent operations on the session model are defined through a DSL scripts acting on the session interface, and configured as a //command prototype.// Typically these need to be enriched with at least the actual subject to invoke this command on; many commands require additional parameters, e.g. some time or colour value. These actual invocation parameters need to be picked up from UI elements, and the process of preparing and outfitting a generic command with these actual values is tracked by an ''InvocationTrail handle''. When ready, finally this handle can be issued on any bus terminal, i.e. on any [[tangible interface element|UI-Element]].
The actual media data is rendered by [[individually scheduled render jobs|RenderJob]]. All these calculations together implement a [[stream of calculations|CalcStream]], as demanded and directed by the PlayProcess. During the preparation of playback, a ''node planning phase'' is performed, to arrange for [[dispatching|FrameDispatcher]] the individual calculations per frame.  The goal of these //preparations//  is to find out