Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNEFrameAttributeModules.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2023 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/****************************************************************************/
18// Auxiliary class for GNEFrame Modules (only for attributes edition)
19/****************************************************************************/
20#include <config.h>
21
23#include <netedit/GNENet.h>
24#include <netedit/GNEUndoList.h>
25#include <netedit/GNEViewNet.h>
36
38#include "GNEFlowEditor.h"
39
40
41// ===========================================================================
42// FOX callback mapping
43// ===========================================================================
44
51
55
59
64
69
70// Object implementation
71FXIMPLEMENT(GNEFrameAttributeModules::AttributesEditorRow, FXHorizontalFrame, AttributesEditorRowMap, ARRAYNUMBER(AttributesEditorRowMap))
72FXIMPLEMENT(GNEFrameAttributeModules::AttributesEditor, MFXGroupBoxModule, AttributesEditorMap, ARRAYNUMBER(AttributesEditorMap))
73FXIMPLEMENT(GNEFrameAttributeModules::AttributesEditorExtended, MFXGroupBoxModule, AttributesEditorExtendedMap, ARRAYNUMBER(AttributesEditorExtendedMap))
74FXIMPLEMENT(GNEFrameAttributeModules::GenericDataAttributes, MFXGroupBoxModule, GenericDataAttributesMap, ARRAYNUMBER(GenericDataAttributesMap))
75FXIMPLEMENT(GNEFrameAttributeModules::ParametersEditor, MFXGroupBoxModule, ParametersEditorMap, ARRAYNUMBER(ParametersEditorMap))
76
77
78// ===========================================================================
79// method definitions
80// ===========================================================================
81
82// ---------------------------------------------------------------------------
83// GNEFrameAttributeModules::AttributesEditorRow - methods
84// ---------------------------------------------------------------------------
85
87 const std::string& value, const bool attributeEnabled, const bool computed, GNEAttributeCarrier* ACParent) :
88 FXHorizontalFrame(attributeEditorParent->getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame),
89 myAttributesEditorParent(attributeEditorParent),
90 myACAttr(ACAttr),
91 myACParent(ACParent) {
92 // Create and hide label
93 myAttributeLabel = new MFXLabelTooltip(this,
94 attributeEditorParent->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
95 "attributeLabel", nullptr, GUIDesignLabelThickedFixed(100));
96 myAttributeLabel->hide();
97 // Create and hide check button
98 myAttributeCheckButton = new FXCheckButton(this, "attributeCheckButton", this, MID_GNE_SET_ATTRIBUTE_BOOL, GUIDesignCheckButtonAttribute);
99 myAttributeCheckButton->hide();
100 // Create and hide ButtonCombinableChoices
101 myAttributeAllowButton = new MFXButtonTooltip(this,
102 attributeEditorParent->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
103 "attributeAllowButton", nullptr, this, MID_GNE_SET_ATTRIBUTE_DIALOG, GUIDesignButtonAttribute);
104 myAttributeAllowButton->hide();
105 // create and hide color editor
106 myAttributeColorButton = new MFXButtonTooltip(this,
107 attributeEditorParent->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
108 "attributeColorButton", nullptr, this, MID_GNE_SET_ATTRIBUTE_DIALOG, GUIDesignButtonAttribute);
109 myAttributeColorButton->hide();
110 // create and hide color editor
111 myAttributeVTypeButton = new MFXButtonTooltip(this,
112 attributeEditorParent->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
113 "attributeVTypeButton", myACParent ? myACParent->getACIcon() : nullptr, this, MID_GNE_SET_ATTRIBUTE_VTYPE, GUIDesignButtonAttribute);
114 myAttributeVTypeButton->hide();
115 // Create and hide MFXTextFieldTooltip for string attributes
116 myValueTextField = new MFXTextFieldTooltip(this,
117 attributeEditorParent->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
119 myValueTextField->hide();
120 // Create and hide ComboBox
121 myValueChoicesComboBox = new MFXComboBoxIcon(this, GUIDesignComboBoxNCol, (ACAttr.getAttr() == SUMO_ATTR_VCLASS), this, MID_GNE_SET_ATTRIBUTE, GUIDesignComboBoxAttribute);
122 myValueChoicesComboBox->hide();
123 // Create and hide checkButton
124 myValueCheckButton = new FXCheckButton(this, "", this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
125 myValueCheckButton->hide();
126 // only create if parent was created
127 if (getParent()->id()) {
128 // create AttributesEditorRow
129 FXHorizontalFrame::create();
130 // start enabling all elements, depending if attribute is enabled
131 if (attributeEnabled == false) {
132 myValueTextField->disable();
133 myValueChoicesComboBox->disable();
134 myValueCheckButton->disable();
135 } else {
136 myValueTextField->enable();
137 myValueChoicesComboBox->enable();
138 myValueCheckButton->enable();
139 }
140 // if Tag correspond to an network element but we're in demand mode (or vice versa), disable all elements
141 if (myACAttr.getAttr() != SUMO_ATTR_NOTHING) {
142 if (isSupermodeValid(myAttributesEditorParent->getFrameParent()->getViewNet(), myACAttr)) {
143 myAttributeAllowButton->enable();
144 myAttributeColorButton->enable();
145 myAttributeVTypeButton->enable();
146 myAttributeCheckButton->enable();
147 } else {
148 myAttributeColorButton->disable();
149 myAttributeVTypeButton->disable();
150 myAttributeCheckButton->disable();
151 myValueTextField->disable();
152 myValueChoicesComboBox->disable();
153 myValueCheckButton->disable();
154 myAttributeAllowButton->disable();
155 }
156 }
157 // set left column
158 if (myACParent) {
159 // show color button and set color text depending of computed
160 if (computed) {
161 myAttributeVTypeButton->setTextColor(FXRGB(0, 0, 255));
162 } else {
163 myAttributeVTypeButton->setTextColor(FXRGB(0, 0, 0));
164 myAttributeVTypeButton->killFocus();
165 }
166 myAttributeVTypeButton->setText(myACAttr.getAttrStr().c_str());
167 myAttributeVTypeButton->setTipText((TL("Inspect vehicle ") + myACAttr.getAttrStr() + " parent").c_str());
168 myAttributeVTypeButton->setHelpText((TL("Inspect vehicle ") + myACAttr.getAttrStr() + " parent").c_str());
169 myAttributeVTypeButton->show();
170 } else if (myACAttr.isColor()) {
171 // show color button and set color text depending of computed
172 if (computed) {
173 myAttributeColorButton->setTextColor(FXRGB(0, 0, 255));
174 } else {
175 myAttributeColorButton->setTextColor(FXRGB(0, 0, 0));
176 myAttributeColorButton->killFocus();
177 }
178 myAttributeColorButton->setText(myACAttr.getAttrStr().c_str());
179 myAttributeColorButton->setTipText(TL("Open dialog for editing color"));
180 myAttributeColorButton->setHelpText(TL("Open dialog for editing color"));
181 myAttributeColorButton->show();
182 } else if (myACAttr.getAttr() == SUMO_ATTR_ALLOW) {
183 myAttributeAllowButton->setText(myACAttr.getAttrStr().c_str());
184 myAttributeAllowButton->setTipText(TL("Open dialog for editing allowed vClasses"));
185 myAttributeAllowButton->setHelpText(TL("Open dialog for editing allowed vClasses"));
186 myAttributeAllowButton->show();
187 } else if (myACAttr.isActivatable()) {
188 // show checkbox button and set color text depending of computed
189 if (computed) {
190 myAttributeCheckButton->setTextColor(FXRGB(0, 0, 255));
191 } else {
192 myAttributeCheckButton->setTextColor(FXRGB(0, 0, 0));
193 myAttributeCheckButton->killFocus();
194 }
195 myAttributeCheckButton->setText(myACAttr.getAttrStr().c_str());
196 myAttributeCheckButton->show();
197 // check or uncheck depending of attributeEnabled
198 if (attributeEnabled) {
199 myAttributeCheckButton->setCheck(TRUE);
200 } else {
201 myAttributeCheckButton->setCheck(FALSE);
202 }
203 } else {
204 // Show attribute Label
205 myAttributeLabel->setText(myACAttr.getAttrStr().c_str());
206 myAttributeLabel->setTipText(myACAttr.getDefinition().c_str());
207 myAttributeLabel->show();
208 }
209 // Set field depending of the type of value
210 if (myACAttr.isBool()) {
211 // first we need to check if all boolean values are equal
212 bool allBooleanValuesEqual = true;
213 // declare boolean vector
214 std::vector<bool> booleanVector;
215 // check if value can be parsed to a boolean vector
216 if (GNEAttributeCarrier::canParse<std::vector<bool> >(value)) {
217 booleanVector = GNEAttributeCarrier::parse<std::vector<bool> >(value);
218 }
219 // iterate over passed booleans comparing all element with the first
220 for (const auto& booleanValue : booleanVector) {
221 if (booleanValue != booleanVector.front()) {
222 allBooleanValuesEqual = false;
223 }
224 }
225 // use checkbox or textfield depending if all booleans are equal
226 if (allBooleanValuesEqual) {
227 // set check button
228 if ((booleanVector.size() > 0) && booleanVector.front()) {
229 myValueCheckButton->setCheck(true);
230 myValueCheckButton->setText("true");
231 } else {
232 myValueCheckButton->setCheck(false);
233 myValueCheckButton->setText("false");
234 }
235 // show check button
236 myValueCheckButton->show();
237 } else {
238 // show list of bools (0 1)
239 myValueTextField->setText(value.c_str());
240 // set text depending of computed
241 if (computed) {
242 myValueTextField->setTextColor(FXRGB(0, 0, 255));
243 } else {
244 myValueTextField->setTextColor(FXRGB(0, 0, 0));
245 myValueTextField->killFocus();
246 }
247 myValueTextField->show();
248 }
249 } else if (myACAttr.isDiscrete()) {
250 // Check if are VClasses
251 if ((myACAttr.getDiscreteValues().size() > 0) && myACAttr.isVClasses()) {
252 // hide label
253 myAttributeLabel->hide();
254 // Show button combinable choices
255 myAttributeAllowButton->setText(myACAttr.getAttrStr().c_str());
256 myAttributeAllowButton->setTipText(TL("Open dialog for editing allowed vClasses"));
257 myAttributeAllowButton->setHelpText(TL("Open dialog for editing allowed vClasses"));
258 myAttributeAllowButton->show();
259 // Show string with the values
260 myValueTextField->setText(value.c_str());
261 // set color depending of computed
262 if (computed) {
263 myValueTextField->setTextColor(FXRGB(0, 0, 255));
264 } else {
265 myValueTextField->setTextColor(FXRGB(0, 0, 0));
266 myValueTextField->killFocus();
267 }
268 myValueTextField->show();
269 } else {
270 // fill comboBox
271 myValueChoicesComboBox->clearItems();
272 // special case for VClass
273 if (ACAttr.getAttr() == SUMO_ATTR_VCLASS) {
274 // add all vClasses with their icons
275 for (const auto& vClassStr : SumoVehicleClassStrings.getStrings()) {
276 myValueChoicesComboBox->appendIconItem(vClassStr.c_str(), VClassIcons::getVClassIcon(getVehicleClassID(vClassStr)));
277 }
278 } else {
279 for (const auto& discreteValue : myACAttr.getDiscreteValues()) {
280 myValueChoicesComboBox->appendIconItem(discreteValue.c_str());
281 }
282 }
283 // show combo box with values
284 if (myACAttr.showAllDiscreteValues()) {
285 myValueChoicesComboBox->setNumVisible(myValueChoicesComboBox->getNumItems());
286 } else {
287 myValueChoicesComboBox->setNumVisible(myValueChoicesComboBox->getNumItems() < 10 ? myValueChoicesComboBox->getNumItems() : 10);
288 }
289 const int itemIndex = myValueChoicesComboBox->findItem(value.c_str());
290 if (itemIndex == -1) {
291 myValueChoicesComboBox->setText(value.c_str());
292 } else {
293 myValueChoicesComboBox->setCurrentItem(itemIndex);
294 }
295 // set color depending of computed
296 if (computed) {
297 myValueChoicesComboBox->setTextColor(FXRGB(0, 0, 255));
298 } else {
299 myValueChoicesComboBox->setTextColor(FXRGB(0, 0, 0));
300 myValueChoicesComboBox->killFocus();
301 }
302 myValueChoicesComboBox->show();
303 }
304 } else if (ACParent && myACAttr.isVType() && (myACAttr.getAttr() == SUMO_ATTR_TYPE)) {
305 // fill comboBox with vTypes and vType distributions
306 myValueChoicesComboBox->clearItems();
307 for (const auto& vType : ACParent->getNet()->getAttributeCarriers()->getDemandElements().at(SUMO_TAG_VTYPE)) {
308 myValueChoicesComboBox->appendIconItem(vType->getID().c_str(), vType->getACIcon());
309 }
310 for (const auto& vType : ACParent->getNet()->getAttributeCarriers()->getDemandElements().at(SUMO_TAG_VTYPE_DISTRIBUTION)) {
311 myValueChoicesComboBox->appendIconItem(vType->getID().c_str(), vType->getACIcon());
312 }
313 // show only 10 vtypes
314 myValueChoicesComboBox->setNumVisible(myValueChoicesComboBox->getNumItems() < 10 ? myValueChoicesComboBox->getNumItems() : 10);
315 const int itemIndex = myValueChoicesComboBox->findItem(value.c_str());
316 if (itemIndex == -1) {
317 myValueChoicesComboBox->setText(value.c_str());
318 } else {
319 myValueChoicesComboBox->setCurrentItem(itemIndex);
320 }
321 // set color depending of computed
322 if (computed) {
323 myValueChoicesComboBox->setTextColor(FXRGB(0, 0, 255));
324 } else {
325 myValueChoicesComboBox->setTextColor(FXRGB(0, 0, 0));
326 myValueChoicesComboBox->killFocus();
327 }
328 myValueChoicesComboBox->show();
329 } else {
330 // In any other case (String, list, etc.), show value as String
331 myValueTextField->setText(value.c_str());
332 // set color depending of computed
333 if (computed) {
334 myValueTextField->setTextColor(FXRGB(0, 0, 255));
335 } else {
336 myValueTextField->setTextColor(FXRGB(0, 0, 0));
337 myValueTextField->killFocus();
338 }
339 myValueTextField->show();
340 }
341 // Show AttributesEditorRow
342 show();
343 }
344}
345
346
347void
349 // only destroy if parent was created
350 if (getParent()->id()) {
351 FXHorizontalFrame::destroy();
352 }
353}
354
355
356void
358 const bool forceRefresh, const bool attributeEnabled, const bool computed, GNEAttributeCarrier* ACParent) {
359 if (ACParent) {
360 myACParent = ACParent;
361 }
362 // start enabling all elements, depending if attribute is enabled
363 if (attributeEnabled == false) {
364 myValueTextField->disable();
365 myValueChoicesComboBox->disable();
366 myValueCheckButton->disable();
367 } else {
368 myValueTextField->enable();
369 myValueChoicesComboBox->enable();
370 myValueCheckButton->enable();
371 }
372 // if Tag correspond to an network element but we're in demand mode (or vice versa), disable all elements
373 if (myACAttr.getAttr() != SUMO_ATTR_NOTHING) {
374 if (isSupermodeValid(myAttributesEditorParent->getFrameParent()->getViewNet(), myACAttr)) {
375 myAttributeAllowButton->enable();
376 myAttributeColorButton->enable();
377 myAttributeCheckButton->enable();
378 } else {
379 myAttributeColorButton->disable();
380 myAttributeCheckButton->disable();
381 myValueTextField->disable();
382 myValueChoicesComboBox->disable();
383 myValueCheckButton->disable();
384 myAttributeAllowButton->disable();
385 }
386 }
387 // set check button
388 if (myAttributeCheckButton->shown()) {
389 myAttributeCheckButton->setCheck(attributeEnabled);
390 }
391 if ((myAttributesEditorParent->getFrameParent()->getViewNet()->getInspectedAttributeCarriers().size() == 1) &&
392 ACParent && myACAttr.isVType() && (myACAttr.getAttr() == SUMO_ATTR_TYPE)) {
393 // fill comboBox with vTypes
394 myValueChoicesComboBox->clearItems();
395 for (const auto& vType : ACParent->getNet()->getAttributeCarriers()->getDemandElements().at(SUMO_TAG_VTYPE)) {
396 myValueChoicesComboBox->appendIconItem(vType->getID().c_str(), vType->getACIcon());
397 }
398 for (const auto& vType : ACParent->getNet()->getAttributeCarriers()->getDemandElements().at(SUMO_TAG_VTYPE_DISTRIBUTION)) {
399 myValueChoicesComboBox->appendIconItem(vType->getID().c_str(), vType->getACIcon());
400 }
401 // show only 10 vtypes
402 myValueChoicesComboBox->setNumVisible(myValueChoicesComboBox->getNumItems() < 10 ? myValueChoicesComboBox->getNumItems() : 10);
403 myValueChoicesComboBox->setCurrentItem(myValueChoicesComboBox->findItem(value.c_str()));
404 myValueChoicesComboBox->show();
405 } else if (myValueTextField->shown()) {
406 // set last valid value and restore color if onlyValid is disabled
407 if (myValueTextField->getTextColor() == FXRGB(0, 0, 0) || myValueTextField->getTextColor() == FXRGB(0, 0, 255) || forceRefresh) {
408 myValueTextField->setText(value.c_str());
409 // set blue color if is an computed value
410 if (computed) {
411 myValueTextField->setTextColor(FXRGB(0, 0, 255));
412 } else {
413 myValueTextField->setTextColor(FXRGB(0, 0, 0));
414 myValueTextField->killFocus();
415 }
416 }
417 } else if (myValueChoicesComboBox->shown()) {
418 // fill comboBox
419 myValueChoicesComboBox->clearItems();
420 // special case for VClass
421 if (myACAttr.getAttr() == SUMO_ATTR_VCLASS) {
422 // add all vClasses with their icons
423 for (const auto& vClassStr : SumoVehicleClassStrings.getStrings()) {
424 myValueChoicesComboBox->appendIconItem(vClassStr.c_str(), VClassIcons::getVClassIcon(getVehicleClassID(vClassStr)));
425 }
426 } else {
427 for (const auto& discreteValue : myACAttr.getDiscreteValues()) {
428 myValueChoicesComboBox->appendIconItem(discreteValue.c_str(), nullptr);
429 }
430 }
431 // show combo box with values
432 if (myACAttr.showAllDiscreteValues()) {
433 myValueChoicesComboBox->setNumVisible(myValueChoicesComboBox->getNumItems());
434 } else {
435 myValueChoicesComboBox->setNumVisible(myValueChoicesComboBox->getNumItems() < 10 ? myValueChoicesComboBox->getNumItems() : 10);
436 }
437 myValueChoicesComboBox->setCurrentItem(myValueChoicesComboBox->findItem(value.c_str()));
438 // set blue color if is an computed value
439 if (computed) {
440 myValueChoicesComboBox->setTextColor(FXRGB(0, 0, 255));
441 } else {
442 myValueChoicesComboBox->setTextColor(FXRGB(0, 0, 0));
443 myValueChoicesComboBox->killFocus();
444 }
445 myValueChoicesComboBox->show();
446 } else if (myValueCheckButton->shown()) {
447 if (GNEAttributeCarrier::canParse<bool>(value)) {
448 myValueCheckButton->setCheck(GNEAttributeCarrier::parse<bool>(value));
449 } else {
450 myValueCheckButton->setCheck(false);
451 }
452 }
453}
454
455
456bool
458 return ((myValueTextField->getTextColor() == FXRGB(0, 0, 0)) || (myValueTextField->getTextColor() == FXRGB(0, 0, 255))) &&
459 ((myValueChoicesComboBox->getTextColor() == FXRGB(0, 0, 0)) || (myValueChoicesComboBox->getTextColor() == FXRGB(0, 0, 255)));
460}
461
462
463long
465 GNEViewNet* viewNet = myAttributesEditorParent->getFrameParent()->getViewNet();
466 const auto& ACs = myAttributesEditorParent->getFrameParent()->getViewNet()->getInspectedAttributeCarriers();
467 if (obj == myAttributeColorButton) {
468 // create FXColorDialog
469 FXColorDialog colordialog(this, TL("Color Dialog"));
470 colordialog.setTarget(this);
471 // If previous attribute wasn't correct, set black as default color
472 if (GNEAttributeCarrier::canParse<RGBColor>(myValueTextField->getText().text())) {
473 colordialog.setRGBA(MFXUtils::getFXColor(GNEAttributeCarrier::parse<RGBColor>(myValueTextField->getText().text())));
474 } else if (!myACAttr.getDefaultValue().empty()) {
475 colordialog.setRGBA(MFXUtils::getFXColor(GNEAttributeCarrier::parse<RGBColor>(myACAttr.getDefaultValue())));
476 } else {
477 colordialog.setRGBA(MFXUtils::getFXColor(RGBColor::BLACK));
478 }
479 // execute dialog to get a new color
480 if (colordialog.execute()) {
481 std::string newValue = toString(MFXUtils::getRGBColor(colordialog.getRGBA()));
482 myValueTextField->setText(newValue.c_str());
483 if (viewNet->getInspectedAttributeCarriers().front()->isValid(myACAttr.getAttr(), newValue)) {
484 // if its valid for the first AC than its valid for all (of the same type)
485 if (ACs.size() > 1) {
486 viewNet->getUndoList()->begin(ACs.front()->getTagProperty().getGUIIcon(), TL("change multiple attributes"));
487 }
488 // Set new value of attribute in all selected ACs
489 for (const auto& inspectedAC : viewNet->getInspectedAttributeCarriers()) {
490 inspectedAC->setAttribute(myACAttr.getAttr(), newValue, viewNet->getUndoList());
491 }
492 // finish change multiple attributes
493 if (ACs.size() > 1) {
494 viewNet->getUndoList()->end();
495 }
496 // If previously value was incorrect, change font color to black
497 myValueTextField->setTextColor(FXRGB(0, 0, 0));
498 myValueTextField->killFocus();
499 }
500 }
501 return 0;
502 } else if (obj == myAttributeAllowButton) {
503 // if its valid for the first AC than its valid for all (of the same type)
504 if (ACs.size() > 1) {
505 viewNet->getUndoList()->begin(ACs.front()->getTagProperty().getGUIIcon(), TL("change multiple attributes"));
506 }
507 // declare accept changes
508 bool acceptChanges = false;
509 // open GNEAllowVClassesDialog (also used to modify SUMO_ATTR_CHANGE_LEFT etc
511 viewNet->getInspectedAttributeCarriers().front(), myACAttr.getAttr(), &acceptChanges).execute();
512 // continue depending of acceptChanges
513 if (acceptChanges) {
514 std::string allowed = viewNet->getInspectedAttributeCarriers().front()->getAttribute(myACAttr.getAttr());
515 // Set new value of attribute in all selected ACs
516 for (const auto& inspectedAC : viewNet->getInspectedAttributeCarriers()) {
517 inspectedAC->setAttribute(myACAttr.getAttr(), allowed, viewNet->getUndoList());
518 }
519 // finish change multiple attributes
520 if (ACs.size() > 1) {
521 viewNet->getUndoList()->end();
522 }
523 // update frame parent after attribute successfully set
524 myAttributesEditorParent->getFrameParent()->attributeUpdated(myACAttr.getAttr());
525 }
526 return 1;
527 } else {
528 throw ProcessError("Invalid call to onCmdOpenAttributeDialog");
529 }
530}
531
532
533long
535 auto viewnet = myAttributesEditorParent->getFrameParent()->getViewNet();
536 viewnet->getViewParent()->getInspectorFrame()->inspectChild(myACParent, viewnet->getInspectedAttributeCarriers().front());
537 return 1;
538}
539
540
541long
543 // Declare changed value
544 std::string newVal;
545 // First, obtain the string value of the new attribute depending of their type
546 if (myACAttr.isBool()) {
547 // first check if we're editing boolean as a list of string or as a checkbox
548 if (myValueCheckButton->shown()) {
549 // Set true o false depending of the checkBox
550 if (myValueCheckButton->getCheck()) {
551 myValueCheckButton->setText("true");
552 newVal = "true";
553 } else {
554 myValueCheckButton->setText("false");
555 newVal = "false";
556 }
557 } else {
558 // obtain boolean value of myValueTextField (because we're inspecting multiple attribute carriers with different values)
559 newVal = myValueTextField->getText().text();
560 }
561 } else if (myACAttr.isDiscrete()) {
562 // Check if are VClasses
563 if ((myACAttr.getDiscreteValues().size() > 0) && myACAttr.isVClasses()) {
564 // Get value obtained using AttributesEditor
565 newVal = myValueTextField->getText().text();
566 } else {
567 // Get value of ComboBox
568 newVal = myValueChoicesComboBox->getText().text();
569 }
570 } else if (myACParent && myACAttr.isVType() && (myACAttr.getAttr() == SUMO_ATTR_TYPE)) {
571 // Get value of ComboBox
572 if (myValueChoicesComboBox->shown()) {
573 newVal = myValueChoicesComboBox->getText().text();
574 } else {
575 newVal = myValueTextField->getText().text();
576 }
577 } else {
578 // Check if default value of attribute must be set
579 if (myValueTextField->getText().empty() && myACAttr.hasDefaultValue()) {
580 newVal = myACAttr.getDefaultValue();
581 myValueTextField->setText(newVal.c_str());
582 } else if (myACAttr.isInt() && GNEAttributeCarrier::canParse<double>(myValueTextField->getText().text())) {
583 // filter int attributes
584 double doubleValue = GNEAttributeCarrier::parse<double>(myValueTextField->getText().text());
585 // check if myValueTextField has to be updated
586 if ((doubleValue - (int)doubleValue) == 0) {
587 newVal = toString((int)doubleValue);
588 myValueTextField->setText(newVal.c_str(), FALSE);
589 }
590 } else if ((myACAttr.getAttr() == SUMO_ATTR_ANGLE) && GNEAttributeCarrier::canParse<double>(myValueTextField->getText().text())) {
591 // filter angle
592 double angle = GNEAttributeCarrier::parse<double>(myValueTextField->getText().text());
593 // filter if angle isn't between [0,360]
594 if ((angle < 0) || (angle > 360)) {
595 // apply module
596 angle = fmod(angle, 360);
597 }
598 // set newVal
599 newVal = toString(angle);
600 // update Textfield
601 myValueTextField->setText(newVal.c_str(), FALSE);
602 } else {
603 // obtain value of myValueTextField
604 newVal = myValueTextField->getText().text();
605 }
606 }
607 // we need a extra check for Position and Shape Values, due #2658
608 if ((myACAttr.getAttr() == SUMO_ATTR_POSITION) || (myACAttr.getAttr() == SUMO_ATTR_SHAPE)) {
609 newVal = stripWhitespaceAfterComma(newVal);
610 }
611 // get inspected ACs (for code cleaning)
612 const auto& inspectedACs = myAttributesEditorParent->getFrameParent()->getViewNet()->getInspectedAttributeCarriers();
613 // check if use default value
614 const bool useDefaultValue = (newVal.empty() && myACAttr.hasDefaultValue());
615 // Check if attribute must be changed
616 if ((inspectedACs.size() > 0) && (inspectedACs.front()->isValid(myACAttr.getAttr(), newVal) || useDefaultValue)) {
617 // check if we're merging junction
618 if (!mergeJunction(myACAttr.getAttr(), inspectedACs, newVal)) {
619 // if its valid for the first AC than its valid for all (of the same type)
620 if (inspectedACs.size() > 1) {
621 myAttributesEditorParent->getFrameParent()->getViewNet()->getUndoList()->begin(inspectedACs.front()->getTagProperty().getGUIIcon(), TL("change multiple attributes"));
622 } else if (myACAttr.getAttr() == SUMO_ATTR_ID) {
623 // IDs attribute has to be encapsulated
624 myAttributesEditorParent->getFrameParent()->getViewNet()->getUndoList()->begin(inspectedACs.front()->getTagProperty().getGUIIcon(), TL("change ") + myACAttr.getTagPropertyParent().getTagStr() + TL(" attribute"));
625 }
626 // Set new value of attribute in all selected ACs
627 for (const auto& inspectedAC : inspectedACs) {
628 if (useDefaultValue) {
629 inspectedAC->setAttribute(myACAttr.getAttr(), myACAttr.getDefaultValue(), myAttributesEditorParent->getFrameParent()->getViewNet()->getUndoList());
630 } else {
631 inspectedAC->setAttribute(myACAttr.getAttr(), newVal, myAttributesEditorParent->getFrameParent()->getViewNet()->getUndoList());
632 }
633 }
634 // finish change multiple attributes or ID Attributes
635 if (inspectedACs.size() > 1) {
636 myAttributesEditorParent->getFrameParent()->getViewNet()->getUndoList()->end();
637 } else if (myACAttr.getAttr() == SUMO_ATTR_ID) {
638 myAttributesEditorParent->getFrameParent()->getViewNet()->getUndoList()->end();
639 }
640 // If previously value was incorrect, change font color to black
641 if (myACAttr.isVClasses()) {
642 myValueTextField->setTextColor(FXRGB(0, 0, 0));
643 myValueTextField->setBackColor(FXRGB(255, 255, 255));
644 myValueTextField->killFocus();
645 } else if (myACAttr.isDiscrete()) {
646 myValueChoicesComboBox->setTextColor(FXRGB(0, 0, 0));
647 myValueChoicesComboBox->setBackColor(FXRGB(255, 255, 255));
648 myValueChoicesComboBox->killFocus();
649 } else if (myValueTextField != nullptr) {
650 myValueTextField->setTextColor(FXRGB(0, 0, 0));
651 myValueTextField->setBackColor(FXRGB(255, 255, 255));
652 myValueTextField->killFocus();
653 }
654 // in this case, we need to refresh the other values (For example, allow/Disallow objects)
655 myAttributesEditorParent->refreshAttributeEditor(false, false);
656 // update frame parent after attribute successfully set
657 myAttributesEditorParent->getFrameParent()->attributeUpdated(myACAttr.getAttr());
658 }
659 } else {
660 // If value of TextField isn't valid, change color to Red depending of type
661 if (myACAttr.isVClasses()) {
662 myValueTextField->setTextColor(FXRGB(255, 0, 0));
663 if (newVal.empty()) {
664 myValueTextField->setBackColor(FXRGBA(255, 213, 213, 255));
665 }
666 } else if (myACAttr.isDiscrete()) {
667 myValueChoicesComboBox->setTextColor(FXRGB(255, 0, 0));
668 if (newVal.empty()) {
669 myValueChoicesComboBox->setBackColor(FXRGBA(255, 213, 213, 255));
670 }
671 } else if (myValueTextField != nullptr) {
672 myValueTextField->setTextColor(FXRGB(255, 0, 0));
673 if (newVal.empty()) {
674 myValueTextField->setBackColor(FXRGBA(255, 213, 213, 255));
675 }
676 }
677 // Write Warning in console if we're in testing mode
678 WRITE_DEBUG(TL("Value '") + newVal + TL("' for attribute ") + myACAttr.getAttrStr() + TL(" of ") + myACAttr.getTagPropertyParent().getTagStr() + TL(" isn't valid"));
679 }
680 return 1;
681}
682
683
684long
686 const auto& ACs = myAttributesEditorParent->getFrameParent()->getViewNet()->getInspectedAttributeCarriers();
687 // obtain undoList (To improve code legibly)
688 GNEUndoList* undoList = myAttributesEditorParent->getFrameParent()->getViewNet()->getUndoList();
689 // check if we have to enable or disable
690 if (myAttributeCheckButton->getCheck()) {
691 // enable input values
692 myValueCheckButton->enable();
693 myValueTextField->enable();
694 // enable attribute
695 undoList->begin(ACs.front()->getTagProperty().getGUIIcon(), TL("enable attribute '") + myACAttr.getAttrStr() + "'");
696 ACs.front()->enableAttribute(myACAttr.getAttr(), undoList);
697 undoList->end();
698 } else {
699 // disable input values
700 myValueCheckButton->disable();
701 myValueTextField->disable();
702 // disable attribute
703 undoList->begin(ACs.front()->getTagProperty().getGUIIcon(), TL("disable attribute '") + myACAttr.getAttrStr() + "'");
704 ACs.front()->disableAttribute(myACAttr.getAttr(), undoList);
705 undoList->end();
706 }
707 return 0;
708}
709
710
712 myAttributesEditorParent(nullptr) {
713}
714
715
716std::string
718 std::string result(stringValue);
719 while (result.find(", ") != std::string::npos) {
720 result = StringUtils::replace(result, ", ", ",");
721 }
722 return result;
723}
724
725
726bool
727GNEFrameAttributeModules::AttributesEditorRow::mergeJunction(SumoXMLAttr attr, const std::vector<GNEAttributeCarrier*>& inspectedACs, const std::string& newVal) const {
728 // check if we're editing junction position
729 if ((inspectedACs.size() == 1) && (inspectedACs.front()->getTagProperty().getTag() == SUMO_TAG_JUNCTION) && (attr == SUMO_ATTR_POSITION)) {
730 // retrieve original junction
731 GNEJunction* movedJunction = myAttributesEditorParent->getFrameParent()->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(inspectedACs.front()->getID());
732 // parse position
733 const Position newPosition = GNEAttributeCarrier::parse<Position>(newVal);
734 // iterate over network junction
735 for (const auto& junction : myAttributesEditorParent->getFrameParent()->getViewNet()->getNet()->getAttributeCarriers()->getJunctions()) {
736 // check distance position
737 if ((junction.second->getPositionInView().distanceTo2D(newPosition) < POSITION_EPS) &&
738 myAttributesEditorParent->getFrameParent()->getViewNet()->mergeJunctions(movedJunction, junction.second)) {
739 return true;
740 }
741 }
742 }
743 // nothing to merge
744 return false;
745}
746
747// ---------------------------------------------------------------------------
748// GNEFrameAttributeModules::AttributesEditor - methods
749// ---------------------------------------------------------------------------
750
752 MFXGroupBoxModule(frameParent, TL("Internal attributes")),
753 myFrameParent(frameParent),
754 myIncludeExtended(true) {
755 // resize myAttributesEditorRows
757 // create myAttributesFlowEditor
758 myAttributesEditorFlow = new GNEFlowEditor(frameParent->getViewNet(), frameParent);
759 // leave it hidden
761 // Create help button
762 myHelpButton = new FXButton(getCollapsableFrame(), TL("Help"), nullptr, this, MID_HELP, GUIDesignButtonRectangular);
763}
764
765
766void
768 myIncludeExtended = includeExtended;
769 // first remove all rows
770 for (auto& row : myAttributesEditorRows) {
771 // destroy and delete all rows
772 if (row != nullptr) {
773 row->destroy();
774 delete row;
775 row = nullptr;
776 }
777 }
778 // get inspected ACs
779 const auto& ACs = myFrameParent->getViewNet()->getInspectedAttributeCarriers();
780 // declare flag to check if flow editor has to be shown
781 bool showFlowEditor = false;
782 if (ACs.size() > 0) {
783 // Iterate over attributes
784 for (const auto& attrProperty : ACs.front()->getTagProperty()) {
785 // declare flag to show/hide attribute
786 bool editAttribute = true;
787 // disable editing for unique attributes in case of multi-selection
788 if ((ACs.size() > 1) && attrProperty.isUnique()) {
789 editAttribute = false;
790 }
791 // disable editing of extended attributes if includeExtended isn't enabled
792 if (attrProperty.isExtended() && !includeExtended) {
793 editAttribute = false;
794 }
795 // disable editing of flow definition attributes, but enable flow editor
796 if (attrProperty.isFlowDefinition()) {
797 editAttribute = false;
798 showFlowEditor = true;
799 }
800 // continue if attribute is editable
801 if (editAttribute) {
802 // Declare a set of occurring values and insert attribute's values of item (note: We use a set to avoid repeated values)
803 std::set<std::string> occurringValues;
804 // iterate over edited attributes
805 for (const auto& inspectedAC : ACs) {
806 occurringValues.insert(inspectedAC->getAttribute(attrProperty.getAttr()));
807 }
808 // get current value
809 std::ostringstream oss;
810 for (auto values = occurringValues.begin(); values != occurringValues.end(); values++) {
811 if (values != occurringValues.begin()) {
812 oss << " ";
813 }
814 oss << *values;
815 }
816 // obtain value to be shown in row
817 std::string value = oss.str();
818 // declare a flag for enabled attributes
819 bool attributeEnabled = ACs.front()->isAttributeEnabled(attrProperty.getAttr());
820 // overwrite value if attribute is disabled (used by LinkIndex)
821 if (attributeEnabled == false) {
822 value = ACs.front()->getAlternativeValueForDisabledAttributes(attrProperty.getAttr());
823 }
824 // for types, the following attributes must be always enabled
825 if (ACs.front()->getTagProperty().isType() &&
826 ((attrProperty.getAttr() == SUMO_ATTR_LENGTH) ||
827 (attrProperty.getAttr() == SUMO_ATTR_MINGAP) ||
828 (attrProperty.getAttr() == SUMO_ATTR_MAXSPEED) ||
829 (attrProperty.getAttr() == SUMO_ATTR_DESIRED_MAXSPEED))) {
830 attributeEnabled = true;
831 }
832 // extra check for Triggered and container Triggered
833 if (ACs.front()->getTagProperty().isStop() || ACs.front()->getTagProperty().isStopPerson()) {
834 if ((attrProperty.getAttr() == SUMO_ATTR_EXPECTED) && (ACs.front()->isAttributeEnabled(SUMO_ATTR_TRIGGERED) == false)) {
835 attributeEnabled = false;
836 } else if ((attrProperty.getAttr() == SUMO_ATTR_EXPECTED_CONTAINERS) && (ACs.front()->isAttributeEnabled(SUMO_ATTR_CONTAINER_TRIGGERED) == false)) {
837 attributeEnabled = false;
838 }
839 }
840 // check if this attribute is computed
841 const bool computed = (ACs.size() > 1) ? false : ACs.front()->isAttributeComputed(attrProperty.getAttr());
842 // if is a Vtype, obtain icon
843 GNEAttributeCarrier* ACParent = nullptr;
844 if ((ACs.size() == 1) && attrProperty.isVType()) {
845 if (attrProperty.getAttr() == SUMO_ATTR_TYPE) {
846 ACParent = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, ACs.front()->getAttribute(SUMO_ATTR_TYPE), false);
847 if (ACParent == nullptr) {
848 ACParent = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, ACs.front()->getAttribute(SUMO_ATTR_TYPE), false);
849 }
850 }
851 }
852 // create attribute editor row
853 myAttributesEditorRows[attrProperty.getPositionListed()] = new AttributesEditorRow(this, attrProperty, value, attributeEnabled, computed, ACParent);
854 }
855 }
856 // check if Flow editor has to be shown
857 if (showFlowEditor) {
858 myAttributesEditorFlow->showFlowEditor(ACs);
859 } else {
860 myAttributesEditorFlow->hideFlowEditor();
861 }
862 // show AttributesEditor
863 show();
864 } else {
865 myAttributesEditorFlow->hideFlowEditor();
866 }
867 // reparent help button (to place it at bottom)
868 myHelpButton->reparent(this);
869}
870
871
872void
874 // hide AttributesEditorFlowModule
875 myAttributesEditorFlow->hideFlowEditor();
876 // hide also AttributesEditor
877 hide();
878}
879
880
881void
882GNEFrameAttributeModules::AttributesEditor::refreshAttributeEditor(bool forceRefreshShape, bool forceRefreshPosition) {
883 // get inspected ACs
884 const auto& ACs = myFrameParent->getViewNet()->getInspectedAttributeCarriers();
885 // first check if there is inspected attribute carriers
886 if (ACs.size() > 0) {
887 // Iterate over inspected attribute carriers
888 for (const auto& attrProperty : ACs.front()->getTagProperty()) {
889 // declare flag to show/hide attribute
890 bool editAttribute = true;
891 // disable editing for unique attributes in case of multi-selection
892 if ((ACs.size() > 1) && attrProperty.isUnique()) {
893 editAttribute = false;
894 }
895 // disable editing of extended attributes if includeExtended isn't enabled
896 if (attrProperty.isExtended() && !myIncludeExtended) {
897 editAttribute = false;
898 }
899 // disable editing of flow definition attributes, but enable flow editor
900 if (attrProperty.isFlowDefinition()) {
901 editAttribute = false;
902 }
903 // continue if attribute is editable
904 if (editAttribute) {
905 // Declare a set of occurring values and insert attribute's values of item (note: We use a set to avoid repeated values)
906 std::set<std::string> occurringValues;
907 // iterate over edited attributes
908 for (const auto& inspectedAC : ACs) {
909 occurringValues.insert(inspectedAC->getAttribute(attrProperty.getAttr()));
910 }
911 // get current value
912 std::ostringstream oss;
913 for (auto values = occurringValues.begin(); values != occurringValues.end(); values++) {
914 if (values != occurringValues.begin()) {
915 oss << " ";
916 }
917 oss << *values;
918 }
919 // obtain value to be shown in row
920 std::string value = oss.str();
921 // declare a flag for enabled attributes
922 bool attributeEnabled = ACs.front()->isAttributeEnabled(attrProperty.getAttr());
923 // for types, the following attributes must be always enabled
924 if (ACs.front()->getTagProperty().isType() &&
925 ((attrProperty.getAttr() == SUMO_ATTR_LENGTH) ||
926 (attrProperty.getAttr() == SUMO_ATTR_MINGAP) ||
927 (attrProperty.getAttr() == SUMO_ATTR_MAXSPEED) ||
928 (attrProperty.getAttr() == SUMO_ATTR_DESIRED_MAXSPEED))) {
929 attributeEnabled = true;
930 }
931 // overwrite value if attribute is disabled (used by LinkIndex)
932 if (attributeEnabled == false) {
933 value = ACs.front()->getAlternativeValueForDisabledAttributes(attrProperty.getAttr());
934 }
935 // extra check for Triggered and container Triggered
936 if (ACs.front()->getTagProperty().isStop() || ACs.front()->getTagProperty().isStopPerson()) {
937 if ((attrProperty.getAttr() == SUMO_ATTR_EXPECTED) && (ACs.front()->isAttributeEnabled(SUMO_ATTR_TRIGGERED) == false)) {
938 attributeEnabled = false;
939 } else if ((attrProperty.getAttr() == SUMO_ATTR_EXPECTED_CONTAINERS) && (ACs.front()->isAttributeEnabled(SUMO_ATTR_CONTAINER_TRIGGERED) == false)) {
940 attributeEnabled = false;
941 }
942 }
943 // check if this attribute is computed
944 const bool computed = (ACs.size() > 1) ? false : ACs.front()->isAttributeComputed(attrProperty.getAttr());
945 // Check if Position or Shape refresh has to be forced
946 if ((attrProperty.getAttr() == SUMO_ATTR_SHAPE) && forceRefreshShape) {
947 myAttributesEditorRows[attrProperty.getPositionListed()]->refreshAttributesEditorRow(value, true, attributeEnabled, computed, nullptr);
948 } else if ((attrProperty.getAttr() == SUMO_ATTR_POSITION) && forceRefreshPosition) {
949 myAttributesEditorRows[attrProperty.getPositionListed()]->refreshAttributesEditorRow(value, true, attributeEnabled, computed, nullptr);
950 } else if (attrProperty.isVType() && (attrProperty.getTagPropertyParent().isVehicle() || attrProperty.getTagPropertyParent().isPerson() ||
951 attrProperty.getTagPropertyParent().isContainer())) {
952 // get type/distribution parent
953 auto typeParent = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, ACs.front()->getAttribute(SUMO_ATTR_TYPE), false);
954 if (typeParent == nullptr) {
955 typeParent = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, ACs.front()->getAttribute(SUMO_ATTR_TYPE), false);
956 }
957 myAttributesEditorRows[attrProperty.getPositionListed()]->refreshAttributesEditorRow(value, false, attributeEnabled, computed, typeParent);
958 } else {
959 // Refresh attributes maintain invalid values
960 myAttributesEditorRows[attrProperty.getPositionListed()]->refreshAttributesEditorRow(value, false, attributeEnabled, computed, nullptr);
961 }
962 }
963 }
964 // check if flow editor has to be update
965 if (myAttributesEditorFlow->shownFlowEditor()) {
966 myAttributesEditorFlow->refreshFlowEditor();
967 }
968 }
969}
970
971
974 return myFrameParent;
975}
976
977
978long
980 // open Help attributes dialog if there is inspected ACs
981 if (myFrameParent->getViewNet()->getInspectedAttributeCarriers().size() > 0) {
982 // open Help attributes dialog
983 myFrameParent->openHelpAttributesDialog(myFrameParent->getViewNet()->getInspectedAttributeCarriers().front());
984 }
985 return 1;
986}
987
988// ---------------------------------------------------------------------------
989// GNEFrameAttributeModules::AttributesEditorExtended- methods
990// ---------------------------------------------------------------------------
991
993 MFXGroupBoxModule(frameParent, TL("Extended attributes")),
994 myFrameParent(frameParent) {
995 // Create open dialog button
996 new FXButton(getCollapsableFrame(), TL("Open attributes editor"), nullptr, this, MID_GNE_SET_ATTRIBUTE_DIALOG, GUIDesignButton);
997}
998
999
1001
1002
1003void
1007
1008
1009void
1013
1014
1015long
1017 // open GNEAttributesCreator extended dialog
1018 myFrameParent->attributesEditorExtendedDialogOpened();
1019 return 1;
1020}
1021
1022// ---------------------------------------------------------------------------
1023// GNEFrameAttributeModules::GenericDataAttributes - methods
1024// ---------------------------------------------------------------------------
1025
1027 MFXGroupBoxModule(frameParent, TL("Attributes")),
1028 myFrameParent(frameParent) {
1029 // create textfield and buttons
1031 myButtonEditParameters = new FXButton(getCollapsableFrame(), TL("Edit attributes"), nullptr, this, MID_GNE_OPEN_PARAMETERS_DIALOG, GUIDesignButton);
1032}
1033
1034
1036
1037
1038void
1040 // refresh GenericDataAttributes
1041 refreshGenericDataAttributes();
1042 // show groupbox
1043 show();
1044}
1045
1046
1047void
1052
1053
1054void
1056 myTextFieldParameters->setText(getParametersStr().c_str());
1057 myTextFieldParameters->setTextColor(FXRGB(0, 0, 0));
1058 myTextFieldParameters->killFocus();
1059}
1060
1061
1062const Parameterised::Map&
1066
1067
1068std::string
1070 std::string result;
1071 // Generate an string using the following structure: "key1=value1|key2=value2|...
1072 for (const auto& parameter : myParameters) {
1073 result += parameter.first + "=" + parameter.second + "|";
1074 }
1075 // remove the last "|"
1076 if (!result.empty()) {
1077 result.pop_back();
1078 }
1079 return result;
1080}
1081
1082
1083std::vector<std::pair<std::string, std::string> >
1085 std::vector<std::pair<std::string, std::string> > result;
1086 // Generate a vector string using the following structure: "<key1,value1>, <key2, value2>,...
1087 for (const auto& parameter : myParameters) {
1088 result.push_back(std::make_pair(parameter.first, parameter.second));
1089 }
1090 return result;
1091}
1092
1093
1094void
1095GNEFrameAttributeModules::GenericDataAttributes::setParameters(const std::vector<std::pair<std::string, std::string> >& parameters) {
1096 // declare result string
1097 std::string result;
1098 // Generate an string using the following structure: "key1=value1|key2=value2|...
1099 for (const auto& parameter : parameters) {
1100 result += parameter.first + "=" + parameter.second + "|";
1101 }
1102 // remove the last "|"
1103 if (!result.empty()) {
1104 result.pop_back();
1105 }
1106 // set result in textField (and call onCmdEditParameters)
1107 myTextFieldParameters->setText(result.c_str(), TRUE);
1108}
1109
1110
1111GNEFrame*
1115
1116
1117bool
1119 if (myTextFieldParameters->getText().empty()) {
1120 return true;
1121 } else if (myTextFieldParameters->getTextColor() == FXRGB(255, 0, 0)) {
1122 return false;
1123 } else {
1124 return Parameterised::areAttributesValid(getParametersStr());
1125 }
1126}
1127
1128
1129long
1131 // write debug information
1132 WRITE_DEBUG("Open single parameters dialog");
1133 if (GNESingleParametersDialog(this).execute()) {
1134 // write debug information
1135 WRITE_DEBUG("Close single parameters dialog");
1136 // Refresh parameter EditorCreator
1137 refreshGenericDataAttributes();
1138 } else {
1139 // write debug information
1140 WRITE_DEBUG("Cancel single parameters dialog");
1141 }
1142 return 1;
1143}
1144
1145
1146long
1148 // clear current existent parameters
1149 myParameters.clear();
1150 // check if current given string is valid
1151 if (Parameterised::areParametersValid(myTextFieldParameters->getText().text(), true)) {
1152 // parsed parameters ok, then set text field black and continue
1153 myTextFieldParameters->setTextColor(FXRGB(0, 0, 0));
1154 myTextFieldParameters->killFocus();
1155 // obtain parameters "key=value"
1156 std::vector<std::string> parameters = StringTokenizer(myTextFieldParameters->getText().text(), "|", true).getVector();
1157 // iterate over parameters
1158 for (const auto& parameter : parameters) {
1159 // obtain key, value
1160 std::vector<std::string> keyParam = StringTokenizer(parameter, "=", true).getVector();
1161 // save it in myParameters
1162 myParameters[keyParam.front()] = keyParam.back();
1163 }
1164 // overwrite myTextFieldParameters (to remove duplicated parameters
1165 myTextFieldParameters->setText(getParametersStr().c_str(), FALSE);
1166 } else {
1167 myTextFieldParameters->setTextColor(FXRGB(255, 0, 0));
1168 }
1169 return 1;
1170}
1171
1172// ---------------------------------------------------------------------------
1173// GNEFrameAttributeModules::ParametersEditor - methods
1174// ---------------------------------------------------------------------------
1175
1177 MFXGroupBoxModule(inspectorFrameParent, TL("Parameters")),
1178 myInspectorFrameParent(inspectorFrameParent) {
1179 // create textfield and buttons
1181 myButtonEditParameters = new FXButton(getCollapsableFrame(), TL("Edit parameters"), nullptr, this, MID_GNE_OPEN_PARAMETERS_DIALOG, GUIDesignButton);
1182}
1183
1184
1186 MFXGroupBoxModule(typeFrameParent, TL("Parameters")),
1187 myTypeFrameParent(typeFrameParent) {
1188 // create textfield and buttons
1190 myButtonEditParameters = new FXButton(getCollapsableFrame(), TL("Edit parameters"), nullptr, this, MID_GNE_OPEN_PARAMETERS_DIALOG, GUIDesignButton);
1191}
1192
1193
1195
1196
1199 return myInspectorFrameParent ? myInspectorFrameParent->getViewNet() : myTypeFrameParent->getViewNet();
1200}
1201
1202
1203void
1205 if (myInspectorFrameParent) {
1206 // get inspected ACs
1207 const auto& inspectedACs = myInspectorFrameParent->getViewNet()->getInspectedAttributeCarriers();
1208 if ((inspectedACs.size() > 0) && inspectedACs.front()->getTagProperty().hasParameters()) {
1209 // refresh ParametersEditor
1210 refreshParametersEditor();
1211 // show groupbox
1212 show();
1213 } else {
1214 hideParametersEditor();
1215 }
1216 } else if (myTypeFrameParent) {
1217 if (myTypeFrameParent->getTypeSelector()->getCurrentType() != nullptr) {
1219 refreshParametersEditor();
1220 // show groupbox
1221 show();
1222 } else {
1223 hideParametersEditor();
1224 }
1225 } else {
1226 hideParametersEditor();
1227 }
1228}
1229
1230
1231void
1233 // hide groupbox
1234 hide();
1235}
1236
1237
1238void
1240 if (myInspectorFrameParent) {
1241 // get inspected ACs
1242 const auto& inspectedACs = myInspectorFrameParent->getViewNet()->getInspectedAttributeCarriers();
1243 // get front AC
1244 const GNEAttributeCarrier* frontAC = inspectedACs.size() > 0 ? inspectedACs.front() : nullptr;
1245 // continue depending of frontAC
1246 if (frontAC && frontAC->getTagProperty().hasParameters()) {
1247 // check if we're editing a single or a multiple AC
1248 if (inspectedACs.size() == 1) {
1249 // set text field parameters
1250 myTextFieldParameters->setText(frontAC->getAttribute(GNE_ATTR_PARAMETERS).c_str());
1251 } else if (inspectedACs.size() > 0) {
1252 // check if parameters of all inspected ACs are different
1253 std::string parameters = frontAC->getAttribute(GNE_ATTR_PARAMETERS);
1254 for (const auto& AC : inspectedACs) {
1255 if (parameters != AC->getAttribute(GNE_ATTR_PARAMETERS)) {
1256 parameters = "different parameters";
1257 }
1258 }
1259 // set text field
1260 myTextFieldParameters->setText(parameters.c_str());
1261 }
1262 // reset color
1263 myTextFieldParameters->setTextColor(FXRGB(0, 0, 0));
1264 // disable myTextFieldParameters if Tag correspond to an network element but we're in demand mode (or vice versa), disable all elements
1265 if (GNEFrameAttributeModules::isSupermodeValid(myInspectorFrameParent->getViewNet(), frontAC)) {
1266 myTextFieldParameters->enable();
1267 myButtonEditParameters->enable();
1268 } else {
1269 myTextFieldParameters->disable();
1270 myButtonEditParameters->disable();
1271 }
1272 }
1273 } else if (myTypeFrameParent) {
1274 // get type
1275 GNEDemandElement* type = myTypeFrameParent->getTypeSelector()->getCurrentType();
1276 // continue depending of frontAC
1277 if (type) {
1278 // set text field parameters
1279 myTextFieldParameters->setText(type->getAttribute(GNE_ATTR_PARAMETERS).c_str());
1280 // reset color
1281 myTextFieldParameters->setTextColor(FXRGB(0, 0, 0));
1282 // disable myTextFieldParameters if Tag correspond to an network element but we're in demand mode (or vice versa), disable all elements
1283 if (GNEFrameAttributeModules::isSupermodeValid(myTypeFrameParent->getViewNet(), type)) {
1284 myTextFieldParameters->enable();
1285 myButtonEditParameters->enable();
1286 } else {
1287 myTextFieldParameters->disable();
1288 myButtonEditParameters->disable();
1289 }
1290 }
1291 }
1292}
1293
1294
1297 return myInspectorFrameParent;
1298}
1299
1300
1303 return myTypeFrameParent;
1304}
1305
1306
1307long
1309 if (myInspectorFrameParent) {
1310 // get inspected ACs
1311 const auto& inspectedACs = myInspectorFrameParent->getViewNet()->getInspectedAttributeCarriers();
1312 // get front AC
1313 const GNEAttributeCarrier* frontAC = inspectedACs.size() > 0 ? inspectedACs.front() : nullptr;
1314 // continue depending of frontAC
1315 if (frontAC && frontAC->getTagProperty().hasParameters()) {
1316 if (inspectedACs.size() > 1) {
1317 // write debug information
1318 WRITE_DEBUG("Open multiple parameters dialog");
1319 // open multiple parameters dialog
1320 if (GNEMultipleParametersDialog(this).execute()) {
1321 // write debug information
1322 WRITE_DEBUG("Close multiple parameters dialog");
1323 // update frame parent after attribute successfully set
1324 myInspectorFrameParent->attributeUpdated(GNE_ATTR_PARAMETERS);
1325 // Refresh parameter EditorInspector
1326 refreshParametersEditor();
1327 } else {
1328 // write debug information
1329 WRITE_DEBUG("Cancel multiple parameters dialog");
1330 }
1331 } else {
1332 // write debug information
1333 WRITE_DEBUG("Open single parameters dialog");
1334 if (GNESingleParametersDialog(this).execute()) {
1335 // write debug information
1336 WRITE_DEBUG("Close single parameters dialog");
1337 // update frame parent after attribute successfully set
1338 myInspectorFrameParent->attributeUpdated(GNE_ATTR_PARAMETERS);
1339 // Refresh parameter EditorInspector
1340 refreshParametersEditor();
1341 } else {
1342 // write debug information
1343 WRITE_DEBUG("Cancel single parameters dialog");
1344 }
1345 }
1346 }
1347 } else if (myTypeFrameParent) {
1348 // get type
1349 GNEDemandElement* type = myTypeFrameParent->getTypeSelector()->getCurrentType();
1350 // continue depending of type
1351 if (type) {
1352 // write debug information
1353 WRITE_DEBUG("Open single parameters dialog");
1354 if (GNESingleParametersDialog(this).execute()) {
1355 // write debug information
1356 WRITE_DEBUG("Close single parameters dialog");
1357 // Refresh parameter EditorInspector
1358 refreshParametersEditor();
1359 } else {
1360 // write debug information
1361 WRITE_DEBUG("Cancel single parameters dialog");
1362 }
1363 }
1364 }
1365 return 1;
1366}
1367
1368
1369long
1371 if (myInspectorFrameParent) {
1372 const auto& inspectedACs = myInspectorFrameParent->getAttributesEditor()->getFrameParent()->getViewNet()->getInspectedAttributeCarriers();
1373 // get front AC
1374 GNEAttributeCarrier* frontAC = inspectedACs.size() > 0 ? inspectedACs.front() : nullptr;
1375 // continue depending of frontAC
1376 if (frontAC && frontAC->getTagProperty().hasParameters()) {
1377 // check if current given string is valid
1378 if (frontAC->isValid(GNE_ATTR_PARAMETERS, myTextFieldParameters->getText().text())) {
1379 // parsed parameters ok, then set text field black and continue
1380 myTextFieldParameters->setTextColor(FXRGB(0, 0, 0));
1381 myTextFieldParameters->killFocus();
1382 // check inspected parameters
1383 if (inspectedACs.size() == 1) {
1384 // begin undo list
1385 myInspectorFrameParent->getViewNet()->getUndoList()->begin(frontAC->getTagProperty().getGUIIcon(), "change parameters");
1386 // set parameters
1387 frontAC->setACParameters(myTextFieldParameters->getText().text(), myInspectorFrameParent->getViewNet()->getUndoList());
1388 // end undo list
1389 myInspectorFrameParent->getViewNet()->getUndoList()->end();
1390 } else if (inspectedACs.size() > 0) {
1391 // begin undo list
1392 myInspectorFrameParent->getViewNet()->getUndoList()->begin(frontAC->getTagProperty().getGUIIcon(), "change multiple parameters");
1393 // set parameters in all ACs
1394 for (const auto& inspectedAC : inspectedACs) {
1395 inspectedAC->setACParameters(myTextFieldParameters->getText().text(), myInspectorFrameParent->getViewNet()->getUndoList());
1396 }
1397 // end undo list
1398 myInspectorFrameParent->getViewNet()->getUndoList()->end();
1399 }
1400 // update frame parent after attribute successfully set
1401 myInspectorFrameParent->attributeUpdated(GNE_ATTR_PARAMETERS);
1402 } else {
1403 myTextFieldParameters->setTextColor(FXRGB(255, 0, 0));
1404 }
1405 }
1406 } else if (myTypeFrameParent) {
1407 // get type
1408 GNEDemandElement* type = myTypeFrameParent->getTypeSelector()->getCurrentType();
1409 // continue depending of frontAC
1410 if (type) {
1411 // check if current given string is valid
1412 if (type->isValid(GNE_ATTR_PARAMETERS, myTextFieldParameters->getText().text())) {
1413 // parsed parameters ok, then set text field black and continue
1414 myTextFieldParameters->setTextColor(FXRGB(0, 0, 0));
1415 myTextFieldParameters->killFocus();
1416 // begin undo list
1417 myTypeFrameParent->getViewNet()->getUndoList()->begin(type->getTagProperty().getGUIIcon(), "change parameters");
1418 // set parameters
1419 type->setACParameters(myTextFieldParameters->getText().text(), myTypeFrameParent->getViewNet()->getUndoList());
1420 // end undo list
1421 myTypeFrameParent->getViewNet()->getUndoList()->end();
1422 } else {
1423 myTextFieldParameters->setTextColor(FXRGB(255, 0, 0));
1424 }
1425 }
1426 }
1427 return 1;
1428}
1429
1430
1431bool
1433 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
1435 return true;
1436 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
1438 return true;
1439 } else if (viewNet->getEditModes().isCurrentSupermodeData() &&
1441 return true;
1442 } else {
1443 return false;
1444 }
1445}
1446
1447
1448bool
1451 return (viewNet->getEditModes().isCurrentSupermodeNetwork());
1452 } else if (ACAttr.getTagPropertyParent().isDemandElement()) {
1453 return (viewNet->getEditModes().isCurrentSupermodeDemand());
1454 } else if (ACAttr.getTagPropertyParent().isDataElement() || ACAttr.getTagPropertyParent().isMeanData()) {
1455 return (viewNet->getEditModes().isCurrentSupermodeData());
1456 } else {
1457 return false;
1458 }
1459}
1460
1461/****************************************************************************/
FXDEFMAP(GNEFrameAttributeModules::AttributesEditorRow) AttributesEditorRowMap[]
@ MID_GNE_SET_ATTRIBUTE_VTYPE
inspect attribute vType/vTypeDistribution
Definition GUIAppEnum.h:945
@ MID_GNE_SET_ATTRIBUTE
attribute edited
Definition GUIAppEnum.h:907
@ MID_GNE_OPEN_PARAMETERS_DIALOG
open parameters dialog
Definition GUIAppEnum.h:947
@ MID_GNE_SET_ATTRIBUTE_DIALOG
attribute edited trough dialog
Definition GUIAppEnum.h:943
@ MID_HELP
help button
Definition GUIAppEnum.h:645
@ MID_GNE_SET_ATTRIBUTE_BOOL
bool attribute edited
Definition GUIAppEnum.h:941
#define GUIDesignButtonAttribute
button extended over over column with thick and raise frame
Definition GUIDesigns.h:77
#define GUIDesignButton
Definition GUIDesigns.h:74
#define GUIDesignComboBoxAttribute
Combo box static (cannot be edited) extended over the matrix column.
Definition GUIDesigns.h:297
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition GUIDesigns.h:306
#define GUIDesignTextField
Definition GUIDesigns.h:51
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:394
#define GUIDesignButtonRectangular
little rectangular button used in frames (For example, in "help" buttons)
Definition GUIDesigns.h:80
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition GUIDesigns.h:66
#define GUIDesignCheckButton
checkButton placed in left position
Definition GUIDesigns.h:187
#define GUIDesignCheckButtonAttribute
checkButton without thick extended over the frame used for attributes
Definition GUIDesigns.h:196
#define GUIDesignLabelThickedFixed(width)
label thicked, icon before text, text centered and custom width
Definition GUIDesigns.h:247
#define WRITE_DEBUG(msg)
Definition MsgHandler.h:281
#define TL(string)
Definition MsgHandler.h:287
SUMOVehicleClass getVehicleClassID(const std::string &name)
Returns the class id of the abstract class given by its name.
StringBijection< SUMOVehicleClass > SumoVehicleClassStrings(sumoVehicleClassStringInitializer, SVC_CUSTOM2, false)
@ SUMO_TAG_VTYPE
description of a vehicle/person/container type
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_VTYPE_DISTRIBUTION
distribution of a vehicle type
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_CONTAINER_TRIGGERED
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_MINGAP
@ GNE_ATTR_PARAMETERS
parameters "key1=value1|key2=value2|...|keyN=valueN"
@ SUMO_ATTR_EXPECTED
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_DESIRED_MAXSPEED
@ SUMO_ATTR_ANGLE
@ SUMO_ATTR_VCLASS
@ SUMO_ATTR_EXPECTED_CONTAINERS
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_MAXSPEED
@ SUMO_ATTR_ID
@ SUMO_ATTR_TRIGGERED
@ SUMO_ATTR_POSITION
@ SUMO_ATTR_NOTHING
invalid attribute
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
Dialog for edit rerouters.
void setACParameters(const std::string &parameters, GNEUndoList *undoList)
set parameters (string)
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
static bool canParse(const std::string &string)
true if a value of type T can be parsed from string
virtual bool isValid(SumoXMLAttr key, const std::string &value)=0
GNENet * getNet() const
get pointer to net
virtual std::string getAttribute(SumoXMLAttr key) const =0
static const size_t MAXNUMBEROFATTRIBUTES
max number of attributes allowed for every tag
const GNETagProperties & getTagPropertyParent() const
get reference to tagProperty parent
An Element which don't belong to GNENet but has influence in the simulation.
virtual std::string getAttribute(SumoXMLAttr key) const =0
virtual bool isValid(SumoXMLAttr key, const std::string &value)=0
method for checking if the key and their conrrespond attribute are valids
void hideFlowEditor()
hide group box
void showAttributesEditorExtendedModule()
show AttributesEditorExtended modul
AttributesEditorExtended(GNEFrame *frameParent)
FOX-declaration.
void refreshAttributeEditor(bool forceRefreshShape, bool forceRefreshPosition)
refresh attribute editor (only the valid values will be refresh)
GNEFlowEditor * myAttributesEditorFlow
GNEFlowEditor modul.
GNEFrame * getFrameParent() const
pointer to GNEFrame parent
long onCmdAttributesEditorHelp(FXObject *, FXSelector, void *)
void showAttributeEditorModule(bool includeExtended)
show attributes of multiple ACs
std::vector< AttributesEditorRow * > myAttributesEditorRows
list of Attribute editor rows
AttributesEditor(GNEFrame *inspectorFrameParent)
FOX-declaration.
void refreshAttributesEditorRow(const std::string &value, const bool forceRefresh, const bool attributeEnabled, const bool computed, GNEAttributeCarrier *ACParent)
refresh current row
bool mergeJunction(SumoXMLAttr attr, const std::vector< GNEAttributeCarrier * > &inspectedACs, const std::string &newVal) const
check junction merging
long onCmdSetAttribute(FXObject *, FXSelector, void *)
try to set new attribute value
std::string stripWhitespaceAfterComma(const std::string &stringValue)
removed invalid spaces of Positions and shapes
long onCmdInspectVTypeParent(FXObject *, FXSelector, void *)
inspect vType/VTypeDistribution parent
bool isAttributesEditorRowValid() const
check if current attribute of TextField/ComboBox is valid
void destroy()
destroy GNEAttributesCreatorRow (but don't delete)
long onCmdOpenAttributeDialog(FXObject *, FXSelector, void *)
open model dialog for more comfortable attribute editing
long onCmdSelectCheckButton(FXObject *, FXSelector, void *)
called when user press a check button
long onCmdSetParameters(FXObject *, FXSelector, void *)
Called when user udpate the parameter text field.
bool areAttributesValid() const
check if current attributes are valid
const Parameterised::Map & getParametersMap() const
get parameters as map
FXButton * myButtonEditParameters
button for edit parameters using specific dialog
FXTextField * myTextFieldParameters
text field for write parameters
void showGenericDataAttributes()
show netedit attributes EditorCreator
GNEFrame * getFrameParent() const
pointer to frame parent
std::vector< std::pair< std::string, std::string > > getParameters() const
get parameters as vector of strings
std::string getParametersStr() const
get parameters as string
GenericDataAttributes(GNEFrame *frameParent)
FOX-declaration.
void hideGenericDataAttributes()
hide netedit attributes EditorCreator
void setParameters(const std::vector< std::pair< std::string, std::string > > &parameters)
set parameters
void refreshParametersEditor()
refresh netedit attributes
long onCmdSetParameters(FXObject *, FXSelector, void *)
Called when user udpate the parameter text field.
long onCmdEditParameters(FXObject *, FXSelector, void *)
ParametersEditor(GNEInspectorFrame *inspectorFrameParent)
FOX-declaration.
void hideParametersEditor()
hide netedit attributes EditorInspector
GNEInspectorFrame * getInspectorFrameParent() const
get inspector frame parent
FXButton * myButtonEditParameters
button for edit parameters using specific dialog
FXTextField * myTextFieldParameters
text field for write parameters
GNETypeFrame * getTypeFrameParent() const
get type frame parent
void showParametersEditor()
show netedit attributes EditorInspector
static bool isSupermodeValid(const GNEViewNet *viewNet, const GNEAttributeCarrier *AC)
return true if AC can be edited in the current supermode
GNEViewNet * getViewNet() const
get view net
Definition GNEFrame.cpp:150
void openHelpAttributesDialog(const GNEAttributeCarrier *AC) const
Open help attributes dialog.
Definition GNEFrame.cpp:184
const std::map< SumoXMLTag, std::set< GNEDemandElement * > > & getDemandElements() const
get demand elements
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
GNEDemandElement * retrieveDemandElement(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named demand element.
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:120
Dialog for edit parameters.
bool isMeanData() const
return true if tag correspond to a mean data element
bool isNetworkElement() const
return true if tag correspond to a network element
bool isDataElement() const
return true if tag correspond to a data element
GUIIcon getGUIIcon() const
get GUI icon associated to this Tag
bool hasParameters() const
return true if Tag correspond to an element that supports parameters "key1=value1|key2=value2|....
bool isDemandElement() const
return true if tag correspond to a demand element
bool isAdditionalElement() const
return true if tag correspond to an additional element (note: this include TAZ, shapes and wires)
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
GNEUndoList * getUndoList() const
get the undoList object
const std::vector< GNEAttributeCarrier * > & getInspectedAttributeCarriers() const
get inspected attribute carriers
ComboBox with icon.
MFXGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
static FXColor getFXColor(const RGBColor &col)
converts FXColor to RGBColor
Definition MFXUtils.cpp:112
static RGBColor getRGBColor(FXColor col)
converts FXColor to RGBColor
Definition MFXUtils.cpp:106
static bool areAttributesValid(const std::string &value, bool report=false, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to an attributes map "key1=value1|key2=value2|....
static bool areParametersValid(const std::string &value, bool report=false, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to a parameters map "key1=value1|key2=value2|....
std::map< std::string, std::string > Map
parameters map
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
static const RGBColor BLACK
Definition RGBColor.h:193
std::vector< std::string > getVector()
return vector of strings
static std::string replace(std::string str, const std::string &what, const std::string &by)
Replaces all occurrences of the second string by the third string within the first string.
static FXIcon * getVClassIcon(const SUMOVehicleClass vc)
returns icon associated to the given vClass
Definition json.hpp:4471
bool isCurrentSupermodeDemand() const
@check if current supermode is Demand
bool isCurrentSupermodeData() const
@check if current supermode is Data
bool isCurrentSupermodeNetwork() const
@check if current supermode is Network