diff --git a/src/window.cpp b/src/window.cpp --- a/src/window.cpp +++ b/src/window.cpp @@ -224,10 +224,8 @@ int Window::GetRowFromWidget(int clickpo */ void Window::DisableAllWidgetHighlight() { - for (uint i = 0; i < this->nested_array_size; i++) { - NWidgetBase *nwid = this->GetWidget(i); - if (nwid == nullptr) continue; - + for (auto &pair : this->widget_lookup) { + NWidgetBase *nwid = pair.second; if (nwid->IsHighlighted()) { nwid->SetHighlighted(TC_INVALID); nwid->SetDirty(this); @@ -244,8 +242,6 @@ void Window::DisableAllWidgetHighlight() */ void Window::SetWidgetHighlight(byte widget_index, TextColour highlighted_colour) { - assert(widget_index < this->nested_array_size); - NWidgetBase *nwid = this->GetWidget(widget_index); if (nwid == nullptr) return; @@ -258,9 +254,8 @@ void Window::SetWidgetHighlight(byte wid } else { /* If we disable a highlight, check all widgets if anyone still has a highlight */ bool valid = false; - for (uint i = 0; i < this->nested_array_size; i++) { - nwid = this->GetWidget(i); - if (nwid == nullptr) continue; + for (const auto &pair : this->widget_lookup) { + nwid = pair.second; if (!nwid->IsHighlighted()) continue; valid = true; @@ -277,8 +272,6 @@ void Window::SetWidgetHighlight(byte wid */ bool Window::IsWidgetHighlighted(byte widget_index) const { - assert(widget_index < this->nested_array_size); - const NWidgetBase *nwid = this->GetWidget(widget_index); if (nwid == nullptr) return false; @@ -493,18 +486,19 @@ void Window::UnfocusFocusedWidget() */ bool Window::SetFocusedWidget(int widget_index) { - /* Do nothing if widget_index is already focused, or if it wasn't a valid widget. */ - if ((uint)widget_index >= this->nested_array_size) return false; - - assert(this->widget_lookup[widget_index] != nullptr); // Setting focus to a non-existing widget is a bad idea. + NWidgetCore *widget = this->GetWidget(widget_index); + assert(widget != nullptr); /* Setting focus to a non-existing widget is a bad idea. */ + if (this->nested_focus != nullptr) { - if (this->GetWidget(widget_index) == this->nested_focus) return false; + /* Do nothing if widget_index is already focused. */ + if (widget == this->nested_focus) return false; /* Repaint the widget that lost focus. A focused edit box may else leave the caret on the screen. */ this->nested_focus->SetDirty(this); if (this->nested_focus->type == WWT_EDITBOX) VideoDriver::GetInstance()->EditBoxLostFocus(); } - this->nested_focus = this->GetWidget(widget_index); + + this->nested_focus = widget; if (this->nested_focus->type == WWT_EDITBOX) VideoDriver::GetInstance()->EditBoxGainedFocus(); return true; } @@ -531,21 +525,23 @@ void Window::OnFocusLost(bool) */ void Window::RaiseButtons(bool autoraise) { - for (uint i = 0; i < this->nested_array_size; i++) { - if (this->widget_lookup[i] == nullptr) continue; - WidgetType type = this->widget_lookup[i]->type; + for (auto &pair : this->widget_lookup) { + WidgetType type = pair.second->type; + NWidgetCore *wid = dynamic_cast(pair.second); if (((type & ~WWB_PUSHBUTTON) < WWT_LAST || type == NWID_PUSHBUTTON_DROPDOWN) && - (!autoraise || (type & WWB_PUSHBUTTON) || type == WWT_EDITBOX) && this->IsWidgetLowered(i)) { - this->RaiseWidget(i); - this->SetWidgetDirty(i); + (!autoraise || (type & WWB_PUSHBUTTON) || type == WWT_EDITBOX) && wid->IsLowered()) { + wid->SetLowered(false); + wid->SetDirty(this); } } /* Special widgets without widget index */ - NWidgetCore *wid = this->nested_root != nullptr ? (NWidgetCore*)this->nested_root->GetWidgetOfType(WWT_DEFSIZEBOX) : nullptr; - if (wid != nullptr) { - wid->SetLowered(false); - wid->SetDirty(this); + { + NWidgetCore *wid = this->nested_root != nullptr ? dynamic_cast(this->nested_root->GetWidgetOfType(WWT_DEFSIZEBOX)) : nullptr; + if (wid != nullptr) { + wid->SetLowered(false); + wid->SetDirty(this); + } } } @@ -556,9 +552,10 @@ void Window::RaiseButtons(bool autoraise void Window::SetWidgetDirty(byte widget_index) const { /* Sometimes this function is called before the window is even fully initialized */ - if (this->widget_lookup == nullptr) return; - - this->widget_lookup[widget_index]->SetDirty(this); + auto it = this->widget_lookup.find(widget_index); + if (it == std::end(this->widget_lookup)) return; + + it->second->SetDirty(this); } /** @@ -635,7 +632,7 @@ static void DispatchLeftClickEvent(Windo /* Clicked on a widget that is not disabled. * So unless the clicked widget is the caption bar, change focus to this widget. * Exception: In the OSK we always want the editbox to stay focused. */ - if (widget_type != WWT_CAPTION && w->window_class != WC_OSK) { + if (widget_index >= 0 && widget_type != WWT_CAPTION && w->window_class != WC_OSK) { /* focused_widget_changed is 'now' only true if the window this widget * is in gained focus. In that case it must remain true, also if the * local widget focus did not change. As such it's the logical-or of @@ -1091,8 +1088,6 @@ Window::~Window() assert(*this->z_position == nullptr); if (this->viewport != nullptr) DeleteWindowViewport(this); - - free(this->widget_lookup); // Contents is released through deletion of #nested_root. delete this->nested_root; } @@ -1729,12 +1724,8 @@ static Point LocalGetWindowPlacement(con */ void Window::CreateNestedTree() { - int biggest_index = -1; - this->nested_root = MakeWindowNWidgetTree(this->window_desc->nwid_begin, this->window_desc->nwid_end, &biggest_index, &this->shade_select); - this->nested_array_size = (uint)(biggest_index + 1); - - this->widget_lookup = CallocT(this->nested_array_size); - this->nested_root->FillWidgetLookup(this->widget_lookup, this->nested_array_size); + this->nested_root = MakeWindowNWidgetTree(this->window_desc->nwid_begin, this->window_desc->nwid_end, &this->shade_select); + this->nested_root->FillWidgetLookup(this->widget_lookup); } /** @@ -1840,9 +1831,9 @@ static void DecreaseWindowCounters() for (Window *w : Window::Iterate()) { if (_scroller_click_timeout == 0) { /* Unclick scrollbar buttons if they are pressed. */ - for (uint i = 0; i < w->nested_array_size; i++) { - NWidgetBase *nwid = w->widget_lookup[i]; - if (nwid != nullptr && (nwid->type == NWID_HSCROLLBAR || nwid->type == NWID_VSCROLLBAR)) { + for (auto &pair : w->widget_lookup) { + NWidgetBase *nwid = pair.second; + if (nwid->type == NWID_HSCROLLBAR || nwid->type == NWID_VSCROLLBAR) { NWidgetScrollbar *sb = static_cast(nwid); if (sb->disp_flags & (ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN)) { sb->disp_flags &= ~(ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN); @@ -3155,8 +3146,8 @@ void Window::ProcessHighlightedInvalidat { if ((this->flags & WF_HIGHLIGHTED) == 0) return; - for (uint i = 0; i < this->nested_array_size; i++) { - if (this->IsWidgetHighlighted(i)) this->SetWidgetDirty(i); + for (const auto &pair : this->widget_lookup) { + if (pair.second->IsHighlighted()) pair.second->SetDirty(this); } }