* Update size and position of window to fit dropdown list into available space. */
| 168 | * Update size and position of window to fit dropdown list into available space. |
| 169 | */ |
| 170 | void UpdateSizeAndPosition() |
| 171 | { |
| 172 | Rect button_rect = this->wi_rect.Translate(this->parent->left, this->parent->top); |
| 173 | |
| 174 | /* Get the dimensions required for the list. */ |
| 175 | Dimension list_dim = GetDropDownListDimension(this->list); |
| 176 | |
| 177 | /* Set up dimensions for the items widget. */ |
| 178 | Dimension widget_dim = list_dim; |
| 179 | widget_dim.width += WidgetDimensions::scaled.dropdownlist.Horizontal(); |
| 180 | widget_dim.height += WidgetDimensions::scaled.dropdownlist.Vertical(); |
| 181 | |
| 182 | /* Width should match at least the width of the parent widget. */ |
| 183 | widget_dim.width = std::max<uint>(widget_dim.width, button_rect.Width()); |
| 184 | |
| 185 | /* Available height below (or above, if the dropdown is placed above the widget). */ |
| 186 | uint available_height_below = std::max(GetMainViewBottom() - button_rect.bottom - 1, 0); |
| 187 | uint available_height_above = std::max(button_rect.top - 1 - GetMainViewTop(), 0); |
| 188 | |
| 189 | /* Is it better to place the dropdown above the widget? */ |
| 190 | if (widget_dim.height > available_height_below && available_height_above > available_height_below) { |
| 191 | FitAvailableHeight(widget_dim, list_dim, available_height_above); |
| 192 | this->position.y = button_rect.top - widget_dim.height; |
| 193 | } else { |
| 194 | FitAvailableHeight(widget_dim, list_dim, available_height_below); |
| 195 | this->position.y = button_rect.bottom + 1; |
| 196 | } |
| 197 | |
| 198 | if (_current_text_dir == TD_RTL) { |
| 199 | /* In case the list is wider than the parent button, the list should be right aligned to the button and overflow to the left. */ |
| 200 | this->position.x = button_rect.right + 1 - (int)(widget_dim.width + (list_dim.height > widget_dim.height ? NWidgetScrollbar::GetVerticalDimension().width : 0)); |
| 201 | } else { |
| 202 | this->position.x = button_rect.left; |
| 203 | } |
| 204 | |
| 205 | this->items_dim = widget_dim; |
| 206 | this->GetWidget<NWidgetStacked>(WID_DM_SHOW_SCROLL)->SetDisplayedPlane(list_dim.height > widget_dim.height ? 0 : SZSP_NONE); |
| 207 | |
| 208 | /* Capacity is the average number of items visible */ |
| 209 | this->vscroll->SetCapacity(widget_dim.height - WidgetDimensions::scaled.dropdownlist.Vertical()); |
| 210 | this->vscroll->SetStepSize(list_dim.height / this->list.size()); |
| 211 | this->vscroll->SetCount(list_dim.height); |
| 212 | |
| 213 | /* If the dropdown is positioned above the parent widget, start selection at the bottom. */ |
| 214 | if (this->position.y < button_rect.top && list_dim.height > widget_dim.height) this->vscroll->UpdatePosition(INT_MAX); |
| 215 | } |
| 216 | |
| 217 | void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override |
| 218 | { |
no test coverage detected