UiElement: code and document the functor components

This commit is contained in:
Fischlurch 2018-08-31 19:52:24 +02:00
parent 551920e952
commit 04424fb8df
2 changed files with 125 additions and 28 deletions

View file

@ -23,11 +23,37 @@
/** @file expander-revealer.hpp
** Helper components to implement some standard UI-element actions by installing a functor.
** The protocol for operating UI elements connected to the [UI-Bus](\ref ui-bus.hpp) includes
** some generic operations, which need to be concretised for each actual usage situation.
** Moreover, there are many situations where implementing those actions does not make
** much sense, and thus they need to be treated as optional.
** - some widgets or elements can be expanded or collapsed, to show more information
** or to save screen real estate. Such widgets also expose an _expansion_ state.
** - sometimes it is necessary to bring a given widget into sight, be it to show
** the effect of some processing, or be it to indicate an error situation.
**
** ## Interactions
** ## Usage in the default implementation
**
** The base class of all [tangible UI elements](\ref Tangible) provides a default implementation
** for these generic interaction mechanism: It offers slots to connect UI signals against, and
** it understands the _`mark`_ messages "`expand`" and "`revealYourself`". These are implemented
** by delegating to the \ref Expander and \ref Revealer functors respectively. Moreover, this
** default implementation automatically detects a resulting state change and emits an appropriate
** _`note`_ message on the UI-Bus, so to make those state changes persistent. However, in order
** to supply an concrete implementation, depending on the circumstances, either the widget itself
** or a parent container holding the element needs to install lambdas into those functor holders,
** to detail what actually needs to be done. E.g. it is quite common to implement the "expand"
** functionality by wrapping the widget into a `Gtk::Expander`. Which effectively means that
** the widget itself is not able to expand itself, since this `Gtk::Expander` container widget
** lives within the parent widget to hold the element. So this parent needs to install a
** lambda when establishing the child element, and bind it to the `Gtk::Expander::set_expanded`
** property, and the corresponding `Gtk::Expander::get_expanded` to retrieve the current
** _expansion state_. However, to the contrary, some widgets do implement their _expansion state_
** all by themselves, e.g. by switching the presentation layout. Those widgets will have to
** install an appropriate Expander functor within their constructor.
**
** @see [UI-Element protocol](\ref tangible.hpp)
** @see \ref BusTerm_test
** @see [usage example](\ref error-log-display.hpp)
**
*/
@ -37,54 +63,118 @@
#include "lib/error.hpp"
//#include "lib/idi/entry-id.hpp"
//#include "lib/symbol.hpp"
#include <functional>
//#include <utility>
//#include <string>
#include <utility>
namespace gui {
namespace model {
// using std::string;
// using lib::Symbol;
using std::move;
/**
* Functor component to support the default implementation of expanding/collapsing.
* It is built based on closures (lambdas) to explicate how to detect the expansion
* state of the widget in question and how actively to expand or collapse it.
* A default constructed Expander disables this feature -- which can be detected
* through the #canExpand() function.
*/
class Expander
{
public:
protected:
using ProbeFun = std::function<bool(void)>;
using ChangeFun = std::function<void(bool)>;
Expander()
{ }
ProbeFun probeState_;
ChangeFun changeState_;
public:
Expander() { }
Expander(ProbeFun detectCurrExpansionState, ChangeFun expand_collapse)
: probeState_{move (detectCurrExpansionState)}
, changeState_{move (expand_collapse)}
{
ENSURE (canExpand());
}
protected:
bool
canExpand() const
{
return bool{probeState_}
and bool{changeState_};
}
operator bool() const
{
REQUIRE (canExpand());
return probeState_();
}
bool
operator() (bool shallExpand)
{
REQUIRE (canExpand());
bool currState = probeState_();
if (currState != shallExpand)
changeState_(shallExpand);
return currState;
}
/* === alternate "expressive" API === */
bool
expand (bool yes =true)
{
return this->operator() (yes);
}
bool
collapse()
{
return expand (false);
}
bool
isExpanded() const
{
return bool{*this};
}
};
/**
* Functor component to support the default implementation of revealing an UI-Element.
* It is built based on a closure (lambda) detailing what actually to do in order
* to bring a given UI element into sight. A default constructed Revealer disables
* this feature, which can be detected through the #canReveal() function.
*/
class Revealer
{
public:
protected:
using RevealeItFun = std::function<void()>;
Revealer()
{ }
RevealeItFun revealIt_;
public:
Revealer() { }
Revealer(RevealeItFun how_to_uncover_the_element)
: revealIt_{move (how_to_uncover_the_element)}
{
ENSURE (canReveal());
}
protected:
bool
canReveal() const
{
return bool{revealIt_};
}
void
operator()()
{
REQUIRE (canReveal());
revealIt_();
}
};

View file

@ -1779,7 +1779,7 @@
<icon BUILTIN="info"/>
</node>
</node>
<node CREATED="1535554640586" ID="ID_1376241476" MODIFIED="1535554936517" TEXT="essentiell: passiert im Parent-Widget">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1535554640586" ID="ID_1376241476" MODIFIED="1535737885653" TEXT="essentiell: passiert im Parent-Widget">
<richcontent TYPE="NOTE"><html>
<head>
@ -1789,6 +1789,7 @@
<p>der Parent-Container ist f&#252;r das expand/collapse zust&#228;ndig</p>
</body>
</html></richcontent>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1535634032601" ID="ID_964641889" MODIFIED="1535731317069" TEXT="Design-Problem: sich expandieren">
<icon BUILTIN="button_ok"/>
<node CREATED="1535634116925" ID="ID_1129948550" MODIFIED="1535634126600" TEXT="Voraussetzung: unser Widget-Protokoll">
@ -1917,15 +1918,15 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1535638412517" ID="ID_447101734" MODIFIED="1535731461556" TEXT="Adapter-Interfaces entwerfen">
<node COLOR="#338800" CREATED="1535638412517" ID="ID_447101734" MODIFIED="1535737874447" TEXT="Adapter-Interfaces entwerfen">
<arrowlink COLOR="#709eaf" DESTINATION="ID_316446199" ENDARROW="Default" ENDINCLINATION="-354;-490;" ID="Arrow_ID_1105268233" STARTARROW="None" STARTINCLINATION="-3385;0;"/>
<linktarget COLOR="#5f8cc1" DESTINATION="ID_447101734" ENDARROW="Default" ENDINCLINATION="22;-23;" ID="Arrow_ID_272345450" SOURCE="ID_603236457" STARTARROW="None" STARTINCLINATION="-97;-5;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1535725900392" ID="ID_489679545" MODIFIED="1535725913903" TEXT="Expander">
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1535725900392" ID="ID_489679545" MODIFIED="1535737870629" TEXT="Expander">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1535725906647" ID="ID_1380126396" MODIFIED="1535725914798" TEXT="Revealer">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1535725906647" ID="ID_1380126396" MODIFIED="1535737872678" TEXT="Revealer">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1535726065753" ID="ID_578786610" MODIFIED="1535726072346" TEXT="default-Impl doExpand()">
@ -1941,6 +1942,9 @@
<icon BUILTIN="flag-yellow"/>
<node CREATED="1535725940226" ID="ID_162482468" MODIFIED="1535725949205" TEXT="validiert das Design"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1535737902126" ID="ID_1001984094" MODIFIED="1535737905991" TEXT="Unit-Test">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1534725101578" ID="ID_974315967" MODIFIED="1534725412673" TEXT="clearAll">
@ -2015,6 +2019,9 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1535725982021" ID="ID_858097581" MODIFIED="1535725997876" TEXT="Revealer geeignet verdrahten">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1535737911365" ID="ID_79619425" MODIFIED="1535737923428" TEXT="Unit-Test: AbtractTangible_test erweitern">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>