From ffcfa7afd4159b64b0ff505bd761dd9df09f2d95 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 3 Oct 2016 01:59:47 +0200 Subject: [PATCH] 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" --- src/gui/ctrl/bus-controller.cpp | 2 +- src/gui/model/tangible.hpp | 4 + tests/gui/abstract-tangible-test.cpp | 11 +- tests/gui/test/mock-elm.hpp | 54 +++++++++- wiki/thinkPad.ichthyo.mm | 151 ++++++++++++++++++++++++++- 5 files changed, 211 insertions(+), 11 deletions(-) diff --git a/src/gui/ctrl/bus-controller.cpp b/src/gui/ctrl/bus-controller.cpp index 213973b4c..a17802663 100644 --- a/src/gui/ctrl/bus-controller.cpp +++ b/src/gui/ctrl/bus-controller.cpp @@ -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) diff --git a/src/gui/model/tangible.hpp b/src/gui/model/tangible.hpp index 9ac8b196e..a7147080f 100644 --- a/src/gui/model/tangible.hpp +++ b/src/gui/model/tangible.hpp @@ -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 diff --git a/tests/gui/abstract-tangible-test.cpp b/tests/gui/abstract-tangible-test.cpp index efdc79349..2dafbe9dc 100644 --- a/tests/gui/abstract-tangible-test.cpp +++ b/tests/gui/abstract-tangible-test.cpp @@ -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 } }; diff --git a/tests/gui/test/mock-elm.hpp b/tests/gui/test/mock-elm.hpp index 3d04cff10..944354a09 100644 --- a/tests/gui/test/mock-elm.hpp +++ b/tests/gui/test/mock-elm.hpp @@ -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 +#include #include #include @@ -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; + /** * 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; + 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(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 attrib; - std::vector scope; + std::vector scope; /* ==== Query/Verification API ==== */ diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index cb7d1a09d..434579397 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -5559,7 +5559,7 @@ - + @@ -5658,8 +5658,155 @@ + + + + + + + + + + + +

+ ...aus gutem Grund! +

+

+ Der Nexus speichert nämlich eine direkte Referenz in der Routingtabelle +

+ + +
+
- + + + + + + + + + + + + + + + + + + + + +
    +
  • + Map hat kein emplace_back +
  • +
  • + Map hat kein back() +
  • +
+

+ Beides ist erst mal sinnvoll. Map hat zwar ein emplace, aber das fügt eben irgendwo ein +

+

+ Und es gibt nicht sowas wie das "zuletzt behandelte" Element +

+ + +
+ +
+ + + + + + + + + + + + + + + +

+ Reihenfolge +

+

+ erhalten! +

+ + +
+ + + + + + + + + + + + + + +

+ ...hat eine "zufällige" Reihenfolge, die von den Hash-Werten der gespeicherten Daten abhängt. +

+

+ Das bricht mit unserem grundsätzlichen Konzept der kongruenten  Daten-Strukturen +

+ + +
+ +
+ + + + + + +

+ Ein Diff, das von einer ETD gezogen wurde, +

+

+ läßt sich nicht auf eine Map-Implementierung aufspielen +

+ + +
+ +
+
+
+ + + + + + +

+ Entscheidung: abgelehnt +

+ + +
+ +
+
+
+
+
+
+