UiElement: code and document the functor components
This commit is contained in:
parent
551920e952
commit
04424fb8df
2 changed files with 125 additions and 28 deletions
|
|
@ -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_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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ür das expand/collapse zustä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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue