diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 410ec62a40..45420b0bab 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -101,7 +101,7 @@ const WindowDesc _dropdown_desc( struct DropdownWindow : Window { WindowClass parent_wnd_class; ///< Parent window class. WindowNumber parent_wnd_num; ///< Parent window number. - byte parent_button; ///< Parent widget number where the window is dropped from. + int parent_button; ///< Parent widget number where the window is dropped from. DropDownList *list; ///< List with dropdown menu items. int selected_index; ///< Index of the selected item in the list. byte click_delay; ///< Timer to delay selection. @@ -168,21 +168,18 @@ struct DropdownWindow : Window { ~DropdownWindow() { + /* Make the dropdown "invisible", so it doesn't affect new window placement. + * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ + this->window_class = WC_INVALID; + this->SetDirty(); + Window *w2 = FindWindowById(this->parent_wnd_class, this->parent_wnd_num); if (w2 != NULL) { - if (w2->nested_array != NULL) { - NWidgetCore *nwi2 = w2->GetWidget(this->parent_button); - if ((nwi2->type & WWT_MASK) == NWID_BUTTON_DROPDOWN) { - nwi2->disp_flags &= ~ND_DROPDOWN_ACTIVE; - } else { - w2->RaiseWidget(this->parent_button); - } - } else { - w2->RaiseWidget(this->parent_button); - } - w2->SetWidgetDirty(this->parent_button); + Point pt = _cursor.pos; + pt.x -= w2->left; + pt.y -= w2->top; + w2->OnDropdownClose(pt, this->parent_button, this->selected_index, this->instant_close); } - DeleteDropDownList(this->list); } @@ -305,19 +302,7 @@ struct DropdownWindow : Window { if (!_left_button_clicked) { this->drag_mode = false; if (!this->GetDropDownItem(item)) { - if (this->instant_close) { - /* Make the dropdown "invisible", so it doesn't affect new window placement. - * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */ - this->window_class = WC_INVALID; - this->SetDirty(); - - if (GetWidgetFromPos(w2, _cursor.pos.x - w2->left, _cursor.pos.y - w2->top) == this->parent_button) { - /* Send event for selected option if we're still - * on the parent button of the list. */ - w2->OnDropdownSelect(this->parent_button, this->selected_index); - } - delete this; - } + if (this->instant_close) delete this; return; } this->click_delay = 2; diff --git a/src/window.cpp b/src/window.cpp index 6e2916f9ea..ad04818ee6 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -167,6 +167,39 @@ bool Window::IsWidgetHighlighted(byte widget_index) const return nwid->IsHighlighted(); } +/** + * A dropdown window associated to this window has been closed. + * @param pt the point inside the window the mouse resides on after closure. + * @param widget the widget (button) that the dropdown is associated with. + * @param index the element in the dropdown that is selected. + * @param instant_close whether the dropdown was configured to close on mouse up. + */ +void Window::OnDropdownClose(Point pt, int widget, int index, bool instant_close) +{ + if (widget < 0) return; + + if (instant_close) { + /* Send event for selected option if we're still + * on the parent button of the dropdown (behaviour of the dropdowns in the main toolbar). */ + if (GetWidgetFromPos(this, pt.x, pt.y) == widget) { + this->OnDropdownSelect(widget, index); + } + } + + /* Raise the dropdown button */ + if (this->nested_array != NULL) { + NWidgetCore *nwi2 = this->GetWidget(widget); + if ((nwi2->type & WWT_MASK) == NWID_BUTTON_DROPDOWN) { + nwi2->disp_flags &= ~ND_DROPDOWN_ACTIVE; + } else { + this->RaiseWidget(widget); + } + } else { + this->RaiseWidget(widget); + } + this->SetWidgetDirty(widget); +} + /** * Return the Scrollbar to a widget index. * @param widnum Scrollbar widget index diff --git a/src/window_gui.h b/src/window_gui.h index 1e5fb5a397..bd1448ee99 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -665,6 +665,8 @@ public: */ virtual void OnDropdownSelect(int widget, int index) {} + virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close); + /** * The query window opened from this window has closed. * @param str the new value of the string, NULL if the window