changeset 11511:bf92950ea00b draft

(svn r15872) -Codechange: add paddings for widgets, this makes writing new widget arrays less cumbersome.
author yexo <yexo@openttd.org>
date Sat, 28 Mar 2009 11:13:39 +0000
parents d35693964818
children 315cce32da87
files src/widget.cpp src/widget_type.h
diffstat 2 files changed, 142 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -876,12 +876,19 @@
 	this->resize_x = 0;   // smallest non-zero child widget resize step.
 	this->resize_y = 1;   // smallest common child resize step
 
+	if (this->head != NULL) this->head->padding_left += this->pip_pre;
 	for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
 		int idx = child_wid->ComputeMinimalSize();
 		biggest_index = max(biggest_index, idx);
 
-		this->min_x += child_wid->min_x;
-		this->min_y = max(this->min_y, child_wid->min_y);
+		if (child_wid->next != NULL) {
+			child_wid->padding_right += this->pip_inter;
+		} else {
+			child_wid->padding_right += this->pip_post;
+		}
+
+		this->min_x += child_wid->min_x + child_wid->padding_left + child_wid->padding_right;
+		this->min_y = max(this->min_y, child_wid->min_y + child_wid->padding_top + child_wid->padding_bottom);
 		this->fill_x |= child_wid->fill_x;
 		this->fill_y &= child_wid->fill_y;
 
@@ -890,6 +897,8 @@
 		}
 		this->resize_y = LeastCommonMultiple(this->resize_y, child_wid->resize_y);
 	}
+	/* We need to zero the PIP settings so we can re-initialize the tree. */
+	this->pip_pre = this->pip_inter = this->pip_post = 0;
 
 	return biggest_index;
 }
@@ -918,15 +927,16 @@
 	allow_resize_x = (this->resize_x > 0);
 	child_wid = rtl ? this->tail : this->head;
 	while (child_wid != NULL) {
+		assert(given_height >= child_wid->min_y + child_wid->padding_top + child_wid->padding_bottom);
 		/* Decide about vertical filling of the child. */
 		uint child_height; // Height of the child widget.
 		uint child_pos_y; // Vertical position of child relative to the top of the container.
 		if (child_wid->fill_y) {
-			child_height = given_height;
-			child_pos_y = 0;
+			child_height = given_height - child_wid->padding_top - child_wid->padding_bottom;
+			child_pos_y = child_wid->padding_top;
 		} else {
 			child_height = child_wid->min_y;
-			child_pos_y = (given_height - child_height) / 2;
+			child_pos_y = (given_height - child_wid->padding_top - child_wid->padding_bottom - child_height) / 2 + child_wid->padding_top;
 		}
 
 		/* Decide about horizontal filling of the child. */
@@ -941,8 +951,8 @@
 			child_width += increment;
 		}
 
-		child_wid->AssignMinimalPosition(x + position, y + child_pos_y, child_width, child_height, allow_resize_x, (this->resize_y > 0), rtl);
-		position += child_width;
+		child_wid->AssignMinimalPosition(x + position + (rtl ? child_wid->padding_right : child_wid->padding_left), y + child_pos_y, child_width, child_height, allow_resize_x, (this->resize_y > 0), rtl);
+		position += child_width + child_wid->padding_right + child_wid->padding_left;
 		if (child_wid->resize_x > 0) allow_resize_x = false; // Widget array allows only one child resizing
 
 		child_wid = rtl ? child_wid->prev : child_wid->next;
@@ -989,12 +999,19 @@
 	this->resize_x = 1;   // smallest common child resize step
 	this->resize_y = 0;   // smallest non-zero child widget resize step.
 
+	if (this->head != NULL) this->head->padding_top += this->pip_pre;
 	for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
 		int idx = child_wid->ComputeMinimalSize();
 		biggest_index = max(biggest_index, idx);
 
-		this->min_y += child_wid->min_y;
-		this->min_x = max(this->min_x, child_wid->min_x);
+		if (child_wid->next != NULL) {
+			child_wid->padding_bottom += this->pip_inter;
+		} else {
+			child_wid->padding_bottom += this->pip_post;
+		}
+
+		this->min_y += child_wid->min_y + child_wid->padding_top + child_wid->padding_bottom;
+		this->min_x = max(this->min_x, child_wid->min_x + child_wid->padding_left + child_wid->padding_right);
 		this->fill_y |= child_wid->fill_y;
 		this->fill_x &= child_wid->fill_x;
 
@@ -1003,6 +1020,8 @@
 		}
 		this->resize_x = LeastCommonMultiple(this->resize_x, child_wid->resize_x);
 	}
+	/* We need to zero the PIP settings so we can re-initialize the tree. */
+	this->pip_pre = this->pip_inter = this->pip_post = 0;
 
 	return biggest_index;
 }
