Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/dialogs/fix/GNEFixElementsDialog.h
193674 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2026 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 GNEFixElementsDialog.h
15
/// @author Pablo Alvarez Lopez
16
/// @date Jul 2025
17
///
18
// template used to fix elements during saving
19
/****************************************************************************/
20
#pragma once
21
#include <config.h>
22
23
#include <netedit/dialogs/basic/GNEErrorBasicDialog.h>
24
#include <netedit/dialogs/basic/GNEInformationBasicDialog.h>
25
#include <netedit/frames/common/GNEGroupBoxModule.h>
26
#include <utils/gui/div/GUIDesigns.h>
27
#include <utils/gui/windows/GUIAppEnum.h>
28
29
// ===========================================================================
30
// class definitions
31
// ===========================================================================
32
33
template <typename T>
34
class GNEFixElementsDialog : public GNEDialog {
35
36
public:
37
/// @brief Conflict
38
class ConflictElement {
39
40
public:
41
/// @brief constructor
42
ConflictElement(T element, const std::string& id, FXIcon* icon, const std::string& description) :
43
myElement(element),
44
myID(id),
45
myIcon(icon),
46
myDescription(description) {}
47
48
/// @brief destructor
49
~ConflictElement() {}
50
51
/// @brief conflicted element
52
T getElement() const {
53
return myElement;
54
}
55
56
/// @brief get element ID
57
const std::string& getID() const {
58
return myID;
59
}
60
61
/// @brief get element icon
62
FXIcon* getIcon() const {
63
return myIcon;
64
}
65
66
/// @brief get conflict description
67
const std::string& getDescription() const {
68
return myDescription;
69
}
70
71
private:
72
/// @brief conflicted element
73
T myElement;
74
75
/// @brief ID of the element
76
std::string myID;
77
78
/// @brief icon
79
FXIcon* myIcon = nullptr;
80
81
/// @brief conflict description
82
std::string myDescription;
83
84
/// @brief invalidate default constructor
85
ConflictElement() = delete;
86
};
87
88
/// @brief GNEFixOptions module
89
class FixOptions : public GNEGroupBoxModule {
90
91
public:
92
/// @brief constructor
93
FixOptions(GNEFixElementsDialog<T>* fixElementDialog, FXVerticalFrame* frameParent, const std::string& title) :
94
GNEGroupBoxModule(frameParent, title, GNEGroupBoxModule::Options::SAVE),
95
myFixElementDialogParent(fixElementDialog) {
96
// register this fix option to list of fix options
97
fixElementDialog->registerFixOptions(this);
98
// Create table
99
myTable = new FXTable(getCollapsableFrame(), this, MID_TABLE, GUIDesignTableFixElements);
100
// create frames for options
101
FXHorizontalFrame* optionsFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
102
myLeftFrameOptions = new FXVerticalFrame(optionsFrame, GUIDesignAuxiliarFrameFixedWidth(int(myTable->getWidth() * 0.5)));
103
myRightFrameOptions = new FXVerticalFrame(optionsFrame, GUIDesignAuxiliarFrameFixedWidth(int(myTable->getWidth() * 0.5)));
104
}
105
106
/// @brief select internal test solution (used in internal tests)
107
virtual void selectInternalTestSolution(const std::string& solution) = 0;
108
109
/// @brief apply selected fix option
110
virtual bool applyFixOption() = 0;
111
112
/// @name FOX-callbacks
113
/// @{
114
115
/// @brief called when user select a option
116
virtual long onCmdSelectOption(FXObject*, FXSelector, void*) = 0;
117
118
/// @}
119
120
/// @brief set invalid elements to fix
121
void setInvalidElements(const std::vector<ConflictElement>& conflictedElements) {
122
// parse invalid elements
123
myConflictedElements = conflictedElements;
124
// configure table
125
myTable->setTableSize((int)(myConflictedElements.size()), 3);
126
myTable->setSelBackColor(FXRGBA(255, 255, 255, 255));
127
myTable->setSelTextColor(FXRGBA(0, 0, 0, 255));
128
myTable->setEditable(false);
129
// configure header
130
myTable->setVisibleColumns(4);
131
myTable->setColumnHeaderHeight(GUIDesignHeight);
132
myTable->getRowHeader()->setWidth(0);
133
// icon
134
myTable->setColumnWidth(0, GUIDesignHeight);
135
myTable->setColumnText(0, "");
136
// ID
137
myTable->setColumnWidth(1, 110);
138
myTable->setColumnText(1, toString(SUMO_ATTR_ID).c_str());
139
// description
140
myTable->setColumnWidth(2, myTable->getWidth() - GUIDesignHeight - 110 - 15);
141
myTable->setColumnText(2, TL("Conflict"));
142
// Declare pointer to FXTableItem
143
FXTableItem* item = nullptr;
144
// iterate over invalid edges
145
for (int i = 0; i < (int)myConflictedElements.size(); i++) {
146
// Set icon
147
item = new FXTableItem("", myConflictedElements.at(i).getIcon());
148
item->setIconPosition(FXTableItem::CENTER_X);
149
myTable->setItem(i, 0, item);
150
// Set ID
151
item = new FXTableItem(myConflictedElements.at(i).getID().c_str());
152
item->setJustify(FXTableItem::LEFT | FXTableItem::CENTER_Y);
153
myTable->setItem(i, 1, item);
154
// Set conflict
155
item = new FXTableItem(myConflictedElements.at(i).getDescription().c_str());
156
item->setJustify(FXTableItem::LEFT | FXTableItem::CENTER_Y);
157
myTable->setItem(i, 2, item);
158
// set row height
159
myTable->setRowHeight(i, GUIDesignHeight);
160
}
161
// check if enable or disable options
162
if (myConflictedElements.size() > 0) {
163
enableOptions();
164
} else {
165
disableOptions();
166
}
167
}
168
169
protected:
170
/// @brief pointer to the parent dialog
171
GNEFixElementsDialog* myFixElementDialogParent = nullptr;
172
173
/// @brief Table with the demand elements
174
FXTable* myTable = nullptr;
175
176
/// @brief vertical left frame for options
177
FXVerticalFrame* myLeftFrameOptions = nullptr;
178
179
/// @brief vertical right frame for options
180
FXVerticalFrame* myRightFrameOptions = nullptr;
181
182
/// @brief list of elements to fix
183
std::vector<ConflictElement> myConflictedElements;
184
185
/// @brief default constructor
186
FixOptions() :
187
GNEGroupBoxModule() {
188
}
189
190
/// @brief add option to options container (used for adjust width and enable/disable)
191
void registerOption(FXWindow* option) {
192
myOptions.push_back(option);
193
// adjust width
194
option->setWidth(int(myTable->getWidth() * 0.5));
195
}
196
197
private:
198
/// @brief list of options
199
std::vector<FXWindow*> myOptions;
200
201
/// @brief enable options
202
void enableOptions() {
203
// enable each option
204
for (auto option : myOptions) {
205
option->enable();
206
}
207
}
208
209
/// @brief disable options
210
void disableOptions() {
211
// disable each option
212
for (auto option : myOptions) {
213
option->disable();
214
}
215
}
216
217
/// @brief save save list of conflicted items to a file (Reimplemented from GNEGroupBoxModule)
218
bool saveContents() const {
219
// open file dialog to save list of conflicted items
220
const FXString file = MFXUtils::getFilename2Write(myTable,
221
TL("Save list of conflicted items"),
222
SUMOXMLDefinitions::TXTFileExtensions.getMultilineString().c_str(),
223
GUIIconSubSys::getIcon(GUIIcon::SAVE), gCurrentFolder);
224
// continue if file is not empty
225
if (file == "") {
226
return false;
227
} else {
228
try {
229
// open output device
230
OutputDevice& device = OutputDevice::getDevice(file.text());
231
// get invalid element ID and problem
232
for (const auto& conflictedElement : myConflictedElements) {
233
device << conflictedElement.getID() << ":" << conflictedElement.getDescription() << "\n";
234
}
235
// close output device
236
device.close();
237
// open information message box
238
GNEInformationBasicDialog(myFixElementDialogParent->myApplicationWindow, myFixElementDialogParent,
239
TL("Saving successfully"),
240
TL("List of conflicted items was successfully saved"));
241
return true;
242
} catch (IOError& e) {
243
// open message box error
244
GNEErrorBasicDialog(myFixElementDialogParent->myApplicationWindow, myFixElementDialogParent,
245
TL("Saving list of conflicted items failed"), e.what());
246
return false;
247
}
248
}
249
}
250
251
/// @brief Invalidated copy constructor.
252
FixOptions(const FixOptions&) = delete;
253
254
/// @brief Invalidated assignment operator.
255
FixOptions& operator=(const FixOptions&) = delete;
256
};
257
258
/// @brief Constructor
259
GNEFixElementsDialog(GNEApplicationWindow* applicationWindow, const std::string title, GUIIcon icon, DialogType type):
260
GNEDialog(applicationWindow, title.c_str(), icon, type, GNEDialog::Buttons::ACCEPT_CANCEL,
261
GNEDialog::OpenType::MODAL, ResizeMode::STATIC) {
262
// create left and right frames
263
FXHorizontalFrame* columnFrame = new FXHorizontalFrame(myContentFrame, GUIDesignAuxiliarHorizontalFrame);
264
myLeftFrame = new FXVerticalFrame(columnFrame, GUIDesignAuxiliarVerticalFrame);
265
myRightFrame = new FXVerticalFrame(columnFrame, GUIDesignAuxiliarVerticalFrame);
266
}
267
268
/// @brief destructor
269
~GNEFixElementsDialog() {}
270
271
/// @brief pointer to the main window
272
GNEApplicationWindow* getApplicationWindow() {
273
return myApplicationWindow;
274
}
275
276
/// @brief register fix options to the dialog (called automatically during FixOptions constructor)
277
void registerFixOptions(FixOptions* fixOptions) {
278
myFixOptions.push_back(fixOptions);
279
}
280
281
/// @brief run internal test
282
void runInternalTest(const InternalTestStep::DialogArgument* dialogArgument) {
283
// run internal test for each fix option
284
for (auto fixOption : myFixOptions) {
285
fixOption->selectInternalTestSolution(dialogArgument->getCustomAction());
286
}
287
}
288
289
/// @name FOX-callbacks
290
/// @{
291
292
/// @brief event after press accept button
293
long onCmdAccept(FXObject*, FXSelector, void*) {
294
bool abortSaving = false;
295
// apply each fix option in their correspond fixOption
296
for (auto fixOption : myFixOptions) {
297
// if applyFixOption returns false, abort saving (usually for selecting invalid elements)
298
if (fixOption->applyFixOption() == false) {
299
abortSaving = true;
300
}
301
}
302
// continue depending of abortSaving
303
if (abortSaving == false) {
304
return closeDialogAccepting();
305
} else {
306
return closeDialogCanceling();
307
}
308
}
309
310
/// @}
311
312
protected:
313
/// @brief vector with all fix options
314
std::vector<GNEFixElementsDialog::FixOptions*> myFixOptions;
315
316
/// @brief left frame for fix options
317
FXVerticalFrame* myLeftFrame = nullptr;
318
319
/// @brief right frame for fix options
320
FXVerticalFrame* myRightFrame = nullptr;
321
322
private:
323
/// @brief Invalidated copy constructor.
324
GNEFixElementsDialog(const GNEFixElementsDialog&) = delete;
325
326
/// @brief Invalidated assignment operator.
327
GNEFixElementsDialog& operator=(const GNEFixElementsDialog&) = delete;
328
};
329
330