changeset 13707:472de6714e9a draft

(svn r18232) -Fix: Extend container widgets to accomadate multiples of filling step size.
author alberth <alberth@openttd.org>
date Sun, 22 Nov 2009 18:31:17 +0000
parents a15d8546fedf
children e55432e0dc86
files src/widget.cpp
diffstat 1 files changed, 46 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -1106,11 +1106,33 @@
 	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 @@
 		}
 
 		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 @@
 	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 @@
 		}
 
 		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;
 		}