summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/intro_gui.cpp18
-rw-r--r--src/town_gui.cpp29
-rw-r--r--src/widget.cpp235
-rw-r--r--src/window_gui.h23
4 files changed, 174 insertions, 131 deletions
diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp
index dcc55b131..9b2c8511b 100644
--- a/src/intro_gui.cpp
+++ b/src/intro_gui.cpp
@@ -83,16 +83,18 @@ struct SelectGameWindow : public Window {
}
}
- virtual Dimension GetWidgetContentSize(int widget)
+ virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize)
{
- Dimension d = {0, 0};
- if (widget == SGI_DIFFICULTIES) {
- for (uint i = STR_DIFFICULTY_LEVEL_EASY; i <= STR_DIFFICULTY_LEVEL_CUSTOM; i++) {
- SetDParam(0, i);
- d = maxdim(d, GetStringBoundingBox(STR_INTRO_DIFFICULTY));
- }
+ if (widget != SGI_DIFFICULTIES) return;
+
+ Dimension textdim = {0, 0};
+ for (uint i = STR_DIFFICULTY_LEVEL_EASY; i <= STR_DIFFICULTY_LEVEL_CUSTOM; i++) {
+ SetDParam(0, i);
+ textdim = maxdim(textdim, GetStringBoundingBox(STR_INTRO_DIFFICULTY));
}
- return d;
+ textdim.width += padding.width;
+ textdim.height += padding.height;
+ *size = maxdim(*size, textdim);
}
virtual void OnClick(Point pt, int widget)
diff --git a/src/town_gui.cpp b/src/town_gui.cpp
index b8dfe4fcf..d017c04a7 100644
--- a/src/town_gui.cpp
+++ b/src/town_gui.cpp
@@ -643,18 +643,19 @@ public:
}
}
- virtual Dimension GetWidgetContentSize(int widget)
+ virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize)
{
- Dimension d = {0, 0};
switch (widget) {
case TDW_SORTNAME:
case TDW_SORTPOPULATION: {
- d = GetStringBoundingBox(this->nested_array[widget]->widget_data);
- d.width += WD_SORTBUTTON_ARROW_WIDTH * 2; // Doubled since the word is centered, also looks nice.
+ Dimension d = GetStringBoundingBox(this->nested_array[widget]->widget_data);
+ d.width += padding.width + WD_SORTBUTTON_ARROW_WIDTH * 2; // Doubled since the word is centered, also looks nice.
+ d.height += padding.height;
+ *size = maxdim(*size, d);
break;
}
-
- case TDW_CENTERTOWN:
+ case TDW_CENTERTOWN: {
+ Dimension d = {0, 0};
for (uint i = 0; i < this->towns.Length(); i++) {
const Town *t = this->towns[i];
@@ -664,15 +665,21 @@ public:
SetDParam(1, 10000000); // 10^7
d = maxdim(d, GetStringBoundingBox(STR_TOWN_DIRECTORY_TOWN));
}
- d.width += 2 + 2; // Text is rendered with 2 pixel offset at both sides.
+ d.width += padding.width + 2 + 2; // Text is rendered with 2 pixel offset at both sides.
+ d.height += padding.height;
+ *size = maxdim(*size, d);
+ resize->height = d.height;
break;
-
- case TDW_EMPTYBOTTOM:
+ }
+ case TDW_EMPTYBOTTOM: {
SetDParam(0, 1000000000); // 10^9
- d = GetStringBoundingBox(STR_TOWN_POPULATION);
+ Dimension d = GetStringBoundingBox(STR_TOWN_POPULATION);
+ d.width += padding.width;
+ d.height += padding.height;
+ *size = maxdim(*size, d);
break;
+ }
}
- return d;
}
virtual void OnClick(Point pt, int widget)
diff --git a/src/widget.cpp b/src/widget.cpp
index 652876b2f..9e5c3b988 100644
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -892,7 +892,7 @@ NWidgetBase::NWidgetBase(WidgetType tp) : ZeroedMemoryAllocator()
*
* The smallest size of a widget is the smallest size that a widget needs to
* display itself properly. In addition, filling and resizing of the widget are computed.
- * If \a w is not \c NULL, the function calls #Window::GetWidgetContentSize for each leaf widget and
+ * If \a w is not \c NULL, the function calls #Window::UpdateWidgetSize for each leaf widget and
* background widget without child with a non-negative index.
*
* @param w Optional window owning the widget.
@@ -1692,12 +1692,18 @@ void NWidgetBackground::SetupSmallestSize(Window *w, bool init_array)
this->resize_y = this->child->resize_y;
} else {
Dimension d = {this->min_x, this->min_y};
+ Dimension resize = {this->resize_x, this->resize_y};
if (w != NULL) { // A non-NULL window pointer acts as switch to turn dynamic widget size on.
- if (this->index >= 0) d = maxdim(d, w->GetWidgetContentSize(this->index));
if (this->type == WWT_FRAME || this->type == WWT_INSET) d = maxdim(d, GetStringBoundingBox(this->widget_data));
+ if (this->index >= 0) {
+ static const Dimension padding = {0, 0};
+ w->UpdateWidgetSize(this->index, &d, padding, &resize);
+ }
}
this->smallest_x = d.width;
this->smallest_y = d.height;
+ this->resize_x = resize.width;
+ this->resize_y = resize.height;
}
}
@@ -1887,109 +1893,138 @@ NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, int index, uint16 data,
void NWidgetLeaf::SetupSmallestSize(Window *w, bool init_array)
{
- Dimension d = {this->min_x, this->min_y}; // At least minimal size is needed.
+ if (w == NULL) { // Conversion to widget array.
+ this->smallest_x = this->min_x;
+ this->smallest_y = this->min_y;
+ /* All other data is already at the right place. */
+ return;
+ }
- if (w != NULL) { // A non-NULL window pointer acts as switch to turn dynamic widget sizing on.
- Dimension d2 = {0, 0};
- if (this->index >= 0) {
- if (init_array) {
- assert(w->nested_array_size > (uint)this->index);
- w->nested_array[this->index] = this;
+ if (this->index >= 0 && init_array) { // Fill w->nested_array[]
+ assert(w->nested_array_size > (uint)this->index);
+ w->nested_array[this->index] = this;
+ }
+
+ /* A non-NULL window pointer acts as switch to turn dynamic widget sizing on. */
+ Dimension size = {this->min_x, this->min_y};
+ Dimension resize = {this->resize_x, this->resize_y};
+ /* Get padding, and update size with the real content size if appropriate. */
+ const Dimension *padding = NULL;
+ switch (this->type) {
+ case WWT_EMPTY:
+ case WWT_MATRIX:
+ case WWT_SCROLLBAR:
+ case WWT_SCROLL2BAR:
+ case WWT_HSCROLLBAR: {
+ static const Dimension extra = {0, 0};
+ padding = &extra;
+ break;
+ }
+ case WWT_STICKYBOX: {
+ static const Dimension extra = {WD_STICKYBOX_LEFT + WD_STICKYBOX_RIGHT, WD_STICKYBOX_TOP + WD_STICKYBOX_BOTTOM};
+ padding = &extra;
+ if (NWidgetLeaf::stickybox_dimension.width == 0) {
+ NWidgetLeaf::stickybox_dimension = maxdim(GetSpriteSize(SPR_PIN_UP), GetSpriteSize(SPR_PIN_DOWN));
+ NWidgetLeaf::stickybox_dimension.width += extra.width;
+ NWidgetLeaf::stickybox_dimension.height += extra.height;
}
- d2 = maxdim(d2, w->GetWidgetContentSize(this->index)); // If appropriate, ask window for smallest size.
+ size = maxdim(size, NWidgetLeaf::stickybox_dimension);
+ break;
}
-
- /* Check size requirements of the widget itself too.
- * Also, add the offset used for rendering.
- */
- switch (this->type) {
- case WWT_EMPTY:
- case WWT_MATRIX:
- case WWT_SCROLLBAR:
- case WWT_SCROLL2BAR:
- case WWT_HSCROLLBAR:
- break;
-
- case WWT_STICKYBOX:
- if (NWidgetLeaf::stickybox_dimension.width == 0) {
- NWidgetLeaf::stickybox_dimension = maxdim(GetSpriteSize(SPR_PIN_UP), GetSpriteSize(SPR_PIN_DOWN));
- NWidgetLeaf::stickybox_dimension.width += WD_STICKYBOX_LEFT + WD_STICKYBOX_RIGHT;
- NWidgetLeaf::stickybox_dimension.height += WD_STICKYBOX_TOP + WD_STICKYBOX_BOTTOM;
- }
- d2 = maxdim(d2, NWidgetLeaf::stickybox_dimension);
- break;
-
- case WWT_RESIZEBOX:
- if (NWidgetLeaf::resizebox_dimension.width == 0) {
- NWidgetLeaf::resizebox_dimension = maxdim(GetSpriteSize(SPR_WINDOW_RESIZE_LEFT), GetSpriteSize(SPR_WINDOW_RESIZE_RIGHT));
- NWidgetLeaf::resizebox_dimension.width += WD_RESIZEBOX_LEFT + WD_RESIZEBOX_RIGHT;
- NWidgetLeaf::resizebox_dimension.height += WD_RESIZEBOX_TOP + WD_RESIZEBOX_BOTTOM;
- }
- d2 = maxdim(d2, NWidgetLeaf::resizebox_dimension);
- break;
-
- case WWT_PUSHBTN:
- case WWT_EDITBOX:
- d2.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
- d2.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
- break;
-
- case WWT_IMGBTN:
- case WWT_PUSHIMGBTN:
- d2 = maxdim(d2, GetSpriteSize(this->widget_data));
- d2.height += WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM;
- d2.width += WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT;
- break;
-
- case WWT_IMGBTN_2:
- d2 = maxdim(d2, GetSpriteSize(this->widget_data));
- d2 = maxdim(d2, GetSpriteSize(this->widget_data + 1));
- d2.height += WD_IMGBTN2_TOP + WD_IMGBTN2_BOTTOM;
- d2.width += WD_IMGBTN2_LEFT + WD_IMGBTN2_RIGHT;
- break;
-
- case WWT_CLOSEBOX:
- if (NWidgetLeaf::closebox_dimension.width == 0) {
- NWidgetLeaf::closebox_dimension = maxdim(GetStringBoundingBox(STR_BLACK_CROSS), GetStringBoundingBox(STR_SILVER_CROSS));
- NWidgetLeaf::closebox_dimension.width += WD_CLOSEBOX_LEFT + WD_CLOSEBOX_RIGHT;
- NWidgetLeaf::closebox_dimension.height += WD_CLOSEBOX_TOP + WD_CLOSEBOX_BOTTOM;
- }
- d2 = maxdim(d2, NWidgetLeaf::closebox_dimension);
- break;
-
- case WWT_TEXTBTN:
- case WWT_PUSHTXTBTN:
- case WWT_TEXTBTN_2:
- d2 = maxdim(d2, GetStringBoundingBox(this->widget_data));
- d2.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
- d2.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
- break;
-
- case WWT_LABEL:
- case WWT_TEXT:
- d2 = maxdim(d2, GetStringBoundingBox(this->widget_data));
- break;
-
- case WWT_CAPTION:
- d2 = maxdim(d2, GetStringBoundingBox(this->widget_data));
- d2.width += WD_CAPTIONTEXT_LEFT + WD_CAPTIONTEXT_RIGHT;
- d2.height += WD_CAPTIONTEXT_TOP + WD_CAPTIONTEXT_BOTTOM;
- break;
-
- case WWT_DROPDOWN:
- d2 = maxdim(d2, GetStringBoundingBox(this->widget_data));
- d2.width += WD_DROPDOWNTEXT_LEFT + WD_DROPDOWNTEXT_RIGHT;
- d2.height += WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM;
- break;
-
- default:
- NOT_REACHED();
+ case WWT_RESIZEBOX: {
+ static const Dimension extra = {WD_RESIZEBOX_LEFT + WD_RESIZEBOX_RIGHT, WD_RESIZEBOX_TOP + WD_RESIZEBOX_BOTTOM};
+ padding = &extra;
+ if (NWidgetLeaf::resizebox_dimension.width == 0) {
+ NWidgetLeaf::resizebox_dimension = maxdim(GetSpriteSize(SPR_WINDOW_RESIZE_LEFT), GetSpriteSize(SPR_WINDOW_RESIZE_RIGHT));
+ NWidgetLeaf::resizebox_dimension.width += extra.width;
+ NWidgetLeaf::resizebox_dimension.height += extra.height;
+ }
+ size = maxdim(size, NWidgetLeaf::resizebox_dimension);
+ break;
}
- d = maxdim(d, d2);
+ case WWT_PUSHBTN:
+ case WWT_EDITBOX: {
+ static const Dimension extra = {WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM};
+ padding = &extra;
+ break;
+ }
+ case WWT_IMGBTN:
+ case WWT_PUSHIMGBTN: {
+ static const Dimension extra = {WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT, WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM};
+ padding = &extra;
+ Dimension d2 = GetSpriteSize(this->widget_data);
+ d2.width += extra.width;
+ d2.height += extra.height;
+ size = maxdim(size, d2);
+ break;
+ }
+ case WWT_IMGBTN_2: {
+ static const Dimension extra = {WD_IMGBTN2_LEFT + WD_IMGBTN2_RIGHT, WD_IMGBTN2_TOP + WD_IMGBTN2_BOTTOM};
+ padding = &extra;
+ Dimension d2 = maxdim(GetSpriteSize(this->widget_data), GetSpriteSize(this->widget_data + 1));
+ d2.width += extra.width;
+ d2.height += extra.height;
+ size = maxdim(size, d2);
+ break;
+ }
+ case WWT_CLOSEBOX: {
+ static const Dimension extra = {WD_CLOSEBOX_LEFT + WD_CLOSEBOX_RIGHT, WD_CLOSEBOX_TOP + WD_CLOSEBOX_BOTTOM};
+ padding = &extra;
+ if (NWidgetLeaf::closebox_dimension.width == 0) {
+ NWidgetLeaf::closebox_dimension = maxdim(GetStringBoundingBox(STR_BLACK_CROSS), GetStringBoundingBox(STR_SILVER_CROSS));
+ NWidgetLeaf::closebox_dimension.width += extra.width;
+ NWidgetLeaf::closebox_dimension.height += extra.height;
+ }
+ size = maxdim(size, NWidgetLeaf::closebox_dimension);
+ break;
+ }
+ case WWT_TEXTBTN:
+ case WWT_PUSHTXTBTN:
+ case WWT_TEXTBTN_2: {
+ static const Dimension extra = {WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM};
+ padding = &extra;
+ Dimension d2 = GetStringBoundingBox(this->widget_data);
+ d2.width += extra.width;
+ d2.height += extra.height;
+ size = maxdim(size, d2);
+ break;
+ }
+ case WWT_LABEL:
+ case WWT_TEXT: {
+ static const Dimension extra = {0, 0};
+ padding = &extra;
+ size = maxdim(size, GetStringBoundingBox(this->widget_data));
+ break;
+ }
+ case WWT_CAPTION: {
+ static const Dimension extra = {WD_CAPTIONTEXT_LEFT + WD_CAPTIONTEXT_RIGHT, WD_CAPTIONTEXT_TOP + WD_CAPTIONTEXT_BOTTOM};
+ padding = &extra;
+ Dimension d2 = GetStringBoundingBox(this->widget_data);
+ d2.width += extra.width;
+ d2.height += extra.height;
+ size = maxdim(size, d2);
+ break;
+ }
+ case WWT_DROPDOWN: {
+ static const Dimension extra = {WD_DROPDOWNTEXT_LEFT + WD_DROPDOWNTEXT_RIGHT, WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM};
+ padding = &extra;
+ Dimension d2 = GetStringBoundingBox(this->widget_data);
+ d2.width += extra.width;
+ d2.height += extra.height;
+ size = maxdim(size, d2);
+ break;
+ }
+ default:
+ NOT_REACHED();
}
- this->smallest_x = d.width;
- this->smallest_y = d.height;
- /* All other data is already at the right place. */
+
+ if (this->index >= 0) w->UpdateWidgetSize(this->index, &size, *padding, &resize);
+
+ this->smallest_x = size.width;
+ this->smallest_y = size.height;
+ this->resize_x = resize.width;
+ this->resize_y = resize.height;
+ /* this->fill_x and this->fill_y are already correct. */
}
void NWidgetLeaf::Draw(const Window *w)
diff --git a/src/window_gui.h b/src/window_gui.h
index eee49674b..846a5a2db 100644
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -521,18 +521,17 @@ public:
virtual void DrawWidget(const Rect &r, int widget) const {}
/**
- * Compute size of the contents of a widget.
- * If no useful size can be computed, return null-size (both width and height \c 0).
- * @param widget Number of the widget to get the size of.
- * @return Size of the contents of the widget.
- * @note If the contents ever becomes larger than what is returned here, the window should be re-initialized (with #Window::ReInit),
- * and this function should return a larger size.
- */
- virtual Dimension GetWidgetContentSize(int widget)
- {
- Dimension d = {0, 0};
- return d;
- }
+ * Update size and resize step of a widget in the window.
+ * After retrieval of the minimal size and the resize-steps of a widget, this function is called to allow further refinement,
+ * typically by computing the real maximal size of the content. Afterwards, \a size is taken to be the minimal size of the widget
+ * and \a resize is taken to contain the resize steps. For the convenience of the callee, \a padding contains the amount of
+ * padding between the content and the edge of the widget. This should be added to the returned size.
+ * @param widget Widget number.
+ * @param size Size of the widget.
+ * @param padding Recommended amount of space between the widget content and the widget edge.
+ * @param resize Resize step of the widget.
+ */
+ virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize) {}
/**
* Called when window gains focus