1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file GNEAdditionalFrame.cpp
11 /// @author Pablo Alvarez Lopez
12 /// @date Dec 2015
13 /// @version $Id$
14 ///
15 // The Widget for add additional elements
16 /****************************************************************************/
17
18 // ===========================================================================
19 // included modules
20 // ===========================================================================
21 #include <config.h>
22
23 #include <utils/gui/windows/GUIAppEnum.h>
24 #include <utils/gui/div/GUIDesigns.h>
25 #include <utils/xml/SUMOSAXAttributesImpl_Cached.h>
26 #include <netedit/changes/GNEChange_Additional.h>
27 #include <netedit/netelements/GNEEdge.h>
28 #include <netedit/netelements/GNELane.h>
29 #include <netedit/netelements/GNEConnection.h>
30 #include <netedit/additionals/GNEAdditional.h>
31 #include <netedit/additionals/GNEAdditionalHandler.h>
32 #include <netedit/GNENet.h>
33 #include <netedit/GNEViewNet.h>
34 #include <netedit/GNEUndoList.h>
35
36 #include "GNEAdditionalFrame.h"
37
38
39 // ===========================================================================
40 // FOX callback mapping
41 // ===========================================================================
42
43 FXDEFMAP(GNEAdditionalFrame::SelectorLaneParents) ConsecutiveLaneSelectorMap[] = {
44 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_STOPSELECTION, GNEAdditionalFrame::SelectorLaneParents::onCmdStopSelection),
45 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_ABORTSELECTION, GNEAdditionalFrame::SelectorLaneParents::onCmdAbortSelection),
46 };
47
48 FXDEFMAP(GNEAdditionalFrame::SelectorEdgeChilds) SelectorParentEdgesMap[] = {
49 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_USESELECTED, GNEAdditionalFrame::SelectorEdgeChilds::onCmdUseSelectedEdges),
50 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_CLEARSELECTION, GNEAdditionalFrame::SelectorEdgeChilds::onCmdClearSelection),
51 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_INVERTSELECTION, GNEAdditionalFrame::SelectorEdgeChilds::onCmdInvertSelection),
52 FXMAPFUNC(SEL_CHANGED, MID_GNE_ADDITIONALFRAME_SEARCH, GNEAdditionalFrame::SelectorEdgeChilds::onCmdTypeInSearchBox),
53 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_SELECT, GNEAdditionalFrame::SelectorEdgeChilds::onCmdSelectEdge),
54 };
55
56 FXDEFMAP(GNEAdditionalFrame::SelectorLaneChilds) SelectorParentLanesMap[] = {
57 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_USESELECTED, GNEAdditionalFrame::SelectorLaneChilds::onCmdUseSelectedLanes),
58 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_CLEARSELECTION, GNEAdditionalFrame::SelectorLaneChilds::onCmdClearSelection),
59 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_INVERTSELECTION, GNEAdditionalFrame::SelectorLaneChilds::onCmdInvertSelection),
60 FXMAPFUNC(SEL_CHANGED, MID_GNE_ADDITIONALFRAME_SEARCH, GNEAdditionalFrame::SelectorLaneChilds::onCmdTypeInSearchBox),
61 FXMAPFUNC(SEL_COMMAND, MID_GNE_ADDITIONALFRAME_SELECT, GNEAdditionalFrame::SelectorLaneChilds::onCmdSelectLane),
62 };
63
64 // Object implementation
FXIMPLEMENT(GNEAdditionalFrame::SelectorLaneParents,FXGroupBox,ConsecutiveLaneSelectorMap,ARRAYNUMBER (ConsecutiveLaneSelectorMap))65 FXIMPLEMENT(GNEAdditionalFrame::SelectorLaneParents, FXGroupBox, ConsecutiveLaneSelectorMap, ARRAYNUMBER(ConsecutiveLaneSelectorMap))
66 FXIMPLEMENT(GNEAdditionalFrame::SelectorEdgeChilds, FXGroupBox, SelectorParentEdgesMap, ARRAYNUMBER(SelectorParentEdgesMap))
67 FXIMPLEMENT(GNEAdditionalFrame::SelectorLaneChilds, FXGroupBox, SelectorParentLanesMap, ARRAYNUMBER(SelectorParentLanesMap))
68
69
70 // ---------------------------------------------------------------------------
71 // GNEAdditionalFrame::SelectorLaneParents - methods
72 // ---------------------------------------------------------------------------
73
74 GNEAdditionalFrame::SelectorLaneParents::SelectorLaneParents(GNEAdditionalFrame* additionalFrameParent) :
75 FXGroupBox(additionalFrameParent->myContentFrame, "Lane Selector", GUIDesignGroupBoxFrame),
76 myAdditionalFrameParent(additionalFrameParent) {
77 // create start and stop buttons
78 myStopSelectingButton = new FXButton(this, "Stop selecting", nullptr, this, MID_GNE_ADDITIONALFRAME_STOPSELECTION, GUIDesignButton);
79 myAbortSelectingButton = new FXButton(this, "Abort selecting", nullptr, this, MID_GNE_ADDITIONALFRAME_ABORTSELECTION, GUIDesignButton);
80 // disable stop and abort functions as init
81 myStopSelectingButton->disable();
82 myAbortSelectingButton->disable();
83 // define colors
84 myCandidateLaneColor = RGBColor(0, 64, 0, 255);
85 mySelectedLaneColor = RGBColor::GREEN;
86 }
87
88
~SelectorLaneParents()89 GNEAdditionalFrame::SelectorLaneParents::~SelectorLaneParents() {}
90
91
92 void
showSelectorLaneParentsModul()93 GNEAdditionalFrame::SelectorLaneParents::showSelectorLaneParentsModul() {
94 // abort current selection before show
95 abortConsecutiveLaneSelector();
96 // show FXGroupBox
97 FXGroupBox::show();
98 }
99
100
101 void
hideSelectorLaneParentsModul()102 GNEAdditionalFrame::SelectorLaneParents::hideSelectorLaneParentsModul() {
103 // abort current selection before hide
104 abortConsecutiveLaneSelector();
105 // hide FXGroupBox
106 FXGroupBox::hide();
107 }
108
109
110 void
startConsecutiveLaneSelector(GNELane * lane,const Position & clickedPosition)111 GNEAdditionalFrame::SelectorLaneParents::startConsecutiveLaneSelector(GNELane* lane, const Position& clickedPosition) {
112 // Only start selection if SelectorLaneParents modul is shown
113 if (shown()) {
114 // change buttons
115 myStopSelectingButton->enable();
116 myAbortSelectingButton->enable();
117 // add lane
118 addSelectedLane(lane, clickedPosition);
119 }
120 }
121
122
123 bool
stopConsecutiveLaneSelector()124 GNEAdditionalFrame::SelectorLaneParents::stopConsecutiveLaneSelector() {
125 // obtain tagproperty (only for improve code legibility)
126 const auto& tagValues = myAdditionalFrameParent->myItemSelector->getCurrentTagProperties();
127 // abort if there isn't at least two lanes
128 if (mySelectedLanes.size() < 2) {
129 WRITE_WARNING(myAdditionalFrameParent->myItemSelector->getCurrentTagProperties().getTagStr() + " requieres at least two lanes.");
130 // abort consecutive lane selector
131 abortConsecutiveLaneSelector();
132 return false;
133 }
134 // Declare map to keep attributes from Frames from Frame
135 std::map<SumoXMLAttr, std::string> valuesMap = myAdditionalFrameParent->myAdditionalAttributes->getAttributesAndValues(true);
136 // fill valuesOfElement with Netedit attributes from Frame
137 myAdditionalFrameParent->myNeteditAttributes->getNeteditAttributesAndValues(valuesMap, nullptr);
138 // Generate id of element
139 valuesMap[SUMO_ATTR_ID] = myAdditionalFrameParent->generateID(nullptr);
140 // obtain lane IDs
141 std::vector<std::string> laneIDs;
142 for (auto i : mySelectedLanes) {
143 laneIDs.push_back(i.first->getID());
144 }
145 valuesMap[SUMO_ATTR_LANES] = joinToString(laneIDs, " ");
146 // Obtain clicked position over first lane
147 valuesMap[SUMO_ATTR_POSITION] = toString(mySelectedLanes.front().second);
148 // Obtain clicked position over last lane
149 valuesMap[SUMO_ATTR_ENDPOS] = toString(mySelectedLanes.back().second);
150 // parse common attributes
151 if (!myAdditionalFrameParent->buildAdditionalCommonAttributes(valuesMap, tagValues)) {
152 return false;
153 }
154 // show warning dialogbox and stop check if input parameters are valid
155 if (myAdditionalFrameParent->myAdditionalAttributes->areValuesValid() == false) {
156 myAdditionalFrameParent->myAdditionalAttributes->showWarningMessage();
157 return false;
158 } else {
159 // declare SUMOSAXAttributesImpl_Cached to convert valuesMap into SUMOSAXAttributes
160 SUMOSAXAttributesImpl_Cached SUMOSAXAttrs(valuesMap, myAdditionalFrameParent->getPredefinedTagsMML(), toString(tagValues.getTag()));
161 // try to build additional
162 if (GNEAdditionalHandler::buildAdditional(myAdditionalFrameParent->myViewNet, true, myAdditionalFrameParent->myItemSelector->getCurrentTagProperties().getTag(), SUMOSAXAttrs, nullptr)) {
163 // abort consecutive lane selector
164 abortConsecutiveLaneSelector();
165 return true;
166 } else {
167 return false;
168 }
169 }
170 }
171
172
173 void
abortConsecutiveLaneSelector()174 GNEAdditionalFrame::SelectorLaneParents::abortConsecutiveLaneSelector() {
175 // reset color of all candidate lanes
176 for (auto i : myCandidateLanes) {
177 i->setSpecialColor(nullptr);
178 }
179 // clear candidate colors
180 myCandidateLanes.clear();
181 // reset color of all selected lanes
182 for (auto i : mySelectedLanes) {
183 i.first->setSpecialColor(nullptr);
184 }
185 // clear selected lanes
186 mySelectedLanes.clear();
187 // disable buttons
188 myStopSelectingButton->disable();
189 myAbortSelectingButton->disable();
190 // update view (due colors)
191 myAdditionalFrameParent->getViewNet()->update();
192 }
193
194
195 bool
addSelectedLane(GNELane * lane,const Position & clickedPosition)196 GNEAdditionalFrame::SelectorLaneParents::addSelectedLane(GNELane* lane, const Position& clickedPosition) {
197 // first check that lane exist
198 if (lane == nullptr) {
199 return false;
200 }
201 // check that lane wasn't already selected
202 for (auto i : mySelectedLanes) {
203 if (i.first == lane) {
204 WRITE_WARNING("Duplicated lanes aren't allowed");
205 return false;
206 }
207 }
208 // check that there is candidate lanes
209 if (mySelectedLanes.size() > 0) {
210 if (myCandidateLanes.empty()) {
211 WRITE_WARNING("Only candidate lanes are allowed");
212 return false;
213 } else if ((myCandidateLanes.size() > 0) && (std::find(myCandidateLanes.begin(), myCandidateLanes.end(), lane) == myCandidateLanes.end())) {
214 WRITE_WARNING("Only consecutive lanes are allowed");
215 return false;
216 }
217 }
218 // select lane and save the clicked position
219 mySelectedLanes.push_back(std::make_pair(lane, lane->getShape().nearest_offset_to_point2D(clickedPosition) / lane->getLengthGeometryFactor()));
220 // change color of selected lane
221 lane->setSpecialColor(&mySelectedLaneColor);
222 // restore original color of candidates (except already selected)
223 for (auto i : myCandidateLanes) {
224 if (!isLaneSelected(i)) {
225 i->setSpecialColor(nullptr);
226 }
227 }
228 // clear candidate lanes
229 myCandidateLanes.clear();
230 // fill candidate lanes
231 for (auto i : lane->getParentEdge().getGNEConnections()) {
232 // check that possible candidate lane isn't already selected
233 if ((lane == i->getLaneFrom()) && (!isLaneSelected(i->getLaneTo()))) {
234 // set candidate lane
235 i->getLaneTo()->setSpecialColor(&myCandidateLaneColor);
236 myCandidateLanes.push_back(i->getLaneTo());
237 }
238 }
239 // update view (due colors)
240 myAdditionalFrameParent->getViewNet()->update();
241 return true;
242 }
243
244
245 void
removeLastSelectedLane()246 GNEAdditionalFrame::SelectorLaneParents::removeLastSelectedLane() {
247 if (mySelectedLanes.size() > 1) {
248 mySelectedLanes.pop_back();
249 } else {
250 WRITE_WARNING("First lane cannot be removed");
251 }
252 }
253
254
255 bool
isSelectingLanes() const256 GNEAdditionalFrame::SelectorLaneParents::isSelectingLanes() const {
257 return myStopSelectingButton->isEnabled();
258 }
259
260
261 bool
isShown() const262 GNEAdditionalFrame::SelectorLaneParents::isShown() const {
263 return shown();
264 }
265
266
267 const RGBColor&
getSelectedLaneColor() const268 GNEAdditionalFrame::SelectorLaneParents::getSelectedLaneColor() const {
269 return mySelectedLaneColor;
270 }
271
272
273 const std::vector<std::pair<GNELane*, double> >&
getSelectedLanes() const274 GNEAdditionalFrame::SelectorLaneParents::getSelectedLanes() const {
275 return mySelectedLanes;
276 }
277
278
279 long
onCmdStopSelection(FXObject *,FXSelector,void *)280 GNEAdditionalFrame::SelectorLaneParents::onCmdStopSelection(FXObject*, FXSelector, void*) {
281 stopConsecutiveLaneSelector();
282 return 0;
283 }
284
285
286 long
onCmdAbortSelection(FXObject *,FXSelector,void *)287 GNEAdditionalFrame::SelectorLaneParents::onCmdAbortSelection(FXObject*, FXSelector, void*) {
288 abortConsecutiveLaneSelector();
289 return 0;
290 }
291
292
293 bool
isLaneSelected(GNELane * lane) const294 GNEAdditionalFrame::SelectorLaneParents::isLaneSelected(GNELane* lane) const {
295 for (auto i : mySelectedLanes) {
296 if (i.first == lane) {
297 return true;
298 }
299 }
300 return false;
301 }
302
303 // ---------------------------------------------------------------------------
304 // GNEAdditionalFrame::SelectorAdditionalParent - methods
305 // ---------------------------------------------------------------------------
306
SelectorAdditionalParent(GNEAdditionalFrame * additionalFrameParent)307 GNEAdditionalFrame::SelectorAdditionalParent::SelectorAdditionalParent(GNEAdditionalFrame* additionalFrameParent) :
308 FXGroupBox(additionalFrameParent->myContentFrame, "Parent selector", GUIDesignGroupBoxFrame),
309 myAdditionalFrameParent(additionalFrameParent),
310 myAdditionalTypeParent(SUMO_TAG_NOTHING) {
311 // Create label with the type of SelectorAdditionalParent
312 myFirstAdditionalParentsLabel = new FXLabel(this, "No additional selected", nullptr, GUIDesignLabelLeftThick);
313 // Create list
314 myFirstAdditionalParentsList = new FXList(this, this, MID_GNE_SET_TYPE, GUIDesignListSingleElementFixedHeight);
315 // Hide List
316 hideSelectorAdditionalParentModul();
317 }
318
319
~SelectorAdditionalParent()320 GNEAdditionalFrame::SelectorAdditionalParent::~SelectorAdditionalParent() {}
321
322
323 std::string
getIdSelected() const324 GNEAdditionalFrame::SelectorAdditionalParent::getIdSelected() const {
325 for (int i = 0; i < myFirstAdditionalParentsList->getNumItems(); i++) {
326 if (myFirstAdditionalParentsList->isItemSelected(i)) {
327 return myFirstAdditionalParentsList->getItem(i)->getText().text();
328 }
329 }
330 return "";
331 }
332
333
334 void
setIDSelected(const std::string & id)335 GNEAdditionalFrame::SelectorAdditionalParent::setIDSelected(const std::string& id) {
336 // first unselect all
337 for (int i = 0; i < myFirstAdditionalParentsList->getNumItems(); i++) {
338 myFirstAdditionalParentsList->getItem(i)->setSelected(false);
339 }
340 // select element if correspond to given ID
341 for (int i = 0; i < myFirstAdditionalParentsList->getNumItems(); i++) {
342 if (myFirstAdditionalParentsList->getItem(i)->getText().text() == id) {
343 myFirstAdditionalParentsList->getItem(i)->setSelected(true);
344 }
345 }
346 // recalc myFirstAdditionalParentsList
347 myFirstAdditionalParentsList->recalc();
348 }
349
350
351 bool
showSelectorAdditionalParentModul(SumoXMLTag additionalType)352 GNEAdditionalFrame::SelectorAdditionalParent::showSelectorAdditionalParentModul(SumoXMLTag additionalType) {
353 // make sure that we're editing an additional tag
354 auto listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_ADDITIONAL, false);
355 for (auto i : listOfTags) {
356 if (i == additionalType) {
357 myAdditionalTypeParent = additionalType;
358 myFirstAdditionalParentsLabel->setText(("Parent type: " + toString(additionalType)).c_str());
359 refreshSelectorAdditionalParentModul();
360 show();
361 return true;
362 }
363 }
364 return false;
365 }
366
367
368 void
hideSelectorAdditionalParentModul()369 GNEAdditionalFrame::SelectorAdditionalParent::hideSelectorAdditionalParentModul() {
370 myAdditionalTypeParent = SUMO_TAG_NOTHING;
371 hide();
372 }
373
374
375 void
refreshSelectorAdditionalParentModul()376 GNEAdditionalFrame::SelectorAdditionalParent::refreshSelectorAdditionalParentModul() {
377 myFirstAdditionalParentsList->clearItems();
378 if (myAdditionalTypeParent != SUMO_TAG_NOTHING) {
379 // fill list with IDs of additionals
380 for (auto i : myAdditionalFrameParent->getViewNet()->getNet()->getAdditionalByType(myAdditionalTypeParent)) {
381 myFirstAdditionalParentsList->appendItem(i.first.c_str());
382 }
383 }
384 }
385
386 // ---------------------------------------------------------------------------
387 // GNEAdditionalFrame::SelectorEdgeChilds - methods
388 // ---------------------------------------------------------------------------
389
SelectorEdgeChilds(GNEAdditionalFrame * additionalFrameParent)390 GNEAdditionalFrame::SelectorEdgeChilds::SelectorEdgeChilds(GNEAdditionalFrame* additionalFrameParent) :
391 FXGroupBox(additionalFrameParent->myContentFrame, "Edges", GUIDesignGroupBoxFrame),
392 myAdditionalFrameParent(additionalFrameParent) {
393 // Create menuCheck for selected edges
394 myUseSelectedEdgesCheckButton = new FXCheckButton(this, ("Use selected " + toString(SUMO_TAG_EDGE) + "s").c_str(), this, MID_GNE_ADDITIONALFRAME_USESELECTED, GUIDesignCheckButtonAttribute);
395
396 // Create search box
397 myEdgesSearch = new FXTextField(this, GUIDesignTextFieldNCol, this, MID_GNE_ADDITIONALFRAME_SEARCH, GUIDesignTextField);
398
399 // Create list
400 myList = new FXList(this, this, MID_GNE_ADDITIONALFRAME_SELECT, GUIDesignListFixedHeight, 0, 0, 0, 100);
401
402 // Create horizontal frame
403 FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
404
405 // Create button for clear selection
406 myClearEdgesSelection = new FXButton(buttonsFrame, "Clear", nullptr, this, MID_GNE_ADDITIONALFRAME_CLEARSELECTION, GUIDesignButtonRectangular);
407
408 // Create button for invert selection
409 myInvertEdgesSelection = new FXButton(buttonsFrame, "Invert", nullptr, this, MID_GNE_ADDITIONALFRAME_INVERTSELECTION, GUIDesignButtonRectangular);
410
411 // Hide List
412 hideSelectorEdgeChildsModul();
413 }
414
415
~SelectorEdgeChilds()416 GNEAdditionalFrame::SelectorEdgeChilds::~SelectorEdgeChilds() {}
417
418
419 std::string
getEdgeIdsSelected() const420 GNEAdditionalFrame::SelectorEdgeChilds::getEdgeIdsSelected() const {
421 std::vector<std::string> vectorOfIds;
422 if (myUseSelectedEdgesCheckButton->getCheck()) {
423 // get Selected edges
424 std::vector<GNEEdge*> selectedEdges = myAdditionalFrameParent->getViewNet()->getNet()->retrieveEdges(true);
425 // Iterate over selectedEdges and getId
426 for (auto i : selectedEdges) {
427 vectorOfIds.push_back(i->getID());
428 }
429 } else {
430 // Obtain Id's of list
431 for (int i = 0; i < myList->getNumItems(); i++) {
432 if (myList->isItemSelected(i)) {
433 vectorOfIds.push_back(myList->getItem(i)->getText().text());
434 }
435 }
436 }
437 return joinToString(vectorOfIds, " ");
438 }
439
440
441 void
showSelectorEdgeChildsModul(std::string search)442 GNEAdditionalFrame::SelectorEdgeChilds::showSelectorEdgeChildsModul(std::string search) {
443 // clear list of egdge ids
444 myList->clearItems();
445 // get all edges of net
446 /// @todo this function must be improved.
447 std::vector<GNEEdge*> vectorOfEdges = myAdditionalFrameParent->getViewNet()->getNet()->retrieveEdges(false);
448 // iterate over edges of net
449 for (auto i : vectorOfEdges) {
450 // If search criterium is correct, then append ittem
451 if (i->getID().find(search) != std::string::npos) {
452 myList->appendItem(i->getID().c_str());
453 }
454 }
455 // By default, CheckBox for useSelectedEdges isn't checked
456 myUseSelectedEdgesCheckButton->setCheck(false);
457 // Recalc Frame
458 recalc();
459 // Update Frame
460 update();
461 // Show dialog
462 show();
463 }
464
465
466 void
hideSelectorEdgeChildsModul()467 GNEAdditionalFrame::SelectorEdgeChilds::hideSelectorEdgeChildsModul() {
468 FXGroupBox::hide();
469 }
470
471
472 void
updateUseSelectedEdges()473 GNEAdditionalFrame::SelectorEdgeChilds::updateUseSelectedEdges() {
474 // Enable or disable use selected edges
475 if (myAdditionalFrameParent->getViewNet()->getNet()->retrieveEdges(true).size() > 0) {
476 myUseSelectedEdgesCheckButton->enable();
477 } else {
478 myUseSelectedEdgesCheckButton->disable();
479 }
480 }
481
482
483 long
onCmdUseSelectedEdges(FXObject *,FXSelector,void *)484 GNEAdditionalFrame::SelectorEdgeChilds::onCmdUseSelectedEdges(FXObject*, FXSelector, void*) {
485 if (myUseSelectedEdgesCheckButton->getCheck()) {
486 myEdgesSearch->hide();
487 myList->hide();
488 myClearEdgesSelection->hide();
489 myInvertEdgesSelection->hide();
490 } else {
491 myEdgesSearch->show();
492 myList->show();
493 myClearEdgesSelection->show();
494 myInvertEdgesSelection->show();
495 }
496 // Recalc Frame
497 recalc();
498 // Update Frame
499 update();
500 return 1;
501 }
502
503
504 long
onCmdTypeInSearchBox(FXObject *,FXSelector,void *)505 GNEAdditionalFrame::SelectorEdgeChilds::onCmdTypeInSearchBox(FXObject*, FXSelector, void*) {
506 // Show only Id's of SelectorEdgeChilds that contains the searched string
507 showSelectorEdgeChildsModul(myEdgesSearch->getText().text());
508 return 1;
509 }
510
511
512 long
onCmdSelectEdge(FXObject *,FXSelector,void *)513 GNEAdditionalFrame::SelectorEdgeChilds::onCmdSelectEdge(FXObject*, FXSelector, void*) {
514 return 1;
515 }
516
517
518 long
onCmdClearSelection(FXObject *,FXSelector,void *)519 GNEAdditionalFrame::SelectorEdgeChilds::onCmdClearSelection(FXObject*, FXSelector, void*) {
520 for (int i = 0; i < myList->getNumItems(); i++) {
521 if (myList->getItem(i)->isSelected()) {
522 myList->deselectItem(i);
523 }
524 }
525 return 1;
526 }
527
528
529 long
onCmdInvertSelection(FXObject *,FXSelector,void *)530 GNEAdditionalFrame::SelectorEdgeChilds::onCmdInvertSelection(FXObject*, FXSelector, void*) {
531 for (int i = 0; i < myList->getNumItems(); i++) {
532 if (myList->getItem(i)->isSelected()) {
533 myList->deselectItem(i);
534 } else {
535 myList->selectItem(i);
536 }
537 }
538 return 1;
539 }
540
541 // ---------------------------------------------------------------------------
542 // GNEAdditionalFrame::SelectorLaneChilds - methods
543 // ---------------------------------------------------------------------------
544
SelectorLaneChilds(GNEAdditionalFrame * additionalFrameParent)545 GNEAdditionalFrame::SelectorLaneChilds::SelectorLaneChilds(GNEAdditionalFrame* additionalFrameParent) :
546 FXGroupBox(additionalFrameParent->myContentFrame, "Lanes", GUIDesignGroupBoxFrame),
547 myAdditionalFrameParent(additionalFrameParent) {
548 // Create CheckBox for selected lanes
549 myUseSelectedLanesCheckButton = new FXCheckButton(this, ("Use selected " + toString(SUMO_TAG_LANE) + "s").c_str(), this, MID_GNE_ADDITIONALFRAME_USESELECTED, GUIDesignCheckButtonAttribute);
550
551 // Create search box
552 myLanesSearch = new FXTextField(this, GUIDesignTextFieldNCol, this, MID_GNE_ADDITIONALFRAME_SEARCH, GUIDesignTextField);
553
554 // Create list
555 myList = new FXList(this, this, MID_GNE_ADDITIONALFRAME_SELECT, GUIDesignListFixedHeight, 0, 0, 0, 100);
556
557 // Create horizontal frame
558 FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
559
560 // Create button for clear selection
561 clearLanesSelection = new FXButton(buttonsFrame, "clear", nullptr, this, MID_GNE_ADDITIONALFRAME_CLEARSELECTION, GUIDesignButtonRectangular);
562
563 // Create button for invert selection
564 invertLanesSelection = new FXButton(buttonsFrame, "invert", nullptr, this, MID_GNE_ADDITIONALFRAME_INVERTSELECTION, GUIDesignButtonRectangular);
565
566 // Hide List
567 hideSelectorLaneChildsModul();
568 }
569
570
~SelectorLaneChilds()571 GNEAdditionalFrame::SelectorLaneChilds::~SelectorLaneChilds() {}
572
573
574 std::string
getLaneIdsSelected() const575 GNEAdditionalFrame::SelectorLaneChilds::getLaneIdsSelected() const {
576 std::vector<std::string> vectorOfIds;
577 if (myUseSelectedLanesCheckButton->getCheck()) {
578 // get Selected lanes
579 std::vector<GNELane*> selectedLanes = myAdditionalFrameParent->getViewNet()->getNet()->retrieveLanes(true);
580 // Iterate over selectedLanes and getId
581 for (auto i : selectedLanes) {
582 vectorOfIds.push_back(i->getID());
583 }
584 } else {
585 // Obtain Id's of list
586 for (int i = 0; i < myList->getNumItems(); i++) {
587 if (myList->isItemSelected(i)) {
588 vectorOfIds.push_back(myList->getItem(i)->getText().text());
589 }
590 }
591 }
592 return joinToString(vectorOfIds, " ");
593 }
594
595
596 void
showSelectorLaneChildsModul(std::string search)597 GNEAdditionalFrame::SelectorLaneChilds::showSelectorLaneChildsModul(std::string search) {
598 myList->clearItems();
599 std::vector<GNELane*> vectorOfLanes = myAdditionalFrameParent->getViewNet()->getNet()->retrieveLanes(false);
600 for (auto i : vectorOfLanes) {
601 if (i->getID().find(search) != std::string::npos) {
602 myList->appendItem(i->getID().c_str());
603 }
604 }
605 // By default, CheckBox for useSelectedLanes isn't checked
606 myUseSelectedLanesCheckButton->setCheck(false);
607 // Show list
608 show();
609 }
610
611
612 void
hideSelectorLaneChildsModul()613 GNEAdditionalFrame::SelectorLaneChilds::hideSelectorLaneChildsModul() {
614 FXGroupBox::hide();
615 }
616
617
618 void
updateUseSelectedLanes()619 GNEAdditionalFrame::SelectorLaneChilds::updateUseSelectedLanes() {
620 // Enable or disable use selected Lanes
621 if (myAdditionalFrameParent->getViewNet()->getNet()->retrieveLanes(true).size() > 0) {
622 myUseSelectedLanesCheckButton->enable();
623 } else {
624 myUseSelectedLanesCheckButton->disable();
625 }
626 }
627
628
629 long
onCmdUseSelectedLanes(FXObject *,FXSelector,void *)630 GNEAdditionalFrame::SelectorLaneChilds::onCmdUseSelectedLanes(FXObject*, FXSelector, void*) {
631 if (myUseSelectedLanesCheckButton->getCheck()) {
632 myLanesSearch->hide();
633 myList->hide();
634 clearLanesSelection->hide();
635 invertLanesSelection->hide();
636 } else {
637 myLanesSearch->show();
638 myList->show();
639 clearLanesSelection->show();
640 invertLanesSelection->show();
641 }
642 // Recalc Frame
643 recalc();
644 // Update Frame
645 update();
646 return 1;
647 }
648
649
650 long
onCmdTypeInSearchBox(FXObject *,FXSelector,void *)651 GNEAdditionalFrame::SelectorLaneChilds::onCmdTypeInSearchBox(FXObject*, FXSelector, void*) {
652 // Show only Id's of SelectorLaneChilds that contains the searched string
653 showSelectorLaneChildsModul(myLanesSearch->getText().text());
654 return 1;
655 }
656
657
658 long
onCmdSelectLane(FXObject *,FXSelector,void *)659 GNEAdditionalFrame::SelectorLaneChilds::onCmdSelectLane(FXObject*, FXSelector, void*) {
660 return 1;
661 }
662
663
664 long
onCmdClearSelection(FXObject *,FXSelector,void *)665 GNEAdditionalFrame::SelectorLaneChilds::onCmdClearSelection(FXObject*, FXSelector, void*) {
666 for (int i = 0; i < myList->getNumItems(); i++) {
667 if (myList->getItem(i)->isSelected()) {
668 myList->deselectItem(i);
669 }
670 }
671 return 1;
672 }
673
674
675 long
onCmdInvertSelection(FXObject *,FXSelector,void *)676 GNEAdditionalFrame::SelectorLaneChilds::onCmdInvertSelection(FXObject*, FXSelector, void*) {
677 for (int i = 0; i < myList->getNumItems(); i++) {
678 if (myList->getItem(i)->isSelected()) {
679 myList->deselectItem(i);
680 } else {
681 myList->selectItem(i);
682 }
683 }
684 return 1;
685 }
686
687 // ===========================================================================
688 // method definitions
689 // ===========================================================================
690
GNEAdditionalFrame(FXHorizontalFrame * horizontalFrameParent,GNEViewNet * viewNet)691 GNEAdditionalFrame::GNEAdditionalFrame(FXHorizontalFrame* horizontalFrameParent, GNEViewNet* viewNet) :
692 GNEFrame(horizontalFrameParent, viewNet, "Additionals") {
693
694 // create item Selector modul for additionals
695 myItemSelector = new ItemSelector(this, GNEAttributeCarrier::TagType::TAGTYPE_ADDITIONAL);
696
697 // Create additional parameters
698 myAdditionalAttributes = new AttributesCreator(this);
699
700 // Create Netedit parameter
701 myNeteditAttributes = new NeteditAttributes(this);
702
703 // Create consecutive Lane Selector
704 mySelectorLaneParents = new SelectorLaneParents(this);
705
706 // Create create list for additional Set
707 mySelectorAdditionalParent = new SelectorAdditionalParent(this);
708
709 /// Create list for SelectorEdgeChilds
710 mySelectorEdgeChilds = new SelectorEdgeChilds(this);
711
712 /// Create list for SelectorLaneChilds
713 mySelectorLaneChilds = new SelectorLaneChilds(this);
714
715 // set BusStop as default additional
716 myItemSelector->setCurrentTypeTag(SUMO_TAG_BUS_STOP);
717 }
718
719
~GNEAdditionalFrame()720 GNEAdditionalFrame::~GNEAdditionalFrame() {}
721
722
723 void
show()724 GNEAdditionalFrame::show() {
725 // refresh item selector
726 myItemSelector->refreshTagProperties();
727 // show frame
728 GNEFrame::show();
729 }
730
731
732 bool
addAdditional(const GNEViewNetHelper::ObjectsUnderCursor & objectsUnderCursor)733 GNEAdditionalFrame::addAdditional(const GNEViewNetHelper::ObjectsUnderCursor& objectsUnderCursor) {
734 // first check that current selected additional is valid
735 if (myItemSelector->getCurrentTagProperties().getTag() == SUMO_TAG_NOTHING) {
736 myViewNet->setStatusBarText("Current selected additional isn't valid.");
737 return false;
738 }
739
740 // obtain tagproperty (only for improve code legibility)
741 const auto& tagValues = myItemSelector->getCurrentTagProperties();
742
743 // Declare map to keep attributes from Frames from Frame
744 std::map<SumoXMLAttr, std::string> valuesMap = myAdditionalAttributes->getAttributesAndValues(true);
745
746 // fill netedit attributes
747 if (!myNeteditAttributes->getNeteditAttributesAndValues(valuesMap, objectsUnderCursor.getLaneFront())) {
748 return false;
749 }
750
751 // If element owns an additional parent, get id of parent from AdditionalParentSelector
752 if (tagValues.hasParent() && !buildAdditionalWithParent(valuesMap, objectsUnderCursor.getAdditionalFront(), tagValues)) {
753 return false;
754 }
755 // If consecutive Lane Selector is enabled, it means that either we're selecting lanes or we're finished or we'rent started
756 if (tagValues.hasAttribute(SUMO_ATTR_EDGE)) {
757 return buildAdditionalOverEdge(valuesMap, objectsUnderCursor.getLaneFront(), tagValues);
758 } else if (tagValues.hasAttribute(SUMO_ATTR_LANE)) {
759 return buildAdditionalOverLane(valuesMap, objectsUnderCursor.getLaneFront(), tagValues);
760 } else if (tagValues.hasAttribute(SUMO_ATTR_LANES)) {
761 return buildAdditionalOverLanes(valuesMap, objectsUnderCursor.getLaneFront(), tagValues);
762 } else {
763 return buildAdditionalOverView(valuesMap, tagValues);
764 }
765 }
766
767
768 void
showSelectorLaneChildsModul()769 GNEAdditionalFrame::showSelectorLaneChildsModul() {
770 // Show frame
771 GNEFrame::show();
772 // Update UseSelectedLane CheckBox
773 mySelectorEdgeChilds->updateUseSelectedEdges();
774 // Update UseSelectedLane CheckBox
775 mySelectorLaneChilds->updateUseSelectedLanes();
776 }
777
778
779 GNEAdditionalFrame::SelectorLaneParents*
getConsecutiveLaneSelector() const780 GNEAdditionalFrame::getConsecutiveLaneSelector() const {
781 return mySelectorLaneParents;
782 }
783
784
785 void
enableModuls(const GNEAttributeCarrier::TagProperties & tagProperties)786 GNEAdditionalFrame::enableModuls(const GNEAttributeCarrier::TagProperties& tagProperties) {
787 // show additional attributes modul
788 myAdditionalAttributes->showAttributesCreatorModul(tagProperties);
789 // show netedit attributes
790 myNeteditAttributes->showNeteditAttributesModul(tagProperties);
791 // Show myAdditionalFrameParent if we're adding a additional with parent
792 if (tagProperties.hasParent()) {
793 mySelectorAdditionalParent->showSelectorAdditionalParentModul(tagProperties.getParentTag());
794 } else {
795 mySelectorAdditionalParent->hideSelectorAdditionalParentModul();
796 }
797 // Show SelectorEdgeChilds if we're adding an additional that own the attribute SUMO_ATTR_EDGES
798 if (tagProperties.hasAttribute(SUMO_ATTR_EDGES)) {
799 mySelectorEdgeChilds->showSelectorEdgeChildsModul();
800 } else {
801 mySelectorEdgeChilds->hideSelectorEdgeChildsModul();
802 }
803 // Show SelectorLaneChilds or consecutive lane selector if we're adding an additional that own the attribute SUMO_ATTR_LANES
804 if (tagProperties.hasAttribute(SUMO_ATTR_LANES)) {
805 if (tagProperties.hasParent() && tagProperties.getParentTag() == SUMO_TAG_LANE) {
806 // show selector lane parent and hide selector lane child
807 mySelectorLaneParents->showSelectorLaneParentsModul();
808 mySelectorLaneChilds->hideSelectorLaneChildsModul();
809 } else {
810 // show selector lane child and hide selector lane parent
811 mySelectorLaneChilds->showSelectorLaneChildsModul();
812 mySelectorLaneParents->hideSelectorLaneParentsModul();
813 }
814 } else {
815 mySelectorLaneChilds->hideSelectorLaneChildsModul();
816 mySelectorLaneParents->hideSelectorLaneParentsModul();
817 }
818 }
819
820
821 void
disableModuls()822 GNEAdditionalFrame::disableModuls() {
823 // hide all moduls if additional isn't valid
824 myAdditionalAttributes->hideAttributesCreatorModul();
825 myNeteditAttributes->hideNeteditAttributesModul();
826 mySelectorAdditionalParent->hideSelectorAdditionalParentModul();
827 mySelectorEdgeChilds->hideSelectorEdgeChildsModul();
828 mySelectorLaneChilds->hideSelectorLaneChildsModul();
829 mySelectorLaneParents->hideSelectorLaneParentsModul();
830 }
831
832
833 std::string
generateID(GNENetElement * netElement) const834 GNEAdditionalFrame::generateID(GNENetElement* netElement) const {
835 // obtain current number of additionals to generate a new index faster
836 int additionalIndex = myViewNet->getNet()->getNumberOfAdditionals(myItemSelector->getCurrentTagProperties().getTag());
837 // obtain tag Properties (only for improve code legilibility
838 const auto& tagProperties = myItemSelector->getCurrentTagProperties();
839 if (netElement) {
840 // special case for vaporizers
841 if (tagProperties.getTag() == SUMO_TAG_VAPORIZER) {
842 return netElement->getID();
843 } else {
844 // generate ID using netElement
845 while (myViewNet->getNet()->retrieveAdditional(tagProperties.getTag(), tagProperties.getTagStr() + "_" + netElement->getID() + "_" + toString(additionalIndex), false) != nullptr) {
846 additionalIndex++;
847 }
848 return tagProperties.getTagStr() + "_" + netElement->getID() + "_" + toString(additionalIndex);
849 }
850 } else {
851 // generate ID without netElement
852 while (myViewNet->getNet()->retrieveAdditional(tagProperties.getTag(), tagProperties.getTagStr() + "_" + toString(additionalIndex), false) != nullptr) {
853 additionalIndex++;
854 }
855 return tagProperties.getTagStr() + "_" + toString(additionalIndex);
856 }
857 }
858
859
860 bool
buildAdditionalWithParent(std::map<SumoXMLAttr,std::string> & valuesMap,GNEAdditional * additionalParent,const GNEAttributeCarrier::TagProperties & tagValues)861 GNEAdditionalFrame::buildAdditionalWithParent(std::map<SumoXMLAttr, std::string>& valuesMap, GNEAdditional* additionalParent, const GNEAttributeCarrier::TagProperties& tagValues) {
862 // if user click over an additional element parent, mark int in AdditionalParentSelector
863 if (additionalParent && (additionalParent->getTagProperty().getTag() == tagValues.getParentTag())) {
864 valuesMap[GNE_ATTR_PARENT] = additionalParent->getID();
865 mySelectorAdditionalParent->setIDSelected(additionalParent->getID());
866 }
867 // stop if currently there isn't a valid selected parent
868 if (mySelectorAdditionalParent->getIdSelected() != "") {
869 valuesMap[GNE_ATTR_PARENT] = mySelectorAdditionalParent->getIdSelected();
870 } else {
871 myAdditionalAttributes->showWarningMessage("A " + toString(tagValues.getParentTag()) + " must be selected before insertion of " + myItemSelector->getCurrentTagProperties().getTagStr() + ".");
872 return false;
873 }
874 return true;
875 }
876
877
878 bool
buildAdditionalCommonAttributes(std::map<SumoXMLAttr,std::string> & valuesMap,const GNEAttributeCarrier::TagProperties & tagValues)879 GNEAdditionalFrame::buildAdditionalCommonAttributes(std::map<SumoXMLAttr, std::string>& valuesMap, const GNEAttributeCarrier::TagProperties& tagValues) {
880 // If additional has a interval defined by a begin or end, check that is valid
881 if (tagValues.hasAttribute(SUMO_ATTR_STARTTIME) && tagValues.hasAttribute(SUMO_ATTR_END)) {
882 double begin = GNEAttributeCarrier::parse<double>(valuesMap[SUMO_ATTR_STARTTIME]);
883 double end = GNEAttributeCarrier::parse<double>(valuesMap[SUMO_ATTR_END]);
884 if (begin > end) {
885 myAdditionalAttributes->showWarningMessage("Attribute '" + toString(SUMO_ATTR_STARTTIME) + "' cannot be greater than attribute '" + toString(SUMO_ATTR_END) + "'.");
886 return false;
887 }
888 }
889 // If additional own the attribute SUMO_ATTR_FILE but was't defined, will defined as <ID>.xml
890 if (tagValues.hasAttribute(SUMO_ATTR_FILE) && valuesMap[SUMO_ATTR_FILE] == "") {
891 if ((myItemSelector->getCurrentTagProperties().getTag() != SUMO_TAG_CALIBRATOR) && (myItemSelector->getCurrentTagProperties().getTag() != SUMO_TAG_REROUTER)) {
892 // SUMO_ATTR_FILE is optional for calibrators and rerouters (fails to load in sumo when given and the file does not exist)
893 valuesMap[SUMO_ATTR_FILE] = (valuesMap[SUMO_ATTR_ID] + ".xml");
894 }
895 }
896 // If element own a list of SelectorEdgeChilds as attribute
897 if (tagValues.hasAttribute(SUMO_ATTR_EDGES) && valuesMap[SUMO_ATTR_EDGES].empty()) {
898 // obtain edge IDs
899 valuesMap[SUMO_ATTR_EDGES] = mySelectorEdgeChilds->getEdgeIdsSelected();
900 // check if attribute has at least one edge
901 if (valuesMap[SUMO_ATTR_EDGES] == "") {
902 myAdditionalAttributes->showWarningMessage("List of " + toString(SUMO_TAG_EDGE) + "s cannot be empty");
903 return false;
904 }
905 }
906 // get values of mySelectorLaneChilds, if tag correspond to an element that has lanes as childs
907 if (tagValues.hasAttribute(SUMO_ATTR_LANES) && valuesMap[SUMO_ATTR_LANES].empty()) {
908 // obtain lane IDs
909 valuesMap[SUMO_ATTR_LANES] = mySelectorLaneChilds->getLaneIdsSelected();
910 // check if attribute has at least a lane
911 if (valuesMap[SUMO_ATTR_LANES] == "") {
912 myAdditionalAttributes->showWarningMessage("List of " + toString(SUMO_TAG_LANE) + "s cannot be empty");
913 return false;
914 }
915 }
916 // all ok, continue building additionals
917 return true;
918 }
919
920
921 bool
buildAdditionalOverEdge(std::map<SumoXMLAttr,std::string> & valuesMap,GNELane * lane,const GNEAttributeCarrier::TagProperties & tagValues)922 GNEAdditionalFrame::buildAdditionalOverEdge(std::map<SumoXMLAttr, std::string>& valuesMap, GNELane* lane, const GNEAttributeCarrier::TagProperties& tagValues) {
923 // check that edge exist
924 if (lane) {
925 // Get attribute lane's edge
926 valuesMap[SUMO_ATTR_EDGE] = lane->getParentEdge().getID();
927 // Generate id of element based on the lane's edge
928 valuesMap[SUMO_ATTR_ID] = generateID(&lane->getParentEdge());
929 } else {
930 return false;
931 }
932 // parse common attributes
933 if (!buildAdditionalCommonAttributes(valuesMap, tagValues)) {
934 return false;
935 }
936 // show warning dialogbox and stop check if input parameters are valid
937 if (!myAdditionalAttributes->areValuesValid()) {
938 myAdditionalAttributes->showWarningMessage();
939 return false;
940 } else {
941 // declare SUMOSAXAttributesImpl_Cached to convert valuesMap into SUMOSAXAttributes
942 SUMOSAXAttributesImpl_Cached SUMOSAXAttrs(valuesMap, getPredefinedTagsMML(), toString(tagValues.getTag()));
943 // try to build additional
944 if (GNEAdditionalHandler::buildAdditional(myViewNet, true, myItemSelector->getCurrentTagProperties().getTag(), SUMOSAXAttrs, nullptr)) {
945 // Refresh additional Parent Selector (For additionals that have a limited number of childs)
946 mySelectorAdditionalParent->refreshSelectorAdditionalParentModul();
947 // clear selected eddges and lanes
948 mySelectorEdgeChilds->onCmdClearSelection(nullptr, 0, nullptr);
949 mySelectorLaneChilds->onCmdClearSelection(nullptr, 0, nullptr);
950 return true;
951 } else {
952 return false;
953 }
954 }
955 }
956
957
958 bool
buildAdditionalOverLane(std::map<SumoXMLAttr,std::string> & valuesMap,GNELane * lane,const GNEAttributeCarrier::TagProperties & tagValues)959 GNEAdditionalFrame::buildAdditionalOverLane(std::map<SumoXMLAttr, std::string>& valuesMap, GNELane* lane, const GNEAttributeCarrier::TagProperties& tagValues) {
960 // check that lane exist
961 if (lane != nullptr) {
962 // Get attribute lane
963 valuesMap[SUMO_ATTR_LANE] = lane->getID();
964 // Generate id of element based on the lane
965 valuesMap[SUMO_ATTR_ID] = generateID(lane);
966 } else {
967 return false;
968 }
969 // Obtain position of the mouse over lane (limited over grid)
970 double mousePositionOverLane = lane->getShape().nearest_offset_to_point2D(myViewNet->snapToActiveGrid(myViewNet->getPositionInformation())) / lane->getLengthGeometryFactor();
971 // set attribute position as mouse position over lane
972 valuesMap[SUMO_ATTR_POSITION] = toString(mousePositionOverLane);
973 // parse common attributes
974 if (!buildAdditionalCommonAttributes(valuesMap, tagValues)) {
975 return false;
976 }
977 // show warning dialogbox and stop check if input parameters are valid
978 if (!myAdditionalAttributes->areValuesValid()) {
979 myAdditionalAttributes->showWarningMessage();
980 return false;
981 } else {
982 // declare SUMOSAXAttributesImpl_Cached to convert valuesMap into SUMOSAXAttributes
983 SUMOSAXAttributesImpl_Cached SUMOSAXAttrs(valuesMap, getPredefinedTagsMML(), toString(tagValues.getTag()));
984 // try to build additional
985 if (GNEAdditionalHandler::buildAdditional(myViewNet, true, myItemSelector->getCurrentTagProperties().getTag(), SUMOSAXAttrs, nullptr)) {
986 // Refresh additional Parent Selector (For additionals that have a limited number of childs)
987 mySelectorAdditionalParent->refreshSelectorAdditionalParentModul();
988 // clear selected eddges and lanes
989 mySelectorEdgeChilds->onCmdClearSelection(nullptr, 0, nullptr);
990 mySelectorLaneChilds->onCmdClearSelection(nullptr, 0, nullptr);
991 return true;
992 } else {
993 return false;
994 }
995 }
996 }
997
998
999 bool
buildAdditionalOverLanes(std::map<SumoXMLAttr,std::string> & valuesMap,GNELane * lane,const GNEAttributeCarrier::TagProperties & tagValues)1000 GNEAdditionalFrame::buildAdditionalOverLanes(std::map<SumoXMLAttr, std::string>& valuesMap, GNELane* lane, const GNEAttributeCarrier::TagProperties& tagValues) {
1001 // stop if lane isn't valid
1002 if (lane == nullptr) {
1003 return false;
1004 }
1005 if (mySelectorLaneParents->isSelectingLanes()) {
1006 // select clicked lane, but don't build additional
1007 mySelectorLaneParents->addSelectedLane(lane, myViewNet->getPositionInformation());
1008 return false;
1009 } else if (mySelectorLaneParents->getSelectedLanes().empty()) {
1010 // if there isn't selected lanes, that means that we will be start selecting lanes
1011 mySelectorLaneParents->startConsecutiveLaneSelector(lane, myViewNet->getPositionInformation());
1012 return false;
1013 } else {
1014 // Generate id of element based on the first lane
1015 valuesMap[SUMO_ATTR_ID] = generateID(mySelectorLaneParents->getSelectedLanes().front().first);
1016 // obtain lane IDs
1017 std::vector<std::string> laneIDs;
1018 for (auto i : mySelectorLaneParents->getSelectedLanes()) {
1019 laneIDs.push_back(i.first->getID());
1020 }
1021 valuesMap[SUMO_ATTR_LANES] = joinToString(laneIDs, " ");
1022 // Check if clicked position over first lane has to be obtained
1023 if (tagValues.hasAttribute(SUMO_ATTR_POSITION)) {
1024 valuesMap[SUMO_ATTR_POSITION] = toString(mySelectorLaneParents->getSelectedLanes().front().second);
1025 }
1026 // Check if clicked position over last lane has to be obtained
1027 if (tagValues.hasAttribute(SUMO_ATTR_ENDPOS)) {
1028 valuesMap[SUMO_ATTR_ENDPOS] = toString(mySelectorLaneParents->getSelectedLanes().back().second);
1029 }
1030 // parse common attributes
1031 if (!buildAdditionalCommonAttributes(valuesMap, tagValues)) {
1032 return false;
1033 }
1034 // show warning dialogbox and stop check if input parameters are valid
1035 if (myAdditionalAttributes->areValuesValid() == false) {
1036 myAdditionalAttributes->showWarningMessage();
1037 return false;
1038 } else {
1039 // declare SUMOSAXAttributesImpl_Cached to convert valuesMap into SUMOSAXAttributes
1040 SUMOSAXAttributesImpl_Cached SUMOSAXAttrs(valuesMap, getPredefinedTagsMML(), toString(tagValues.getTag()));
1041 // try to build additional
1042 if (GNEAdditionalHandler::buildAdditional(myViewNet, true, myItemSelector->getCurrentTagProperties().getTag(), SUMOSAXAttrs, nullptr)) {
1043 // Refresh additional Parent Selector (For additionals that have a limited number of childs)
1044 mySelectorAdditionalParent->refreshSelectorAdditionalParentModul();
1045 // abort lane selector
1046 mySelectorLaneParents->abortConsecutiveLaneSelector();
1047 return true;
1048 } else {
1049 // additional cannot be build
1050 return false;
1051 }
1052 }
1053 }
1054 }
1055
1056
1057 bool
buildAdditionalOverView(std::map<SumoXMLAttr,std::string> & valuesMap,const GNEAttributeCarrier::TagProperties & tagValues)1058 GNEAdditionalFrame::buildAdditionalOverView(std::map<SumoXMLAttr, std::string>& valuesMap, const GNEAttributeCarrier::TagProperties& tagValues) {
1059 // Generate id of element
1060 valuesMap[SUMO_ATTR_ID] = generateID(nullptr);
1061 // Obtain position as the clicked position over view
1062 valuesMap[SUMO_ATTR_POSITION] = toString(myViewNet->snapToActiveGrid(myViewNet->getPositionInformation()));
1063 // parse common attributes
1064 if (!buildAdditionalCommonAttributes(valuesMap, tagValues)) {
1065 return false;
1066 }
1067 // show warning dialogbox and stop check if input parameters are valid
1068 if (myAdditionalAttributes->areValuesValid() == false) {
1069 myAdditionalAttributes->showWarningMessage();
1070 return false;
1071 } else {
1072 // declare SUMOSAXAttributesImpl_Cached to convert valuesMap into SUMOSAXAttributes
1073 SUMOSAXAttributesImpl_Cached SUMOSAXAttrs(valuesMap, getPredefinedTagsMML(), toString(tagValues.getTag()));
1074 // try to build additional
1075 if (GNEAdditionalHandler::buildAdditional(myViewNet, true, myItemSelector->getCurrentTagProperties().getTag(), SUMOSAXAttrs, nullptr)) {
1076 // Refresh additional Parent Selector (For additionals that have a limited number of childs)
1077 mySelectorAdditionalParent->refreshSelectorAdditionalParentModul();
1078 // clear selected eddges and lanes
1079 mySelectorEdgeChilds->onCmdClearSelection(nullptr, 0, nullptr);
1080 mySelectorLaneChilds->onCmdClearSelection(nullptr, 0, nullptr);
1081 return true;
1082 } else {
1083 return false;
1084 }
1085 }
1086 }
1087
1088 /****************************************************************************/
1089