@@ -1029,15 +1048,16 @@
 	uint position = 0; // Place to put next child relative to origin of the container.
 	allow_resize_y = (this->resize_y > 0);
 	for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
+		assert(given_width >= child_wid->min_x + child_wid->padding_left + child_wid->padding_right);
 		/* Decide about horizontal filling of the child. */
 		uint child_width; // Width of the child widget.
 		uint child_pos_x; // Horizontal position of child relative to the left of the container.
 		if (child_wid->fill_x) {
-			child_width = given_width;
-			child_pos_x = 0;
+			child_width = given_width - child_wid->padding_left - child_wid->padding_right;
+			child_pos_x = (rtl ? child_wid->padding_right : child_wid->padding_left);
 		} else {
 			child_width = child_wid->min_x;
-			child_pos_x = (given_width - child_width) / 2;
+			child_pos_x = (given_width - child_wid->padding_left - child_wid->padding_right - child_width) / 2 + (rtl ? child_wid->padding_right : child_wid->padding_left);
 		}
 
 		/* Decide about vertical filling of the child. */
@@ -1052,8 +1072,8 @@
 			child_height += increment;
 		}
 
-		child_wid->AssignMinimalPosition(x + child_pos_x, y + position, child_width, child_height, (this->resize_x > 0), allow_resize_y, rtl);
-		position += child_height;
+		child_wid->AssignMinimalPosition(x + child_pos_x, y + position + child_wid->padding_top, child_width, child_height, (this->resize_x > 0), allow_resize_y, rtl);
+		position += child_height + child_wid->padding_top + child_wid->padding_bottom;
 		if (child_wid->resize_y > 0) allow_resize_y = false; // Widget array allows only one child resizing
 	}
 }
@@ -1153,7 +1173,12 @@
 	if (!allow_resize_x) this->resize_x = 0;
 	if (!allow_resize_y) this->resize_y = 0;
 
-	if (this->child != NULL) this->child->AssignMinimalPosition(x, y, given_width, given_height, (this->resize_x > 0), (this->resize_y > 0), rtl);
+	if (this->child != NULL) {
+		uint x_offset = (rtl ? this->child->padding_right : this->child->padding_left);
+		uint width = given_width - this->child->padding_right - this->child->padding_left;
+		uint height = given_height - this->child->padding_top - this->child->padding_bottom;
+		this->child->AssignMinimalPosition(x + x_offset, y + this->child->padding_top, width, height, (this->resize_x > 0), (this->resize_y > 0), rtl);
+	}
 }
 
 void NWidgetBackground::StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl)
@@ -1438,6 +1463,27 @@
 				break;
 			}
 
+			case WPT_PADDING: {
+				NWidgetBase *nwb = *dest;
+				if (nwb != NULL) {
+					nwb->padding_top = parts->u.padding.top;
+					nwb->padding_right = parts->u.padding.right;
+					nwb->padding_bottom = parts->u.padding.bottom;
+					nwb->padding_left = parts->u.padding.left;
+				}
+				break;
+			}
+
+			case WPT_PIPSPACE: {
+				NWidgetContainer *nwc = dynamic_cast<NWidgetContainer *>(*dest);
+				if (nwc != NULL) {
+					nwc->pip_pre = parts->u.pip.pre;
+					nwc->pip_inter = parts->u.pip.inter;
+					nwc->pip_post = parts->u.pip.post;
+				}
+				break;
+			}
+
 			case WPT_ENDCONTAINER:
 				return num_used;
 
--- a/src/widget_type.h
+++ b/src/widget_type.h
@@ -109,6 +109,8 @@
 	WPT_FILL,         ///< Widget part for specifying fill.
 	WPT_DATATIP,      ///< Widget part for specifying data and tooltip.
 	WPT_DATATIP_PTR,  ///< Widget part for specifying data and tooltip via a pointer.
+	WPT_PADDING,      ///< Widget part for specifying a padding.
+	WPT_PIPSPACE,     ///< Widget part for specifying pre/inter/post space for containers.
 	WPT_ENDCONTAINER, ///< Widget part to denote end of a container.
 
 	/* Pushable window widget types. */
@@ -151,19 +153,24 @@
 
 	virtual void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl) = 0;
 
