Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/frames/GNEAttributesEditorRow.cpp
193769 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 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
auto GNEApp = myAttributeTable->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows();
405
RGBColor color = RGBColor::BLACK;
406
// If previous attribute wasn't correct, set black as default color
407
if (GNEAttributeCarrier::canParse<RGBColor>(myValueTextField->getText().text())) {
408
color = GNEAttributeCarrier::parse<RGBColor>(myValueTextField->getText().text());
409
} else if (myAttrProperty->hasDefaultValue()) {
410
color = myAttrProperty->getDefaultColorValue();
411
}
412
// declare colorDialog
413
const auto colorDialog = new GNEColorDialog(GNEApp, color);
414
// continue depending of result
415
if (colorDialog->getResult() == GNEDialog::Result::ACCEPT) {
416
myValueTextField->setText(toString(colorDialog->getColor()).c_str(), TRUE);
417
}
418
return 1;
419
}
420
421
422
long
423
GNEAttributesEditorRow::onCmdOpenVClassDialog(FXObject*, FXSelector, void*) {
424
auto GNEApp = myAttributeTable->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows();
425
// declare allowVClassesDialog
426
const auto allowVClassesDialog = new GNEVClassesDialog(GNEApp, myAttrProperty->getAttr(), myValueTextField->getText().text());
427
// continue depending of result
428
if (allowVClassesDialog->getResult() == GNEDialog::Result::ACCEPT) {
429
myValueTextField->setText(allowVClassesDialog->getModifiedVClasses().c_str(), TRUE);
430
}
431
return 1;
432
}
433
434
435
long
436
GNEAttributesEditorRow::onCmdOpenFileDialog(FXObject*, FXSelector, void*) {
437
// open dialog
438
const GNEFileDialog fileDialog(myAttributeTable->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows(),
439
myAttrProperty->getAttrStr(),
440
myAttrProperty->getFilenameExtensions(),
441
myAttrProperty->isFileSave() ? GNEFileDialog::OpenMode::SAVE : GNEFileDialog::OpenMode::LOAD_SINGLE,
442
GNEFileDialog::ConfigType::NETEDIT);
443
// update text field
444
if (fileDialog.getResult() == GNEDialog::Result::ACCEPT) {
445
myValueTextField->setText(fileDialog.getFilename().c_str(), TRUE);
446
}
447
return 1;
448
}
449
450
451
long
452
GNEAttributesEditorRow::onCmdReparent(FXObject*, FXSelector, void*) {
453
myAttributeTable->enableReparent();
454
return 1;
455
}
456
457
458
long
459
GNEAttributesEditorRow::onCmdInspectParent(FXObject*, FXSelector, void*) {
460
myAttributeTable->inspectParent();
461
return 1;
462
}
463
464
465
long
466
GNEAttributesEditorRow::onCmdMoveLaneUp(FXObject*, FXSelector, void*) {
467
myAttributeTable->moveLaneUp();
468
return 1;
469
}
470
471
472
long
473
GNEAttributesEditorRow::onCmdMoveLaneDown(FXObject*, FXSelector, void*) {
474
myAttributeTable->moveLaneDown();
475
return 1;
476
}
477
478
479
long
480
GNEAttributesEditorRow::onCmdSetAttribute(FXObject* obj, FXSelector, void*) {
481
if (myAttributeTable->myEditedACs.empty()) {
482
return 0;
483
}
484
const auto& editedAC = myAttributeTable->myEditedACs.front();
485
const auto attribute = myAttrProperty->getAttr();
486
// continue depending of clicked object
487
if (obj == myValueCheckButton) {
488
// Set true o false depending of the checkBox
489
if (myValueCheckButton->getCheck()) {
490
myValueCheckButton->setText("true");
491
} else {
492
myValueCheckButton->setText("false");
493
}
494
myAttributeTable->setAttribute(attribute, myValueCheckButton->getText().text());
495
} else if (obj == myValueComboBox) {
496
const std::string newValue = myValueComboBox->getText().text();
497
// check if the new comboBox value is valid
498
if (editedAC->isValid(attribute, newValue)) {
499
myValueComboBox->setTextColor(GUIDesignTextColorBlack);
500
myValueComboBox->setBackColor(GUIDesignBackgroundColorWhite);
501
myValueComboBox->killFocus();
502
myAttributeTable->setAttribute(attribute, newValue);
503
} else {
504
// edit colors
505
myValueComboBox->setTextColor(GUIDesignTextColorRed);
506
if (newValue.empty()) {
507
myValueComboBox->setBackColor(GUIDesignBackgroundColorRed);
508
}
509
}
510
} else if (obj == myValueTextField) {
511
// first check if set default value
512
if (myValueTextField->getText().empty() && myAttrProperty->hasDefaultValue() && !myAttrProperty->isVClass()) {
513
// update text field without notify
514
myValueTextField->setText(myAttrProperty->getDefaultStringValue().c_str(), FALSE);
515
}
516
// if we're editing an angle, check if filter between [0,360]
517
if ((attribute == SUMO_ATTR_ANGLE) && GNEAttributeCarrier::canParse<double>(myValueTextField->getText().text())) {
518
// filter anglea and update text field without notify
519
const double angle = fmod(GNEAttributeCarrier::parse<double>(myValueTextField->getText().text()), 360);
520
myValueTextField->setText(toString(angle).c_str(), FALSE);
521
}
522
// if we're editing a position or a shape, strip whitespace after comma
523
if ((attribute == SUMO_ATTR_POSITION) || (attribute == SUMO_ATTR_SHAPE)) {
524
std::string shape(myValueTextField->getText().text());
525
while (shape.find(", ") != std::string::npos) {
526
shape = StringUtils::replace(shape, ", ", ",");
527
}
528
myValueTextField->setText(toString(shape).c_str(), FALSE);
529
}
530
// if we're editing a int, strip decimal value
531
if (myAttrProperty->isInt() && GNEAttributeCarrier::canParse<double>(myValueTextField->getText().text())) {
532
double doubleValue = GNEAttributeCarrier::parse<double>(myValueTextField->getText().text());
533
if ((doubleValue - (int)doubleValue) == 0) {
534
myValueTextField->setText(toString((int)doubleValue).c_str(), FALSE);
535
}
536
}
537
// after apply all filters, obtain value
538
const std::string newValue = myValueTextField->getText().text();
539
// check if the new textField value is valid
540
if (editedAC->isValid(attribute, newValue)) {
541
myValueTextField->setTextColor(GUIDesignTextColorBlack);
542
myValueTextField->setBackColor(GUIDesignBackgroundColorWhite);
543
myValueTextField->killFocus();
544
if (myAttributeTable->isEditorTypeEditor() || newValue.empty() || (attribute != SUMO_ATTR_ID)) {
545
myAttributeTable->setAttribute(attribute, newValue);
546
}
547
} else {
548
// edit colors
549
myValueTextField->setTextColor(GUIDesignTextColorRed);
550
if (newValue.empty()) {
551
myValueTextField->setBackColor(GUIDesignBackgroundColorRed);
552
}
553
}
554
}
555
return 1;
556
}
557
558
559
long
560
GNEAttributesEditorRow::onCmdToggleEnableAttribute(FXObject*, FXSelector, void*) {
561
myAttributeTable->toggleEnableAttribute(myAttrProperty->getAttr(), myAttributeToggleEnableCheckButton->getCheck() == TRUE);
562
return 0;
563
}
564
565
566
GNEAttributesEditorRow::GNEAttributesEditorRow() :
567
myAttributeTable(nullptr) {
568
}
569
570
571
const std::string
572
GNEAttributesEditorRow::getAttributeValue(const bool enabled) const {
573
const auto attribute = myAttrProperty->getAttr();
574
// if we're in creator mode, generate ID
575
if ((attribute == SUMO_ATTR_ID) && (myAttributeTable->myEditorType == GNEAttributesEditorType::EditorType::CREATOR)) {
576
const auto& ACs = myAttributeTable->getFrameParent()->getViewNet()->getNet()->getAttributeCarriers();
577
const auto parentTag = myAttrProperty->getTagPropertyParent()->getTag();
578
if (myAttrProperty->getTagPropertyParent()->getTag() == SUMO_TAG_EDGE) {
579
return ACs->generateEdgeID();
580
} else if (myAttrProperty->getTagPropertyParent()->isAdditionalElement()) {
581
return ACs->generateAdditionalID(parentTag);
582
} else if (myAttrProperty->getTagPropertyParent()->isDemandElement()) {
583
return ACs->generateDemandElementID(parentTag);
584
} else if (myAttrProperty->getTagPropertyParent()->isMeanData()) {
585
return ACs->generateMeanDataID(parentTag);
586
} else if (parentTag == SUMO_TAG_TYPE) {
587
return ACs->generateEdgeTypeID();
588
} else if (parentTag == SUMO_TAG_DATASET) {
589
return ACs->generateDataSetID();
590
}
591
}
592
if (enabled) {
593
// Declare a set of occurring values and insert attribute's values of item (note: We use a set to avoid repeated values)
594
std::set<std::string> values;
595
// iterate over edited attributes and insert every value in set
596
for (const auto& editedAC : myAttributeTable->myEditedACs) {
597
if (editedAC->hasAttribute(attribute)) {
598
values.insert(editedAC->getAttribute(attribute));
599
}
600
}
601
// merge all values in a single string
602
std::ostringstream oss;
603
for (auto it = values.begin(); it != values.end(); it++) {
604
if (it != values.begin()) {
605
oss << " ";
606
}
607
oss << *it;
608
}
609
// obtain value to be shown in row
610
return oss.str();
611
} else {
612
return myAttributeTable->myEditedACs.front()->getAlternativeValueForDisabledAttributes(attribute);
613
}
614
}
615
616
617
void
618
GNEAttributesEditorRow::showAttributeToggleEnable(const GNEAttributeProperties* attrProperty, const bool value) {
619
myAttributeToggleEnableCheckButton->setText(attrProperty->getAttrStr().c_str());
620
myAttributeToggleEnableCheckButton->setCheck(value);
621
myAttributeToggleEnableCheckButton->enable();
622
myAttributeToggleEnableCheckButton->show();
623
// hide other elements
624
myAttributeLabel->hide();
625
myAttributeButton->hide();
626
}
627
628
629
void
630
GNEAttributesEditorRow::showAttributeReparent(const bool enabled) {
631
// update attribute button
632
myAttributeButton->setText(TL("Reparent"));
633
myAttributeButton->setHelpText(TL("Change parent of this element"));
634
myAttributeButton->setTipText(myAttributeButton->getHelpText());
635
myAttributeButton->setIcon(nullptr);
636
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_REPARENT);
637
if (enabled) {
638
myAttributeButton->enable();
639
} else {
640
myAttributeButton->disable();
641
}
642
myAttributeButton->show();
643
// hide other elements
644
myAttributeLabel->hide();
645
myAttributeToggleEnableCheckButton->hide();
646
}
647
648
649
void
650
GNEAttributesEditorRow::showAttributeInspectParent(const GNEAttributeProperties* attrProperty, const bool enabled) {
651
// update attribute button
652
myAttributeButton->setText(attrProperty->getAttrStr().c_str());
653
myAttributeButton->setHelpText(TLF("Inspect % parent", attrProperty->getAttrStr()).c_str());
654
myAttributeButton->setTipText(myAttributeButton->getHelpText());
655
myAttributeButton->setIcon(GUIIconSubSys::getIcon(attrProperty->getTagPropertyParent()->getGUIIcon()));
656
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_INSPECTPARENT);
657
if (enabled) {
658
myAttributeButton->enable();
659
} else {
660
myAttributeButton->disable();
661
}
662
myAttributeButton->show();
663
// hide other elements
664
myAttributeLabel->hide();
665
myAttributeToggleEnableCheckButton->hide();
666
}
667
668
669
void
670
GNEAttributesEditorRow::showAttributeVClass(const GNEAttributeProperties* attrProperty, const bool enabled) {
671
// update attribute button
672
myAttributeButton->setText(attrProperty->getAttrStr().c_str());
673
myAttributeButton->setHelpText(TL("Open dialog for editing vClasses"));
674
myAttributeButton->setTipText(myAttributeButton->getHelpText());
675
myAttributeButton->setIcon(nullptr);
676
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_ALLOW);
677
if (enabled) {
678
myAttributeButton->enable();
679
} else {
680
myAttributeButton->disable();
681
}
682
myAttributeButton->show();
683
// hide other elements
684
myAttributeLabel->hide();
685
myAttributeToggleEnableCheckButton->hide();
686
}
687
688
689
void
690
GNEAttributesEditorRow::showAttributeColor(const GNEAttributeProperties* attrProperty, const bool enabled) {
691
// update attribute button
692
myAttributeButton->setText(attrProperty->getAttrStr().c_str());
693
myAttributeButton->setHelpText(TL("Open dialog for editing color"));
694
myAttributeButton->setTipText(myAttributeButton->getHelpText());
695
myAttributeButton->setIcon(GUIIconSubSys::getIcon(GUIIcon::COLORWHEEL));
696
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_COLOR);
697
if (enabled) {
698
myAttributeButton->enable();
699
} else {
700
myAttributeButton->disable();
701
}
702
myAttributeButton->show();
703
// hide other elements
704
myAttributeLabel->hide();
705
myAttributeToggleEnableCheckButton->hide();
706
}
707
708
709
void
710
GNEAttributesEditorRow::showAttributeFile(const GNEAttributeProperties* attrProperty, const bool enabled) {
711
// update attribute button
712
myAttributeButton->setText(attrProperty->getAttrStr().c_str());
713
if (attrProperty->isFileOpen()) {
714
myAttributeButton->setHelpText(TL("Open dialog to select an existent file"));
715
} else {
716
myAttributeButton->setHelpText(TL("Open dialog to select or create an existent file"));
717
}
718
myAttributeButton->setTipText(myAttributeButton->getHelpText());
719
myAttributeButton->setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN));
720
myAttributeButton->setSelector(MID_GNE_ATTRIBUTESEDITORROW_OPENDIALOG_FILE);
721
if (enabled) {
722
myAttributeButton->enable();
723
} else {
724
myAttributeButton->disable();
725
}
726
myAttributeButton->show();
727
// hide other elements
728
myAttributeLabel->hide();
729
myAttributeToggleEnableCheckButton->hide();
730
}
731
732
733
void
734
GNEAttributesEditorRow::showAttributeLabel(const GNEAttributeProperties* attrProperty) {
735
myAttributeLabel->setText(attrProperty->getAttrStr().c_str());
736
myAttributeLabel->setTipText(attrProperty->getDefinition().c_str());
737
myAttributeLabel->show();
738
// hide other elements
739
myAttributeToggleEnableCheckButton->hide();
740
myAttributeButton->hide();
741
}
742
743
744
void
745
GNEAttributesEditorRow::hideAllAttributeElements() {
746
myAttributeLabel->hide();
747
myAttributeToggleEnableCheckButton->hide();
748
myAttributeButton->hide();
749
}
750
751
752
void
753
GNEAttributesEditorRow::showValueCheckButton(const std::string& value,
754
const bool enabled, const bool computed) {
755
// first we need to check if all boolean values are equal
756
bool allValuesEqual = true;
757
// declare boolean vector
758
std::vector<bool> booleanVector;
759
// check if value can be parsed to a boolean vector
760
if (GNEAttributeCarrier::canParse<std::vector<bool> >(value)) {
761
booleanVector = GNEAttributeCarrier::parse<std::vector<bool> >(value);
762
}
763
// iterate over booleans comparing all element with the first
764
for (const auto booleanValue : booleanVector) {
765
if (booleanValue != booleanVector.front()) {
766
allValuesEqual = false;
767
}
768
}
769
// use checkbox or textfield depending if all booleans are equal
770
if (allValuesEqual) {
771
if (enabled) {
772
myValueCheckButton->enable();
773
} else {
774
myValueCheckButton->disable();
775
}
776
// set check button
777
if ((booleanVector.size() > 0) && booleanVector.front()) {
778
myValueCheckButton->setCheck(true);
779
myValueCheckButton->setText("true");
780
} else {
781
myValueCheckButton->setCheck(false);
782
myValueCheckButton->setText("false");
783
}
784
// show check button
785
myValueCheckButton->show();
786
// hide other value elements
787
myValueTextField->hide();
788
myValueComboBox->hide();
789
myValueLaneUpButton->hide();
790
myValueLaneDownButton->hide();
791
} else {
792
// show value as string
793
showValueString(value, enabled, computed);
794
}
795
}
796
797
798
void
799
GNEAttributesEditorRow::showValueComboBox(const GNEAttributeProperties* attrProperty, const std::string& value,
800
const bool enabled, const bool computed) {
801
// first we need to check if all boolean values are equal
802
bool allValuesEqual = true;
803
// declare boolean vector
804
std::vector<std::string> stringVector = GNEAttributeCarrier::parse<std::vector<std::string> >(value);
805
// iterate over string comparing all element with the first
806
for (const auto& stringValue : stringVector) {
807
if (stringValue != stringVector.front()) {
808
allValuesEqual = false;
809
}
810
}
811
// use checkbox or textfield depending if all booleans are equal
812
if (allValuesEqual) {
813
// clear and enable comboBox
814
myValueComboBox->clearItems();
815
myValueComboBox->setTextColor(GUIDesignTextColorBlack);
816
myValueComboBox->setBackColor(GUIDesignBackgroundColorWhite);
817
if (enabled) {
818
myValueComboBox->enable();
819
} else {
820
myValueComboBox->disable();
821
}
822
// fill depeding of ACAttr
823
if (attrProperty->getAttr() == SUMO_ATTR_VCLASS) {
824
// add all vClasses with their icons
825
for (const auto& vClassStr : SumoVehicleClassStrings.getStrings()) {
826
myValueComboBox->appendIconItem(vClassStr.c_str(), VClassIcons::getVClassIcon(getVehicleClassID(vClassStr)));
827
}
828
} else if (attrProperty->isVType()) {
829
// get ACs
830
const auto& ACs = myAttributeTable->myFrameParent->getViewNet()->getNet()->getAttributeCarriers();
831
// fill comboBox with all vTypes and vType distributions sorted by ID
832
std::map<std::string, GNEDemandElement*> sortedTypes;
833
for (const auto& type : ACs->getDemandElements().at(SUMO_TAG_VTYPE)) {
834
sortedTypes[type.second->getID()] = type.second;
835
}
836
for (const auto& sortedType : sortedTypes) {
837
myValueComboBox->appendIconItem(sortedType.first.c_str(), sortedType.second->getACIcon());
838
}
839
sortedTypes.clear();
840
for (const auto& typeDistribution : ACs->getDemandElements().at(SUMO_TAG_VTYPE_DISTRIBUTION)) {
841
sortedTypes[typeDistribution.second->getID()] = typeDistribution.second;
842
}
843
for (const auto& sortedType : sortedTypes) {
844
myValueComboBox->appendIconItem(sortedType.first.c_str(), sortedType.second->getACIcon());
845
}
846
} else if (attrProperty->getAttr() == SUMO_ATTR_ICON) {
847
// add all POIIcons with their icons
848
for (const auto& POIIcon : SUMOXMLDefinitions::POIIcons.getValues()) {
849
myValueComboBox->appendIconItem(SUMOXMLDefinitions::POIIcons.getString(POIIcon).c_str(), POIIcons::getPOIIcon(POIIcon));
850
}
851
} else if ((attrProperty->getAttr() == SUMO_ATTR_RIGHT_OF_WAY) && (myAttributeTable->myEditedACs.size() == 1) &&
852
(attrProperty->getTagPropertyParent()->getTag() == SUMO_TAG_JUNCTION)) {
853
// special case for junction types
854
if (myAttributeTable->myEditedACs.front()->getAttribute(SUMO_ATTR_TYPE) == "priority") {
855
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::DEFAULT).c_str(), nullptr);
856
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::EDGEPRIORITY).c_str(), nullptr);
857
} else if (myAttributeTable->myEditedACs.front()->getAttribute(SUMO_ATTR_TYPE) == "traffic_light") {
858
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::DEFAULT).c_str(), nullptr);
859
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::MIXEDPRIORITY).c_str(), nullptr);
860
myValueComboBox->appendIconItem(SUMOXMLDefinitions::RightOfWayValues.getString(RightOfWay::ALLWAYSTOP).c_str(), nullptr);
861
} else {
862
myValueComboBox->disable();
863
}
864
} else {
865
// fill comboBox with discrete values
866
for (const auto& discreteValue : attrProperty->getDiscreteValues()) {
867
myValueComboBox->appendIconItem(discreteValue.c_str(), nullptr);
868
}
869
}
870
// set current value (or disable)
871
const auto index = myValueComboBox->findItem(value.c_str());
872
if (index < 0) {
873
if (myValueComboBox->getNumItems() > 0) {
874
myValueComboBox->setCurrentItem(0);
875
} else {
876
myValueComboBox->disable();
877
}
878
} else {
879
myValueComboBox->setCurrentItem(index);
880
}
881
// show comboBox button
882
myValueComboBox->show();
883
// hide other value elements
884
myValueTextField->hide();
885
myValueCheckButton->hide();
886
myValueLaneUpButton->hide();
887
myValueLaneDownButton->hide();
888
} else {
889
// show value as string
890
showValueString(value, enabled, computed);
891
}
892
}
893
894
895
void
896
GNEAttributesEditorRow::showValueString(const std::string& value, const bool enabled, const bool computed) {
897
// clear and enable comboBox
898
myValueTextField->setText(value.c_str());
899
if (computed) {
900
myValueTextField->setTextColor(GUIDesignTextColorBlue);
901
} else {
902
myValueTextField->setTextColor(GUIDesignTextColorBlack);
903
}
904
if (enabled) {
905
myValueTextField->enable();
906
} else {
907
myValueTextField->disable();
908
}
909
// show list of values
910
myValueTextField->show();
911
// hide other value elements
912
myValueCheckButton->hide();
913
myValueComboBox->hide();
914
}
915
916
917
void
918
GNEAttributesEditorRow::showMoveLaneButtons(const std::string& laneID) {
919
// retrieve lane
920
const auto lane = myAttributeTable->myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveLane(laneID, false);
921
// check lane
922
if (lane) {
923
// check if disable move up
924
if ((lane->getIndex() + 1) >= (int)lane->getParentEdge()->getChildLanes().size()) {
925
myValueLaneUpButton->disable();
926
} else {
927
myValueLaneUpButton->enable();
928
}
929
// check if disable move down
930
if ((lane->getIndex() - 1) < 0) {
931
myValueLaneDownButton->disable();
932
} else {
933
myValueLaneDownButton->enable();
934
}
935
} else {
936
// if lane doesn't exist, disable both
937
myValueLaneUpButton->disable();
938
myValueLaneDownButton->disable();
939
}
940
}
941
942
943
void
944
GNEAttributesEditorRow::enableElements(const GNEAttributeProperties* attrProperty, const bool forceDisable) {
945
const auto& editModes = myAttributeTable->myFrameParent->getViewNet()->getEditModes();
946
const auto tagProperty = attrProperty->getTagPropertyParent();
947
// by default we assume that elements are disabled
948
bool enableElements = false;
949
if (forceDisable) {
950
enableElements = false;
951
} else if (editModes.isCurrentSupermodeNetwork()) {
952
if (tagProperty->isNetworkElement() || tagProperty->isAdditionalElement()) {
953
enableElements = true;
954
} else if ((tagProperty->getTag() == SUMO_TAG_TAZSOURCE) || (tagProperty->getTag() == SUMO_TAG_TAZSINK)) {
955
enableElements = true;
956
}
957
} else if (editModes.isCurrentSupermodeDemand() && tagProperty->isDemandElement()) {
958
enableElements = true;
959
} else if (editModes.isCurrentSupermodeData() && (tagProperty->isDataElement() || tagProperty->isMeanData())) {
960
enableElements = true;
961
}
962
if (!enableElements) {
963
myAttributeToggleEnableCheckButton->disable();
964
myAttributeButton->disable();
965
myValueTextField->disable();
966
myValueComboBox->disable();
967
myValueCheckButton->disable();
968
myValueLaneUpButton->disable();
969
myValueLaneDownButton->disable();
970
}
971
}
972
973
974
bool
975
GNEAttributesEditorRow::isAttributeEnabled(const GNEAttributeProperties* attrProperty) const {
976
if (attrProperty->isAlwaysEnabled()) {
977
return true;
978
} else {
979
for (const auto& AC : myAttributeTable->myEditedACs) {
980
if (AC->isAttributeEnabled(attrProperty->getAttr())) {
981
return true;
982
}
983
}
984
return false;
985
}
986
}
987
988
/****************************************************************************/
989
990