Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/frames/GNEAttributesEditorRow.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-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 GNEAttributesEditorRow.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Nov 2024
17
///
18
// Row used for edit attributes in GNEAttributesEditorType
19
/****************************************************************************/
20
21
#include <netedit/dialogs/GNEVClassesDialog.h>
22
#include <netedit/dialogs/GNEColorDialog.h>
23
#include <netedit/frames/common/GNEInspectorFrame.h>
24
#include <netedit/GNEApplicationWindow.h>
25
#include <netedit/GNEInternalTest.h>
26
#include <netedit/GNENet.h>
27
#include <netedit/GNETagProperties.h>
28
#include <netedit/GNEViewNet.h>
29
#include <netedit/GNEViewParent.h>
30
#include <utils/common/Translation.h>
31
#include <utils/foxtools/MFXLabelTooltip.h>
32
#include <utils/foxtools/MFXTextFieldIcon.h>
33
#include <utils/gui/div/GUIDesigns.h>
34
#include <utils/gui/images/POIIcons.h>
35
#include <utils/gui/images/VClassIcons.h>
36
37
#include "GNEAttributesEditorRow.h"
38
39
// ===========================================================================
40
// FOX callback mapping
41
// ===========================================================================
42
43
FXDEFMAP(GNEAttributesEditorRow) GNEAttributeRowMap[] = {
44
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_SETATTRIBUTE, GNEAttributesEditorRow::onCmdSetAttribute),
45
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_TOGGLEENABLEATTRIBUTE, GNEAttributesEditorRow::onCmdToggleEnableAttribute),
46
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_COLOR, GNEAttributesEditorRow::onCmdOpenColorDialog),
47
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_ALLOW, GNEAttributesEditorRow::onCmdOpenVClassDialog),
48
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_FILE, GNEAttributesEditorRow::onCmdOpenFileDialog),
49
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_REPARENT, GNEAttributesEditorRow::onCmdReparent),
50
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_INSPECTPARENT, GNEAttributesEditorRow::onCmdInspectParent),
51
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_MOVELANEUP, GNEAttributesEditorRow::onCmdMoveLaneUp),
52
FXMAPFUNC(SEL_COMMAND, MID_GNE_ATTRIBUTESEDITORROW_MOVELANEDOWN, GNEAttributesEditorRow::onCmdMoveLaneDown)
53
};
54
55
// Object implementation
56
FXIMPLEMENT(GNEAttributesEditorRow, FXHorizontalFrame, GNEAttributeRowMap, ARRAYNUMBER(GNEAttributeRowMap))
57
58
// ===========================================================================
59
// method definitions
60
// ===========================================================================
61
62
GNEAttributesEditorRow::GNEAttributesEditorRow(GNEAttributesEditorType* attributeTable) :
63
FXHorizontalFrame(attributeTable->getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame),
64
myAttributeTable(attributeTable) {
65
// get static tooltip menu
66
const auto tooltipMenu = attributeTable->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();
67
// Create left label
68
myAttributeLabel = new MFXLabelTooltip(this, tooltipMenu, "Label", nullptr, GUIDesignLabelThickedFixed(100));
69
myAttributeLabel->hide();
70
// create lef boolean checkBox for enable/disable attributes
71
myAttributeToggleEnableCheckButton = new FXCheckButton(this, "Enable/Disable attribute checkBox", this,
72
MID_GNE_ATTRIBUTESEDITORROW_TOGGLEENABLEATTRIBUTE, GUIDesignCheckButtonAttribute);
73
myAttributeToggleEnableCheckButton->hide();
74
// create left button parent
75
myAttributeButton = new MFXButtonTooltip(this, tooltipMenu, "button", nullptr, this,
76
MID_GNE_ATTRIBUTESEDITORROW_REPARENT, GUIDesignButtonAttribute);
77
// create right text field for string attributes
78
myValueTextField = new MFXTextFieldIcon(this, tooltipMenu, GUIIcon::EMPTY, this, MID_GNE_ATTRIBUTESEDITORROW_SETATTRIBUTE, GUIDesignTextField);
79
myValueTextField->hide();
80
// create right combo box for discrete attributes
81
myValueComboBox = new MFXComboBoxIcon(this, tooltipMenu, true, GUIDesignComboBoxVisibleItems, this,
82
MID_GNE_ATTRIBUTESEDITORROW_SETATTRIBUTE, GUIDesignComboBoxAttribute);
83
myValueComboBox->hide();
84
// Create right check button
85
myValueCheckButton = new FXCheckButton(this, "check button", this, MID_GNE_ATTRIBUTESEDITORROW_SETATTRIBUTE, GUIDesignCheckButton);
86
myValueCheckButton->hide();
87
// create right move lane up button
88
myValueLaneUpButton = new MFXButtonTooltip(this, tooltipMenu, "", GUIIconSubSys::getIcon(GUIIcon::ARROW_UP), this,
89
MID_GNE_ATTRIBUTESEDITORROW_MOVELANEUP, GUIDesignButtonIcon);
90
myValueLaneUpButton->hide();
91
// set tip texts
92
myValueLaneUpButton->setTipText(TL("Move element up one lane"));
93
myValueLaneUpButton->setHelpText(TL("Move element up one lane"));
94
// create right move lane down button
95
myValueLaneDownButton = new MFXButtonTooltip(this, tooltipMenu, "", GUIIconSubSys::getIcon(GUIIcon::ARROW_DOWN), this,
96
MID_GNE_ATTRIBUTESEDITORROW_MOVELANEDOWN, GUIDesignButtonIcon);
97
myValueLaneDownButton->hide();
98
// set tip texts
99
myValueLaneDownButton->setTipText(TL("Move element down one lane"));
100
myValueLaneDownButton->setHelpText(TL("Move element down one lane"));
101
// start hidden
102
hide();
103
}
104
105
106
bool
107
GNEAttributesEditorRow::showAttributeRow(GNEAttributesEditorType* attributeTable, const GNEAttributeProperties* attrProperty, const bool forceDisable) {
108
// update parent table
109
myAttributeTable = attributeTable;
110
if (myAttributeTable->myEditedACs.empty()) {
111
return false;
112
} else {
113
reparent(myAttributeTable->getCollapsableFrame());
114
}
115
myAttrProperty = attrProperty;
116
const auto attribute = myAttrProperty->getAttr();
117
const auto tagPropertyParent = attrProperty->getTagPropertyParent();
118
const auto firstEditedAC = myAttributeTable->myEditedACs.front();
119
// check if we're editing multiple ACs
120
const auto multipleEditedACs = (myAttributeTable->myEditedACs.size() > 1);
121
// declare flag for show attribute enabled
122
const bool attributeEnabled = isAttributeEnabled(attrProperty);
123
// check if this attribute is computed
124
const bool computedAttribute = multipleEditedACs ? false : firstEditedAC->isAttributeComputed(attribute);
125
// get string value depending if attribute is enabled
126
const std::string value = getAttributeValue(attributeEnabled);
127
// get parent if we're editing single vTypes
128
GNEAttributeCarrier* ACParent = nullptr;
129
if (!multipleEditedACs && attrProperty->isVType()) {
130
const auto& ACs = myAttributeTable->myFrameParent->getViewNet()->getNet()->getAttributeCarriers();
131
// parent can be either type or distribution
132
if (attribute == SUMO_ATTR_TYPE) {
133
ACParent = ACs->retrieveDemandElement(SUMO_TAG_VTYPE, firstEditedAC->getAttribute(SUMO_ATTR_TYPE), false);
134
}
135
if (ACParent == nullptr) {
136
ACParent = ACs->retrieveDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, firstEditedAC->getAttribute(SUMO_ATTR_TYPE), false);
137
}
138
}
139
// hide editing for unique attributes in case of multi-selection
140
if (multipleEditedACs && attrProperty->isUnique()) {
141
return hideAttributeRow();
142
}
143
// front element has their own button, and doesn't use the UndoList
144
if (attribute == GNE_ATTR_FRONTELEMENT) {
145
return hideAttributeRow();
146
}
147
// if we have a disabled flow attribute, don't show row
148
if (attrProperty->isFlow() && !attributeEnabled) {
149
return hideAttributeRow();
150
}
151
// expected and joins depend of triggered
152
if (tagPropertyParent->isVehicleStop() && !attributeEnabled) {
153
if (attribute == SUMO_ATTR_EXPECTED) {
154
return hideAttributeRow();
155
} else if (attribute == SUMO_ATTR_EXPECTED_CONTAINERS) {
156
return hideAttributeRow();
157
} else if (attribute == SUMO_ATTR_JOIN) {
158
return hideAttributeRow();
159
}
160
}
161
// don't show stop offset exception if stopOffset is zero
162
if ((attribute == GNE_ATTR_STOPOEXCEPTION) && !attributeEnabled) {
163
return hideAttributeRow();
164
}
165
// show elements depending of attribute properties
166
if (attrProperty->isActivatable()) {
167
showAttributeToggleEnable(attrProperty, attributeEnabled);
168
} else if (attrProperty->isFileOpen() || attrProperty->isFileSave()) {
169
showAttributeFile(attrProperty, attributeEnabled);
170
} else if (attribute == GNE_ATTR_PARENT) {
171
showAttributeReparent(attributeEnabled);
172
} else if ((attribute == SUMO_ATTR_TYPE) && tagPropertyParent->hasTypeParent()) {
173
showAttributeInspectParent(attrProperty, attributeEnabled);
174
} else if (attrProperty->isVClass() && (attribute != SUMO_ATTR_DISALLOW)) {
175
showAttributeVClass(attrProperty, attributeEnabled);
176
} else if (attribute == SUMO_ATTR_COLOR) {
177
showAttributeColor(attrProperty, attributeEnabled);
178
} else if (attribute == GNE_ATTR_PARAMETERS) {
179
hideAllAttributeElements();
180
} else {
181
showAttributeLabel(attrProperty);
182
}
183
// continue depending of type of attribute
184
if (attrProperty->isBool()) {
185
showValueCheckButton(value, attributeEnabled, computedAttribute);
186
} else if (attrProperty->isDiscrete() || attrProperty->isVType()) {
187
showValueComboBox(attrProperty, value, attributeEnabled, computedAttribute);
188
} else {
189
showValueString(value, attributeEnabled, computedAttribute);
190
}
191
// check if show move lane buttons
192
if (!multipleEditedACs && !tagPropertyParent->isNetworkElement() && (attribute == SUMO_ATTR_LANE)) {
193
showMoveLaneButtons(value);
194
myValueLaneUpButton->show();
195
myValueLaneDownButton->show();
196
} else {
197
myValueLaneUpButton->hide();
198
myValueLaneDownButton->hide();
199
}
200
// enable depending of supermode
201
enableElements(attrProperty, forceDisable);
202
// Show row
203
show();
204
return true;
205
}
206
207
208
bool
209
GNEAttributesEditorRow::hideAttributeRow() {
210
hide();
211
return false;
212
}
213
214
215
void
216
GNEAttributesEditorRow::disable() {
217
// disable all elements
218
myAttributeToggleEnableCheckButton->disable();
219
myAttributeButton->disable();
220
myValueTextField->disable();
221
myValueComboBox->disable();
222
myValueCheckButton->disable();
223
myValueLaneUpButton->disable();
224
myValueLaneDownButton->disable();
225
}
226
227
228
const GNEAttributeProperties*
229
GNEAttributesEditorRow::getAttrProperty() const {
230
return myAttrProperty;
231
}
232
233
234
std::string
235
GNEAttributesEditorRow::getCurrentValue() const {
236
if (myValueCheckButton->shown()) {
237
return (myValueCheckButton->getCheck() == TRUE) ? "true" : "false";
238
} else if (myValueComboBox->shown()) {
239
return myValueComboBox->getText().text();
240
} else if (myValueTextField->shown()) {
241
return myValueTextField->getText().text();
242
} else {
243
return "";
244
}
245
}
246
247
248
bool
249
GNEAttributesEditorRow::isValueValid() const {
250
if (myValueCheckButton->shown()) {
251
return true;
252
} else if (myValueComboBox->shown()) {
253
return (myValueComboBox->getTextColor() != GUIDesignTextColorRed) &&
254
(myValueComboBox->getBackColor() != GUIDesignBackgroundColorRed);
255
} else if (myValueTextField->shown()) {
256
return (myValueTextField->getTextColor() != GUIDesignTextColorRed) &&
257
(myValueTextField->getBackColor() != GUIDesignBackgroundColorRed);
258
} else {
259
return true;
260
}
261
}
262
263
264
bool
265
GNEAttributesEditorRow::isAttributeRowShown() const {
266
return shown();
267
}
268
269
270
SumoXMLAttr
271
GNEAttributesEditorRow::fillSumoBaseObject(CommonXMLStructure::SumoBaseObject* baseObject, const bool insertDefaultValues) const {
272
const auto attribute = myAttrProperty->getAttr();
273
// check if this is the default value
274
const bool usingDefaultValue = isValueValid() && (myAttrProperty->getDefaultStringValue() == getCurrentValue());
275
// first check if insert default values
276
if (!insertDefaultValues && usingDefaultValue) {
277
return SUMO_ATTR_NOTHING;
278
}
279
// now check if attribute is activatable AND is enabled
280
if (myAttrProperty->isActivatable() && (myAttributeToggleEnableCheckButton->getCheck() == FALSE)) {
281
return SUMO_ATTR_NOTHING;
282
}
283
// continue depending of type
284
if (myAttrProperty->isBool()) {
285
baseObject->addBoolAttribute(attribute, myValueCheckButton->getCheck() == TRUE);
286
} else if (myAttrProperty->isDiscrete()) {
287
if ((myValueComboBox->getTextColor() == GUIDesignTextColorRed) ||
288
(myValueComboBox->getBackColor() == GUIDesignBackgroundColorRed)) {
289
return attribute;
290
} else {
291
baseObject->addStringAttribute(attribute, myValueComboBox->getText().text());
292
}
293
} else if ((myValueTextField->getTextColor() == GUIDesignTextColorRed) ||
294
(myValueTextField->getBackColor() == GUIDesignBackgroundColorRed)) {
295
return attribute;
296
} else if (myAttrProperty->isInt()) {
297
// int value
298
if (GNEAttributeCarrier::canParse<int>(myValueTextField->getText().text())) {
299
const auto intValue = GNEAttributeCarrier::parse<int>(myValueTextField->getText().text());
300
if (myAttrProperty->isPositive() && (intValue < 0)) {
301
return attribute;
302
} else {
303
baseObject->addIntAttribute(attribute, intValue);
304
}
305
} else if (myAttrProperty->hasDefaultValue() && (myValueTextField->getText().text() == myAttrProperty->getDefaultStringValue())) {
306
baseObject->addIntAttribute(attribute, myAttrProperty->getDefaultIntValue());
307
} else if (myAttrProperty->hasDefaultValue() && myValueTextField->getText().empty()) {
308
baseObject->addIntAttribute(attribute, myAttrProperty->getDefaultIntValue());
309
} else {
310
return attribute;
311
}
312
} else if (myAttrProperty->isFloat()) {
313
// double value
314
if (myAttrProperty->isList()) {
315
if (GNEAttributeCarrier::canParse<std::vector<double> >(myValueTextField->getText().text())) {
316
const auto doubleListValue = GNEAttributeCarrier::parse<std::vector<double> >(myValueTextField->getText().text());
317
// check every double
318
for (const auto doubleValue : doubleListValue) {
319
if (myAttrProperty->isPositive() && (doubleValue < 0)) {
320
return attribute;
321
} else if (myAttrProperty->isFloat() && ((doubleValue < 0) || (doubleValue > 1))) {
322
return attribute;
323
}
324
}
325
baseObject->addDoubleListAttribute(attribute, doubleListValue);
326
} else {
327
return attribute;
328
}
329
} else if (GNEAttributeCarrier::canParse<double>(myValueTextField->getText().text())) {
330
const auto doubleValue = GNEAttributeCarrier::parse<double>(myValueTextField->getText().text());
331
// check using default value for certain default values (for example, length = -1)
332
if (!usingDefaultValue && myAttrProperty->isPositive() && (doubleValue < 0)) {
333
return attribute;
334
} else if (!usingDefaultValue && myAttrProperty->isProbability() && ((doubleValue < 0) || (doubleValue > 1))) {
335
return attribute;
336
} else {
337
baseObject->addDoubleAttribute(attribute, doubleValue);
338
}
339
} else if (myAttrProperty->hasDefaultValue() && (myValueTextField->getText().text() == myAttrProperty->getDefaultStringValue())) {
340
baseObject->addDoubleAttribute(attribute, myAttrProperty->getDefaultDoubleValue());
341
} else if (myAttrProperty->hasDefaultValue() && myValueTextField->getText().empty()) {
342
baseObject->addDoubleAttribute(attribute, myAttrProperty->getDefaultDoubleValue());
343
} else {
344
return attribute;
345
}
346
} else if (myAttrProperty->isSUMOTime()) {
347
// time value
348
if (GNEAttributeCarrier::canParse<SUMOTime>(myValueTextField->getText().text())) {
349
const auto timeValue = GNEAttributeCarrier::parse<SUMOTime>(myValueTextField->getText().text());
350
if (timeValue < 0) {
351
return attribute;
352
} else {
353
baseObject->addTimeAttribute(attribute, timeValue);
354
}
355
} else if (myAttrProperty->hasDefaultValue() && (myValueTextField->getText().text() == myAttrProperty->getDefaultStringValue())) {
356
baseObject->addTimeAttribute(attribute, myAttrProperty->getDefaultTimeValue());
357
} else if (myAttrProperty->hasDefaultValue() && myValueTextField->getText().empty()) {
358
baseObject->addTimeAttribute(attribute, myAttrProperty->getDefaultTimeValue());
359
} else {
360
return attribute;
361
}
362
} else if (myAttrProperty->isPosition()) {
363
// position value
364
if (myAttrProperty->isList()) {
365
if (GNEAttributeCarrier::canParse<PositionVector>(myValueTextField->getText().text())) {
366
baseObject->addPositionVectorAttribute(attribute, GNEAttributeCarrier::parse<PositionVector>(myValueTextField->getText().text()));
367
} else {
368
return attribute;
369
}
370
} else if (GNEAttributeCarrier::canParse<Position>(myValueTextField->getText().text())) {
371
baseObject->addPositionAttribute(attribute, GNEAttributeCarrier::parse<Position>(myValueTextField->getText().text()));
372
} else if (myAttrProperty->hasDefaultValue() && (myValueTextField->getText().text() == myAttrProperty->getDefaultStringValue())) {
373
baseObject->addPositionAttribute(attribute, myAttrProperty->getDefaultPositionValue());
374
} else if (myAttrProperty->hasDefaultValue() && myValueTextField->getText().empty()) {
375
baseObject->addPositionAttribute(attribute, myAttrProperty->getDefaultPositionValue());
376
} else {
377
return attribute;
378
}
379
} else if (myAttrProperty->isColor()) {
380
// color value
381
if (GNEAttributeCarrier::canParse<RGBColor>(myValueTextField->getText().text())) {
382
baseObject->addColorAttribute(attribute, GNEAttributeCarrier::parse<RGBColor>(myValueTextField->getText().text()));
383
} else if (myAttrProperty->hasDefaultValue() && (myValueTextField->getText().text() == myAttrProperty->getDefaultStringValue())) {
384
baseObject->addColorAttribute(attribute, myAttrProperty->getDefaultColorValue());
385
} else if (myAttrProperty->hasDefaultValue() && myValueTextField->getText().empty()) {
386
baseObject->addColorAttribute(attribute, myAttrProperty->getDefaultColorValue());
387
} else {
388
return attribute;
389
}
390
} else if (myAttrProperty->isList()) {
391
baseObject->addStringListAttribute(attribute, GNEAttributeCarrier::parse<std::vector<std::string> >(myValueTextField->getText().text()));
392
} else if (attribute == GNE_ATTR_PARAMETERS) {
393
baseObject->addParameters(myValueTextField->getText().text());
394
} else {
395
baseObject->addStringAttribute(attribute, myValueTextField->getText().text());
396
}
397
// all ok, then return nothing
398
return SUMO_ATTR_NOTHING;
399
}
400
401
402
long
403
GNEAttributesEditorRow::onCmdOpenColorDialog(FXObject*, FXSelector, void*) {
404
RGBColor color = RGBColor::BLACK;
405
// If previous attribute wasn't correct, set black as default color
406
if (GNEAttributeCarrier::canParse<RGBColor>(myValueTextField->getText().text())) {
407
color = GNEAttributeCarrier::parse<RGBColor>(myValueTextField->getText().text());
408
} else if (myAttrProperty->hasDefaultValue()) {
409
color = myAttrProperty->getDefaultColorValue();
410
}
411
// declare colorDialog
412
const auto colorDialog = new GNEColorDialog(myAttributeTable->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows(), color);
413
// continue depending of result
414
if (colorDialog->getResult() == GNEDialog::Result::ACCEPT) {
415
myValueTextField->setText(toString(colorDialog->getColor()).c_str(), TRUE);
416
}
417
return 1;
418
}
419
420
421
long
422
GNEAttributesEditorRow::onCmdOpenVClassDialog(FXObject*, FXSelector, void*) {
423
// declare allowVClassesDialog
424
const auto allowVClassesDialog = new GNEVClassesDialog(myAttributeTable->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows(),
425
myAttrProperty->getAttr(), myValueTextField->getText().text());
426
// continue depending of result
427
if (allowVClassesDialog->getResult() == GNEDialog::Result::ACCEPT) {
428
myValueTextField->setText(allowVClassesDialog->getModifiedVClasses().c_str(), TRUE);
429
}
430
return 1;
431
}
432
433
434
long
435
GNEAttributesEditorRow::onCmdOpenFileDialog(FXObject*, FXSelector, void*) {
436
// open dialog
437
const auto fileDialog = GNEFileDialog(myAttributeTable->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows(),
438
myAttrProperty->getAttrStr(),
439
myAttrProperty->getFilenameExtensions(),
440
myAttrProperty->isFileSave() ? GNEFileDialog::OpenMode::SAVE : GNEFileDialog::OpenMode::LOAD_SINGLE,
441
GNEFileDialog::ConfigType::NETEDIT);
442
// update text field
443
if (fileDialog.getResult() == GNEDialog::Result::ACCEPT) {
444
myValueTextField->setText(fileDialog.getFilename().c_str(), TRUE);
445
}
446
return 1;
447
}
448
449
450
long
451
GNEAttributesEditorRow::onCmdReparent(FXObject*, FXSelector, void*) {
452
myAttributeTable->enableReparent();
453
return 1;
454
}
455
456
457
long
458
GNEAttributesEditorRow::onCmdInspectParent(FXObject*, FXSelector, void*) {
459
myAttributeTable->inspectParent();
460
return 1;
461
}
462
463
464
long
465
GNEAttributesEditorRow::onCmdMoveLaneUp(FXObject*, FXSelector, void*) {
466
myAttributeTable->moveLaneUp();
467
return 1;
468
}
469
470
471
long
472
GNEAttributesEditorRow::onCmdMoveLaneDown(FXObject*, FXSelector, void*) {
473
myAttributeTable->moveLaneDown();
474
return 1;
475
}
476
477
478
long
479
GNEAttributesEditorRow::onCmdSetAttribute(FXObject* obj, FXSelector, void*) {
480
if (myAttributeTable->myEditedACs.empty()) {
481
return 0;
482
}
483
const auto& editedAC = myAttributeTable->myEditedACs.front();
484
const auto attribute = myAttrProperty->getAttr();
485
// continue depending of clicked object
486
if (obj == myValueCheckButton) {
487
// Set true o false depending of the checkBox
488
if (myValueCheckButton->getCheck()) {
489
myValueCheckButton->setText("true");
490
} else {
491
myValueCheckButton->setText("false");
492
}
493
myAttributeTable->setAttribute(attribute, myValueCheckButton->getText().text());
494
} else if (obj == myValueComboBox) {
495
const std::string newValue = myValueComboBox->getText().text();
496
// check if the new comboBox value is valid
497
if (editedAC->isValid(attribute, newValue)) {
498
myValueComboBox->setTextColor(GUIDesignTextColorBlack);
499
myValueComboBox->setBackColor(GUIDesignBackgroundColorWhite);
500
myValueComboBox->killFocus();
501
myAttributeTable->setAttribute(attribute, newValue);
502
} else {
503
// edit colors
504
myValueComboBox->setTextColor(GUIDesignTextColorRed);
505
if (newValue.empty()) {
506
myValueComboBox->setBackColor(GUIDesignBackgroundColorRed);
507
}
508
}
509
} else if (obj == myValueTextField) {
510
// first check if set default value
511
if (myValueTextField->getText().empty() && myAttrProperty->hasDefaultValue() && !myAttrProperty->isVClass()) {
512
// update text field without notify
513
myValueTextField->setText(myAttrProperty->getDefaultStringValue().c_str(), FALSE);
514
}
515
// if we're editing an angle, check if filter between [0,360]
516
if ((attribute == SUMO_ATTR_ANGLE) && GNEAttributeCarrier::canParse<double>(myValueTextField->getText().text())) {
517
// filter anglea and update text field without notify
518
const double angle = fmod(GNEAttributeCarrier::parse<double>(myValueTextField->getText().text()), 360);
519
myValueTextField->setText(toString(angle).c_str(), FALSE);
520
}
521
// if we're editing a position or a shape, strip whitespace after comma
522
if ((attribute == SUMO_ATTR_POSITION) || (attribute == SUMO_ATTR_SHAPE)) {
523
std::string shape(myValueTextField->getText().text());
524
while (shape.find(", ") != std::string::npos) {
525
shape = StringUtils::replace(shape, ", ", ",");
526
}
527
myValueTextField->setText(toString(shape).c_str(), FALSE);
528
}
529
// if we're editing a int, strip decimal value
530
if (myAttrProperty->isInt() && GNEAttributeCarrier::canParse<double>(myValueTextField->getText().text())) {
531
double doubleValue = GNEAttributeCarrier::parse<double>(myValueTextField->getText().text());
532
if ((doubleValue - (int)doubleValue) == 0) {
533
myValueTextField->setText(toString((int)doubleValue).c_str(), FALSE);
534
}
535
}
536
// after apply all filters, obtain value
537
const std::string newValue = myValueTextField->getText().text();
538
// check if the new textField value is valid
539
if (editedAC->isValid(attribute, newValue)) {
540
myValueTextField->setTextColor(GUIDesignTextColorBlack);
541
myValueTextField->setBackColor(GUIDesignBackgroundColorWhite);
542
myValueTextField->killFocus();
543
if (myAttributeTable->isEditorTypeEditor() || newValue.empty() || (attribute != SUMO_ATTR_ID)) {
544
myAttributeTable->setAttribute(attribute, newValue);
545
}
546
} else {
547
// edit colors
548
myValueTextField->setTextColor(GUIDesignTextColorRed);
549
if (newValue.empty()) {
550
myValueTextField->setBackColor(GUIDesignBackgroundColorRed);
551
}
552
}
553
}
554
return 1;
555
}
556
557
558
long
559
GNEAttributesEditorRow::onCmdToggleEnableAttribute(FXObject*, FXSelector, void*) {
560
myAttributeTable->toggleEnableAttribute(myAttrProperty->getAttr(), myAttributeToggleEnableCheckButton->getCheck() == TRUE);
561
return 0;
562
}
563
564
565
GNEAttributesEditorRow::GNEAttributesEditorRow() :
566
myAttributeTable(nullptr) {
567
}
568
569
570
const std::string
571
GNEAttributesEditorRow::getAttributeValue(const bool enabled) const {
572
const auto attribute = myAttrProperty->getAttr();
573
// if we're in creator mode, generate ID
574
if ((attribute == SUMO_ATTR_ID) && (myAttributeTable->myEditorType == GNEAttributesEditorType::EditorType::CREATOR)) {
575
const auto& ACs = myAttributeTable->getFrameParent()->getViewNet()->getNet()->getAttributeCarriers();
576
const auto parentTag = myAttrProperty->getTagPropertyParent()->getTag();
577
if (myAttrProperty->getTagPropertyParent()->getTag() == SUMO_TAG_EDGE) {
578
return ACs->generateEdgeID();
579
} else if (myAttrProperty->getTagPropertyParent()->isAdditionalElement()) {
580
return ACs->generateAdditionalID(parentTag);
581
} else if (myAttrProperty->getTagPropertyParent()->isDemandElement()) {
582
return ACs->generateDemandElementID(parentTag);
583
} else if (myAttrProperty->getTagPropertyParent()->isMeanData()) {
584
return ACs->generateMeanDataID(parentTag);
585
} else if (parentTag == SUMO_TAG_TYPE) {
586
return ACs->generateEdgeTypeID();
587
} else if (parentTag == SUMO_TAG_DATASET) {
588
return ACs->generateDataSetID();
589
}
590
}
591
if (enabled) {
592
// Declare a set of occurring values and insert attribute's values of item (note: We use a set to avoid repeated values)
593
std::set<std::string> values;
594
// iterate over edited attributes and insert every value in set
595
for (const auto& editedAC : myAttributeTable->myEditedACs) {
596
if (editedAC->hasAttribute(attribute)) {
597
values.insert(editedAC->getAttribute(attribute));
598
}
599
}
600
// merge all values in a single string
601
std::ostringstream oss;
602
for (auto it = values.begin(); it != values.end(); it++) {
603
if (it != values.begin()) {
604
oss << " ";
605
}
606
oss << *it;
607
}
608
// obtain value to be shown in row
609
return oss.str();
610
} else {
611
return myAttributeTable->myEditedACs.front()->getAlternativeValueForDisabledAttributes(attribute);
612
}
613
}
614
615
616
void
617
GNEAttributesEditorRow::showAttributeToggleEnable(const GNEAttributeProperties* attrProperty, const bool value) {
618
myAttributeToggleEnableCheckButton->setText(attrProperty->getAttrStr().c_str());
619
myAttributeToggleEnableCheckButton->setCheck(value);
620
myAttributeToggleEnableCheckButton->enable();
621
myAttributeToggleEnableCheckButton->show();
622
// hide other elements
623
myAttributeLabel->hide();
624
myAttributeButton->hide();
625
}
626
627
628
void
629
GNEAttributesEditorRow::showAttributeReparent(const bool enabled) {
630
// update attribute button
631
myAttributeButton->setText(TL("Reparent"));
632
myAttributeButton->setHelpText(TL("Change parent of this element"));
633
myAttributeButton->setTipText(myAttributeButton->getHelpText());
634
myAttributeButton->setIcon(nullptr);
635
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_REPARENT);
636
if (enabled) {
637
myAttributeButton->enable();
638
} else {
639
myAttributeButton->disable();
640
}
641
myAttributeButton->show();
642
// hide other elements
643
myAttributeLabel->hide();
644
myAttributeToggleEnableCheckButton->hide();
645
}
646
647
648
void
649
GNEAttributesEditorRow::showAttributeInspectParent(const GNEAttributeProperties* attrProperty, const bool enabled) {
650
// update attribute button
651
myAttributeButton->setText(attrProperty->getAttrStr().c_str());
652
myAttributeButton->setHelpText(TLF("Inspect % parent", attrProperty->getAttrStr()).c_str());
653
myAttributeButton->setTipText(myAttributeButton->getHelpText());
654
myAttributeButton->setIcon(GUIIconSubSys::getIcon(attrProperty->getTagPropertyParent()->getGUIIcon()));
655
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_INSPECTPARENT);
656
if (enabled) {
657
myAttributeButton->enable();
658
} else {
659
myAttributeButton->disable();
660
}
661
myAttributeButton->show();
662
// hide other elements
663
myAttributeLabel->hide();
664
myAttributeToggleEnableCheckButton->hide();
665
}
666
667
668
void
669
GNEAttributesEditorRow::showAttributeVClass(const GNEAttributeProperties* attrProperty, const bool enabled) {
670
// update attribute button
671
myAttributeButton->setText(attrProperty->getAttrStr().c_str());
672
myAttributeButton->setHelpText(TL("Open dialog for editing vClasses"));
673
myAttributeButton->setTipText(myAttributeButton->getHelpText());
674
myAttributeButton->setIcon(nullptr);
675
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_ALLOW);
676
if (enabled) {
677
myAttributeButton->enable();
678
} else {
679
myAttributeButton->disable();
680
}
681
myAttributeButton->show();
682
// hide other elements
683
myAttributeLabel->hide();
684
myAttributeToggleEnableCheckButton->hide();
685
}
686
687
688
void
689
GNEAttributesEditorRow::showAttributeColor(const GNEAttributeProperties* attrProperty, const bool enabled) {
690
// update attribute button
691
myAttributeButton->setText(attrProperty->getAttrStr().c_str());
692
myAttributeButton->setHelpText(TL("Open dialog for editing color"));
693
myAttributeButton->setTipText(myAttributeButton->getHelpText());
694
myAttributeButton->setIcon(GUIIconSubSys::getIcon(GUIIcon::COLORWHEEL));
695
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_COLOR);
696
if (enabled) {
697
myAttributeButton->enable();
698
} else {
699
myAttributeButton->disable();
700
}
701
myAttributeButton->show();
702
// hide other elements
703
myAttributeLabel->hide();
704
myAttributeToggleEnableCheckButton->hide();
705
}
706
707
708
void
709
GNEAttributesEditorRow::showAttributeFile(const GNEAttributeProperties* attrProperty, const bool enabled) {
710
// update attribute button
711
myAttributeButton->setText(attrProperty->getAttrStr().c_str());
712
if (attrProperty->isFileOpen()) {
713
myAttributeButton->setHelpText(TL("Open dialog to select an existent file"));
714
} else {
715
myAttributeButton->setHelpText(TL("Open dialog to select or create an existent file"));
716
}
717
myAttributeButton->setTipText(myAttributeButton->getHelpText());
718
myAttributeButton->setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN));
719
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_FILE);
720
if (enabled) {
721
myAttributeButton->enable();
722
} else {
723
myAttributeButton->disable();
724
}
725
myAttributeButton->show();
726
// hide other elements
727
myAttributeLabel->hide();
728
myAttributeToggleEnableCheckButton->hide();
729
}
730
731
732
void
733
GNEAttributesEditorRow::showAttributeLabel(const GNEAttributeProperties* attrProperty) {
734
myAttributeLabel->setText(attrProperty->getAttrStr().c_str());
735
myAttributeLabel->show();
736
// hide other elements
737
myAttributeToggleEnableCheckButton->hide();
738
myAttributeButton->hide();
739
}
740
741
742
void
743
GNEAttributesEditorRow::hideAllAttributeElements() {
744
myAttributeLabel->hide();
745
myAttributeToggleEnableCheckButton->hide();
746
myAttributeButton->hide();
747
}
748
749
750
void
751
GNEAttributesEditorRow::showValueCheckButton(const std::string& value,
752
const bool enabled, const bool computed) {
753
// first we need to check if all boolean values are equal
754
bool allValuesEqual = true;
755
// declare boolean vector
756
std::vector<bool> booleanVector;
757
// check if value can be parsed to a boolean vector
758
if (GNEAttributeCarrier::canParse<std::vector<bool> >(value)) {
759
booleanVector = GNEAttributeCarrier::parse<std::vector<bool> >(value);
760
}
761
// iterate over booleans comparing all element with the first
762
for (const auto& booleanValue : booleanVector) {
763
if (booleanValue != booleanVector.front()) {
764
allValuesEqual = false;
765
}
766
}
767
// use checkbox or textfield depending if all booleans are equal
768
if (allValuesEqual) {
769
if (enabled) {
770
myValueCheckButton->enable();
771
} else {
772
myValueCheckButton->disable();
773
}
774
// set check button
775
if ((booleanVector.size() > 0) && booleanVector.front()) {
776
myValueCheckButton->setCheck(true);
777
myValueCheckButton->setText("true");
778
} else {
779
myValueCheckButton->setCheck(false);
780
myValueCheckButton->setText("false");
781
}
782
// show check button
783
myValueCheckButton->show();
784
// hide other value elements
785
myValueTextField->hide();
786
myValueComboBox->hide();
787
myValueLaneUpButton->hide();
788
myValueLaneDownButton->hide();
789
} else {
790
// show value as string
791
showValueString(value, enabled, computed);
792
}
793
}
794
795
796
void
797
GNEAttributesEditorRow::showValueComboBox(const GNEAttributeProperties* attrProperty, const std::string& value,
798
const bool enabled, const bool computed) {
799
// first we need to check if all boolean values are equal
800
bool allValuesEqual = true;
801
// declare boolean vector
802
std::vector<std::string> stringVector = GNEAttributeCarrier::parse<std::vector<std::string> >(value);
803
// iterate over string comparing all element with the first
804
for (const auto& stringValue : stringVector) {
805
if (stringValue != stringVector.front()) {
806
allValuesEqual = false;
807
}
808
}
809
// use checkbox or textfield depending if all booleans are equal
810
if (allValuesEqual) {
811
// clear and enable comboBox
812
myValueComboBox->clearItems();
813
myValueComboBox->setTextColor(GUIDesignTextColorBlack);
814
myValueComboBox->setBackColor(GUIDesignBackgroundColorWhite);
815
if (enabled) {
816
myValueComboBox->enable();
817
} else {
818
myValueComboBox->disable();
819
}
820
// fill depeding of ACAttr
821
if (attrProperty->getAttr() == SUMO_ATTR_VCLASS) {
822
// add all vClasses with their icons
823
for (const auto& vClassStr : SumoVehicleClassStrings.getStrings()) {
824
myValueComboBox->appendIconItem(vClassStr.c_str(), VClassIcons::getVClassIcon(getVehicleClassID(vClassStr)));
825
}
826
} else if (attrProperty->isVType()) {
827
// get ACs
828
const auto& ACs = myAttributeTable->myFrameParent->getViewNet()->getNet()->getAttributeCarriers();
829
// fill comboBox with all vTypes and vType distributions sorted by ID
830
std::map<std::string, GNEDemandElement*> sortedTypes;
831
for (const auto& type : ACs->getDemandElements().at(SUMO_TAG_VTYPE)) {
832
sortedTypes[type.second->getID()] = type.second;
833
}
834
for (const auto& sortedType : sortedTypes) {
835
myValueComboBox->appendIconItem(sortedType.first.c_str(), sortedType.second->getACIcon());
836
}
837
sortedTypes.clear();
838
for (const auto& typeDistribution : ACs->getDemandElements().at(SUMO_TAG_VTYPE_DISTRIBUTION)) {
839
sortedTypes[typeDistribution.second->getID()] = typeDistribution.second;
840
}
841
for (const auto& sortedType : sortedTypes) {
842
myValueComboBox->appendIconItem(sortedType.first.c_str(), sortedType.second->getACIcon());
843
}
844
} else if (attrProperty->getAttr() == SUMO_ATTR_ICON) {
845
// add all POIIcons with their icons
846
for (const auto& POIIcon : SUMOXMLDefinitions::POIIcons.getValues()) {
847
myValueComboBox->appendIconItem(SUMOXMLDefinitions::POIIcons.getString(POIIcon).c_str(), POIIcons::getPOIIcon(POIIcon));
848
}
849
} else if ((attrProperty->getAttr() == SUMO_ATTR_RIGHT_OF_WAY) && (myAttributeTable->myEditedACs.size() == 1) &&
850
(attrProperty->getTagPropertyParent()->getTag() == SUMO_TAG_JUNCTION)) {
851
// special case for junction types
852
if (myAttributeTable->myEditedACs.front()->getAttribute(SUMO_ATTR_TYPE) == "priority") {
853
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::DEFAULT).c_str(), nullptr);
854
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::EDGEPRIORITY).c_str(), nullptr);
855
} else if (myAttributeTable->myEditedACs.front()->getAttribute(SUMO_ATTR_TYPE) == "traffic_light") {
856
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::DEFAULT).c_str(), nullptr);
857
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::MIXEDPRIORITY).c_str(), nullptr);
858
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::ALLWAYSTOP).c_str(), nullptr);
859
} else {
860
myValueComboBox->disable();
861
}
862
} else {
863
// fill comboBox with discrete values
864
for (const auto& discreteValue : attrProperty->getDiscreteValues()) {
865
myValueComboBox->appendIconItem(discreteValue.c_str(), nullptr);
866
}
867
}
868
// set current value (or disable)
869
const auto index = myValueComboBox->findItem(value.c_str());
870
if (index < 0) {
871
if (myValueComboBox->getNumItems() > 0) {
872
myValueComboBox->setCurrentItem(0);
873
} else {
874
myValueComboBox->disable();
875
}
876
} else {
877
myValueComboBox->setCurrentItem(index);
878
}
879
// show comboBox button
880
myValueComboBox->show();
881
// hide other value elements
882
myValueTextField->hide();
883
myValueCheckButton->hide();
884
myValueLaneUpButton->hide();
885
myValueLaneDownButton->hide();
886
} else {
887
// show value as string
888
showValueString(value, enabled, computed);
889
}
890
}
891
892
893
void
894
GNEAttributesEditorRow::showValueString(const std::string& value, const bool enabled, const bool computed) {
895
// clear and enable comboBox
896
myValueTextField->setText(value.c_str());
897
if (computed) {
898
myValueTextField->setTextColor(GUIDesignTextColorBlue);
899
} else {
900
myValueTextField->setTextColor(GUIDesignTextColorBlack);
901
}
902
if (enabled) {
903
myValueTextField->enable();
904
} else {
905
myValueTextField->disable();
906
}
907
// show list of values
908
myValueTextField->show();
909
// hide other value elements
910
myValueCheckButton->hide();
911
myValueComboBox->hide();
912
}
913
914
915
void
916
GNEAttributesEditorRow::showMoveLaneButtons(const std::string& laneID) {
917
// retrieve lane
918
const auto lane = myAttributeTable->myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveLane(laneID, false);
919
// check lane
920
if (lane) {
921
// check if disable move up
922
if ((lane->getIndex() + 1) >= (int)lane->getParentEdge()->getChildLanes().size()) {
923
myValueLaneUpButton->disable();
924
} else {
925
myValueLaneUpButton->enable();
926
}
927
// check if disable move down
928
if ((lane->getIndex() - 1) < 0) {
929
myValueLaneDownButton->disable();
930
} else {
931
myValueLaneDownButton->enable();
932
}
933
} else {
934
// if lane doesn't exist, disable both
935
myValueLaneUpButton->disable();
936
myValueLaneDownButton->disable();
937
}
938
}
939
940
941
void
942
GNEAttributesEditorRow::enableElements(const GNEAttributeProperties* attrProperty, const bool forceDisable) {
943
const auto& editModes = myAttributeTable->myFrameParent->getViewNet()->getEditModes();
944
const auto tagProperty = attrProperty->getTagPropertyParent();
945
// by default we assume that elements are disabled
946
bool enableElements = false;
947
if (forceDisable) {
948
enableElements = false;
949
} else if (editModes.isCurrentSupermodeNetwork()) {
950
if (tagProperty->isNetworkElement() || tagProperty->isAdditionalElement()) {
951
enableElements = true;
952
} else if ((tagProperty->getTag() == SUMO_TAG_TAZSOURCE) || (tagProperty->getTag() == SUMO_TAG_TAZSINK)) {
953
enableElements = true;
954
}
955
} else if (editModes.isCurrentSupermodeDemand() && tagProperty->isDemandElement()) {
956
enableElements = true;
957
} else if (editModes.isCurrentSupermodeData() && (tagProperty->isDataElement() || tagProperty->isMeanData())) {
958
enableElements = true;
959
}
960
if (!enableElements) {
961
myAttributeToggleEnableCheckButton->disable();
962
myAttributeButton->disable();
963
myValueTextField->disable();
964
myValueComboBox->disable();
965
myValueCheckButton->disable();
966
myValueLaneUpButton->disable();
967
myValueLaneDownButton->disable();
968
}
969
}
970
971
972
bool
973
GNEAttributesEditorRow::isAttributeEnabled(const GNEAttributeProperties* attrProperty) const {
974
if (attrProperty->isAlwaysEnabled()) {
975
return true;
976
} else {
977
for (const auto& AC : myAttributeTable->myEditedACs) {
978
if (AC->isAttributeEnabled(attrProperty->getAttr())) {
979
return true;
980
}
981
}
982
return false;
983
}
984
}
985
986
/****************************************************************************/
987
988