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
)
69 uint32 p1
= 0, p2
= 0;
72 SB(p1
, 0, 3, program
->track
);
75 case WID_PROGSIG_OWN_DEFAULT_COLOR_RED
:
76 if (this->program
->own_default_state
!= SIGNAL_STATE_RED
) {
78 SB(p1
, 6, 2, SIGNAL_STATE_RED
);
82 case WID_PROGSIG_OWN_DEFAULT_COLOR_GREEN
:
83 if (this->program
->own_default_state
!= SIGNAL_STATE_GREEN
) {
85 SB(p1
, 6, 2, SIGNAL_STATE_GREEN
);
89 case WID_PROGSIG_TRIGGER_COLOR_RED
:
90 if (this->program
->trigger_state
!= SIGNAL_STATE_RED
) {
92 SB(p1
, 6, 2, SIGNAL_STATE_RED
);
96 case WID_PROGSIG_TRIGGER_COLOR_GREEN
:
97 if (this->program
->trigger_state
!= SIGNAL_STATE_GREEN
) {
99 SB(p1
, 6, 2, SIGNAL_STATE_GREEN
);
103 case WID_PROGSIG_OPERATOR_OR
:
104 if (this->program
->signal_op
!= SIGNAL_OP_OR
) {
106 SB(p1
, 6, 2, SIGNAL_OP_OR
);
110 case WID_PROGSIG_OPERATOR_AND
:
111 if (this->program
->signal_op
!= SIGNAL_OP_AND
) {
113 SB(p1
, 6, 2, SIGNAL_OP_AND
);
117 case WID_PROGSIG_OPERATOR_NAND
:
118 if (this->program
->signal_op
!= SIGNAL_OP_NAND
) {
120 SB(p1
, 6, 2, SIGNAL_OP_NAND
);
124 case WID_PROGSIG_OPERATOR_XOR
:
125 if (this->program
->signal_op
!= SIGNAL_OP_XOR
) {
127 SB(p1
, 6, 2, SIGNAL_OP_XOR
);
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);
137 ResetObjectToPlace();
140 case WID_PROGSIG_CLEAR_LINKS
:
141 if (this->program
->LinkCount() > 0) {
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
188 case WID_PROGSIG_LINK_COUNT
:
189 SetDParam(0, program
->LinkCount());
195 * Executed whenever user tries to link two signals together
197 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
201 SB(p1
, 0, 3, this->program
->track
);
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
),
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
),
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
),
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
),
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
),
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
),
257 static WindowDesc
_signal_program_desc (
258 WDP_AUTO
, nullptr, 0, 0,
259 WC_SIGNAL_PROGRAM
, WC_NONE
,
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
) != nullptr) return;
274 new SignalProgramWindow(&_signal_program_desc
, wnum
, program
);