SUMO - Simulation of Urban MObility
GNESelectorFrame.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // The Widget for modifying selections of network-elements
8 // (some elements adapted from GUIDialog_GLChosenEditor)
9 /****************************************************************************/
10 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
11 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
12 /****************************************************************************/
13 //
14 // This file is part of SUMO.
15 // SUMO is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <iostream>
42 
43 #include "GNESelectorFrame.h"
44 #include "GNEViewNet.h"
45 #include "GNEViewParent.h"
46 #include "GNENet.h"
47 #include "GNEJunction.h"
48 #include "GNEEdge.h"
49 #include "GNELane.h"
50 #include "GNEPoly.h"
51 #include "GNEPOI.h"
52 #include "GNEUndoList.h"
53 #include "GNEChange_Selection.h"
54 #include "GNEAttributeCarrier.h"
55 
56 
57 // ===========================================================================
58 // FOX callback mapping
59 // ===========================================================================
60 FXDEFMAP(GNESelectorFrame) GNESelectorFrameMap[] = {
62  FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_ELEMENTS, GNESelectorFrame::onCmdSubset),
63  FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_LOAD, GNESelectorFrame::onCmdLoad),
64  FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_SAVE, GNESelectorFrame::onCmdSave),
65  FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_INVERT, GNESelectorFrame::onCmdInvert),
66  FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_CLEAR, GNESelectorFrame::onCmdClear),
67  FXMAPFUNC(SEL_COMMAND, MID_GNE_SELMB_TAG, GNESelectorFrame::onCmdSelMBTag),
70  FXMAPFUNC(SEL_COMMAND, MID_HELP, GNESelectorFrame::onCmdHelp),
72 };
73 
74 // Object implementation
75 FXIMPLEMENT(GNESelectorFrame, FXVerticalFrame, GNESelectorFrameMap, ARRAYNUMBER(GNESelectorFrameMap))
76 
77 // ===========================================================================
78 // method definitions
79 // ===========================================================================
80 GNESelectorFrame::GNESelectorFrame(FXHorizontalFrame* horizontalFrameParent, GNEViewNet* viewNet):
81  GNEFrame(horizontalFrameParent, viewNet, "Selection"),
82  mySetOperation(SET_ADD),
83  myCurrentTag(SUMO_TAG_NOTHING),
84  myCurrentAttribute(SUMO_ATTR_NOTHING) {
85  // create combo box and label for selected items
86  FXGroupBox* mySelectedItemsComboBox = new FXGroupBox(myContentFrame, "Selected items", GUIDesignGroupBoxFrame);
87  mySelectedItems = new FXLabel(mySelectedItemsComboBox, "", 0, GUIDesignLabelLeft);;
88  // create combo box for selection modification mode
89  FXGroupBox* selBox = new FXGroupBox(myContentFrame, "Modification Mode", GUIDesignGroupBoxFrame);
90  // Create all options buttons
91  myAddRadioButton = new FXRadioButton(selBox, "add\t\tSelected objects are added to the previous selection",
93  myRemoveRadioButton = new FXRadioButton(selBox, "remove\t\tSelected objects are removed from the previous selection",
95  myKeepRadioButton = new FXRadioButton(selBox, "keep\t\tRestrict previous selection by the current selection",
97  myReplaceRadioButton = new FXRadioButton(selBox, "replace\t\tReplace previous selection by the current selection",
99  myAddRadioButton->setCheck(true);
100  // Create groupBox for selection by expression matching (match box)
101  FXGroupBox* elementBox = new FXGroupBox(myContentFrame, "type of element", GUIDesignGroupBoxFrame);
102  // Create MatchTagBox for tags and fill it
103  mySetComboBox = new FXComboBox(elementBox, GUIDesignComboBoxNCol, this, MID_CHOOSEN_ELEMENTS, GUIDesignComboBox);
104  mySetComboBox->appendItem("Net Element");
105  mySetComboBox->appendItem("Additional");
106  mySetComboBox->appendItem("Shape");
107  mySetComboBox->setNumVisible(mySetComboBox->getNumItems());
108  // Create groupBox fro selection by expression matching (match box)
109  FXGroupBox* matchBox = new FXGroupBox(myContentFrame, "Match Attribute", GUIDesignGroupBoxFrame);
110  // Create MatchTagBox for tags
111  myMatchTagComboBox = new FXComboBox(matchBox, GUIDesignComboBoxNCol, this, MID_GNE_SELMB_TAG, GUIDesignComboBox);
112  // Create listBox for Attributes
113  myMatchAttrComboBox = new FXComboBox(matchBox, GUIDesignComboBoxNCol, this, MID_GME_SELMB_ATTRIBUTE, GUIDesignComboBox);
114  // Create TextField for Match string
115  myMatchString = new FXTextField(matchBox, GUIDesignTextFieldNCol, this, MID_GNE_SELMB_STRING, GUIDesignTextField);
116  // Fill list of sub-items
117  onCmdSubset(0, 0, 0);
118  // Set speed of edge as default attribute
119  myCurrentTag = SUMO_TAG_EDGE;
120  myMatchAttrComboBox->setCurrentItem(3);
121  myCurrentAttribute = SUMO_ATTR_SPEED;
122  // Set default value for Match string
123  myMatchString->setText(">10.0");
124  // Create help button
125  new FXButton(matchBox, "Help", 0, this, MID_HELP, GUIDesignButtonRectangular);
126  // Create Groupbox for visual scalings
127  FXGroupBox* selSizeBox = new FXGroupBox(myContentFrame, "Visual Scaling", GUIDesignGroupBoxFrame);
128  // Create spin button and configure it
129  mySelectionScaling = new FXRealSpinDial(selSizeBox, 7, this, MID_GNE_SELECT_SCALE, GUIDesignSpinDial);
130  mySelectionScaling->setNumberFormat(1);
131  mySelectionScaling->setIncrements(0.1, .5, 1);
132  mySelectionScaling->setRange(1, 100);
133  mySelectionScaling->setValue(1);
134  mySelectionScaling->setHelpText("Enlarge selected objects");
135  // Create groupbox for additional buttons
136  FXGroupBox* additionalButtons = new FXGroupBox(myContentFrame, "Operations for selections", GUIDesignGroupBoxFrame);
137  // Create "Clear List" Button
138  new FXButton(additionalButtons, "Clear\t\t", 0, this, MID_CHOOSEN_CLEAR, GUIDesignButton);
139  // Create "Invert" Button
140  new FXButton(additionalButtons, "Invert\t\t", 0, this, MID_CHOOSEN_INVERT, GUIDesignButton);
141  // Create "Save" Button
142  new FXButton(additionalButtons, "Save\t\tSave ids of currently selected objects to a file.", 0, this, MID_CHOOSEN_SAVE, GUIDesignButton);
143  // Create "Load" Button
144  new FXButton(additionalButtons, "Load\t\tLoad ids from a file according to the current modfication mode.", 0, this, MID_CHOOSEN_LOAD, GUIDesignButton);
145  // Create groupbox for information about selections
146  FXGroupBox* selectionHintGroupBox = new FXGroupBox(myContentFrame, "Information", GUIDesignGroupBoxFrame);
147  // Create Selection Hint
148  new FXLabel(selectionHintGroupBox, " - Hold <SHIFT> for \n rectangle selection.\n - Press <DEL> to\n delete selected items.", 0, GUIDesignLabelLeft);
149 }
150 
151 
154 }
155 
156 
157 long
158 GNESelectorFrame::onCmdSelectOperation(FXObject* obj, FXSelector, void*) {
159  if (obj == myAddRadioButton) {
161  myAddRadioButton->setCheck(true);
162  myRemoveRadioButton->setCheck(false);
163  myKeepRadioButton->setCheck(false);
164  myReplaceRadioButton->setCheck(false);
165  return 1;
166  } else if (obj == myRemoveRadioButton) {
168  myAddRadioButton->setCheck(false);
169  myRemoveRadioButton->setCheck(true);
170  myKeepRadioButton->setCheck(false);
171  myReplaceRadioButton->setCheck(false);
172  return 1;
173  } else if (obj == myKeepRadioButton) {
175  myAddRadioButton->setCheck(false);
176  myRemoveRadioButton->setCheck(false);
177  myKeepRadioButton->setCheck(true);
178  myReplaceRadioButton->setCheck(false);
179  return 1;
180  } else if (obj == myReplaceRadioButton) {
182  myAddRadioButton->setCheck(false);
183  myRemoveRadioButton->setCheck(false);
184  myKeepRadioButton->setCheck(false);
185  myReplaceRadioButton->setCheck(true);
186  return 1;
187  } else {
188  return 0;
189  }
190 }
191 
192 
193 long
194 GNESelectorFrame::onCmdSubset(FXObject*, FXSelector, void*) {
195  if (mySetComboBox->getText() == "Net Element") {
196  mySetComboBox->setTextColor(FXRGB(0, 0, 0));
197  myMatchTagComboBox->enable();
198  myMatchAttrComboBox->enable();
199  myMatchString->enable();
200  // Clear items of myMatchTagComboBox
201  myMatchTagComboBox->clearItems();
202  // Set items depending of current items
204  myMatchTagComboBox->appendItem(toString(i).c_str());
205  }
206  myMatchTagComboBox->setCurrentItem(0); // edges
207  myMatchTagComboBox->setNumVisible(myMatchTagComboBox->getNumItems());
208  // Fill attributes with the current element type
209  onCmdSelMBTag(0, 0, 0);
210  } else if (mySetComboBox->getText() == "Additional") {
211  mySetComboBox->setTextColor(FXRGB(0, 0, 0));
212  myMatchTagComboBox->enable();
213  myMatchAttrComboBox->enable();
214  myMatchString->enable();
215  // Clear items of myMatchTagComboBox
216  myMatchTagComboBox->clearItems();
217  // Set items depending of current items
219  myMatchTagComboBox->appendItem(toString(i).c_str());
220  }
221  myMatchTagComboBox->setCurrentItem(0); // edges
222  myMatchTagComboBox->setNumVisible(myMatchTagComboBox->getNumItems());
223  // Fill attributes with the current element type
224  onCmdSelMBTag(0, 0, 0);
225  } else if (mySetComboBox->getText() == "Shape") {
226  mySetComboBox->setTextColor(FXRGB(0, 0, 0));
227  myMatchTagComboBox->enable();
228  myMatchAttrComboBox->enable();
229  myMatchString->enable();
230  // Clear items of myMatchTagComboBox
231  myMatchTagComboBox->clearItems();
232  // Set items depending of current items
233  for (auto i : GNEAttributeCarrier::allowedShapeTags()) {
234  myMatchTagComboBox->appendItem(toString(i).c_str());
235  }
236  myMatchTagComboBox->setCurrentItem(0); // edges
237  myMatchTagComboBox->setNumVisible(myMatchTagComboBox->getNumItems());
238  // Fill attributes with the current element type
239  onCmdSelMBTag(0, 0, 0);
240  } else {
241  mySetComboBox->setTextColor(FXRGB(255, 0, 0));
242  myMatchTagComboBox->disable();
243  myMatchAttrComboBox->disable();
244  myMatchString->disable();
245  }
246  return 1;
247 }
248 
249 
250 long
251 GNESelectorFrame::onCmdLoad(FXObject*, FXSelector, void*) {
252  // get the new file name
253  FXFileDialog opendialog(this, "Open List of Selected Items");
254  opendialog.setIcon(GUIIconSubSys::getIcon(ICON_EMPTY));
255  opendialog.setSelectMode(SELECTFILE_EXISTING);
256  opendialog.setPatternList("Selection files (*.txt)\nAll files (*)");
257  if (gCurrentFolder.length() != 0) {
258  opendialog.setDirectory(gCurrentFolder);
259  }
260  if (opendialog.execute()) {
261  gCurrentFolder = opendialog.getDirectory();
262  std::string file = opendialog.getFilename().text();
263  // @todo maybe rewrite so that mySetOperation also applies to loaded items?
264  std::string errors;
265  std::set<GUIGlID> ids = gSelected.loadIDs(file, errors);
266  handleIDs(std::vector<GUIGlID>(ids.begin(), ids.end()), false);
267  if (errors != "") {
268  // write warning if netedit is running in testing mode
269  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
270  WRITE_WARNING("Opening FXMessageBox 'error loading selection'");
271  }
272  // open message box error
273  FXMessageBox::error(this, MBOX_OK, "Errors while loading Selection", "%s", errors.c_str());
274  // write warning if netedit is running in testing mode
275  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
276  WRITE_WARNING("Closed FXMessageBox 'error loading selection' with 'OK'");
277  }
278  }
279  }
280  myViewNet->update();
281  return 1;
282 }
283 
284 
285 long
286 GNESelectorFrame::onCmdSave(FXObject*, FXSelector, void*) {
287  FXString file = MFXUtils::getFilename2Write(
288  this, "Save List of selected Items", ".txt", GUIIconSubSys::getIcon(ICON_EMPTY), gCurrentFolder);
289  if (file == "") {
290  return 1;
291  }
292  try {
293  gSelected.save(file.text());
294  } catch (IOError& e) {
295  // write warning if netedit is running in testing mode
296  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
297  WRITE_WARNING("Opening FXMessageBox 'error storing selection'");
298  }
299  // open message box error
300  FXMessageBox::error(this, MBOX_OK, "Storing Selection failed", "%s", e.what());
301  // write warning if netedit is running in testing mode
302  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
303  WRITE_WARNING("Closed FXMessageBox 'error storing selection' with 'OK'");
304  }
305  }
306  return 1;
307 }
308 
309 
310 long
311 GNESelectorFrame::onCmdClear(FXObject*, FXSelector, void*) {
312  myViewNet->getUndoList()->p_begin("clear selection");
313  myViewNet->getUndoList()->add(new GNEChange_Selection(myViewNet->getNet(), std::set<GUIGlID>(), gSelected.getSelected(), true), true);
315  myViewNet->update();
316  return 1;
317 }
318 
319 
320 long
321 GNESelectorFrame::onCmdInvert(FXObject*, FXSelector, void*) {
322  // declare a set to keep unselected elements
323  std::set<GUIGlID> unselectedElements;
324  // iterate over all junctions to obtain unselected
325  std::set<GUIGlID> ids = myViewNet->getNet()->getGlIDs(GLO_JUNCTION);
326  for (auto it : ids) {
327  if (gSelected.isSelected(GLO_JUNCTION, it) == false) {
328  unselectedElements.insert(it);
329  }
330 
331  }
332  // iterate over all edges or lanes (Depending of checkbox) to obtain unselected
333  GUIGlObjectType currentEdgeOrLane = myViewNet->selectEdges() ? GLO_EDGE : GLO_LANE;
334  ids = myViewNet->getNet()->getGlIDs(currentEdgeOrLane);
335  for (auto it : ids) {
336  if (gSelected.isSelected(currentEdgeOrLane, it) == false) {
337  unselectedElements.insert(it);
338  }
339 
340  }
341  // iterate over all additionals to obtain unselected
343  for (auto it : ids) {
344  if (gSelected.isSelected(GLO_ADDITIONAL, it) == false) {
345  unselectedElements.insert(it);
346  }
347  }
348  // iterate over all connections to obtain unselected
350  for (auto it : ids) {
351  if (gSelected.isSelected(GLO_CONNECTION, it) == false) {
352  unselectedElements.insert(it);
353  }
354  }
355  // iterate over all crossings to obtain unselected
357  for (auto it : ids) {
358  if (gSelected.isSelected(GLO_CROSSING, it) == false) {
359  unselectedElements.insert(it);
360  }
361  }
362  // iterate over all visible polygons to obtain unselected
363  for (auto it : myViewNet->getNet()->getPolygons().getMyMap()) {
364  GNEPoly* poly = dynamic_cast<GNEPoly*>(it.second);
365  if ((gSelected.isSelected(GLO_CROSSING, poly->getGlID()) == false) && (poly->isShapeVisible())) {
366  unselectedElements.insert(poly->getGlID());
367  }
368  }
369  // iterate over all visible POIs to obtain unselected
370  for (auto it : myViewNet->getNet()->getPOIs().getMyMap()) {
371  GNEPOI* POI = dynamic_cast<GNEPOI*>(it.second);
372  if ((gSelected.isSelected(GLO_CROSSING, POI->getGlID()) == false) && (POI->isShapeVisible())) {
373  unselectedElements.insert(POI->getGlID());
374  }
375  }
376  // invert selection first cleaning current selection and next selecting elements of set "unselectedElements"
377  myViewNet->getUndoList()->p_begin("invert selection");
378  myViewNet->getUndoList()->add(new GNEChange_Selection(myViewNet->getNet(), std::set<GUIGlID>(), gSelected.getSelected(), true), true);
379  myViewNet->getUndoList()->add(new GNEChange_Selection(myViewNet->getNet(), unselectedElements, std::set<GUIGlID>(), true), true);
381  myViewNet->update();
382  return 1;
383 }
384 
385 
386 long
387 GNESelectorFrame::onCmdSelMBTag(FXObject*, FXSelector, void*) {
389  // find current element tag
390  if (mySetComboBox->getText() == "Net Element") {
392  if (toString(i) == myMatchTagComboBox->getText().text()) {
393  myCurrentTag = i;
394  }
395  }
396  } else if (mySetComboBox->getText() == "Additional") {
398  if (toString(i) == myMatchTagComboBox->getText().text()) {
399  myCurrentTag = i;
400  }
401  }
402  } else if (mySetComboBox->getText() == "Shape") {
403  for (auto i : GNEAttributeCarrier::allowedShapeTags()) {
404  if (toString(i) == myMatchTagComboBox->getText().text()) {
405  myCurrentTag = i;
406  }
407  }
408  } else {
409  throw ProcessError("Unkown set");
410  }
411 
412  // check that typed by user value is correct
414  // set color and enable items
415  myMatchTagComboBox->setTextColor(FXRGB(0, 0, 0));
416  myMatchAttrComboBox->enable();
417  myMatchString->enable();
418  myMatchAttrComboBox->clearItems();
420  myMatchAttrComboBox->appendItem(toString(it.first).c_str());
421  }
422  // @ToDo: Here can be placed a butto to set the default value
423  myMatchAttrComboBox->setNumVisible(myMatchAttrComboBox->getNumItems());
424  onCmdSelMBAttribute(0, 0, 0);
425  } else {
426  // change color to red and disable items
427  myMatchTagComboBox->setTextColor(FXRGB(255, 0, 0));
428  myMatchAttrComboBox->disable();
429  myMatchString->disable();
430  }
431  update();
432  return 1;
433 }
434 
435 
436 long
437 GNESelectorFrame::onCmdSelMBAttribute(FXObject*, FXSelector, void*) {
438  const std::vector<std::pair <SumoXMLAttr, std::string> >& attrs = GNEAttributeCarrier::allowedAttributes(myCurrentTag);
440  for (auto i : attrs) {
441  if (toString(i.first) == myMatchAttrComboBox->getText().text()) {
442  myCurrentAttribute = i.first;
443  }
444  }
446  myMatchAttrComboBox->setTextColor(FXRGB(0, 0, 0));
447  myMatchString->enable();
448  } else {
449  myMatchAttrComboBox->setTextColor(FXRGB(255, 0, 0));
450  myMatchString->disable();
451  }
452  return 1;
453 }
454 
455 
456 long
457 GNESelectorFrame::onCmdSelMBString(FXObject*, FXSelector, void*) {
458  std::string expr(myMatchString->getText().text());
459  bool valid = true;
460  if (expr == "") {
461  // the empty expression matches all objects
462  handleIDs(getMatches(myCurrentTag, myCurrentAttribute, '@', 0, expr), false);
464  // The expression must have the form
465  // <val matches if attr < val
466  // >val matches if attr > val
467  // =val matches if attr = val
468  // val matches if attr = val
469  char compOp = expr[0];
470  if (compOp == '<' || compOp == '>' || compOp == '=') {
471  expr = expr.substr(1);
472  } else {
473  compOp = '=';
474  }
475  try {
476  handleIDs(getMatches(myCurrentTag, myCurrentAttribute, compOp, GNEAttributeCarrier::parse<double>(expr.c_str()), expr), false);
477  } catch (EmptyData&) {
478  valid = false;
479  } catch (NumberFormatException&) {
480  valid = false;
481  }
482  } else {
483  // The expression must have the form
484  // =str: matches if <str> is an exact match
485  // !str: matches if <str> is not a substring
486  // ^str: matches if <str> is not an exact match
487  // str: matches if <str> is a substring (sends compOp '@')
488  // Alternatively, if the expression is empty it matches all objects
489  char compOp = expr[0];
490  if (compOp == '=' || compOp == '!' || compOp == '^') {
491  expr = expr.substr(1);
492  } else {
493  compOp = '@';
494  }
495  handleIDs(getMatches(myCurrentTag, myCurrentAttribute, compOp, 0, expr), false);
496  }
497  if (valid) {
498  myMatchString->setTextColor(FXRGB(0, 0, 0));
499  myMatchString->killFocus();
500  } else {
501  myMatchString->setTextColor(FXRGB(255, 0, 0));
502  }
503  return 1;
504 }
505 
506 
507 long
508 GNESelectorFrame::onCmdHelp(FXObject*, FXSelector, void*) {
509  FXDialogBox* helpDialog = new FXDialogBox(this, "Match Attribute Help", GUIDesignDialogBox);
510  std::ostringstream help;
511  help
512  << "The 'Match Attribute' controls allow to specify a set of objects which are then applied to the current selection "
513  << "according to the current 'Modification Mode'.\n"
514  << "1. Select an object type from the first input box\n"
515  << "2. Select an attribute from the second input box\n"
516  << "3. Enter a 'match expression' in the third input box and press <return>\n"
517  << "\n"
518  << "The empty expression matches all objects\n"
519  << "For numerical attributes the match expression must consist of a comparison operator ('<', '>', '=') and a number.\n"
520  << "An object matches if the comparison between its attribute and the given number by the given operator evaluates to 'true'\n"
521  << "\n"
522  << "For string attributes the match expression must consist of a comparison operator ('', '=', '!', '^') and a string.\n"
523  << " '' (no operator) matches if string is a substring of that object'ts attribute.\n"
524  << " '=' matches if string is an exact match.\n"
525  << " '!' matches if string is not a substring.\n"
526  << " '^' matches if string is not an exact match.\n"
527  << "\n"
528  << "Examples:\n"
529  << "junction; id; 'foo' -> match all junctions that have 'foo' in their id\n"
530  << "junction; type; '=priority' -> match all junctions of type 'priority', but not of type 'priority_stop'\n"
531  << "edge; speed; '>10' -> match all edges with a speed above 10\n";
532  new FXLabel(helpDialog, help.str().c_str(), 0, GUIDesignLabelLeft);
533  // "OK"
534  new FXButton(helpDialog, "OK\t\tSave modifications", GUIIconSubSys::getIcon(ICON_ACCEPT), helpDialog, FXDialogBox::ID_ACCEPT, GUIDesignButtonOK);
535  helpDialog->create();
536  helpDialog->show();
537  return 1;
538 }
539 
540 
541 long
542 GNESelectorFrame::onCmdScaleSelection(FXObject*, FXSelector, void*) {
544  myViewNet->update();
545  return 1;
546 }
547 
548 
549 void
551  // selection may have changed due to deletions
552  gSelected.add2Update(this);
554  // Show frame
555  GNEFrame::show();
556 }
557 
558 
559 void
561  // selection may have changed due to deletions
563  // hide frame
564  GNEFrame::hide();
565 }
566 
567 
568 void
570  // show extra information for tests
571  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
572  WRITE_WARNING("Current selection: " +
573  toString(gSelected.getSelected(GLO_JUNCTION).size()) + " Junctions, " +
574  toString(gSelected.getSelected(GLO_EDGE).size()) + " Edges, " +
575  toString(gSelected.getSelected(GLO_LANE).size()) + " Lanes, " +
576  toString(gSelected.getSelected(GLO_CONNECTION).size()) + " connections, " +
577  toString(gSelected.getSelected(GLO_ADDITIONAL).size()) + " Additionals, " +
578  toString(gSelected.getSelected(GLO_CROSSING).size()) + " Crossings, " +
579  toString(gSelected.getSelected(GLO_POLYGON).size()) + " Polygons, " +
580  toString(gSelected.getSelected(GLO_POI).size()) + " POIs");
581  }
582  // update mySelectedItems label
583  std::ostringstream selection;
584  selection
585  << toString(gSelected.getSelected(GLO_JUNCTION).size()) + " Junctions\n"
586  << toString(gSelected.getSelected(GLO_EDGE).size()) + " Edges\n"
587  << toString(gSelected.getSelected(GLO_LANE).size()) + " Lanes\n"
588  << toString(gSelected.getSelected(GLO_CONNECTION).size()) + " Connections\n"
589  << toString(gSelected.getSelected(GLO_ADDITIONAL).size()) + " Additionals\n"
590  << toString(gSelected.getSelected(GLO_CROSSING).size()) + " Crossings\n"
591  << toString(gSelected.getSelected(GLO_POLYGON).size()) + " Polygons\n"
592  << toString(gSelected.getSelected(GLO_POI).size()) + " POIs";
593  mySelectedItems->setText(selection.str().c_str());
594  update();
595 }
596 
597 
598 void
599 GNESelectorFrame::handleIDs(std::vector<GUIGlID> ids, bool selectEdgesEnabled, SetOperation setop) {
600  const SetOperation setOperation = (setop == SET_DEFAULT ? (SetOperation)mySetOperation : setop);
601  std::set<GUIGlID> previousSelection;
602  myViewNet->getUndoList()->p_begin("change selection");
603  if (setOperation == SET_REPLACE) {
604  myViewNet->getUndoList()->add(new GNEChange_Selection(myViewNet->getNet(), std::set<GUIGlID>(), gSelected.getSelected(), true), true);
605  } else if (setOperation == SET_RESTRICT) {
606  previousSelection = gSelected.getSelected(); // have to make a copy
607  myViewNet->getUndoList()->add(new GNEChange_Selection(myViewNet->getNet(), std::set<GUIGlID>(), gSelected.getSelected(), true), true);
608  }
609  // handle ids
610  GUIGlObject* object;
611  GUIGlObjectType type;
612  std::set<GUIGlID> idsSet(ids.begin(), ids.end());
613  std::set<GUIGlID> selected;
614  std::set<GUIGlID> deselected;
615  if (myViewNet->autoSelectNodes()) {
616  for (auto it : ids) {
617  if (it > 0) { // net object?
619  if ((object->getType() == GLO_LANE) && selectEdgesEnabled) {
620  const GNEEdge& edge = (static_cast<GNELane*>(object))->getParentEdge();
621  idsSet.insert(edge.getGNEJunctionSource()->getGlID());
622  idsSet.insert(edge.getGNEJunctionDestiny()->getGlID());
623  }
625  }
626  }
627  }
628  for (auto it : idsSet) {
629  if (it > 0) { // net object?
631  if (object == 0) {
632  // in debug mode we would like to know about this.
633  // It might be caused by a corrupted gl-name stack.
634  // However, most cases of uninitizliaed values would go hidden since 0 is assumed to be the net object anyway
635  assert(false);
636  continue;
637  }
638  type = object->getType();
640  if ((type == GLO_LANE) && selectEdgesEnabled) {
641  // @note edge may be selected/deselected multiple times but this shouldn't
642  // hurt unless we add SET_TOGGLE
643  it = (static_cast<GNELane*>(object))->getParentEdge().getGlID();
644  }
645  // doing the switch outside the loop requires functional techniques. this was deemed to ugly
646  switch (setOperation) {
649  selected.insert(it);
650  break;
652  deselected.insert(it);
653  break;
655  if (previousSelection.count(it)) {
656  selected.insert(it);
657  }
658  break;
659  default:
660  break;
661  }
662  }
663  }
664  myViewNet->getUndoList()->add(new GNEChange_Selection(myViewNet->getNet(), selected, deselected, true), true);
666  myViewNet->update();
667 }
668 
669 
670 std::vector<GUIGlID>
671 GNESelectorFrame::getMatches(SumoXMLTag ACTag, SumoXMLAttr ACAttr, char compOp, double val, const std::string& expr) {
672  GUIGlObject* object;
674  std::vector<GUIGlID> result;
675  const std::set<GUIGlID> allIDs = myViewNet->getNet()->getGlIDs();
676  const bool numerical = GNEAttributeCarrier::isNumerical(ACTag, ACAttr);
677  for (auto it : allIDs) {
679  if (!object) {
680  throw ProcessError("Unkown object passed to GNESelectorFrame::getMatches (id=" + toString(it) + ").");
681  }
682  ac = dynamic_cast<GNEAttributeCarrier*>(object);
683  if (ac && ac->getTag() == ACTag) { // not all objects need to be attribute carriers
684  if (expr == "") {
685  result.push_back(it);
686  } else if (numerical) {
687  double acVal;
688  std::istringstream buf(ac->getAttribute(ACAttr));
689  buf >> acVal;
690  switch (compOp) {
691  case '<':
692  if (acVal < val) {
693  result.push_back(it);
694  }
695  break;
696  case '>':
697  if (acVal > val) {
698  result.push_back(it);
699  }
700  break;
701  case '=':
702  if (acVal == val) {
703  result.push_back(it);
704  }
705  break;
706  }
707  } else {
708  // string match
709  std::string acVal = ac->getAttributeForSelection(ACAttr);
710  switch (compOp) {
711  case '@':
712  if (acVal.find(expr) != std::string::npos) {
713  result.push_back(it);
714  }
715  break;
716  case '!':
717  if (acVal.find(expr) == std::string::npos) {
718  result.push_back(it);
719  }
720  break;
721  case '=':
722  if (acVal == expr) {
723  result.push_back(it);
724  }
725  break;
726  case '^':
727  if (acVal != expr) {
728  result.push_back(it);
729  }
730  break;
731  }
732  }
733  }
735  }
736  return result;
737 }
738 
739 /****************************************************************************/
FXRadioButton * myReplaceRadioButton
replace radio button
a tl-logic
SumoXMLTag
Numbers representing SUMO-XML - element names.
bool selectEdges()
whether inspection, selection and inversion should apply to edges or to lanes
Definition: GNEViewNet.cpp:304
void selectionUpdated()
called if currently registered for updates for changes of global selection
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:197
GNEJunction * getGNEJunctionSource() const
returns the source-junction
Definition: GNEEdge.cpp:194
long onCmdSelMBString(FXObject *, FXSelector, void *)
Called when the user enters a new selection expression.
a polygon
FXComboBox * myMatchAttrComboBox
attributes of the match box
GUIGlObjectType
SetOperation
FOX-declaration.
FXDEFMAP(GNESelectorFrame) GNESelectorFrameMap[]
long onCmdSave(FXObject *, FXSelector, void *)
Called when the user presses the Save-button.
static const std::vector< SumoXMLTag > & allowedShapeTags()
get all editable for tag shape elements
FXLabel * mySelectedItems
label with the list of current selected elements
Definition: GNEPOI.h:52
std::set< GUIGlID > getGlIDs(GUIGlObjectType type=GLO_MAX)
get ids of currently active objects
Definition: GNENet.cpp:1070
a connection
void show()
show Frame
static const std::vector< SumoXMLTag > & allowedNetElementsTags()
get all editable for tag net elements
std::vector< GUIGlID > getMatches(SumoXMLTag ACTag, SumoXMLAttr ACAttr, char compOp, double val, const std::string &expr)
return objects of the given type with matching attrs
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
SumoXMLAttr myCurrentAttribute
current SumoXMLTag Attribute
FXTextField * myMatchString
string of the match
FXRealSpinDial * mySelectionScaling
selection scaling
SumoXMLTag myCurrentTag
current SumoXMLTag tag
void remove2Update()
Removes the dialog to be updated.
bool isSelected(GUIGlObjectType type, GUIGlID id)
Returns the information whether the object with the given type and id is selected.
Deselect selected items.
Definition: GUIAppEnum.h:357
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:54
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:85
long onCmdLoad(FXObject *, FXSelector, void *)
Called when the user presses the Load-button.
FXString gCurrentFolder
The folder used as last.
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
void handleIDs(std::vector< GUIGlID > ids, bool selectEdgesEnabled, SetOperation setop=SET_DEFAULT)
apply list of ids to the current selection according to SetOperation,
Save set.
Definition: GUIAppEnum.h:349
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extension, FXIcon *icon, FXString &currentFolder)
Returns the file name to write.
Definition: MFXUtils.cpp:91
const Polygons & getPolygons() const
Returns all polygons.
static const std::vector< std::pair< SumoXMLAttr, std::string > > & allowedAttributes(SumoXMLTag tag)
get all editable attributes for tag and their default values.
GUIGlID getGlID() const
Returns the numerical id of the object.
long onCmdHelp(FXObject *, FXSelector, void *)
Called when the user clicks the help button.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:65
GNEUndoList * getUndoList() const
get the undoList object
#define GUIDesignComboBox
Definition: GUIDesigns.h:187
GNEViewNet * myViewNet
the window to inform when the tls is modfied
Definition: GNEFrame.h:95
std::set< GUIGlID > loadIDs(const std::string &filename, std::string &msgOut, GUIGlObjectType type=GLO_MAX, int maxErrors=16)
Loads a selection list (optionally with restricted type) and returns the ids of all active objects...
~GNESelectorFrame()
Destructor.
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
long onCmdScaleSelection(FXObject *, FXSelector, void *)
Called when the user changes visual scaling.
long onCmdClear(FXObject *, FXSelector, void *)
Called when the user presses the Clear-button.
selector match box messages
Definition: GUIAppEnum.h:459
const std::set< GUIGlID > & getSelected() const
Returns the set of ids of all selected objects.
#define GUIDesignTextField
Definition: GUIDesigns.h:41
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
SetOperation mySetOperation
how to modify selection
FXdouble getValue() const
Return current value.
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:92
long onCmdSelMBAttribute(FXObject *, FXSelector, void *)
Called when the user selectes a tag in the match box.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
invalid attribute
bool autoSelectNodes()
whether to autoselect nodes or to lanes
Definition: GNEViewNet.cpp:322
const POIs & getPOIs() const
Returns all pois.
virtual std::string getAttributeForSelection(SumoXMLAttr key) const
method for getting the attribute in the context of object selection
FXRadioButton * myKeepRadioButton
keep button
Clear set.
Definition: GUIAppEnum.h:351
#define GUIDesignButtonRectangular
little button rectangular (46x23) used in frames (For example, in "help" buttons) ...
Definition: GUIDesigns.h:63
long onCmdSelectOperation(FXObject *, FXSelector, void *)
set subset of elements
Definition: GUIAppEnum.h:345
begin/end of the description of an edge
void setSelectionScaling(double selectionScale)
set selection scaling
Definition: GNEViewNet.cpp:328
const IDMap & getMyMap() const
Returns a reference to the internal map.
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:58
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:50
compound additional
#define GUIDesignButton
Definition: GUIDesigns.h:57
long onCmdSubset(FXObject *, FXSelector, void *)
Called when the user change the type of element to search (netElement or Additional) ...
virtual void show()
show Frame
Definition: GNEFrame.cpp:98
#define GUIDesignDialogBox
Definition: GUIDesigns.h:393
FXRadioButton * myRemoveRadioButton
remove radio button
static const std::vector< SumoXMLTag > & allowedAdditionalTags()
get all editable for tag additional elements
void add2Update(UpdateTarget *updateTarget)
Adds a dialog to be updated.
#define GUIDesignGroupBoxFrame
Group box design extended over frame.
Definition: GUIDesigns.h:219
Load set.
Definition: GUIAppEnum.h:347
virtual std::string getAttribute(SumoXMLAttr key) const =0
This functions has to be implemented in allGNEAttributeCarrier.
FXComboBox * myMatchTagComboBox
tag of the match box
long onCmdInvert(FXObject *, FXSelector, void *)
Called when the user presses the Invert-button.
an edge
changes the visual scaling of selected items
Definition: GUIAppEnum.h:702
GNENet * getNet() const
get the net object
virtual void hide()
hide Frame
Definition: GNEFrame.cpp:107
#define GUIDesignButtonOK
Definition: GUIDesigns.h:98
SumoXMLTag getTag() const
get XML Tag assigned to this object
bool isShapeVisible() const
check if shape is visible (Was added into view using insertPolygon/POIInView)
Definition: GNEShape.cpp:75
#define GUIDesignSpinDial
Definition: GUIDesigns.h:301
void unblockObject(GUIGlID id)
Marks an object as unblocked.
void hide()
hide Frame
#define GUIDesignLabelLeft
Definition: GUIDesigns.h:144
help button
Definition: GUIAppEnum.h:404
static bool isNumerical(SumoXMLTag tag, SumoXMLAttr attr)
whether an attribute is numerical (int or float)
FXRadioButton * myAddRadioButton
add radio button
Spinner control.
GUIGlObject * getObjectBlocking(GUIGlID id)
Returns the object from the container locking it.
#define GUIDesignRadioButton
Definition: GUIDesigns.h:134
long onCmdSelMBTag(FXObject *, FXSelector, void *)
Called when the user selectes a tag in the match box.
FXComboBox * mySetComboBox
tag of the sets of elements
GUISelectedStorage gSelected
A global holder of selected objects.
static FXIcon * getIcon(GUIIcon which)
returns a icon previously defined in the enum GUIIcon
set type of selection
Definition: GUIAppEnum.h:343
void save(GUIGlObjectType type, const std::string &filename)
Saves a selection list.
a junction
GNEJunction * getGNEJunctionDestiny() const
returns the destination-junction
Definition: GNEEdge.cpp:200