ElementBox: draft logic to impose size constraint on child widgets
...does not work reliably yet... - on first invocation, the child allocation is still zero - later on, there seem to be lots of further invocations, always when the application window gains focus - these further invocations somehow change the visible extension of the widget's background
This commit is contained in:
parent
36594cd774
commit
8fdde735d4
4 changed files with 144 additions and 26 deletions
|
|
@ -267,7 +267,13 @@ namespace timeline {
|
|||
new model::CanvasHooked<widget::ElementBoxWidget, Gtk::Widget>{display_.hookedAt(x,y)
|
||||
, widget::Kind::MARK
|
||||
, widget::Type::LABEL
|
||||
, widget::name("Ω")
|
||||
, widget::name("ΩΩΩΩΩ")
|
||||
, widget::constrained(
|
||||
[]()
|
||||
{
|
||||
uint arbitrarySiz = 10 + rand() % 60;
|
||||
return arbitrarySiz;
|
||||
})
|
||||
});
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1201 : test/code... remove this
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@
|
|||
|
||||
//#include "stage/ui-bus.hpp"
|
||||
//#include "lib/format-string.hpp"
|
||||
//#include "lib/format-cout.hpp"
|
||||
#include "lib/format-cout.hpp" //////////////////////TODO debugging
|
||||
|
||||
//#include "lib/util.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <algorithm>
|
||||
//#include <vector>
|
||||
|
|
@ -78,10 +78,13 @@ namespace widget {
|
|||
|
||||
|
||||
ElementBoxWidget::Strategy
|
||||
ElementBoxWidget::Config::buildLayoutStrategy(ElementBoxWidget& widget)
|
||||
ElementBoxWidget::Config::buildLayoutStrategy(ElementBoxWidget&)
|
||||
{
|
||||
Strategy strategy; //NOTE: relying on return-value-optimisation
|
||||
///////////////////////////////////////////////////////////////////////////TICKET #1235 : evaluate size constraint here
|
||||
Strategy strategy;
|
||||
if (widthConstraint_)
|
||||
strategy.getWidth = move(widthConstraint_);
|
||||
if (heightConstraint_)
|
||||
strategy.getHeight = move(heightConstraint_);
|
||||
return strategy;
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +144,7 @@ namespace widget {
|
|||
* - adjust_for_align
|
||||
* After these adjustments and some sanity checks, the resulting size allocation
|
||||
* is passed to the `size_allocate` vfunc, which could be tapped on the Gtk::Widget
|
||||
* C++ wrapper, but usually just stores this allocation into the widget private data.
|
||||
* C++ wrapper, but usually just stores this allocation into the widget private data.
|
||||
*/
|
||||
void
|
||||
ElementBoxWidget::get_preferred_width_vfunc (int& minimum_width, int& natural_width) const
|
||||
|
|
@ -161,6 +164,68 @@ namespace widget {
|
|||
_Base::get_preferred_height_for_width_vfunc (width, minimum_height,natural_height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tap into the notification of screen space allocation to possibly enforce size constraints.
|
||||
* Generally speaking, explicit size constrained widgets are not a concept supported by GTK,
|
||||
* due to its flexible layout model and the use of CSS for styling and theming. Unfortunately
|
||||
* we need this feature, in order to implement Clip widgets on a time calibrated canvas.
|
||||
* Thus we use an **implementation trick**: we report our size constraints as "natural size"
|
||||
* to GTK, knowing that GTK will respect those extensions (unless the widget is placed into
|
||||
* a container with fill-alignment). However, by doing so, we have effectively lied to GTK
|
||||
* with respect to our child widgets. Thus we now have to take on the responsibility to
|
||||
* somehow make those child widgets fit into the limited size allocation....
|
||||
*/
|
||||
void
|
||||
ElementBoxWidget::on_size_allocate (Gtk::Allocation& availableSize)
|
||||
{
|
||||
if (strategy_.is_size_constrained())
|
||||
imposeSizeConstraint (availableSize.get_width(), availableSize.get_height());
|
||||
_Base::on_size_allocate(availableSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensure the child widgets can be represented and possibly adjust or hide content,
|
||||
* in case the extension of ElementBoxWidget is explicitly constrained in size.
|
||||
*/
|
||||
void
|
||||
ElementBoxWidget::imposeSizeConstraint(int widthC, int heightC)
|
||||
{
|
||||
//if (not icon_.get_realized()) return;
|
||||
bool isRe = name_.get_realized();
|
||||
bool isMa = name_.get_mapped();
|
||||
|
||||
bool hiddenCaption = not name_.get_visible();
|
||||
|
||||
Gtk::Allocation iconSiz = icon_.get_allocation();
|
||||
Gtk::Allocation nameSiz = name_.get_allocation();
|
||||
|
||||
if (not hiddenCaption)
|
||||
{
|
||||
labelWidth_ = nameSiz.get_width();
|
||||
labelHeight_= nameSiz.get_height();
|
||||
}
|
||||
int requiredWidth = iconSiz.get_width() + labelWidth_;
|
||||
int requiredHeight = iconSiz.get_height() + labelHeight_;
|
||||
|
||||
if (hiddenCaption)
|
||||
{
|
||||
if (requiredWidth <= widthC and requiredHeight <= heightC)
|
||||
{ /////////////////////////////////////////////////////////////////////////////////////////////////TODO: diagnostics -- remove this
|
||||
name_.show();
|
||||
cout << "SHOW::"<<this<<":: "<<requiredWidth<<" <= "<<widthC <<endl;/////////////////////////////TODO: diagnostics -- remove this
|
||||
} /////////////////////////////////////////////////////////////////////////////////////////////////TODO: diagnostics -- remove this
|
||||
}
|
||||
else
|
||||
{
|
||||
if (requiredWidth > widthC or requiredHeight > heightC)
|
||||
{ /////////////////////////////////////////////////////////////////////////////////////////////////TODO: diagnostics -- remove this
|
||||
name_.hide();
|
||||
cout << "HIDE::"<<this<<":: "<<requiredWidth<<" > "<<widthC <<endl;//////////////////////////////TODO: diagnostics -- remove this
|
||||
} /////////////////////////////////////////////////////////////////////////////////////////////////TODO: diagnostics -- remove this
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}}// namespace stage::widget
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
//#include <memory>
|
||||
//#include <vector>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <string> //////TODO debugging
|
||||
|
||||
|
||||
|
|
@ -59,6 +60,7 @@
|
|||
namespace stage {
|
||||
namespace widget {
|
||||
|
||||
using std::move;
|
||||
using lib::Literal;
|
||||
using std::string; /////TODO
|
||||
using util::_Fmt; /////TODO debugging?
|
||||
|
|
@ -83,6 +85,7 @@ namespace widget {
|
|||
, META ///< represents some meta entity
|
||||
};
|
||||
|
||||
using SizeGetter = std::function<int()>;
|
||||
|
||||
/**
|
||||
* A basic building block of the Lumiera UI.
|
||||
|
|
@ -97,7 +100,6 @@ namespace widget {
|
|||
: public Gtk::Frame
|
||||
{
|
||||
using _Base = Gtk::Frame;
|
||||
using SizeGetter = std::function<int()>;
|
||||
struct Strategy
|
||||
{
|
||||
SizeGetter getWidth{};
|
||||
|
|
@ -130,8 +132,10 @@ namespace widget {
|
|||
Gtk::SizeRequestMode get_request_mode_vfunc() const final;
|
||||
void get_preferred_width_vfunc (int&, int&) const override;
|
||||
void get_preferred_height_for_width_vfunc (int, int&,int&) const override;
|
||||
void on_size_allocate (Gtk::Allocation&) override;
|
||||
|
||||
_Base& getBase() { return *this; }
|
||||
void imposeSizeConstraint(int, int);
|
||||
int labelWidth_{0}, labelHeight_{0};
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -140,11 +144,15 @@ namespace widget {
|
|||
{
|
||||
Type type_;
|
||||
uString nameID_{"∅"};
|
||||
SizeGetter widthConstraint_;
|
||||
SizeGetter heightConstraint_;
|
||||
string logTODO_{nameID_}; //////////////////////////////////////////////////////////////////////////TICKET #1219 : Placeholder for detailed layout configuration
|
||||
|
||||
friend Qualifier kind(Kind);
|
||||
friend Qualifier name(string id);
|
||||
friend Qualifier expander(model::Expander&);
|
||||
friend Qualifier constrained(SizeGetter);
|
||||
friend Qualifier constrained(SizeGetter,SizeGetter);
|
||||
|
||||
public:
|
||||
template<class... QS>
|
||||
|
|
@ -198,6 +206,28 @@ namespace widget {
|
|||
}};
|
||||
}
|
||||
|
||||
inline ElementBoxWidget::Config::Qualifier
|
||||
constrained(SizeGetter widthConstraint)
|
||||
{
|
||||
return ElementBoxWidget::Config::Qualifier{
|
||||
[wC=move(widthConstraint)](ElementBoxWidget::Config& config) -> void
|
||||
{
|
||||
config.widthConstraint_ = move(wC);
|
||||
}};
|
||||
}
|
||||
|
||||
inline ElementBoxWidget::Config::Qualifier
|
||||
constrained(SizeGetter widthConstraint, SizeGetter heightConstraint)
|
||||
{
|
||||
return ElementBoxWidget::Config::Qualifier{
|
||||
[wC=move(widthConstraint),hC=move(heightConstraint)]
|
||||
(ElementBoxWidget::Config& config) -> void
|
||||
{
|
||||
config.widthConstraint_ = move(wC);
|
||||
config.heightConstraint_ = move(hC);
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
/** setup an ElementBoxWidget with suitable presentation style.
|
||||
* @param widgetKind the basic presentation intent
|
||||
|
|
|
|||
|
|
@ -18668,6 +18668,9 @@
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664027526879" ID="ID_849843415" MODIFIED="1664027540069" TEXT="an der konkreten Implementierung beobachten">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1664152872453" ID="ID_1559151133" MODIFIED="1664152874424" TEXT="korrekt"/>
|
||||
<node CREATED="1664152875229" ID="ID_1591242265" MODIFIED="1664152886391" TEXT="definitiv aus der Event-Loop"/>
|
||||
<node CREATED="1664152887076" ID="ID_1667743717" MODIFIED="1664152893950" TEXT="und nicht aus dem Widget-ctor"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1664027626370" ID="ID_244953029" MODIFIED="1664027646110" TEXT="eine falsche Angabe führt zu (vorübergehend) falschem Layout"/>
|
||||
|
|
@ -18767,13 +18770,13 @@
|
|||
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664028782841" ID="ID_1596292708" MODIFIED="1664028795533" TEXT="Implementierung der Schnittstelle">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664028797404" ID="ID_1421736344" MODIFIED="1664028806653" TEXT="die λ speichern">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1664028782841" ID="ID_1596292708" MODIFIED="1664152807960" TEXT="Implementierung der Schnittstelle">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1664028797404" ID="ID_1421736344" MODIFIED="1664152806643" TEXT="die λ speichern">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664028811314" ID="ID_1790496772" MODIFIED="1664028821834" TEXT="die Höhen-Angabe optional machen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1664028811314" ID="ID_1790496772" MODIFIED="1664152804500" TEXT="die Höhen-Angabe optional machen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1664028833680" ID="ID_822885755" MODIFIED="1664136676337" TEXT="Prädikat: Erkennung size-constrained">
|
||||
<linktarget COLOR="#fff78b" DESTINATION="ID_822885755" ENDARROW="Default" ENDINCLINATION="-71;5;" ID="Arrow_ID_502040558" SOURCE="ID_10961106" STARTARROW="None" STARTINCLINATION="67;7;"/>
|
||||
|
|
@ -18781,16 +18784,16 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664028974965" ID="ID_1683239335" MODIFIED="1664028982693" TEXT="Weiche in den Layout-Callbacks">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664028987763" ID="ID_10961106" MODIFIED="1664029045885" TEXT="beruht auf dem Prädikat">
|
||||
<node COLOR="#338800" CREATED="1664028974965" ID="ID_1683239335" MODIFIED="1664152835281" TEXT="Weiche in den Layout-Callbacks">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1664028987763" ID="ID_10961106" MODIFIED="1664152816917" TEXT="beruht auf dem Prädikat">
|
||||
<arrowlink COLOR="#fff78b" DESTINATION="ID_822885755" ENDARROW="Default" ENDINCLINATION="-71;5;" ID="Arrow_ID_502040558" STARTARROW="None" STARTINCLINATION="67;7;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664029083790" ID="ID_1708491997" MODIFIED="1664029103893" TEXT="Antwort der Callbacks implementieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664029105419" ID="ID_1976797471" MODIFIED="1664029125271" TEXT="entweder per λ">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1664029083790" ID="ID_1708491997" MODIFIED="1664152834413" TEXT="Antwort der Callbacks implementieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1664029105419" ID="ID_1976797471" MODIFIED="1664152823165" TEXT="entweder per λ">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1664029112435" ID="ID_82095109" MODIFIED="1664136681131" TEXT="oder die Basis-Impl verwenden">
|
||||
<arrowlink COLOR="#6873c6" DESTINATION="ID_986565985" ENDARROW="Default" ENDINCLINATION="31;1;" ID="Arrow_ID_1518071893" STARTARROW="None" STARTINCLINATION="-102;26;"/>
|
||||
|
|
@ -18810,8 +18813,8 @@
|
|||
</node>
|
||||
<node CREATED="1664029267136" ID="ID_1383671067" MODIFIED="1664029355911" TEXT="zwei Themen">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664029340460" ID="ID_1398837731" MODIFIED="1664029426849" TEXT="Ausdehnung des Labels steuern">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1664029340460" ID="ID_1398837731" MODIFIED="1664152792801" TEXT="Ausdehnung des Labels steuern">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1664031831907" ID="ID_701574899" MODIFIED="1664031980972" TEXT="Problem: reaktiv getriggert">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
|
@ -18828,8 +18831,8 @@
|
|||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664035985288" ID="ID_1514029086" MODIFIED="1664035990688" TEXT="#1238 hide ElementBoxWidget label to meet size constraint">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664032709767" ID="ID_89148369" MODIFIED="1664032719812" TEXT="einfache Lösung: per Seiteneffekt verbergen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1664032709767" ID="ID_89148369" MODIFIED="1664152782210" TEXT="einfache Lösung: per Seiteneffekt verbergen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1664032721142" ID="ID_999001948" MODIFIED="1664033062210" TEXT="geht das?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
|
@ -18852,6 +18855,20 @@
|
|||
</ul>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1664152924415" ID="ID_1883395520" MODIFIED="1664152940446" TEXT="funktioniert nicht zuverläasig">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1664152946955" ID="ID_5147112" MODIFIED="1664152961325" TEXT="beim 1.Aufruf sind die Allocationen noch allesamt 0"/>
|
||||
<node CREATED="1664152963036" ID="ID_1568702731" MODIFIED="1664152994857" TEXT="es gibt später bei jedem Focus-Wechsel einen Aufruf"/>
|
||||
<node CREATED="1664152996461" ID="ID_1521476415" MODIFIED="1664153038156" TEXT="und dieser führt jeweils zu einer anderen Ausdehnung des Hintergrunds (Flackern?)">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1664153044266" ID="ID_175410634" MODIFIED="1664153998416" TEXT="und das Debugging per cout gibt Hexzahlen aus">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1664152748537" ID="ID_1604673752" MODIFIED="1664152775554" TEXT="besser: on_size_allocate verwenden">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1664027420141" ID="ID_969143327" MODIFIED="1664032937882" TEXT="führt das zu einem re-Draw?">
|
||||
<linktarget COLOR="#bf4283" DESTINATION="ID_969143327" ENDARROW="Default" ENDINCLINATION="-1003;96;" ID="Arrow_ID_190980327" SOURCE="ID_945958753" STARTARROW="None" STARTINCLINATION="260;-42;"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue