WIP: draft a concrete TreeMutator binding for MockElm

...this is the first attempt to integrate the Diff-Framework into (mock) UI code.
Right now there is a conceptual problem with the representation of attributes;
I tend to reject idea of binding to an "attribute map"
This commit is contained in:
Fischlurch 2016-10-03 01:59:47 +02:00
parent c8ad698ac4
commit ffcfa7afd4
5 changed files with 211 additions and 11 deletions

View file

@ -85,7 +85,7 @@ namespace ctrl {
* `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 will detach this UI-Bus connection altogether.
*/
BusTerm
BusTerm::attach (ID identity, Tangible& newNode)

View file

@ -152,6 +152,10 @@ namespace model {
* which is the [UI-Bus](ui-bus.hpp). Any tangible element acquires a distinct identity
* and has to be formed starting from an already existing bus nexus.
* @see [explanation of the basic interactions](tangible.hpp)
* @warning Tangible is `noncopyable` for good reason: the UI-Bus Nexus adds a direct
* reference into the routing table, tied to the given Tangible's ID (identity.
* Consequently you must not store tangibles in STL containers, since these
* might re-allocate and thus change the location in memory.
*/
class Tangible
: public sigc::trackable

View file

@ -72,6 +72,7 @@ using gui::test::MockElm;
using lib::test::EventLog;
using lib::idi::EntryID;
using lib::diff::Rec;
using lib::diff::MakeRec;
using lib::diff::GenNode;
using lib::diff::DataCap;
using proc::control::Command;
@ -592,8 +593,8 @@ namespace test {
const GenNode
ATTRIB_AL = GenNode("α", "quadrant"),
ATTRIB_PI = GenNode("π", 3.14159265),
CHILD_1 = GenNode("a"),
CHILD_2 = GenNode('b');
CHILD_1 = MakeRec().genNode("a"),
CHILD_2 = MakeRec().genNode("b");
auto
generateDiff()
@ -629,9 +630,9 @@ namespace test {
CHECK (2 == rootMock.scope.size()); // we've got two children now
CHECK (rootMock.attrib["α"] == "quadrant"); // alpha attribute has been reassigned
CHECK (rootMock.scope[0].getID() == diffSrc.CHILD_1.idi); // children have the expected IDs
CHECK (rootMock.scope[1].getID() == diffSrc.CHILD_2.idi);
CHECK (rootMock.scope[1].attrib["π"] == "3.1415927"); // and the second child got attribute Pi
CHECK (rootMock.scope[0]->getID() == diffSrc.CHILD_1.idi); // children have the expected IDs
CHECK (rootMock.scope[1]->getID() == diffSrc.CHILD_2.idi);
CHECK (rootMock.scope[1]->attrib["π"] == "3.1415927"); // and the second child got attribute Pi
}
};

View file

@ -66,11 +66,13 @@
#include "lib/diff/record.hpp"
#include "lib/idi/genfunc.hpp"
#include "test/test-nexus.hpp"
#include "lib/diff/test-mutation-target.hpp" ///////////TICKET #1009 -- extract the render(DataCap) function?
#include "lib/format-cout.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <string>
#include <memory>
#include <vector>
#include <map>
@ -84,10 +86,14 @@ namespace gui {
namespace test{
using lib::diff::TreeMutator;
using util::isnil;
using lib::Symbol;
using std::string;
class MockElm;
using PMockElm = std::shared_ptr<MockElm>;
/**
* Mock UI element or controller.
@ -227,9 +233,51 @@ namespace test{
}
virtual void
buildMutator (lib::diff::TreeMutator::Handle buffer) override
buildMutator (TreeMutator::Handle buffer) override
{
UNIMPLEMENTED ("create a TreeMutator to deal with our playground data");
using Attrib = std::pair<const string,string>;
using lib::diff::collection;
using lib::diff::render; ///////////TICKET #1009
buffer.create (
TreeMutator::build()
.attach (collection(scope)
.isApplicableIf ([&](GenNode const& spec) -> bool
{
return spec.data.isNested(); // »Selector« : require object-like sub scope
})
.matchElement ([&](GenNode const& spec, PMockElm const& elm) -> bool
{
return spec.idi == elm->getID();
})
.constructFrom ([&](GenNode const& spec) -> PMockElm
{
return std::make_shared<MockElm>(spec.idi, this->uiBus_); // create a child element wired via this Element's BusTerm
})
.buildChildMutator ([&](PMockElm& target, GenNode::ID const& subID, TreeMutator::Handle buff) -> bool
{
if (target->getID() != subID) return false; //require match on already existing child object
target->buildMutator (buff); // delegate to child to build nested TreeMutator
return true;
}))
.attach (collection(attrib)
.isApplicableIf ([&](GenNode const& spec) -> bool
{
return spec.isNamed(); // »Selector« : accept anything attribute-like
})
.matchElement ([&](GenNode const& spec, Attrib const& elm) -> bool
{
return elm.first == spec.idi.getSym();
})
.constructFrom ([&](GenNode const& spec) -> Attrib
{
return {spec.idi.getSym(), render(spec.data)};
})
.assignElement ([&](Attrib& target, GenNode const& spec) -> bool
{
target.second = render (spec.data);
return true;
})));
}
protected:
@ -301,7 +349,7 @@ namespace test{
/* ==== Attributes and mock children ==== */
std::map<string, string> attrib;
std::vector<MockElm> scope;
std::vector<PMockElm> scope;
/* ==== Query/Verification API ==== */

View file

@ -5559,7 +5559,7 @@
<icon BUILTIN="help"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1475342135193" HGAP="31" ID="ID_336806935" MODIFIED="1475342156412" TEXT="Problem: Diff-Nachricht" VSHIFT="7">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1475342135193" FOLDED="true" HGAP="31" ID="ID_336806935" MODIFIED="1475449459631" TEXT="Problem: Diff-Nachricht" VSHIFT="7">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1475342157302" ID="ID_1383404259" MODIFIED="1475342166025" TEXT="&quot;Diff&quot; ist kein Typ"/>
<node CREATED="1475342185707" ID="ID_787925049" MODIFIED="1475342190662" TEXT="Lumiera-Iteratoren sind generisch"/>
@ -5658,8 +5658,155 @@
</node>
</node>
</node>
<node CREATED="1475449460694" HGAP="13" ID="ID_425831735" MODIFIED="1475449476287" TEXT="Prototyp: MockElm" VSHIFT="32">
<icon BUILTIN="pencil"/>
<node CREATED="1475449491378" ID="ID_1309107114" MODIFIED="1475449505548" TEXT="f&#xfc;hre Spiel-Attribute und Kinder ein"/>
<node CREATED="1475449507224" ID="ID_1783640184" MODIFIED="1475449529881" TEXT="Kinder">
<node CREATED="1475449530565" ID="ID_284330532" MODIFIED="1475449531825" TEXT="collection von MockElm"/>
<node CREATED="1475449532556" ID="ID_1804332542" MODIFIED="1475449578332" TEXT="MockElm ist noncopyable">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...aus gutem Grund!
</p>
<p>
Der Nexus speichert n&#228;mlich eine direkte Referenz in der Routingtabelle
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1473352470896" ID="ID_864450713" MODIFIED="1473352474499" TEXT="Unit-Tests">
<node CREATED="1475449544379" ID="ID_1132064603" MODIFIED="1475449583284" TEXT="also nur per shared_ptr">
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1475449589725" ID="ID_460570633" MODIFIED="1475449593209" TEXT="Attribute">
<node CREATED="1475449594060" HGAP="27" ID="ID_1311933287" MODIFIED="1475449971752" TEXT="Typ" VSHIFT="14">
<icon BUILTIN="help"/>
<node CREATED="1475449959916" ID="ID_573697431" MODIFIED="1475449966244" TEXT="map&lt;string,string&gt;"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1475449611754" HGAP="33" ID="ID_1285123321" MODIFIED="1475449984190" TEXT="Grundsatzfrage: Attribut-Map" VSHIFT="1">
<icon BUILTIN="help"/>
<node CREATED="1475449654357" ID="ID_1802368116" MODIFIED="1475449659480" TEXT="Ordnung / Unordnung"/>
<node CREATED="1475449660020" ID="ID_286191859" MODIFIED="1475449740005" TEXT="Diff geht von Listen-Ordnung aus">
<icon BUILTIN="info"/>
</node>
<node CREATED="1475449777532" ID="ID_476663339" MODIFIED="1475449893670" TEXT="Symptom: Compile-Fehler">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<ul>
<li>
Map hat kein emplace_back
</li>
<li>
Map hat kein back()
</li>
</ul>
<p>
Beides ist erst mal sinnvoll. Map hat zwar ein emplace, aber das f&#252;gt eben <i>irgendwo</i>&#160;ein
</p>
<p>
Und es gibt nicht sowas wie das &quot;zuletzt behandelte&quot; Element
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1475449719180" ID="ID_6178930" MODIFIED="1475449724993" TEXT="Sinnvoll das zu erweitern">
<icon BUILTIN="help"/>
<node CREATED="1475450034810" ID="ID_445949466" MODIFIED="1475450443961" TEXT="pro">
<icon BUILTIN="button_cancel"/>
<node CREATED="1475450042009" ID="ID_1941838908" MODIFIED="1475450049932" TEXT="man k&#xf6;nnte">
<node CREATED="1475450050824" ID="ID_1660008285" MODIFIED="1475450053243" TEXT="ins"/>
<node CREATED="1475450055775" ID="ID_1213643084" MODIFIED="1475450058698" TEXT="after::END"/>
<node CREATED="1475450064470" ID="ID_754885592" MODIFIED="1475450069265" TEXT="assign / mutate"/>
</node>
<node CREATED="1475450148771" ID="ID_736367412" MODIFIED="1475450178254">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Reihenfolge
</p>
<p>
erhalten!
</p>
</body>
</html>
</richcontent>
<node CREATED="1475450179591" ID="ID_793985703" MODIFIED="1475450197936" TEXT="dann sogar del"/>
<node CREATED="1475450053927" ID="ID_1110207658" MODIFIED="1475450055018" TEXT="pick"/>
</node>
</node>
<node CREATED="1475450038953" ID="ID_1285250844" MODIFIED="1475450446655" TEXT="con">
<icon BUILTIN="button_ok"/>
<node CREATED="1475450285336" ID="ID_288261682" MODIFIED="1475450300712" TEXT="kein Schutz gegen sinnlose Operationen"/>
<node CREATED="1475450229944" ID="ID_957217069" MODIFIED="1475450239042" TEXT="Reihenfolge ist Impl-Detail"/>
<node CREATED="1475450240318" ID="ID_1993698586" MODIFIED="1475450376320" TEXT="Hashmap">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...hat eine &quot;zuf&#228;llige&quot; Reihenfolge, die von den Hash-Werten der gespeicherten Daten abh&#228;ngt.
</p>
<p>
Das bricht mit unserem grunds&#228;tzlichen Konzept der <b>kongruenten</b>&#160; Daten-Strukturen
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1475450272442" ID="ID_567969130" MODIFIED="1475450429317" TEXT="inkompatibel mit GenNode">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Ein Diff, das von einer ETD gezogen wurde,
</p>
<p>
l&#228;&#223;t sich nicht auf eine Map-Implementierung aufspielen
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
</node>
<node CREATED="1475450448290" ID="ID_1738216720" MODIFIED="1475450466683">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Entscheidung: <i>abgelehnt</i>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1473352470896" HGAP="21" ID="ID_864450713" MODIFIED="1475449484393" TEXT="Unit-Tests" VSHIFT="18">
<node CREATED="1473352475375" ID="ID_731425414" MODIFIED="1473352482010" TEXT="AbstractTangible_test"/>
<node CREATED="1473352482502" ID="ID_1891838260" MODIFIED="1473352485210" TEXT="UiBus_test"/>
</node>