Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/frames/common/GNESelectorFrame.cpp
169684 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 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
/****************************************************************************/
14
/// @file GNESelectorFrame.cpp
15
/// @author Jakob Erdmann
16
/// @date Mar 2011
17
///
18
// The Widget for modifying selections of network-elements
19
/****************************************************************************/
20
21
#include <netedit/GNEApplicationWindow.h>
22
#include <netedit/GNENet.h>
23
#include <netedit/GNETagPropertiesDatabase.h>
24
#include <netedit/GNEUndoList.h>
25
#include <netedit/GNEViewNet.h>
26
#include <netedit/GNEViewParent.h>
27
#include <netedit/dialogs/basic/GNEErrorBasicDialog.h>
28
#include <netedit/dialogs/basic/GNEQuestionBasicDialog.h>
29
#include <netedit/elements/network/GNEConnection.h>
30
#include <netedit/elements/network/GNECrossing.h>
31
#include <netedit/elements/network/GNEWalkingArea.h>
32
#include <netedit/frames/GNEMatchAttribute.h>
33
#include <utils/foxtools/MFXDynamicLabel.h>
34
#include <utils/gui/div/GUIDesigns.h>
35
#include <utils/gui/globjects/GUIGlObjectStorage.h>
36
#include <utils/gui/windows/GUIAppEnum.h>
37
38
#include "GNESelectorFrame.h"
39
40
// ===========================================================================
41
// FOX callback mapping
42
// ===========================================================================
43
44
FXDEFMAP(GNESelectorFrame::ModificationMode) ModificationModeMap[] = {
45
FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_OPERATION, GNESelectorFrame::ModificationMode::onCmdSelectModificationMode)
46
};
47
48
FXDEFMAP(GNESelectorFrame::VisualScaling) VisualScalingMap[] = {
49
FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECTORFRAME_SELECTSCALE, GNESelectorFrame::VisualScaling::onCmdScaleSelection)
50
};
51
52
FXDEFMAP(GNESelectorFrame::SelectionOperation) SelectionOperationMap[] = {
53
FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_LOAD, GNESelectorFrame::SelectionOperation::onCmdLoad),
54
FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_SAVE, GNESelectorFrame::SelectionOperation::onCmdSave),
55
FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_INVERT, GNESelectorFrame::SelectionOperation::onCmdInvert),
56
FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_CLEAR, GNESelectorFrame::SelectionOperation::onCmdClear),
57
FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_DELETE, GNESelectorFrame::SelectionOperation::onCmdDelete),
58
FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_REDUCE, GNESelectorFrame::SelectionOperation::onCmdReduce)
59
};
60
61
FXDEFMAP(GNESelectorFrame::SelectionHierarchy) SelectionHierarchyMap[] = {
62
FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECT, GNESelectorFrame::SelectionHierarchy::onCmdSelectItem),
63
FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECTORFRAME_PARENTS, GNESelectorFrame::SelectionHierarchy::onCmdParents),
64
FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECTORFRAME_CHILDREN, GNESelectorFrame::SelectionHierarchy::onCmdChildren),
65
};
66
67
// Object implementation
68
FXIMPLEMENT(GNESelectorFrame::ModificationMode, MFXGroupBoxModule, ModificationModeMap, ARRAYNUMBER(ModificationModeMap))
69
FXIMPLEMENT(GNESelectorFrame::VisualScaling, MFXGroupBoxModule, VisualScalingMap, ARRAYNUMBER(VisualScalingMap))
70
FXIMPLEMENT(GNESelectorFrame::SelectionOperation, MFXGroupBoxModule, SelectionOperationMap, ARRAYNUMBER(SelectionOperationMap))
71
FXIMPLEMENT(GNESelectorFrame::SelectionHierarchy, MFXGroupBoxModule, SelectionHierarchyMap, ARRAYNUMBER(SelectionHierarchyMap))
72
73
// ===========================================================================
74
// method definitions
75
// ===========================================================================
76
77
// ---------------------------------------------------------------------------
78
// ModificationMode::SelectionInformation - methods
79
// ---------------------------------------------------------------------------
80
81
GNESelectorFrame::SelectionInformation::SelectionInformation(GNESelectorFrame* selectorFrameParent) :
82
MFXGroupBoxModule(selectorFrameParent, TL("Selection information")),
83
mySelectorFrameParent(selectorFrameParent) {
84
// information label
85
myInformationLabel = new FXLabel(getCollapsableFrame(), "", nullptr, GUIDesignLabelFrameInformation);
86
}
87
88
89
GNESelectorFrame::SelectionInformation::~SelectionInformation() {}
90
91
92
void
93
GNESelectorFrame::SelectionInformation::updateInformationLabel() {
94
// first clear information
95
myInformation.clear();
96
// get attribute carriers
97
const auto ACs = mySelectorFrameParent->getViewNet()->getNet()->getAttributeCarriers();
98
// continue depending of supermode
99
if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeNetwork()) {
100
updateInformationLabel(TL("Junctions"), ACs->getNumberOfSelectedJunctions());
101
updateInformationLabel(TL("Edges"), ACs->getNumberOfSelectedEdges());
102
updateInformationLabel(TL("Lanes"), ACs->getNumberOfSelectedLanes());
103
updateInformationLabel(TL("Connections"), ACs->getNumberOfSelectedConnections());
104
updateInformationLabel(TL("Crossings"), ACs->getNumberOfSelectedCrossings());
105
updateInformationLabel(TL("WalkingAreas"), ACs->getNumberOfSelectedWalkingAreas());
106
updateInformationLabel(TL("Additionals"), ACs->getNumberOfSelectedPureAdditionals());
107
updateInformationLabel(TL("Wires"), ACs->getNumberOfSelectedWires());
108
updateInformationLabel(TL("TAZs"), ACs->getNumberOfSelectedTAZs());
109
updateInformationLabel(TL("Polygons"), ACs->getNumberOfSelectedPolygons());
110
updateInformationLabel(TL("POIs"), ACs->getNumberOfSelectedPOIs());
111
updateInformationLabel(TL("JuPedSim elements"),
112
ACs->getNumberOfSelectedJpsWalkableAreas() +
113
ACs->getNumberOfSelectedJpsObstacles());
114
} else if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
115
updateInformationLabel(TL("Routes"), ACs->getNumberOfSelectedRoutes());
116
updateInformationLabel(TL("Vehicles"), ACs->getNumberOfSelectedVehicles());
117
updateInformationLabel(TL("Persons"), ACs->getNumberOfSelectedPersons());
118
updateInformationLabel(TL("Person trips"), ACs->getNumberOfSelectedPersonTrips());
119
updateInformationLabel(TL("Walks"), ACs->getNumberOfSelectedWalks());
120
updateInformationLabel(TL("Rides"), ACs->getNumberOfSelectedRides());
121
updateInformationLabel(TL("Containers"), ACs->getNumberOfSelectedContainers());
122
updateInformationLabel(TL("Transport"), ACs->getNumberOfSelectedTransport());
123
updateInformationLabel(TL("Tranships"), ACs->getNumberOfSelectedTranships());
124
updateInformationLabel(TL("Stops"), ACs->getNumberOfSelectedStops());
125
} else if (mySelectorFrameParent->getViewNet()->getEditModes().isCurrentSupermodeData()) {
126
updateInformationLabel(TL("EdgeDatas"), ACs->getNumberOfSelectedEdgeDatas());
127
updateInformationLabel(TL("EdgeRelDatas"), ACs->getNumberOfSelectedEdgeRelDatas());
128
updateInformationLabel(TL("EdgeTAZRel"), ACs->getNumberOfSelectedEdgeTAZRel());
129
}
130
// adjust format
131
const auto numberLines = std::count(myInformation.begin(), myInformation.end(), ':');
132
if (numberLines == 0) {
133
myInformation.append(" \n \n");
134
} else if (numberLines > 1) {
135
myInformation.pop_back();
136
}
137
// set label
138
myInformationLabel->setText(myInformation.c_str());
139
}
140
141
142
void
143
GNESelectorFrame::SelectionInformation::updateInformationLabel(const std::string& element, int number) {
144
// check number
145
if (number > 0) {
146
myInformation.append(element + ": " + toString(number) + "\n");
147
}
148
}
149
150
// ---------------------------------------------------------------------------
151
// ModificationMode::ModificationMode - methods
152
// ---------------------------------------------------------------------------
153
154
GNESelectorFrame::ModificationMode::ModificationMode(GNESelectorFrame* selectorFrameParent) :
155
MFXGroupBoxModule(selectorFrameParent, TL("Modification Mode")),
156
myModificationModeType(Operation::ADD) {
157
// Create all options buttons
158
myAddRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("add"), "", TL("Selected objects are added to the previous selection"),
159
this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);
160
myRemoveRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("remove"), "", TL("Selected objects are removed from the previous selection"),
161
this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);
162
myKeepRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("keep"), "", TL("Restrict previous selection by the current selection"),
163
this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);
164
myReplaceRadioButton = GUIDesigns::buildFXRadioButton(getCollapsableFrame(), TL("replace"), "", TL("Replace previous selection by the current selection"),
165
this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);
166
myAddRadioButton->setCheck(true);
167
}
168
169
170
GNESelectorFrame::ModificationMode::~ModificationMode() {}
171
172
173
GNESelectorFrame::ModificationMode::Operation
174
GNESelectorFrame::ModificationMode::getModificationMode() const {
175
return myModificationModeType;
176
}
177
178
179
long
180
GNESelectorFrame::ModificationMode::onCmdSelectModificationMode(FXObject* obj, FXSelector, void*) {
181
if (obj == myAddRadioButton) {
182
myModificationModeType = Operation::ADD;
183
myAddRadioButton->setCheck(true);
184
myRemoveRadioButton->setCheck(false);
185
myKeepRadioButton->setCheck(false);
186
myReplaceRadioButton->setCheck(false);
187
return 1;
188
} else if (obj == myRemoveRadioButton) {
189
myModificationModeType = Operation::SUB;
190
myAddRadioButton->setCheck(false);
191
myRemoveRadioButton->setCheck(true);
192
myKeepRadioButton->setCheck(false);
193
myReplaceRadioButton->setCheck(false);
194
return 1;
195
} else if (obj == myKeepRadioButton) {
196
myModificationModeType = Operation::RESTRICT;
197
myAddRadioButton->setCheck(false);
198
myRemoveRadioButton->setCheck(false);
199
myKeepRadioButton->setCheck(true);
200
myReplaceRadioButton->setCheck(false);
201
return 1;
202
} else if (obj == myReplaceRadioButton) {
203
myModificationModeType = Operation::REPLACE;
204
myAddRadioButton->setCheck(false);
205
myRemoveRadioButton->setCheck(false);
206
myKeepRadioButton->setCheck(false);
207
myReplaceRadioButton->setCheck(true);
208
return 1;
209
} else {
210
return 0;
211
}
212
}
213
214
// ---------------------------------------------------------------------------
215
// ModificationMode::VisualScaling - methods
216
// ---------------------------------------------------------------------------
217
218
GNESelectorFrame::VisualScaling::VisualScaling(GNESelectorFrame* selectorFrameParent) :
219
MFXGroupBoxModule(selectorFrameParent, TL("Visual Scaling")),
220
mySelectorFrameParent(selectorFrameParent) {
221
// Create spin button and configure it
222
mySelectionScaling = new FXRealSpinner(getCollapsableFrame(), 7, this, MID_GNE_SELECTORFRAME_SELECTSCALE, GUIDesignSpinDial);
223
//mySelectionScaling->setNumberFormat(1);
224
//mySelectionScaling->setIncrements(0.1, .5, 1);
225
mySelectionScaling->setIncrement(0.5);
226
mySelectionScaling->setRange(1, 100000);
227
mySelectionScaling->setValue(1);
228
mySelectionScaling->setHelpText(TL("Enlarge selected objects"));
229
}
230
231
232
GNESelectorFrame::VisualScaling::~VisualScaling() {}
233
234
235
long
236
GNESelectorFrame::VisualScaling::onCmdScaleSelection(FXObject*, FXSelector, void*) {
237
// set scale in viewnet
238
mySelectorFrameParent->myViewNet->setSelectorFrameScale(mySelectionScaling->getValue());
239
mySelectorFrameParent->myViewNet->updateViewNet();
240
return 1;
241
}
242
243
// ---------------------------------------------------------------------------
244
// ModificationMode::SelectionHierarchy - methods
245
// ---------------------------------------------------------------------------
246
247
GNESelectorFrame::SelectionOperation::SelectionOperation(GNESelectorFrame* selectorFrameParent) :
248
MFXGroupBoxModule(selectorFrameParent, TL("Selection operations")),
249
mySelectorFrameParent(selectorFrameParent) {
250
// tabular buttons, see GNETLSEditorFrame
251
252
FXHorizontalFrame* selectionButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
253
FXVerticalFrame* col1 = new FXVerticalFrame(selectionButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // left button columm
254
FXVerticalFrame* col2 = new FXVerticalFrame(selectionButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // right button column
255
256
// Create "Clear List" Button
257
GUIDesigns::buildFXButton(col1, TL("Clear"), "", TL("Deselect all objects (hotkey: ESC)"), nullptr, this, MID_CHOOSEN_CLEAR, GUIDesignButton);
258
// Create "Invert" Button
259
GUIDesigns::buildFXButton(col2, TL("Invert"), "", TL("Invert selection status of all objects"), nullptr, this, MID_CHOOSEN_INVERT, GUIDesignButton);
260
// Create "Save" Button
261
GUIDesigns::buildFXButton(col1, TL("Save"), "", TL("Save ids of currently selected objects to a file."), nullptr, this, MID_CHOOSEN_SAVE, GUIDesignButton);
262
// Create "Load" Button
263
GUIDesigns::buildFXButton(col2, TL("Load"), "", TL("Load ids from a file according to the current modification mode."), nullptr, this, MID_CHOOSEN_LOAD, GUIDesignButton);
264
// Create "Delete" Button
265
GUIDesigns::buildFXButton(col1, TL("Delete"), "", TL("Delete all selected objects (hotkey: DEL)"), nullptr, this, MID_CHOOSEN_DELETE, GUIDesignButton);
266
// Create "reduce" Button
267
GUIDesigns::buildFXButton(col2, TL("Reduce"), "", TL("Reduce network to current selection."), nullptr, this, MID_CHOOSEN_REDUCE, GUIDesignButton);
268
}
269
270
271
GNESelectorFrame::SelectionOperation::~SelectionOperation() {}
272
273
274
void
275
GNESelectorFrame::SelectionOperation::loadFromFile(const std::string& file) const {
276
std::vector<GNEAttributeCarrier*> loadedACs;
277
std::ifstream strm(file.c_str());
278
// check if file can be opened
279
if (!strm.good()) {
280
WRITE_ERRORF(TL("Could not open '%'."), file);
281
} else {
282
// convert all glObjects into GNEAttributeCarriers
283
std::map<const std::string, GNEAttributeCarrier*> GLFUllNameAC;
284
const auto GLObjects = GUIGlObjectStorage::gIDStorage.getAllGLObjects();
285
for (const auto& GLObject : GLObjects) {
286
// try to parse GLObject to AC
287
GNEAttributeCarrier* AC = dynamic_cast<GNEAttributeCarrier*>(GLObject);
288
// if was successfully parsed and is NOT a template, add into GLFUllNameAC using fullName
289
if (AC && !AC->isTemplate()) {
290
GLFUllNameAC[GUIGlObject::TypeNames.getString(GLObject->getType()) + ":" + AC->getID()] = AC;
291
}
292
}
293
// continue while stream exist
294
while (strm.good()) {
295
std::string line;
296
strm >> line;
297
// check if line isn't empty
298
if (line.length() != 0) {
299
// obtain AC from GLFUllNameAC
300
if (StringUtils::startsWith(line, "node:")) {
301
line = StringUtils::replace(line, "node:", "junction:");
302
}
303
GNEAttributeCarrier* AC = GLFUllNameAC.count(line) > 0 ? GLFUllNameAC.at(line) : nullptr;
304
// check if AC exist, is selectable, and isn't locked
305
if (AC && AC->getTagProperty()->isSelectable() && !mySelectorFrameParent->getViewNet()->getLockManager().isObjectLocked(AC->getGUIGlObject()->getType(), false)) {
306
// now check if we're in the correct supermode to load this element
307
if (((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeNetwork()) && !AC->getTagProperty()->isDemandElement()) ||
308
((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeDemand()) && AC->getTagProperty()->isDemandElement()) ||
309
((mySelectorFrameParent->myViewNet->getEditModes().isCurrentSupermodeData()) && AC->getTagProperty()->isDataElement())) {
310
loadedACs.push_back(AC);
311
}
312
}
313
}
314
}
315
// change selected attribute in loaded ACs allowing undo/redo
316
if (loadedACs.size() > 0) {
317
mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("load selection"));
318
mySelectorFrameParent->handleIDs(loadedACs);
319
mySelectorFrameParent->myViewNet->getUndoList()->end();
320
}
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(SUMOXMLDefinitions::TXTFileExtensions.getMultilineString().c_str());
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, TL("Save List of selected Items"),
346
SUMOXMLDefinitions::TXTFileExtensions.getMultilineString().c_str(),
347
GUIIconSubSys::getIcon(GUIIcon::SAVE), gCurrentFolder);
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
// open message box error
364
GNEErrorBasicDialog(mySelectorFrameParent->getViewNet()->getViewParent()->getGNEAppWindows(),
365
TL("Storing Selection failed"), e.what());
366
}
367
return 1;
368
}
369
370
371
long
372
GNESelectorFrame::SelectionOperation::onCmdClear(FXObject*, FXSelector, void*) {
373
const auto& editModes = mySelectorFrameParent->myViewNet->getEditModes();
374
GNEUndoList* undoList = mySelectorFrameParent->myViewNet->getUndoList();
375
// declare massive selection
376
MassiveSelection massiveSelection =
377
editModes.isCurrentSupermodeNetwork() ? processMassiveNetworkElementSelection(false) :
378
editModes.isCurrentSupermodeDemand() ? processMassiveDemandElementSelection() :
379
processMassiveDataElementSelection();
380
// only continue if there are elements to unselect
381
if (massiveSelection.isElementToProcess()) {
382
// check if add locked elements
383
bool askedContinueIfLock = false;
384
bool addLockedElements = false;
385
bool unlockedElements = false;
386
for (const auto& ACToUnselect : massiveSelection.ACsToUnselect) {
387
if (ACToUnselect.second == false) {
388
// there are unlocked elements
389
unlockedElements = true;
390
} else if (!askedContinueIfLock) {
391
addLockedElements = askContinueIfLock();
392
// only ask one time for locking
393
askedContinueIfLock = true;
394
}
395
}
396
if (unlockedElements || addLockedElements) {
397
mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("clear selection"));
398
for (const auto& ACToUnselect : massiveSelection.ACsToUnselect) {
399
if (addLockedElements || !ACToUnselect.second) {
400
ACToUnselect.first->setAttribute(GNE_ATTR_SELECTED, "false", undoList);
401
}
402
}
403
mySelectorFrameParent->myViewNet->getUndoList()->end();
404
}
405
}
406
mySelectorFrameParent->myViewNet->updateViewNet();
407
return 1;
408
}
409
410
long
411
GNESelectorFrame::SelectionOperation::onCmdDelete(FXObject*, FXSelector, void*) {
412
// acts like the 'del' hotkey
413
mySelectorFrameParent->getViewNet()->hotkeyDel();
414
return 1;
415
}
416
417
418
long
419
GNESelectorFrame::SelectionOperation::onCmdInvert(FXObject*, FXSelector, void*) {
420
const auto& editModes = mySelectorFrameParent->myViewNet->getEditModes();
421
GNEUndoList* undoList = mySelectorFrameParent->myViewNet->getUndoList();
422
// declare massive selection
423
MassiveSelection massiveSelection =
424
editModes.isCurrentSupermodeNetwork() ? processMassiveNetworkElementSelection(true) :
425
editModes.isCurrentSupermodeDemand() ? processMassiveDemandElementSelection() :
426
processMassiveDataElementSelection();
427
// only continue if there are elements to select and unselect
428
if (massiveSelection.isElementToProcess()) {
429
// check if add locked elements
430
bool askedContinueIfLock = false;
431
bool addLockedElements = false;
432
bool unlockedElements = false;
433
for (const auto& ACToSelect : massiveSelection.ACsToSelect) {
434
if (ACToSelect.second == false) {
435
// there are unlocked elements
436
unlockedElements = true;
437
} else if (!askedContinueIfLock) {
438
addLockedElements = askContinueIfLock();
439
// only ask one time for locking
440
askedContinueIfLock = true;
441
}
442
}
443
for (const auto& ACToUnselect : massiveSelection.ACsToUnselect) {
444
if (ACToUnselect.second == 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
if (unlockedElements || addLockedElements) {
454
mySelectorFrameParent->myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("invert selection"));
455
for (const auto& ACToSelect : massiveSelection.ACsToSelect) {
456
if (addLockedElements || !ACToSelect.second) {
457
ACToSelect.first->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
458
}
459
}
460
for (const auto& ACToUnselect : massiveSelection.ACsToUnselect) {
461
if (addLockedElements || !ACToUnselect.second) {
462
ACToUnselect.first->setAttribute(GNE_ATTR_SELECTED, "false", undoList);
463
}
464
}
465
mySelectorFrameParent->myViewNet->getUndoList()->end();
466
}
467
}
468
return 1;
469
}
470
471
472
long
473
GNESelectorFrame::SelectionOperation::onCmdReduce(FXObject*, FXSelector, void*) {
474
// begin undoList operation
475
mySelectorFrameParent->getViewNet()->getUndoList()->begin(Supermode::NETWORK, GUIIcon::SIMPLIFYNETWORK, TL("reduce network"));
476
// invert and clear
477
onCmdInvert(0, 0, 0);
478
onCmdDelete(0, 0, 0);
479
// end undoList operation
480
mySelectorFrameParent->getViewNet()->getUndoList()->end();
481
return 1;
482
}
483
484
485
GNESelectorFrame::SelectionOperation::MassiveSelection
486
GNESelectorFrame::SelectionOperation::processMassiveNetworkElementSelection(const bool filterLanes) const {
487
const auto& ACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers();
488
const bool selectEdges = mySelectorFrameParent->getViewNet()->getNetworkViewOptions().selectEdges();
489
// extract all network elements
490
std::unordered_set<GNEAttributeCarrier*> networkACs;
491
// add junctions
492
for (const auto& junction : ACs->getJunctions()) {
493
networkACs.insert(junction.second);
494
// due we iterate over all junctions, only it's necessary iterate over incoming edges
495
for (const auto& incomingEdge : junction.second->getGNEIncomingEdges()) {
496
if (!filterLanes || selectEdges) {
497
networkACs.insert(incomingEdge);
498
}
499
// add lanes
500
if (!filterLanes || !selectEdges) {
501
for (const auto& lane : incomingEdge->getChildLanes()) {
502
networkACs.insert(lane);
503
}
504
}
505
// add connections
506
for (const auto& connection : incomingEdge->getGNEConnections()) {
507
networkACs.insert(connection);
508
}
509
}
510
// add crossings
511
for (const auto& crossing : junction.second->getGNECrossings()) {
512
networkACs.insert(crossing);
513
}
514
// add walkingArea
515
for (const auto& walkingArea : junction.second->getGNEWalkingAreas()) {
516
networkACs.insert(walkingArea);
517
}
518
}
519
// add additionals
520
for (const auto& additionalTags : ACs->getAdditionals()) {
521
for (const auto& additional : additionalTags.second) {
522
if (additional.second->getTagProperty()->isSelectable()) {
523
networkACs.insert(additional.second);
524
}
525
}
526
}
527
// declare massive selection
528
GNESelectorFrame::SelectionOperation::MassiveSelection massiveSelection(ACs->getNumberOfNetworkElements());
529
// iterate over network ACs
530
for (const auto& networkAC : networkACs) {
531
const auto networkACObjectType = networkAC->getGUIGlObject()->getType();
532
// save locking status in lockedTypes
533
if (massiveSelection.lockedTypes.find(networkACObjectType) == massiveSelection.lockedTypes.end()) {
534
massiveSelection.lockedTypes[networkACObjectType] = networkAC->getGUIGlObject()->isGLObjectLocked();
535
}
536
// save element and their locking status
537
if (networkAC->isAttributeCarrierSelected()) {
538
massiveSelection.ACsToUnselect[networkAC] = massiveSelection.lockedTypes.at(networkACObjectType);
539
} else {
540
massiveSelection.ACsToSelect[networkAC] = massiveSelection.lockedTypes.at(networkACObjectType);
541
}
542
}
543
return massiveSelection;
544
}
545
546
547
GNESelectorFrame::SelectionOperation::MassiveSelection
548
GNESelectorFrame::SelectionOperation::processMassiveDemandElementSelection() const {
549
const auto& ACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers();
550
// declare massive selection
551
GNESelectorFrame::SelectionOperation::MassiveSelection massiveSelection(ACs->getNumberOfDemandElements());
552
// iterate over selectable demand elements
553
for (const auto& demandElementTag : ACs->getDemandElements()) {
554
for (const auto& demandElement : demandElementTag.second) {
555
if (demandElement.second->getTagProperty()->isSelectable()) {
556
const auto networkACObjectType = demandElement.first->getType();
557
// save locking status in lockedTypes
558
if (massiveSelection.lockedTypes.find(networkACObjectType) == massiveSelection.lockedTypes.end()) {
559
massiveSelection.lockedTypes[networkACObjectType] = demandElement.first->isGLObjectLocked();
560
}
561
// save element and their locking status
562
if (demandElement.second->isAttributeCarrierSelected()) {
563
massiveSelection.ACsToUnselect[demandElement.second] = massiveSelection.lockedTypes.at(networkACObjectType);
564
} else {
565
massiveSelection.ACsToSelect[demandElement.second] = massiveSelection.lockedTypes.at(networkACObjectType);
566
}
567
}
568
}
569
}
570
return massiveSelection;
571
}
572
573
574
GNESelectorFrame::SelectionOperation::MassiveSelection
575
GNESelectorFrame::SelectionOperation::processMassiveDataElementSelection() const {
576
const auto& ACs = mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers();
577
// declare massive selection
578
GNESelectorFrame::SelectionOperation::MassiveSelection massiveSelection(ACs->getNumberOfDataElements());
579
// iterate over selectable demand elements
580
for (const auto& genericDataTag : mySelectorFrameParent->myViewNet->getNet()->getAttributeCarriers()->getGenericDatas()) {
581
for (const auto& genericData : genericDataTag.second) {
582
if (genericData.second->getTagProperty()->isSelectable()) {
583
const auto networkACObjectType = genericData.first->getType();
584
// save locking status in lockedTypes
585
if (massiveSelection.lockedTypes.find(networkACObjectType) == massiveSelection.lockedTypes.end()) {
586
massiveSelection.lockedTypes[networkACObjectType] = genericData.first->isGLObjectLocked();
587
}
588
// save element and their locking status
589
if (genericData.second->isAttributeCarrierSelected()) {
590
massiveSelection.ACsToUnselect[genericData.second] = massiveSelection.lockedTypes.at(networkACObjectType);
591
} else {
592
massiveSelection.ACsToSelect[genericData.second] = massiveSelection.lockedTypes.at(networkACObjectType);
593
}
594
}
595
}
596
}
597
return massiveSelection;
598
}
599
600
601
bool
602
GNESelectorFrame::SelectionOperation::askContinueIfLock() const {
603
// open question dialog box
604
const auto questionDialog = GNEQuestionBasicDialog(mySelectorFrameParent->getViewNet()->getViewParent()->getGNEAppWindows(),
605
GNEDialog::Buttons::YES_NO,
606
TL("Confirm selection operation"),
607
TL("There are locked elements in the current selection."),
608
TL("Apply operation to locked elements?"));
609
// check result
610
return (questionDialog.getResult() == GNEDialog::Result::ACCEPT);
611
}
612
613
// ---------------------------------------------------------------------------
614
// ModificationMode::SelectionOperation::SelectionHierarchy - methods
615
// ---------------------------------------------------------------------------
616
617
GNESelectorFrame::SelectionOperation::MassiveSelection::MassiveSelection(const int bucketSize) {
618
ACsToSelect.reserve(bucketSize);
619
ACsToUnselect.reserve(bucketSize);
620
}
621
622
623
GNESelectorFrame::SelectionOperation::MassiveSelection::~MassiveSelection() {}
624
625
626
inline bool GNESelectorFrame::SelectionOperation::MassiveSelection::isElementToProcess() const {
627
return (ACsToSelect.size() + ACsToUnselect.size()) > 0;
628
}
629
630
631
GNESelectorFrame::SelectionOperation::MassiveSelection::MassiveSelection() {}
632
633
// ---------------------------------------------------------------------------
634
// ModificationMode::SelectionHierarchy - methods
635
// ---------------------------------------------------------------------------
636
637
GNESelectorFrame::SelectionHierarchy::SelectionHierarchy(GNESelectorFrame* selectorFrameParent) :
638
MFXGroupBoxModule(selectorFrameParent, TL("Hierarchy operations")),
639
mySelectorFrameParent(selectorFrameParent),
640
myCurrentSelectedParent(Selection::ALL),
641
myCurrentSelectedChild(Selection::ALL) {
642
const auto staticTooltipMenu = selectorFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();
643
// create label for parents
644
new FXLabel(getCollapsableFrame(), TL("Select parents"), nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL));
645
// Create MFXComboBoxIcon for parent comboBox
646
myParentsComboBox = new MFXComboBoxIcon(getCollapsableFrame(), staticTooltipMenu, true, GUIDesignComboBoxVisibleItems,
647
this, MID_GNE_SELECT, GUIDesignComboBox);
648
// create parent buttons
649
FXHorizontalFrame* parentButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
650
// Create "select" Button
651
mySelectParentsButton = GUIDesigns::buildFXButton(parentButtons, TL("Select"), "", "", GUIIconSubSys::getIcon(GUIIcon::SELECT), this, MID_GNE_SELECTORFRAME_PARENTS, GUIDesignButton);
652
// Create "unselect" Button
653
myUnselectParentsButton = GUIDesigns::buildFXButton(parentButtons, TL("Unselect"), "", "", GUIIconSubSys::getIcon(GUIIcon::UNSELECT), this, MID_GNE_SELECTORFRAME_PARENTS, GUIDesignButton);
654
// create label for parents
655
new FXLabel(getCollapsableFrame(), TL("Select children"), nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL));
656
// Create MFXComboBoxIcon for parent comboBox
657
myChildrenComboBox = new MFXComboBoxIcon(getCollapsableFrame(), staticTooltipMenu, true, GUIDesignComboBoxVisibleItems,
658
this, MID_GNE_SELECT, GUIDesignComboBox);
659
// create children buttons
660
FXHorizontalFrame* childrenButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
661
// Create "select" Button
662
mySelectChildrenButton = GUIDesigns::buildFXButton(childrenButtons, TL("Select"), "", "", GUIIconSubSys::getIcon(GUIIcon::SELECT), this, MID_GNE_SELECTORFRAME_CHILDREN, GUIDesignButton);
663
// Create "unselect" Button
664
myUnselectChildrenButton = GUIDesigns::buildFXButton(childrenButtons, TL("Unselect"), "", "", GUIIconSubSys::getIcon(GUIIcon::UNSELECT), this, MID_GNE_SELECTORFRAME_CHILDREN, GUIDesignButton);
665
// fill comboBoxes
666
for (const auto& item : myItems) {
667
myParentsComboBox->appendIconItem(item.second.c_str());
668
myChildrenComboBox->appendIconItem(item.second.c_str());
669
}
670
}
671
672
673
GNESelectorFrame::SelectionHierarchy::~SelectionHierarchy() {}
674
675
676
long
677
GNESelectorFrame::SelectionHierarchy::onCmdSelectItem(FXObject* obj, FXSelector, void*) {
678
if (obj == myParentsComboBox) {
679
for (const auto& item : myItems) {
680
if (item.second == myParentsComboBox->getText().text()) {
681
// enable buttons
682
mySelectParentsButton->enable();
683
myUnselectParentsButton->enable();
684
// change text color
685
myParentsComboBox->setTextColor(GUIDesignTextColorBlack);
686
// set current selected parent
687
myCurrentSelectedParent = item.first;
688
return 1;
689
}
690
}
691
// item not found
692
myCurrentSelectedParent = Selection::NOTHING;
693
// disable buttons
694
mySelectParentsButton->disable();
695
myUnselectParentsButton->disable();
696
myParentsComboBox->setTextColor(GUIDesignTextColorRed);
697
return 1;
698
} else if (obj == myChildrenComboBox) {
699
for (const auto& item : myItems) {
700
if (item.second == myChildrenComboBox->getText().text()) {
701
// enable buttons
702
mySelectChildrenButton->enable();
703
myUnselectChildrenButton->enable();
704
// change text color
705
myChildrenComboBox->setTextColor(GUIDesignTextColorBlack);
706
// set current selected parent
707
myCurrentSelectedChild = item.first;
708
return 1;
709
}
710
}
711
// item not found
712
myCurrentSelectedChild = Selection::NOTHING;
713
// disable buttons
714
mySelectChildrenButton->disable();
715
myUnselectChildrenButton->disable();
716
myChildrenComboBox->setTextColor(GUIDesignTextColorRed);
717
return 1;
718
}
719
return 0;
720
}
721
722
723
long
724
GNESelectorFrame::SelectionHierarchy::onCmdParents(FXObject* obj, FXSelector, void*) {
725
const auto viewNet = mySelectorFrameParent->getViewNet();
726
// get selected elements
727
const auto selectedACs = viewNet->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(true);
728
// check if there is selected ACs
729
if ((selectedACs.size() > 0) && (myCurrentSelectedParent != Selection::NOTHING)) {
730
// vector of of element to select or unselect
731
std::vector<GNEAttributeCarrier*> editedParents;
732
for (const auto& selectedAC : selectedACs) {
733
if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_CONNECTION) {
734
const auto connection = viewNet->getNet()->getAttributeCarriers()->retrieveConnection(selectedAC->getGUIGlObject());
735
editedParents.push_back(connection->getLaneFrom());
736
editedParents.push_back(connection->getLaneTo());
737
} else if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_CROSSING) {
738
const auto crossing = viewNet->getNet()->getAttributeCarriers()->retrieveCrossing(selectedAC->getGUIGlObject());
739
editedParents.push_back(crossing->getParentJunctions().front());
740
} else {
741
// get hierarchical element
742
const auto hierarchicalElement = selectedAC->getHierarchicalElement();
743
// get parent junctions
744
if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::JUNCTION)) {
745
editedParents.insert(editedParents.end(), hierarchicalElement->getParentJunctions().begin(), hierarchicalElement->getParentJunctions().end());
746
}
747
// get parent edges
748
if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::EDGE)) {
749
if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_LANE) {
750
// special case for lanes
751
editedParents.push_back(dynamic_cast<GNELane*>(selectedAC)->getParentEdge());
752
} else {
753
editedParents.insert(editedParents.end(), hierarchicalElement->getParentEdges().begin(), hierarchicalElement->getParentEdges().end());
754
}
755
}
756
// get parent lanes
757
if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::LANE)) {
758
editedParents.insert(editedParents.end(), hierarchicalElement->getParentLanes().begin(), hierarchicalElement->getParentLanes().end());
759
}
760
// get parent additional
761
if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::ADDITIONAL)) {
762
editedParents.insert(editedParents.end(), hierarchicalElement->getParentAdditionals().begin(), hierarchicalElement->getParentAdditionals().end());
763
}
764
// get parent wire
765
if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::WIRE)) {
766
editedParents.insert(editedParents.end(), hierarchicalElement->getParentAdditionals().begin(), hierarchicalElement->getParentAdditionals().end());
767
}
768
// get parent demand
769
if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::DEMAND)) {
770
editedParents.insert(editedParents.end(), hierarchicalElement->getParentDemandElements().begin(), hierarchicalElement->getParentDemandElements().end());
771
}
772
// get parent data
773
if ((myCurrentSelectedParent == Selection::ALL) || (myCurrentSelectedParent == Selection::DATA)) {
774
editedParents.insert(editedParents.end(), hierarchicalElement->getParentGenericDatas().begin(), hierarchicalElement->getParentGenericDatas().end());
775
}
776
}
777
}
778
// select HE
779
if (editedParents.size() > 0) {
780
if (editedParents.size() > 1) {
781
viewNet->getUndoList()->begin(GUIIcon::SELECT, TL("select parents"));
782
}
783
for (const auto& HE : editedParents) {
784
if (obj == mySelectParentsButton) {
785
HE->setAttribute(GNE_ATTR_SELECTED, "true", viewNet->getUndoList());
786
} else {
787
HE->setAttribute(GNE_ATTR_SELECTED, "false", viewNet->getUndoList());
788
}
789
}
790
if (editedParents.size() > 1) {
791
viewNet->getUndoList()->end();
792
}
793
}
794
// update information label
795
mySelectorFrameParent->mySelectionInformation->updateInformationLabel();
796
// update viewNet
797
viewNet->update();
798
}
799
return 1;
800
}
801
802
803
long
804
GNESelectorFrame::SelectionHierarchy::onCmdChildren(FXObject* obj, FXSelector, void*) {
805
// get selected elements
806
const auto selectedACs = mySelectorFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(true);
807
// check if there is selected ACs
808
if ((selectedACs.size() > 0) && (myCurrentSelectedChild != Selection::NOTHING)) {
809
// vector of of element to select or unselect
810
std::vector<GNEAttributeCarrier*> editedChildren;
811
for (const auto& selectedAC : selectedACs) {
812
// get hierarchical element
813
const auto hierarchicalElement = selectedAC->getHierarchicalElement();
814
// junctions
815
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::JUNCTION)) {
816
if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_JUNCTION) {
817
// special case for junction
818
const auto junction = dynamic_cast<GNEJunction*>(selectedAC);
819
// insert edges
820
editedChildren.insert(editedChildren.end(), junction->getGNEIncomingEdges().begin(), junction->getGNEIncomingEdges().end());
821
editedChildren.insert(editedChildren.end(), junction->getGNEOutgoingEdges().begin(), junction->getGNEOutgoingEdges().end());
822
} else {
823
editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildJunctions().begin(), hierarchicalElement->getChildJunctions().end());
824
}
825
}
826
// edges
827
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::EDGE)) {
828
if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_EDGE) {
829
// special case for edges
830
const auto edge = dynamic_cast<GNEEdge*>(selectedAC);
831
// insert lanes
832
editedChildren.insert(editedChildren.end(), edge->getChildLanes().begin(), edge->getChildLanes().end());
833
} else {
834
editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildEdges().begin(), hierarchicalElement->getChildEdges().end());
835
}
836
}
837
// connections
838
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::CONNECTION)) {
839
if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_EDGE) {
840
// case for edges
841
const auto edge = dynamic_cast<GNEEdge*>(selectedAC);
842
// insert connections
843
editedChildren.insert(editedChildren.end(), edge->getGNEConnections().begin(), edge->getGNEConnections().end());
844
} else if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_LANE) {
845
// case for lanes
846
const auto lane = dynamic_cast<GNELane*>(selectedAC);
847
// insert connections
848
for (const auto& connection : lane->getParentEdge()->getGNEConnections()) {
849
if (connection->getAttribute(SUMO_ATTR_FROM_LANE) == lane->getAttribute(SUMO_ATTR_INDEX)) {
850
editedChildren.push_back(connection);
851
}
852
}
853
} else if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_JUNCTION) {
854
// case for junction
855
const auto junction = dynamic_cast<GNEJunction*>(selectedAC);
856
// get connections
857
const auto connections = junction->getGNEConnections();
858
// insert connections
859
editedChildren.insert(editedChildren.end(), connections.begin(), connections.end());
860
}
861
}
862
// crossings
863
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::CROSSING)) {
864
if (selectedAC->getTagProperty()->getTag() == SUMO_TAG_JUNCTION) {
865
// case for junction
866
const auto junction = dynamic_cast<GNEJunction*>(selectedAC);
867
// insert crossings
868
editedChildren.insert(editedChildren.end(), junction->getGNECrossings().begin(), junction->getGNECrossings().end());
869
}
870
}
871
// lanes
872
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::LANE)) {
873
editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildLanes().begin(), hierarchicalElement->getChildLanes().end());
874
}
875
// additional
876
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::ADDITIONAL)) {
877
// avoid insert symbols
878
for (const auto& additionalChild : hierarchicalElement->getChildAdditionals()) {
879
if (!additionalChild->getTagProperty()->isWireElement() && !additionalChild->getTagProperty()->isSymbol()) {
880
editedChildren.push_back(additionalChild);
881
}
882
}
883
}
884
// wire
885
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::WIRE)) {
886
// avoid insert symbols
887
for (const auto& wireChild : hierarchicalElement->getChildAdditionals()) {
888
if (wireChild->getTagProperty()->isWireElement() && !wireChild->getTagProperty()->isSymbol()) {
889
editedChildren.push_back(wireChild);
890
}
891
}
892
}
893
// demand
894
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::DEMAND)) {
895
editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildDemandElements().begin(), hierarchicalElement->getChildDemandElements().end());
896
}
897
// data
898
if ((myCurrentSelectedChild == Selection::ALL) || (myCurrentSelectedChild == Selection::DATA)) {
899
editedChildren.insert(editedChildren.end(), hierarchicalElement->getChildGenericDatas().begin(), hierarchicalElement->getChildGenericDatas().end());
900
}
901
}
902
// select HE
903
if (editedChildren.size() > 0) {
904
if (editedChildren.size() > 1) {
905
mySelectorFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::SELECT, TL("select children"));
906
}
907
for (const auto& HE : editedChildren) {
908
if (obj == mySelectChildrenButton) {
909
HE->setAttribute(GNE_ATTR_SELECTED, "true", mySelectorFrameParent->getViewNet()->getUndoList());
910
} else {
911
HE->setAttribute(GNE_ATTR_SELECTED, "false", mySelectorFrameParent->getViewNet()->getUndoList());
912
}
913
}
914
if (editedChildren.size() > 1) {
915
mySelectorFrameParent->getViewNet()->getUndoList()->end();
916
}
917
}
918
// update information label
919
mySelectorFrameParent->mySelectionInformation->updateInformationLabel();
920
// update viewNet
921
mySelectorFrameParent->getViewNet()->update();
922
}
923
return 1;
924
}
925
926
// ---------------------------------------------------------------------------
927
// GNECrossingFrame::Legend - methods
928
// ---------------------------------------------------------------------------
929
930
GNESelectorFrame::Information::Information(GNESelectorFrame* selectorFrameParent) :
931
MFXGroupBoxModule(selectorFrameParent, TL("Information")) {
932
// Create Selection Hint
933
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);
934
}
935
936
937
GNESelectorFrame::Information::~Information() {}
938
939
// ---------------------------------------------------------------------------
940
// GNESelectorFrame - methods
941
// ---------------------------------------------------------------------------
942
943
GNESelectorFrame::GNESelectorFrame(GNEViewParent* viewParent, GNEViewNet* viewNet) :
944
GNEFrame(viewParent, viewNet, TL("Selection")) {
945
// create selection information
946
mySelectionInformation = new SelectionInformation(this);
947
// create Modification Mode modul
948
myModificationMode = new ModificationMode(this);
949
// create ElementSet modul
950
myMatchAttribute = new GNEMatchAttribute(this);
951
// create VisualScaling modul
952
myVisualScaling = new VisualScaling(this);
953
// create SelectionOperation modul
954
mySelectionOperation = new SelectionOperation(this);
955
// create SelectionHierarchy modul
956
mySelectionHierarchy = new SelectionHierarchy(this);
957
// create Information modul
958
myInformation = new Information(this);
959
}
960
961
962
GNESelectorFrame::~GNESelectorFrame() {}
963
964
965
void
966
GNESelectorFrame::show() {
967
myMatchAttribute->showMatchAttribute();
968
// update information label
969
mySelectionInformation->updateInformationLabel();
970
// Show frame
971
GNEFrame::show();
972
}
973
974
975
void
976
GNESelectorFrame::hide() {
977
// hide frame
978
GNEFrame::hide();
979
}
980
981
982
void
983
GNESelectorFrame::updateFrameAfterUndoRedo() {
984
// update information label
985
mySelectionInformation->updateInformationLabel();
986
}
987
988
989
void
990
GNESelectorFrame::clearCurrentSelection() const {
991
mySelectionOperation->onCmdClear(nullptr, 0, nullptr);
992
}
993
994
995
bool
996
GNESelectorFrame::selectAttributeCarrier(const GNEViewNetHelper::ViewObjectsSelector& viewObjects) {
997
// get front AC
998
auto AC = viewObjects.getAttributeCarrierFront();
999
// check AC
1000
if (AC == nullptr) {
1001
return false;
1002
}
1003
// check locking
1004
if (myViewNet->getLockManager().isObjectLocked(AC->getGUIGlObject()->getType(), AC->isAttributeCarrierSelected())) {
1005
return false;
1006
}
1007
// check modes
1008
if ((AC->getTagProperty()->isNetworkElement() || AC->getTagProperty()->isAdditionalElement()) &&
1009
!myViewNet->getEditModes().isCurrentSupermodeNetwork()) {
1010
return false;
1011
}
1012
if (AC->getTagProperty()->isDemandElement() && !myViewNet->getEditModes().isCurrentSupermodeDemand()) {
1013
return false;
1014
}
1015
if (AC->getTagProperty()->isDataElement() && !myViewNet->getEditModes().isCurrentSupermodeData()) {
1016
return false;
1017
}
1018
// filter GLObjects by layer
1019
auto filteredGLObjects = GNEViewNetHelper::filterElementsByLayer(viewObjects.getGLObjects());
1020
// check if we have to open dialog
1021
if (filteredGLObjects.size() > 1) {
1022
myViewNet->openSelectDialogAtCursor(filteredGLObjects);
1023
} else {
1024
// toggle selection
1025
if (AC->isAttributeCarrierSelected()) {
1026
AC->unselectAttributeCarrier();
1027
} else {
1028
AC->selectAttributeCarrier();
1029
}
1030
// update information label
1031
mySelectionInformation->updateInformationLabel();
1032
}
1033
return true;
1034
}
1035
1036
1037
void
1038
GNESelectorFrame::handleIDs(const std::vector<GNEAttributeCarrier*>& ACs, const ModificationMode::Operation setop) {
1039
// declare set operation
1040
const ModificationMode::Operation setOperation = ((setop == ModificationMode::Operation::DEFAULT) ? myModificationMode->getModificationMode() : setop);
1041
// declare two sets of attribute carriers, one for select and another for unselect
1042
std::set<std::pair<std::string, GNEAttributeCarrier*> > ACsToSelect, ACsToUnselect;
1043
// in restrict AND replace mode all current selected attribute carriers will be unselected
1044
if ((setOperation == ModificationMode::Operation::REPLACE) || (setOperation == ModificationMode::Operation::RESTRICT)) {
1045
// obtain selected ACs depending of current supermode
1046
auto selectedACs = myViewNet->getNet()->getAttributeCarriers()->getSelectedAttributeCarriers(false);
1047
// add id into ACs to unselect
1048
for (const auto& selectedAC : selectedACs) {
1049
ACsToUnselect.insert(std::make_pair(selectedAC->getID(), selectedAC));
1050
}
1051
}
1052
// handle ids
1053
for (const auto& AC : ACs) {
1054
// iterate over AttributeCarriers an place it in ACsToSelect or ACsToUnselect
1055
switch (setOperation) {
1056
case GNESelectorFrame::ModificationMode::Operation::SUB:
1057
ACsToUnselect.insert(std::make_pair(AC->getID(), AC));
1058
break;
1059
case GNESelectorFrame::ModificationMode::Operation::RESTRICT:
1060
if (ACsToUnselect.find(std::make_pair(AC->getID(), AC)) != ACsToUnselect.end()) {
1061
ACsToSelect.insert(std::make_pair(AC->getID(), AC));
1062
}
1063
break;
1064
default:
1065
ACsToSelect.insert(std::make_pair(AC->getID(), AC));
1066
break;
1067
}
1068
}
1069
// select junctions and their connections if Auto select junctions is enabled (note: only for "add mode")
1070
if (myViewNet->autoSelectNodes() && (setop == ModificationMode::Operation::ADD)) {
1071
std::set<GNEEdge*> edgesToSelect;
1072
// iterate over ACsToSelect and extract edges
1073
for (const auto& AC : ACsToSelect) {
1074
if (AC.second->getTagProperty()->getTag() == SUMO_TAG_EDGE) {
1075
edgesToSelect.insert(myViewNet->getNet()->getAttributeCarriers()->retrieveEdge(AC.second->getID()));
1076
}
1077
}
1078
// iterate over extracted edges
1079
for (const auto& edgeToSelect : edgesToSelect) {
1080
// select junction source and all connections, crossings and walkingAreas
1081
ACsToSelect.insert(std::make_pair(edgeToSelect->getFromJunction()->getID(), edgeToSelect->getFromJunction()));
1082
for (const auto& connectionToSelect : edgeToSelect->getFromJunction()->getGNEConnections()) {
1083
ACsToSelect.insert(std::make_pair(connectionToSelect->getID(), connectionToSelect));
1084
}
1085
for (const auto& fromCrossingToSelect : edgeToSelect->getFromJunction()->getGNECrossings()) {
1086
ACsToSelect.insert(std::make_pair(fromCrossingToSelect->getID(), fromCrossingToSelect));
1087
}
1088
for (const auto& fromWalkingAreaToSelect : edgeToSelect->getFromJunction()->getGNEWalkingAreas()) {
1089
ACsToSelect.insert(std::make_pair(fromWalkingAreaToSelect->getID(), fromWalkingAreaToSelect));
1090
}
1091
// select junction destination and all connections, crossings and walkingAreas
1092
ACsToSelect.insert(std::make_pair(edgeToSelect->getToJunction()->getID(), edgeToSelect->getToJunction()));
1093
for (const auto& connectionToSelect : edgeToSelect->getToJunction()->getGNEConnections()) {
1094
ACsToSelect.insert(std::make_pair(connectionToSelect->getID(), connectionToSelect));
1095
}
1096
for (const auto& toCrossingToSelect : edgeToSelect->getToJunction()->getGNECrossings()) {
1097
ACsToSelect.insert(std::make_pair(toCrossingToSelect->getID(), toCrossingToSelect));
1098
}
1099
for (const auto& toWalkingAreaToSelect : edgeToSelect->getToJunction()->getGNEWalkingAreas()) {
1100
ACsToSelect.insert(std::make_pair(toWalkingAreaToSelect->getID(), toWalkingAreaToSelect));
1101
}
1102
}
1103
}
1104
// only continue if there is ACs to select or unselect
1105
if ((ACsToSelect.size() + ACsToUnselect.size()) > 0) {
1106
// first unselect AC of ACsToUnselect and then selects AC of ACsToSelect
1107
myViewNet->getUndoList()->begin(GUIIcon::MODESELECT, TL("selection"));
1108
for (const auto& ACToUnselect : ACsToUnselect) {
1109
if (ACToUnselect.second->getTagProperty()->isSelectable()) {
1110
ACToUnselect.second->setAttribute(GNE_ATTR_SELECTED, "false", myViewNet->getUndoList());
1111
}
1112
}
1113
for (const auto& ACToSelect : ACsToSelect) {
1114
if (ACToSelect.second->getTagProperty()->isSelectable()) {
1115
ACToSelect.second->setAttribute(GNE_ATTR_SELECTED, "true", myViewNet->getUndoList());
1116
}
1117
}
1118
// finish operation
1119
myViewNet->getUndoList()->end();
1120
}
1121
}
1122
1123
1124
FXVerticalFrame*
1125
GNESelectorFrame::getContentFrame() const {
1126
return myContentFrame;
1127
}
1128
1129
1130
GNESelectorFrame::ModificationMode*
1131
GNESelectorFrame::getModificationModeModul() const {
1132
return myModificationMode;
1133
}
1134
1135
1136
GNESelectorFrame::SelectionOperation*
1137
GNESelectorFrame::getSelectionOperationModul() const {
1138
return mySelectionOperation;
1139
}
1140
1141
1142
GNESelectorFrame::SelectionInformation*
1143
GNESelectorFrame::getSelectionInformation() const {
1144
return mySelectionInformation;
1145
}
1146
1147
/****************************************************************************/
1148
1149