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/>.
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"
18 #include "strings_func.h"
19 #include "overlay_cmd.h"
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
,
35 WID_PROGSIG_CLEAR_LINKS
39 * The Window used for editing signal programs of logic signals.
41 struct SignalProgramWindow
: Window
43 SignalProgram
*program
;
49 SignalProgramWindow(WindowDesc
*desc
, WindowNumber window_number
, SignalProgram
*prog
) : Window(desc
)
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();
65 * Handler which is executed whenever user clicks on the window.
67 virtual void OnClick(Point pt
, int widget
, int click_count
)
73 SB(p1
, 0, 3, program
->track
);
76 case WID_PROGSIG_OWN_DEFAULT_COLOR_RED
:
77 if (this->program
->own_default_state
!= SIGNAL_STATE_RED
) {
79 SB(p1
, 6, 2, SIGNAL_STATE_RED
);
83 case WID_PROGSIG_OWN_DEFAULT_COLOR_GREEN
:
84 if (this->program
->own_default_state
!= SIGNAL_STATE_GREEN
) {
86 SB(p1
, 6, 2, SIGNAL_STATE_GREEN
);
90 case WID_PROGSIG_TRIGGER_COLOR_RED
:
91 if (this->program
->trigger_state
!= SIGNAL_STATE_RED
) {
93 SB(p1
, 6, 2, SIGNAL_STATE_RED
);
97 case WID_PROGSIG_TRIGGER_COLOR_GREEN
:
98 if (this->program
->trigger_state
!= SIGNAL_STATE_GREEN
) {
100 SB(p1
, 6, 2, SIGNAL_STATE_GREEN
);
104 case WID_PROGSIG_OPERATOR_OR
:
105 if (this->program
->signal_op
!= SIGNAL_OP_OR
) {
107 SB(p1
, 6, 2, SIGNAL_OP_OR
);
111 case WID_PROGSIG_OPERATOR_AND
:
112 if (this->program
->signal_op
!= SIGNAL_OP_AND
) {
114 SB(p1
, 6, 2, SIGNAL_OP_AND
);
118 case WID_PROGSIG_OPERATOR_NAND
:
119 if (this->program
->signal_op
!= SIGNAL_OP_NAND
) {
121 SB(p1
, 6, 2, SIGNAL_OP_NAND
);
125 case WID_PROGSIG_OPERATOR_XOR
:
126 if (this->program
->signal_op
!= SIGNAL_OP_XOR
) {
128 SB(p1
, 6, 2, SIGNAL_OP_XOR
);
132 case WID_PROGSIG_ADD_LINK
:
133 SetWidgetDirty(WID_PROGSIG_ADD_LINK
);
134 ToggleWidgetLoweredState(WID_PROGSIG_ADD_LINK
);
135 if (IsWidgetLowered(WID_PROGSIG_ADD_LINK
)) {
136 SetObjectToPlaceWnd(SPR_CURSOR_TRANSMITTER
, PAL_NONE
, HT_RECT
, this);
138 ResetObjectToPlace();
141 case WID_PROGSIG_CLEAR_LINKS
:
142 if (this->program
->LinkCount() > 0) {
149 if (changed
) DoCommandP(program
->tile
, p1
, p2
, CMD_PROGRAM_LOGIC_SIGNAL
| CMD_MSG(STR_ERROR_PROGRAM_SIGNAL_HEADER
));
152 virtual void OnFocus(Window
*previously_focused_window
) override
154 if (this != previously_focused_window
) {
155 Overlays::Instance()->SetLogicSignalOverlay(this->program
);
159 virtual void OnFocusLost(Window
*newly_focused_window
) override
161 if (newly_focused_window
!= nullptr && newly_focused_window
->window_class
!= WC_SIGNAL_PROGRAM
) {
162 Overlays::Instance()->ClearLogicSignalOverlay();
167 * Handler which is executed whenever data has become invalid on the window.
169 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
171 if (!gui_scope
) return;
173 this->SetWidgetLoweredState(WID_PROGSIG_OWN_DEFAULT_COLOR_RED
, this->program
->own_default_state
== SIGNAL_STATE_RED
);
174 this->SetWidgetLoweredState(WID_PROGSIG_OWN_DEFAULT_COLOR_GREEN
, this->program
->own_default_state
== SIGNAL_STATE_GREEN
);
175 this->SetWidgetLoweredState(WID_PROGSIG_TRIGGER_COLOR_RED
, this->program
->trigger_state
== SIGNAL_STATE_RED
);
176 this->SetWidgetLoweredState(WID_PROGSIG_TRIGGER_COLOR_GREEN
, this->program
->trigger_state
== SIGNAL_STATE_GREEN
);
177 this->SetWidgetLoweredState(WID_PROGSIG_OPERATOR_OR
, this->program
->signal_op
== SIGNAL_OP_OR
);
178 this->SetWidgetLoweredState(WID_PROGSIG_OPERATOR_AND
, this->program
->signal_op
== SIGNAL_OP_AND
);
179 this->SetWidgetLoweredState(WID_PROGSIG_OPERATOR_NAND
, this->program
->signal_op
== SIGNAL_OP_NAND
);
180 this->SetWidgetLoweredState(WID_PROGSIG_OPERATOR_XOR
, this->program
->signal_op
== SIGNAL_OP_XOR
);
184 * Used to set dynamic string parameters to the widget.
186 virtual void SetStringParameters(int widget
) const
189 case WID_PROGSIG_LINK_COUNT
:
190 SetDParam(0, program
->LinkCount());
196 * Executed whenever user tries to link two signals together
198 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
202 SB(p1
, 0, 3, this->program
->track
);
205 DoCommandP(this->program
->tile
, p1
, tile
, CMD_PROGRAM_LOGIC_SIGNAL
| CMD_MSG(STR_ERROR_LINK_SIGNAL_HEADER
));
209 * Executed when user aborts the linking of signals
211 virtual void OnPlaceObjectAbort()
213 SetWidgetLoweredState(WID_PROGSIG_ADD_LINK
, false);
214 SetWidgetDirty(WID_PROGSIG_ADD_LINK
);
219 * Widget structure definition for programmable signals
221 static const NWidgetPart _nested_program_widgets
[] = {
222 NWidget(NWID_HORIZONTAL
),
223 NWidget(WWT_CLOSEBOX
, COLOUR_GREY
),
224 NWidget(WWT_CAPTION
, COLOUR_GREY
), SetDataTip(STR_PROGSIG_CAPTION
, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS
),
225 NWidget(WWT_SHADEBOX
, COLOUR_GREY
),
226 NWidget(WWT_DEFSIZEBOX
, COLOUR_GREY
),
227 NWidget(WWT_STICKYBOX
, COLOUR_GREY
),
229 NWidget(WWT_PANEL
, COLOUR_GREY
),
230 NWidget(NWID_HORIZONTAL
), SetPIP(3, 0, 0),
231 NWidget(WWT_TEXT
, COLOUR_GREY
), SetMinimalSize(200, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OWN_DEFAULT_COLOR
, STR_PROGSIG_OWN_DEFAULT_COLOR_TOOLTIP
),
232 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
),
233 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
),
235 NWidget(NWID_HORIZONTAL
), SetPIP(3, 0, 0),
236 NWidget(WWT_TEXT
, COLOUR_GREY
), SetMinimalSize(200, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_TRIGGER_COLOR
, STR_PROGSIG_TRIGGER_COLOR_TOOLTIP
),
237 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
),
238 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
),
240 NWidget(NWID_HORIZONTAL
), SetPIP(3, 0, 0),
241 NWidget(WWT_TEXT
, COLOUR_GREY
), SetMinimalSize(200, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OPERATOR
, STR_PROGSIG_OPERATOR_TOOLTIP
),
242 NWidget(WWT_TEXTBTN
, COLOUR_GREY
, WID_PROGSIG_OPERATOR_OR
), SetMinimalSize(40, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OP_OR
, STR_PROGSIG_OPERATOR_TOOLTIP
),
243 NWidget(WWT_TEXTBTN
, COLOUR_GREY
, WID_PROGSIG_OPERATOR_AND
), SetMinimalSize(40, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OP_AND
, STR_PROGSIG_OPERATOR_TOOLTIP
),
244 NWidget(WWT_TEXTBTN
, COLOUR_GREY
, WID_PROGSIG_OPERATOR_XOR
), SetMinimalSize(40, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OP_XOR
, STR_PROGSIG_OPERATOR_TOOLTIP
),
245 NWidget(WWT_TEXTBTN
, COLOUR_GREY
, WID_PROGSIG_OPERATOR_NAND
), SetMinimalSize(40, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_OP_NAND
, STR_PROGSIG_OPERATOR_TOOLTIP
),
247 NWidget(NWID_HORIZONTAL
), SetPIP(3, 0, 0),
248 NWidget(WWT_TEXT
, COLOUR_GREY
), SetMinimalSize(200, 14), SetFill(1, 0), SetDataTip(STR_PROGSIG_LINKED_SIGNALS
, STR_PROGSIG_LINKED_SIGNALS_TOOLTIP
),
249 NWidget(WWT_TEXT
, COLOUR_ORANGE
, WID_PROGSIG_LINK_COUNT
), SetMinimalSize(160, 14), SetFill(1, 0), SetDataTip(STR_JUST_INT
, STR_PROGSIG_LINKED_SIGNALS_TOOLTIP
),
252 NWidget(NWID_HORIZONTAL
, NC_EQUALSIZE
),
253 NWidget(WWT_TEXTBTN
, COLOUR_GREY
, WID_PROGSIG_ADD_LINK
), SetFill(1, 0), SetDataTip(STR_PROGSIG_ADD_LINK
, STR_PROGSIG_ADD_LINK_TOOLTIP
),
254 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, WID_PROGSIG_CLEAR_LINKS
), SetFill(1, 0), SetDataTip(STR_PROGSIG_CLEAR_LINKS
, STR_PROGSIG_CLEAR_LINKS_TOOLTIP
),
258 static WindowDesc
_signal_program_desc (
259 WDP_AUTO
, nullptr, 0, 0,
260 WC_SIGNAL_PROGRAM
, WC_NONE
,
262 _nested_program_widgets
, lengthof(_nested_program_widgets
)
266 * Displays a signal program window.
267 * @param program The target signal program which this window modifies.
269 void ShowSignalProgramWindow(SignalProgram
*program
)
271 WindowNumber wnum
= GetSignalReference(program
->tile
, program
->track
);
273 if (BringWindowToFrontById(WC_SIGNAL_PROGRAM
, wnum
) != nullptr) return;
275 new SignalProgramWindow(&_signal_program_desc
, wnum
, program
);