From 83fab8cb0ffd6ee7a38ec6e4dd768b1b3f9eb896 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Mon, 29 Dec 2025 16:21:17 +0100 Subject: Fix Fl_Pack to support more box types. Old code supported only frame styles, this code can now handle box types with a background. --- FL/Fl_Pack.H | 8 ++++++++ src/Fl_Pack.cxx | 35 +++++++++++++++++++++++++++-------- test/preferences.fl | 8 ++++++-- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/FL/Fl_Pack.H b/FL/Fl_Pack.H index 3990a1907..334123115 100644 --- a/FL/Fl_Pack.H +++ b/FL/Fl_Pack.H @@ -21,6 +21,7 @@ #define Fl_Pack_H #include +#include /** This widget was designed to add the functionality of compressing and @@ -39,6 +40,12 @@ resizable() widget is the last widget in the group it is extended to take the full available width or height, respectively, of the Fl_Pack group. + \note Fl_Pack is optimized to use a frame-only (`..._FRAME`) box type. + Box types with background graphics (`..._BOX`) generally work, but can be + slower witch a large number of children. Not all box types work well + with FL_Pack. Avoid irregular graphics like FL_DIAMOND_BOX and background + images. + \note You can nest Fl_Pack widgets or put them inside Fl_Scroll widgets or inside other group widgets but their behavior can sometimes be "surprising". This is partly due to the fact that Fl_Pack widgets @@ -61,6 +68,7 @@ public: }; protected: + void draw_filler_(const Fl_Rect& rect); void draw() override; public: diff --git a/src/Fl_Pack.cxx b/src/Fl_Pack.cxx index bbc5c2434..f28218c20 100644 --- a/src/Fl_Pack.cxx +++ b/src/Fl_Pack.cxx @@ -49,6 +49,22 @@ Fl_Pack::Fl_Pack(int X, int Y, int W, int H, const char *L) // type(VERTICAL); // already set like this } +/** Draw a rectangular area as a background filler. + If the box type has a background (is not a frame), this will clip to the + rectangular area and draw the box. Otherwise, it will draw a rectangle + in widget color. + \param[in] rect fill this rectangle inside the widget bounds + */ +void Fl_Pack::draw_filler_(const Fl_Rect& rect) { + if (Fl::box_bg(box())) { + fl_push_clip(rect.x(), rect.y(), rect.w(), rect.h()); + draw_box(); + fl_pop_clip(); + } else { + fl_rectf(rect.x(), rect.y(), rect.w(), rect.h(), color()); + } +} + void Fl_Pack::draw() { int tx = x()+Fl::box_dx(box()); int ty = y()+Fl::box_dy(box()); @@ -102,11 +118,10 @@ void Fl_Pack::draw() { } if (spacing_ && current_position>maximum_position && box() && (X != o->x() || Y != o->y() || d&FL_DAMAGE_ALL)) { - fl_color(color()); if (horizontal()) - fl_rectf(maximum_position, ty, spacing_, th); + draw_filler_( { maximum_position, ty, spacing_, th } ); else - fl_rectf(tx, maximum_position, tw, spacing_); + draw_filler_( { tx, maximum_position, tw, spacing_ } ); } if (X != o->x() || Y != o->y() || W != o->w() || H != o->h()) { o->resize(X,Y,W,H); @@ -132,14 +147,12 @@ void Fl_Pack::draw() { if (horizontal()) { if (maximum_position < tx+tw && box()) { - fl_color(color()); - fl_rectf(maximum_position, ty, tx+tw-maximum_position, th); + draw_filler_( { maximum_position, ty, tx+tw-maximum_position, th } ); } tw = maximum_position-tx; } else { if (maximum_position < ty+th && box()) { - fl_color(color()); - fl_rectf(tx, maximum_position, tw, ty+th-maximum_position); + draw_filler_( { tx, maximum_position, tw, ty+th-maximum_position } ); } th = maximum_position-ty; } @@ -153,7 +166,13 @@ void Fl_Pack::draw() { d = FL_DAMAGE_ALL; } if (d&FL_DAMAGE_ALL) { - draw_box(); + if (Fl::box_bg(box())) { + // Make sure that we only draw the frame part, because the children + // and fillers are already rendered at this point. + draw_box(fl_frame(box()), x(), y(), w(), h(), color()); + } else { + draw_box(); + } draw_label(); } } diff --git a/test/preferences.fl b/test/preferences.fl index dec03d2b3..23a6c1a38 100644 --- a/test/preferences.fl +++ b/test/preferences.fl @@ -186,9 +186,11 @@ Fl_Input::paste_menu_text = gettext("Paste");} {} MenuItem {} { label sandals callback {[](Fl_Widget*, void*) +/* If this code generates an error, you are using an older version of Fluid */ +/* Support for lambda callbacks was added dec 12 2025 */ { puts("The shoe is the sign!"); -}} selected +}} xywh {0 0 100 20} } MenuItem {} { @@ -223,6 +225,8 @@ Fl_Input::paste_menu_text = gettext("Paste");} {} Fl_Check_Button wShave { label shave callback {[](Fl_Widget* w, void*)->void { +/* If this code generates an error, you are using an older version of Fluid */ +/* Support for lambda callbacks was added dec 12 2025 */ auto* btn = static_cast(w); if (btn->value()) { puts("Shave."); @@ -230,7 +234,7 @@ Fl_Input::paste_menu_text = gettext("Paste");} {} puts("Don't shave."); } }} - comment {// Testing lambdas for callbacks} + comment {// Testing lambdas for callbacks} selected xywh {25 212 105 24} down_box DOWN_BOX } Fl_Check_Button wBrush { -- cgit v1.2.3