SUMO - Simulation of Urban MObility
GNEInspectorFrame.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
16 // The Widget for modifying network-element attributes (i.e. lane speed)
17 /****************************************************************************/
18 
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #include <iostream>
26 #include <cassert>
27 #include <cmath>
28 #include <regex>
45 #include <netedit/GNENet.h>
48 #include <netedit/GNEUndoList.h>
49 #include <netedit/GNEViewNet.h>
50 #include <netedit/GNEViewParent.h>
52 
53 #include "GNEInspectorFrame.h"
54 #include "GNEDeleteFrame.h"
55 #include "GNEAdditionalFrame.h"
56 
57 
58 // ===========================================================================
59 // FOX callback mapping
60 // ===========================================================================
61 
62 FXDEFMAP(GNEInspectorFrame) GNEInspectorFrameMap[] = {
64 
65 };
66 
70 };
71 
72 FXDEFMAP(GNEInspectorFrame::AttributesEditor) AttributesEditorMap[] = {
74 };
75 
76 FXDEFMAP(GNEInspectorFrame::NeteditAttributesEditor) NeteditAttributesEditorMap[] = {
79 };
80 
81 FXDEFMAP(GNEInspectorFrame::GEOAttributesEditor) GEOAttributesEditorMap[] = {
84 };
85 
86 FXDEFMAP(GNEInspectorFrame::TemplateEditor) TemplateEditorMap[] = {
90 };
91 
92 // Object implementation
93 FXIMPLEMENT(GNEInspectorFrame, FXVerticalFrame, GNEInspectorFrameMap, ARRAYNUMBER(GNEInspectorFrameMap))
94 FXIMPLEMENT(GNEInspectorFrame::AttributesEditor::AttributeInput, FXHorizontalFrame, AttributeInputMap, ARRAYNUMBER(AttributeInputMap))
95 FXIMPLEMENT(GNEInspectorFrame::AttributesEditor, FXGroupBox, AttributesEditorMap, ARRAYNUMBER(AttributesEditorMap))
96 FXIMPLEMENT(GNEInspectorFrame::NeteditAttributesEditor, FXGroupBox, NeteditAttributesEditorMap, ARRAYNUMBER(NeteditAttributesEditorMap))
97 FXIMPLEMENT(GNEInspectorFrame::GEOAttributesEditor, FXGroupBox, GEOAttributesEditorMap, ARRAYNUMBER(GEOAttributesEditorMap))
98 FXIMPLEMENT(GNEInspectorFrame::TemplateEditor, FXGroupBox, TemplateEditorMap, ARRAYNUMBER(TemplateEditorMap))
99 
100 
101 // ===========================================================================
102 // method definitions
103 // ===========================================================================
104 
105 GNEInspectorFrame::GNEInspectorFrame(FXHorizontalFrame* horizontalFrameParent, GNEViewNet* viewNet):
106  GNEFrame(horizontalFrameParent, viewNet, "Inspector"),
107  myPreviousElementInspect(nullptr),
108  myPreviousElementDelete(nullptr) {
109 
110  // Create back button
111  myBackButton = new FXButton(myHeaderLeftFrame, "", GUIIconSubSys::getIcon(ICON_NETEDITARROW), this, MID_GNE_INSPECTORFRAME_GOBACK, GUIDesignButtonIconRectangular);
112  myHeaderLeftFrame->hide();
113  myBackButton->hide();
114 
115  // Create Attributes Editor
116  myAttributesEditor = new AttributesEditor(this);
117 
118  // Create GEO Parameters Editor
119  myGEOAttributesEditor = new GEOAttributesEditor(this);
120 
121  // create Generic parameters editor
122  myGenericParametersEditor = new GenericParametersEditor(this);
123 
124  // Create Netedit Attributes Editor
125  myNeteditAttributesEditor = new NeteditAttributesEditor(this);
126 
127  // Create Template editor
128  myTemplateEditor = new TemplateEditor(this);
129 
130  // Create groupbox and tree list
131  myACHierarchy = new GNEFrame::ACHierarchy(this);
132 }
133 
134 
136 
137 
138 void
140  inspectElement(nullptr);
141  GNEFrame::show();
142 }
143 
144 
145 void
147  myInspectedACs.clear();
148  myViewNet->setACUnderCursor(nullptr);
149  GNEFrame::hide();
150 }
151 
152 
153 void
155  // Use the implementation of inspect for multiple AttributeCarriers to avoid repetition of code
156  std::vector<GNEAttributeCarrier*> itemsToInspect;
157  if (AC != nullptr) {
159  if (AC->isAttributeCarrierSelected()) {
160  std::vector<GNEAttributeCarrier*> selectedACs = myViewNet->getNet()->getSelectedAttributeCarriers();
161  for (auto i : selectedACs) {
162  if (i->getTag() == AC->getTag()) {
163  itemsToInspect.push_back(i);
164  }
165  }
166  } else {
167  itemsToInspect.push_back(AC);
168  }
169  }
170  inspectMultisection(itemsToInspect);
171 }
172 
173 
174 void
175 GNEInspectorFrame::inspectMultisection(const std::vector<GNEAttributeCarrier*>& ACs) {
176  // hide back button
177  myHeaderLeftFrame->hide();
178  myBackButton->hide();
179  // Assing ACs to myACs
180  myInspectedACs = ACs;
181  // Hide all elements
188  // If vector of attribute Carriers contain data
189  if (myInspectedACs.size() > 0) {
190  // Set header
191  std::string headerString;
192  if (dynamic_cast<GNENetElement*>(myInspectedACs.front())) {
193  headerString = "Net: ";
194  } else if (dynamic_cast<GNEAdditional*>(myInspectedACs.front())) {
195  headerString = "Additional: ";
196  } else if (dynamic_cast<GNEShape*>(myInspectedACs.front())) {
197  headerString = "Shape: ";
198  }
199  if (myInspectedACs.size() > 1) {
200  headerString += toString(myInspectedACs.size()) + " ";
201  }
202  headerString += toString(myInspectedACs.front()->getTag());
203  if (myInspectedACs.size() > 1) {
204  headerString += "s";
205  }
206  // Set headerString into header label
207  getFrameHeaderLabel()->setText(headerString.c_str());
208 
209  // Show attributes editor
211 
212  // show netedit attributes editor if we're inspecting elements with Netedit Attributes
214 
215  // Show GEO Attributes Editor if we're inspecting elements with GEO Attributes
217 
218  // show generic attributes editor
219  if (myInspectedACs.size() == 1) {
221  } else {
223  }
224 
225  // If attributes correspond to an Edge, show template editor
227 
228  // if we inspect a single Attribute carrier vector, show their childs
229  if (myInspectedACs.size() == 1) {
231  }
232  } else {
233  getFrameHeaderLabel()->setText("Inspect");
234  myContentFrame->recalc();
235  }
236 }
237 
238 
239 void
241  // Show back button if myPreviousElementInspect was defined
242  myPreviousElementInspect = previousElement;
243  if (myPreviousElementInspect != nullptr) {
244  // disable myPreviousElementDelete to avoid inconsistences
245  myPreviousElementDelete = nullptr;
246  inspectElement(AC);
247  myHeaderLeftFrame->show();
248  myBackButton->show();
249  }
250 }
251 
252 
253 void
254 GNEInspectorFrame::inspectFromDeleteFrame(GNEAttributeCarrier* AC, GNEAttributeCarrier* previousElement, bool previousElementWasMarked) {
255  myPreviousElementDelete = previousElement;
256  myPreviousElementDeleteWasMarked = previousElementWasMarked;
257  // Show back button if myPreviousElementDelete is valid
258  if (myPreviousElementDelete != nullptr) {
259  // disable myPreviousElementInspect to avoid inconsistences
260  myPreviousElementInspect = nullptr;
261  inspectElement(AC);
262  myHeaderLeftFrame->show();
263  myBackButton->show();
264  }
265 }
266 
267 void
269  // Only remove if there is inspected ACs
270  if (myInspectedACs.size() > 0) {
271  // Try to find AC in myACs
272  auto i = std::find(myInspectedACs.begin(), myInspectedACs.end(), ac);
273  // if was found
274  if (i != myInspectedACs.end()) {
275  // erase AC from inspected ACs
276  myInspectedACs.erase(i);
277  // Write Warning in console if we're in testing mode
278  WRITE_DEBUG("Removed inspected element from Inspected ACs. " + toString(myInspectedACs.size()) + " ACs remains.");
279  // Inspect multi selection again
281  }
282  }
283 }
284 
285 
286 void
288  // Only remove if there is inspected ACs
289  if (myInspectedACs.size() > 0) {
290  // clear ACs
291  myInspectedACs.clear();
292  myViewNet->setACUnderCursor(nullptr);
293  // Inspect multi selection again (to hide all Editors)
295  }
296 }
297 
298 
301  return myACHierarchy;
302 }
303 
304 
307  return myTemplateEditor;
308 }
309 
310 
311 long
312 GNEInspectorFrame::onCmdGoBack(FXObject*, FXSelector, void*) {
313  // Inspect previous element or go back to Delete Frame
316  myPreviousElementInspect = nullptr;
317  } else if (myPreviousElementDelete != nullptr) {
318  myPreviousElementDelete = nullptr;
319  // Hide inspect frame and show delete frame
320  hide();
322  }
323  return 1;
324 }
325 
326 
327 const std::vector<GNEAttributeCarrier*>&
329  return myInspectedACs;
330 }
331 
332 // ===========================================================================
333 // GNEInspectorFrame::AttributesEditor::AttributeInput method definitions
334 // ===========================================================================
335 
337  FXHorizontalFrame(attributeEditorParent, GUIDesignAuxiliarHorizontalFrame),
338  myAttributesEditorParent(attributeEditorParent),
339  myTag(SUMO_TAG_NOTHING),
340  myAttr(SUMO_ATTR_NOTHING),
341  myMultiple(false) {
342  // Create and hide label
343  myLabel = new FXLabel(this, "attributeLabel", 0, GUIDesignLabelAttribute);
344  myLabel->hide();
345  // Create and hide ButtonCombinableChoices
346  myButtonCombinableChoices = new FXButton(this, "AttributeButton", 0, this, MID_GNE_SET_ATTRIBUTE_DIALOG, GUIDesignButtonAttribute);
348  // create and hidde color editor
349  myColorEditor = new FXButton(this, "ColorButton", 0, this, MID_GNE_SET_ATTRIBUTE_DIALOG, GUIDesignButtonAttribute);
350  myColorEditor->hide();
351  // Create and hide textField for int attributes
353  myTextFieldInt->hide();
354  // Create and hide textField for real/time attributes
356  myTextFieldReal->hide();
357  // Create and hide textField for string attributes
359  myTextFieldStrings->hide();
360  // Create and hide ComboBox
362  myChoicesCombo->hide();
363  // Create and hide checkButton
364  myBoolCheckButton = new FXCheckButton(this, "", this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButtonAttribute);
365  myBoolCheckButton->hide();
366 }
367 
368 
369 void
371  // Set actual Tag, Attribute and multiple
372  myTag = ACTag;
373  myAttr = ACAttr;
374  // set multiple
375  myMultiple = GNEAttributeCarrier::parse<std::vector<std::string>>(value).size() > 1;
376  // obtain attribute property (only for improve code legibility)
378  // enable all input values
380  if (attrValue.isColor()) {
381  myColorEditor->setTextColor(FXRGB(0, 0, 0));
382  myColorEditor->setText(toString(ACAttr).c_str());
383  myColorEditor->show();
384  } else {
385  // Show attribute Label
386  myLabel->setText(toString(myAttr).c_str());
387  myLabel->show();
388  }
389  // Set field depending of the type of value
390  if (attrValue.isBool()) {
391  // set check button
393  myBoolCheckButton->setCheck(true);
394  myBoolCheckButton->setText("true");
395  } else {
396  myBoolCheckButton->setCheck(false);
397  myBoolCheckButton->setText("false");
398  }
399  // show check button
400  myBoolCheckButton->show();
401  // enable or disable depending if attribute is editable
402  if (attrValue.isNonEditable()) {
403  myBoolCheckButton->disable();
404  } else {
405  myBoolCheckButton->enable();
406  }
407  } else if (attrValue.isDiscrete()) {
408  // Check if are combinable choices
409  if ((attrValue.getDiscreteValues().size() > 0) && attrValue.isCombinable()) {
410  // hide label
411  myLabel->hide();
412  // Show button combinable choices
413  myButtonCombinableChoices->setText(toString(myAttr).c_str());
415  // Show string with the values
416  myTextFieldStrings->setText(value.c_str());
417  myTextFieldStrings->setTextColor(FXRGB(0, 0, 0));
418  myTextFieldStrings->show();
419  } else if (!myMultiple) {
420  // fill comboBox
421  myChoicesCombo->clearItems();
422  for (auto it : attrValue.getDiscreteValues()) {
423  myChoicesCombo->appendItem(it.c_str());
424  }
425  // show combo box with values
426  myChoicesCombo->setNumVisible((int)attrValue.getDiscreteValues().size());
427  myChoicesCombo->setCurrentItem(myChoicesCombo->findItem(value.c_str()));
428  myChoicesCombo->setTextColor(FXRGB(0, 0, 0));
429  myChoicesCombo->show();
430  // enable or disable depending if attribute is editable
431  if (attrValue.isNonEditable()) {
432  myChoicesCombo->disable();
433  } else {
434  myChoicesCombo->enable();
435  }
436  } else {
437  // represent combinable choices in multiple selections always with a textfield instead with a comboBox
438  myTextFieldStrings->setText(value.c_str());
439  myTextFieldStrings->setTextColor(FXRGB(0, 0, 0));
440  myTextFieldStrings->show();
441  // enable or disable depending if attribute is editable
442  if (attrValue.isNonEditable()) {
443  myTextFieldStrings->disable();
444  } else {
445  myTextFieldStrings->enable();
446  }
447  }
448  } else if (attrValue.isFloat() || attrValue.isTime()) {
449  // show TextField for real/time values
450  myTextFieldReal->setText(value.c_str());
451  myTextFieldReal->setTextColor(FXRGB(0, 0, 0));
452  myTextFieldReal->show();
453  // enable or disable depending if attribute is editable
454  if (attrValue.isNonEditable()) {
455  myTextFieldReal->disable();
456  } else {
457  myTextFieldReal->enable();
458  }
459  } else if (attrValue.isInt()) {
460  // Show textField for int attributes
461  myTextFieldInt->setText(value.c_str());
462  myTextFieldInt->setTextColor(FXRGB(0, 0, 0));
463  myTextFieldInt->show();
464  // enable or disable depending if attribute is editable
465  if (attrValue.isNonEditable()) {
466  myTextFieldInt->disable();
467  } else {
468  myTextFieldInt->enable();
469  }
470  } else {
471  // In any other case (String, list, etc.), show value as String
472  myTextFieldStrings->setText(value.c_str());
473  myTextFieldStrings->setTextColor(FXRGB(0, 0, 0));
474  myTextFieldStrings->show();
475  // enable or disable depending if attribute is editable
476  if (attrValue.isNonEditable()) {
477  myTextFieldStrings->disable();
478  } else {
479  myTextFieldStrings->enable();
480  }
481  }
482  // Show AttributeInput
483  show();
484  // recalc after show elements
485  recalc();
486 }
487 
488 
489 void
491  // Hide all elements
492  myLabel->hide();
493  myTextFieldInt->hide();
494  myTextFieldReal->hide();
495  myTextFieldStrings->hide();
496  myChoicesCombo->hide();
497  myBoolCheckButton->hide();
499  myColorEditor->hide();
500  // hide AttributeInput
501  hide();
502  // recalc after hide all elements
503  recalc();
504 }
505 
506 
507 void
509  if (myTextFieldInt->shown()) {
510  // set last valid value and restore color if onlyValid is disabled
511  if (myTextFieldInt->getTextColor() == FXRGB(0, 0, 0) || forceRefresh) {
512  myTextFieldInt->setText(value.c_str());
513  myTextFieldInt->setTextColor(FXRGB(0, 0, 0));
514  }
515  } else if (myTextFieldReal->shown()) {
516  // set last valid value and restore color if onlyValid is disabled
517  if (myTextFieldReal->getTextColor() == FXRGB(0, 0, 0) || forceRefresh) {
518  myTextFieldReal->setText(value.c_str());
519  myTextFieldReal->setTextColor(FXRGB(0, 0, 0));
520  }
521  } else if (myTextFieldStrings->shown()) {
522  // set last valid value and restore color if onlyValid is disabled
523  if (myTextFieldStrings->getTextColor() == FXRGB(0, 0, 0) || forceRefresh) {
524  myTextFieldStrings->setText(value.c_str());
525  myTextFieldStrings->setTextColor(FXRGB(0, 0, 0));
526  }
527  } else if (myChoicesCombo->shown()) {
528  // set last valid value and restore color if onlyValid is disabled
529  if (myChoicesCombo->getTextColor() == FXRGB(0, 0, 0) || forceRefresh) {
530  myChoicesCombo->setText(value.c_str());
531  myChoicesCombo->setTextColor(FXRGB(0, 0, 0));
532  }
533  } else if (myBoolCheckButton->shown()) {
534  myBoolCheckButton->setCheck(GNEAttributeCarrier::parse<bool>(value));
535  }
536 }
537 
538 
539 bool
541  return ((myTextFieldInt->getTextColor() == FXRGB(0, 0, 0)) && (myTextFieldReal->getTextColor() == FXRGB(0, 0, 0)) &&
542  (myTextFieldStrings->getTextColor() == FXRGB(0, 0, 0)) && (myChoicesCombo->getTextColor() == FXRGB(0, 0, 0)));
543 }
544 
545 
546 long
548  if (obj == myColorEditor) {
549  // create FXColorDialog
550  FXColorDialog colordialog(this, tr("Color Dialog"));
551  colordialog.setTarget(this);
552  // If previous attribute wasn't correct, set black as default color
553  if (GNEAttributeCarrier::canParse<RGBColor>(myTextFieldStrings->getText().text())) {
554  colordialog.setRGBA(MFXUtils::getFXColor(RGBColor::parseColor(myTextFieldStrings->getText().text())));
555  } else {
557  }
558  // execute dialog to get a new color
559  if (colordialog.execute()) {
560  std::string newValue = toString(MFXUtils::getRGBColor(colordialog.getRGBA()));
561  myTextFieldStrings->setText(newValue.c_str());
562  if (myAttributesEditorParent->getInspectorFrameParent()->getInspectedACs().front()->isValid(myAttr, newValue)) {
563  // if its valid for the first AC than its valid for all (of the same type)
565  myAttributesEditorParent->getInspectorFrameParent()->getViewNet()->getUndoList()->p_begin("Change multiple attributes");
566  }
567  // Set new value of attribute in all selected ACs
569  it_ac->setAttribute(myAttr, newValue, myAttributesEditorParent->getInspectorFrameParent()->getViewNet()->getUndoList());
570  }
571  // If previously value was incorrect, change font color to black
572  myTextFieldStrings->setTextColor(FXRGB(0, 0, 0));
573  myTextFieldStrings->killFocus();
574  }
575  }
576  return 0;
577  } else if (obj == myButtonCombinableChoices) {
578  // if its valid for the first AC than its valid for all (of the same type)
580  myAttributesEditorParent->getInspectorFrameParent()->getViewNet()->getUndoList()->p_begin("Change multiple attributes");
581  }
582  // open GNEDialog_AllowDisallow
584  std::string allowed = myAttributesEditorParent->getInspectorFrameParent()->getInspectedACs().front()->getAttribute(SUMO_ATTR_ALLOW);
585  // Set new value of attribute in all selected ACs
588  }
589  // finish change multiple attributes
592  }
593  return 1;
594  } else {
595  throw ProcessError("Invalid call to onCmdOpenAttributeDialog");
596  }
597 }
598 
599 
600 long
602  // Declare changed value
603  std::string newVal;
604  bool refreshGEOAndNeteditEditors = false;
605  // get Tag and attribute Values (only for improve efficiency)
606  const auto& tagValues = GNEAttributeCarrier::getTagProperties(myTag);
607  const auto& attrValues = tagValues.getAttribute(myAttr);
608  // First, obtain the string value of the new attribute depending of their type
609  if (attrValues.isBool()) {
610  // Set true o false depending of the checkBox
611  if (myBoolCheckButton->getCheck()) {
612  myBoolCheckButton->setText("true");
613  newVal = "true";
614  } else {
615  myBoolCheckButton->setText("false");
616  newVal = "false";
617  }
618  } else if (attrValues.isDiscrete()) {
619  // Check if are combinable choices (for example, Vehicle Types)
620  if ((attrValues.getDiscreteValues().size() > 0) &&
621  attrValues.isCombinable()) {
622  // Get value obtained using AttributesEditor
623  newVal = myTextFieldStrings->getText().text();
624  } else if (!myMultiple) {
625  // Get value of ComboBox
626  newVal = myChoicesCombo->getText().text();
627  } else {
628  // due this is a multiple selection, obtain value of myTextFieldStrings instead of comboBox
629  newVal = myTextFieldStrings->getText().text();
630  }
631  } else if (attrValues.isFloat() || attrValues.isTime()) {
632  // Check if default value of attribute must be set
633  if (myTextFieldReal->getText().empty() && attrValues.hasDefaultValue()) {
634  newVal = tagValues.getDefaultValue(myAttr);
635  myTextFieldReal->setText(newVal.c_str());
636  } else {
637  // obtain value of myTextFieldReal
638  newVal = myTextFieldReal->getText().text();
639  }
640  } else if (attrValues.isInt()) {
641  // Check if default value of attribute must be set
642  if (myTextFieldInt->getText().empty() && attrValues.hasDefaultValue()) {
643  newVal = tagValues.getDefaultValue(myAttr);
644  myTextFieldInt->setText(newVal.c_str());
645  } else {
646  // obtain value of myTextFieldInt
647  newVal = myTextFieldInt->getText().text();
648  }
649  } else if (attrValues.isString()) {
650  // Check if default value of attribute must be set
651  if (myTextFieldStrings->getText().empty() && attrValues.hasDefaultValue()) {
652  newVal = tagValues.getDefaultValue(myAttr);
653  myTextFieldStrings->setText(newVal.c_str());
654  } else {
655  // obtain value of myTextFieldStrings
656  newVal = myTextFieldStrings->getText().text();
657  }
658  }
659 
660  // we need a extra check for Position and Shape Values, due #2658
661  if ((myAttr == SUMO_ATTR_POSITION) || (myAttr == SUMO_ATTR_SHAPE)) {
662  newVal = stripWhitespaceAfterComma(newVal);
663  // due we're changing a Position and Shape attribute, GEO and Netedit Editors must be refresh
664  refreshGEOAndNeteditEditors = true;
665  }
666 
667  // Check if attribute must be changed
668  if (myAttributesEditorParent->getInspectorFrameParent()->getInspectedACs().front()->isValid(myAttr, newVal)) {
669  // if its valid for the first AC than its valid for all (of the same type)
671  myAttributesEditorParent->getInspectorFrameParent()->getViewNet()->getUndoList()->p_begin("Change multiple attributes");
672  } else if (myAttr == SUMO_ATTR_ID) {
673  // IDs attribute has to be encapsulated
675  }
676  // Set new value of attribute in all selected ACs
678  it_ac->setAttribute(myAttr, newVal, myAttributesEditorParent->getInspectorFrameParent()->getViewNet()->getUndoList());
679  }
680  // finish change multiple attributes or ID Attributes
683  } else if (myAttr == SUMO_ATTR_ID) {
685  }
686  // If previously value was incorrect, change font color to black
687  if (attrValues.isCombinable()) {
688  myTextFieldStrings->setTextColor(FXRGB(0, 0, 0));
689  myTextFieldStrings->killFocus();
690  // in this case, we need to refresh the other values (For example, allow/Disallow objects)
692  } else if (attrValues.isDiscrete()) {
693  myChoicesCombo->setTextColor(FXRGB(0, 0, 0));
694  myChoicesCombo->killFocus();
695  } else if (attrValues.isFloat() || attrValues.isTime()) {
696  myTextFieldReal->setTextColor(FXRGB(0, 0, 0));
697  myTextFieldReal->killFocus();
698  } else if (attrValues.isInt() && myTextFieldStrings != 0) {
699  myTextFieldInt->setTextColor(FXRGB(0, 0, 0));
700  myTextFieldInt->killFocus();
701  } else if (myTextFieldStrings != 0) {
702  myTextFieldStrings->setTextColor(FXRGB(0, 0, 0));
703  myTextFieldStrings->killFocus();
704  }
705  // Check if GEO and Netedit editors must be refresh
706  if (refreshGEOAndNeteditEditors) {
709  }
710  } else {
711  // If value of TextField isn't valid, change color to Red depending of type
712  if (attrValues.isCombinable()) {
713  myTextFieldStrings->setTextColor(FXRGB(255, 0, 0));
714  myTextFieldStrings->killFocus();
715  } else if (attrValues.isDiscrete()) {
716  myChoicesCombo->setTextColor(FXRGB(255, 0, 0));
717  myChoicesCombo->killFocus();
718  } else if (attrValues.isFloat() || attrValues.isTime()) {
719  myTextFieldReal->setTextColor(FXRGB(255, 0, 0));
720  } else if (attrValues.isInt() && myTextFieldStrings != 0) {
721  myTextFieldInt->setTextColor(FXRGB(255, 0, 0));
722  } else if (myTextFieldStrings != 0) {
723  myTextFieldStrings->setTextColor(FXRGB(255, 0, 0));
724  }
725  // Write Warning in console if we're in testing mode
726  WRITE_DEBUG("Value '" + newVal + "' for attribute " + toString(myAttr) + " of " + toString(myTag) + " isn't valid");
727  }
728  return 1;
729 }
730 
731 
732 std::string
734  std::string result(stringValue);
735  while (result.find(", ") != std::string::npos) {
736  result = StringUtils::replace(result, ", ", ",");
737  }
738  return result;
739 }
740 
741 
742 void
744  myTextFieldInt->enable();
745  myTextFieldReal->enable();
746  myTextFieldStrings->enable();
747  myChoicesCombo->enable();
748  myBoolCheckButton->enable();
749 }
750 
751 
752 void
754  myTextFieldInt->disable();
755  myTextFieldReal->disable();
756  myTextFieldStrings->disable();
757  myChoicesCombo->disable();
758  myBoolCheckButton->disable();
759 }
760 
761 // ===========================================================================
762 // GNEInspectorFrame::AttributesEditor method definitions
763 // ===========================================================================
764 
766  FXGroupBox(inspectorFrameParent->myContentFrame, "Internal attributes", GUIDesignGroupBoxFrame),
767  myInspectorFrameParent(inspectorFrameParent) {
768  // Create sufficient AttributeInput for all types of AttributeCarriers
769  for (int i = 0; i < (int)GNEAttributeCarrier::getHigherNumberOfAttributes(); i++) {
770  myVectorOfAttributeInputs.push_back(new AttributeInput(this));
771  }
772  // Create help button
773  myHelpButton = new FXButton(this, "Help", 0, this, MID_HELP, GUIDesignButtonRectangular);
774 }
775 
776 
777 void
779  if (myInspectorFrameParent->getInspectedACs().size() > 0) {
780  // Gets tag (only for simplify code)
781  SumoXMLTag ACFrontTag = myInspectorFrameParent->getInspectedACs().front()->getTag();
782  // check if current AC is a Junction without TLSs (needed to hidde TLS options)
783  bool disableTLSinJunctions = (dynamic_cast<GNEJunction*>(myInspectorFrameParent->getInspectedACs().front()) && (dynamic_cast<GNEJunction*>(myInspectorFrameParent->getInspectedACs().front())->getNBNode()->getControllingTLS().empty()));
784  // Iterate over attributes
785  for (auto it : GNEAttributeCarrier::getTagProperties(ACFrontTag)) {
786  // disable editing for unique attributes in case of multi-selection
787  if ((myInspectorFrameParent->getInspectedACs().size() > 1) && it.second.isUnique()) {
788  continue;
789  }
790  // Declare a set of occuring values and insert attribute's values of item
791  std::set<std::string> occuringValues;
792  for (auto it_ac : myInspectorFrameParent->getInspectedACs()) {
793  occuringValues.insert(it_ac->getAttribute(it.first));
794  }
795  // get current value
796  std::ostringstream oss;
797  for (auto it_val = occuringValues.begin(); it_val != occuringValues.end(); it_val++) {
798  if (it_val != occuringValues.begin()) {
799  oss << " ";
800  }
801  oss << *it_val;
802  }
803  // Show attribute
804  if ((disableTLSinJunctions && (ACFrontTag == SUMO_TAG_JUNCTION) && ((it.first == SUMO_ATTR_TLTYPE) || (it.first == SUMO_ATTR_TLID))) == false) {
805  // first show AttributesEditor
806  show();
807  // show attribute
808  myVectorOfAttributeInputs[it.second.getPositionListed()]->showAttribute(ACFrontTag, it.first, oss.str());
809  }
810  }
811  }
812 }
813 
814 
815 void
817  // hide al attributes
818  for (auto i : myVectorOfAttributeInputs) {
819  i->hideAttribute();
820  }
821  // hide also AttributesEditor
822  hide();
823 }
824 
825 
826 void
827 GNEInspectorFrame::AttributesEditor::refreshAttributeEditor(bool forceRefreshShape, bool forceRefreshPosition) {
828  if (myInspectorFrameParent->getInspectedACs().size() > 0) {
829  // Declare pointer for allow/Disallow vehicles
830  std::pair<GNEInspectorFrame::AttributesEditor::AttributeInput*, std::string> myAllowAttribute(nullptr, "");
831  std::pair<GNEInspectorFrame::AttributesEditor::AttributeInput*, std::string> myDisallowAttribute(nullptr, "");
832  // Gets tag (only for simplify code)
833  SumoXMLTag ACFrontTag = myInspectorFrameParent->getInspectedACs().front()->getTag();
834  // check if current AC is a Junction without TLSs (needed to hidde TLS options)
835  bool disableTLSinJunctions = (dynamic_cast<GNEJunction*>(myInspectorFrameParent->getInspectedACs().front()) && (dynamic_cast<GNEJunction*>(myInspectorFrameParent->getInspectedACs().front())->getNBNode()->getControllingTLS().empty()));
836  // Iterate over attributes
837  for (auto it : GNEAttributeCarrier::getTagProperties(ACFrontTag)) {
838  // disable editing for unique attributes in case of multi-selection
839  if ((myInspectorFrameParent->getInspectedACs().size() > 1) && it.second.isUnique()) {
840  continue;
841  }
842  // Declare a set of occuring values and insert attribute's values of item
843  std::set<std::string> occuringValues;
844  for (auto it_ac : myInspectorFrameParent->getInspectedACs()) {
845  occuringValues.insert(it_ac->getAttribute(it.first));
846  }
847  // get current value
848  std::ostringstream oss;
849  for (auto it_val = occuringValues.begin(); it_val != occuringValues.end(); it_val++) {
850  if (it_val != occuringValues.begin()) {
851  oss << " ";
852  }
853  oss << *it_val;
854  }
855  // Show attribute
856  if ((disableTLSinJunctions && (ACFrontTag == SUMO_TAG_JUNCTION) && ((it.first == SUMO_ATTR_TLTYPE) || (it.first == SUMO_ATTR_TLID))) == false) {
857  // refresh attribute, with a special case for allow/disallow vehicles
858  if (it.first == SUMO_ATTR_ALLOW) {
859  myAllowAttribute.first = myVectorOfAttributeInputs[it.second.getPositionListed()];
860  myAllowAttribute.second = oss.str();
861  } else if (it.first == SUMO_ATTR_DISALLOW) {
862  myDisallowAttribute.first = myVectorOfAttributeInputs[it.second.getPositionListed()];
863  myDisallowAttribute.second = oss.str();
864  } else {
865  // Check if refresh of Position or Shape has to be forced
866  if ((it.first == SUMO_ATTR_SHAPE) && forceRefreshShape) {
867  myVectorOfAttributeInputs[it.second.getPositionListed()]->refreshAttributeInput(oss.str(), true);
868  } else if ((it.first == SUMO_ATTR_POSITION) && forceRefreshPosition) {
869  // Refresh attributes maintain invalid values
870  myVectorOfAttributeInputs[it.second.getPositionListed()]->refreshAttributeInput(oss.str(), true);
871  } else {
872  // Refresh attributes maintain invalid values
873  myVectorOfAttributeInputs[it.second.getPositionListed()]->refreshAttributeInput(oss.str(), false);
874  }
875  }
876  }
877  }
878  // Check special case for Allow/Disallow attributes
879  if (myAllowAttribute.first && myDisallowAttribute.first) {
880  // if allow attribute is valid but disallow attribute is invalid
881  if (myAllowAttribute.first->isCurrentAttributeValid() && !myDisallowAttribute.first->isCurrentAttributeValid()) {
882  // force refresh of disallow attribute
883  myDisallowAttribute.first->refreshAttributeInput(myDisallowAttribute.second, true);
884  }
885  // if disallow attribute is valid but allow attribute is invalid
886  if (myDisallowAttribute.first->isCurrentAttributeValid() && !myAllowAttribute.first->isCurrentAttributeValid()) {
887  // force refresh of disallow attribute
888  myAllowAttribute.first->refreshAttributeInput(myAllowAttribute.second, true);
889  }
890  }
891  }
892 }
893 
894 
897  return myInspectorFrameParent;
898 }
899 
900 
901 long
903  // open Help attributes dialog if there is inspected ACs
904  if (myInspectorFrameParent->getInspectedACs().size() > 0) {
905  // open Help attributes dialog
907  }
908  return 1;
909 }
910 
911 // ===========================================================================
912 // GNEInspectorFrame::NeteditAttributesEditor method definitions
913 // ===========================================================================
914 
916  FXGroupBox(inspectorFrameParent->myContentFrame, "Netedit attributes", GUIDesignGroupBoxFrame),
917  myInspectorFrameParent(inspectorFrameParent) {
918 
919  // Create elements for additional parent
923 
924  // Create elements for block movement
928 
929  // Create elements for block shape
930  myHorizontalFrameBlockShape = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
933 
934  // Create elements for close shape
935  myHorizontalFrameCloseShape = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
938 
939  // Create help button
940  myHelpButton = new FXButton(this, "Help", 0, this, MID_HELP, GUIDesignButtonRectangular);
941 }
942 
943 
945 
946 
947 void
949  if (myInspectorFrameParent->getInspectedACs().size() > 0) {
950  // obtain tag property (only for improve code legibility)
951  const auto& tagValue = GNEAttributeCarrier::getTagProperties(myInspectorFrameParent->getInspectedACs().front()->getTag());
952  // Check if item can be moved
953  if (tagValue.canBlockMovement()) {
954  // show NeteditAttributesEditor
955  show();
956  // Iterate over AC to obtain values
957  bool value = true;
958  for (auto i : myInspectorFrameParent->getInspectedACs()) {
959  value &= GNEAttributeCarrier::parse<bool>(i->getAttribute(GNE_ATTR_BLOCK_MOVEMENT));
960  }
961  // show block movement frame
963  // set check box value and update label
964  if (value) {
965  myCheckBoxBlockMovement->setCheck(true);
966  myCheckBoxBlockMovement->setText("true");
967  } else {
968  myCheckBoxBlockMovement->setCheck(false);
969  myCheckBoxBlockMovement->setText("false");
970  }
971  }
972  // check if item can block their shape
973  if (tagValue.canBlockShape()) {
974  // show NeteditAttributesEditor
975  show();
976  // Iterate over AC to obtain values
977  bool value = true;
978  for (auto i : myInspectorFrameParent->getInspectedACs()) {
979  value &= GNEAttributeCarrier::parse<bool>(i->getAttribute(GNE_ATTR_BLOCK_SHAPE));
980  }
981  // show block shape frame
983  // set check box value and update label
984  if (value) {
985  myCheckBoxBlockShape->setCheck(true);
986  myCheckBoxBlockShape->setText("true");
987  } else {
988  myCheckBoxBlockShape->setCheck(false);
989  myCheckBoxBlockShape->setText("false");
990  }
991  }
992  // check if item can block their shape
993  if (tagValue.canCloseShape()) {
994  // show NeteditAttributesEditor
995  show();
996  // Iterate over AC to obtain values
997  bool value = true;
998  for (auto i : myInspectorFrameParent->getInspectedACs()) {
999  value &= GNEAttributeCarrier::parse<bool>(i->getAttribute(GNE_ATTR_CLOSE_SHAPE));
1000  }
1001  // show close shape frame
1003  // set check box value and update label
1004  if (value) {
1005  myCheckBoxCloseShape->setCheck(true);
1006  myCheckBoxCloseShape->setText("true");
1007  } else {
1008  myCheckBoxCloseShape->setCheck(false);
1009  myCheckBoxCloseShape->setText("false");
1010  }
1011  }
1012  // Check if item has another item as parent and can be reparemt
1013  if (tagValue.hasParent() && tagValue.canBeReparent()) {
1014  // show NeteditAttributesEditor
1015  show();
1016  // obtain additional Parent
1017  GNEAdditional* additional = myInspectorFrameParent->getViewNet()->getNet()->retrieveAdditional(tagValue.getParentTag(), myInspectorFrameParent->getInspectedACs().front()->getAttribute(GNE_ATTR_PARENT));
1018  // show additional parent frame
1020  // set Label and TextField with the Tag and ID of parent
1021  myLabelAdditionalParent->setText((toString(additional->getTag()) + " parent").c_str());
1022  myTextFieldAdditionalParent->setText(additional->getID().c_str());
1023  }
1024  }
1025 }
1026 
1027 
1028 void
1030  // hide all elements of GroupBox
1035  // hide groupbox
1036  hide();
1037 }
1038 
1039 
1040 void
1042  if (myInspectorFrameParent->getInspectedACs().size() > 0) {
1043  // refresh block movement
1044  if (myHorizontalFrameBlockMovement->shown()) {
1045  // Iterate over AC to obtain values
1046  bool value = true;
1047  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1048  value &= GNEAttributeCarrier::parse<bool>(i->getAttribute(GNE_ATTR_BLOCK_MOVEMENT));
1049  }
1050  // set check box value and update label
1051  if (value) {
1052  myCheckBoxBlockMovement->setCheck(true);
1053  myCheckBoxBlockMovement->setText("true");
1054  } else {
1055  myCheckBoxBlockMovement->setCheck(false);
1056  myCheckBoxBlockMovement->setText("false");
1057  }
1058  }
1059  // refresh block shape
1060  if (myHorizontalFrameBlockShape->shown()) {
1061  // Iterate over AC to obtain values
1062  bool value = true;
1063  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1064  value &= GNEAttributeCarrier::parse<bool>(i->getAttribute(GNE_ATTR_BLOCK_SHAPE));
1065  }
1066  // set check box value and update label
1067  if (value) {
1068  myCheckBoxBlockShape->setCheck(true);
1069  myCheckBoxBlockShape->setText("true");
1070  } else {
1071  myCheckBoxBlockShape->setCheck(false);
1072  myCheckBoxBlockShape->setText("false");
1073  }
1074  }
1075  // refresh close shape
1076  if (myHorizontalFrameCloseShape->shown()) {
1077  // Iterate over AC to obtain values
1078  bool value = true;
1079  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1080  value &= GNEAttributeCarrier::parse<bool>(i->getAttribute(GNE_ATTR_CLOSE_SHAPE));
1081  }
1082  // set check box value and update label
1083  if (value) {
1084  myCheckBoxCloseShape->setCheck(true);
1085  myCheckBoxCloseShape->setText("true");
1086  } else {
1087  myCheckBoxCloseShape->setCheck(false);
1088  myCheckBoxCloseShape->setText("false");
1089  }
1090  }
1091  // Check if item has another item as parent (Currently only for single Additionals)
1092  if (myHorizontalFrameAdditionalParent->shown() && ((myTextFieldAdditionalParent->getTextColor() == FXRGB(0, 0, 0)) || forceRefresh)) {
1093  // set Label and TextField with the Tag and ID of parent
1094  myLabelAdditionalParent->setText((toString(GNEAttributeCarrier::getTagProperties(myInspectorFrameParent->getInspectedACs().front()->getTag()).getParentTag()) + " parent").c_str());
1095  myTextFieldAdditionalParent->setText(myInspectorFrameParent->getInspectedACs().front()->getAttribute(GNE_ATTR_PARENT).c_str());
1096  }
1097  }
1098 }
1099 
1100 
1101 long
1103 
1104  // make sure that ACs has elements
1105  if (myInspectorFrameParent->getInspectedACs().size() > 0) {
1106  // check if we're changing multiple attributes
1107  if (myInspectorFrameParent->getInspectedACs().size() > 1) {
1108  myInspectorFrameParent->getViewNet()->getUndoList()->p_begin("Change multiple attributes");
1109  }
1110  if (obj == myCheckBoxBlockMovement) {
1111  // set new values in all inspected Attribute Carriers
1112  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1113  if (myCheckBoxBlockMovement->getCheck() == 1) {
1114  i->setAttribute(GNE_ATTR_BLOCK_MOVEMENT, "true", myInspectorFrameParent->getViewNet()->getUndoList());
1115  myCheckBoxBlockMovement->setText("true");
1116  } else {
1117  i->setAttribute(GNE_ATTR_BLOCK_MOVEMENT, "false", myInspectorFrameParent->getViewNet()->getUndoList());
1118  myCheckBoxBlockMovement->setText("false");
1119  }
1120  }
1121  } else if (obj == myCheckBoxBlockShape) {
1122  // set new values in all inspected Attribute Carriers
1123  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1124  if (myCheckBoxBlockShape->getCheck() == 1) {
1125  i->setAttribute(GNE_ATTR_BLOCK_SHAPE, "true", myInspectorFrameParent->getViewNet()->getUndoList());
1126  myCheckBoxBlockShape->setText("true");
1127  } else {
1128  i->setAttribute(GNE_ATTR_BLOCK_SHAPE, "false", myInspectorFrameParent->getViewNet()->getUndoList());
1129  myCheckBoxBlockShape->setText("false");
1130  }
1131  }
1132  } else if (obj == myCheckBoxCloseShape) {
1133  // set new values in all inspected Attribute Carriers
1134  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1135  if (myCheckBoxCloseShape->getCheck() == 1) {
1136  i->setAttribute(GNE_ATTR_CLOSE_SHAPE, "true", myInspectorFrameParent->getViewNet()->getUndoList());
1137  myCheckBoxCloseShape->setText("true");
1138  } else {
1139  i->setAttribute(GNE_ATTR_CLOSE_SHAPE, "false", myInspectorFrameParent->getViewNet()->getUndoList());
1140  myCheckBoxCloseShape->setText("false");
1141  }
1142  }
1143  } else if (obj == myTextFieldAdditionalParent) {
1144  if (myInspectorFrameParent->getInspectedACs().front()->isValid(GNE_ATTR_PARENT, myTextFieldAdditionalParent->getText().text())) {
1145  // change parent of all inspected elements
1146  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1148  }
1149  myTextFieldAdditionalParent->setTextColor(FXRGB(0, 0, 0));
1150  } else {
1151  myTextFieldAdditionalParent->setTextColor(FXRGB(255, 0, 0));
1152  myTextFieldAdditionalParent->killFocus();
1153  }
1154  }
1155  // finish change multiple attributes
1156  if (myInspectorFrameParent->getInspectedACs().size() > 1) {
1158  }
1159  // force refresh values of AttributesEditor and GEOAttributesEditor
1162  }
1163  return 1;
1164 }
1165 
1166 
1167 long
1169  return 0;
1170 }
1171 
1172 // ---------------------------------------------------------------------------
1173 // GNEInspectorFrame::GEOAttributesEditor - methods
1174 // ---------------------------------------------------------------------------
1175 
1177  FXGroupBox(inspectorFrameParent->myContentFrame, "GEO Attributes", GUIDesignGroupBoxFrame),
1178  myInspectorFrameParent(inspectorFrameParent) {
1179 
1180  // Create Frame for GEOAttribute
1181  myGEOAttributeFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
1182  myGEOAttributeLabel = new FXLabel(myGEOAttributeFrame, "Undefined GEO Attribute", 0, GUIDesignLabelAttribute);
1184 
1185  // Create Frame for use GEO
1186  myUseGEOFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
1189 
1190  // Create help button
1191  myHelpButton = new FXButton(this, "Help", 0, this, MID_HELP, GUIDesignButtonRectangular);
1192 }
1193 
1194 
1196 
1197 
1198 void
1200  // make sure that ACs has elements
1201  if (myInspectorFrameParent->getInspectedACs().size() > 0) {
1202  // obtain tag property (only for improve code legibility)
1203  const auto& tagValue = GNEAttributeCarrier::getTagProperties(myInspectorFrameParent->getInspectedACs().front()->getTag());
1204  // check if item can use a geo position
1205  if (tagValue.hasGEOPosition() || tagValue.hasGEOShape()) {
1206  // show GEOAttributesEditor
1207  show();
1208  // Iterate over AC to obtain values
1209  bool value = true;
1210  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1211  value &= GNEAttributeCarrier::parse<bool>(i->getAttribute(SUMO_ATTR_GEO));
1212  }
1213  // show use geo frame
1214  myUseGEOFrame->show();
1215  // set UseGEOCheckButton value of and update label (only if geo conversion is defined)
1216  if (GeoConvHelper::getFinal().getProjString() != "!") {
1217  myUseGEOCheckButton->enable();
1218  if (value) {
1219  myUseGEOCheckButton->setCheck(true);
1220  myUseGEOCheckButton->setText("true");
1221  } else {
1222  myUseGEOCheckButton->setCheck(false);
1223  myUseGEOCheckButton->setText("false");
1224  }
1225  } else {
1226  myUseGEOCheckButton->disable();
1227  }
1228  // now specify if a single position or an entire shape must be shown (note: cannot be shown both at the same time, and GEO Shape/Position only works for single selections)
1229  if (tagValue.hasGEOPosition() && myInspectorFrameParent->getInspectedACs().size() == 1) {
1230  myGEOAttributeFrame->show();
1232  myGEOAttributeTextField->setTextColor(FXRGB(0, 0, 0));
1233  // only allow edit if geo conversion is defined
1234  if (GeoConvHelper::getFinal().getProjString() != "!") {
1235  myGEOAttributeTextField->enable();
1236  myGEOAttributeTextField->setText(myInspectorFrameParent->getInspectedACs().front()->getAttribute(SUMO_ATTR_GEOPOSITION).c_str());
1237  } else {
1238  myGEOAttributeTextField->disable();
1239  myGEOAttributeTextField->setText("No geo-conversion defined");
1240  }
1241  } else if (tagValue.hasGEOShape() && myInspectorFrameParent->getInspectedACs().size() == 1) {
1242  myGEOAttributeFrame->show();
1243  myGEOAttributeLabel->setText(toString(SUMO_ATTR_GEOSHAPE).c_str());
1244  myGEOAttributeTextField->setTextColor(FXRGB(0, 0, 0));
1245  // only allow edit if geo conversion is defined
1246  if (GeoConvHelper::getFinal().getProjString() != "!") {
1247  myGEOAttributeTextField->enable();
1248  myGEOAttributeTextField->setText(myInspectorFrameParent->getInspectedACs().front()->getAttribute(SUMO_ATTR_GEOSHAPE).c_str());
1249  } else {
1250  myGEOAttributeTextField->disable();
1251  myGEOAttributeTextField->setText("No geo-conversion defined");
1252  }
1253  }
1254  }
1255  }
1256 }
1257 
1258 
1259 void
1261  // hide all elements of GroupBox
1262  myGEOAttributeFrame->hide();
1263  myUseGEOFrame->hide();
1264  // hide groupbox
1265  hide();
1266 }
1267 
1268 
1269 void
1271  // obtain tag property (only for improve code legibility)
1272  const auto& tagValue = GNEAttributeCarrier::getTagProperties(myInspectorFrameParent->getInspectedACs().front()->getTag());
1273  // Check that myGEOAttributeFrame is shown
1274  if ((GeoConvHelper::getFinal().getProjString() != "!") && myGEOAttributeFrame->shown() && ((myGEOAttributeTextField->getTextColor() == FXRGB(0, 0, 0)) || forceRefresh)) {
1275  if (tagValue.hasGEOPosition()) {
1276  myGEOAttributeTextField->setText(myInspectorFrameParent->getInspectedACs().front()->getAttribute(SUMO_ATTR_GEOPOSITION).c_str());
1277  } else if (tagValue.hasGEOShape()) {
1278  myGEOAttributeTextField->setText(myInspectorFrameParent->getInspectedACs().front()->getAttribute(SUMO_ATTR_GEOSHAPE).c_str());
1279  }
1280  myGEOAttributeTextField->setTextColor(FXRGB(0, 0, 0));
1281  }
1282 }
1283 
1284 
1285 long
1287  // make sure that ACs has elements
1288  if ((GeoConvHelper::getFinal().getProjString() != "!") && (myInspectorFrameParent->getInspectedACs().size() > 0)) {
1289  if (obj == myGEOAttributeTextField) {
1290  // obtain tag property (only for improve code legibility)
1291  const auto& tagValue = GNEAttributeCarrier::getTagProperties(myInspectorFrameParent->getInspectedACs().front()->getTag());
1292  // Change GEO Attribute depending of type (Position or shape)
1293  if (tagValue.hasGEOPosition()) {
1294  if (myInspectorFrameParent->getInspectedACs().front()->isValid(SUMO_ATTR_GEOPOSITION, myGEOAttributeTextField->getText().text())) {
1296  myGEOAttributeTextField->setTextColor(FXRGB(0, 0, 0));
1297  } else {
1298  myGEOAttributeTextField->setTextColor(FXRGB(255, 0, 0));
1299  myGEOAttributeTextField->killFocus();
1300  }
1301  } else if (tagValue.hasGEOShape()) {
1302  if (myInspectorFrameParent->getInspectedACs().front()->isValid(SUMO_ATTR_GEOSHAPE, myGEOAttributeTextField->getText().text())) {
1304  myGEOAttributeTextField->setTextColor(FXRGB(0, 0, 0));
1305  } else {
1306  myGEOAttributeTextField->setTextColor(FXRGB(255, 0, 0));
1307  myGEOAttributeTextField->killFocus();
1308  }
1309  } else {
1310  throw ProcessError("myGEOAttributeTextField must be hidden becaurse there isn't GEO Attribute to edit");
1311  }
1312  } else if (obj == myUseGEOCheckButton) {
1313  // update GEO Attribute of entire selection
1314  for (auto i : myInspectorFrameParent->getInspectedACs()) {
1315  if (myUseGEOCheckButton->getCheck() == 1) {
1316  i->setAttribute(SUMO_ATTR_GEO, "true", myInspectorFrameParent->getViewNet()->getUndoList());
1317  myUseGEOCheckButton->setText("true");
1318  } else {
1319  i->setAttribute(SUMO_ATTR_GEO, "false", myInspectorFrameParent->getViewNet()->getUndoList());
1320  myUseGEOCheckButton->setText("false");
1321  }
1322  }
1323  }
1324  // force refresh values of Attributes editor and NeteditAttributesEditor
1327  }
1328  return 1;
1329 }
1330 
1331 
1332 long
1334  FXDialogBox* helpDialog = new FXDialogBox(this, "GEO attributes Help", GUIDesignDialogBox);
1335  std::ostringstream help;
1336  help
1337  << " SUMO uses the World Geodetic System 84 (WGS84/UTM).\n"
1338  << " For a GEO-referenced network, geo coordinates are represented as pairs of Longitude and Latitude\n"
1339  << " in decimal degrees without extra symbols. (N,W..)\n"
1340  << " - Longitude: East-west position of a point on the Earth's surface.\n"
1341  << " - Latitude: North-south position of a point on the Earth's surface.\n"
1342  << " - CheckBox 'geo' enables or disables saving position in GEO coordinates\n";
1343  new FXLabel(helpDialog, help.str().c_str(), 0, GUIDesignLabelFrameInformation);
1344  // "OK"
1345  new FXButton(helpDialog, "OK\t\tclose", GUIIconSubSys::getIcon(ICON_ACCEPT), helpDialog, FXDialogBox::ID_ACCEPT, GUIDesignButtonOK);
1346  helpDialog->create();
1347  helpDialog->show();
1348  return 1;
1349 }
1350 
1351 // ---------------------------------------------------------------------------
1352 // GNEInspectorFrame::TemplateEditor - methods
1353 // ---------------------------------------------------------------------------
1354 
1356  FXGroupBox(inspectorFrameParent->myContentFrame, "Templates", GUIDesignGroupBoxFrame),
1357  myInspectorFrameParent(inspectorFrameParent),
1358  myEdgeTemplate(nullptr) {
1359 
1360  // Create copy template button
1361  myCopyTemplateButton = new FXButton(this, "", 0, this, MID_GNE_INSPECTORFRAME_COPYTEMPLATE, GUIDesignButton);
1362  myCopyTemplateButton->hide();
1363 
1364  // Create set template button
1365  mySetTemplateButton = new FXButton(this, "Set as Template\t\t", 0, this, MID_GNE_INSPECTORFRAME_SETTEMPLATE, GUIDesignButton);
1366  mySetTemplateButton->hide();
1367 }
1368 
1369 
1371  if (myEdgeTemplate) {
1372  // delete template
1373  myEdgeTemplate->decRef("GNEInspectorFrame::~GNEInspectorFrame");
1374  if (myEdgeTemplate->unreferenced()) {
1375  delete myEdgeTemplate;
1376  }
1377  }
1378 }
1379 
1380 
1381 void
1383  if (myInspectorFrameParent->getInspectedACs().front()->getTag() == SUMO_TAG_EDGE) {
1384  // show template editor
1385  show();
1386  // show "Copy Template" (caption supplied via onUpdate)
1387  myCopyTemplateButton->show();
1388  // show "Set As Template"
1389  if (myInspectorFrameParent->getInspectedACs().size() == 1) {
1390  mySetTemplateButton->show();
1391  mySetTemplateButton->setText(("Set edge '" + myInspectorFrameParent->getInspectedACs().front()->getID() + "' as Template").c_str());
1392  }
1393  }
1394 }
1395 
1396 
1397 void
1399  // hide buttons
1400  myCopyTemplateButton->hide();
1401  mySetTemplateButton->hide();
1402  // hide template editor
1403  hide();
1404 }
1405 
1406 
1407 GNEEdge*
1409  return myEdgeTemplate;
1410 }
1411 
1412 
1413 void
1415  if (myEdgeTemplate) {
1416  myEdgeTemplate->decRef("GNEInspectorFrame::setEdgeTemplate");
1417  if (myEdgeTemplate->unreferenced()) {
1418  delete myEdgeTemplate;
1419  }
1420  }
1421  myEdgeTemplate = tpl;
1422  myEdgeTemplate->incRef("GNEInspectorFrame::setEdgeTemplate");
1423 }
1424 
1425 
1426 long
1428  for (auto it : myInspectorFrameParent->getInspectedACs()) {
1429  GNEEdge* edge = dynamic_cast<GNEEdge*>(it);
1430  assert(edge);
1433  }
1434  return 1;
1435 }
1436 
1437 
1438 long
1440  assert(myInspectorFrameParent->getInspectedACs().size() == 1);
1441  GNEEdge* edge = dynamic_cast<GNEEdge*>(myInspectorFrameParent->getInspectedACs().front());
1442  assert(edge);
1443  setEdgeTemplate(edge);
1444  return 1;
1445 }
1446 
1447 
1448 long
1449 GNEInspectorFrame::TemplateEditor::onUpdCopyTemplate(FXObject* sender, FXSelector, void*) {
1450  // declare caption for button
1451  FXString caption;
1452  if (myEdgeTemplate) {
1453  if (myInspectorFrameParent->getInspectedACs().size() == 1) {
1454  caption = ("Copy '" + myEdgeTemplate->getMicrosimID() + "' into edge '" + myInspectorFrameParent->getInspectedACs().front()->getID() + "'").c_str();
1455  } else {
1456  caption = ("Copy '" + myEdgeTemplate->getMicrosimID() + "' into " + toString(myInspectorFrameParent->getInspectedACs().size()) + " selected edges").c_str();
1457  }
1458  sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
1459  } else {
1460  caption = "No edge Template Set";
1461  sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1462  }
1463  sender->handle(this, FXSEL(SEL_COMMAND, FXLabel::ID_SETSTRINGVALUE), (void*)&caption);
1464  return 1;
1465 }
1466 
1467 /****************************************************************************/
void hideGenericParametersEditor()
hide netedit attributes editor
Definition: GNEFrame.cpp:556
long onCmdSetAttribute(FXObject *, FXSelector, void *)
try to set new attribute value
void refreshNeteditAttributesEditor(bool forceRefresh)
refresh netedit attributes
void copyTemplate(GNEEdge *tpl, GNEUndoList *undolist)
copy edge attributes from tpl
Definition: GNEEdge.cpp:800
void showTemplateEditor()
show template editor
FXLabel * myLabelBlockMovement
Label for Check blocked movement.
SumoXMLTag
Numbers representing SUMO-XML - element names.
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:205
static RGBColor parseColor(std::string coldef)
Parses a color information.
Definition: RGBColor.cpp:173
#define GUIDesignCheckButtonAttribute
checkButton without thick extended over the frame used for attributes
Definition: GUIDesigns.h:115
void removeInspectedAC(GNEAttributeCarrier *ac)
remove AC from current inspected ACs
#define GUIDesignButtonAttribute
button extended over over column with thick and raise frame
Definition: GUIDesigns.h:57
GNEInspectorFrame * myInspectorFrameParent
current GNEInspectorFrame parent
FXHorizontalFrame * myHorizontalFrameBlockMovement
horizontal frame for block movement
long onCmdNeteditAttributeHelp(FXObject *, FXSelector, void *)
Called when user press the help button.
void inspectElement(GNEAttributeCarrier *AC)
Inspect a single element.
GNEInspectorFrame * myInspectorFrameParent
pointer to GNEInspectorFrame parent
std::vector< GNEAttributeCarrier * > myInspectedACs
the multi-selection currently being inspected
begin/end of the description of a junction
FXLabel * getFrameHeaderLabel() const
get the label for the frame&#39;s header
Definition: GNEFrame.cpp:772
FXButton * mySetTemplateButton
set template button
AttributesEditor * myAttributesEditor
Attribute editor.
block shape of a graphic element (Used mainly in GNEShapes)
FXTextField * myTextFieldInt
textField to modify the value of int attributes
FXLabel * myLabel
pointer to attribute label
FXHorizontalFrame * myGEOAttributeFrame
horizontal frame for GEOAttribute
bool isCurrentAttributeValid() const
check if current attribute of TextField/ComboBox is valid
void showACHierarchy(GNEAttributeCarrier *AC)
show ACHierarchy
Definition: GNEFrame.cpp:99
#define GUIDesignComboBoxAttribute
Combo box static (cannot be edited) extended over the matrix column.
Definition: GUIDesigns.h:201
void inspectFromDeleteFrame(GNEAttributeCarrier *AC, GNEAttributeCarrier *previousElement, bool previousElementWasMarked)
inspect called from DeleteFrame
void show()
show delete frame
void hideACHierarchy()
hide ACHierarchy
Definition: GNEFrame.cpp:110
static RGBColor getRGBColor(FXColor col)
converts FXColor to RGBColor
Definition: MFXUtils.cpp:108
GNEViewParent * getViewParent() const
get the net object
go back to the previous element
Definition: GUIAppEnum.h:589
FXTextField * myGEOAttributeTextField
textField for GEOAttribute
static int getHigherNumberOfAttributes()
return the number of attributes of the tag with the most highter number of attributes ...
void refreshGEOAttributesEditor(bool forceRefresh)
refresh GEO attributes editor
Close shape of a polygon (Used by GNEPolys)
link,node: the traffic light id responsible for this link
void refreshAttributeInput(const std::string &value, bool forceRefresh)
refresh current attribute input
FXCheckButton * myUseGEOCheckButton
checkBox for use GEO
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:78
GNEFrame::ACHierarchy * myACHierarchy
Attribute Carrier Hierarchy.
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
FXTextField * myTextFieldStrings
textField to modify the value of string attributes
FXHorizontalFrame * myUseGEOFrame
horizontal frame for use GEO
void hideTemplateEditor()
hide template editor
void openHelpAttributesDialog(SumoXMLTag tag) const
Open help attributes dialog.
Definition: GNEFrame.cpp:784
std::vector< GNEAttributeCarrier * > getSelectedAttributeCarriers()
get all selected attribute carriers
Definition: GNENet.cpp:1743
void showNeteditAttributesEditor()
show netedit attributes editor
GNEViewNet * getViewNet() const
get view net
Definition: GNEFrame.cpp:766
long onCmdSetGEOAttribute(FXObject *, FXSelector, void *)
Called when user change the current GEO Attribute.
FXTextField * myTextFieldAdditionalParent
pointer for change additional parent
FXLabel * myLabelCloseShape
Label for close shape.
~GNEInspectorFrame()
Destructor.
GenericParametersEditor * myGenericParametersEditor
Generic parameters editor.
long onCmdSetNeteditAttribute(FXObject *, FXSelector, void *)
Called when user change the current GEO Attribute.
GNEViewNet * myViewNet
View Net for changes.
Definition: GNEFrame.h:232
long onCmdSetTemplate(FXObject *, FXSelector, void *)
set current edge as new template
const std::vector< GNEAttributeCarrier * > & getInspectedACs() const
get current list of inspected ACs
void hide()
hide inspector frame
FXHorizontalFrame * myHorizontalFrameAdditionalParent
horizontal frame for change additional parent
GNEAdditional * retrieveAdditional(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named additional.
Definition: GNENet.cpp:1787
bool myPreviousElementDeleteWasMarked
flag to ckec if myPreviousElementDelete was marked in Delete Frame
FXButton * myHelpButton
button for help
#define GUIDesignButtonIconRectangular
button only with icon (46x23)
Definition: GUIDesigns.h:66
void showGEOAttributesEditor()
show GEO attributes editor
GNEUndoList * getUndoList() const
get the undoList object
FXButton * myColorEditor
Button for open color editor.
void enableAttributeInputElements()
enable attribute input elements
long onCmdOpenAttributeDialog(FXObject *, FXSelector, void *)
open model dialog for more comfortable attribute editing
#define GUIDesignTextField
Definition: GUIDesigns.h:34
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
FXHorizontalFrame * myHorizontalFrameBlockShape
horizontal frame for block shape
FXVerticalFrame * myContentFrame
Vertical frame that holds all widgets of frame.
Definition: GNEFrame.h:235
help button
Definition: GUIAppEnum.h:400
FXCheckButton * myBoolCheckButton
pointer to menu check
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise, the sub-group will be added as a new command into parent group. A matching begin() must have been called previously.
Definition: GNEUndoList.cpp:85
FXButton * myHelpButton
button for help
GNEInspectorFrame * myInspectorFrameParent
current GNEInspectorFrame parent
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames ...
Definition: GUIDesigns.h:258
void disableAttributeInputElements()
disable attribute input elements
FXTextField * myTextFieldReal
textField to modify the value of real/Time attributes
set object as template
Definition: GUIAppEnum.h:585
GNEFrame::ACHierarchy * getACHierarchy() const
get ACHierarchy
virtual bool isAttributeCarrierSelected() const =0
check if attribute carrier is selected
FXButton * myCopyTemplateButton
copy template button
block movement of a graphic element
invalid attribute
attribute edited trought dialog
Definition: GUIAppEnum.h:543
static bool parseStringToANDBool(const std::string &string)
parse a string of booleans (1 0 1 1....) using AND operation
node: the type of traffic light
FXLabel * myLabelAdditionalParent
Label for additional parent.
edge: the shape in xml-definition
long onCmdCopyTemplate(FXObject *, FXSelector, void *)
copy edge attributes from edge template
FXHorizontalFrame * myHorizontalFrameCloseShape
horizontal frame for close shape
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
const std::string getID() const
function to support debugging
void clearInspectedAC()
Clear all current inspected ACs.
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:249
#define GUIDesignLabelFrameInformation
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition: GUIDesigns.h:184
void incRef(const std::string &debugMsg="")
Increarse reference.
Dialog for edit rerouters.
#define GUIDesignButtonRectangular
little button rectangular (46x23) used in frames (For example, in "help" buttons) ...
Definition: GUIDesigns.h:60
FXComboBox * myChoicesCombo
pointer to combo box choices
long onUpdCopyTemplate(FXObject *, FXSelector, void *)
update the copy button with the name of the template
GNEAttributeCarrier * myPreviousElementInspect
pointer to previous element called by Inspector Frame
long onCmdGoBack(FXObject *, FXSelector, void *)
called when user toogle the go back button
FXCheckButton * myCheckBoxBlockShape
pointer to check box "Block Shape"
void showAttributeEditor()
show attributes of ac
void decRef(const std::string &debugMsg="")
Decrease reference.
GNEEdge * myEdgeTemplate
the edge template
void refreshAttributeEditor(bool forceRefreshShape, bool forceRefreshPosition)
refresh attribute editor (only the valid values will be refresh)
begin/end of the description of an edge
void showAttribute(SumoXMLTag ACTag, SumoXMLAttr ACAttribute, const std::string &value)
show attribute of ac
FXCheckButton * myCheckBoxBlockMovement
pointer to check box "Block movement"
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:50
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:46
long onCmdGEOAttributeHelp(FXObject *, FXSelector, void *)
Called when user press the help button.
static std::string replace(std::string str, const char *what, const char *by)
#define GUIDesignButton
Definition: GUIDesigns.h:54
GNEAttributeCarrier * myPreviousElementDelete
pointer to previous element called by Delete Frame
void setACUnderCursor(const GNEAttributeCarrier *AC)
set attributeCarrier under cursor
virtual void show()
show Frame
Definition: GNEFrame.cpp:741
#define GUIDesignDialogBox
Definition: GUIDesigns.h:407
FXButton * myButtonCombinableChoices
pointer to buttonCombinableChoices
An Element which don&#39;t belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:53
#define GUIDesignGroupBoxFrame
Group box design extended over frame.
Definition: GUIDesigns.h:227
std::string stripWhitespaceAfterComma(const std::string &stringValue)
removed invalid spaces of Positions and shapes
const AttributeValues & getAttribute(SumoXMLAttr attr) const
get attribute (throw error if doesn&#39;t exist)
GEOAttributesEditor * myGEOAttributesEditor
GEO Attributes editor.
void showGenericParametersEditor(GNEAttributeCarrier *AC)
show netedit attributes editor (used for edit generic parameters of an existent AC) ...
Definition: GNEFrame.cpp:512
FXLabel * myUseGEOLabel
Label for use GEO.
TemplateEditor * getTemplateEditor() const
get template editor
NeteditAttributesEditor * myNeteditAttributesEditor
Netedit Attributes editor.
GNEInspectorFrame * getInspectorFrameParent() const
get InspectorFrame Parent
TemplateEditor * myTemplateEditor
Template editor.
FXLabel * myLabelBlockShape
Label for Check blocked shape.
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
#define GUIDesignTextFieldInt
text field extended over Frame with thick frame and limited to Integers
Definition: GUIDesigns.h:37
virtual void hide()
hide Frame
Definition: GNEFrame.cpp:750
void setEdgeTemplate(GNEEdge *tpl)
seh the template edge (we assume shared responsibility via reference counting)
GNEDeleteFrame * getDeleteFrame() const
get frame for GNE_MODE_DELETE
void show()
show inspector frame
GNENet * getNet() const
get the net object
#define GUIDesignTextFieldReal
text field extended over Frame with thick frame and limited to Doubles/doubles
Definition: GUIDesigns.h:40
static FXColor getFXColor(const RGBColor &col)
converts FXColor to RGBColor
Definition: MFXUtils.cpp:114
void hideNeteditAttributesEditor()
hide netedit attributes editor
attribute edited
Definition: GUIAppEnum.h:535
FXCheckButton * myCheckBoxCloseShape
pointer to check box "Block movement"
#define GUIDesignButtonOK
Definition: GUIDesigns.h:96
void inspectChild(GNEAttributeCarrier *AC, GNEAttributeCarrier *previousElement)
inspect child of already inspected element
void hideAttributesEditor()
hide attribute editor
FXDEFMAP(GNEInspectorFrame) GNEInspectorFrameMap[]
parent of an additional element
static const TagValues & getTagProperties(SumoXMLTag tag)
get Tag Properties
GNEEdge * getEdgeTemplate() const
get the template edge (to copy attributes from)
void hideGEOAttributesEditor()
hide GEO attributes editor
FXButton * myBackButton
back Button
bool myMultiple
flag to check if input element contains multiple values
void inspectMultisection(const std::vector< GNEAttributeCarrier *> &ACs)
Inspect the given multi-selection.
#define GUIDesignLabelAttribute
label extended over the matrix column with thick frame and height of 23
Definition: GUIDesigns.h:166
FXLabel * myGEOAttributeLabel
Label for GEOAttribute.
std::vector< GNEInspectorFrame::AttributesEditor::AttributeInput * > myVectorOfAttributeInputs
list of Attribute inputs
GNEInspectorFrame * myInspectorFrameParent
pointer to inspector frame parent
static FXIcon * getIcon(GUIIcon which)
returns a icon previously defined in the enum GUIIcon
long onCmdAttributeHelp(FXObject *, FXSelector, void *)
Called when user press the help button.
bool unreferenced()
check if object ins&#39;t referenced
GNEInspectorFrame::AttributesEditor * myAttributesEditorParent
pointer to AttributesEditor parent
FXHorizontalFrame * myHeaderLeftFrame
fame for left header elements
Definition: GNEFrame.h:241
SumoXMLTag getTag() const
get XML Tag assigned to this object