diff --git a/src/gfx.cpp b/src/gfx.cpp --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1285,7 +1285,7 @@ void LoadStringWidthTable(bool monospace } } - ReInitAllWindows(); + ReInitAllWindows(false); } /** diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -323,7 +323,7 @@ void CheckBlitter() ClearFontCache(); GfxClearSpriteCache(); - ReInitAllWindows(); + ReInitAllWindows(false); } /** Initialise and load all the sprites. */ diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -98,7 +98,9 @@ public: this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_YEARS, STR_NETWORK_SERVER_LIST_YEARS_CAPTION, STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP)); leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_INFO, STR_EMPTY, STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP); - leaf->SetMinimalSize(14 + GetSpriteSize(SPR_LOCK).width + GetSpriteSize(SPR_BLOT).width + GetSpriteSize(SPR_FLAGS_BASE).width, 12); + leaf->SetMinimalSize(14 + GetSpriteSize(SPR_LOCK, nullptr, ZOOM_LVL_OUT_4X).width + + GetSpriteSize(SPR_BLOT, nullptr, ZOOM_LVL_OUT_4X).width + + GetSpriteSize(SPR_FLAGS_BASE, nullptr, ZOOM_LVL_OUT_4X).width, 12); leaf->SetFill(0, 1); this->Add(leaf); diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1972,7 +1972,7 @@ static void NewGRFConfirmationCallback(W w->InvalidateData(); - ReInitAllWindows(); + ReInitAllWindows(false); DeleteWindowByClass(WC_BUILD_OBJECT); } } diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -237,7 +237,7 @@ static void AddKey(NWidgetHorizontal *ho hor->Add(spc); } NWidgetLeaf *leaf = new NWidgetLeaf(widtype, COLOUR_GREY, widnum, widdata, STR_NULL); - leaf->SetMinimalSize(ScaleGUITrad(key_width), height); + leaf->SetMinimalSizeAbsolute(ScaleGUITrad(key_width), height); hor->Add(leaf); } diff --git a/src/settings.cpp b/src/settings.cpp --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1172,7 +1172,7 @@ static bool InvalidateNewGRFChangeWindow { InvalidateWindowClassesData(WC_SAVELOAD); DeleteWindowByClass(WC_GAME_OPTIONS); - ReInitAllWindows(); + ReInitAllWindows(_gui_zoom_cfg); return true; } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -530,7 +530,7 @@ struct GameOptionsWindow : Window { case WID_GO_CURRENCY_DROPDOWN: // Currency if (index == CURRENCY_CUSTOM) ShowCustCurrency(); this->opt->locale.currency = index; - ReInitAllWindows(); + ReInitAllWindows(false); break; case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options @@ -545,7 +545,7 @@ struct GameOptionsWindow : Window { ClearAllCachedNames(); UpdateAllVirtCoords(); CheckBlitter(); - ReInitAllWindows(); + ReInitAllWindows(false); break; case WID_GO_RESOLUTION_DROPDOWN: // Change resolution @@ -573,7 +573,7 @@ struct GameOptionsWindow : Window { UpdateCursorSize(); UpdateAllVirtCoords(); FixTitleGameZoom(); - ReInitAllWindows(); + ReInitAllWindows(true); } break; } @@ -587,6 +587,7 @@ struct GameOptionsWindow : Window { ClearFontCache(); LoadStringWidthTable(); UpdateAllVirtCoords(); + ReInitAllWindows(true); } break; } diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp --- a/src/video/video_driver.cpp +++ b/src/video/video_driver.cpp @@ -115,7 +115,7 @@ void VideoDriver::RealChangeBlitter(cons this->ClearSystemSprites(); ClearFontCache(); GfxClearSpriteCache(); - ReInitAllWindows(); + ReInitAllWindows(false); } void VideoDriver::Tick() diff --git a/src/widget.cpp b/src/widget.cpp --- a/src/widget.cpp +++ b/src/widget.cpp @@ -822,6 +822,14 @@ NWidgetBase *NWidgetBase::GetWidgetOfTyp return (this->type == tp) ? this : nullptr; } +void NWidgetBase::AdjustPaddingForZoom() +{ + this->padding_top = ScaleGUITrad(this->uz_padding_top); + this->padding_right = ScaleGUITrad(this->uz_padding_right); + this->padding_bottom = ScaleGUITrad(this->uz_padding_bottom); + this->padding_left = ScaleGUITrad(this->uz_padding_left); +} + /** * Constructor for resizable nested widgets. * @param tp Nested widget type. @@ -834,6 +842,15 @@ NWidgetResizeBase::NWidgetResizeBase(Wid this->fill_y = fill_y; } +void NWidgetResizeBase::AdjustPaddingForZoom() +{ + if (!this->absolute) { + this->min_x = ScaleGUITrad(this->uz_min_x); + this->min_y = std::max(ScaleGUITrad(this->uz_min_y), this->uz_text_lines * GetCharacterHeight(this->uz_text_size) + ScaleGUITrad(this->uz_text_spacing)); + } + NWidgetBase::AdjustPaddingForZoom(); +} + /** * Set minimal size of the widget. * @param min_x Horizontal minimal size of the widget. @@ -841,6 +858,20 @@ NWidgetResizeBase::NWidgetResizeBase(Wid */ void NWidgetResizeBase::SetMinimalSize(uint min_x, uint min_y) { + this->uz_min_x = std::max(this->uz_min_x, min_x); + this->uz_min_y = std::max(this->uz_min_y, min_y); + this->min_x = ScaleGUITrad(this->uz_min_x); + this->min_y = std::max(ScaleGUITrad(this->uz_min_y), this->uz_text_lines * GetCharacterHeight(this->uz_text_size) + ScaleGUITrad(this->uz_text_spacing)); +} + +/** + * Set absolute (post-scaling) minimal size of the widget. + * @param min_x Horizontal minimal size of the widget. + * @param min_y Vertical minimal size of the widget. + */ +void NWidgetResizeBase::SetMinimalSizeAbsolute(uint min_x, uint min_y) +{ + this->absolute = true; this->min_x = std::max(this->min_x, min_x); this->min_y = std::max(this->min_y, min_y); } @@ -853,7 +884,10 @@ void NWidgetResizeBase::SetMinimalSize(u */ void NWidgetResizeBase::SetMinimalTextLines(uint8 min_lines, uint8 spacing, FontSize size) { - this->min_y = min_lines * GetCharacterHeight(size) + spacing; + this->uz_text_lines = min_lines; + this->uz_text_spacing = spacing; + this->uz_text_size = size; + this->min_y = std::max(ScaleGUITrad(this->uz_min_y), this->uz_text_lines * GetCharacterHeight(this->uz_text_size) + ScaleGUITrad(this->uz_text_spacing)); } /** @@ -991,6 +1025,14 @@ NWidgetBase *NWidgetContainer::GetWidget return nullptr; } +void NWidgetContainer::AdjustPaddingForZoom() +{ + for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) { + child_wid->AdjustPaddingForZoom(); + } + NWidgetBase::AdjustPaddingForZoom(); +} + /** * Append widget \a wid to container. * @param wid Widget to append. @@ -1032,6 +1074,14 @@ void NWidgetStacked::SetIndex(int index) this->index = index; } +void NWidgetStacked::AdjustPaddingForZoom() +{ + for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) { + child_wid->AdjustPaddingForZoom(); + } + NWidgetContainer::AdjustPaddingForZoom(); +} + void NWidgetStacked::SetupSmallestSize(Window *w, bool init_array) { if (this->index >= 0 && init_array) { // Fill w->nested_array[] @@ -1145,6 +1195,14 @@ NWidgetPIPContainer::NWidgetPIPContainer this->flags = flags; } +void NWidgetPIPContainer::AdjustPaddingForZoom() +{ + this->pip_pre = ScaleGUITrad(this->uz_pip_pre); + this->pip_inter = ScaleGUITrad(this->uz_pip_inter); + this->pip_post = ScaleGUITrad(this->uz_pip_post); + NWidgetContainer::AdjustPaddingForZoom(); +} + /** * Set additional pre/inter/post space for the container. * @@ -1156,9 +1214,13 @@ NWidgetPIPContainer::NWidgetPIPContainer */ void NWidgetPIPContainer::SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post) { - this->pip_pre = pip_pre; - this->pip_inter = pip_inter; - this->pip_post = pip_post; + this->uz_pip_pre = pip_pre; + this->uz_pip_inter = pip_inter; + this->uz_pip_post = pip_post; + + this->pip_pre = ScaleGUITrad(this->uz_pip_pre); + this->pip_inter = ScaleGUITrad(this->uz_pip_inter); + this->pip_post = ScaleGUITrad(this->uz_pip_post); } void NWidgetPIPContainer::Draw(const Window *w) @@ -1813,6 +1875,12 @@ void NWidgetBackground::SetPIP(uint8 pip this->child->SetPIP(pip_pre, pip_inter, pip_post); } +void NWidgetBackground::AdjustPaddingForZoom() +{ + if (child != nullptr) child->AdjustPaddingForZoom(); + NWidgetCore::AdjustPaddingForZoom(); +} + void NWidgetBackground::SetupSmallestSize(Window *w, bool init_array) { if (init_array && this->index >= 0) { @@ -2137,11 +2205,11 @@ void NWidgetScrollbar::SetupSmallestSize switch (this->type) { case NWID_HSCROLLBAR: - this->SetMinimalSize(NWidgetScrollbar::GetHorizontalDimension().width * 3, NWidgetScrollbar::GetHorizontalDimension().height); + this->SetMinimalSizeAbsolute(NWidgetScrollbar::GetHorizontalDimension().width * 3, NWidgetScrollbar::GetHorizontalDimension().height); break; case NWID_VSCROLLBAR: - this->SetMinimalSize(NWidgetScrollbar::GetVerticalDimension().width, NWidgetScrollbar::GetVerticalDimension().height * 3); + this->SetMinimalSizeAbsolute(NWidgetScrollbar::GetVerticalDimension().width, NWidgetScrollbar::GetVerticalDimension().height * 3); break; default: NOT_REACHED(); @@ -2768,7 +2836,7 @@ static int MakeNWidget(const NWidgetPart NWidgetResizeBase *nwrb = dynamic_cast(*dest); if (nwrb != nullptr) { assert(parts->u.xy.x >= 0 && parts->u.xy.y >= 0); - nwrb->SetMinimalSize(ScaleGUITrad(parts->u.xy.x), ScaleGUITrad(parts->u.xy.y)); + nwrb->SetMinimalSize(parts->u.xy.x, parts->u.xy.y); } break; } @@ -2814,15 +2882,15 @@ static int MakeNWidget(const NWidgetPart } case WPT_PADDING: - if (*dest != nullptr) (*dest)->SetPadding(ScaleGUITrad(parts->u.padding.top), ScaleGUITrad(parts->u.padding.right), ScaleGUITrad(parts->u.padding.bottom), ScaleGUITrad(parts->u.padding.left)); + if (*dest != nullptr) (*dest)->SetPadding(parts->u.padding.top, parts->u.padding.right, parts->u.padding.bottom, parts->u.padding.left); break; case WPT_PIPSPACE: { NWidgetPIPContainer *nwc = dynamic_cast(*dest); - if (nwc != nullptr) nwc->SetPIP(ScaleGUITrad(parts->u.pip.pre), ScaleGUITrad(parts->u.pip.inter), ScaleGUITrad(parts->u.pip.post)); + if (nwc != nullptr) nwc->SetPIP(parts->u.pip.pre, parts->u.pip.inter, parts->u.pip.post); NWidgetBackground *nwb = dynamic_cast(*dest); - if (nwb != nullptr) nwb->SetPIP(ScaleGUITrad(parts->u.pip.pre), ScaleGUITrad(parts->u.pip.inter), ScaleGUITrad(parts->u.pip.post)); + if (nwb != nullptr) nwb->SetPIP(parts->u.pip.pre, parts->u.pip.inter, parts->u.pip.post); break; } @@ -3019,7 +3087,7 @@ NWidgetBase *MakeCompanyButtonRows(int * NWidgetHorizontal *hor = nullptr; // Storage for buttons in one row. int hor_length = 0; - Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON); + Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON, nullptr, ZOOM_LVL_OUT_4X); sprite_size.width += WD_MATRIX_LEFT + WD_MATRIX_RIGHT; sprite_size.height += WD_MATRIX_TOP + WD_MATRIX_BOTTOM + 1; // 1 for the 'offset' of being pressed diff --git a/src/widget_type.h b/src/widget_type.h --- a/src/widget_type.h +++ b/src/widget_type.h @@ -127,6 +127,7 @@ class NWidgetBase : public ZeroedMemoryA public: NWidgetBase(WidgetType tp); + virtual void AdjustPaddingForZoom(); virtual void SetupSmallestSize(Window *w, bool init_array) = 0; virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) = 0; @@ -148,10 +149,11 @@ public: */ inline void SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left) { - this->padding_top = top; - this->padding_right = right; - this->padding_bottom = bottom; - this->padding_left = left; + this->uz_padding_top = top; + this->uz_padding_right = right; + this->uz_padding_bottom = bottom; + this->uz_padding_left = left; + this->AdjustPaddingForZoom(); } inline uint GetHorizontalStepSize(SizingType sizing) const; @@ -195,6 +197,11 @@ public: 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. (parent container may swap this with padding_right for RTL) + uint8 uz_padding_top; ///< Unscaled top padding, for resize calculation. + uint8 uz_padding_right; ///< Unscaled right padding, for resize calculation. + uint8 uz_padding_bottom; ///< Unscaled bottom padding, for resize calculation. + uint8 uz_padding_left; ///< Unscaled left padding, for resize calculation. + protected: inline void StoreSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height); }; @@ -246,7 +253,9 @@ class NWidgetResizeBase : public NWidget public: NWidgetResizeBase(WidgetType tp, uint fill_x, uint fill_y); + void AdjustPaddingForZoom() override; void SetMinimalSize(uint min_x, uint min_y); + void SetMinimalSizeAbsolute(uint min_x, uint min_y); void SetMinimalTextLines(uint8 min_lines, uint8 spacing, FontSize size); void SetFill(uint fill_x, uint fill_y); void SetResize(uint resize_x, uint resize_y); @@ -255,6 +264,14 @@ public: uint min_x; ///< Minimal horizontal size of only this widget. uint min_y; ///< Minimal vertical size of only this widget. + + bool absolute; ///< Set if minimum size is fixed and should not be resized. + uint uz_min_x; ///< Unscaled Minimal horizontal size of only this widget. + uint uz_min_y; ///< Unscaled Minimal vertical size of only this widget. + + uint8 uz_text_lines; ///< 'Unscaled' text lines, stored for resize calculation. + uint8 uz_text_spacing; ///< 'Unscaled' text padding, stored for resize calculation. + FontSize uz_text_size; ///< 'Unscaled' font size, stored for resize calculation. }; /** Nested widget flags that affect display and interaction with 'real' widgets. */ @@ -385,6 +402,7 @@ public: NWidgetContainer(WidgetType tp); ~NWidgetContainer(); + void AdjustPaddingForZoom() override; void Add(NWidgetBase *wid); void FillNestedArray(NWidgetBase **array, uint length) override; @@ -423,6 +441,7 @@ public: void SetIndex(int index); + void AdjustPaddingForZoom() override; void SetupSmallestSize(Window *w, bool init_array) override; void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override; void FillNestedArray(NWidgetBase **array, uint length) override; @@ -450,6 +469,7 @@ class NWidgetPIPContainer : public NWidg public: NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags = NC_NONE); + void AdjustPaddingForZoom() override; void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post); void Draw(const Window *w) override; @@ -460,6 +480,10 @@ protected: 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. + + uint8 uz_pip_pre; ///< Unscaled space before first widget. + uint8 uz_pip_inter; ///< Unscaled space between widgets. + uint8 uz_pip_post; ///< Unscaled space after last widget. }; /** @@ -565,6 +589,7 @@ public: void Add(NWidgetBase *nwid); void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post); + void AdjustPaddingForZoom() override; void SetupSmallestSize(Window *w, bool init_array) override; void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override; diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -153,7 +153,7 @@ struct DropdownWindow : Window { uint items_width = size.width - (scroll ? NWidgetScrollbar::GetVerticalDimension().width : 0); NWidgetCore *nwi = this->GetWidget(WID_DM_ITEMS); - nwi->SetMinimalSize(items_width, size.height + 4); + nwi->SetMinimalSizeAbsolute(items_width, size.height + 4); nwi->colour = wi_colour; nwi = this->GetWidget(WID_DM_SCROLL); diff --git a/src/window.cpp b/src/window.cpp --- a/src/window.cpp +++ b/src/window.cpp @@ -3412,7 +3412,7 @@ void HideVitalWindows() } /** Re-initialize all windows. */ -void ReInitAllWindows() +void ReInitAllWindows(bool zoom_changed) { NWidgetLeaf::InvalidateDimensionCache(); // Reset cached sizes of several widgets. NWidgetScrollbar::InvalidateDimensionCache(); @@ -3421,6 +3421,7 @@ void ReInitAllWindows() InitDepotWindowBlockSizes(); for (Window *w : Window::IterateFromBack()) { + if (zoom_changed) w->nested_root->AdjustPaddingForZoom(); w->ReInit(); } diff --git a/src/window_func.h b/src/window_func.h --- a/src/window_func.h +++ b/src/window_func.h @@ -43,7 +43,11 @@ void DeleteConstructionWindows(); void HideVitalWindows(); void ShowVitalWindows(); -void ReInitAllWindows(); +/** + * Re-initialize all windows. + * @param zoom_changed Set if windows are being re-initialized due to a zoom level changed. + */ +void ReInitAllWindows(bool zoom_changed); void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index); void SetWindowDirty(WindowClass cls, WindowNumber number);