Fix some daylength issues, possible division by zero in main menu.
[openttd-joker.git] / src / logic_signals_gui.cpp
blob4b9e259fa4e3ee9a8c89b2da54b5d7977a96c848
1 /*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 <http://www.gnu.org/licenses/>.
6 */
8 /** @file logic_signals_gui.cpp A Window for editing signal programs. */
10 #include "logic_signals.h"
11 #include "window_type.h"
12 #include "window_gui.h"
13 #include "table/strings.h"
14 #include "command_func.h"
15 #include "tilehighlight_func.h"
16 #include "table/sprites.h"
17 #include "rail_map.h"
18 #include "strings_func.h"
19 #include "overlay_cmd.h"
21 /**
22 * Definition of widgets
24 enum ProgramSignalWidgets {
25 WID_PROGSIG_OWN_DEFAULT_COLOR_RED,
26 WID_PROGSIG_OWN_DEFAULT_COLOR_GREEN,
27 WID_PROGSIG_TRIGGER_COLOR_RED,
28 WID_PROGSIG_TRIGGER_COLOR_GREEN,
29 WID_PROGSIG_OPERATOR_OR,
30 WID_PROGSIG_OPERATOR_AND,
31 WID_PROGSIG_OPERATOR_NAND,
32 WID_PROGSIG_OPERATOR_XOR,
33 WID_PROGSIG_LINK_COUNT,
34 WID_PROGSIG_ADD_LINK,
35 WID_PROGSIG_CLEAR_LINKS
38 /**
39 * The Window used for editing signal programs of logic signals.
41 struct SignalProgramWindow : Window
43 SignalProgram *program;
44 bool add_link_button;
46 /**
47 * Constructor
49 SignalProgramWindow(WindowDesc *desc, WindowNumber window_number, SignalProgram *prog) : Window(desc)
51 this->program = prog;
52 this->add_link_button = false;
53 this->InitNested(window_number);
54 this->OnInvalidateData();
57 ~SignalProgramWindow()
59 if (_focused_window == this) {
60 Overlays::Instance()->ClearLogicSignalOverlay();
64 /**
65 * Handler which is executed whenever user clicks on the window.
67 virtual void OnClick(Point pt, int widget, int click_count)
69 uint32 p1 = 0, p2 = 0;
70 bool changed = false;
72 SB(p1, 0, 3, program->track);
74 switch (widget) {
75 case WID_PROGSIG_OWN_DEFAULT_COLOR_RED:
76 if (this->program->own_default_state != SIGNAL_STATE_RED) {
77 SB(p1, 3, 3, 1);
78 SB(p1, 6, 2, SIGNAL_STATE_RED);
79 changed = true;
81 break;
82 case WID_PROGSIG_OWN_DEFAULT_COLOR_GREEN:
83 if (this->program->own_default_state != SIGNAL_STATE_GREEN) {
84 SB(p1, 3, 3, 1);
85 SB(p1, 6, 2, SIGNAL_STATE_GREEN);
86 changed = true;
88 break;
89 case WID_PROGSIG_TRIGGER_COLOR_RED:
90 if (this->program->trigger_state != SIGNAL_STATE_RED) {
91 SB(p1, 3, 3, 2);
92 SB(p1, 6, 2, SIGNAL_STATE_RED);
93 changed = true;
95 break;
96 case WID_PROGSIG_TRIGGER_COLOR_GREEN:
97 if (this->program->trigger_state != SIGNAL_STATE_GREEN) {
98 SB(p1, 3, 3, 2);
99 SB(p1, 6, 2, SIGNAL_STATE_GREEN);
100 changed = true;
102 break;
103 case WID_PROGSIG_OPERATOR_OR:
104 if (this->program->signal_op != SIGNAL_OP_OR) {
105 SB(p1, 3, 3, 3);
106 SB(p1, 6, 2, SIGNAL_OP_OR);
107 changed = true;
109 break;
110 case WID_PROGSIG_OPERATOR_AND:
111 if (this->program->signal_op != SIGNAL_OP_AND) {
112 SB(p1, 3, 3, 3);
113 SB(p1, 6, 2, SIGNAL_OP_AND);
114 changed = true;
116 break;
117 case WID_PROGSIG_OPERATOR_NAND:
118 if (this->program->signal_op != SIGNAL_OP_NAND) {
119 SB(p1, 3, 3, 3);
120 SB(p1, 6, 2, SIGNAL_OP_NAND);
121 changed = true;
123 break;
124 case WID_PROGSIG_OPERATOR_XOR:
125 if (this->program->signal_op != SIGNAL_OP_XOR) {
126 SB(p1, 3, 3, 3);
127 SB(p1, 6, 2, SIGNAL_OP_XOR);
128 changed = true;
130 break;
131 case WID_PROGSIG_ADD_LINK:
132 SetWidgetDirty(WID_PROGSIG_ADD_LINK);
133 ToggleWidgetLoweredState(WID_PROGSIG_ADD_LINK);
134 if (IsWidgetLowered(WID_PROGSIG_ADD_LINK)) {
135 SetObjectToPlaceWnd(SPR_CURSOR_TRANSMITTER, PAL_NONE, HT_RECT, this);
136 } else {
137 ResetObjectToPlace();
139 break;
140 case WID_PROGSIG_CLEAR_LINKS:
141 if (this->program->LinkCount() > 0) {
142 SB(p1, 3, 2, 5);
143 changed = true;
145 break;
148 if (changed) DoCommandP(program->tile, p1, p2, CMD_PROGRAM_LOGIC_SIGNAL | CMD_MSG(STR_ERROR_PROGRAM_SIGNAL_HEADER));
151 virtual void OnFocus(Window *previously_focused_window) override
153 if (this != previously_focused_window) {
154 Overlays::Instance()->SetLogicSignalOverlay(this->program);
158 virtual void OnFocusLost(Window *newly_focused_window) override
160 if (newly_focused_window != nullptr && newly_focused_window->window_class != WC_SIGNAL_PROGRAM) {
161 Overlays::Instance()->ClearLogicSignalOverlay();
166 * Handler which is executed whenever data has become invalid on the window.
168 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
170 if (!gui_scope) return;
172 this->SetWidgetLoweredState(WID_PROGSIG_OWN_DEFAULT_COLOR_RED, this->program->own_default_state == SIGNAL_STATE_RED);
173 this->SetWidgetLoweredState(WID_PROGSIG_OWN_DEFAULT_COLOR_GREEN, this->program->own_default_state == SIGNAL_STATE_GREEN);
174 this->SetWidgetLoweredState(WID_PROGSIG_TRIGGER_COLOR_RED, this->program->trigger_state == SIGNAL_STATE_RED);
175 this->SetWidgetLoweredState(WID_PROGSIG_TRIGGER_COLOR_GREEN, this->program->trigger_state == SIGNAL_STATE_GREEN);
176 this->SetWidgetLoweredState(WID_PROGSIG_OPERATOR_OR, this->program->signal_op == SIGNAL_OP_OR);
177 this->SetWidgetLoweredState(WID_PROGSIG_OPERATOR_AND, this->program->signal_op == SIGNAL_OP_AND);
178 this->SetWidgetLoweredState(WID_PROGSIG_OPERATOR_NAND, this->program->signal_op == SIGNAL_OP_NAND);
179 this->SetWidgetLoweredState(WID_PROGSIG_OPERATOR_XOR, this->program->signal_op == SIGNAL_OP_XOR);
183 * Used to set dynamic string parameters to the widget.
185 virtual void SetStringParameters(int widget) const
187 switch (widget) {
188 case WID_PROGSIG_LINK_COUNT:
189 SetDParam(0, program->LinkCount());
190 break;
195 * Executed whenever user tries to link two signals together
197 virtual void OnPlaceObject(Point pt, TileIndex tile)
199 uint32 p1 = 0;
201 SB(p1, 0, 3, this->program->track);
202 SB(p1, 3, 3, 4);
204 DoCommandP(this->program->tile, p1, tile, CMD_PROGRAM_LOGIC_SIGNAL | CMD_MSG(STR_ERROR_LINK_SIGNAL_HEADER));
208 * Executed when user aborts the linking of signals
210 virtual void OnPlaceObjectAbort()
212 SetWidgetLoweredState(WID_PROGSIG_ADD_LINK, false);
213 SetWidgetDirty(WID_PROGSIG_ADD_LINK);
218 * Widget structure definition for programmable signals
220 static const NWidgetPart _nested_program_widgets[] = {
221 NWidget(NWID_HORIZONTAL),
222 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
223 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_PROGSIG_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
224 NWidget(WWT_SHADEBOX, COLOUR_GREY),
225 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
226 NWidget(WWT_STICKYBOX, COLOUR_GREY),
227 EndContainer(),
228 NWidget(WWT_PANEL, COLOUR_GREY),
229 NWidget(NWID_HORIZONTAL), SetPIP(3, 0, 0),
230 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(200, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OWN_DEFAULT_COLOR, STR_PROGSIG_OWN_DEFAULT_COLOR_TOOLTIP),
231 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_OWN_DEFAULT_COLOR_RED), SetMinimalSize(80, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_COLOR_RED, STR_PROGSIG_OWN_DEFAULT_COLOR_TOOLTIP),
232 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_OWN_DEFAULT_COLOR_GREEN), SetMinimalSize(80, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_COLOR_GREEN, STR_PROGSIG_OWN_DEFAULT_COLOR_TOOLTIP),
233 EndContainer(),
234 NWidget(NWID_HORIZONTAL), SetPIP(3, 0, 0),
235 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(200, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_TRIGGER_COLOR, STR_PROGSIG_TRIGGER_COLOR_TOOLTIP),
236 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_TRIGGER_COLOR_RED), SetMinimalSize(80, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_COLOR_RED, STR_PROGSIG_TRIGGER_COLOR_TOOLTIP),
237 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_TRIGGER_COLOR_GREEN), SetMinimalSize(80, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_COLOR_GREEN, STR_PROGSIG_TRIGGER_COLOR_TOOLTIP),
238 EndContainer(),
239 NWidget(NWID_HORIZONTAL), SetPIP(3, 0, 0),
240 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(200, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OPERATOR, STR_PROGSIG_OPERATOR_TOOLTIP),
241 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_OPERATOR_OR), SetMinimalSize(40, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OP_OR, STR_PROGSIG_OPERATOR_TOOLTIP),
242 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_OPERATOR_AND), SetMinimalSize(40, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OP_AND, STR_PROGSIG_OPERATOR_TOOLTIP),
243 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_OPERATOR_XOR), SetMinimalSize(40, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OP_XOR, STR_PROGSIG_OPERATOR_TOOLTIP),
244 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_OPERATOR_NAND), SetMinimalSize(40, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OP_NAND, STR_PROGSIG_OPERATOR_TOOLTIP),
245 EndContainer(),
246 NWidget(NWID_HORIZONTAL), SetPIP(3, 0, 0),
247 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(200, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_LINKED_SIGNALS, STR_PROGSIG_LINKED_SIGNALS_TOOLTIP),
248 NWidget(WWT_TEXT, COLOUR_ORANGE, WID_PROGSIG_LINK_COUNT), SetMinimalSize(160, 14), SetFill(1, 0), SetDataTip(STR_JUST_INT, STR_PROGSIG_LINKED_SIGNALS_TOOLTIP),
249 EndContainer(),
250 EndContainer(),
251 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
252 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_PROGSIG_ADD_LINK), SetFill(1, 0), SetDataTip(STR_PROGSIG_ADD_LINK, STR_PROGSIG_ADD_LINK_TOOLTIP),
253 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PROGSIG_CLEAR_LINKS), SetFill(1, 0), SetDataTip(STR_PROGSIG_CLEAR_LINKS, STR_PROGSIG_CLEAR_LINKS_TOOLTIP),
254 EndContainer(),
257 static WindowDesc _signal_program_desc (
258 WDP_AUTO, NULL, 0, 0,
259 WC_SIGNAL_PROGRAM, WC_NONE,
260 WDF_CONSTRUCTION,
261 _nested_program_widgets, lengthof(_nested_program_widgets)
265 * Displays a signal program window.
266 * @param program The target signal program which this window modifies.
268 void ShowSignalProgramWindow(SignalProgram *program)
270 WindowNumber wnum = GetSignalReference(program->tile, program->track);
272 if (BringWindowToFrontById(WC_SIGNAL_PROGRAM, wnum) != NULL) return;
274 new SignalProgramWindow(&_signal_program_desc, wnum, program);