draft of the UI-Bus communication structure

what you see here now is just the tip of the icebearg...
If we follow this route, the Lumiera UI will become way more
elaborate and responsive than average desktop applications
This commit is contained in:
Fischlurch 2015-11-26 21:10:38 +01:00
parent 16c01ab2bd
commit bb627fc1f8
3 changed files with 81 additions and 19 deletions

View file

@ -22,12 +22,23 @@
/** @file bus-term.hpp
** Attachment point to the UI-Bos.
** Attachment point to the UI-Bus.
** Every gui::model::Tangible holds a BusTerm, which is linked
** to the Tangible's identity, and serves to relay interface actions
** towards the Proc-Layer. Moreover, the BusTerm is the service point
** towards the Proc-Layer, to remember state changes and to broadcast
** notifications. Moreover, the BusTerm is the service point
** to receive structural change messages.
**
** \par Lifecycle and identity
** An BusTerm is always created starting from another BusTerm, to
** which it will be wired. Moreover, each BusTerm bears a distinct
** [identity][::endpointID_], which is used as _implicit subject_
** for emanating messages, or as explicit destination for routing.
** The whole [UI-Bus][BusController] is built to perform within the
** UI event thread and thus is _not threadsafe_. For that reason,
** the automatic detachment built into each BusTerm's dtor is
** sufficient to ensure sane connectivity.
**
** @todo as of 11/2015 this is complete WIP-WIP-WIP
**
** @see ////TODO_test usage example
@ -42,6 +53,8 @@
#include "lib/error.hpp"
//#include "lib/symbol.hpp"
//#include "lib/util.hpp"
#include "lib/idi/entry-id.hpp"
#include "lib/diff/gen-node.hpp"
#include <boost/noncopyable.hpp>
#include <string>
@ -52,23 +65,54 @@ namespace ctrl{
// using lib::HashVal;
// using util::isnil;
using lib::idi::EntryID;
using lib::diff::GenNode;
using std::string;
/**
* @todo write type comment...
* connection point at the UI-Bus.
* The UI-Bus is a star shaped network of terminal points,
* where each \link Tangible tangible UI element \endlink
* holds a BusTerm serving access point. The BusTerm interface
* exposes the basic "verbs" available for communication within
* the UI
* - to _act_ on an element means to issue a command
* - to _note_ some state or information for later replay
* - to _mark_ as erroneous, send an information message,
* replay remembered presentation state or effect structural change
* There are \em indirect variants of the message verbs, which are
* intended for routing, broadcasting or forwarding. Effectively,
* routing is determined from the context and meaning of a message,
* where the _act_ and _note_ messages have an implicit receiver
* (either the Proc-Layer or the UI state manager), while the
* _mark_ messages are always directed _downstream_ towards
* some element.
*/
class BusTerm
: boost::noncopyable
{
string nothing_;
EntryID endpointID_;
BusTerm& theBus_;
public:
BusTerm();
~BusTerm();
virtual ~BusTerm(); ///< this is an interface
virtual void act (GenNode command) =0;
virtual void note (GenNode mark) =0;
virtual void mark (GenNode mark) =0;
virtual void act (EntryID subject, GenNode command) =0;
virtual void note (EntryID subject, GenNode mark) =0;
virtual void mark (EntryID subject, GenNode mark) =0;
BusTerm attach (EntryID newAddress);
protected:
string mayday () const;
BusTerm(EntryID identity, BusTerm& attached_to =*this)
: endpointID_(identity)
, theBus_(attached_to)
{ }
};

View file

