summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/widget.cpp50
1 files changed, 46 insertions, 4 deletions
diff --git a/src/widget.cpp b/src/widget.cpp
index 9f1dce98e..320a34e80 100644
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -1106,11 +1106,33 @@ void NWidgetHorizontal::SetupSmallestSize(Window *w, bool init_array)
this->resize_x = 0; // smallest non-zero child widget resize step.
this->resize_y = 1; // smallest common child resize step.
- /* 1. Forward call, collect biggest nested array index, and longest child length. */
+ /* 1a. Forward call, collect biggest nested array index, and longest/widest child length. */
uint longest = 0; // Longest child found.
+ uint max_vert_fill = 0; // Biggest vertical fill step.
for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
child_wid->SetupSmallestSize(w, init_array);
longest = max(longest, child_wid->smallest_x);
+ max_vert_fill = max(max_vert_fill, child_wid->GetVerticalStepSize(ST_SMALLEST));
+ this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
+ }
+ /* 1b. Make the container higher if needed to accomadate all childs nicely. */
+ uint max_smallest = this->smallest_y + 3 * max_vert_fill; // Upper limit to computing smallest height.
+ uint cur_height = this->smallest_y;
+ while (true) {
+ for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
+ uint step_size = child_wid->GetVerticalStepSize(ST_SMALLEST);
+ uint child_height = child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom;
+ if (step_size > 1 && child_height < cur_height) { // Small step sizes or already fitting childs are not interesting.
+ uint remainder = (cur_height - child_height) % step_size;
+ if (remainder > 0) { // Child did not fit entirely, widen the container.
+ cur_height += step_size - remainder;
+ assert(cur_height < max_smallest); // Safeguard against infinite height expansion.
+ /* Remaining childs will adapt to the new cur_height, thus speeding up the computation. */
+ }
+ }
+ }
+ if (this->smallest_y == cur_height) break;
+ this->smallest_y = cur_height; // Smallest height got changed, try again.
}
/* 2. For containers that must maintain equal width, extend child minimal size. */
if (this->flags & NC_EQUALSIZE) {
@@ -1128,7 +1150,6 @@ void NWidgetHorizontal::SetupSmallestSize(Window *w, bool init_array)
}
this->smallest_x += child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right;
- this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
if (child_wid->fill_x > 0) {
if (this->fill_x == 0 || this->fill_x > child_wid->fill_x) this->fill_x = child_wid->fill_x;
}
@@ -1237,11 +1258,33 @@ void NWidgetVertical::SetupSmallestSize(Window *w, bool init_array)
this->resize_x = 1; // smallest common child resize step.
this->resize_y = 0; // smallest non-zero child widget resize step.
- /* 1. Forward call, collect biggest nested array index, and longest child length. */
+ /* 1a. Forward call, collect biggest nested array index, and longest/widest child length. */
uint highest = 0; // Highest child found.
+ uint max_hor_fill = 0; // Biggest horizontal fill step.
for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
child_wid->SetupSmallestSize(w, init_array);
highest = max(highest, child_wid->smallest_y);
+ max_hor_fill = max(max_hor_fill, child_wid->GetHorizontalStepSize(ST_SMALLEST));
+ this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
+ }
+ /* 1b. Make the container wider if needed to accomadate all childs nicely. */
+ uint max_smallest = this->smallest_x + 3 * max_hor_fill; // Upper limit to computing smallest height.
+ uint cur_width = this->smallest_x;
+ while (true) {
+ for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
+ uint step_size = child_wid->GetHorizontalStepSize(ST_SMALLEST);
+ uint child_width = child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right;
+ if (step_size > 1 && child_width < cur_width) { // Small step sizes or already fitting childs are not interesting.
+ uint remainder = (cur_width - child_width) % step_size;
+ if (remainder > 0) { // Child did not fit entirely, widen the container.
+ cur_width += step_size - remainder;
+ assert(cur_width < max_smallest); // Safeguard against infinite width expansion.
+ /* Remaining childs will adapt to the new cur_width, thus speeding up the computation. */
+ }
+ }
+ }
+ if (this->smallest_x == cur_width) break;
+ this->smallest_x = cur_width; // Smallest width got changed, try again.
}
/* 2. For containers that must maintain equal width, extend child minimal size. */
if (this->flags & NC_EQUALSIZE) {
@@ -1259,7 +1302,6 @@ void NWidgetVertical::SetupSmallestSize(Window *w, bool init_array)
}
this->smallest_y += child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom;
- this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
if (child_wid->fill_y > 0) {
if (this->fill_y == 0 || this->fill_y > child_wid->fill_y) this->fill_y = child_wid->fill_y;
}