Eclipse SUMO - Simulation of Urban MObility
GNESelectorFrame.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // The Widget for modifying selections of network-elements
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <netedit/GNENet.h>
23 #include <netedit/GNEUndoList.h>
24 #include <netedit/GNEViewNet.h>
32 #include <utils/xml/NamespaceIDs.h>
33 
34 #include "GNESelectorFrame.h"
35 #include "GNEElementSet.h"
36 
37 
38 // ===========================================================================
39 // FOX callback mapping
40 // ===========================================================================
41 FXDEFMAP(GNESelectorFrame::ModificationMode) ModificationModeMap[] = {
43 };
44 
47 };
48 
49 FXDEFMAP(GNESelectorFrame::SelectionOperation) SelectionOperationMap[] = {
56 };
57 
58 FXDEFMAP(GNESelectorFrame::SelectionHierarchy) SelectionHierarchyMap[] = {
62 };
63 
64 // Object implementation
65 FXIMPLEMENT(GNESelectorFrame::ModificationMode, MFXGroupBoxModule, ModificationModeMap, ARRAYNUMBER(ModificationModeMap))
66 FXIMPLEMENT(GNESelectorFrame::VisualScaling, MFXGroupBoxModule, VisualScalingMap, ARRAYNUMBER(VisualScalingMap))
67 FXIMPLEMENT(GNESelectorFrame::SelectionOperation, MFXGroupBoxModule, SelectionOperationMap, ARRAYNUMBER(SelectionOperationMap))
68 FXIMPLEMENT(GNESelectorFrame::SelectionHierarchy, MFXGroupBoxModule, SelectionHierarchyMap, ARRAYNUMBER(SelectionHierarchyMap))
69 
70 // ===========================================================================
71 // method definitions
72 // ===========================================================================
73 
74 // ---------------------------------------------------------------------------
75 // ModificationMode::SelectionInformation - methods
76 // ---------------------------------------------------------------------------
77 
79  MFXGroupBoxModule(selectorFrameParent, TL("Selection information")),
80  mySelectorFrameParent(selectorFrameParent) {
81  // information label
82  myInformationLabel = new FXLabel(getCollapsableFrame(), "", nullptr, GUIDesignLabelFrameInformation);
83 }
84 
85 
87 
88 
89 void
91  // first clear information
92  myInformation.clear();
93  // get attribute carriers
94  const auto ACs = mySelectorFrameParent->getViewNet()->getNet()->getAttributeCarriers();
95  // continue depending of supermode
96  if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeNetwork()) {
97  updateInformationLabel(TL("Junctions"), ACs->getNumberOfSelectedJunctions());
98  updateInformationLabel(TL("Edges"), ACs->getNumberOfSelectedEdges());
99  updateInformationLabel(TL("Lanes"), ACs->getNumberOfSelectedLanes());
100  updateInformationLabel(TL("Connections"), ACs->getNumberOfSelectedConnections());
101  updateInformationLabel(TL("Crossings"), ACs->getNumberOfSelectedCrossings());
102  updateInformationLabel(TL("WalkingAreas"), ACs->getNumberOfSelectedWalkingAreas());
103  updateInformationLabel(TL("Additionals"), ACs->getNumberOfSelectedPureAdditionals());
104  updateInformationLabel(TL("Wires"), ACs->getNumberOfSelectedWires());
105  updateInformationLabel(TL("TAZs"), ACs->getNumberOfSelectedTAZs());
106  updateInformationLabel(TL("TAZSources"), ACs->getNumberOfSelectedTAZSources());
107  updateInformationLabel(TL("TAZSinks"), ACs->getNumberOfSelectedTAZSinks());
108  updateInformationLabel(TL("Polygons"), ACs->getNumberOfSelectedPolygons());
109  updateInformationLabel(TL("POIs"), ACs->getNumberOfSelectedPOIs());
110  updateInformationLabel(TL("JuPedSim elements"),
111  ACs->getNumberOfSelectedJpsWalkableAreas() +
112  ACs->getNumberOfSelectedJpsObstacles());
113  } else if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
114  updateInformationLabel(TL("Routes"), ACs->getNumberOfSelectedRoutes());
115  updateInformationLabel(TL("Vehicles"), ACs->getNumberOfSelectedVehicles());
116  updateInformationLabel(TL("Persons"), ACs->getNumberOfSelectedPersons());
117  updateInformationLabel(TL("Person trips"), ACs->getNumberOfSelectedPersonTrips());
118  updateInformationLabel(TL("Walks"), ACs->getNumberOfSelectedWalks());
119  updateInformationLabel(TL("Rides"), ACs->getNumberOfSelectedRides());
120  updateInformationLabel(TL("Containers"), ACs->getNumberOfSelectedContainers());
121  updateInformationLabel(TL("Transport"), ACs->getNumberOfSelectedTransport());
122  updateInformationLabel(TL("Tranships"), ACs->getNumberOfSelectedTranships());
123  updateInformationLabel(TL("Stops"), ACs->getNumberOfSelectedStops());
124  } else if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeData()) {
125  updateInformationLabel(TL("EdgeDatas"), ACs->getNumberOfSelectedEdgeDatas());
126  updateInformationLabel(TL("EdgeRelDatas"), ACs->getNumberOfSelectedEdgeRelDatas());
127  updateInformationLabel(TL("EdgeTAZRel"), ACs->getNumberOfSelectedEdgeTAZRel());
128  }
129  // adjust format
130  const auto numberLines = std::count(myInformation.begin(), myInformation.end(), ':');
131  if (numberLines == 0) {
132  myInformation.append(" \n \n");
133  } else if (numberLines > 1) {
134  myInformation.pop_back();
135  }
136  // set label
137  myInformationLabel->setText(myInformation.c_str());
138 }
139 
140 
141 void
142 GNESelectorFrame::SelectionInformation::updateInformationLabel(const std::string& element, int number) {
143  // check number
144  if (number > 0) {
145  myInformation.append(element + ": " + toString(number) + "\n");
146  }
147 }
148 
149 // ---------------------------------------------------------------------------
150 // ModificationMode::ModificationMode - methods
151 // ---------------------------------------------------------------------------
152 
154  MFXGroupBoxModule(selectorFrameParent, TL("Modification Mode")),
155  myModificationModeType(Operation::ADD) {
156  // Create all options buttons
157  myAddRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("add"), "", TL("Selected objects are added to the previous selection"),
159  myRemoveRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("remove"), "", TL("Selected objects are removed from the previous selection"),
161  myKeepRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("keep"), "", TL("Restrict previous selection by the current selection"),
163  myReplaceRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("replace"), "", TL("Replace previous selection by the current selection"),
165  myAddRadioButton->setCheck(true);
166 }
167 
168 
170 
171 
174  return myModificationModeType;
175 }
176 
177 
178 long
180  if (obj == myAddRadioButton) {
181  myModificationModeType = Operation::ADD;
182  myAddRadioButton->setCheck(true);
183  myRemoveRadioButton->setCheck(false);
184  myKeepRadioButton->setCheck(false);
185  myReplaceRadioButton->setCheck(false);
186  return 1;
187  } else if (obj == myRemoveRadioButton) {
188  myModificationModeType = Operation::SUB;
189  myAddRadioButton->setCheck(false);
190  myRemoveRadioButton->setCheck(true);
191  myKeepRadioButton->setCheck(false);
192  myReplaceRadioButton->setCheck(false);
193  return 1;
194  } else if (obj == myKeepRadioButton) {
195  myModificationModeType = Operation::RESTRICT;
196  myAddRadioButton->setCheck(false);
197  myRemoveRadioButton->setCheck(false);
198  myKeepRadioButton->setCheck(true);
199  myReplaceRadioButton->setCheck(false);
200  return 1;
201  } else if (obj == myReplaceRadioButton) {
202  myModificationModeType = Operation::REPLACE;
203  myAddRadioButton->setCheck(false);
204  myRemoveRadioButton->setCheck(false);
205  myKeepRadioButton->setCheck(false);
206  myReplaceRadioButton->setCheck(true);
207  return 1;
208  } else {
209  return 0;
210  }
211 }
212 
213 // ---------------------------------------------------------------------------
214 // ModificationMode::VisualScaling - methods
215 // ---------------------------------------------------------------------------
216 
218  MFXGroupBoxModule(selectorFrameParent, TL("Visual Scaling")),
219  mySelectorFrameParent(selectorFrameParent) {
220  // Create spin button and configure it
222  //mySelectionScaling->setNumberFormat(1);
223  //mySelectionScaling->setIncrements(0.1, .5, 1);
224  mySelectionScaling->setIncrement(0.5);
225  mySelectionScaling->setRange(1, 100000);
226  mySelectionScaling->setValue(1);
227  mySelectionScaling->setHelpText(TL("Enlarge selected objects"));
228 }
229 
230 
232 
233 
234 long
236  // set scale in viewnet
237  mySelectorFrameParent->myViewNet->setSelectorFrameScale(mySelectionScaling->getValue());
238  mySelectorFrameParent->myViewNet->updateViewNet();
239  return 1;
240 }
241 
242 // ---------------------------------------------------------------------------
243 // ModificationMode::SelectionHierarchy - methods
244 // ---------------------------------------------------------------------------
245 
247  MFXGroupBoxModule(selectorFrameParent, TL("Selection operations")),
248  mySelectorFrameParent(selectorFrameParent) {
249  // tabular buttons, see GNETLSEditorFrame
250 
251  FXHorizontalFrame* selectionButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
252  FXVerticalFrame* col1 = new FXVerticalFrame(selectionButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // left button columm
253  FXVerticalFrame* col2 = new FXVerticalFrame(selectionButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // right button column
254 
255  // Create "Clear List" Button
256  GUIDesigns::buildFXButton(col1, TL("Clear"), "", TL("Deselect all objects (hotkey: ESC)"), nullptr, this, MID_CHOOSEN_CLEAR, GUIDesignButton);
257  // Create "Invert" Button
258  GUIDesigns::buildFXButton(col2, TL("Invert"), "", TL("Invert selection status of all objects"), nullptr, this, MID_CHOOSEN_INVERT, GUIDesignButton);
259  // Create "Save" Button
260  GUIDesigns::buildFXButton(col1, TL("Save"), "", TL("Save ids of currently selected objects to a file."), nullptr, this, MID_CHOOSEN_SAVE, GUIDesignButton);
261  // Create "Load" Button
262  GUIDesigns::buildFXButton(col2, TL("Load"), "", TL("Load ids from a file according to the current modification mode."), nullptr, this, MID_CHOOSEN_LOAD, GUIDesignButton);
263  // Create "Delete" Button
264  GUIDesigns::buildFXButton(col1, TL("Delete"), "", TL("Delete all selected objects (hotkey: DEL)"), nullptr, this, MID_CHOOSEN_DELETE, GUIDesignButton);
265  // Create "reduce" Button
266  GUIDesigns::buildFXButton(col2, TL("Reduce"), "", TL("Reduce network to current selection."), nullptr, this, MID_CHOOSEN_REDUCE, GUIDesignButton);
267 }
268 
269 
271 
272 
273 void
275  std::vector<GNEAttributeCarrier*> loadedACs;
276  std::ifstream strm(file.c_str());
277  // check if file can be opened
278  if (!strm.good()) {
279  WRITE_ERRORF(TL("Could not open '%'."), file);
280  } else {
281  // convert all glObjects into GNEAttributeCarriers
282  std::map<const std::string, GNEAttributeCarrier*> GLFUllNameAC;
283  const auto GLObjects = GUIGlObjectStorage::gIDStorage.getAllGLObjects();
284  for (const auto& GLObject : GLObjects) {
285  // try to parse GLObject to AC
286  GNEAttributeCarrier* AC = dynamic_cast<GNEAttributeCarrier*>(GLObject);
287  // if was successfully parsed and is NOT a template, add into GLFUllNameAC using fullName
288  if (AC && !AC->isTemplate()) {
289  GLFUllNameAC[GUIGlObject::TypeNames.getString(GLObject->getType()) + ":" + AC->getID()] = AC;
290  }
291  }
292  // continue while stream exist
293  while (strm.good()) {
294  std::string line;
295  strm >> line;
296  // check if line isn't empty
297  if (line.length() != 0) {
298  // obtain AC from GLFUllNameAC
299  if (StringUtils::startsWith(line, "node:")) {
300  line = StringUtils::replace(line, "node:", "junction:");
301  }
302  GNEAttributeCarrier* AC = GLFUllNameAC.count(line) > 0 ? GLFUllNameAC.at(line) : nullptr;
303  // check if AC exist, is selectable, and isn't locked
304  if (AC && AC->getTagProperty().isSelectable() && !mySelectorFrameParent->getViewNet()->getLockManager().isObjectLocked(AC->getGUIGlObject()->getType(), false)) {
305  // now check if we're in the correct supermode to load this element
306  if (((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeNetwork()) && !AC->getTagProperty().isDemandElement()) ||
307  ((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeDemand()) && AC->getTagProperty().isDemandElement()) ||
308  ((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeData()) && AC->getTagProperty().isDataElement())) {
309  loadedACs.push_back(AC);
310  }
311  }
312  }
313  }
314  // change selected attribute in loaded ACs allowing undo/redo
315  if (loadedACs.size() > 0) {
316  mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("load selection"));
317  mySelectorFrameParent->handleIDs(loadedACs);
318  mySelectorFrameParent->myViewNet->getUndoList()->end();
319  }
320  mySelectorFrameParent->myViewNet->updateViewNet();
321  }
322 }
323 
324 
325 long
326 GNESelectorFrame::SelectionOperation::onCmdLoad(FXObject*, FXSelector, void*) {
327  // get the new file name
328  FXFileDialog opendialog(getCollapsableFrame(), TL("Open List of Selected Items"));
329  opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN));
330  opendialog.setSelectMode(SELECTFILE_EXISTING);
331  opendialog.setPatternList("Selection files (*.txt)\nAll files (*)");
332  if (gCurrentFolder.length() != 0) {
333  opendialog.setDirectory(gCurrentFolder);
334  }
335  if (opendialog.execute()) {
336  gCurrentFolder = opendialog.getDirectory();
337  loadFromFile(opendialog.getFilename().text());
338  }
339  return 1;
340 }
341 
342 
343 long
344 GNESelectorFrame::SelectionOperation::onCmdSave(FXObject*, FXSelector, void*) {
345  FXString file = MFXUtils::getFilename2Write(this,
346  TL("Save List of selected Items"), ".txt",
348  if (file == "") {
349  return 1;
350  }
351  try {
352  OutputDevice& dev = OutputDevice::getDevice(file.text());
353  // get selected attribute carriers
354  const auto selectedACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(false);
355  for (const auto& selectedAC : selectedACs) {
356  GUIGlObject* object = dynamic_cast<GUIGlObject*>(selectedAC);
357  if (object) {
358  dev << GUIGlObject::TypeNames.getString(object->getType()) << ":" << selectedAC->getID() << "\n";
359  }
360  }
361  dev.close();
362  } catch (IOError& e) {
363  // write warning if netedit is running in testing mode
364  WRITE_DEBUG("Opening FXMessageBox 'error storing selection'");
365  // open message box error
366  FXMessageBox::error(getCollapsableFrame(), MBOX_OK, "Storing Selection failed", "%s", e.what());
367  // write warning if netedit is running in testing mode
368  WRITE_DEBUG("Closed FXMessageBox 'error storing selection' with 'OK'");
369  }
370  return 1;
371 }
372 
373 
374 long
376  // obtain undoList (only for improve code legibly)
377  GNEUndoList* undoList = mySelectorFrameParent->myViewNet->getUndoList();
378  // get element to select/unselect depending of current supermode
379  std::pair<std::vector<std::pair<bool, GNEAttributeCarrier*> >, std::vector<std::pair<bool, GNEAttributeCarrier*> > > ACsToSelectUnselect;
380  if (mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeNetwork()) {
381  ACsToSelectUnselect = processMassiveNetworkElementSelection(false);
382  } else if (mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeDemand()) {
383  ACsToSelectUnselect = processMassiveDemandElementSelection();
384  } else if (mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeData()) {
385  ACsToSelectUnselect = processMassiveDataElementSelection();
386  }
387  // only continue if there are elements to unselect
388  if (ACsToSelectUnselect.second.size() > 0) {
389  // check if add locked elements
390  bool askedContinueIfLock = false;
391  bool addLockedElements = false;
392  bool unlockedElements = false;
393  for (const auto& AC : ACsToSelectUnselect.second) {
394  if (AC.first == false) {
395  // there are unlocked elements
396  unlockedElements = true;
397  } else if (!askedContinueIfLock) {
398  addLockedElements = askContinueIfLock();
399  // only ask one time for locking
400  askedContinueIfLock = true;
401  }
402  }
403  if (unlockedElements || addLockedElements) {
404  mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("clear selection"));
405  for (const auto& AC : ACsToSelectUnselect.second) {
406  if (addLockedElements || !AC.first) {
407  AC.second->setAttribute(GNE_ATTR_SELECTED, "false", undoList);
408  }
409  }
410  mySelectorFrameParent->myViewNet->getUndoList()->end();
411  }
412  }
413  return 1;
414 }
415 
416 long
418  // acts like the 'del' hotkey
419  mySelectorFrameParent->getViewNet()->hotkeyDel();
420  return 1;
421 }
422 
423 
424 long
426  // obtain undoList (only for improve code legibly)
427  GNEUndoList* undoList = mySelectorFrameParent->myViewNet->getUndoList();
428  // get element to select/unselect depending of current supermode
429  std::pair<std::vector<std::pair<bool, GNEAttributeCarrier*> >, std::vector<std::pair<bool, GNEAttributeCarrier*> > > ACsToSelectUnselect;
430  if (mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeNetwork()) {
431  ACsToSelectUnselect = processMassiveNetworkElementSelection(true);
432  } else if (mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeDemand()) {
433  ACsToSelectUnselect = processMassiveDemandElementSelection();
434  } else if (mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeData()) {
435  ACsToSelectUnselect = processMassiveDataElementSelection();
436  }
437  // only continue if there are elements to select and unselect
438  if ((ACsToSelectUnselect.first.size() + ACsToSelectUnselect.second.size()) > 0) {
439  // check if add locked elements
440  bool askedContinueIfLock = false;
441  bool addLockedElements = false;
442  bool unlockedElements = false;
443  for (const auto& AC : ACsToSelectUnselect.first) {
444  if (AC.first == false) {
445  // there are unlocked elements
446  unlockedElements = true;
447  } else if (!askedContinueIfLock) {
448  addLockedElements = askContinueIfLock();
449  // only ask one time for locking
450  askedContinueIfLock = true;
451  }
452  }
453  for (const auto& AC : ACsToSelectUnselect.second) {
454  if (AC.first == false) {
455  // there are unlocked elements
456  unlockedElements = true;
457  } else if (!askedContinueIfLock) {
458  addLockedElements = askContinueIfLock();
459  // only ask one time for locking
460  askedContinueIfLock = true;
461  }
462  }
463  if (unlockedElements || addLockedElements) {
464  mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("invert selection"));
465  for (const auto& AC : ACsToSelectUnselect.first) {
466  if (addLockedElements || !AC.first) {
467  AC.second->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
468  }
469  }
470  for (const auto& AC : ACsToSelectUnselect.second) {
471  if (addLockedElements || !AC.first) {
472  AC.second->setAttribute(GNE_ATTR_SELECTED, "false", undoList);
473  }
474  }
475  mySelectorFrameParent->myViewNet->getUndoList()->end();
476  }
477  }
478  return 1;
479 }
480 
481 
482 long
484  // begin undoList operation
485  mySelectorFrameParent->getViewNet()->getUndoList()->begin(Supermode::NETWORK, GUIIcon::SIMPLIFYNETWORK, TL("reduce network"));
486  // invert and clear
487  onCmdInvert(0, 0, 0);
488  onCmdDelete(0, 0, 0);
489  // end undoList operation
490  mySelectorFrameParent->getViewNet()->getUndoList()->end();
491  return 1;
492 }
493 
494 
495 std::pair<std::vector<std::pair<bool, GNEAttributeCarrier*> >, std::vector<std::pair<bool, GNEAttributeCarrier*> > >
497  // get attribute carriers (only for improve code legibly)
498  const auto& ACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers();
499  // extract all network elements
500  std::vector<GNEAttributeCarrier*> networkACs;
501  // add junctions
502  for (const auto& junction : ACs->getJunctions()) {
503  networkACs.push_back(junction.second);
504  // due we iterate over all junctions, only it's necessary iterate over incoming edges
505  for (const auto& incomingEdge : junction.second->getGNEIncomingEdges()) {
506  if (!filterLanes || mySelectorFrameParent->getViewNet()->getNetworkViewOptions().selectEdges()) {
507  networkACs.push_back(incomingEdge);
508  }
509  // add lanes
510  if (!filterLanes || !mySelectorFrameParent->getViewNet()->getNetworkViewOptions().selectEdges()) {
511  for (const auto& lane : incomingEdge->getLanes()) {
512  networkACs.push_back(lane);
513  }
514  }
515  // add connections
516  for (const auto& connection : incomingEdge->getGNEConnections()) {
517  networkACs.push_back(connection);
518  }
519  }
520  // add crossings
521  for (const auto& crossing : junction.second->getGNECrossings()) {
522  networkACs.push_back(crossing);
523  }
524  // add walkingArea
525  for (const auto& walkingArea : junction.second->getGNEWalkingAreas()) {
526  networkACs.push_back(walkingArea);
527  }
528  }
529  // add additionals
530  for (const auto& additionalTags : ACs->getAdditionals()) {
531  for (const auto& additional : additionalTags.second) {
532  if (additional.second->getTagProperty().isSelectable()) {
533  networkACs.push_back(additional.second);
534  }
535  }
536  }
537  // declare set of checked GLTypes to avoid unnecessary calls to isGLObjectLocked()
538  std::map<GUIGlObjectType, bool> checkedTypes;
539  // declare vector in which save ACs to select and unselect
540  std::pair<std::vector<std::pair<bool, GNEAttributeCarrier*> >, std::vector<std::pair<bool, GNEAttributeCarrier*> > > ACsToSelectUnselect;
541  // iterate over network ACs
542  for (const auto& networkAC : networkACs) {
543  const auto networkACObjectType = networkAC->getGUIGlObject()->getType();
544  // save locking status in checkedTypes
545  if (checkedTypes.find(networkACObjectType) == checkedTypes.end()) {
546  checkedTypes[networkACObjectType] = networkAC->getGUIGlObject()->isGLObjectLocked();
547  }
548  // save element and their locking status
549  if (networkAC->isAttributeCarrierSelected()) {
550  ACsToSelectUnselect.second.push_back(std::make_pair(checkedTypes.at(networkACObjectType), networkAC));
551  } else {
552  ACsToSelectUnselect.first.push_back(std::make_pair(checkedTypes.at(networkACObjectType), networkAC));
553  }
554  }
555  return ACsToSelectUnselect;
556 }
557 
558 
559 std::pair<std::vector<std::pair<bool, GNEAttributeCarrier*> >, std::vector<std::pair<bool, GNEAttributeCarrier*> > >
561  // declare set of checked GLTypes to avoid unnecessary calls to isGLObjectLocked()
562  std::map<GUIGlObjectType, bool> checkedTypes;
563  // declare vector in which save ACs to select and unselect
564  std::pair<std::vector<std::pair<bool, GNEAttributeCarrier*> >, std::vector<std::pair<bool, GNEAttributeCarrier*> > > ACsToSelectUnselect;
565  // iterate over selectable demand elements
566  for (const auto& demandElementTag : mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers()->getDemandElements()) {
567  for (const auto& demandElement : demandElementTag.second) {
568  if (demandElement.second->getTagProperty().isSelectable()) {
569  const auto networkACObjectType = demandElement.first->getType();
570  // save locking status in checkedTypes
571  if (checkedTypes.find(networkACObjectType) == checkedTypes.end()) {
572  checkedTypes[networkACObjectType] = demandElement.first->isGLObjectLocked();
573  }
574  // save element and their locking status
575  if (demandElement.second->isAttributeCarrierSelected()) {
576  ACsToSelectUnselect.second.push_back(std::make_pair(checkedTypes.at(networkACObjectType), demandElement.second));
577  } else {
578  ACsToSelectUnselect.first.push_back(std::make_pair(checkedTypes.at(networkACObjectType), demandElement.second));
579  }
580  }
581  }
582  }
583  return ACsToSelectUnselect;
584 }
585 
586 
587 std::pair<std::vector<std::pair<bool, GNEAttributeCarrier*> >, std::vector<std::pair<bool, GNEAttributeCarrier*> > >
589  // declare set of checked GLTypes to avoid unnecessary calls to isGLObjectLocked()
590  std::map<GUIGlObjectType, bool> checkedTypes;
591  // declare vector in which save ACs to select and unselect
592  std::pair<std::vector<std::pair<bool, GNEAttributeCarrier*> >, std::vector<std::pair<bool, GNEAttributeCarrier*> > > ACsToSelectUnselect;
593  // iterate over selectable demand elements
594  for (const auto& genericDataTag : mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers()->getGenericDatas()) {
595  for (const auto& genericData : genericDataTag.second) {
596  if (genericData.second->getTagProperty().isSelectable()) {
597  const auto networkACObjectType = genericData.first->getType();
598  // save locking status in checkedTypes
599  if (checkedTypes.find(networkACObjectType) == checkedTypes.end()) {
600  checkedTypes[networkACObjectType] = genericData.first->isGLObjectLocked();
601  }
602  // save element and their locking status
603  if (genericData.second->isAttributeCarrierSelected()) {
604  ACsToSelectUnselect.second.push_back(std::make_pair(checkedTypes.at(networkACObjectType), genericData.second));
605  } else {
606  ACsToSelectUnselect.first.push_back(std::make_pair(checkedTypes.at(networkACObjectType), genericData.second));
607  }
608  }
609  }
610  }
611  return ACsToSelectUnselect;
612 }
613 
614 
615 bool
617  WRITE_DEBUG("Opening FXMessageBox 'confirm selection operation'");
618  // open question box
619  const FXuint answer = FXMessageBox::question(mySelectorFrameParent->getViewNet()->getApp(),
620  MBOX_YES_NO, "Confirm selection operation", "There are locked elements in the current selection.\nApply operation to locked elements?");
621  if (answer != 1) { //1:yes, 2:no, 4:esc
622  // write warning if netedit is running in testing mode
623  if (answer == 2) {
624  WRITE_DEBUG("Closed FXMessageBox 'confirm selection operation' with 'No'");
625  } else if (answer == 4) {
626  WRITE_DEBUG("Closed FXMessageBox 'confirm selection operation' with 'ESC'");
627  }
628  return false;
629  } else {
630  // write warning if netedit is running in testing mode
631  WRITE_DEBUG("Closed FXMessageBox 'confirm selection operation' with 'Yes'");
632  return true;
633  }
634 }
635 
636 // ---------------------------------------------------------------------------
637 // ModificationMode::SelectionHierarchy - methods
638 // ---------------------------------------------------------------------------
639 
641  MFXGroupBoxModule(selectorFrameParent, TL("Hierarchy operations")),
642  mySelectorFrameParent(selectorFrameParent),
643  myCurrentSelectedParent(Selection::ALL),
644  myCurrentSelectedChild(Selection::ALL) {
645  // create label for parents
646  new FXLabel(getCollapsableFrame(), TL("Select parents"), nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL));
647  // Create MFXComboBoxIcon for parent comboBox
650  // create parent buttons
651  FXHorizontalFrame* parentButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
652  // Create "select" Button
654  // Create "unselect" Button
656  // create label for parents
657  new FXLabel(getCollapsableFrame(), TL("Select children"), nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL));
658  // Create MFXComboBoxIcon for parent comboBox
661  // create children buttons
662  FXHorizontalFrame* childrenButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
663  // Create "select" Button
665  // Create "unselect" Button
667  // fill comboBoxes
668  for (const auto& item : myItems) {
669  myParentsComboBox->appendIconItem(item.second.c_str());
670  myChildrenComboBox->appendIconItem(item.second.c_str());
671  }
672 }
673 
674 
676 
677 
678 long
679 GNESelectorFrame::SelectionHierarchy::onCmdSelectItem(FXObject* obj, FXSelector, void*) {
680  if (obj == myParentsComboBox) {
681  for (const auto& item : myItems) {
682  if (item.second == myParentsComboBox->getText().text()) {
683  // enable buttons
684  mySelectParentsButton->enable();
685  myUnselectParentsButton->enable();
686  // change text color
687  myParentsComboBox->setTextColor(FXRGB(0, 0, 0));
688  // set current selected parent
689  myCurrentSelectedParent = item.first;
690  return 1;
691  }
692  }
693  // item not found
694  myCurrentSelectedParent = Selection::NOTHING;
695  // disable buttons
696  mySelectParentsButton->disable();
697  myUnselectParentsButton->disable();
698  myParentsComboBox->setTextColor(FXRGB(255, 0, 0));
699  return 1;
700  } else if (obj == myChildrenComboBox) {
701  for (const auto& item : myItems) {
702  if (item.second == myChildrenComboBox->getText().text()) {
703  // enable buttons
704  mySelectChildrenButton->enable();
705  myUnselectChildrenButton->enable();
706  // change text color
707  myChildrenComboBox->setTextColor(FXRGB(0, 0, 0));
708  // set current selected parent
709  myCurrentSelectedChild = item.first;
710  return 1;
711  }
712  }
713  // item not found
714  myCurrentSelectedChild = Selection::NOTHING;
715  // disable buttons
716  mySelectChildrenButton->disable();
717  myUnselectChildrenButton->disable();
718  myChildrenComboBox->setTextColor(FXRGB(255, 0, 0));
719  return 1;
720  }
721  return 0;
722 }
723 
724 
725 long
726 GNESelectorFrame::SelectionHierarchy::onCmdParents(FXObject* obj, FXSelector, void*) {
727  // get selected elements
728  const auto selectedACs = mySelectorFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(true);
729  // check if there is selected ACs
730  if ((selectedACs.size() > 0) && (myCurrentSelectedParent != Selection::NOTHING)) {
731  // vector of hierarchical elements to select
732  std::vector<GNEHierarchicalElement*> HEToSelect;
733  for (const auto& selectedAC : selectedACs) {
734  // get hierarchical element
735  const auto HE = selectedAC->getHierarchicalElement();
736  // junctions
737  if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::JUNCTION)) {
738  HEToSelect.insert(HEToSelect.end(), HE->getParentJunctions().begin(), HE->getParentJunctions().end());
739  }
740  // edges
741  if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::EDGE)) {
742  if (selectedAC->getTagProperty().getTag() == SUMO_TAG_LANE) {
743  // special case for lanes
744  HEToSelect.push_back(dynamic_cast<GNELane*>(selectedAC)->getParentEdge());
745  } else {
746  HEToSelect.insert(HEToSelect.end(), HE->getParentEdges().begin(), HE->getParentEdges().end());
747  }
748  }
749  // lanes
750  if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::LANE)) {
751  HEToSelect.insert(HEToSelect.end(), HE->getParentLanes().begin(), HE->getParentLanes().end());
752  }
753  // additional
754  if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::ADDITIONAL)) {
755  HEToSelect.insert(HEToSelect.end(), HE->getParentAdditionals().begin(), HE->getParentAdditionals().end());
756  }
757  // wire
758  if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::WIRE)) {
759  HEToSelect.insert(HEToSelect.end(), HE->getParentAdditionals().begin(), HE->getParentAdditionals().end());
760  }
761  // demand
762  if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::DEMAND)) {
763  HEToSelect.insert(HEToSelect.end(), HE->getParentDemandElements().begin(), HE->getParentDemandElements().end());
764  }
765  // data
766  if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::DATA)) {
767  HEToSelect.insert(HEToSelect.end(), HE->getParentGenericDatas().begin(), HE->getParentGenericDatas().end());
768  }
769  }
770  // select HE
771  if (HEToSelect.size() > 0) {
772  if (HEToSelect.size() > 1) {
773  mySelectorFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::SELECT, TL("select parents"));
774  }
775  for (const auto& HE : HEToSelect) {
776  if (obj == mySelectParentsButton) {
777  HE->setAttribute(GNE_ATTR_SELECTED, "true", mySelectorFrameParent->getViewNet()->getUndoList());
778  } else {
779  HE->setAttribute(GNE_ATTR_SELECTED, "false", mySelectorFrameParent->getViewNet()->getUndoList());
780  }
781  }
782  if (HEToSelect.size() > 1) {
783  mySelectorFrameParent->getViewNet()->getUndoList()->end();
784  }
785  }
786  // update information label
787  mySelectorFrameParent->mySelectionInformation->updateInformationLabel();
788  // update viewNet
789  mySelectorFrameParent->getViewNet()->update();
790  }
791  return 1;
792 }
793 
794 
795 long
796 GNESelectorFrame::SelectionHierarchy::onCmdChildren(FXObject* obj, FXSelector, void*) {
797  // get selected elements
798  const auto selectedACs = mySelectorFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(true);
799  // check if there is selected ACs
800  if ((selectedACs.size() > 0) && (myCurrentSelectedChild != Selection::NOTHING)) {
801  // vector of hierarchical elements to select
802  std::vector<GNEHierarchicalElement*> HEToSelect;
803  for (const auto& selectedAC : selectedACs) {
804  // get hierarchical element
805  const auto HE = selectedAC->getHierarchicalElement();
806  // junctions
807  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::JUNCTION)) {
808  if (selectedAC->getTagProperty().getTag() == SUMO_TAG_JUNCTION) {
809  // special case for junction
810  const auto junction = dynamic_cast<GNEJunction*>(selectedAC);
811  // insert edges
812  HEToSelect.insert(HEToSelect.end(), junction->getGNEIncomingEdges().begin(), junction->getGNEIncomingEdges().end());
813  HEToSelect.insert(HEToSelect.end(), junction->getGNEOutgoingEdges().begin(), junction->getGNEOutgoingEdges().end());
814  } else {
815  HEToSelect.insert(HEToSelect.end(), HE->getChildJunctions().begin(), HE->getChildJunctions().end());
816  }
817  }
818  // edges
819  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::EDGE)) {
820  if (selectedAC->getTagProperty().getTag() == SUMO_TAG_EDGE) {
821  // special case for edges
822  const auto edge = dynamic_cast<GNEEdge*>(selectedAC);
823  // insert lanes
824  HEToSelect.insert(HEToSelect.end(), edge->getLanes().begin(), edge->getLanes().end());
825  } else {
826  HEToSelect.insert(HEToSelect.end(), HE->getChildEdges().begin(), HE->getChildEdges().end());
827  }
828  }
829  // connections
830  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::CONNECTION)) {
831  if (selectedAC->getTagProperty().getTag() == SUMO_TAG_EDGE) {
832  // case for edges
833  const auto edge = dynamic_cast<GNEEdge*>(selectedAC);
834  // insert connections
835  HEToSelect.insert(HEToSelect.end(), edge->getGNEConnections().begin(), edge->getGNEConnections().end());
836  } else if (selectedAC->getTagProperty().getTag() == SUMO_TAG_LANE) {
837  // case for lanes
838  const auto lane = dynamic_cast<GNELane*>(selectedAC);
839  // insert connections
840  for (const auto& connection : lane->getParentEdge()->getGNEConnections()) {
841  if (connection->getAttribute(SUMO_ATTR_FROM_LANE) == lane->getAttribute(SUMO_ATTR_INDEX)) {
842  HEToSelect.push_back(connection);
843  }
844  }
845  } else if (selectedAC->getTagProperty().getTag() == SUMO_TAG_JUNCTION) {
846  // case for junction
847  const auto junction = dynamic_cast<GNEJunction*>(selectedAC);
848  // get connections
849  const auto connections = junction->getGNEConnections();
850  // insert connections
851  HEToSelect.insert(HEToSelect.end(), connections.begin(), connections.end());
852  }
853  }
854  // crossings
855  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::CROSSING)) {
856  if (selectedAC->getTagProperty().getTag() == SUMO_TAG_JUNCTION) {
857  // case for junction
858  const auto junction = dynamic_cast<GNEJunction*>(selectedAC);
859  // insert crossings
860  HEToSelect.insert(HEToSelect.end(), junction->getGNECrossings().begin(), junction->getGNECrossings().end());
861  }
862  }
863  // lanes
864  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::LANE)) {
865  HEToSelect.insert(HEToSelect.end(), HE->getChildLanes().begin(), HE->getChildLanes().end());
866  }
867  // additional
868  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::ADDITIONAL)) {
869  // avoid insert symbols
870  for (const auto& additionalChild : HE->getChildAdditionals()) {
871  if (!additionalChild->getTagProperty().isWireElement() && !additionalChild->getTagProperty().isSymbol()) {
872  HEToSelect.push_back(additionalChild);
873  }
874  }
875  }
876  // wire
877  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::WIRE)) {
878  // avoid insert symbols
879  for (const auto& wireChild : HE->getChildAdditionals()) {
880  if (wireChild->getTagProperty().isWireElement() && !wireChild->getTagProperty().isSymbol()) {
881  HEToSelect.push_back(wireChild);
882  }
883  }
884  }
885  // demand
886  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::DEMAND)) {
887  HEToSelect.insert(HEToSelect.end(), HE->getChildDemandElements().begin(), HE->getChildDemandElements().end());
888  }
889  // data
890  if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::DATA)) {
891  HEToSelect.insert(HEToSelect.end(), HE->getChildGenericDatas().begin(), HE->getChildGenericDatas().end());
892  }
893  }
894  // select HE
895  if (HEToSelect.size() > 0) {
896  if (HEToSelect.size() > 1) {
897  mySelectorFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::SELECT, TL("select children"));
898  }
899  for (const auto& HE : HEToSelect) {
900  if (obj == mySelectChildrenButton) {
901  HE->setAttribute(GNE_ATTR_SELECTED, "true", mySelectorFrameParent->getViewNet()->getUndoList());
902  } else {
903  HE->setAttribute(GNE_ATTR_SELECTED, "false", mySelectorFrameParent->getViewNet()->getUndoList());
904  }
905  }
906  if (HEToSelect.size() > 1) {
907  mySelectorFrameParent->getViewNet()->getUndoList()->end();
908  }
909  }
910  // update information label
911  mySelectorFrameParent->mySelectionInformation->updateInformationLabel();
912  // update viewNet
913  mySelectorFrameParent->getViewNet()->update();
914  }
915  return 1;
916 }
917 
918 // ---------------------------------------------------------------------------
919 // GNECrossingFrame::Legend - methods
920 // ---------------------------------------------------------------------------
921 
923  MFXGroupBoxModule(selectorFrameParent, TL("Information")) {
924  // Create Selection Hint
925  new MFXDynamicLabel(getCollapsableFrame(), (std::string("- ") + TL("Hold <SHIFT> for rectangle selection.") + std::string("\n- ") + TL("Press <DEL> to delete selected objects.")).c_str(), nullptr, GUIDesignLabelFrameInformation);
926 }
927 
928 
930 
931 // ---------------------------------------------------------------------------
932 // GNESelectorFrame - methods
933 // ---------------------------------------------------------------------------
934 
936  GNEFrame(viewParent, viewNet, TL("Selection")) {
937  // create selection information
939  // create Modification Mode modul
941  // create ElementSet modul
945  // create VisualScaling modul
946  myVisualScaling = new VisualScaling(this);
947  // create SelectionOperation modul
949  // create SelectionHierarchy modul
951  // create Information modul
952  myInformation = new Information(this);
953 }
954 
955 
957 
958 
959 void
961  // refresh element set
963  // only show network element set
968  // only show demand element set
973  // only show data element set
977  }
978  // update information label
980  // Show frame
981  GNEFrame::show();
982 }
983 
984 
985 void
987  // hide frame
988  GNEFrame::hide();
989 }
990 
991 
992 void
994  // update information label
996 }
997 
998 
999 void
1001  mySelectionOperation->onCmdClear(nullptr, 0, nullptr);
1002 }
1003 
1004 
1005 bool
1007  // get front AC
1008  auto AC = viewObjects.getAttributeCarrierFront();
1009  // check AC
1010  if (AC == nullptr) {
1011  return false;
1012  }
1013  // check locking
1014  if (myViewNet->getLockManager().isObjectLocked(AC->getGUIGlObject()->getType(), AC->isAttributeCarrierSelected())) {
1015  return false;
1016  }
1017  // check modes
1018  if ((AC->getTagProperty().isNetworkElement() || AC->getTagProperty().isAdditionalElement()) &&
1020  return false;
1021  }
1022  if (AC->getTagProperty().isDemandElement() && !myViewNet->getEditModes().isCurrentSupermodeDemand()) {
1023  return false;
1024  }
1025  if (AC->getTagProperty().isDataElement() && !myViewNet->getEditModes().isCurrentSupermodeData()) {
1026  return false;
1027  }
1028  // filter GLObjects by layer
1029  auto filteredGLObjects = GNEViewNetHelper::filterElementsByLayer(viewObjects.getGLObjects());
1030  // check if we have to open dialog
1031  if (filteredGLObjects.size() > 1) {
1032  myViewNet->openSelectDialogAtCursor(filteredGLObjects);
1033  } else {
1034  // toggle selection
1035  if (AC->isAttributeCarrierSelected()) {
1036  AC->unselectAttributeCarrier();
1037  } else {
1038  AC->selectAttributeCarrier();
1039  }
1040  // update information label
1042  }
1043  return true;
1044 }
1045 
1046 
1047 void
1048 GNESelectorFrame::handleIDs(const std::vector<GNEAttributeCarrier*>& ACs, const ModificationMode::Operation setop) {
1049  // declare set operation
1051  // declare two sets of attribute carriers, one for select and another for unselect
1052  std::set<std::pair<std::string, GNEAttributeCarrier*> > ACsToSelect, ACsToUnselect;
1053  // in restrict AND replace mode all current selected attribute carriers will be unselected
1054  if ((setOperation == ModificationMode::Operation::REPLACE) || (setOperation == ModificationMode::Operation::RESTRICT)) {
1055  // obtain selected ACs depending of current supermode
1056  std::vector<GNEAttributeCarrier*> selectedACs = myViewNet->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(false);
1057  // add id into ACs to unselect
1058  for (const auto& selectedAC : selectedACs) {
1059  ACsToUnselect.insert(std::make_pair(selectedAC->getID(), selectedAC));
1060  }
1061  }
1062  // handle ids
1063  for (const auto& AC : ACs) {
1064  // iterate over AttributeCarriers an place it in ACsToSelect or ACsToUnselect
1065  switch (setOperation) {
1067  ACsToUnselect.insert(std::make_pair(AC->getID(), AC));
1068  break;
1070  if (ACsToUnselect.find(std::make_pair(AC->getID(), AC)) != ACsToUnselect.end()) {
1071  ACsToSelect.insert(std::make_pair(AC->getID(), AC));
1072  }
1073  break;
1074  default:
1075  ACsToSelect.insert(std::make_pair(AC->getID(), AC));
1076  break;
1077  }
1078  }
1079  // select junctions and their connections if Auto select junctions is enabled (note: only for "add mode")
1081  std::set<GNEEdge*> edgesToSelect;
1082  // iterate over ACsToSelect and extract edges
1083  for (const auto& AC : ACsToSelect) {
1084  if (AC.second->getTagProperty().getTag() == SUMO_TAG_EDGE) {
1085  edgesToSelect.insert(myViewNet->getNet()->getAttributeCarriers()->retrieveEdge(AC.second->getID()));
1086  }
1087  }
1088  // iterate over extracted edges
1089  for (const auto& edgeToSelect : edgesToSelect) {
1090  // select junction source and all connections, crossings and walkingAreas
1091  ACsToSelect.insert(std::make_pair(edgeToSelect->getFromJunction()->getID(), edgeToSelect->getFromJunction()));
1092  for (const auto& connectionToSelect : edgeToSelect->getFromJunction()->getGNEConnections()) {
1093  ACsToSelect.insert(std::make_pair(connectionToSelect->getID(), connectionToSelect));
1094  }
1095  for (const auto& fromCrossingToSelect : edgeToSelect->getFromJunction()->getGNECrossings()) {
1096  ACsToSelect.insert(std::make_pair(fromCrossingToSelect->getID(), fromCrossingToSelect));
1097  }
1098  for (const auto& fromWalkingAreaToSelect : edgeToSelect->getFromJunction()->getGNEWalkingAreas()) {
1099  ACsToSelect.insert(std::make_pair(fromWalkingAreaToSelect->getID(), fromWalkingAreaToSelect));
1100  }
1101  // select junction destination and all connections, crossings and walkingAreas
1102  ACsToSelect.insert(std::make_pair(edgeToSelect->getToJunction()->getID(), edgeToSelect->getToJunction()));
1103  for (const auto& connectionToSelect : edgeToSelect->getToJunction()->getGNEConnections()) {
1104  ACsToSelect.insert(std::make_pair(connectionToSelect->getID(), connectionToSelect));
1105  }
1106  for (const auto& toCrossingToSelect : edgeToSelect->getToJunction()->getGNECrossings()) {
1107  ACsToSelect.insert(std::make_pair(toCrossingToSelect->getID(), toCrossingToSelect));
1108  }
1109  for (const auto& toWalkingAreaToSelect : edgeToSelect->getToJunction()->getGNEWalkingAreas()) {
1110  ACsToSelect.insert(std::make_pair(toWalkingAreaToSelect->getID(), toWalkingAreaToSelect));
1111  }
1112  }
1113  }
1114  // only continue if there is ACs to select or unselect
1115  if ((ACsToSelect.size() + ACsToUnselect.size()) > 0) {
1116  // first unselect AC of ACsToUnselect and then selects AC of ACsToSelect
1117  myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("selection"));
1118  for (const auto& ACToUnselect : ACsToUnselect) {
1119  if (ACToUnselect.second->getTagProperty().isSelectable()) {
1120  ACToUnselect.second->setAttribute(GNE_ATTR_SELECTED, "false", myViewNet->getUndoList());
1121  }
1122  }
1123  for (const auto& ACToSelect : ACsToSelect) {
1124  if (ACToSelect.second->getTagProperty().isSelectable()) {
1125  ACToSelect.second->setAttribute(GNE_ATTR_SELECTED, "true", myViewNet->getUndoList());
1126  }
1127  }
1128  // finish operation
1129  myViewNet->getUndoList()->end();
1130  }
1131 }
1132 
1133 
1134 std::vector<GNEAttributeCarrier*>
1135 GNESelectorFrame::getMatches(const SumoXMLTag ACTag, const SumoXMLAttr ACAttr, const char compOp, const double val, const std::string& expr) {
1136  std::vector<GNEAttributeCarrier*> result;
1137  // first retrieve all ACs using ACTag
1138  const auto allACbyTag = myViewNet->getNet()->getAttributeCarriers()->retrieveAttributeCarriers(ACTag);
1139  // get Tag value
1140  const auto& tagValue = GNEAttributeCarrier::getTagProperty(ACTag);
1141  // iterate over all ACs
1142  for (const auto& AC : allACbyTag) {
1143  if (expr == "" && compOp == '@') {
1144  result.push_back(AC);
1145  } else if (tagValue.hasAttribute(ACAttr) && tagValue.getAttributeProperties(ACAttr).isNumerical()) {
1146  double acVal;
1147  std::istringstream buf(AC->getAttribute(ACAttr));
1148  buf >> acVal;
1149  switch (compOp) {
1150  case '<':
1151  if (acVal < val) {
1152  result.push_back(AC);
1153  }
1154  break;
1155  case '>':
1156  if (acVal > val) {
1157  result.push_back(AC);
1158  }
1159  break;
1160  case '=':
1161  if (acVal == val) {
1162  result.push_back(AC);
1163  }
1164  break;
1165  }
1166  } else {
1167  // string match
1168  std::string acVal = AC->getAttributeForSelection(ACAttr);
1169  switch (compOp) {
1170  case '@':
1171  if (acVal.find(expr) != std::string::npos) {
1172  result.push_back(AC);
1173  }
1174  break;
1175  case '!':
1176  if (acVal.find(expr) == std::string::npos) {
1177  result.push_back(AC);
1178  }
1179  break;
1180  case '=':
1181  if (acVal == expr) {
1182  result.push_back(AC);
1183  }
1184  break;
1185  case '^':
1186  if (acVal != expr) {
1187  result.push_back(AC);
1188  }
1189  break;
1190  }
1191  }
1192  }
1193  return result;
1194 }
1195 
1196 
1197 std::vector<GNEAttributeCarrier*>
1198 GNESelectorFrame::getGenericMatches(const std::vector<GNEGenericData*>& genericDatas, const std::string& attr, const char compOp, const double val, const std::string& expr) {
1199  std::vector<GNEAttributeCarrier*> result;
1200  // iterate over generic datas
1201  for (const auto& genericData : genericDatas) {
1202  if (expr == "" && compOp == '@') {
1203  result.push_back(genericData);
1204  } else if (attr != toString(GNE_ATTR_PARENT)) {
1205  double acVal;
1206  std::istringstream buf(genericData->getParameter(attr, "0"));
1207  buf >> acVal;
1208  switch (compOp) {
1209  case '<':
1210  if (acVal < val) {
1211  result.push_back(genericData);
1212  }
1213  break;
1214  case '>':
1215  if (acVal > val) {
1216  result.push_back(genericData);
1217  }
1218  break;
1219  case '=':
1220  if (acVal == val) {
1221  result.push_back(genericData);
1222  }
1223  break;
1224  }
1225  } else {
1226  // string match
1227  std::string acVal = genericData->getAttributeForSelection(GNE_ATTR_PARENT);
1228  switch (compOp) {
1229  case '@':
1230  if (acVal.find(expr) != std::string::npos) {
1231  result.push_back(genericData);
1232  }
1233  break;
1234  case '!':
1235  if (acVal.find(expr) == std::string::npos) {
1236  result.push_back(genericData);
1237  }
1238  break;
1239  case '=':
1240  if (acVal == expr) {
1241  result.push_back(genericData);
1242  }
1243  break;
1244  case '^':
1245  if (acVal != expr) {
1246  result.push_back(genericData);
1247  }
1248  break;
1249  }
1250  }
1251  }
1252  return result;
1253 }
1254 
1255 
1256 FXVerticalFrame*
1258  return myContentFrame;
1259 }
1260 
1261 
1264  return myModificationMode;
1265 }
1266 
1267 
1270  return mySelectionOperation;
1271 }
1272 
1273 
1276  return mySelectionInformation;
1277 }
1278 
1279 /****************************************************************************/
FXDEFMAP(GNESelectorFrame::ModificationMode) ModificationModeMap[]
@ NETWORK
Network mode (Edges, junctions, etc..)
@ DATA
Data mode (edgeData, LaneData etc..)
@ DEMAND
Demand mode (Routes, Vehicles etc..)
@ MID_GNE_SELECTORFRAME_SELECTSCALE
changes the visual scaling of selected items
Definition: GUIAppEnum.h:1051
@ MID_GNE_SELECTORFRAME_CHILDREN
select/unselect children
Definition: GUIAppEnum.h:1065
@ MID_CHOOSEN_SAVE
Save set.
Definition: GUIAppEnum.h:603
@ MID_CHOOSEN_INVERT
Deselect selected items.
Definition: GUIAppEnum.h:615
@ MID_CHOOSEN_DELETE
delete set
Definition: GUIAppEnum.h:607
@ MID_CHOOSEN_OPERATION
set type of selection
Definition: GUIAppEnum.h:597
@ MID_CHOOSEN_LOAD
Load set.
Definition: GUIAppEnum.h:601
@ MID_CHOOSEN_REDUCE
simplify network reduction
Definition: GUIAppEnum.h:619
@ MID_CHOOSEN_CLEAR
Clear set.
Definition: GUIAppEnum.h:605
@ MID_GNE_SELECT
select element
Definition: GUIAppEnum.h:953
@ MID_GNE_SELECTORFRAME_PARENTS
select/unselect parents
Definition: GUIAppEnum.h:1063
#define GUIDesignSpinDial
Definition: GUIDesigns.h:488
#define GUIDesignButton
Definition: GUIDesigns.h:88
#define GUIDesignComboBox
Definition: GUIDesigns.h:299
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:317
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:405
#define GUIDesignComboBoxVisibleItemsMedium
combo box medium small
Definition: GUIDesigns.h:53
#define GUIDesignLabelThick(justify)
label extended over frame with thick and with text justify to left
Definition: GUIDesigns.h:255
#define GUIDesignRadioButton
Definition: GUIDesigns.h:235
#define GUIDesignLabelFrameInformation
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition: GUIDesigns.h:285
FXString gCurrentFolder
The folder used as last.
@ OPEN
open icons
@ SIMPLIFYNETWORK
@ SAVE
save icons
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:306
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define TL(string)
Definition: MsgHandler.h:315
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ GNE_TAG_EDGEREL_SINGLE
@ SUMO_TAG_VEHICLE
description of a vehicle
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_EDGE
begin/end of the description of an edge
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_FROM_LANE
@ GNE_ATTR_PARENT
parent of an additional element
@ GNE_ATTR_SELECTED
element is selected
@ GNE_ATTR_PARAMETERS
parameters "key1=value1|key2=value2|...|keyN=valueN"
@ SUMO_ATTR_INDEX
@ SUMO_ATTR_ID
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
const std::string getID() const
get ID (all Attribute Carriers have one)
virtual GUIGlObject * getGUIGlObject()=0
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
bool isTemplate() const
check if this AC is template
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
void hideElementSet()
hide element set
void showElementSet()
show element set
GNEViewNet * myViewNet
FOX need this.
Definition: GNEFrame.h:117
FXVerticalFrame * myContentFrame
Vertical frame that holds all widgets of frame.
Definition: GNEFrame.h:120
virtual void show()
show Frame
Definition: GNEFrame.cpp:115
virtual void hide()
hide Frame
Definition: GNEFrame.cpp:124
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
std::vector< GNEConnection * > getGNEConnections() const
Returns all GNEConnections vinculated with this junction.
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
std::vector< GNEAttributeCarrier * > retrieveAttributeCarriers(SumoXMLTag tag=SUMO_TAG_NOTHING)
get the attribute carriers based on Type
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
std::vector< GNEAttributeCarrier * > getSelectedAttributeCarriers(const bool ignoreCurrentSupermode)
get all selected attribute carriers (or only relative to current supermode
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:123
Information(GNESelectorFrame *selectorFrameParent)
constructor
FXRadioButton * myReplaceRadioButton
replace radio button
ModificationMode(GNESelectorFrame *selectorFrameParent)
constructor
long onCmdSelectModificationMode(FXObject *, FXSelector, void *)
FXRadioButton * myAddRadioButton
FOX need this.
Operation getModificationMode() const
get current modification mode
FXRadioButton * myRemoveRadioButton
remove radio button
FXRadioButton * myKeepRadioButton
keep button
SelectionHierarchy(GNESelectorFrame *selectorFrameParent)
FOX-declaration.
MFXComboBoxIcon * myChildrenComboBox
comboBox for children
FXButton * myUnselectParentsButton
unselect parents button
FXButton * mySelectParentsButton
select parents button
FXButton * myUnselectChildrenButton
unselect parents button
long onCmdParents(FXObject *obj, FXSelector, void *)
called when user press select/unselect parents button
long onCmdChildren(FXObject *obj, FXSelector, void *)
called when user press select/unselect children button
long onCmdSelectItem(FXObject *obj, FXSelector, void *)
called when user select an item in comboBox
MFXComboBoxIcon * myParentsComboBox
comboBox for parents
const std::vector< std::pair< Selection, std::string > > myItems
FXButton * mySelectChildrenButton
select children button
void updateInformationLabel()
update information label
SelectionOperation(GNESelectorFrame *selectorFrameParent)
FOX-declaration.
long onCmdSave(FXObject *, FXSelector, void *)
Called when the user presses the Save-button.
bool askContinueIfLock() const
ask if continue due locking
long onCmdDelete(FXObject *, FXSelector, void *)
Called when the user presses the delete-button.
long onCmdReduce(FXObject *, FXSelector, void *)
Called when the user presses the Reduce-button.
long onCmdInvert(FXObject *, FXSelector, void *)
Called when the user presses the Invert-button.
long onCmdClear(FXObject *, FXSelector, void *)
Called when the user presses the Clear-button.
long onCmdLoad(FXObject *, FXSelector, void *)
Called when the user presses the Load-button.
std::pair< std::vector< std::pair< bool, GNEAttributeCarrier * > >, std::vector< std::pair< bool, GNEAttributeCarrier * > > > processMassiveNetworkElementSelection(const bool filterLanes)
FOX need this.
std::pair< std::vector< std::pair< bool, GNEAttributeCarrier * > >, std::vector< std::pair< bool, GNEAttributeCarrier * > > > processMassiveDataElementSelection()
process massive dataelement selection
std::pair< std::vector< std::pair< bool, GNEAttributeCarrier * > >, std::vector< std::pair< bool, GNEAttributeCarrier * > > > processMassiveDemandElementSelection()
process massive demand element selection
void loadFromFile(const std::string &file) const
load from file
long onCmdScaleSelection(FXObject *, FXSelector, void *)
Called when the user changes visual scaling.
VisualScaling(GNESelectorFrame *selectorFrameParent)
FOX-declaration.
FXRealSpinner * mySelectionScaling
Spinner for selection scaling.
FXVerticalFrame * getContentFrame() const
get vertical frame that holds all widgets of frame
std::vector< GNEAttributeCarrier * > getMatches(const SumoXMLTag ACTag, const SumoXMLAttr ACAttr, const char compOp, const double val, const std::string &expr)
return ACs of the given type with matching attrs
void updateFrameAfterUndoRedo()
function called after undo/redo in the current frame
ModificationMode * getModificationModeModul() const
get modification mode modul
std::vector< GNEAttributeCarrier * > getGenericMatches(const std::vector< GNEGenericData * > &genericDatas, const std::string &attr, const char compOp, const double val, const std::string &expr)
return GenericDatas of the given type with matching attrs
void show()
show Frame
GNESelectorFrame::SelectionOperation * mySelectionOperation
modul for selection operations
~GNESelectorFrame()
Destructor.
GNESelectorFrame::SelectionInformation * mySelectionInformation
modul for selection information
GNESelectorFrame::VisualScaling * myVisualScaling
modul for visual scaling
GNEElementSet * myDemandElementSet
moduls for select demand element set
GNESelectorFrame::Information * myInformation
information modul
GNESelectorFrame::SelectionHierarchy * mySelectionHierarchy
modul for selection hierarchy
GNEElementSet * myNetworkElementSet
moduls for select network element set
GNEElementSet * myDataElementSet
moduls for select data element set
GNESelectorFrame::ModificationMode * myModificationMode
modul for change modification mode
void clearCurrentSelection() const
clear current selection with possibility of undo/redo
void hide()
hide Frame
GNESelectorFrame::SelectionOperation * getSelectionOperationModul() const
get selection operation modul
void handleIDs(const std::vector< GNEAttributeCarrier * > &ACs, const ModificationMode::Operation setop=ModificationMode::Operation::DEFAULT)
apply list of ids to the current selection according to Operation,
GNESelectorFrame(GNEViewParent *viewParent, GNEViewNet *viewNet)
Constructor.
SelectionInformation * getSelectionInformation() const
get modul for selection information
bool selectAttributeCarrier(const GNEViewNetHelper::ViewObjectsSelector &viewObjects)
select attribute carrier (element)
bool isDataElement() const
return true if tag correspond to a data element
bool isSelectable() const
return true if tag correspond to a selectable element
bool isDemandElement() const
return true if tag correspond to a demand element
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
bool isObjectLocked(GUIGlObjectType objectType, const bool selected) const
check if given GLObject is locked for inspect, select, delete and move
class used to group all variables related with objects under cursor after a click over view
GNEAttributeCarrier * getAttributeCarrierFront() const
get front attribute carrier or a pointer to nullptr
const std::vector< GUIGlObject * > & getGLObjects() const
get vector with GL objects
GNENet * getNet() const
get the net object
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:723
void openSelectDialogAtCursor(const std::vector< GUIGlObject * > &GLObjects)
open select dialog at cursor
Definition: GNEViewNet.cpp:680
bool autoSelectNodes()
whether to autoselect nodes or to lanes
Definition: GNEViewNet.cpp:839
GNEUndoList * getUndoList() const
get the undoList object
GNEViewNetHelper::LockManager & getLockManager()
get lock manager
A single child window which contains a view of the simulation area.
Definition: GNEViewParent.h:88
static FXButton * buildFXButton(FXComposite *p, const std::string &text, const std::string &tip, const std::string &help, FXIcon *ic, FXObject *tgt, FXSelector sel, FXuint opts=BUTTON_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0, FXint pl=DEFAULT_PAD, FXint pr=DEFAULT_PAD, FXint pt=DEFAULT_PAD, FXint pb=DEFAULT_PAD)
build button
Definition: GUIDesigns.cpp:128
static FXRadioButton * buildFXRadioButton(FXComposite *p, const std::string &text, const std::string &tip, const std::string &help, FXObject *tgt, FXSelector sel, FXuint opts=RADIOBUTTON_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0, FXint pl=DEFAULT_PAD, FXint pr=DEFAULT_PAD, FXint pt=DEFAULT_PAD, FXint pb=DEFAULT_PAD)
build radio button
Definition: GUIDesigns.cpp:138
static StringBijection< GUIGlObjectType > TypeNames
associates object types with strings
Definition: GUIGlObject.h:71
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
Definition: GUIGlObject.h:156
const std::vector< GUIGlObject * > & getAllGLObjects() const
Returns the set of all known objects.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
ComboBox with icon.
FXint appendIconItem(const FXString &text, FXIcon *icon=nullptr, FXColor bgColor=FXRGB(255, 255, 255), void *ptr=nullptr)
append icon item in the last position
A list item which allows for custom coloring.
MFXGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
void setText(const std::string &text)
set text
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extension, FXIcon *icon, FXString &currentFolder)
Returns the file name to write.
Definition: MFXUtils.cpp:82
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
void close()
Closes the device and removes it from the dictionary.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
const std::string & getString(const T key) const
static std::string replace(std::string str, const std::string &what, const std::string &by)
Replaces all occurrences of the second string by the third string within the first string.
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
bool isCurrentSupermodeDemand() const
@check if current supermode is Demand
bool isCurrentSupermodeData() const
@check if current supermode is Data
bool isCurrentSupermodeNetwork() const
@check if current supermode is Network
static std::vector< GUIGlObject * > filterElementsByLayer(const std::vector< GUIGlObject * > &GLObjects)
filter elements based on the layer