@ -2448,7 +2448,7 @@ The workspace starts out with a single element, corresponding to the »model roo
Speaking of implementation, this state and update mechanics relies on two crucial provisions: Lumiera's framework for [[tree diff representation|TreeDiffModel]] and the ExternalTreeDescription, which is an abstracted, ~DOM-like rendering of the relevant parts of the session; this model tree is comprised of [[generic node elements|GenNode]] acting as proxy for [[calls into|SessionInterface]] the [[session model|HighLevelModel]] proper.
</pre>
</div>
<div title="GuiModelUpdate" creator="Ichthyostega" modifier="Ichthyostega" created="201410250121" modified="201511210302" tags="GuiIntegration GuiPattern design decision discuss draft" changecount="39">
<div title="GuiModelUpdate" creator="Ichthyostega" modifier="Ichthyostega" created="201410250121" modified="201511261846" tags="GuiIntegration GuiPattern design decision discuss draft" changecount="40">
<pre>Considerations regarding the [[structure of custom timeline widgets|GuiTimelineWidgetStructure]] highlight again the necessity of a clean separation of concerns and an &quot;open closed design&quot;. For the purpose of updating the timeline(s) to reflect the HighLevelModel in Proc-Layer, several requirements can be identified
* we need incremental updates: we must not start redrawing each and everything on each tiny change
* we need recursive programming, since this is the only sane way to deal with tree like nested structures.
@ -2475,7 +2475,7 @@ Hereby we introduce a new in-layer abstraction: The UI-Bus.
!initiating model updates
Model updates are always pushed up from Proc-Layer, coordinated by the ProcDispatcher. A model update can be requested by the GUI -- but the actual update will arrive asynchronously. The update information originate from within the [[build process|BuildFixture]]. {{red{TODO 10/2014 clarify the specifics}}}. When updates arrive, a ''diff is generated'' against the current GuiModel contents. The GuiModel is updated to reflect the differences and the Receivers or Listeners are signalled. It is their responsibility in turn to schedule an update operation into the GUI event thread. When performing this update, the Listener thus actively retrieves and pulls the diffed information from within the GUI event thread. The GuiModel's object monitor is sufficient to coordinate this handover.
Model updates are always pushed up from Proc-Layer, coordinated by the ProcDispatcher. A model update can be requested by the GUI -- but the actual update will arrive asynchronously. The update information originate from within the [[build process|BuildFixture]]. {{red{TODO 10/2014 clarify the specifics}}}. When updates arrive, a ''diff is generated'' against the current GuiModel contents. The GuiModel is updated to reflect the differences and then notifications for any Receivers or Listeners are scheduled into the GUI event thread. On reception, it is their responsibility in turn to pull the targeted diff. When performing this update, the Listener thus actively retrieves and pulls the diffed information from within the GUI event thread. The GuiModel's object monitor is sufficient to coordinate this handover.
&amp;rarr; representation of changes as a [[tree of diffs|TreeDiffModel]]
&amp;rarr; properties and behaviour of [[generic interface elements|UI-Element]]
@ -8314,7 +8314,7 @@ The UI-Bus is a ''Mediator'' -- impersonating the role of the //Model// and the
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>
</div>
<div title="UI-Element" creator="Ichthyostega" modifier="Ichthyostega" created="201511210307" modified="201511242314" tags="GuiPattern design draft decision" changecount="10">
<div title="UI-Element" creator="Ichthyostega" modifier="Ichthyostega" created="201511210307" modified="201511261841" tags="GuiPattern design draft decision" changecount="12">
<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
As a starting point, we know
* there is a backbone structure known as the UI-Bus
@ -8346,10 +8346,10 @@ And finally, there are the //essential updates// -- any changes in the model //f
:connect to an existing term, supply the {{{EntryID}}} of the new element
;act
:send a GenNode representing the action
;mark
:send a GenNode representing the //state mark//
;note
:receive a GenNode representing the //feedback//
:send a GenNode representing the //state mark//
;mark
:receive a GenNode representing the //feedback// or replayed //state mark//
;signals
:the individual element exposes some generic signal slots
:* sigMut prompts the element to draw a diff to alter its configuration
@ -8360,7 +8360,7 @@ And finally, there are the //essential updates// -- any changes in the model //f
:* either is an incremental status update
:* or is a from-scratch reconfiguration
We should note that these conventions of interchange lead to a ''self similar design'' of the UI-Bus: Each {{{BusTerm}}} is a personalised connection to yet another {{{BusTerm}}}. Even the ''bus master'' appears as just another {{{BusTerm}}} to all the communication partners. The overall topology of the bus might be reshaped without the participating elements being aware of such a change.
We should note that these conventions of interchange lead to a recursive or ''self similar design'' of the UI-Bus: Each {{{BusTerm}}} is a personalised connection to yet another {{{BusTerm}}}. Even the ''bus master'' appears as just another {{{BusTerm}}} to all the communication partners. The overall topology of the bus might be reshaped without the participating elements being aware of such a change.
</pre>
</div>
<div title="ViewConnection" modifier="Ichthyostega" created="201105221854" modified="201501091154" tags="def Model SessionLogic" changecount="3">

