consider the bus side of the generic UI base in more detail
especially define the outline of the bus communication and connection management
This commit is contained in:
parent
59c2d2b482
commit
af98d75da4
8 changed files with 114 additions and 56 deletions
|
|
@ -69,18 +69,19 @@ namespace ctrl {
|
|||
|
||||
|
||||
|
||||
/** Builder function: establish and wire
|
||||
* a new BusTerm as connected to this one */
|
||||
BusTerm&&
|
||||
BusTerm::attach (ID newAddress)
|
||||
/** Builder function: establish and wire a new BusTerm.
|
||||
* @param newNode the UI-Element corresponding to and using the new BusTerm
|
||||
* @remarks automatically establishes a down-link connection to the given
|
||||
* [Tangible]; the UI-Bus will use this node as target to dispatch
|
||||
* `mark` messages addressed to the new node's ID. It is expected
|
||||
* that the Tangible in turn will use the returned BusTerm for
|
||||
* any up-link communication. Thus, on destruction, the new
|
||||
* BusTerm will detach this UI-Bus connection alltogether.
|
||||
*/
|
||||
BusTerm
|
||||
BusTerm::attach (ID identity, Tangible newNode)
|
||||
{
|
||||
return std::move( BusTerm(newAddress, *this));
|
||||
}
|
||||
|
||||
BusTerm::ID
|
||||
BusTerm::getID() const
|
||||
{
|
||||
return endpointID_;
|
||||
return BusTerm(identity, theBus_.routeAdd(newNode));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -88,43 +89,59 @@ namespace ctrl {
|
|||
/* ==== standard implementation of the BusTerm interface ==== */
|
||||
|
||||
void
|
||||
BusTerm::act (GenNode command)
|
||||
BusTerm::act (GenNode const& command)
|
||||
{
|
||||
UNIMPLEMENTED("issue command");
|
||||
}
|
||||
|
||||
|
||||
/** */
|
||||
/** record state mark from this subject */
|
||||
void
|
||||
BusTerm::note (GenNode mark)
|
||||
BusTerm::note (GenNode const& mark)
|
||||
{
|
||||
UNIMPLEMENTED("send notification downstream");
|
||||
theBus_.note(this->endpointID_, mark);
|
||||
}
|
||||
|
||||
|
||||
/** */
|
||||
void
|
||||
BusTerm::note (ID subject, GenNode mark)
|
||||
{
|
||||
UNIMPLEMENTED("send notification to subject");
|
||||
}
|
||||
|
||||
|
||||
/** */
|
||||
void
|
||||
BusTerm::mark (GenNode mark)
|
||||
{
|
||||
UNIMPLEMENTED("record state mark");
|
||||
}
|
||||
|
||||
|
||||
/** */
|
||||
void
|
||||
BusTerm::mark (ID subject, GenNode mark)
|
||||
BusTerm::note (ID subject, GenNode const& mark)
|
||||
{
|
||||
UNIMPLEMENTED("forward state mark from subject");
|
||||
}
|
||||
|
||||
|
||||
/** */
|
||||
void
|
||||
BusTerm::mark (ID subject, GenNode const& mark)
|
||||
{
|
||||
UNIMPLEMENTED("send notification or state mark to subject");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal establish new down-link connection form UI-Bus
|
||||
* @param node reference to the [Tangible] to be connected.
|
||||
* @return corresponding up-link for the initiating node to use
|
||||
*/
|
||||
BusTerm&
|
||||
BusTerm::routeAdd (Tangible node)
|
||||
{
|
||||
return theBus_.routeAdd(node);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal disable down-link connection
|
||||
* @remarks corresponding node is about to go away.
|
||||
*/
|
||||
void
|
||||
BusTerm::routeDetach(ID node) noexcept
|
||||
{
|
||||
theBus_.routeDetach (node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace gui::ctrl
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@
|
|||
|
||||
|
||||
namespace gui {
|
||||
namespace model {
|
||||
class Tangible;
|
||||
}
|
||||
namespace ctrl{
|
||||
|
||||
// using lib::HashVal;
|
||||
|
|
@ -92,24 +95,26 @@ namespace ctrl{
|
|||
*/
|
||||
class BusTerm
|
||||
{
|
||||
using ID = lib::idi::BareEntryID;
|
||||
using EntryID = lib::idi::BareEntryID;
|
||||
using ID = EntryID const&;
|
||||
using Tangible = gui::model::Tangible const&;
|
||||
|
||||
ID endpointID_;
|
||||
EntryID endpointID_;
|
||||
BusTerm& theBus_;
|
||||
|
||||
public:
|
||||
virtual ~BusTerm(); ///< this is an interface
|
||||
|
||||
virtual void act (GenNode command);
|
||||
virtual void note (GenNode mark);
|
||||
virtual void mark (GenNode mark);
|
||||
virtual void act (GenNode const& command);
|
||||
virtual void note (GenNode const& mark);
|
||||
|
||||
virtual void note (ID subject, GenNode mark);
|
||||
virtual void mark (ID subject, GenNode mark);
|
||||
virtual void note (ID subject, GenNode const& mark);
|
||||
virtual void mark (ID subject, GenNode const& mark);
|
||||
|
||||
BusTerm&& attach (ID newAddress);
|
||||
ID getID() const { return endpointID_; }
|
||||
|
||||
ID getID() const;
|
||||
|
||||
BusTerm attach (ID, Tangible newNode);
|
||||
|
||||
/** may be moved, but not copied,
|
||||
* due to the embedded identity */
|
||||
|
|
@ -120,6 +125,9 @@ namespace ctrl{
|
|||
: endpointID_(identity)
|
||||
, theBus_(attached_to)
|
||||
{ }
|
||||
|
||||
virtual BusTerm& routeAdd(Tangible);
|
||||
virtual void routeDetach(ID) noexcept;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ namespace model {
|
|||
void
|
||||
Tangible::prepareCommand (Cmd const& prototype, Rec&& arguments)
|
||||
{
|
||||
uiBus_.act (prototype.bind(std::forward<Rec>(arguments)));
|
||||
uiBus_.act (prototype.bind (std::forward<Rec>(arguments)));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -71,18 +71,20 @@ namespace model {
|
|||
using GenNode = lib::diff::GenNode;
|
||||
using Cmd = interact::InvocationTrail;
|
||||
using Rec = lib::diff::Rec;
|
||||
using ID = lib::idi::BareEntryID;
|
||||
using ID = lib::idi::BareEntryID const&;
|
||||
|
||||
ctrl::BusTerm uiBus_;
|
||||
|
||||
|
||||
Tangible(ID identity, ctrl::BusTerm& nexus)
|
||||
: uiBus_(nexus.attach(identity))
|
||||
: uiBus_(nexus.attach(identity, *this))
|
||||
{ }
|
||||
|
||||
public:
|
||||
virtual ~Tangible(); ///< this is an interface
|
||||
|
||||
operator ID() const { return uiBus_.getID();}
|
||||
|
||||
void reset();
|
||||
|
||||
void prepareCommand (Cmd const& prototype, Rec&& arguments);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
|
||||
/** @file abstract-tangible-test.cpp
|
||||
* Verify the common base shared by all interface elements of relevance.
|
||||
** Verify the common base shared by all interface elements of relevance.
|
||||
** This test is not so much a test, than a test of the test support for testing
|
||||
** [primary elements][gui::model::Tangible] of the Lumiera GTK UI. Any such element
|
||||
** is connected to the [UI-Bus][gui::UiBus] and responds to some generic actions and
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
|
||||
/** @file test/nexus.cpp
|
||||
** Implementation of a fake UI backbone for testing.
|
||||
** This compilation unit provides the actual setup for running a faked interface from tests.
|
||||
** This compilation unit provides the actual setup for running a faked
|
||||
** user interface from unit tests.
|
||||
**
|
||||
** @todo initial draft and WIP-WIP-WIP as of 11/2015
|
||||
**
|
||||
|
|
|
|||
|
|
@ -8365,11 +8365,28 @@ For now, as of 6/10, we use specialised QueryResolver instances explicitly and d
|
|||
&rarr; QueryRegistration
|
||||
</pre>
|
||||
</div>
|
||||
<div title="UI-Bus" creator="Ichthyostega" modifier="Ichthyostega" created="201501061115" modified="201501061128" tags="GuiPattern Concepts def design draft" changecount="6">
|
||||
<div title="UI-Bus" creator="Ichthyostega" modifier="Ichthyostega" created="201501061115" modified="201512180001" tags="GuiPattern Concepts def design draft" changecount="10">
|
||||
<pre>Abstraction used in the Backbone of Lumiera's GTK User Interface
|
||||
The UI-Bus is a ''Mediator'' -- impersonating the role of the //Model// and the //Controler// in the [[MVC-Pattern|http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller]] in common UI architecture.
|
||||
|
||||
The ~MVC-Pattern as such is fine, and probably the best we know for construction of user interfaces. But it doesn't scale well towards the integration into a larger and more structured system. There is a tension between the Controller in the UI and other parts of an application, which as well need to be //in control.// And, even more important, there is a tension between the demands of UI elements for support by a model, and the demands to be placed on a core domain model of a large scale application. This tension is resolved by enacting these roles while transforming the requests and demands into //Messages.//</pre>
|
||||
The ~MVC-Pattern as such is fine, and probably the best we know for construction of user interfaces. But it doesn't scale well towards the integration into a larger and more structured system. There is a tension between the Controller in the UI and other parts of an application, which as well need to be //in control.// And, even more important, there is a tension between the demands of UI elements for support by a model, and the demands to be placed on a core domain model of a large scale application. This tension is resolved by enacting these roles while transforming the requests and demands into //Messages.//
|
||||
|
||||
!!!rationale
|
||||
This way, we separate between immediate local control of UI state and the more global, generic [[interaction control|InteractionControl]] and [[command binding|GuiCommandBinding]].
|
||||
And we arrive at a backbone like structure, which can be wired, programmed and reasoned about while abstracting from the local concerns of UI toolkit set internal state management. Any element of more than local relevance -- be it a controller or be it a widget representing some entity from the model -- will be attached to the UI-Bus by virtue of a ''bus terminal'', establishing a bi-directional connection. This enables any UI element so invoke commands and persist presentation state (by sending //"state mark" mesages//), and in turn this allows the session and engine core to "cast" state updates towards the UI, without precisely knowing where and how to reach the relevant presentation entities.
|
||||
|
||||
!Bus interactions
|
||||
The UI-Bus has a star shaped topology, with a central "bus master" hub, which maintains a routing table. Attachment and detachment of elements can be managed automatically, since all of the UI-Bus operations perform within the GUI event thread. We distinguish between up-link messages, directed towards some central service (presentation state management or command invocation) and down-link messages, directed towards individual elements. The interactions at the bus are closely interrelated with the elementary UI-Element operations.
|
||||
;act
|
||||
:send a GenNode representing the action
|
||||
:* in a first step, a command prototype is outfitted with actual parameter values
|
||||
:* the actual command invocation is triggered by a "bang" message
|
||||
;note
|
||||
:send a GenNode representing the //state mark//
|
||||
:some (abstracted) presentation state manager is expected to listen to these messages, possibly recording state to be restored later
|
||||
;mark
|
||||
:down-link communication to //feed back// state updates or to replay previously recorded //state marks//
|
||||
</pre>
|
||||
</div>
|
||||
<div title="UI-Element" creator="Ichthyostega" modifier="Ichthyostega" created="201511210307" modified="201512160029" tags="GuiPattern design draft decision" changecount="18">
|
||||
<pre>While our UI widgets are implemented the standard way as proposed by GTKmm, some key elements -- which are especially relevant for the anatomy and mechanics of the interface -- are made to conform to a common interface and behaviour protocol. {{red{WIP 11/15 work out what this protocol is all about}}}. #975
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<node CREATED="1434128046296" ID="ID_1900827283" MODIFIED="1448669775410" POSITION="right" TEXT="GUI">
|
||||
<font NAME="SansSerif" SIZE="14"/>
|
||||
<node CREATED="1434128054470" ID="ID_1166611516" MODIFIED="1434128059666" TEXT="Workflow"/>
|
||||
<node CREATED="1448070434915" HGAP="64" ID="ID_257833497" MODIFIED="1448070642269" VSHIFT="7">
|
||||
<node CREATED="1448070434915" HGAP="64" ID="ID_257833497" MODIFIED="1450390417230" VSHIFT="7">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#3a8df0" DESTINATION="ID_1618124128" ENDARROW="Default" ENDINCLINATION="-19;-25;" ID="Arrow_ID_539627804" STARTARROW="Default" STARTINCLINATION="-2;35;"/>
|
||||
<arrowlink COLOR="#3a8df0" DESTINATION="ID_1618124128" ENDARROW="Default" ENDINCLINATION="-25;-262;" ID="Arrow_ID_539627804" STARTARROW="Default" STARTINCLINATION="-2;35;"/>
|
||||
<node CREATED="1448070545132" HGAP="31" ID="ID_1410368513" MODIFIED="1448669353294" TEXT="Element" VSHIFT="-7">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1448070580927" ID="ID_467382299" MODIFIED="1448070583371" TEXT="Ausprägungen">
|
||||
|
|
@ -453,7 +453,7 @@
|
|||
</node>
|
||||
<node CREATED="1448070605948" ID="ID_1779744719" MODIFIED="1448070608272" TEXT="Verhalten">
|
||||
<node CREATED="1448407128826" ID="ID_1974801494" MODIFIED="1448407138941" TEXT="Bus-Master ist ein speziell implementiertes BusTerm"/>
|
||||
<node CREATED="1448407139441" ID="ID_392543622" MODIFIED="1448407152451" TEXT="das gewöhnliche BusTerm ist an ein Tangible angeschlossen"/>
|
||||
<node CREATED="1448407139441" ID="ID_392543622" MODIFIED="1450390220709" TEXT="das gewöhnliche BusTerm ist einem Tangible zugeordnet"/>
|
||||
<node CREATED="1448407187035" ID="ID_1622894914" MODIFIED="1448407197917" TEXT="sowie bus-seitig an ein "upstream" BusTerm"/>
|
||||
</node>
|
||||
<node CREATED="1448070618434" ID="ID_1925738380" MODIFIED="1448070621878" TEXT="Zuordnung">
|
||||
|
|
@ -470,6 +470,7 @@
|
|||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1448406977350" ID="ID_1450959387" MODIFIED="1448406993656" TEXT="jedes BusTerm ist lediglich eine personalisierte Bus-Anbindung"/>
|
||||
<node CREATED="1450390181806" ID="ID_61666430" MODIFIED="1450390266704" TEXT="es registriert beim Bus-Mater einen Link zum zugehörigen Tangible"/>
|
||||
<node CREATED="1448406994860" ID="ID_846198635" MODIFIED="1448407022869">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
|
@ -486,8 +487,8 @@
|
|||
</node>
|
||||
</node>
|
||||
<node CREATED="1434128059966" ID="ID_823283341" MODIFIED="1434128067529" TEXT="Connect">
|
||||
<node CREATED="1434128071126" ID="ID_1618124128" MODIFIED="1448070642269" TEXT="UI-Bus">
|
||||
<linktarget COLOR="#3a8df0" DESTINATION="ID_1618124128" ENDARROW="Default" ENDINCLINATION="-19;-25;" ID="Arrow_ID_539627804" SOURCE="ID_257833497" STARTARROW="Default" STARTINCLINATION="-2;35;"/>
|
||||
<node CREATED="1434128071126" ID="ID_1618124128" MODIFIED="1450390417230" TEXT="UI-Bus">
|
||||
<linktarget COLOR="#3a8df0" DESTINATION="ID_1618124128" ENDARROW="Default" ENDINCLINATION="-25;-262;" ID="Arrow_ID_539627804" SOURCE="ID_257833497" STARTARROW="Default" STARTINCLINATION="-2;35;"/>
|
||||
<node CREATED="1448548216556" ID="ID_1971609445" MODIFIED="1448548224236" TEXT="Topologie">
|
||||
<node CREATED="1448548225659" ID="ID_807917172" MODIFIED="1448548309275" TEXT="upstream = zum Verteiler"/>
|
||||
<node CREATED="1448548310247" ID="ID_993096699" MODIFIED="1448548316619" TEXT="downstream = zum Empfänger"/>
|
||||
|
|
@ -504,9 +505,21 @@
|
|||
<node CREATED="1448560896232" ID="ID_931223590" MODIFIED="1448560899523" TEXT="implizit"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1434128301525" ID="ID_187622243" MODIFIED="1434128303993" TEXT="Parallelität"/>
|
||||
<node CREATED="1434128332277" ID="ID_33025591" MODIFIED="1434128337777" TEXT="Deregistrierung"/>
|
||||
<node CREATED="1434128310005" ID="ID_644247390" MODIFIED="1434128318561" TEXT="Knoten-ID"/>
|
||||
<node CREATED="1434128301525" ID="ID_187622243" MODIFIED="1434128303993" TEXT="Parallelität">
|
||||
<node CREATED="1450390447884" ID="ID_1176145978" MODIFIED="1450390453590" TEXT="nicht Threadsafe"/>
|
||||
<node CREATED="1450390454236" ID="ID_1617539841" MODIFIED="1450390469325" TEXT="läuft ausschließlich im Event-Thrad"/>
|
||||
</node>
|
||||
<node CREATED="1434128332277" ID="ID_33025591" MODIFIED="1434128337777" TEXT="Deregistrierung">
|
||||
<node CREATED="1450390522393" ID="ID_1448879688" MODIFIED="1450390558817" TEXT="Uplink: implizit, hält Link zu einem Router"/>
|
||||
<node CREATED="1450390559805" ID="ID_1657985065" MODIFIED="1450390565215" TEXT="Downlink:">
|
||||
<node CREATED="1450390566252" ID="ID_591456555" MODIFIED="1450390584621" TEXT="registriert eine Route zu einem Tangible"/>
|
||||
<node CREATED="1450390585329" ID="ID_1371255341" MODIFIED="1450390595419" TEXT="der dtor entfernt diese Route wieder"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1434128310005" ID="ID_644247390" MODIFIED="1434128318561" TEXT="Knoten-ID">
|
||||
<node CREATED="1450390501876" ID="ID_1750345192" MODIFIED="1450390509511" TEXT="ist die EntryID des Tangible"/>
|
||||
<node CREATED="1450390512635" ID="ID_43739373" MODIFIED="1450390519885" TEXT="dient auch zum Routing"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1448063874479" ID="ID_739054690" MODIFIED="1448063878154" TEXT="UI-Modell"/>
|
||||
<node CREATED="1434128074725" FOLDED="true" ID="ID_933994138" MODIFIED="1448063763273" TEXT="Diff-System">
|
||||
|
|
|
|||
Loading…
Reference in a new issue