/** @file zoning_gui.cpp */ #include "stdafx.h" #include "widgets/dropdown_func.h" #include "table/strings.h" #include "strings_func.h" #include "gfx_func.h" #include "core/geometry_func.hpp" #include "zoning.h" #include "hotkeys.h" const StringID _zone_types[] = { //STR_ZONING_NO_ZONING, STR_ZONING_AUTHORITY, STR_ZONING_CAN_BUILD, STR_ZONING_STA_CATCH, STR_ZONING_ACTIVE_STATIONS, STR_ZONING_BUL_UNSER, STR_ZONING_IND_UNSER, STR_ZONING_TOWN_ZONES, STR_ZONING_CB_ACCEPTANCE, STR_ZONING_CB_TOWN_LIMIT, STR_ZONING_ADVERTISEMENT_ZONES, STR_ZONING_TOWN_GROWTH_TILES, }; const int ZONES_COUNT = 11; enum ZoningToolbarWidgets { ZTW_CAPTION, ZTW_OUTER_FIRST, ZTW_INNER_FIRST = ZTW_OUTER_FIRST + ZONES_COUNT, ZTW_INNER_END = ZTW_INNER_FIRST + ZONES_COUNT, }; struct ZoningWindow : public Window { uint maxwidth; uint maxheight; ZoningWindow(WindowDesc *desc, int window_number) : Window(desc) { Dimension dim; this->maxwidth = 0; this->maxheight = 0; for (int i = 0; i < ZONES_COUNT; i++) { dim = GetStringBoundingBox(_zone_types[i]); this->maxwidth = max(this->maxwidth, dim.width); this->maxheight = max(this->maxheight, dim.height); } this->InitNested(window_number); this->InvalidateData(); if(_zoning.outer != CHECKNOTHING) this->LowerWidget(ZTW_OUTER_FIRST + _zoning.outer - 1); //-1:skip CHECKNOTHING if(_zoning.inner != CHECKNOTHING) this->LowerWidget(ZTW_INNER_FIRST + _zoning.inner - 1); } virtual void OnPaint() { this->DrawWidgets(); } virtual void OnClick(Point pt, int widget, int click_count) { bool outer = true; bool deselect = false; EvaluationMode clicked; if (widget >= ZTW_OUTER_FIRST && widget < ZTW_INNER_FIRST){ clicked = (EvaluationMode)(widget - ZTW_OUTER_FIRST + 1); //+1:skip CHECKNOTHING deselect = _zoning.outer == clicked; _zoning.outer = deselect ? CHECKNOTHING : clicked; } else if (widget >= ZTW_INNER_FIRST && widget < ZTW_INNER_END){ clicked = (EvaluationMode)(widget - ZTW_INNER_FIRST + 1); deselect = _zoning.inner == clicked; _zoning.inner = deselect ? CHECKNOTHING : clicked; outer = false; } else return; this->RaiseAllWidgets(outer); if(!deselect) this->ToggleWidgetLoweredState(widget); this->InvalidateData(); MarkWholeScreenDirty(); } void DrawWidget(const Rect &r, int widget) const { StringID strid = STR_EMPTY; if (widget >= ZTW_OUTER_FIRST && widget < ZTW_INNER_FIRST){ strid = _zone_types[widget - ZTW_OUTER_FIRST]; } else if (widget >= ZTW_INNER_FIRST && widget < ZTW_INNER_END){ strid = _zone_types[widget - ZTW_INNER_FIRST]; } else return; bool rtl = _current_text_dir == TD_RTL; byte clk_dif = this->IsWidgetLowered(widget) ? 1 : 0; int x = r.left + WD_FRAMERECT_LEFT; int y = r.top; DrawString(rtl ? r.left : x + clk_dif + 1, (rtl ? r.right + clk_dif : r.right), y + 1 + clk_dif, strid, TC_FROMSTRING, SA_LEFT); } virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) { if (widget >= ZTW_OUTER_FIRST && widget < ZTW_INNER_END){ size->width = this->maxwidth + padding.width + 8; size->height = this->maxheight + 2; } } void RaiseAllWidgets(bool outer){ byte start = outer ? ZTW_OUTER_FIRST : ZTW_INNER_FIRST; byte end = outer ? ZTW_INNER_FIRST : ZTW_INNER_END; for(byte i = start; i < end; i++){ if(this->IsWidgetLowered(i)){ this->ToggleWidgetLoweredState(i); break; } } } virtual EventState OnHotkey(int hotkey) { return Window::OnHotkey(hotkey); } static HotkeyList hotkeys; }; static EventState ZoningWindowGlobalHotkeys(int hotkey) { EvaluationMode zoning = (EvaluationMode)(hotkey - ZTW_OUTER_FIRST); // +1:skip CHECKNOTHING bool deselect = (_zoning.outer == zoning); _zoning.outer = deselect ? CHECKNOTHING : zoning; MarkWholeScreenDirty(); return ES_HANDLED; } static Hotkey zoning_hotkeys[] = { Hotkey(WKC_SHIFT | '1', "authority", ZTW_OUTER_FIRST + CHECKOPINION), Hotkey(WKC_SHIFT | '2', "build_status", ZTW_OUTER_FIRST + CHECKBUILD), Hotkey(WKC_SHIFT | '3', "station_catchment", ZTW_OUTER_FIRST + CHECKSTACATCH), Hotkey(WKC_SHIFT | '4', "unserved_buildings", ZTW_OUTER_FIRST + CHECKBULUNSER), Hotkey(WKC_SHIFT | '5', "unserved_industries", ZTW_OUTER_FIRST + CHECKINDUNSER), Hotkey(WKC_SHIFT | '6', "town_zone", ZTW_OUTER_FIRST + CHECKTOWNZONES), Hotkey(WKC_SHIFT | '7', "cb_acceptance", ZTW_OUTER_FIRST + CHECKCBACCEPTANCE), Hotkey(WKC_SHIFT | '8', "cb_town_limit", ZTW_OUTER_FIRST + CHECKCBTOWNLIMIT), Hotkey(WKC_SHIFT | '9', "advertisement", ZTW_OUTER_FIRST + CHECKTOWNADZONES), Hotkey(WKC_SHIFT | '0', "growth_tiles", ZTW_OUTER_FIRST + CHECKTOWNGROWTHTILES), Hotkey((uint16)0, "active_stations", ZTW_OUTER_FIRST + CHECKACTIVESTATIONS), HOTKEY_LIST_END }; HotkeyList ZoningWindow::hotkeys("zoning_gui", zoning_hotkeys, ZoningWindowGlobalHotkeys); /** Construct the row containing the digit keys. */ static NWidgetBase *MakeZoningButtons(int *biggest_index) { NWidgetHorizontal *hor = new NWidgetHorizontal(NC_EQUALSIZE); int zone_types_size = lengthof(_zone_types); hor->SetPadding(1, 1, 1, 1); for(int i = 0; i < 2; i++){ NWidgetVertical *ver = new NWidgetVertical; int offset = (i == 0) ? ZTW_OUTER_FIRST : ZTW_INNER_FIRST; for (int j = 0; j < zone_types_size; j++) { NWidgetBackground *leaf = new NWidgetBackground(WWT_PANEL, i==0 ? COLOUR_ORANGE : COLOUR_YELLOW, offset + j, NULL); leaf->SetFill(1, 0); leaf->SetPadding(0, 0, 0, 0); ver->Add(leaf); } hor->Add(ver); } *biggest_index = ZTW_INNER_END - 1; return hor; } static const NWidgetPart _nested_zoning_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, ZTW_CAPTION), SetDataTip(STR_ZONING_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), NWidgetFunction(MakeZoningButtons), EndContainer() }; static WindowDesc _zoning_desc ( WDP_AUTO, NULL, 0, 0, WC_ZONING_TOOLBAR, WC_NONE, 0, _nested_zoning_widgets, lengthof(_nested_zoning_widgets), &ZoningWindow::hotkeys ); void ShowZoningToolbar() { AllocateWindowDescFront(&_zoning_desc, 0); }