Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/dialogs/GNEDialog.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2006-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file GNEDialog.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Jul 2025
17
///
18
// Custom FXDialogBox used in Netedit that supports internal tests
19
/****************************************************************************/
20
21
#include <fxkeys.h>
22
#include <netedit/GNEApplicationWindow.h>
23
#include <netedit/GNEInternalTest.h>
24
#include <utils/gui/div/GUIDesigns.h>
25
26
#include "GNEDialog.h"
27
28
// ===========================================================================
29
// FOX callback mapping
30
// ===========================================================================
31
32
FXDEFMAP(GNEDialog) MFXDialogBoxMap[] = {
33
// interaction
34
FXMAPFUNC(SEL_KEYPRESS, 0, GNEDialog::onKeyPress),
35
FXMAPFUNC(SEL_KEYRELEASE, 0, GNEDialog::onKeyRelease),
36
// buttons
37
FXMAPFUNC(SEL_COMMAND, MID_GNE_BUTTON_ACCEPT, GNEDialog::onCmdAccept),
38
FXMAPFUNC(SEL_COMMAND, MID_GNE_BUTTON_CANCEL, GNEDialog::onCmdCancel),
39
FXMAPFUNC(SEL_COMMAND, MID_GNE_BUTTON_RESET, GNEDialog::onCmdReset),
40
FXMAPFUNC(SEL_COMMAND, MID_GNE_BUTTON_RUN, GNEDialog::onCmdRun),
41
FXMAPFUNC(SEL_COMMAND, MID_GNE_BUTTON_BACK, GNEDialog::onCmdBack),
42
FXMAPFUNC(SEL_COMMAND, MID_GNE_BUTTON_ADVANCED, GNEDialog::onCmdAdvanced),
43
// abort dialog
44
FXMAPFUNC(SEL_CLOSE, 0, GNEDialog::onCmdAbort),
45
FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_ESC, GNEDialog::onCmdAbort),
46
FXMAPFUNC(SEL_CHORE, MID_GNE_ABORT, GNEDialog::onCmdAbort),
47
FXMAPFUNC(SEL_TIMEOUT, MID_GNE_ABORT, GNEDialog::onCmdAbort),
48
FXMAPFUNC(SEL_COMMAND, MID_GNE_ABORT, GNEDialog::onCmdAbort),
49
};
50
51
// Object implementation
52
FXIMPLEMENT_ABSTRACT(GNEDialog, FXDialogBox, MFXDialogBoxMap, ARRAYNUMBER(MFXDialogBoxMap))
53
54
// ===========================================================================
55
// method definitions
56
// ===========================================================================
57
58
GNEDialog::GNEDialog(GNEApplicationWindow* applicationWindow, const std::string& name,
59
GUIIcon titleIcon, DialogType type, Buttons buttons, OpenType openType,
60
ResizeMode resizeMode) :
61
FXDialogBox(applicationWindow->getApp(), name.c_str(),
62
(resizeMode == ResizeMode::STATIC) ? GUIDesignGNEDialogStatic : GUIDesignGNEDialogResizable,
63
0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
64
myApplicationWindow(applicationWindow),
65
myType(type),
66
myOpenType(openType) {
67
// build dialog
68
buildDialog(titleIcon, buttons);
69
}
70
71
72
GNEDialog::GNEDialog(GNEApplicationWindow* applicationWindow, const std::string& name,
73
GUIIcon titleIcon, DialogType type, Buttons buttons, OpenType openType,
74
ResizeMode resizeMode, const int width, const int height) :
75
FXDialogBox(applicationWindow->getApp(), name.c_str(),
76
(resizeMode == ResizeMode::STATIC) ? GUIDesignGNEDialogStaticExplicit : GUIDesignGNEDialogResizableExplicit,
77
0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
78
myApplicationWindow(applicationWindow),
79
myType(type),
80
myOpenType(openType) {
81
// build dialog
82
buildDialog(titleIcon, buttons);
83
// set explicit size
84
resize(width, height);
85
}
86
87
88
GNEDialog::Result
89
GNEDialog::getResult() const {
90
return myResult;
91
}
92
93
94
GNEApplicationWindow*
95
GNEDialog::getApplicationWindow() const {
96
return myApplicationWindow;
97
}
98
99
100
FXVerticalFrame*
101
GNEDialog::getContentFrame() const {
102
return myContentFrame;
103
}
104
105
106
long
107
GNEDialog::onCmdAccept(FXObject*, FXSelector, void*) {
108
return closeDialogAccepting();
109
}
110
111
112
long
113
GNEDialog::onCmdCancel(FXObject*, FXSelector, void*) {
114
return closeDialogCanceling();
115
}
116
117
118
long
119
GNEDialog::onCmdAbort(FXObject*, FXSelector, void*) {
120
return closeDialogAborting();
121
}
122
123
124
long
125
GNEDialog::onCmdReset(FXObject*, FXSelector, void*) {
126
throw ProcessError("onCmdReset function must be reimplemented in GNEDialog children");
127
}
128
129
130
long
131
GNEDialog::onCmdRun(FXObject*, FXSelector, void*) {
132
throw ProcessError("onCmdRun function must be reimplemented in GNEDialog children");
133
}
134
135
136
long
137
GNEDialog::onCmdBack(FXObject*, FXSelector, void*) {
138
throw ProcessError("onCmdBack function must be reimplemented in GNEDialog children");
139
}
140
141
142
long
143
GNEDialog::onCmdAdvanced(FXObject*, FXSelector, void*) {
144
throw ProcessError("onCmdAdvanced function must be reimplemented in GNEDialog children");
145
}
146
147
148
long
149
GNEDialog::onKeyPress(FXObject* obj, FXSelector sel, void* ptr) {
150
if (myTesting && (obj != myApplicationWindow->getInternalTest())) {
151
return 1;
152
} else {
153
// if ESC key is pressed, close dialog aborting
154
FXEvent* event = (FXEvent*)ptr;
155
if (event->code == KEY_Escape) {
156
return closeDialogAborting();
157
} else {
158
return FXDialogBox::onKeyPress(obj, sel, ptr);
159
}
160
}
161
}
162
163
164
long
165
GNEDialog::onKeyRelease(FXObject* obj, FXSelector sel, void* ptr) {
166
if (myTesting && (obj != myApplicationWindow->getInternalTest())) {
167
return 1;
168
} else {
169
return FXDialogBox::onKeyRelease(obj, sel, ptr);
170
}
171
}
172
173
174
void
175
GNEDialog::openDialog(FXWindow* focusableElement) {
176
// create dialog
177
create();
178
// check if set focus in button
179
if (focusableElement) {
180
focusableElement->setFocus();
181
} else {
182
myFocusButton->setFocus();
183
}
184
// show in the center of app
185
show(PLACEMENT_OWNER);
186
// continue depending on whether we are testing or not
187
const auto internalTest = myApplicationWindow->getInternalTest();
188
if (internalTest) {
189
myTesting = true;
190
bool closeDialog = false;
191
// execute every dialog step
192
while (internalTest->getCurrentStep() && !closeDialog &&
193
(internalTest->getCurrentStep()->getCategory() == InternalTestStep::Category::DIALOG) &&
194
(internalTest->getCurrentStep()->getDialogArgument()->getType() == myType)) {
195
// set next step
196
const auto testStep = internalTest->setNextStep();
197
// continue depending on the dialog argument action
198
switch (testStep->getDialogArgument()->getAction()) {
199
case InternalTestStep::DialogArgument::Action::ACCEPT:
200
onCmdAccept(internalTest, 0, nullptr);
201
closeDialog = true;
202
break;
203
case InternalTestStep::DialogArgument::Action::CANCEL:
204
onCmdCancel(internalTest, 0, nullptr);
205
closeDialog = true;
206
break;
207
case InternalTestStep::DialogArgument::Action::RESET:
208
onCmdReset(internalTest, 0, nullptr);
209
break;
210
case InternalTestStep::DialogArgument::Action::ABORT:
211
onCmdAbort(nullptr, 0, nullptr);
212
break;
213
default:
214
runInternalTest(testStep->getDialogArgument());
215
break;
216
}
217
}
218
} else {
219
myTesting = false;
220
// continue depending on the dialog type
221
if (myOpenType == OpenType::MODAL) {
222
// run modal dialog
223
getApp()->runModalFor(this);
224
}
225
}
226
}
227
228
229
long
230
GNEDialog::closeDialogAccepting() {
231
// check if stopping modal dialog
232
if (!myTesting && (myOpenType == OpenType::MODAL)) {
233
getApp()->stopModal(this, TRUE);
234
}
235
// hide dialog
236
hide();
237
// set result
238
myResult = Result::ACCEPT;
239
// restore focus to application window (to avoid problems in Linux)
240
myApplicationWindow->setFocus();
241
return 1;
242
}
243
244
245
long
246
GNEDialog::closeDialogCanceling() {
247
// check if stopping modal dialog
248
if (!myTesting && (myOpenType == OpenType::MODAL)) {
249
getApp()->stopModal(this, TRUE);
250
}
251
// hide dialog
252
hide();
253
// set result
254
myResult = Result::CANCEL;
255
// restore focus to application window (to avoid problems in Linux)
256
myApplicationWindow->setFocus();
257
return 0;
258
}
259
260
261
long
262
GNEDialog::closeDialogAborting() {
263
// check if stopping modal dialog
264
if (!myTesting && (myOpenType == OpenType::MODAL)) {
265
getApp()->stopModal(this, TRUE);
266
}
267
// hide dialog
268
hide();
269
// set result
270
myResult = Result::ABORT;
271
// restore focus to application window (to avoid problems in Linux)
272
myApplicationWindow->setFocus();
273
return 0;
274
}
275
276
277
void
278
GNEDialog::updateTitle(const std::string& newTitle) {
279
setTitle(newTitle.c_str());
280
}
281
282
283
void
284
GNEDialog::updateIcon(GUIIcon newIcon) {
285
setIcon(GUIIconSubSys::getIcon(newIcon));
286
}
287
288
289
void
290
GNEDialog::buildDialog(GUIIcon titleIcon, GNEDialog::Buttons buttons) {
291
// set dialog icon
292
setIcon(GUIIconSubSys::getIcon(titleIcon));
293
// create main frame
294
auto mainFrame = new FXVerticalFrame(this, GUIDesignAuxiliarFrame);
295
// create content frame
296
myContentFrame = new FXVerticalFrame(mainFrame, GUIDesignDialogContentFrame);
297
// add separator
298
new FXHorizontalSeparator(mainFrame, GUIDesignHorizontalSeparator);
299
// Create frame for buttons
300
FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(mainFrame, GUIDesignDialogButtonsHorizontalFrame);
301
// add horizontal frame used to center buttons horizontally
302
new FXHorizontalFrame(buttonsFrame, GUIDesignAuxiliarHorizontalFrame);
303
// create buttons according to the type
304
switch (buttons) {
305
case Buttons::OK: {
306
// ok button
307
myAcceptButton = GUIDesigns::buildFXButton(buttonsFrame, TL("OK"), "", TL("OK"),
308
GUIIconSubSys::getIcon(GUIIcon::YES), this,
309
MID_GNE_BUTTON_ACCEPT, GUIDesignButtonDialog);
310
// set focus button
311
myFocusButton = myAcceptButton;
312
break;
313
}
314
case Buttons::YES_NO: {
315
// yes button
316
myAcceptButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Yes"), "", TL("Yes"),
317
GUIIconSubSys::getIcon(GUIIcon::YES), this,
318
MID_GNE_BUTTON_ACCEPT, GUIDesignButtonDialog);
319
// no button
320
myCancelButton = GUIDesigns::buildFXButton(buttonsFrame, TL("No"), "", TL("No"),
321
GUIIconSubSys::getIcon(GUIIcon::NO), this,
322
MID_GNE_BUTTON_CANCEL, GUIDesignButtonDialog);
323
// set focus button
324
myFocusButton = myAcceptButton;
325
break;
326
}
327
case Buttons::YES_NO_CANCEL: {
328
// yes button
329
myAcceptButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Yes"), "", TL("Yes"),
330
GUIIconSubSys::getIcon(GUIIcon::YES), this,
331
MID_GNE_BUTTON_ACCEPT, GUIDesignButtonDialog);
332
// no button
333
myCancelButton = GUIDesigns::buildFXButton(buttonsFrame, TL("No"), "", TL("No"),
334
GUIIconSubSys::getIcon(GUIIcon::NO), this,
335
MID_GNE_BUTTON_CANCEL, GUIDesignButtonDialog);
336
// cancel button
337
myAbortButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Cancel"), "", TL("Cancel"),
338
GUIIconSubSys::getIcon(GUIIcon::CANCEL), this,
339
MID_GNE_ABORT, GUIDesignButtonDialog);
340
// set focus button
341
myFocusButton = myAcceptButton;
342
break;
343
}
344
case Buttons::SAVE_DONTSAVE_CANCEL: {
345
// save button
346
myAcceptButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Save"), "", TL("Save"),
347
GUIIconSubSys::getIcon(GUIIcon::SAVE), this,
348
MID_GNE_BUTTON_ACCEPT, GUIDesignButtonDialog);
349
// don't save button
350
myCancelButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Don't Save"), "", TL("Don't Save"),
351
GUIIconSubSys::getIcon(GUIIcon::NO), this,
352
MID_GNE_BUTTON_CANCEL, GUIDesignButtonDialog);
353
// cancel button
354
myAbortButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Cancel"), "", TL("Cancel"),
355
GUIIconSubSys::getIcon(GUIIcon::CANCEL), this,
356
MID_GNE_ABORT, GUIDesignButtonDialog);
357
// set focus button
358
myFocusButton = myAcceptButton;
359
break;
360
}
361
case Buttons::ACCEPT: {
362
// accept button
363
myAcceptButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Accept"), "", TL("Accept"),
364
GUIIconSubSys::getIcon(GUIIcon::YES), this,
365
MID_GNE_BUTTON_ACCEPT, GUIDesignButtonDialog);
366
// set focus button
367
myFocusButton = myAcceptButton;
368
break;
369
}
370
case Buttons::ACCEPT_CANCEL: {
371
// accept button
372
myAcceptButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Accept"), "", TL("Accept"),
373
GUIIconSubSys::getIcon(GUIIcon::YES), this,
374
MID_GNE_BUTTON_ACCEPT, GUIDesignButtonDialog);
375
// cancel button
376
myCancelButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Cancel"), "", TL("Cancel"),
377
GUIIconSubSys::getIcon(GUIIcon::NO), this,
378
MID_GNE_BUTTON_CANCEL, GUIDesignButtonDialog);
379
// set focus button
380
myFocusButton = myAcceptButton;
381
break;
382
}
383
case Buttons::ACCEPT_CANCEL_RESET: {
384
// accept button
385
myAcceptButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Accept"), "", TL("Accept"),
386
GUIIconSubSys::getIcon(GUIIcon::YES), this,
387
MID_GNE_BUTTON_ACCEPT, GUIDesignButtonDialog);
388
// cancel button
389
myCancelButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Cancel"), "", TL("Cancel"),
390
GUIIconSubSys::getIcon(GUIIcon::NO), this,
391
MID_GNE_BUTTON_CANCEL, GUIDesignButtonDialog);
392
// reset button
393
myResetButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Reset"), "", TL("Reset changes"),
394
GUIIconSubSys::getIcon(GUIIcon::RESET), this,
395
MID_GNE_BUTTON_RESET, GUIDesignButtonDialog);
396
// set focus button
397
myFocusButton = myAcceptButton;
398
break;
399
}
400
case Buttons::RUN_CANCEL_RESET: {
401
// run button
402
myRunButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Run"), "", TL("Run"),
403
GUIIconSubSys::getIcon(GUIIcon::START), this,
404
MID_GNE_BUTTON_RUN, GUIDesignButtonDialog);
405
// reset button
406
myCancelButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Cancel"), "", TL("Cancel"),
407
GUIIconSubSys::getIcon(GUIIcon::NO), this,
408
MID_GNE_BUTTON_CANCEL, GUIDesignButtonDialog);
409
// reset button
410
myResetButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Reset"), "", TL("Reset changes"),
411
GUIIconSubSys::getIcon(GUIIcon::RESET), this,
412
MID_GNE_BUTTON_RESET, GUIDesignButtonDialog);
413
// set focus button
414
myFocusButton = myRunButton;
415
break;
416
}
417
case Buttons::RUN_ADVANCED_CANCEL: {
418
// run button
419
myRunButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Run"), "", TL("Run"),
420
GUIIconSubSys::getIcon(GUIIcon::START), this,
421
MID_GNE_BUTTON_RUN, GUIDesignButtonDialog);
422
// cancel button
423
myAdvancedButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Advanced"), "", TL("Advanced options"),
424
GUIIconSubSys::getIcon(GUIIcon::OPTIONS), this,
425
MID_GNE_BUTTON_ADVANCED, GUIDesignButtonDialog);
426
// cancel button
427
myCancelButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Cancel"), "", TL("Cancel"),
428
GUIIconSubSys::getIcon(GUIIcon::CANCEL), this,
429
MID_GNE_BUTTON_CANCEL, GUIDesignButtonDialog);
430
// set focus button
431
myFocusButton = myRunButton;
432
break;
433
}
434
case Buttons::RERUN_BACK_CLOSE: {
435
// run/abort button
436
myRunButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Rerun"), "", TL("Rerun tool"),
437
GUIIconSubSys::getIcon(GUIIcon::RESET), this,
438
MID_GNE_BUTTON_RUN, GUIDesignButtonDialog);
439
// back button
440
myBackButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Back"), "", TL("Back to tool dialog"),
441
GUIIconSubSys::getIcon(GUIIcon::BACK), this,
442
MID_GNE_BUTTON_BACK, GUIDesignButtonDialog);
443
// cancel button
444
myAcceptButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Close"), "", TL("Close"),
445
GUIIconSubSys::getIcon(GUIIcon::YES), this,
446
MID_GNE_BUTTON_ACCEPT, GUIDesignButtonDialog);
447
// set focus button
448
myFocusButton = myAcceptButton;
449
break;
450
}
451
default:
452
throw ProcessError("Invalid buttons combination in GNEDialog");
453
}
454
// add horizontal frame used to center buttons horizontally
455
new FXHorizontalFrame(buttonsFrame, GUIDesignAuxiliarHorizontalFrame);
456
}
457
458