From 8fdde735d42c954a8ca605ce4574a36f3d40d620 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 26 Sep 2022 00:24:18 +0200 Subject: [PATCH] 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 --- src/stage/timeline/track-presenter.hpp | 8 ++- src/stage/widget/element-box-widget.cpp | 77 +++++++++++++++++++++++-- src/stage/widget/element-box-widget.hpp | 34 ++++++++++- wiki/thinkPad.ichthyo.mm | 51 ++++++++++------ 4 files changed, 144 insertions(+), 26 deletions(-) diff --git a/src/stage/timeline/track-presenter.hpp b/src/stage/timeline/track-presenter.hpp index c7984b900..e98300b84 100644 --- a/src/stage/timeline/track-presenter.hpp +++ b/src/stage/timeline/track-presenter.hpp @@ -267,7 +267,13 @@ namespace timeline { new model::CanvasHooked{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 diff --git a/src/stage/widget/element-box-widget.cpp b/src/stage/widget/element-box-widget.cpp index 82459189b..31d999869 100644 --- a/src/stage/widget/element-box-widget.cpp +++ b/src/stage/widget/element-box-widget.cpp @@ -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 //#include @@ -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::"< "< //#include #include +#include #include //////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; /** * 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; 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 @@ -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 diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 994f1dd9a..78d16a33e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -18668,6 +18668,9 @@ + + + @@ -18767,13 +18770,13 @@ - - - - + + + + - - + + @@ -18781,16 +18784,16 @@ - - - + + + - - - - + + + + @@ -18810,8 +18813,8 @@ - - + + @@ -18828,8 +18831,8 @@ - - + + @@ -18852,6 +18855,20 @@ + + + + + + + + + + + + + +