diff options
-rw-r--r-- | src/intro_gui.cpp | 18 | ||||
-rw-r--r-- | src/town_gui.cpp | 29 | ||||
-rw-r--r-- | src/widget.cpp | 235 | ||||
-rw-r--r-- | src/window_gui.h | 23 |
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 |