summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2025-12-29 16:21:17 +0100
committerMatthias Melcher <github@matthiasm.com>2025-12-29 16:21:17 +0100
commit83fab8cb0ffd6ee7a38ec6e4dd768b1b3f9eb896 (patch)
treefc2d32f010157e63d7534ef7e10bf1115df2ac63
parent2fb67053a14ff4d1e7d40a18b0e165e214adfb16 (diff)
Fix Fl_Pack to support more box types.
Old code supported only frame styles, this code can now handle box types with a background.
-rw-r--r--FL/Fl_Pack.H8
-rw-r--r--src/Fl_Pack.cxx35
-rw-r--r--test/preferences.fl8
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 <FL/Fl_Group.H>
+#include <FL/Fl_Rect.H>
/**
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
<i>"surprising"</i>. 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<Fl_Check_Button*>(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 {