View file

@ -142,32 +142,35 @@
</node>
<node CREATED="1448070547667" ID="ID_669457401" MODIFIED="1448070553662" TEXT="Bus-Terminal">
<node CREATED="1448070601165" ID="ID_1711137699" MODIFIED="1448070603296" TEXT="Methoden">
<node CREATED="1448407030239" ID="ID_619913132" MODIFIED="1448407053748">
<node CREATED="1448407030239" ID="ID_619913132" MODIFIED="1448560681641">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
mark: Nachricht <i>upstream</i>&#160;bzw <i>broadcast</i>
act, note: Nachricht <i>upstream</i>
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1448407054900" ID="ID_1277028437" MODIFIED="1448407096966">
<node CREATED="1448407054900" ID="ID_1277028437" MODIFIED="1448560688352">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
note: Nachricht <i>downstream</i>
mark: Nachricht <i>downstream</i>
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1448560729734" ID="ID_431928237" MODIFIED="1448560743272" TEXT="Nachricht mit Subjekt == indirekt, zur Weiterleitung"/>
<node CREATED="1448560744380" ID="ID_310914031" MODIFIED="1448560762557" TEXT="Nachricht ohne Subjekt == direkt, Subjekt implizit"/>
<node CREATED="1448560790558" ID="ID_1545911136" MODIFIED="1448560800728" TEXT="Bedeutung der Nachricht ergibt sich aus ihrem Namen"/>
</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"/>
@ -208,7 +211,22 @@
<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="1434128297445" ID="ID_1971555917" MODIFIED="1434128300889" TEXT="Nachrichtenformat"/>
<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&#xe4;nger"/>
<node CREATED="1448560840239" ID="ID_1912018032" MODIFIED="1448560846426" TEXT="indirekt = zur Weiterleitung"/>
</node>
<node CREATED="1434128297445" ID="ID_1971555917" MODIFIED="1434128300889" TEXT="Nachrichtenformat">
<node CREATED="1448560865804" ID="ID_907456829" MODIFIED="1448560869319" TEXT="Klassifikation">
<node CREATED="1448548400308" ID="ID_1714197552" MODIFIED="1448548403647" TEXT="dedicated"/>
<node CREATED="1448548404475" ID="ID_1237647034" MODIFIED="1448548407135" TEXT="targetted"/>
<node CREATED="1448548407819" ID="ID_1923087300" MODIFIED="1448548486692" TEXT="flooding"/>
</node>
<node CREATED="1448560887081" ID="ID_1783786781" MODIFIED="1448560890004" TEXT="Addressierung">
<node CREATED="1448560891416" ID="ID_1603035591" MODIFIED="1448560904026" TEXT="per Subjekt"/>
<node CREATED="1448560896232" ID="ID_931223590" MODIFIED="1448560899523" TEXT="implizit"/>
</node>
</node>
<node CREATED="1434128301525" ID="ID_187622243" MODIFIED="1434128303993" TEXT="Parallelit&#xe4;t"/>
<node CREATED="1434128332277" ID="ID_33025591" MODIFIED="1434128337777" TEXT="Deregistrierung"/>
<node CREATED="1434128310005" ID="ID_644247390" MODIFIED="1434128318561" TEXT="Knoten-ID"/>