Path: blob/main/src/netedit/frames/common/GNESelectorFrame.cpp
169684 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GNESelectorFrame.cpp14/// @author Jakob Erdmann15/// @date Mar 201116///17// The Widget for modifying selections of network-elements18/****************************************************************************/1920#include <netedit/GNEApplicationWindow.h>21#include <netedit/GNENet.h>22#include <netedit/GNETagPropertiesDatabase.h>23#include <netedit/GNEUndoList.h>24#include <netedit/GNEViewNet.h>25#include <netedit/GNEViewParent.h>26#include <netedit/dialogs/basic/GNEErrorBasicDialog.h>27#include <netedit/dialogs/basic/GNEQuestionBasicDialog.h>28#include <netedit/elements/network/GNEConnection.h>29#include <netedit/elements/network/GNECrossing.h>30#include <netedit/elements/network/GNEWalkingArea.h>31#include <netedit/frames/GNEMatchAttribute.h>32#include <utils/foxtools/MFXDynamicLabel.h>33#include <utils/gui/div/GUIDesigns.h>34#include <utils/gui/globjects/GUIGlObjectStorage.h>35#include <utils/gui/windows/GUIAppEnum.h>3637#include "GNESelectorFrame.h"3839// ===========================================================================40// FOX callback mapping41// ===========================================================================4243FXDEFMAP(GNESelectorFrame::ModificationMode) ModificationModeMap[] = {44FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_OPERATION, GNESelectorFrame::ModificationMode::onCmdSelectModificationMode)45};4647FXDEFMAP(GNESelectorFrame::VisualScaling) VisualScalingMap[] = {48FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECTORFRAME_SELECTSCALE, GNESelectorFrame::VisualScaling::onCmdScaleSelection)49};5051FXDEFMAP(GNESelectorFrame::SelectionOperation) SelectionOperationMap[] = {52FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_LOAD, GNESelectorFrame::SelectionOperation::onCmdLoad),53FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_SAVE, GNESelectorFrame::SelectionOperation::onCmdSave),54FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_INVERT, GNESelectorFrame::SelectionOperation::onCmdInvert),55FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_CLEAR, GNESelectorFrame::SelectionOperation::onCmdClear),56FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_DELETE, GNESelectorFrame::SelectionOperation::onCmdDelete),57FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_REDUCE, GNESelectorFrame::SelectionOperation::onCmdReduce)58};5960FXDEFMAP(GNESelectorFrame::SelectionHierarchy) SelectionHierarchyMap[] = {61FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECT, GNESelectorFrame::SelectionHierarchy::onCmdSelectItem),62FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECTORFRAME_PARENTS, GNESelectorFrame::SelectionHierarchy::onCmdParents),63FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECTORFRAME_CHILDREN, GNESelectorFrame::SelectionHierarchy::onCmdChildren),64};6566// Object implementation67FXIMPLEMENT(GNESelectorFrame::ModificationMode, MFXGroupBoxModule, ModificationModeMap, ARRAYNUMBER(ModificationModeMap))68FXIMPLEMENT(GNESelectorFrame::VisualScaling, MFXGroupBoxModule, VisualScalingMap, ARRAYNUMBER(VisualScalingMap))69FXIMPLEMENT(GNESelectorFrame::SelectionOperation, MFXGroupBoxModule, SelectionOperationMap, ARRAYNUMBER(SelectionOperationMap))70FXIMPLEMENT(GNESelectorFrame::SelectionHierarchy, MFXGroupBoxModule, SelectionHierarchyMap, ARRAYNUMBER(SelectionHierarchyMap))7172// ===========================================================================73// method definitions74// ===========================================================================7576// ---------------------------------------------------------------------------77// ModificationMode::SelectionInformation - methods78// ---------------------------------------------------------------------------7980GNESelectorFrame::SelectionInformation::SelectionInformation(GNESelectorFrame* selectorFrameParent) :81MFXGroupBoxModule(selectorFrameParent, TL("Selection information")),82mySelectorFrameParent(selectorFrameParent) {83// information label84myInformationLabel = new FXLabel(getCollapsableFrame(), "", nullptr, GUIDesignLabelFrameInformation);85}868788GNESelectorFrame::SelectionInformation::~SelectionInformation() {}899091void92GNESelectorFrame::SelectionInformation::updateInformationLabel() {93// first clear information94myInformation.clear();95// get attribute carriers96const auto ACs = mySelectorFrameParent->getViewNet()->getNet()->getAttributeCarriers();97// continue depending of supermode98if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeNetwork()) {99updateInformationLabel(TL("Junctions"), ACs->getNumberOfSelectedJunctions());100updateInformationLabel(TL("Edges"), ACs->getNumberOfSelectedEdges());101updateInformationLabel(TL("Lanes"), ACs->getNumberOfSelectedLanes());102updateInformationLabel(TL("Connections"), ACs->getNumberOfSelectedConnections());103updateInformationLabel(TL("Crossings"), ACs->getNumberOfSelectedCrossings());104updateInformationLabel(TL("WalkingAreas"), ACs->getNumberOfSelectedWalkingAreas());105updateInformationLabel(TL("Additionals"), ACs->getNumberOfSelectedPureAdditionals());106updateInformationLabel(TL("Wires"), ACs->getNumberOfSelectedWires());107updateInformationLabel(TL("TAZs"), ACs->getNumberOfSelectedTAZs());108updateInformationLabel(TL("Polygons"), ACs->getNumberOfSelectedPolygons());109updateInformationLabel(TL("POIs"), ACs->getNumberOfSelectedPOIs());110updateInformationLabel(TL("JuPedSim elements"),111ACs->getNumberOfSelectedJpsWalkableAreas() +112ACs->getNumberOfSelectedJpsObstacles());113} else if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {114updateInformationLabel(TL("Routes"), ACs->getNumberOfSelectedRoutes());115updateInformationLabel(TL("Vehicles"), ACs->getNumberOfSelectedVehicles());116updateInformationLabel(TL("Persons"), ACs->getNumberOfSelectedPersons());117updateInformationLabel(TL("Person trips"), ACs->getNumberOfSelectedPersonTrips());118updateInformationLabel(TL("Walks"), ACs->getNumberOfSelectedWalks());119updateInformationLabel(TL("Rides"), ACs->getNumberOfSelectedRides());120updateInformationLabel(TL("Containers"), ACs->getNumberOfSelectedContainers());121updateInformationLabel(TL("Transport"), ACs->getNumberOfSelectedTransport());122updateInformationLabel(TL("Tranships"), ACs->getNumberOfSelectedTranships());123updateInformationLabel(TL("Stops"), ACs->getNumberOfSelectedStops());124} else if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeData()) {125updateInformationLabel(TL("EdgeDatas"), ACs->getNumberOfSelectedEdgeDatas());126updateInformationLabel(TL("EdgeRelDatas"), ACs->getNumberOfSelectedEdgeRelDatas());127updateInformationLabel(TL("EdgeTAZRel"), ACs->getNumberOfSelectedEdgeTAZRel());128}129// adjust format130const auto numberLines = std::count(myInformation.begin(), myInformation.end(), ':');131if (numberLines == 0) {132myInformation.append(" \n \n");133} else if (numberLines > 1) {134myInformation.pop_back();135}136// set label137myInformationLabel->setText(myInformation.c_str());138}139140141void142GNESelectorFrame::SelectionInformation::updateInformationLabel(const std::string& element, int number) {143// check number144if (number > 0) {145myInformation.append(element + ": " + toString(number) + "\n");146}147}148149// ---------------------------------------------------------------------------150// ModificationMode::ModificationMode - methods151// ---------------------------------------------------------------------------152153GNESelectorFrame::ModificationMode::ModificationMode(GNESelectorFrame* selectorFrameParent) :154MFXGroupBoxModule(selectorFrameParent, TL("Modification Mode")),155myModificationModeType(Operation::ADD) {156// Create all options buttons157myAddRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("add"), "", TL("Selected objects are added to the previous selection"),158this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);159myRemoveRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("remove"), "", TL("Selected objects are removed from the previous selection"),160this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);161myKeepRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("keep"), "", TL("Restrict previous selection by the current selection"),162this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);163myReplaceRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("replace"), "", TL("Replace previous selection by the current selection"),164this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);165myAddRadioButton->setCheck(true);166}167168169GNESelectorFrame::ModificationMode::~ModificationMode() {}170171172GNESelectorFrame::ModificationMode::Operation173GNESelectorFrame::ModificationMode::getModificationMode() const {174return myModificationModeType;175}176177178long179GNESelectorFrame::ModificationMode::onCmdSelectModificationMode(FXObject* obj, FXSelector, void*) {180if (obj == myAddRadioButton) {181myModificationModeType = Operation::ADD;182myAddRadioButton->setCheck(true);183myRemoveRadioButton->setCheck(false);184myKeepRadioButton->setCheck(false);185myReplaceRadioButton->setCheck(false);186return 1;187} else if (obj == myRemoveRadioButton) {188myModificationModeType = Operation::SUB;189myAddRadioButton->setCheck(false);190myRemoveRadioButton->setCheck(true);191myKeepRadioButton->setCheck(false);192myReplaceRadioButton->setCheck(false);193return 1;194} else if (obj == myKeepRadioButton) {195myModificationModeType = Operation::RESTRICT;196myAddRadioButton->setCheck(false);197myRemoveRadioButton->setCheck(false);198myKeepRadioButton->setCheck(true);199myReplaceRadioButton->setCheck(false);200return 1;201} else if (obj == myReplaceRadioButton) {202myModificationModeType = Operation::REPLACE;203myAddRadioButton->setCheck(false);204myRemoveRadioButton->setCheck(false);205myKeepRadioButton->setCheck(false);206myReplaceRadioButton->setCheck(true);207return 1;208} else {209return 0;210}211}212213// ---------------------------------------------------------------------------214// ModificationMode::VisualScaling - methods215// ---------------------------------------------------------------------------216217GNESelectorFrame::VisualScaling::VisualScaling(GNESelectorFrame* selectorFrameParent) :218MFXGroupBoxModule(selectorFrameParent, TL("Visual Scaling")),219mySelectorFrameParent(selectorFrameParent) {220// Create spin button and configure it221mySelectionScaling = new FXRealSpinner(getCollapsableFrame(), 7, this, MID_GNE_SELECTORFRAME_SELECTSCALE, GUIDesignSpinDial);222//mySelectionScaling->setNumberFormat(1);223//mySelectionScaling->setIncrements(0.1, .5, 1);224mySelectionScaling->setIncrement(0.5);225mySelectionScaling->setRange(1, 100000);226mySelectionScaling->setValue(1);227mySelectionScaling->setHelpText(TL("Enlarge selected objects"));228}229230231GNESelectorFrame::VisualScaling::~VisualScaling() {}232233234long235GNESelectorFrame::VisualScaling::onCmdScaleSelection(FXObject*, FXSelector, void*) {236// set scale in viewnet237mySelectorFrameParent->myViewNet->setSelectorFrameScale(mySelectionScaling->getValue());238mySelectorFrameParent->myViewNet->updateViewNet();239return 1;240}241242// ---------------------------------------------------------------------------243// ModificationMode::SelectionHierarchy - methods244// ---------------------------------------------------------------------------245246GNESelectorFrame::SelectionOperation::SelectionOperation(GNESelectorFrame* selectorFrameParent) :247MFXGroupBoxModule(selectorFrameParent, TL("Selection operations")),248mySelectorFrameParent(selectorFrameParent) {249// tabular buttons, see GNETLSEditorFrame250251FXHorizontalFrame* selectionButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);252FXVerticalFrame* col1 = new FXVerticalFrame(selectionButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // left button columm253FXVerticalFrame* col2 = new FXVerticalFrame(selectionButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // right button column254255// Create "Clear List" Button256GUIDesigns::buildFXButton(col1, TL("Clear"), "", TL("Deselect all objects (hotkey: ESC)"), nullptr, this, MID_CHOOSEN_CLEAR, GUIDesignButton);257// Create "Invert" Button258GUIDesigns::buildFXButton(col2, TL("Invert"), "", TL("Invert selection status of all objects"), nullptr, this, MID_CHOOSEN_INVERT, GUIDesignButton);259// Create "Save" Button260GUIDesigns::buildFXButton(col1, TL("Save"), "", TL("Save ids of currently selected objects to a file."), nullptr, this, MID_CHOOSEN_SAVE, GUIDesignButton);261// Create "Load" Button262GUIDesigns::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" Button264GUIDesigns::buildFXButton(col1, TL("Delete"), "", TL("Delete all selected objects (hotkey: DEL)"), nullptr, this, MID_CHOOSEN_DELETE, GUIDesignButton);265// Create "reduce" Button266GUIDesigns::buildFXButton(col2, TL("Reduce"), "", TL("Reduce network to current selection."), nullptr, this, MID_CHOOSEN_REDUCE, GUIDesignButton);267}268269270GNESelectorFrame::SelectionOperation::~SelectionOperation() {}271272273void274GNESelectorFrame::SelectionOperation::loadFromFile(const std::string& file) const {275std::vector<GNEAttributeCarrier*> loadedACs;276std::ifstream strm(file.c_str());277// check if file can be opened278if (!strm.good()) {279WRITE_ERRORF(TL("Could not open '%'."), file);280} else {281// convert all glObjects into GNEAttributeCarriers282std::map<const std::string, GNEAttributeCarrier*> GLFUllNameAC;283const auto GLObjects = GUIGlObjectStorage::gIDStorage.getAllGLObjects();284for (const auto& GLObject : GLObjects) {285// try to parse GLObject to AC286GNEAttributeCarrier* AC = dynamic_cast<GNEAttributeCarrier*>(GLObject);287// if was successfully parsed and is NOT a template, add into GLFUllNameAC using fullName288if (AC && !AC->isTemplate()) {289GLFUllNameAC[GUIGlObject::TypeNames.getString(GLObject->getType()) + ":" + AC->getID()] = AC;290}291}292// continue while stream exist293while (strm.good()) {294std::string line;295strm >> line;296// check if line isn't empty297if (line.length() != 0) {298// obtain AC from GLFUllNameAC299if (StringUtils::startsWith(line, "node:")) {300line = StringUtils::replace(line, "node:", "junction:");301}302GNEAttributeCarrier* AC = GLFUllNameAC.count(line) > 0 ? GLFUllNameAC.at(line) : nullptr;303// check if AC exist, is selectable, and isn't locked304if (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 element306if (((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeNetwork()) && !AC->getTagProperty()->isDemandElement()) ||307((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeDemand()) && AC->getTagProperty()->isDemandElement()) ||308((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeData()) && AC->getTagProperty()->isDataElement())) {309loadedACs.push_back(AC);310}311}312}313}314// change selected attribute in loaded ACs allowing undo/redo315if (loadedACs.size() > 0) {316mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("load selection"));317mySelectorFrameParent->handleIDs(loadedACs);318mySelectorFrameParent->myViewNet->getUndoList()->end();319}320}321}322323324long325GNESelectorFrame::SelectionOperation::onCmdLoad(FXObject*, FXSelector, void*) {326// get the new file name327FXFileDialog opendialog(getCollapsableFrame(), TL("Open List of Selected Items"));328opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN));329opendialog.setSelectMode(SELECTFILE_EXISTING);330opendialog.setPatternList(SUMOXMLDefinitions::TXTFileExtensions.getMultilineString().c_str());331if (gCurrentFolder.length() != 0) {332opendialog.setDirectory(gCurrentFolder);333}334if (opendialog.execute()) {335gCurrentFolder = opendialog.getDirectory();336loadFromFile(opendialog.getFilename().text());337}338return 1;339}340341342long343GNESelectorFrame::SelectionOperation::onCmdSave(FXObject*, FXSelector, void*) {344FXString file = MFXUtils::getFilename2Write(this, TL("Save List of selected Items"),345SUMOXMLDefinitions::TXTFileExtensions.getMultilineString().c_str(),346GUIIconSubSys::getIcon(GUIIcon::SAVE), gCurrentFolder);347if (file == "") {348return 1;349}350try {351OutputDevice& dev = OutputDevice::getDevice(file.text());352// get selected attribute carriers353const auto selectedACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(false);354for (const auto& selectedAC : selectedACs) {355GUIGlObject* object = dynamic_cast<GUIGlObject*>(selectedAC);356if (object) {357dev << GUIGlObject::TypeNames.getString(object->getType()) << ":" << selectedAC->getID() << "\n";358}359}360dev.close();361} catch (IOError& e) {362// open message box error363GNEErrorBasicDialog(mySelectorFrameParent->getViewNet()->getViewParent()->getGNEAppWindows(),364TL("Storing Selection failed"), e.what());365}366return 1;367}368369370long371GNESelectorFrame::SelectionOperation::onCmdClear(FXObject*, FXSelector, void*) {372const auto& editModes = mySelectorFrameParent->myViewNet->getEditModes();373GNEUndoList* undoList = mySelectorFrameParent->myViewNet->getUndoList();374// declare massive selection375MassiveSelection massiveSelection =376editModes.isCurrentSupermodeNetwork() ? processMassiveNetworkElementSelection(false) :377editModes.isCurrentSupermodeDemand() ? processMassiveDemandElementSelection() :378processMassiveDataElementSelection();379// only continue if there are elements to unselect380if (massiveSelection.isElementToProcess()) {381// check if add locked elements382bool askedContinueIfLock = false;383bool addLockedElements = false;384bool unlockedElements = false;385for (const auto& ACToUnselect : massiveSelection.ACsToUnselect) {386if (ACToUnselect.second == false) {387// there are unlocked elements388unlockedElements = true;389} else if (!askedContinueIfLock) {390addLockedElements = askContinueIfLock();391// only ask one time for locking392askedContinueIfLock = true;393}394}395if (unlockedElements || addLockedElements) {396mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("clear selection"));397for (const auto& ACToUnselect : massiveSelection.ACsToUnselect) {398if (addLockedElements || !ACToUnselect.second) {399ACToUnselect.first->setAttribute(GNE_ATTR_SELECTED, "false", undoList);400}401}402mySelectorFrameParent->myViewNet->getUndoList()->end();403}404}405mySelectorFrameParent->myViewNet->updateViewNet();406return 1;407}408409long410GNESelectorFrame::SelectionOperation::onCmdDelete(FXObject*, FXSelector, void*) {411// acts like the 'del' hotkey412mySelectorFrameParent->getViewNet()->hotkeyDel();413return 1;414}415416417long418GNESelectorFrame::SelectionOperation::onCmdInvert(FXObject*, FXSelector, void*) {419const auto& editModes = mySelectorFrameParent->myViewNet->getEditModes();420GNEUndoList* undoList = mySelectorFrameParent->myViewNet->getUndoList();421// declare massive selection422MassiveSelection massiveSelection =423editModes.isCurrentSupermodeNetwork() ? processMassiveNetworkElementSelection(true) :424editModes.isCurrentSupermodeDemand() ? processMassiveDemandElementSelection() :425processMassiveDataElementSelection();426// only continue if there are elements to select and unselect427if (massiveSelection.isElementToProcess()) {428// check if add locked elements429bool askedContinueIfLock = false;430bool addLockedElements = false;431bool unlockedElements = false;432for (const auto& ACToSelect : massiveSelection.ACsToSelect) {433if (ACToSelect.second == false) {434// there are unlocked elements435unlockedElements = true;436} else if (!askedContinueIfLock) {437addLockedElements = askContinueIfLock();438// only ask one time for locking439askedContinueIfLock = true;440}441}442for (const auto& ACToUnselect : massiveSelection.ACsToUnselect) {443if (ACToUnselect.second == false) {444// there are unlocked elements445unlockedElements = true;446} else if (!askedContinueIfLock) {447addLockedElements = askContinueIfLock();448// only ask one time for locking449askedContinueIfLock = true;450}451}452if (unlockedElements || addLockedElements) {453mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("invert selection"));454for (const auto& ACToSelect : massiveSelection.ACsToSelect) {455if (addLockedElements || !ACToSelect.second) {456ACToSelect.first->setAttribute(GNE_ATTR_SELECTED, "true", undoList);457}458}459for (const auto& ACToUnselect : massiveSelection.ACsToUnselect) {460if (addLockedElements || !ACToUnselect.second) {461ACToUnselect.first->setAttribute(GNE_ATTR_SELECTED, "false", undoList);462}463}464mySelectorFrameParent->myViewNet->getUndoList()->end();465}466}467return 1;468}469470471long472GNESelectorFrame::SelectionOperation::onCmdReduce(FXObject*, FXSelector, void*) {473// begin undoList operation474mySelectorFrameParent->getViewNet()->getUndoList()->begin(Supermode::NETWORK, GUIIcon::SIMPLIFYNETWORK, TL("reduce network"));475// invert and clear476onCmdInvert(0, 0, 0);477onCmdDelete(0, 0, 0);478// end undoList operation479mySelectorFrameParent->getViewNet()->getUndoList()->end();480return 1;481}482483484GNESelectorFrame::SelectionOperation::MassiveSelection485GNESelectorFrame::SelectionOperation::processMassiveNetworkElementSelection(const bool filterLanes) const {486const auto& ACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers();487const bool selectEdges = mySelectorFrameParent->getViewNet()->getNetworkViewOptions().selectEdges();488// extract all network elements489std::unordered_set<GNEAttributeCarrier*> networkACs;490// add junctions491for (const auto& junction : ACs->getJunctions()) {492networkACs.insert(junction.second);493// due we iterate over all junctions, only it's necessary iterate over incoming edges494for (const auto& incomingEdge : junction.second->getGNEIncomingEdges()) {495if (!filterLanes || selectEdges) {496networkACs.insert(incomingEdge);497}498// add lanes499if (!filterLanes || !selectEdges) {500for (const auto& lane : incomingEdge->getChildLanes()) {501networkACs.insert(lane);502}503}504// add connections505for (const auto& connection : incomingEdge->getGNEConnections()) {506networkACs.insert(connection);507}508}509// add crossings510for (const auto& crossing : junction.second->getGNECrossings()) {511networkACs.insert(crossing);512}513// add walkingArea514for (const auto& walkingArea : junction.second->getGNEWalkingAreas()) {515networkACs.insert(walkingArea);516}517}518// add additionals519for (const auto& additionalTags : ACs->getAdditionals()) {520for (const auto& additional : additionalTags.second) {521if (additional.second->getTagProperty()->isSelectable()) {522networkACs.insert(additional.second);523}524}525}526// declare massive selection527GNESelectorFrame::SelectionOperation::MassiveSelection massiveSelection(ACs->getNumberOfNetworkElements());528// iterate over network ACs529for (const auto& networkAC : networkACs) {530const auto networkACObjectType = networkAC->getGUIGlObject()->getType();531// save locking status in lockedTypes532if (massiveSelection.lockedTypes.find(networkACObjectType) == massiveSelection.lockedTypes.end()) {533massiveSelection.lockedTypes[networkACObjectType] = networkAC->getGUIGlObject()->isGLObjectLocked();534}535// save element and their locking status536if (networkAC->isAttributeCarrierSelected()) {537massiveSelection.ACsToUnselect[networkAC] = massiveSelection.lockedTypes.at(networkACObjectType);538} else {539massiveSelection.ACsToSelect[networkAC] = massiveSelection.lockedTypes.at(networkACObjectType);540}541}542return massiveSelection;543}544545546GNESelectorFrame::SelectionOperation::MassiveSelection547GNESelectorFrame::SelectionOperation::processMassiveDemandElementSelection() const {548const auto& ACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers();549// declare massive selection550GNESelectorFrame::SelectionOperation::MassiveSelection massiveSelection(ACs->getNumberOfDemandElements());551// iterate over selectable demand elements552for (const auto& demandElementTag : ACs->getDemandElements()) {553for (const auto& demandElement : demandElementTag.second) {554if (demandElement.second->getTagProperty()->isSelectable()) {555const auto networkACObjectType = demandElement.first->getType();556// save locking status in lockedTypes557if (massiveSelection.lockedTypes.find(networkACObjectType) == massiveSelection.lockedTypes.end()) {558massiveSelection.lockedTypes[networkACObjectType] = demandElement.first->isGLObjectLocked();559}560// save element and their locking status561if (demandElement.second->isAttributeCarrierSelected()) {562massiveSelection.ACsToUnselect[demandElement.second] = massiveSelection.lockedTypes.at(networkACObjectType);563} else {564massiveSelection.ACsToSelect[demandElement.second] = massiveSelection.lockedTypes.at(networkACObjectType);565}566}567}568}569return massiveSelection;570}571572573GNESelectorFrame::SelectionOperation::MassiveSelection574GNESelectorFrame::SelectionOperation::processMassiveDataElementSelection() const {575const auto& ACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers();576// declare massive selection577GNESelectorFrame::SelectionOperation::MassiveSelection massiveSelection(ACs->getNumberOfDataElements());578// iterate over selectable demand elements579for (const auto& genericDataTag : mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers()->getGenericDatas()) {580for (const auto& genericData : genericDataTag.second) {581if (genericData.second->getTagProperty()->isSelectable()) {582const auto networkACObjectType = genericData.first->getType();583// save locking status in lockedTypes584if (massiveSelection.lockedTypes.find(networkACObjectType) == massiveSelection.lockedTypes.end()) {585massiveSelection.lockedTypes[networkACObjectType] = genericData.first->isGLObjectLocked();586}587// save element and their locking status588if (genericData.second->isAttributeCarrierSelected()) {589massiveSelection.ACsToUnselect[genericData.second] = massiveSelection.lockedTypes.at(networkACObjectType);590} else {591massiveSelection.ACsToSelect[genericData.second] = massiveSelection.lockedTypes.at(networkACObjectType);592}593}594}595}596return massiveSelection;597}598599600bool601GNESelectorFrame::SelectionOperation::askContinueIfLock() const {602// open question dialog box603const auto questionDialog = GNEQuestionBasicDialog(mySelectorFrameParent->getViewNet()->getViewParent()->getGNEAppWindows(),604GNEDialog::Buttons::YES_NO,605TL("Confirm selection operation"),606TL("There are locked elements in the current selection."),607TL("Apply operation to locked elements?"));608// check result609return (questionDialog.getResult() == GNEDialog::Result::ACCEPT);610}611612// ---------------------------------------------------------------------------613// ModificationMode::SelectionOperation::SelectionHierarchy - methods614// ---------------------------------------------------------------------------615616GNESelectorFrame::SelectionOperation::MassiveSelection::MassiveSelection(const int bucketSize) {617ACsToSelect.reserve(bucketSize);618ACsToUnselect.reserve(bucketSize);619}620621622GNESelectorFrame::SelectionOperation::MassiveSelection::~MassiveSelection() {}623624625inline bool GNESelectorFrame::SelectionOperation::MassiveSelection::isElementToProcess() const {626return (ACsToSelect.size() + ACsToUnselect.size()) > 0;627}628629630GNESelectorFrame::SelectionOperation::MassiveSelection::MassiveSelection() {}631632// ---------------------------------------------------------------------------633// ModificationMode::SelectionHierarchy - methods634// ---------------------------------------------------------------------------635636GNESelectorFrame::SelectionHierarchy::SelectionHierarchy(GNESelectorFrame* selectorFrameParent) :637MFXGroupBoxModule(selectorFrameParent, TL("Hierarchy operations")),638mySelectorFrameParent(selectorFrameParent),639myCurrentSelectedParent(Selection::ALL),640myCurrentSelectedChild(Selection::ALL) {641const auto staticTooltipMenu = selectorFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();642// create label for parents643new FXLabel(getCollapsableFrame(), TL("Select parents"), nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL));644// Create MFXComboBoxIcon for parent comboBox645myParentsComboBox = new MFXComboBoxIcon(getCollapsableFrame(), staticTooltipMenu, true, GUIDesignComboBoxVisibleItems,646this, MID_GNE_SELECT, GUIDesignComboBox);647// create parent buttons648FXHorizontalFrame* parentButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);649// Create "select" Button650mySelectParentsButton = GUIDesigns::buildFXButton(parentButtons, TL("Select"), "", "", GUIIconSubSys::getIcon(GUIIcon::SELECT), this, MID_GNE_SELECTORFRAME_PARENTS, GUIDesignButton);651// Create "unselect" Button652myUnselectParentsButton = GUIDesigns::buildFXButton(parentButtons, TL("Unselect"), "", "", GUIIconSubSys::getIcon(GUIIcon::UNSELECT), this, MID_GNE_SELECTORFRAME_PARENTS, GUIDesignButton);653// create label for parents654new FXLabel(getCollapsableFrame(), TL("Select children"), nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL));655// Create MFXComboBoxIcon for parent comboBox656myChildrenComboBox = new MFXComboBoxIcon(getCollapsableFrame(), staticTooltipMenu, true, GUIDesignComboBoxVisibleItems,657this, MID_GNE_SELECT, GUIDesignComboBox);658// create children buttons659FXHorizontalFrame* childrenButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);660// Create "select" Button661mySelectChildrenButton = GUIDesigns::buildFXButton(childrenButtons, TL("Select"), "", "", GUIIconSubSys::getIcon(GUIIcon::SELECT), this, MID_GNE_SELECTORFRAME_CHILDREN, GUIDesignButton);662// Create "unselect" Button663myUnselectChildrenButton = GUIDesigns::buildFXButton(childrenButtons, TL("Unselect"), "", "", GUIIconSubSys::getIcon(GUIIcon::UNSELECT), this, MID_GNE_SELECTORFRAME_CHILDREN, GUIDesignButton);664// fill comboBoxes665for (const auto& item : myItems) {666myParentsComboBox->appendIconItem(item.second.c_str());667myChildrenComboBox->appendIconItem(item.second.c_str());668}669}670671672GNESelectorFrame::SelectionHierarchy::~SelectionHierarchy() {}673674675long676GNESelectorFrame::SelectionHierarchy::onCmdSelectItem(FXObject* obj, FXSelector, void*) {677if (obj == myParentsComboBox) {678for (const auto& item : myItems) {679if (item.second == myParentsComboBox->getText().text()) {680// enable buttons681mySelectParentsButton->enable();682myUnselectParentsButton->enable();683// change text color684myParentsComboBox->setTextColor(GUIDesignTextColorBlack);685// set current selected parent686myCurrentSelectedParent = item.first;687return 1;688}689}690// item not found691myCurrentSelectedParent = Selection::NOTHING;692// disable buttons693mySelectParentsButton->disable();694myUnselectParentsButton->disable();695myParentsComboBox->setTextColor(GUIDesignTextColorRed);696return 1;697} else if (obj == myChildrenComboBox) {698for (const auto& item : myItems) {699if (item.second == myChildrenComboBox->getText().text()) {700// enable buttons701mySelectChildrenButton->enable();702myUnselectChildrenButton->enable();703// change text color704myChildrenComboBox->setTextColor(GUIDesignTextColorBlack);705// set current selected parent706myCurrentSelectedChild = item.first;707return 1;708}709}710// item not found711myCurrentSelectedChild = Selection::NOTHING;712// disable buttons713mySelectChildrenButton->disable();714myUnselectChildrenButton->disable();715myChildrenComboBox->setTextColor(GUIDesignTextColorRed);716return 1;717}718return 0;719}720721722long723GNESelectorFrame::SelectionHierarchy::onCmdParents(FXObject* obj, FXSelector, void*) {724const auto viewNet = mySelectorFrameParent->getViewNet();725// get selected elements726const auto selectedACs = viewNet->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(true);727// check if there is selected ACs728if ((selectedACs.size() > 0) && (myCurrentSelectedParent != Selection::NOTHING)) {729// vector of of element to select or unselect730std::vector<GNEAttributeCarrier*> editedParents;731for (const auto& selectedAC : selectedACs) {732if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_CONNECTION) {733const auto connection = viewNet->getNet()->getAttributeCarriers()->retrieveConnection(selectedAC->getGUIGlObject());734editedParents.push_back(connection->getLaneFrom());735editedParents.push_back(connection->getLaneTo());736} else if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_CROSSING) {737const auto crossing = viewNet->getNet()->getAttributeCarriers()->retrieveCrossing(selectedAC->getGUIGlObject());738editedParents.push_back(crossing->getParentJunctions().front());739} else {740// get hierarchical element741const auto hierarchicalElement = selectedAC->getHierarchicalElement();742// get parent junctions743if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::JUNCTION)) {744editedParents.insert(editedParents.end(), hierarchicalElement->getParentJunctions().begin(), hierarchicalElement->getParentJunctions().end());745}746// get parent edges747if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::EDGE)) {748if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_LANE) {749// special case for lanes750editedParents.push_back(dynamic_cast<GNELane*>(selectedAC)->getParentEdge());751} else {752editedParents.insert(editedParents.end(), hierarchicalElement->getParentEdges().begin(), hierarchicalElement->getParentEdges().end());753}754}755// get parent lanes756if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::LANE)) {757editedParents.insert(editedParents.end(), hierarchicalElement->getParentLanes().begin(), hierarchicalElement->getParentLanes().end());758}759// get parent additional760if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::ADDITIONAL)) {761editedParents.insert(editedParents.end(), hierarchicalElement->getParentAdditionals().begin(), hierarchicalElement->getParentAdditionals().end());762}763// get parent wire764if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::WIRE)) {765editedParents.insert(editedParents.end(), hierarchicalElement->getParentAdditionals().begin(), hierarchicalElement->getParentAdditionals().end());766}767// get parent demand768if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::DEMAND)) {769editedParents.insert(editedParents.end(), hierarchicalElement->getParentDemandElements().begin(), hierarchicalElement->getParentDemandElements().end());770}771// get parent data772if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::DATA)) {773editedParents.insert(editedParents.end(), hierarchicalElement->getParentGenericDatas().begin(), hierarchicalElement->getParentGenericDatas().end());774}775}776}777// select HE778if (editedParents.size() > 0) {779if (editedParents.size() > 1) {780viewNet->getUndoList()->begin(GUIIcon::SELECT, TL("select parents"));781}782for (const auto& HE : editedParents) {783if (obj == mySelectParentsButton) {784HE->setAttribute(GNE_ATTR_SELECTED, "true", viewNet->getUndoList());785} else {786HE->setAttribute(GNE_ATTR_SELECTED, "false", viewNet->getUndoList());787}788}789if (editedParents.size() > 1) {790viewNet->getUndoList()->end();791}792}793// update information label794mySelectorFrameParent->mySelectionInformation->updateInformationLabel();795// update viewNet796viewNet->update();797}798return 1;799}800801802long803GNESelectorFrame::SelectionHierarchy::onCmdChildren(FXObject* obj, FXSelector, void*) {804// get selected elements805const auto selectedACs = mySelectorFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(true);806// check if there is selected ACs807if ((selectedACs.size() > 0) && (myCurrentSelectedChild != Selection::NOTHING)) {808// vector of of element to select or unselect809std::vector<GNEAttributeCarrier*> editedChildren;810for (const auto& selectedAC : selectedACs) {811// get hierarchical element812const auto hierarchicalElement = selectedAC->getHierarchicalElement();813// junctions814if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::JUNCTION)) {815if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_JUNCTION) {816// special case for junction817const auto junction = dynamic_cast<GNEJunction*>(selectedAC);818// insert edges819editedChildren.insert(editedChildren.end(), junction->getGNEIncomingEdges().begin(), junction->getGNEIncomingEdges().end());820editedChildren.insert(editedChildren.end(), junction->getGNEOutgoingEdges().begin(), junction->getGNEOutgoingEdges().end());821} else {822editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildJunctions().begin(), hierarchicalElement->getChildJunctions().end());823}824}825// edges826if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::EDGE)) {827if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_EDGE) {828// special case for edges829const auto edge = dynamic_cast<GNEEdge*>(selectedAC);830// insert lanes831editedChildren.insert(editedChildren.end(), edge->getChildLanes().begin(), edge->getChildLanes().end());832} else {833editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildEdges().begin(), hierarchicalElement->getChildEdges().end());834}835}836// connections837if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::CONNECTION)) {838if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_EDGE) {839// case for edges840const auto edge = dynamic_cast<GNEEdge*>(selectedAC);841// insert connections842editedChildren.insert(editedChildren.end(), edge->getGNEConnections().begin(), edge->getGNEConnections().end());843} else if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_LANE) {844// case for lanes845const auto lane = dynamic_cast<GNELane*>(selectedAC);846// insert connections847for (const auto& connection : lane->getParentEdge()->getGNEConnections()) {848if (connection->getAttribute(SUMO_ATTR_FROM_LANE) == lane->getAttribute(SUMO_ATTR_INDEX)) {849editedChildren.push_back(connection);850}851}852} else if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_JUNCTION) {853// case for junction854const auto junction = dynamic_cast<GNEJunction*>(selectedAC);855// get connections856const auto connections = junction->getGNEConnections();857// insert connections858editedChildren.insert(editedChildren.end(), connections.begin(), connections.end());859}860}861// crossings862if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::CROSSING)) {863if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_JUNCTION) {864// case for junction865const auto junction = dynamic_cast<GNEJunction*>(selectedAC);866// insert crossings867editedChildren.insert(editedChildren.end(), junction->getGNECrossings().begin(), junction->getGNECrossings().end());868}869}870// lanes871if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::LANE)) {872editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildLanes().begin(), hierarchicalElement->getChildLanes().end());873}874// additional875if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::ADDITIONAL)) {876// avoid insert symbols877for (const auto& additionalChild : hierarchicalElement->getChildAdditionals()) {878if (!additionalChild->getTagProperty()->isWireElement() && !additionalChild->getTagProperty()->isSymbol()) {879editedChildren.push_back(additionalChild);880}881}882}883// wire884if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::WIRE)) {885// avoid insert symbols886for (const auto& wireChild : hierarchicalElement->getChildAdditionals()) {887if (wireChild->getTagProperty()->isWireElement() && !wireChild->getTagProperty()->isSymbol()) {888editedChildren.push_back(wireChild);889}890}891}892// demand893if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::DEMAND)) {894editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildDemandElements().begin(), hierarchicalElement->getChildDemandElements().end());895}896// data897if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::DATA)) {898editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildGenericDatas().begin(), hierarchicalElement->getChildGenericDatas().end());899}900}901// select HE902if (editedChildren.size() > 0) {903if (editedChildren.size() > 1) {904mySelectorFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::SELECT, TL("select children"));905}906for (const auto& HE : editedChildren) {907if (obj == mySelectChildrenButton) {908HE->setAttribute(GNE_ATTR_SELECTED, "true", mySelectorFrameParent->getViewNet()->getUndoList());909} else {910HE->setAttribute(GNE_ATTR_SELECTED, "false", mySelectorFrameParent->getViewNet()->getUndoList());911}912}913if (editedChildren.size() > 1) {914mySelectorFrameParent->getViewNet()->getUndoList()->end();915}916}917// update information label918mySelectorFrameParent->mySelectionInformation->updateInformationLabel();919// update viewNet920mySelectorFrameParent->getViewNet()->update();921}922return 1;923}924925// ---------------------------------------------------------------------------926// GNECrossingFrame::Legend - methods927// ---------------------------------------------------------------------------928929GNESelectorFrame::Information::Information(GNESelectorFrame* selectorFrameParent) :930MFXGroupBoxModule(selectorFrameParent, TL("Information")) {931// Create Selection Hint932new MFXDynamicLabel(getCollapsableFrame(), (std::string("- ") + TL("Hold <SHIFT> for rectangle selection.") + std::string("\n- ") + TL("Press <DEL> to delete selected objects.")).c_str(), nullptr, GUIDesignLabelFrameInformation);933}934935936GNESelectorFrame::Information::~Information() {}937938// ---------------------------------------------------------------------------939// GNESelectorFrame - methods940// ---------------------------------------------------------------------------941942GNESelectorFrame::GNESelectorFrame(GNEViewParent* viewParent, GNEViewNet* viewNet) :943GNEFrame(viewParent, viewNet, TL("Selection")) {944// create selection information945mySelectionInformation = new SelectionInformation(this);946// create Modification Mode modul947myModificationMode = new ModificationMode(this);948// create ElementSet modul949myMatchAttribute = new GNEMatchAttribute(this);950// create VisualScaling modul951myVisualScaling = new VisualScaling(this);952// create SelectionOperation modul953mySelectionOperation = new SelectionOperation(this);954// create SelectionHierarchy modul955mySelectionHierarchy = new SelectionHierarchy(this);956// create Information modul957myInformation = new Information(this);958}959960961GNESelectorFrame::~GNESelectorFrame() {}962963964void965GNESelectorFrame::show() {966myMatchAttribute->showMatchAttribute();967// update information label968mySelectionInformation->updateInformationLabel();969// Show frame970GNEFrame::show();971}972973974void975GNESelectorFrame::hide() {976// hide frame977GNEFrame::hide();978}979980981void982GNESelectorFrame::updateFrameAfterUndoRedo() {983// update information label984mySelectionInformation->updateInformationLabel();985}986987988void989GNESelectorFrame::clearCurrentSelection() const {990mySelectionOperation->onCmdClear(nullptr, 0, nullptr);991}992993994bool995GNESelectorFrame::selectAttributeCarrier(const GNEViewNetHelper::ViewObjectsSelector& viewObjects) {996// get front AC997auto AC = viewObjects.getAttributeCarrierFront();998// check AC999if (AC == nullptr) {1000return false;1001}1002// check locking1003if (myViewNet->getLockManager().isObjectLocked(AC->getGUIGlObject()->getType(), AC->isAttributeCarrierSelected())) {1004return false;1005}1006// check modes1007if ((AC->getTagProperty()->isNetworkElement() || AC->getTagProperty()->isAdditionalElement()) &&1008!myViewNet->getEditModes().isCurrentSupermodeNetwork()) {1009return false;1010}1011if (AC->getTagProperty()->isDemandElement() && !myViewNet->getEditModes().isCurrentSupermodeDemand()) {1012return false;1013}1014if (AC->getTagProperty()->isDataElement() && !myViewNet->getEditModes().isCurrentSupermodeData()) {1015return false;1016}1017// filter GLObjects by layer1018auto filteredGLObjects = GNEViewNetHelper::filterElementsByLayer(viewObjects.getGLObjects());1019// check if we have to open dialog1020if (filteredGLObjects.size() > 1) {1021myViewNet->openSelectDialogAtCursor(filteredGLObjects);1022} else {1023// toggle selection1024if (AC->isAttributeCarrierSelected()) {1025AC->unselectAttributeCarrier();1026} else {1027AC->selectAttributeCarrier();1028}1029// update information label1030mySelectionInformation->updateInformationLabel();1031}1032return true;1033}103410351036void1037GNESelectorFrame::handleIDs(const std::vector<GNEAttributeCarrier*>& ACs, const ModificationMode::Operation setop) {1038// declare set operation1039const ModificationMode::Operation setOperation = ((setop == ModificationMode::Operation::DEFAULT) ? myModificationMode->getModificationMode() : setop);1040// declare two sets of attribute carriers, one for select and another for unselect1041std::set<std::pair<std::string, GNEAttributeCarrier*> > ACsToSelect, ACsToUnselect;1042// in restrict AND replace mode all current selected attribute carriers will be unselected1043if ((setOperation == ModificationMode::Operation::REPLACE) || (setOperation == ModificationMode::Operation::RESTRICT)) {1044// obtain selected ACs depending of current supermode1045auto selectedACs = myViewNet->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(false);1046// add id into ACs to unselect1047for (const auto& selectedAC : selectedACs) {1048ACsToUnselect.insert(std::make_pair(selectedAC->getID(), selectedAC));1049}1050}1051// handle ids1052for (const auto& AC : ACs) {1053// iterate over AttributeCarriers an place it in ACsToSelect or ACsToUnselect1054switch (setOperation) {1055case GNESelectorFrame::ModificationMode::Operation::SUB:1056ACsToUnselect.insert(std::make_pair(AC->getID(), AC));1057break;1058case GNESelectorFrame::ModificationMode::Operation::RESTRICT:1059if (ACsToUnselect.find(std::make_pair(AC->getID(), AC)) != ACsToUnselect.end()) {1060ACsToSelect.insert(std::make_pair(AC->getID(), AC));1061}1062break;1063default:1064ACsToSelect.insert(std::make_pair(AC->getID(), AC));1065break;1066}1067}1068// select junctions and their connections if Auto select junctions is enabled (note: only for "add mode")1069if (myViewNet->autoSelectNodes() && (setop == ModificationMode::Operation::ADD)) {1070std::set<GNEEdge*> edgesToSelect;1071// iterate over ACsToSelect and extract edges1072for (const auto& AC : ACsToSelect) {1073if (AC.second->getTagProperty()->getTag() == SUMO_TAG_EDGE) {1074edgesToSelect.insert(myViewNet->getNet()->getAttributeCarriers()->retrieveEdge(AC.second->getID()));1075}1076}1077// iterate over extracted edges1078for (const auto& edgeToSelect : edgesToSelect) {1079// select junction source and all connections, crossings and walkingAreas1080ACsToSelect.insert(std::make_pair(edgeToSelect->getFromJunction()->getID(), edgeToSelect->getFromJunction()));1081for (const auto& connectionToSelect : edgeToSelect->getFromJunction()->getGNEConnections()) {1082ACsToSelect.insert(std::make_pair(connectionToSelect->getID(), connectionToSelect));1083}1084for (const auto& fromCrossingToSelect : edgeToSelect->getFromJunction()->getGNECrossings()) {1085ACsToSelect.insert(std::make_pair(fromCrossingToSelect->getID(), fromCrossingToSelect));1086}1087for (const auto& fromWalkingAreaToSelect : edgeToSelect->getFromJunction()->getGNEWalkingAreas()) {1088ACsToSelect.insert(std::make_pair(fromWalkingAreaToSelect->getID(), fromWalkingAreaToSelect));1089}1090// select junction destination and all connections, crossings and walkingAreas1091ACsToSelect.insert(std::make_pair(edgeToSelect->getToJunction()->getID(), edgeToSelect->getToJunction()));1092for (const auto& connectionToSelect : edgeToSelect->getToJunction()->getGNEConnections()) {1093ACsToSelect.insert(std::make_pair(connectionToSelect->getID(), connectionToSelect));1094}1095for (const auto& toCrossingToSelect : edgeToSelect->getToJunction()->getGNECrossings()) {1096ACsToSelect.insert(std::make_pair(toCrossingToSelect->getID(), toCrossingToSelect));1097}1098for (const auto& toWalkingAreaToSelect : edgeToSelect->getToJunction()->getGNEWalkingAreas()) {1099ACsToSelect.insert(std::make_pair(toWalkingAreaToSelect->getID(), toWalkingAreaToSelect));1100}1101}1102}1103// only continue if there is ACs to select or unselect1104if ((ACsToSelect.size() + ACsToUnselect.size()) > 0) {1105// first unselect AC of ACsToUnselect and then selects AC of ACsToSelect1106myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("selection"));1107for (const auto& ACToUnselect : ACsToUnselect) {1108if (ACToUnselect.second->getTagProperty()->isSelectable()) {1109ACToUnselect.second->setAttribute(GNE_ATTR_SELECTED, "false", myViewNet->getUndoList());1110}1111}1112for (const auto& ACToSelect : ACsToSelect) {1113if (ACToSelect.second->getTagProperty()->isSelectable()) {1114ACToSelect.second->setAttribute(GNE_ATTR_SELECTED, "true", myViewNet->getUndoList());1115}1116}1117// finish operation1118myViewNet->getUndoList()->end();1119}1120}112111221123FXVerticalFrame*1124GNESelectorFrame::getContentFrame() const {1125return myContentFrame;1126}112711281129GNESelectorFrame::ModificationMode*1130GNESelectorFrame::getModificationModeModul() const {1131return myModificationMode;1132}113311341135GNESelectorFrame::SelectionOperation*1136GNESelectorFrame::getSelectionOperationModul() const {1137return mySelectionOperation;1138}113911401141GNESelectorFrame::SelectionInformation*1142GNESelectorFrame::getSelectionInformation() const {1143return mySelectionInformation;1144}11451146/****************************************************************************/114711481149