-	WidgetType type;   ///< Type of the widget / nested widget.
-	uint min_x;        ///< Minimal horizontal size.
-	uint min_y;        ///< Minimal vertical size.
-	bool fill_x;       ///< Allow horizontal filling from initial size.
-	bool fill_y;       ///< Allow vertical filling from initial size.
-	uint resize_x;     ///< Horizontal resize step (\c 0 means not resizable).
-	uint resize_y;     ///< Vertical resize step (\c 0 means not resizable).
+	WidgetType type;      ///< Type of the widget / nested widget.
+	uint min_x;           ///< Minimal horizontal size.
+	uint min_y;           ///< Minimal vertical size.
+	bool fill_x;          ///< Allow horizontal filling from initial size.
+	bool fill_y;          ///< Allow vertical filling from initial size.
+	uint resize_x;        ///< Horizontal resize step (\c 0 means not resizable).
+	uint resize_y;        ///< Vertical resize step (\c 0 means not resizable).
 
-	uint pos_x;        ///< Horizontal position of top-left corner of the widget in the window.
-	uint pos_y;        ///< Vertical position of top-left corner of the widget in the window.
+	uint pos_x;           ///< Horizontal position of top-left corner of the widget in the window.
+	uint pos_y;           ///< Vertical position of top-left corner of the widget in the window.
 
-	NWidgetBase *next; ///< Pointer to next widget in container. Managed by parent container widget.
-	NWidgetBase *prev; ///< Pointer to previous widget in container. Managed by parent container widget.
+	NWidgetBase *next;    ///< Pointer to next widget in container. Managed by parent container widget.
+	NWidgetBase *prev;    ///< Pointer to previous widget in container. Managed by parent container widget.
+
+	uint8 padding_top;    ///< Paddings added to the top of the widget. Managed by parent container widget.
+	uint8 padding_right;  ///< Paddings added to the right of the widget. Managed by parent container widget.
+	uint8 padding_bottom; ///< Paddings added to the bottom of the widget. Managed by parent container widget.
+	uint8 padding_left;   ///< Paddings added to the left of the widget. Managed by parent container widget.
 };
 
 /** Base class for a resizable nested widget. */
@@ -202,6 +209,10 @@
 	~NWidgetContainer();
 
 	void Add(NWidgetBase *wid);
+
+	uint8 pip_pre;     ///< Amount of space before first widget.
+	uint8 pip_inter;   ///< Amount of space between widgets.
+	uint8 pip_post;    ///< Amount of space after last widget.
 protected:
 	NWidgetBase *head; ///< Pointer to first widget in container.
 	NWidgetBase *tail; ///< Pointer to last widget in container.
@@ -288,6 +299,16 @@
 	int16 index;    ///< Widget index in the widget array.
 };
 
+/** Widget part for storing padding. */
+struct NWidgetPartPaddings {
+	uint8 top, right, bottom, left; ///< Paddings for all directions.
+};
+
+/** Widget part for storing pre/inter/post spaces. */
+struct NWidgetPartPIP {
+	uint8 pre, inter, post; ///< Amount of space before/between/after child widgets.
+};
+
 /** Partial widget specification to allow NWidgets to be written nested. */
 struct NWidgetPart {
 	WidgetType type;                         ///< Type of the part. @see NWidgetPartType.
@@ -297,6 +318,8 @@
 		NWidgetPartDataTip data_tip;     ///< Part with a data/tooltip.
 		NWidgetPartDataTip *datatip_ptr; ///< Part with a pointer to data/tooltip.
 		NWidgetPartWidget widget;        ///< Part with a start of a widget.
+		NWidgetPartPaddings padding;     ///< Part with paddings.
+		NWidgetPartPIP pip;              ///< Part with pre/inter/post spaces.
 	} u;
 };
 
@@ -419,6 +442,53 @@
 }
 
 /**
+ * Widget part function for setting a padding.
+ * @param top The padding above the widget.
+ * @param right The padding right of the widget.
+ * @param bottom The padding below the widget.
+ * @param left The padding left of the widget.
+ */
+static inline NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
+{
+	NWidgetPart part;
+
+	part.type = WPT_PADDING;
+	part.u.padding.top = top;
+	part.u.padding.right = right;
+	part.u.padding.bottom = bottom;
+	part.u.padding.left = left;
+
+	return part;
+}
+
+/**
+ * Widget part function for setting a padding.
+ * @param padding The padding to use for all directions.
+ */
+static inline NWidgetPart SetPadding(uint8 padding)
+{
+	return SetPadding(padding, padding, padding, padding);
+}
+
+/**
+ * Widget part function for setting a pre/inter/post spaces.
+ * @param pre The amount of space before the first widget.
+ * @param inter The amount of space between widgets.
+ * @param post The amount of space after the last widget.
+ */
+static inline NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
+{
+	NWidgetPart part;
+
+	part.type = WPT_PIPSPACE;
+	part.u.pip.pre = pre;
+	part.u.pip.inter = inter;
+	part.u.pip.post = post;
+
+	return part;
+}
+
+/**
  * Widget part function for starting a new 'real' widget.
  * @param tp  Type of the new nested widget.
  * @param col Colour of the new widget.