diff --git a/src/lang/english.txt b/src/lang/english.txt index d0f0a87e43..b7baa739ea 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4678,6 +4678,8 @@ STR_PLANS_ADD_LINES :{BLACK}Add line STR_PLANS_ADDING_LINES :{BLACK}Adding... STR_PLANS_HIDE_ALL :{BLACK}Hide all STR_PLANS_HIDE_ALL_TOOLTIP :{BLACK}Set the visibility of all the plans and all their lines to false +STR_PLANS_SHOW_ALL :{BLACK}Show all +STR_PLANS_SHOW_ALL_TOOLTIP :{BLACK}Set the visibility of all the plans and all their lines to true STR_PLANS_VISIBILITY_PRIVATE :{BLACK}Make private STR_PLANS_VISIBILITY_PUBLIC :{BLACK}Make public STR_PLANS_VISIBILITY_TOOLTIP :{BLACK}Toggle the visibility of a plan (private is yellow, public is blue). A public plan will be displayed in the plan window of the other companies but only its owner can add lines to it. @@ -4685,7 +4687,7 @@ STR_PLANS_DELETE :{BLACK}Delete STR_PLANS_DELETE_TOOLTIP :{BLACK}Delete the selected item in the list STR_PLANS_LIST_ITEM_PLAN :Plan #{NUM}: {NUM} line{P "" s} ({DATE_SHORT}) STR_PLANS_LIST_ITEM_LINE : -- Line #{NUM}: {NUM} segment{P "" s} -STR_PLANS_LIST_TOOLTIP :{BLACK}Double click any item in the list to (un)fold the related plan +STR_PLANS_LIST_TOOLTIP :{BLACK}Double click any item in the list to (un)fold the related plan.{}Ctrl+Click to scroll to. # Vehicle loading indicators STR_PERCENT_UP_SMALL :{TINY_FONT}{WHITE}{NUM}%{UP_ARROW} diff --git a/src/plans_base.h b/src/plans_base.h index ca31a5ca13..7dac2d45b4 100644 --- a/src/plans_base.h +++ b/src/plans_base.h @@ -131,6 +131,26 @@ struct PlanLine { this->tiles.push_back(FROM_LE32(*data)); } } + + void AddLineToCalculateCentreTile(uint64 &x, uint64 &y, uint32 &count) const + { + for (size_t i = 0; i < this->tiles.size(); i++) { + TileIndex t = this->tiles[i]; + x += TileX(t); + y += TileY(t); + count++; + } + } + + TileIndex CalculateCentreTile() const + { + uint64 x = 0; + uint64 y = 0; + uint32 count = 0; + this->AddLineToCalculateCentreTile(x, y, count); + if (count == 0) return INVALID_TILE; + return TileXY(x / count, y / count); + } }; struct Plan : PlanPool::PoolItem<&_plan_pool> { @@ -229,6 +249,18 @@ struct Plan : PlanPool::PoolItem<&_plan_pool> { if (_current_plan->owner == _local_company) DoCommandP(0, _current_plan->index, !this->visible_by_all, CMD_CHANGE_PLAN_VISIBILITY); return this->visible_by_all; } + + TileIndex CalculateCentreTile() const + { + uint64 x = 0; + uint64 y = 0; + uint32 count = 0; + for (PlanLineVector::const_iterator it = lines.begin(); it != lines.end(); it++) { + (*it)->AddLineToCalculateCentreTile(x, y, count); + } + if (count == 0) return INVALID_TILE; + return TileXY(x / count, y / count); + } }; #define FOR_ALL_PLANS_FROM(var, start) FOR_ALL_ITEMS_FROM(Plan, plan_index, var, start) diff --git a/src/plans_gui.cpp b/src/plans_gui.cpp index 8139e49d24..544227484b 100644 --- a/src/plans_gui.cpp +++ b/src/plans_gui.cpp @@ -51,7 +51,10 @@ static const NWidgetPart _nested_plans_widgets[] = { NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PLN_NEW), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_PLANS_NEW_PLAN, STR_NULL), NWidget(WWT_TEXTBTN_2, COLOUR_GREY, WID_PLN_ADD_LINES), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_PLANS_ADD_LINES, STR_PLANS_ADDING_LINES), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PLN_VISIBILITY), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_PLANS_VISIBILITY_PUBLIC, STR_PLANS_VISIBILITY_TOOLTIP), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PLN_HIDE_ALL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_PLANS_HIDE_ALL, STR_NULL), + NWidget(NWID_SELECTION, INVALID_COLOUR, WID_PLN_HIDE_ALL_SEL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PLN_HIDE_ALL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_PLANS_HIDE_ALL, STR_PLANS_HIDE_ALL_TOOLTIP), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PLN_SHOW_ALL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_PLANS_SHOW_ALL, STR_PLANS_SHOW_ALL_TOOLTIP), + EndContainer(), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PLN_DELETE), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_PLANS_DELETE, STR_PLANS_DELETE_TOOLTIP), NWidget(WWT_RESIZEBOX, COLOUR_GREY), EndContainer(), @@ -73,19 +76,20 @@ struct PlansWindow : Window { } ListItem; Scrollbar *vscroll; - int text_offset; + NWidgetStacked *hide_all_sel; std::vector list; ///< The translation table linking panel indices to their related PlanID. int selected; ///< What item is currently selected in the panel. + uint vis_btn_left; ///< left offset of visibility button + Dimension company_icon_spr_dim; ///< dimensions of company icon PlansWindow(WindowDesc *desc) : Window(desc) { this->CreateNestedTree(); this->vscroll = this->GetScrollbar(WID_PLN_SCROLLBAR); + this->hide_all_sel = this->GetWidget(WID_PLN_HIDE_ALL_SEL); + this->hide_all_sel->SetDisplayedPlane(0); this->FinishInitNested(); - Dimension spr_dim = GetSpriteSize(SPR_COMPANY_ICON); - this->text_offset = WD_FRAMETEXT_LEFT + spr_dim.width + 2 + SETTING_BUTTON_WIDTH; - this->selected = INT_MAX; RebuildList(); } @@ -122,28 +126,50 @@ struct PlansWindow : Window { this->SetWidgetDirty(WID_PLN_LIST); break; } + case WID_PLN_SHOW_ALL: { + Plan *p; + FOR_ALL_PLANS(p) { + if (p->IsListable()) p->SetVisibility(true); + } + this->SetWidgetDirty(WID_PLN_LIST); + break; + } case WID_PLN_VISIBILITY: if (_current_plan) _current_plan->ToggleVisibilityByAll(); break; case WID_PLN_LIST: { int new_selected = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_PLN_LIST, WD_FRAMERECT_TOP); + if (_ctrl_pressed) { + if (new_selected != INT_MAX) { + TileIndex t; + if (this->list[new_selected].is_plan) { + t = Plan::Get(this->list[new_selected].plan_id)->CalculateCentreTile(); + } else { + t = Plan::Get(this->list[new_selected].plan_id)->lines[this->list[new_selected].line_id]->CalculateCentreTile(); + } + if (t != INVALID_TILE) ScrollMainWindowToTile(t); + } + return; + } if (this->selected != INT_MAX) { _current_plan->SetFocus(false); } if (new_selected != INT_MAX) { + const int btn_left = this->vis_btn_left; + const int btn_right = btn_left + SETTING_BUTTON_WIDTH; if (this->list[new_selected].is_plan) { _current_plan = Plan::Get(this->list[new_selected].plan_id); _current_plan->SetFocus(true); - if (pt.x >= 22 && pt.x < 41) _current_plan->ToggleVisibility(); + if (pt.x >= btn_left && pt.x < btn_right) _current_plan->ToggleVisibility(); } else { _current_plan = Plan::Get(this->list[new_selected].plan_id); PlanLine *pl = _current_plan->lines[this->list[new_selected].line_id]; pl->SetFocus(true); - if (pt.x >= 22 && pt.x < 41) { + if (pt.x >= btn_left && pt.x < btn_right) { if (pl->ToggleVisibility()) _current_plan->SetVisibility(true, false); } } - if (click_count > 1 && (pt.x < 22 || pt.x >= 41)) { + if (click_count > 1 && (pt.x < btn_left || pt.x >= btn_right)) { _current_plan->show_lines = !_current_plan->show_lines; this->InvalidateData(INVALID_PLAN); } @@ -161,9 +187,20 @@ struct PlansWindow : Window { } } + bool AllPlansHidden() const + { + Plan *p; + FOR_ALL_PLANS(p) { + if (p->IsVisible()) return false; + } + return true; + } + virtual void OnPaint() { this->SetWidgetDisabledState(WID_PLN_HIDE_ALL, this->vscroll->GetCount() == 0); + this->SetWidgetDisabledState(WID_PLN_SHOW_ALL, this->vscroll->GetCount() == 0); + this->hide_all_sel->SetDisplayedPlane(this->vscroll->GetCount() != 0 && this->AllPlansHidden() ? 1 : 0); if (_current_plan) { this->SetWidgetsDisabledState(_current_plan->owner != _local_company, WID_PLN_ADD_LINES, WID_PLN_VISIBILITY, WID_PLN_DELETE, WIDGET_LIST_END); this->GetWidget(WID_PLN_VISIBILITY)->widget_data = _current_plan->visible_by_all ? STR_PLANS_VISIBILITY_PRIVATE : STR_PLANS_VISIBILITY_PUBLIC; @@ -184,10 +221,11 @@ struct PlansWindow : Window { } bool rtl = _current_text_dir == TD_RTL; - uint icon_left = 4 + (rtl ? r.right - this->text_offset : r.left); - uint btn_left = (rtl ? icon_left - SETTING_BUTTON_WIDTH + 4 : icon_left + SETTING_BUTTON_WIDTH - 4); - uint text_left = r.left + (rtl ? WD_FRAMERECT_LEFT : this->text_offset); - uint text_right = r.right - (rtl ? this->text_offset : WD_FRAMERECT_RIGHT); + uint icon_left = (rtl ? r.right - WD_FRAMERECT_RIGHT - this->company_icon_spr_dim.width : WD_FRAMETEXT_LEFT + r.left); + uint btn_left = (rtl ? icon_left - SETTING_BUTTON_WIDTH - 4 : icon_left + this->company_icon_spr_dim.width + 4); + uint text_left = (rtl ? r.left + WD_FRAMERECT_LEFT : btn_left + SETTING_BUTTON_WIDTH + 4); + uint text_right = (rtl ? btn_left - 4 : r.right - WD_FRAMERECT_RIGHT); + const_cast(this)->vis_btn_left = btn_left; for (uint16 i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < this->vscroll->GetCount(); i++) { Plan *p = Plan::Get(list[i].plan_id); @@ -195,18 +233,18 @@ struct PlansWindow : Window { if (i == this->selected) GfxFillRect(r.left + 1, y, r.right, y + this->resize.step_height, PC_DARK_GREY); if (list[i].is_plan) { - DrawCompanyIcon(p->owner, icon_left, y + (FONT_HEIGHT_NORMAL - 10) / 2 + 1); - DrawBoolButton(btn_left, y + (FONT_HEIGHT_NORMAL - 10) / 2, p->visible, true); + DrawCompanyIcon(p->owner, icon_left, y + (this->resize.step_height - this->company_icon_spr_dim.height) / 2); + DrawBoolButton(btn_left, y + (this->resize.step_height - SETTING_BUTTON_HEIGHT) / 2, p->visible, true); SetDParam(0, list[i].plan_id + 1); SetDParam(1, p->lines.size()); SetDParam(2, p->creation_date); - DrawString(text_left, text_right, y, STR_PLANS_LIST_ITEM_PLAN, p->visible_by_all ? TC_LIGHT_BLUE : TC_YELLOW); + DrawString(text_left, text_right, y + (this->resize.step_height - FONT_HEIGHT_NORMAL) / 2, STR_PLANS_LIST_ITEM_PLAN, p->visible_by_all ? TC_LIGHT_BLUE : TC_YELLOW); } else { PlanLine *pl = p->lines[list[i].line_id]; - DrawBoolButton(btn_left, y + (FONT_HEIGHT_NORMAL - 10) / 2, pl->visible, true); + DrawBoolButton(btn_left, y + (this->resize.step_height - SETTING_BUTTON_HEIGHT) / 2, pl->visible, true); SetDParam(0, list[i].line_id + 1); SetDParam(1, pl->tiles.size() - 1); - DrawString(text_left, text_right, y, STR_PLANS_LIST_ITEM_LINE, TC_WHITE); + DrawString(text_left, text_right, y + (this->resize.step_height - FONT_HEIGHT_NORMAL) / 2, STR_PLANS_LIST_ITEM_LINE, TC_WHITE); } y += this->resize.step_height; } @@ -224,7 +262,8 @@ struct PlansWindow : Window { { switch (widget) { case WID_PLN_LIST: - resize->height = FONT_HEIGHT_NORMAL; + this->company_icon_spr_dim = GetSpriteSize(SPR_COMPANY_ICON); + resize->height = max(FONT_HEIGHT_NORMAL, SETTING_BUTTON_HEIGHT); size->height = resize->height * 5 + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; break; } diff --git a/src/widgets/plans_widget.h b/src/widgets/plans_widget.h index 938ac34649..430abbcbac 100644 --- a/src/widgets/plans_widget.h +++ b/src/widgets/plans_widget.h @@ -21,7 +21,9 @@ enum PlansWidgets { WID_PLN_ADD_LINES, WID_PLN_VISIBILITY, WID_PLN_HIDE_ALL, + WID_PLN_SHOW_ALL, WID_PLN_DELETE, + WID_PLN_HIDE_ALL_SEL, }; #endif /* WIDGETS_PLANS_WIDGET_H */