ElementBox: coping with size constraints (closes #1238)

devise a more fine grained algorithm for adapting the display of IDLabel
to a situation with size constrained layout, e.g. for a time calibrated canvas.
We still do not implement the shortening of ID labels (see #1242),
since doing so would be surprisingly expensive. But at least we
do proceed in several steps now

- first attempt to reduce the name-ID (for now: hide it)
- if this doesn't suffice, also hide the menu
- and as a last resort, hide the icon and thus make the IDLabel empty
This commit is contained in:
Fischlurch 2022-10-03 02:08:22 +02:00
parent 8b6991e0f5
commit 3bf3391a63
4 changed files with 530 additions and 25 deletions

View file

@ -88,9 +88,41 @@ namespace widget {
inline void
queryNaturalSize (Gtk::Widget const& widget, Gtk::Requisition& natSize)
{
Gtk::Requisition minimumDummy;
widget.get_preferred_size (minimumDummy, natSize);
Gtk::Requisition minDummy;
widget.get_preferred_size (minDummy, natSize);
}
inline int
queryNaturalHeight (Gtk::Widget const& widget)
{
int minDummy{0}, natHeight{0};
widget.get_preferred_height(minDummy, natHeight);
return natHeight;
}
inline int
queryNaturalWidth (Gtk::Widget const& widget)
{
int minDummy{0}, natWidth{0};
widget.get_preferred_width(minDummy, natWidth);
return natWidth;
}
/** point of reference for layout computations */
Gtk::Requisition ICON_SIZ{};
/** excess factor used to prevent "layout flickering"
* @remark once hidden, an element will only be re-shown
* when some excess headroom is available */
const double HYSTERESIS = 1.6;
inline void
initIconSizeHeuristic (Gtk::Widget const& icon)
{
if (ICON_SIZ.width > 0) return;
queryNaturalSize (icon, ICON_SIZ);
}
}//(End)helpers
@ -151,6 +183,9 @@ namespace widget {
menu_.get_style_context()->add_class(CLASS_idlabel_menu);
name_.get_style_context()->add_class(CLASS_idlabel_name);
name_.set_hexpand(true);
this->show_all();
initIconSizeHeuristic (icon_);
}
@ -164,6 +199,8 @@ namespace widget {
IDLabel::setCaption(cuString& idCaption)
{
name_.set_text(idCaption);
// cache required full display size (for size constrained layout)
queryNaturalSize (*this, labelFullSize_);
}
@ -287,28 +324,158 @@ namespace widget {
/**
* Ensure the IDLabel stays within a given size constraint.
* In case the standard rendering of with icon and name caption exceeds
* the given screen space, this simplified initial implementation just
* hides the name caption, assuming without further check that the two
* icons will fit into the constrained space.
* @todo as of 9/22, a planned full implementation will eventually
* shorten the caption text and possibly also combine both
* Icons into a single button when necessary... ///////////////////TICKET #1238 : adjust size of the ID caption
* In case the standard rendering complete with icon and name caption
* exceeds the given screen space, try to bring this widget into imposed
* limits by reducing or hiding some parts.
*/
void
IDLabel::imposeSizeConstraint (int widthC, int heightC)
{
if (name_.get_visible())
{ // detect if label box fits within given size constraint
queryNaturalSize (*this, labelFullSize_);
if (labelFullSize_.width > widthC or labelFullSize_.height > heightC)
name_.hide();
// short circuit: need to perform precise checks?
if ( labelFullSize_.width > widthC
or labelFullSize_.height > heightC
)
this->adaptSize(widthC, heightC);
}
namespace {//IDLabel layout management internals....
/** attempt to reduce space consumption
* @return achieved width reduction in pixels
*/
inline int
reduce(Gtk::Button& icon)
{
int widthReduction{0};
if (icon.get_visible())
{
widthReduction = queryNaturalWidth (icon);
icon.hide();
}
return widthReduction;
}
/// @todo 10/22 also attempt to shorten the label... ///////////////////TICKET #1242 : adjust size of the ID caption
inline int
reduce(Gtk::Label& label, int goal)
{
ASSERT (goal >=0);
int reduction{0};
if (label.get_visible())
{
int width = queryNaturalWidth (label);
///////////////TODO do something to shorten the label /////////////////////////TICKET #1242 : adjust size of the ID caption
/////// int after = queryNaturalWidth (label);
/////// reduction = width - after;
if (reduction < goal)
{//shortening alone does not suffice
label.hide();
reduction = width;
}
}
return reduction;
}
/** attempt to use available space to show more content
* @param icon widget to possibly expand
* @param w additional width available
* @param h vertical headroom available
* @param reCheck function to update and verify success
* @return if additional content could successfully be expanded
*/
template<class FUN>
inline bool
maybeShow(Gtk::Button& icon, int w, int h, FUN& reCheck)
{
bool success{false};
if (w >= ICON_SIZ.width * HYSTERESIS and h >= ICON_SIZ.height)
{
icon.show();
if (not (success=reCheck()))
icon.hide();
}
return success;
}
template<class FUN>
inline bool
maybeShow(Gtk::Label& label, int w, int h, FUN& reCheck)
{
bool success{false};
// use icon dimensions as as heuristics to determine
// if attempting to show the label is worth trying...
if (w >= ICON_SIZ.width * HYSTERESIS and h >= ICON_SIZ.height)
{
label.show();
int width = queryNaturalWidth (label);
int goal = width - w;
if (goal > 0) // too large, yet might fit if shortened
reduce (label, goal);
if (not (success=reCheck()))
label.hide();
}
return success;
}
}//(End)Layout helpers
/**
* Multi-step procedure to keep this IDLabel widget within the given
* screen size constraints. In case the extension needs to be reduced,
* the name label and both icons are probed and possibly reduced.
* Otherwise, if there is sufficient headroom, an attempt is made
* possibly to show parts again, albeit with some hysteresis.
* @todo as of 10/22, a planned full implementation will eventually
* shorten the caption text and possibly also combine both
* Icons into a single button when necessary... ///////////////////TICKET #1242 : adjust size of the ID caption
*/
void
IDLabel::adaptSize (int widthC, int heightC)
{
// first determine if vertical extension is problematic
int currH = queryNaturalHeight (*this);
if (currH > heightC)
{//hide all child widgets,
// not much options left...
name_.hide();
menu_.hide();
icon_.hide();
return;
}
// now test if we need to reduce or can expand
int currW = queryNaturalWidth (*this);
if (currW > widthC)
{//reduce to comply
int goal = currW - widthC;
ASSERT (goal > 0);
if (goal -= reduce(name_, goal) <= 0) return;
if (goal -= reduce(menu_) <= 0) return;
if (goal -= reduce(icon_) <= 0) return;
currW = queryNaturalWidth(*this);
goal = currW - widthC;
ENSURE (goal <= 0, "IDLabel layout management floundered. "
"Removed all content, yet remaining width %d > %d"
, currW, widthC);
}
else
{
if (labelFullSize_.width <= widthC and labelFullSize_.height <= heightC)
name_.show();
{//maybe some headroom left to show more?
int headroom = widthC - currW;
auto reCheck = [&]() -> bool
{// WARNING: side effect assignment
currW = queryNaturalWidth (*this);
currH = queryNaturalHeight(*this);
headroom = widthC - currW;
return currH <= heightC
and currW <= widthC;
};
if (not maybeShow (icon_, headroom, heightC, reCheck)) return;
if (not maybeShow (menu_, headroom, heightC, reCheck)) return;
if (not maybeShow (name_, headroom, heightC, reCheck)) return;
}
}

View file

@ -125,6 +125,7 @@ namespace widget {
private:
Gtk::Requisition labelFullSize_{};
void adaptSize (int, int);
};

View file

@ -3217,7 +3217,7 @@ In accordance with this structure, we introduce a central component, the {{{Pane
</pre>
</div>
<div title="GuiElementBoxWidget" creator="Ichthyostega" modifier="Ichthyostega" created="201811011919" modified="202209301654" tags="GuiPattern spec draft" changecount="18">
<div title="GuiElementBoxWidget" creator="Ichthyostega" modifier="Ichthyostega" created="201811011919" modified="202210030338" tags="GuiPattern spec draft" changecount="21">
<pre>//A building block used pervasively throughout the Lumiera UI to represent a named entity.//
This widget presents a horizontally extended body, which holds a characteristic ''Head-Triplet'' of visual Elements:
* an //Icon// to create the visual anchor point. In many cases, this will be ''the Placment Icon'' (a hallmark of Lumiera's UI)
@ -3302,7 +3302,7 @@ Especially when the component determines a placement of the //window// within it
!!!constrained Widget size
When used as Clip display on a timeline canvas with calibrated time axis, the requirement arises to confine a GTK widget to a pre established size constraint. This requirement is problematic, as it stands in ''direct contradiction'' to ''GTK's fundamental design'': Elements are never to be positioned explicitly, but rather the layout will flow into balance, factoring in the specific font, language support and interface styling and theming. GTK does not provide any API to set layout explicitly — not even for special corner cases.
Thus, if we intend to bring a custom widget into compliance with our contextual size constraints, the only solution is to //make the GTK layout engine turn out the desired extension allocation// for this custom widget. An detailed survey of the GTK implementation reveals the possible extension points, were such a layout manipulation could be injected.
Thus, if we intend to bring a custom widget into compliance with our contextual size constraints, the only solution is to //make the GTK layout engine turn out the desired extension allocation in accordance to our constraints// for this custom widget. An detailed survey of the GTK implementation reveals the possible extension points, were such a layout manipulation could be injected.
* some amount of screen extension is allocated by the framework or by a container widget for its children
* this happens on first &quot;realisation&quot; of the Widget, or later, when a resize request is processed and the layout cache invalidated
* the entry point is {{{Gtk::Widget::size_allocate()}}} (possibly with an additional &quot;baseline&quot; value)
@ -3316,6 +3316,10 @@ It turns out that the GTK layout management implementation always observes the w
So the seemingly ''optimal leverage point'' is to ''return our pre established size constraint as result'' from these query functions — which can be overridden in the Gtkmm C++ implementation through the {{{Gtk::Widget::get_preferred_width_vfunc()}}} and {{{Gtk::Widget::get_preferred_height_for_width_vfunc()}}}. However, since GTK assumes these values to be sane and sufficient for a proper realisation of any embedded content, at this point it becomes our responsibility to control and reduce the embedded child widget's extension to bring them into compliance. Failing to do so will lead to garbled drawing on screen.
Our solution approach is to watch the results returned by the default implementation and possibly to hide content until the remaining content conforms to the size constraint; after that, we can return //exactly our calibrated size// and expect GTK to observe this request, passing it down to embedded widgets reduced by style decorations.
{{red{🛆 ''Warning'':}}} the code to perform these successive layout adjustments is //potentially performance critical.//
This code is called //for each focus change// and might have to treat //hundreds of widgets// in a typical film edit timeline.
Further empiric survey of memory footprint and invocation times seems indicated &amp;rArr; [[Ticket #1240|https://issues.lumiera.org/ticket/1240]]
</pre>
</div>
<div title="GuiFacade" modifier="Ichthyostega" created="200902080719" modified="201708041501" tags="def spec" changecount="1">
@ -3658,7 +3662,7 @@ Now, since we build our UI on the notion of mapping session contents via a messa
In any case, this is an advanced topic, and nowhere near trivial. It seems reasonable to reject opening duplicate timeline presentations as a first step, and then address this topic way later, when we've gained sufficient knowledge regarding all the subtleties of timeline presentation and editing.</pre>
</div>
<div title="GuiTimelineView" creator="Ichthyostega" modifier="Ichthyostega" created="201410160100" modified="201907192238" tags="GuiPattern design decision draft img" changecount="62">
<div title="GuiTimelineView" creator="Ichthyostega" modifier="Ichthyostega" created="201410160100" modified="202210012303" tags="GuiPattern design decision draft img" changecount="64">
<pre>Within the Lumieara GUI, the [[Timeline]] structure(s) from the HighLevelModel are arranged and presented according to the following principles and conventions.
Several timeline views may be present at the same time -- and there is not necessarily a relation between them, since »a Timeline« is the top-level concept within the [[Session]]. Obviously, there can also be several //views// based on the same »Timeline« model element, and in this latter case, these //coupled views// behave according to a linked common state. An entity »Timeline« as represented through the GUI, emerges from the combination of several model elements
* a root level [[Binding|BindingMO]] acts as framework
@ -3703,7 +3707,8 @@ As indicated in the drawing above, pretty much every UI element exposes a button
!!!slave Timelines
It is reasonable to expect the ability to have multiple [[slave timeline presentations|GuiTimelineSlave]] to access the same underlying timeline structure.
Currently {{red{as of 10/2018}}} there is a preference to deal with that problem on session level -- but for now we decide to postpone this topic &amp;rarr; [[#1083|http://issues.lumiera.org/ticket/1083]]
Currently {{red{as of 10/2018}}} there is a preference to deal with that problem on session level -- but for now we decide to postpone this topic &amp;rarr; [[#1083|https://issues.lumiera.org/ticket/1083]]
{{red{should also reconsider the term »slave«}}}
!!!nesting
By principle, this workspace structure is //not a list of &quot;Tracks&quot;// -- it is a system of ''nested scopes''. The nesting emerges on demand.

View file

@ -19269,21 +19269,302 @@
<icon BUILTIN="idea"/>
</node>
<node CREATED="1664313319325" ID="ID_1660318028" MODIFIED="1664313502546" TEXT="aber: nach dem hide() liefert die umschlie&#xdf;ende Box sofort angepa&#xdf;te preferred_size">
<arrowlink COLOR="#fcf2bc" DESTINATION="ID_611179505" ENDARROW="Default" ENDINCLINATION="88;-31;" ID="Arrow_ID_96952850" STARTARROW="None" STARTINCLINATION="76;2;"/>
<arrowlink COLOR="#fcf2bc" DESTINATION="ID_611179505" ENDARROW="Default" ENDINCLINATION="-47;-40;" ID="Arrow_ID_96952850" STARTARROW="None" STARTINCLINATION="36;39;"/>
<icon BUILTIN="idea"/>
<node CREATED="1664721403567" ID="ID_1984818373" MODIFIED="1664721416232" TEXT="das w&#xe4;re ein weiterer Ansatzpunkt"/>
<node CREATED="1664721417261" ID="ID_264816651" MODIFIED="1664721437070" TEXT="das Widget k&#xf6;nnen die Situation &quot;proben&quot;"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664033098675" ID="ID_617752641" MODIFIED="1664033125288" TEXT="differenziertere L&#xf6;sung evaluieren">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1664033207476" ID="ID_1973707010" MODIFIED="1664033231388" TEXT="Idee: Label dynamisch k&#xfc;rzen">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664721239543" ID="ID_958938237" MODIFIED="1664721462737" TEXT="Ansatz: Komponenten schritweise verbergen">
<arrowlink COLOR="#f8fecd" DESTINATION="ID_611179505" ENDARROW="None" ENDINCLINATION="-198;-9;" ID="Arrow_ID_990474269" STARTARROW="Default" STARTINCLINATION="202;13;"/>
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1664721613355" HGAP="38" ID="ID_100250479" MODIFIED="1664723295433" TEXT="L&#xf6;sungs-Mechanik?" VSHIFT="-26">
<icon BUILTIN="help"/>
<node BACKGROUND_COLOR="#0d5b57" COLOR="#63cb95" CREATED="1664723304392" ID="ID_351577212" MODIFIED="1664723403946" STYLE="bubble" TEXT="Logik">
<edge COLOR="#52c44c" STYLE="linear"/>
<font BOLD="true" NAME="SansSerif" SIZE="15"/>
<node COLOR="#33565a" CREATED="1664723420339" HGAP="38" ID="ID_1605718107" MODIFIED="1664727861369" TEXT="Handlungsbedarf?" VSHIFT="39">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
BEDINGUNG: Constraint &lt; Vollgr&#246;&#223;e
</p>
<ul>
<li>
Vollgr&#246;&#223;e ist im Widget gespeichert und wird nach Text&#228;nderung ermittelt (&#8227;damit implizit auch initial)
</li>
</ul>
</body>
</html></richcontent>
<arrowlink COLOR="#76fe43" DESTINATION="ID_793769798" ENDARROW="Default" ENDINCLINATION="15;-39;" ID="Arrow_ID_1548203404" STARTARROW="None" STARTINCLINATION="-3;6;"/>
<font NAME="SansSerif" SIZE="10"/>
</node>
<node COLOR="#33565a" CREATED="1664723834064" HGAP="35" ID="ID_793769798" MODIFIED="1664727861369" TEXT="erf&#xfc;llt(cH)?" VSHIFT="26">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
BEDINUNG: cH&#160;&gt; aktuelleH&#246;he
</p>
</body>
</html></richcontent>
<linktarget COLOR="#76fe43" DESTINATION="ID_793769798" ENDARROW="Default" ENDINCLINATION="15;-39;" ID="Arrow_ID_1548203404" SOURCE="ID_1605718107" STARTARROW="None" STARTINCLINATION="-3;6;"/>
<font NAME="SansSerif" SIZE="10"/>
<node COLOR="#33565a" CREATED="1664724142663" ID="ID_212862875" MODIFIED="1664727540444" TEXT="Nein &#x27f9; alles ausblenden &#x25a3;">
<font NAME="SansSerif" SIZE="10"/>
</node>
<node COLOR="#33565a" CREATED="1664725209295" ID="ID_657215999" MODIFIED="1664727540444" TEXT="Ja &#x27f9; pr&#xfc;fen...">
<arrowlink COLOR="#76fe43" DESTINATION="ID_1918462068" ENDARROW="Default" ENDINCLINATION="5;-16;" ID="Arrow_ID_1055241213" STARTARROW="None" STARTINCLINATION="-45;7;"/>
<font NAME="SansSerif" SIZE="10"/>
</node>
</node>
<node COLOR="#33565a" CREATED="1664725271351" HGAP="38" ID="ID_1918462068" MODIFIED="1664727540441" TEXT="erf&#xfc;llt(cW)?" VSHIFT="-10">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
BEDINUNG: cW&#160;&gt; aktuelleWeite
</p>
</body>
</html></richcontent>
<linktarget COLOR="#76fe43" DESTINATION="ID_1918462068" ENDARROW="Default" ENDINCLINATION="5;-16;" ID="Arrow_ID_1055241213" SOURCE="ID_657215999" STARTARROW="None" STARTINCLINATION="-45;7;"/>
<font NAME="SansSerif" SIZE="10"/>
<node COLOR="#33565a" CREATED="1664725445271" ID="ID_1506234286" MODIFIED="1664727540444" TEXT="Nein &#x27f9; reduzieren!">
<font NAME="SansSerif" SIZE="10"/>
<node COLOR="#33565a" CREATED="1664725557464" ID="ID_1964737255" MODIFIED="1664727540443" TEXT="reduce(Name)? &#x27f9; &#x25a3;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
BEDINGUNG: &#916;Name &gt; goal
</p>
<ul>
<li>
Hilfsfunktion reduce(Name) : kann im Extremfall den Namen ausblenden
</li>
</ul>
</body>
</html></richcontent>
<font NAME="SansSerif" SIZE="10"/>
</node>
<node COLOR="#33565a" CREATED="1664725557464" ID="ID_827509447" MODIFIED="1664727540443" TEXT="reduce(Menu)? &#x27f9; &#x25a3;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
BEDINGUNG: &#916;Menu &gt; goal
</p>
<ul>
<li>
Hilfsfunktion reduce(Menu) : kann das Men&#252; ggfs ausblenden und liefert das dadurch erzielte Delta
</li>
</ul>
</body>
</html></richcontent>
<font NAME="SansSerif" SIZE="10"/>
</node>
<node COLOR="#33565a" CREATED="1664725557464" ID="ID_76551672" MODIFIED="1664727540443" TEXT="reduce(Icon) &#x25a3;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Hier kein Test mehr notwendig; mehr als alles ausblenden k&#246;nnen wir nicht
</p>
</body>
</html></richcontent>
<font NAME="SansSerif" SIZE="10"/>
</node>
</node>
<node COLOR="#33565a" CREATED="1664725508319" ID="ID_348137834" MODIFIED="1664727540442" TEXT="Ja &#x27f9; einblenden?">
<font NAME="SansSerif" SIZE="10"/>
<node COLOR="#33565a" CREATED="1664726003283" ID="ID_991077863" MODIFIED="1664727540443" TEXT="show(Icon)? Nein &#x27f9; &#x25a3;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Mehrstufige Pr&#252;fung mit Hysterese (um Flackern zu vermeiden)...
</p>
<ul>
<li>
rechnerische Pr&#252;fung: Nominalgr&#246;&#223;e Icon + Hysterese &lt; cW <i>und ebenso </i>&lt; cH
</li>
<li>
danach: Icon einblenden und reale Gr&#246;&#223;e ermitteln und gegen Constraint checken
</li>
</ul>
</body>
</html></richcontent>
<font NAME="SansSerif" SIZE="10"/>
</node>
<node COLOR="#33565a" CREATED="1664726003283" ID="ID_1754814316" MODIFIED="1664727540443" TEXT="show(Menu)? Nein &#x27f9; &#x25a3;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
auch hier mehrstufige Pr&#252;fung mit Hysterese...
</p>
</body>
</html></richcontent>
<font NAME="SansSerif" SIZE="10"/>
</node>
<node COLOR="#33565a" CREATED="1664726003283" ID="ID_249986815" MODIFIED="1664727540442" TEXT="show(Name)? &#x25a3;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
auch hier mehrstufige Pr&#252;fung...
</p>
<ul>
<li>
zun&#228;chst rechnerisch...
</li>
<ul>
<li>
in der ersten (einfachen) Version wird gegen die nominelle Gesamtgr&#246;&#223;e gepr&#252;ft + Hysterese
</li>
<li>
in der (geplanten) Vollversion pr&#252;fen wir gegen die Icon-Gr&#246;&#223;e + Hysterese, und unterstellen, da&#223; sich der Name dann hinreichend k&#252;rzen kann
</li>
</ul>
<li>
danach wird der Name eingeblendet und reduce(Name) aufgerufen; sollte dies scheitern, mu&#223; eine Warnung und Assertion-Failure erfolgen, da die Logik sonst zwangsl&#228;ufig in ein Schleife mit permanentem Flackern l&#228;uft!
</li>
</ul>
</body>
</html></richcontent>
<font NAME="SansSerif" SIZE="10"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664727903654" HGAP="47" ID="ID_479783297" MODIFIED="1664727915770" TEXT="Implementierung" VSHIFT="-4">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#435e98" CREATED="1664766812799" ID="ID_806792302" MODIFIED="1664767612419" TEXT="weitgehend in lokalen Funktionen implementierbar">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#435e98" CREATED="1664766835991" ID="ID_325959824" MODIFIED="1664767606249" TEXT="redundante Gr&#xf6;&#xdf;en-Ermittlung in der Kette">
<icon BUILTIN="clanbomber"/>
<node CREATED="1664766851269" ID="ID_1929258813" MODIFIED="1664767130682" TEXT="habe hier Bedenken wegen der Performance">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
<font color="#b1058d"><i>premature optimisation</i></font>??
</p>
<p>
Normalwerweise funktionieren alle unsere GUIs trotzdem schnell genug.<br />Aber hier wollen wir diese Sequenz hunderte Mal f&#252;r jeden Fokus-Wechsel machen...
</p>
<p>
</p>
<p>
<b>Problematisch</b>&#160;ist, da&#223; hier &#252;ber zwei Ebenen hinweg und &#252;ber zwei mal zwei virtuelle Calls gegangen wird
</p>
<ul>
<li>
wir springen jeweils in eine non-inline-Funktion auf Gtkmm
</li>
<li>
diese delegiert auf eine non-inline-Funktion in Gtk+
</li>
<li>
und diese nutzt u.U zwei drei virtuelle Callbacks (Layout-Trend, Haupt-Dimension, sekund&#228;re Dimension)
</li>
<li>
und jeder dieser Callbacks wir ein weiteres Mal von Gtkmm durch eine vtable dispatched
</li>
</ul>
</body>
</html></richcontent>
</node>
<node CREATED="1664767140485" ID="ID_428399436" MODIFIED="1664767217656" TEXT="vor allem die wieder-einblenden-Sequenz ist gef&#xe4;hrlich">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...denn sie wird f&#252;r jeden Fokuswechsel und f&#252;r jeden erfolglosen Versuch erneut durchlaufen, und zwar in den meisten F&#228;llen (Label) bis zum 3.Schritt, nur um dann zu merken, da&#223; eben doch nichts mehr rauszuholen ist.
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1664767237232" ID="ID_871917652" MODIFIED="1664767375307" TEXT="leider arbeiten hier die mog&#xf6;ichen Paddings gegen uns">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
wenn das Stylesheet eben doch zus&#228;tzliche Paddings definiert, dann geht die Rechnung nicht auf, da sie auf den required-sizes der Kind-Widgets beruht, und daher (mit Paddings) zu optimistisch ist. Daher <i>m&#252;ssen wir zwingend</i>&#160;nach einem versuchten wieder-Einblenden die <i>reale Ausdehnung des ganzen IDLabel </i>ermitteln und gegen die Constraints pr&#252;fen. Bei der Verkleinerung ist das nicht der Fall, denn da wirken die wegfallenden Paddings als zus&#228;tzlicher &quot;Bonus&quot;.
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1664767377647" ID="ID_482878586" MODIFIED="1664767538685" TEXT="Verwende ein &#x3bb; mit Seiteneffekt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Damit mu&#223; ich nach jedem Schritt nur einmal die Gr&#246;&#223;e neu ermitteln; diese Werte schlagen dann aus dem &#955; per Seiteneffekt auf die Variablen des umschlie&#223;enden Scope durch. Das &#955; selber ist &quot;scheinbar&quot; nur eine Pr&#252;f-Funktion, und wird als Solche an die Hilfsfunktionen gegeben. Nicht sch&#246;n, aber auch nicht wirklich gef&#228;hrlich, da sich alles in einem lokalen Namespace abspielt. Habe eine Warnung im Code hinterlassen
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1664767619949" ID="ID_1351254549" MODIFIED="1664767684028" TEXT="Test">
<icon BUILTIN="pencil"/>
<node CREATED="1664767649344" ID="ID_408352584" MODIFIED="1664767655318" TEXT="kein Crash">
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1664767638298" ID="ID_212652160" MODIFIED="1664767648612" TEXT="Ausblenden des Label funktioniert"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1664767657871" ID="ID_599051282" MODIFIED="1664768828505" TEXT="Ausblenden der Icons funktioniert nicht">
<icon BUILTIN="broken-line"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1664033207476" ID="ID_1973707010" MODIFIED="1664721283088" TEXT="Weiterf&#xfc;hrende Idee: Label dynamisch k&#xfc;rzen">
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664769914851" ID="ID_816204048" MODIFIED="1664769938381" TEXT="#1242 shorten ID-Label text to fit into size constraints">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1664027420141" ID="ID_891209068" MODIFIED="1664033227851" TEXT="kann man den Label-Text &#xe4;ndern und sieht sofort eine &#xc4;nderung auf dem Layout-Callback?">
<linktarget COLOR="#bf4283" DESTINATION="ID_891209068" ENDARROW="Default" ENDINCLINATION="-836;28;" ID="Arrow_ID_120092077" SOURCE="ID_945958753" STARTARROW="None" STARTINCLINATION="260;-42;"/>
<icon BUILTIN="help"/>
<node CREATED="1664313375789" ID="ID_611179505" MODIFIED="1664313504665" TEXT="zumindest nach hide() ist sofort die prefered_size angepa&#xdf;t">
<linktarget COLOR="#fcf2bc" DESTINATION="ID_611179505" ENDARROW="Default" ENDINCLINATION="88;-31;" ID="Arrow_ID_96952850" SOURCE="ID_1660318028" STARTARROW="None" STARTINCLINATION="76;2;"/>
<linktarget COLOR="#fcf2bc" DESTINATION="ID_611179505" ENDARROW="Default" ENDINCLINATION="-47;-40;" ID="Arrow_ID_96952850" SOURCE="ID_1660318028" STARTARROW="None" STARTINCLINATION="36;39;"/>
<linktarget COLOR="#f8fecd" DESTINATION="ID_611179505" ENDARROW="None" ENDINCLINATION="-198;-9;" ID="Arrow_ID_990474269" SOURCE="ID_958938237" STARTARROW="Default" STARTINCLINATION="202;13;"/>
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664543738587" ID="ID_418832883" MODIFIED="1664543749125" TEXT="Experiment durchf&#xfc;hren">
@ -19321,6 +19602,10 @@
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1664033233729" ID="ID_73562728" MODIFIED="1664033252543" TEXT="ggfs &#xdc;bersetzungs-Faktor im Advice-System ablegen">
<icon BUILTIN="hourglass"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1664728069849" ID="ID_458393482" MODIFIED="1664728428510" TEXT="Performance der Anzeigelogik beobachten">
<arrowlink COLOR="#675f90" DESTINATION="ID_1113493685" ENDARROW="Default" ENDINCLINATION="144;-94;" ID="Arrow_ID_314973122" STARTARROW="None" STARTINCLINATION="-577;39;"/>
<icon BUILTIN="bell"/>
</node>
</node>
<node COLOR="#338800" CREATED="1664033337194" ID="ID_142928718" MODIFIED="1664674849781" TEXT="Label-Komponente anlegen">
<arrowlink COLOR="#feebc1" DESTINATION="ID_1075411565" ENDARROW="Default" ENDINCLINATION="-16;-582;" ID="Arrow_ID_957764469" STARTARROW="None" STARTINCLINATION="-606;54;"/>
@ -19712,6 +19997,25 @@
<arrowlink COLOR="#bf4283" DESTINATION="ID_891209068" ENDARROW="Default" ENDINCLINATION="-836;28;" ID="Arrow_ID_120092077" STARTARROW="None" STARTINCLINATION="260;-42;"/>
<icon BUILTIN="hourglass"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#793f70" CREATED="1664728013606" ID="ID_1113493685" MODIFIED="1664730778937" TEXT="Performance-on-scale">
<linktarget COLOR="#675f90" DESTINATION="ID_1113493685" ENDARROW="Default" ENDINCLINATION="144;-94;" ID="Arrow_ID_314973122" SOURCE="ID_458393482" STARTARROW="None" STARTINCLINATION="-577;39;"/>
<linktarget COLOR="#652a49" DESTINATION="ID_1113493685" ENDARROW="Default" ENDINCLINATION="-1026;116;" ID="Arrow_ID_977109999" SOURCE="ID_46750178" STARTARROW="None" STARTINCLINATION="-985;55;"/>
<linktarget COLOR="#652a49" DESTINATION="ID_1113493685" ENDARROW="Default" ENDINCLINATION="-1026;116;" ID="Arrow_ID_1663742451" SOURCE="ID_499807590" STARTARROW="None" STARTINCLINATION="-985;55;"/>
<icon BUILTIN="bell"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664730454742" ID="ID_898331208" MODIFIED="1664730461480" TEXT="#1240 evaluate performance of ElementBoxWidget">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1664728161348" ID="ID_541577601" MODIFIED="1664728171859" TEXT="Speicherbedarf">
<node CREATED="1664728182417" ID="ID_787168469" MODIFIED="1664728197093" TEXT="Speichern der Maximalgr&#xf6;&#xdf;e"/>
<node CREATED="1664728197911" ID="ID_238915264" MODIFIED="1664728205283" TEXT="Speichern des vollst&#xe4;ndigen Label-Textes"/>
<node CREATED="1664728207952" ID="ID_1837798110" MODIFIED="1664728236438" TEXT="Speichern des vorhergehenden Constraints"/>
</node>
<node CREATED="1664728246927" ID="ID_502396500" MODIFIED="1664728250323" TEXT="Laufzeit">
<node CREATED="1664728261343" ID="ID_1345184412" MODIFIED="1664728285571" TEXT="Laufzeit incl Ein/Ausblenden (aller Widgets)"/>
<node CREATED="1664728287779" ID="ID_382936001" MODIFIED="1664728325578" TEXT="Laufzeit mit/ohne Pr&#xfc;fung redundanter Constraints"/>
<node CREATED="1664728326686" ID="ID_724874601" MODIFIED="1664728340360" TEXT="Laufzeit mit/ohne Pr&#xfc;fung der Maximalausdehnung"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1654445541606" ID="ID_520455096" MODIFIED="1654445545420" TEXT="Integrieren">
<icon BUILTIN="flag-yellow"/>
@ -36091,6 +36395,17 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1664730879582" FOLDED="true" ID="ID_580266574" MODIFIED="1664731036535" TEXT="Performance-Aspekte">
<linktarget COLOR="#6e6b89" DESTINATION="ID_580266574" ENDARROW="Default" ENDINCLINATION="-1072;126;" ID="Arrow_ID_1760515184" SOURCE="ID_1774914566" STARTARROW="None" STARTINCLINATION="-1832;638;"/>
<icon BUILTIN="hourglass"/>
<node CREATED="1664730914274" ID="ID_352020246" MODIFIED="1664730918069" TEXT="Architektur"/>
<node CREATED="1664730918937" ID="ID_524082357" MODIFIED="1664730921221" TEXT="Empirie">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664728069849" ID="ID_46750178" MODIFIED="1664730924226" TEXT="#1240 evaluate performance of ElementBoxWidget">
<arrowlink COLOR="#652a49" DESTINATION="ID_1113493685" ENDARROW="Default" ENDINCLINATION="-1026;116;" ID="Arrow_ID_977109999" STARTARROW="None" STARTINCLINATION="-985;55;"/>
<icon BUILTIN="bell"/>
</node>
</node>
</node>
</node>
<node CREATED="1448070434915" HGAP="64" ID="ID_257833497" MODIFIED="1557498707234" VSHIFT="7">
<richcontent TYPE="NODE"><html>
@ -64126,6 +64441,23 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1664730709910" FOLDED="true" ID="ID_532850171" MODIFIED="1664731043947" TEXT="Performance">
<icon BUILTIN="hourglass"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1664730715885" ID="ID_1774914566" MODIFIED="1664731036535" TEXT="GUI">
<arrowlink COLOR="#6e6b89" DESTINATION="ID_580266574" ENDARROW="Default" ENDINCLINATION="-1072;126;" ID="Arrow_ID_1760515184" STARTARROW="None" STARTINCLINATION="-1832;638;"/>
<icon BUILTIN="hourglass"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664728069849" ID="ID_499807590" MODIFIED="1664730778937" TEXT="#1240 evaluate performance of ElementBoxWidget">
<arrowlink COLOR="#652a49" DESTINATION="ID_1113493685" ENDARROW="Default" ENDINCLINATION="-1026;116;" ID="Arrow_ID_1663742451" STARTARROW="None" STARTINCLINATION="-985;55;"/>
<icon BUILTIN="bell"/>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1664730718511" ID="ID_1773381955" MODIFIED="1664730727367" TEXT="Engine">
<icon BUILTIN="hourglass"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1664730722868" ID="ID_1536097796" MODIFIED="1664730727368" TEXT="Session">
<icon BUILTIN="hourglass"/>
</node>
</node>
<node CREATED="1561238618311" ID="ID_1197206022" MODIFIED="1561311521089" TEXT="Plattform-Evolution">
<icon BUILTIN="go"/>
<node COLOR="#435e98" CREATED="1561238627847" ID="ID_776424925" MODIFIED="1561311477641" TEXT="Juni 2019">