/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
*/
/** @file zoning_gui.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "widgets/dropdown_func.h"
#include "widget_type.h"
#include "window_func.h"
#include "gui.h"
#include "viewport_func.h"
#include "sound_func.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "strings_func.h"
#include "gfx_func.h"
#include "core/geometry_func.hpp"
#include "core/random_func.hpp"
#include "zoning.h"
#include "debug_settings.h"
#include
enum ZoningToolbarWidgets {
ZTW_OUTER_DROPDOWN,
ZTW_INNER_DROPDOWN,
ZTW_CAPTION
};
struct ZoningModeInfo {
ZoningEvaluationMode mode;
StringID str;
const char *param;
bool debug;
ZoningModeInfo(ZoningEvaluationMode mode, StringID str) : mode(mode), str(str), param(""), debug(false) {}
ZoningModeInfo(ZoningEvaluationMode mode, const char *param, bool debug = true) : mode(mode), str(STR_JUST_RAW_STRING), param(param), debug(debug) {}
};
static const std::initializer_list _zone_modes = {
ZoningModeInfo(ZEM_NOTHING, STR_ZONING_NO_ZONING),
ZoningModeInfo(ZEM_AUTHORITY, STR_ZONING_AUTHORITY),
ZoningModeInfo(ZEM_CAN_BUILD, STR_ZONING_CAN_BUILD),
ZoningModeInfo(ZEM_STA_CATCH, STR_ZONING_STA_CATCH),
ZoningModeInfo(ZEM_STA_CATCH_WIN, STR_ZONING_STA_CATCH_OPEN),
ZoningModeInfo(ZEM_BUL_UNSER, STR_ZONING_BUL_UNSER),
ZoningModeInfo(ZEM_IND_UNSER, STR_ZONING_IND_UNSER),
ZoningModeInfo(ZEM_TRACERESTRICT, STR_ZONING_TRACERESTRICT),
ZoningModeInfo(ZEM_2x2_GRID, STR_ZONING_2x2_GRID),
ZoningModeInfo(ZEM_3x3_GRID, STR_ZONING_3x3_GRID),
ZoningModeInfo(ZEM_ONE_WAY_ROAD, STR_ZONING_ONE_WAY_ROAD),
ZoningModeInfo(ZEM_DBG_WATER_FLOOD, "Debug: Flooding"),
ZoningModeInfo(ZEM_DBG_WATER_REGION, "Debug: Water regions"),
ZoningModeInfo(ZEM_DBG_TROPIC_ZONE, "Debug: Tropic zones"),
ZoningModeInfo(ZEM_DBG_ANIMATED_TILE, "Debug: Animated tiles"),
};
static const ZoningModeInfo &ZoningEvaluationModeToInfo(ZoningEvaluationMode ev_mode)
{
for (const ZoningModeInfo &info : _zone_modes) {
if (info.mode == ev_mode) return info;
}
NOT_REACHED();
}
struct ZoningWindow : public Window {
ZoningWindow(WindowDesc *desc, int window_number)
: Window(desc)
{
this->InitNested(window_number);
this->InvalidateData();
}
static inline bool IsDebugEnabled()
{
return HasBit(_misc_debug_flags, MDF_ZONING_DEBUG_MODES);
}
void OnPaint() override
{
this->DrawWidgets();
}
void ShowZoningDropDown(WidgetID widget, ZoningEvaluationMode current)
{
DropDownList list;
for (const ZoningModeInfo &info : _zone_modes) {
if (info.debug && !IsDebugEnabled()) continue;
SetDParamStr(0, info.param);
list.push_back(std::make_unique(info.str, info.mode, false));
}
ShowDropDownList(this, std::move(list), current, widget);
}
void OnClick(Point pt, WidgetID widget, int click_count) override
{
switch (widget) {
case ZTW_OUTER_DROPDOWN:
this->ShowZoningDropDown(ZTW_OUTER_DROPDOWN, _zoning.outer);
break;
case ZTW_INNER_DROPDOWN:
this->ShowZoningDropDown(ZTW_INNER_DROPDOWN, _zoning.inner);
break;
}
}
void OnDropdownSelect(WidgetID widget, int index) override
{
switch(widget) {
case ZTW_OUTER_DROPDOWN:
SetZoningMode(false, (ZoningEvaluationMode)index);
break;
case ZTW_INNER_DROPDOWN:
SetZoningMode(true, (ZoningEvaluationMode)index);
break;
}
this->InvalidateData();
}
void SetStringParameters(WidgetID widget) const override
{
switch (widget) {
case ZTW_OUTER_DROPDOWN:
case ZTW_INNER_DROPDOWN: {
const ZoningModeInfo &info = ZoningEvaluationModeToInfo(widget == ZTW_OUTER_DROPDOWN ? _zoning.outer : _zoning.inner);
SetDParam(0, info.str);
SetDParamStr(1, info.param);
break;
}
}
}
void UpdateWidgetSize(WidgetID widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
{
switch (widget) {
case ZTW_OUTER_DROPDOWN:
case ZTW_INNER_DROPDOWN:
for (const ZoningModeInfo &info : _zone_modes) {
SetDParamStr(0, info.param);
*size = maxdim(*size, GetStringBoundingBox(info.str));
}
break;
default:
return;
}
size->width += padding.width;
size->height = GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.dropdowntext.Vertical();
}
};
static constexpr 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),
NWidget(NWID_HORIZONTAL, COLOUR_GREY), SetPIP(10, 3, 10),
NWidget(NWID_VERTICAL, COLOUR_GREY), SetPadding(5, 0, 5, 0), SetPIP(0, 5, 0),
NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_ZONING_OUTER, STR_ZONING_OUTER_INFO), SetResize(1, 0), SetPadding(1, 6, 1, 6),
NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_ZONING_INNER, STR_ZONING_INNER_INFO), SetResize(1, 0), SetPadding(1, 6, 1, 6),
EndContainer(),
NWidget(NWID_VERTICAL, COLOUR_GREY), SetPadding(5, 0, 5, 0), SetPIP(0, 5, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, ZTW_OUTER_DROPDOWN), SetDataTip(STR_JUST_STRING1, STR_NULL), SetFill(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, ZTW_INNER_DROPDOWN), SetDataTip(STR_JUST_STRING1, STR_NULL), SetFill(1, 0),
EndContainer(),
EndContainer(),
EndContainer()
};
static WindowDesc _zoning_desc (__FILE__, __LINE__,
WDP_CENTER, "zoning_gui", 0, 0,
WC_ZONING_TOOLBAR, WC_NONE,
0,
std::begin(_nested_zoning_widgets), std::end(_nested_zoning_widgets)
);
void ShowZoningToolbar()
{
AllocateWindowDescFront(&_zoning_desc, 0);
}