state mark handling within the base element: unit test PASS
...and I made the decision *not* to consider any kind of generic properties for now. YAGNI. UI coding is notorious spaghetti code. No point in fighting that, it is just the way it is, because somewhere you're bound to get concrete, hands-on.
This commit is contained in:
parent
e4a57e27d2
commit
26d0f50e47
4 changed files with 138 additions and 5 deletions
|
|
@ -33,6 +33,7 @@
|
|||
#include "gui/model/tangible.hpp"
|
||||
#include "gui/model/widget.hpp"
|
||||
#include "gui/model/controller.hpp"
|
||||
#include "lib/diff/gen-node.hpp"
|
||||
|
||||
|
||||
namespace gui {
|
||||
|
|
@ -129,5 +130,38 @@ namespace model {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* default implementation and catch-all handler for receiving »state mark« messages.
|
||||
* Such messages serve either to cause a presentation state effect specific to this
|
||||
* element, or they are used to re-play a former state change to restore some
|
||||
* specific UI state captured within a past working session. Events handled here:
|
||||
* - *expand* with a `bool` argument calls the `doExpand(bool)` virtual function.
|
||||
* It is up to the concrete element to give this a tangible meaning, e.g. a track
|
||||
* might switch to detail view and a clip might reveal attached effects.
|
||||
* - *reset* restores the element to the hard wired default, by invoking `doReset()`
|
||||
* - *revealYourself* prompts the element to take the necessary actions to bring
|
||||
* itself into view. There is no requirement for an element to even implement
|
||||
* this call, but those which do typically know some kind of _"parent object"_
|
||||
* to forward this request, by invoking `doReveal(myID)` on this parent.
|
||||
* For instance, a clip might ask the enclosing track, which in turn might
|
||||
* call the enclosing timeline display for help, resulting in a scroll action
|
||||
* to bring the clip into sight.
|
||||
* @note this is a default implementation for a virtual function declared _abstract_
|
||||
* with the intention for derived classes to tail-call this default handler.
|
||||
*/
|
||||
void
|
||||
Tangible::doMark (GenNode const& stateMark)
|
||||
{
|
||||
if (stateMark.idi.getSym() == "expand")
|
||||
this->doExpand (stateMark.data.get<bool>());
|
||||
else
|
||||
if (stateMark.idi.getSym() == "reset")
|
||||
this->doReset();
|
||||
else
|
||||
if (stateMark.idi.getSym() == "revealYourself")
|
||||
this->doRevealYourself();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace gui::model
|
||||
|
|
|
|||
|
|
@ -441,7 +441,43 @@ namespace test {
|
|||
.beforeCall("note").arg(targetID, GenNode{"expand", false})
|
||||
.before("handling state-mark"));
|
||||
|
||||
////////////////////////////////////////////////////////////TODO: WIP
|
||||
|
||||
|
||||
// Second part: replay of a state mark via UI-Bus....
|
||||
auto stateMark = GenNode{"expand", true};
|
||||
auto& uiBus = gui::test::Nexus::testUI();
|
||||
|
||||
CHECK (not mock.isExpanded());
|
||||
CHECK (mock.ensureNot("mark"));
|
||||
|
||||
uiBus.mark (targetID, stateMark);
|
||||
|
||||
CHECK (nexusLog.verifyCall("mark").arg(targetID, stateMark)
|
||||
.before("delivered mark to "+string(targetID)).arg(stateMark));
|
||||
|
||||
CHECK (mock.verifyMark("expand", "true")
|
||||
.beforeCall("expand").arg(true)
|
||||
.beforeEvent("expanded"));
|
||||
CHECK (mock.isExpanded());
|
||||
CHECK (mock.isTouched());
|
||||
|
||||
// the default handler defined in model::Tangible
|
||||
// already supports some rather generic state changes,
|
||||
// like e.g. a reset to the element's default state.
|
||||
// Note that the actual implementation doReset()
|
||||
// is a virtual function, here implemented in MockElm.
|
||||
uiBus.mark (targetID, GenNode{"reset", true});
|
||||
// note: payload is irrelevant for "reset" mark
|
||||
|
||||
// and we're back to pristine state...
|
||||
CHECK (not mock.isTouched());
|
||||
CHECK (not mock.isExpanded());
|
||||
CHECK (mock.verifyMark("reset", "true")
|
||||
.afterEvent("expanded")
|
||||
.beforeCall("reset")
|
||||
.beforeEvent("reset"));
|
||||
|
||||
|
||||
cout << "____Event-Log_________________\n"
|
||||
<< util::join(mock.getLog(), "\n")
|
||||
<< "\n───╼━━━━━━━━━╾────────────────"<<endl;
|
||||
|
|
@ -449,7 +485,6 @@ namespace test {
|
|||
cout << "____Nexus-Log_________________\n"
|
||||
<< util::join(nexusLog, "\n")
|
||||
<< "\n───╼━━━━━━━━━╾────────────────"<<endl;
|
||||
////////////////////////////////////////////////////////////TODO: WIP
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -472,16 +507,16 @@ namespace test {
|
|||
CHECK (mock.ensureNot("Message"));
|
||||
|
||||
// now send a "Flash" mark via UI-Bus....
|
||||
uiBus.mark(targetID, GenNode{"Flash", true });
|
||||
uiBus.mark (targetID, GenNode{"Flash", true });
|
||||
CHECK (mock.verifyMark("Flash"));
|
||||
|
||||
CHECK (mock.ensureNot("Error"));
|
||||
CHECK (mock.ensureNot("Message"));
|
||||
|
||||
uiBus.mark(targetID, GenNode{"Error", "getting serious"});
|
||||
uiBus.mark (targetID, GenNode{"Error", "getting serious"});
|
||||
CHECK (mock.verifyMark("Error", "serious"));
|
||||
|
||||
uiBus.mark(targetID, GenNode{"Message", "by mistake"});
|
||||
uiBus.mark (targetID, GenNode{"Message", "by mistake"});
|
||||
CHECK (mock.verifyMark("Message", "mistake"));
|
||||
|
||||
CHECK (mock.verify("target")
|
||||
|
|
|
|||
|
|
@ -170,6 +170,9 @@ namespace test{
|
|||
log_.call (this->identify(), "doMark", mark);
|
||||
cout << this->identify() << " <-- state-mark = "<< mark <<endl;
|
||||
log_.note ("type=mark", "ID="+mark.idi.getSym(), mark);
|
||||
|
||||
// forward to default handler
|
||||
Tangible::doMark (mark);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -211,6 +211,49 @@
|
|||
<node CREATED="1448659792782" ID="ID_1547056651" MODIFIED="1448659801312" TEXT="räumliche Navigation"/>
|
||||
<node CREATED="1448659824337" ID="ID_1734858009" MODIFIED="1448659829865" TEXT="Markierungen"/>
|
||||
</node>
|
||||
<node CREATED="1455236472002" FOLDED="true" HGAP="49" ID="ID_952544600" MODIFIED="1455236890661" TEXT="generische Eigenschaften" VSHIFT="15">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1455236491432" ID="ID_1268644179" MODIFIED="1455236569787" TEXT="Idee">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1455236501719" HGAP="35" ID="ID_540888754" MODIFIED="1455236634083" TEXT="man könnte Eigenschaften konfigurieren" VSHIFT="2"/>
|
||||
<node CREATED="1455236512373" ID="ID_211355731" MODIFIED="1455236518680" TEXT="jede Eigenschaft hätte">
|
||||
<node CREATED="1455236519677" ID="ID_1698754255" MODIFIED="1455236521384" TEXT="Namen"/>
|
||||
<node CREATED="1455236522020" ID="ID_404018073" MODIFIED="1455236526855" TEXT="slot"/>
|
||||
<node CREATED="1455236527443" ID="ID_45035009" MODIFIED="1455236537118" TEXT="passende »state mark«"/>
|
||||
<node CREATED="1455236537802" ID="ID_1419063243" MODIFIED="1455236554532" TEXT="handler-funktor"/>
|
||||
<node CREATED="1455236554927" ID="ID_772542993" MODIFIED="1455236563746" TEXT="installiert sich in generischen handler"/>
|
||||
</node>
|
||||
<node CREATED="1455236573173" HGAP="72" ID="ID_466911779" MODIFIED="1455236591000" TEXT="Bewertung" VSHIFT="16">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1455236781242" ID="ID_674694140" MODIFIED="1455236787861" TEXT="könnte interessant sein für Diff"/>
|
||||
<node CREATED="1455236788424" ID="ID_1507269502" MODIFIED="1455236848778" TEXT="aber gegen das Grundkonzept">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
ich wollte explizit kein generisch-introspektives UI,
|
||||
</p>
|
||||
<p>
|
||||
weil das die Tendenz hat, sich zu einem Framework auszuwachsen.
|
||||
</p>
|
||||
<p>
|
||||
Für die UI-Programmierung muß man Spaghetticode akzeptieren.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1455236851592" ID="ID_1599276883" MODIFIED="1455236859119" TEXT="YAGNI">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1455236869405" ID="ID_1141383110" MODIFIED="1455236874756" TEXT="später">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1448658696638" ID="ID_1235910089" MODIFIED="1448658704649" TEXT="slots">
|
||||
<node CREATED="1451177440022" ID="ID_1603816152" MODIFIED="1451177686811" TEXT="expand">
|
||||
|
|
@ -280,6 +323,24 @@
|
|||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1451177719577" ID="ID_1175980404" MODIFIED="1451177726636" TEXT="wie finde ich den Vater..."/>
|
||||
<node CREATED="1455236368345" ID="ID_1490676072" MODIFIED="1455236414978" TEXT="besser">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1455236382183" ID="ID_983670310" MODIFIED="1455236392849" TEXT="Einstiegspunkt: revealYourself"/>
|
||||
<node CREATED="1455236393861" ID="ID_1638665625" MODIFIED="1455236410123">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
support ist <i>optional</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1455236418290" ID="ID_1765760054" MODIFIED="1455236435380" TEXT="dieses ruft parent.reveal(myID)"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1448658726090" FOLDED="true" ID="ID_37610818" MODIFIED="1454978057481" TEXT="Commands">
|
||||
|
|
|
|||
Loading…
Reference in a new issue