Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNETLSEditorFrame.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2026 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/****************************************************************************/
19// The Widget for modifying traffic lights
20/****************************************************************************/
21
22#include <config.h>
23
24#include <algorithm>
26#include <netbuild/NBOwnTLDef.h>
29#include <netedit/GNENet.h>
31#include <netedit/GNEUndoList.h>
48#include <utils/xml/XMLSubSys.h>
49
50#include "GNETLSEditorFrame.h"
51
52// ===========================================================================
53// FOX callback mapping
54// ===========================================================================
55
64
74
81
88
93
94// Object implementation
95FXIMPLEMENT(GNETLSEditorFrame::TLSJunction, GNEGroupBoxModule, TLSJunctionMap, ARRAYNUMBER(TLSJunctionMap))
96FXIMPLEMENT(GNETLSEditorFrame::TLSPrograms, GNEGroupBoxModule, TLSProgramsMap, ARRAYNUMBER(TLSProgramsMap))
97FXIMPLEMENT(GNETLSEditorFrame::TLSAttributes, GNEGroupBoxModule, TLSAttributesMap, ARRAYNUMBER(TLSAttributesMap))
98FXIMPLEMENT(GNETLSEditorFrame::TLSPhases, GNEGroupBoxModule, TLSPhasesMap, ARRAYNUMBER(TLSPhasesMap))
99FXIMPLEMENT(GNETLSEditorFrame::TLSFile, GNEGroupBoxModule, TLSFileMap, ARRAYNUMBER(TLSFileMap))
100
101
102// ===========================================================================
103// method definitions
104// ===========================================================================
105
107 GNEFrame(viewParent, viewNet, TL("Edit Traffic Light")),
108 myEditedDef(nullptr) {
109
110 // Create Overlapped Inspection module only for junctions
112
113 // create TLSJunction module
115
116 // create TLSPrograms module
118
119 // create TLSAttributes module
121
122 // create TLSPhases module
124
125 // create TLSFile module
127}
128
129
131 myTLSPhases->clearPhaseTable();
132}
133
134
135void
137 myOverlappedInspection->clearOverlappedInspection();
138 // show
140}
141
142
143void
145 // recalc table width
146 myTLSPhases->getPhaseTable()->recalcTableWidth();
147}
148
149
150void
152 if (myTLSJunction) {
153 myTLSJunction->updateTLSJunction();
154 }
155 if (myTLSPrograms) {
156 myTLSPrograms->updateTLSPrograms();
157 }
158 if (myTLSAttributes) {
159 myTLSAttributes->updateTLSAttributes();
160 }
161 if (myTLSPhases) {
162 myTLSPhases->updateTLSPhases();
163 }
164 if (myTLSFile) {
165 myTLSFile->updateTLSFile();
166 }
167 update();
168}
169
170
171void
172GNETLSEditorFrame::editTLS(GNEViewNetHelper::ViewObjectsSelector& viewObjects, const Position& clickedPosition, const bool shiftKeyPressed) {
173 // first check if in viewObjects there is a junction
174 if (viewObjects.getJunctionFront()) {
175 // check if we're adding or removing joined TLSs
176 if (myTLSJunction->isJoiningJunctions()) {
177 myTLSJunction->toggleJunctionSelected(viewObjects.getJunctionFront());
178 } else {
179 // show objects under cursor
180 myOverlappedInspection->showOverlappedInspection(viewObjects, clickedPosition, shiftKeyPressed);
181 // hide if we inspect only one junction
182 if (myOverlappedInspection->getNumberOfOverlappedACs()) {
183 if (myOverlappedInspection->getNumberOfOverlappedACs() == 1) {
184 myOverlappedInspection->hiderOverlappedInspection();
185 }
186 for (const auto& junction : viewObjects.getJunctions()) {
187 if (junction == myOverlappedInspection->getCurrentAC()) {
188 editJunction(junction);
189 }
190 }
191 }
192 }
193 } else if (viewObjects.getAdditionalFront() && myTLSAttributes->isSetDetectorsToggleButtonEnabled() &&
195 myTLSAttributes->toggleE1DetectorSelection(viewObjects.getAdditionalFront());
196 }
197 myViewNet->update();
198}
199
200
201bool
203 if (myTLSPrograms->checkHaveModifications()) {
204 // show question dialog
205 const GNEQuestionBasicDialog questionDialog(myViewNet->getViewParent()->getGNEAppWindows(),
207 TL("Save TLS Changes"),
208 TL("There are unsaved changes in the currently edited traffic light."),
209 TL("Do you want to save it before changing mode?"));
210 // continue depending of result
211 if (questionDialog.getResult() == GNEDialog::Result::ACCEPT) {
212 // save modifications
213 myTLSPrograms->onCmdSaveChanges(nullptr, 0, nullptr);
214 return true;
215 } else if (questionDialog.getResult() == GNEDialog::Result::CANCEL) {
216 // cancel modifications
217 myTLSPrograms->onCmdDiscardChanges(nullptr, 0, nullptr);
218 return true;
219 } else {
220 // abort changing mode
221 return false;
222 }
223 } else {
224 return true;
225 }
226}
227
228
229bool
230GNETLSEditorFrame::parseTLSPrograms(const std::string& file) {
231 NBTrafficLightLogicCont& tllCont = myViewNet->getNet()->getTLLogicCont();
232 NBTrafficLightLogicCont tmpTLLCont;
233 NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myViewNet->getNet()->getEdgeCont());
234 // existing definitions must be available to update their programs
235 std::set<NBTrafficLightDefinition*> origDefs;
236 for (NBTrafficLightDefinition* def : tllCont.getDefinitions()) {
237 // make a duplicate of every program
238 NBTrafficLightLogic* logic = tllCont.getLogic(def->getID(), def->getProgramID());
239 if (logic != nullptr) {
240 NBTrafficLightDefinition* duplicate = new NBLoadedSUMOTLDef(*def, *logic);
241 std::vector<NBNode*> nodes = def->getNodes();
242 for (auto it_node : nodes) {
243 GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
244 myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, false, false), true);
245 myViewNet->getUndoList()->add(new GNEChange_TLS(junction, duplicate, true), true);
246 }
247 tmpTLLCont.insert(duplicate);
248 origDefs.insert(duplicate);
249 } else {
250 WRITE_WARNINGF(TL("tlLogic '%', program '%' could not be built"), def->getID(), def->getProgramID());
251 }
252 }
253 //std::cout << " initialized tmpCont with " << origDefs.size() << " defs\n";
254 XMLSubSys::runParser(tllHandler, file);
255
256 std::vector<NBLoadedSUMOTLDef*> loadedTLS;
257 for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
258 NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
259 if (sdef != nullptr) {
260 loadedTLS.push_back(sdef);
261 }
262 }
263 myViewNet->setStatusBarText(TL("Loaded ") + toString(loadedTLS.size()) + TL(" programs"));
264 for (auto def : loadedTLS) {
265 if (origDefs.count(def) != 0) {
266 // already add to undolist before
267 //std::cout << " skip " << def->getDescription() << "\n";
268 continue;
269 }
270 std::vector<NBNode*> nodes = def->getNodes();
271 //std::cout << " add " << def->getDescription() << " for nodes=" << toString(nodes) << "\n";
272 for (auto it_node : nodes) {
273 GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
274 //myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, false), true);
275 myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, true), true);
276 }
277 }
278 // clean up temporary container to avoid deletion of defs when its destruct is called
279 for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
280 tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
281 }
282 return true;
283}
284
285
286void
288 auto junction = dynamic_cast<GNEJunction*>(AC);
289 if (junction) {
290 editJunction(junction);
291 }
292}
293
294
295void
297 if (myTLSJunction->getCurrentJunction()) {
298 myTLSJunction->getCurrentJunction()->selectTLS(false);
299 if (myTLSPrograms->getNumberOfPrograms() > 0) {
300 for (const auto& node : myTLSPrograms->getCurrentTLSPrograms()->getNodes()) {
301 myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(node->getID())->selectTLS(false);
302 }
303 }
304 }
305 // clean data structures
306 myTLSJunction->setCurrentJunction(nullptr);
307 // check if delete myEditedDef
308 if (myEditedDef) {
309 delete myEditedDef;
310 myEditedDef = nullptr;
311 }
312 // clear internal lanes
313 buildInternalLanes(nullptr);
314 // clean up attributes
315 myTLSPrograms->clearTLSProgramss();
316 // clean up attributes
317 myTLSAttributes->clearTLSAttributes();
318 // only clears when there are no definitions
319 myTLSPhases->initPhaseTable();
320}
321
322
327
328
333
334
339
340
345
346
347void
349 // clean up previous internal lanes
350 for (const auto& internalLanes : myInternalLanes) {
351 for (const auto& internalLane : internalLanes.second) {
352 // remove internal lane from ACs
353 myViewNet->getNet()->getAttributeCarriers()->deleteInternalLane(internalLane);
354 // delete internal lane
355 delete internalLane;
356 }
357 }
358 // clear container
359 myInternalLanes.clear();
360 // create new internal lanes
361 if (tlDef != nullptr) {
362 const int NUM_POINTS = 10;
363 const NBNode* nbnCurrentJunction = myTLSJunction->getCurrentJunction()->getNBNode();
364 // get innerID NWWriter_SUMO::writeInternalEdges
365 const std::string innerID = ":" + nbnCurrentJunction->getID();
366 const NBConnectionVector& links = tlDef->getControlledLinks();
367 // iterate over links
368 for (const auto& link : links) {
369 int tlIndex = link.getTLIndex();
370 PositionVector shape;
371 try {
372 const NBEdge::Connection& con = link.getFrom()->getConnection(link.getFromLane(), link.getTo(), link.getToLane());
373 shape = con.shape;
374 shape.append(con.viaShape);
375 } catch (ProcessError&) {
376 shape = link.getFrom()->getToNode()->computeInternalLaneShape(link.getFrom(), NBEdge::Connection(link.getFromLane(),
377 link.getTo(), link.getToLane()), NUM_POINTS);
378 }
379 if (shape.length() < 2) {
380 // enlarge shape to ensure visibility
381 shape.clear();
382 const PositionVector laneShapeFrom = link.getFrom()->getLaneShape(link.getFromLane());
383 const PositionVector laneShapeTo = link.getTo()->getLaneShape(link.getToLane());
384 shape.push_back(laneShapeFrom.positionAtOffset(MAX2(0.0, laneShapeFrom.length() - 1)));
385 shape.push_back(laneShapeTo.positionAtOffset(MIN2(1.0, laneShapeFrom.length())));
386 }
387 GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), innerID + '_' + toString(tlIndex), shape, tlIndex);
388 // add into atribute carriers
389 myViewNet->getNet()->getAttributeCarriers()->insertInternalLane(internalLane);
390 myInternalLanes[tlIndex].push_back(internalLane);
391 }
392 // iterate over crossings
393 for (const auto& nbn : tlDef->getNodes()) {
394 for (const auto& crossing : nbn->getCrossings()) {
395 if (crossing->tlLinkIndex2 > 0 && crossing->tlLinkIndex2 != crossing->tlLinkIndex) {
396 // draw both directions
397 PositionVector forward = crossing->shape;
398 forward.move2side(crossing->width / 4);
399 GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, forward, crossing->tlLinkIndex);
400 // add into atribute carriers
401 myViewNet->getNet()->getAttributeCarriers()->insertInternalLane(internalLane);
402 myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
403 PositionVector backward = crossing->shape.reverse();
404 backward.move2side(crossing->width / 4);
405 GNEInternalLane* internalLaneReverse = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id + "_r", backward, crossing->tlLinkIndex2);
406 // add into atribute carriers
407 myViewNet->getNet()->getAttributeCarriers()->insertInternalLane(internalLaneReverse);
408 myInternalLanes[crossing->tlLinkIndex2].push_back(internalLaneReverse);
409 } else {
410 // draw only one lane for both directions
411 GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, crossing->shape, crossing->tlLinkIndex);
412 // add into atribute carriers
413 myViewNet->getNet()->getAttributeCarriers()->insertInternalLane(internalLane);
414 myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
415 }
416 }
417 }
418 }
419}
420
421
422std::string
426
427
430 if ((index >= 0) || (index < (int)myEditedDef->getLogic()->getPhases().size())) {
431 return myEditedDef->getLogic()->getPhases().at(index);
432 } else {
433 throw ProcessError(TL("Invalid phase index"));
434 }
435}
436
437
438void
440 myTLSPrograms->markAsModified();
441 // get current selected row
442 const auto selectedRow = myTLSPhases->getPhaseTable()->getCurrentSelectedRow();
443 if (myViewNet->changeAllPhases()) {
444 for (int row = 0; row < (int)myEditedDef->getLogic()->getPhases().size(); row++) {
445 myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
446 }
447 } else {
448 myEditedDef->getLogic()->setPhaseState(myTLSPhases->getPhaseTable()->getCurrentSelectedRow(), lane->getTLIndex(), lane->getLinkState());
449 }
450 // init phaseTable
451 myTLSPhases->initPhaseTable();
452 // select row
453 myTLSPhases->getPhaseTable()->selectRow(selectedRow);
454 // focus table
455 myTLSPhases->getPhaseTable()->setFocus();
456}
457
458
459void
460GNETLSEditorFrame::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* eventData) {
461 if (myEditedDef != nullptr) {
462 myTLSPrograms->markAsModified();
463 const NBConnectionVector& links = myEditedDef->getControlledLinks();
464 std::set<std::string> fromIDs;
465 fromIDs.insert(lane->getMicrosimID());
466 // if neither the lane nor its edge are selected, apply changes to the whole edge
468 for (auto it_lane : lane->getParentEdge()->getChildLanes()) {
469 fromIDs.insert(it_lane->getMicrosimID());
470 }
471 } else {
472 // if the edge is selected, apply changes to all lanes of all selected edges
474 const auto selectedEdge = myViewNet->getNet()->getAttributeCarriers()->getSelectedEdges();
475 for (const auto& edge : selectedEdge) {
476 for (auto it_lane : edge->getChildLanes()) {
477 fromIDs.insert(it_lane->getMicrosimID());
478 }
479 }
480 }
481 // if the lane is selected, apply changes to all selected lanes
482 if (lane->isAttributeCarrierSelected()) {
483 const auto selectedLanes = myViewNet->getNet()->getAttributeCarriers()->getSelectedLanes();
484 for (auto it_lane : selectedLanes) {
485 fromIDs.insert(it_lane->getMicrosimID());
486 }
487 }
488
489 }
490 // set new state for all connections from the chosen lane IDs
491 for (auto it : links) {
492 if (fromIDs.count(it.getFrom()->getLaneID(it.getFromLane())) > 0) {
493 std::vector<GNEInternalLane*> lanes = myInternalLanes[it.getTLIndex()];
494 for (auto it_lane : lanes) {
495 it_lane->onDefault(obj, sel, eventData);
496 }
497 }
498 }
499 }
500}
501
502
503bool
505 if (myEditedDef != nullptr) {
506 const NBConnectionVector& links = myEditedDef->getControlledLinks();
507 for (auto it : links) {
508 if (it.getFrom()->getID() == edge->getMicrosimID()) {
509 return true;
510 }
511 }
512 }
513 return false;
514}
515
516
517void
519 if ((myTLSJunction->getCurrentJunction() == nullptr) || (!myTLSPrograms->checkHaveModifications() && (junction != myTLSJunction->getCurrentJunction()))) {
520 // discard previous changes
521 myTLSPrograms->discardChanges(false);
522 // set junction
523 myTLSJunction->setCurrentJunction(junction);
524 // init TLS definitions
525 if (myTLSPrograms->initTLSPrograms()) {
526 // init TLSAttributes
527 myTLSAttributes->initTLSAttributes();
528 // begin undo-list
529 myViewNet->getUndoList()->begin(GUIIcon::MODETLS, TL("modifying TLS definition"));
530 // only select TLS if getCurrentJunction exist
531 if (myTLSJunction->getCurrentJunction()) {
532 myTLSJunction->getCurrentJunction()->selectTLS(true);
533 }
534 if (myTLSPrograms->getNumberOfPrograms() > 0) {
535 for (NBNode* node : myTLSPrograms->getCurrentTLSPrograms()->getNodes()) {
536 myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(node->getID())->selectTLS(true);
537 }
538 // update color
539 myTLSPhases->updateTLSColoring();
540 }
541 }
542 } else {
543 myViewNet->setStatusBarText(TL("Unsaved modifications. Abort or Save"));
544 }
546}
547
548
550GNETLSEditorFrame::getSUMOTime(const std::string& string) {
552}
553
554const std::string
558
559// ---------------------------------------------------------------------------
560// GNETLSEditorFrame::TLSAttributes - methods
561// ---------------------------------------------------------------------------
562
564 GNEGroupBoxModule(TLSEditorParent, TL("Traffic Light Attributes")),
565 myTLSEditorParent(TLSEditorParent) {
566 // create frame, label and TextField for Offset (By default disabled)
567 FXHorizontalFrame* horizontalFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
568 new FXLabel(horizontalFrame, toString(SUMO_ATTR_OFFSET).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
570 myOffsetTextField->disable();
571 // create frame, label and TextField for parameters (By default disabled)
572 horizontalFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
575 myButtonEditParameters->disable();
576 myParametersTextField->disable();
577 // create set detectors button (By default disabled)
580 TL("Assign E1 detectors") + std::string("\t") + TL("Enable assign E1 mode") + std::string("\t") + TL("Assign E1 detectors to the current TLS"),
581 TL("Assign E1 detectors") + std::string("\t") + TL("Disable assign E1 mode") + std::string("\t") + TL("Assign E1 detectors to the current TLS"),
585}
586
587
589
590
591void
593 if (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() == 0) {
594 // no TLS programs, disable elements
595 myOffsetTextField->disable();
596 myButtonEditParameters->disable();
597 myParametersTextField->disable();
598 // disable E1 detector mode
601 // clear E1 detectors
602 if (myE1Detectors.size() > 0) {
603 myE1Detectors.clear();
604 myTLSEditorParent->getViewNet()->update();
605 }
606 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
607 // joining TLSs, disable button
608 myOffsetTextField->disable();
609 myButtonEditParameters->disable();
610 myParametersTextField->disable();
611 // disable E1 detector mode
614 // clear E1 detectors
615 if (myE1Detectors.size() > 0) {
616 myE1Detectors.clear();
617 myTLSEditorParent->getViewNet()->update();
618 }
620 // set detectors toggle button is enabled, disable elements
621 myOffsetTextField->disable();
622 myButtonEditParameters->disable();
623 myParametersTextField->disable();
624 } else {
625 myOffsetTextField->enable();
626 myButtonEditParameters->enable();
627 myParametersTextField->enable();
628 // disable E1 detector mode in static
629 if (myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms()->getType() != TrafficLightType::ACTUATED) {
630 // disable E1 detector mode
633 // clear E1 detectors
634 if (myE1Detectors.size() > 0) {
635 myE1Detectors.clear();
636 myTLSEditorParent->getViewNet()->update();
637 }
638 } else {
640 }
641 }
642}
643
644
645void
649
650
651void
655
656
657void
659 // get current edited junction
660 const auto junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
661 if (junction == nullptr) {
662 throw ProcessError("Junction cannot be NULL");
663 } else {
664 // enable Offset
665 myOffsetTextField->enable();
667 // enable parameters
668 myButtonEditParameters->enable();
669 myParametersTextField->enable();
671 // reset mySetDetectorsToggleButton
673 }
674}
675
676
677void
679 // clear and disable Offset TextField
680 myOffsetTextField->setText("");
681 myOffsetTextField->disable();
683 // clear and disable parameters TextField
684 myButtonEditParameters->disable();
685 myParametersTextField->setText("");
686 myParametersTextField->disable();
688}
689
690
695
696
697void
702
703
704bool
708 return true;
709 } else {
711 return false;
712 }
713}
714
715
716std::string
720
721
722void
724 myParametersTextField->setText(parameters.c_str());
726 // update E1 detectors
727 if (myTLSEditorParent->myEditedDef->getType() != TrafficLightType::STATIC) {
729 }
730}
731
732
733bool
743
744
745bool
749
750
751bool
753 // get E1 lane ID
754 const auto laneID = E1->getParentLanes().front()->getID();
755 // iterate over all E1 detectors
756 for (auto it = myE1Detectors.begin(); it != myE1Detectors.end(); it++) {
757 if (E1->getID() == it->second) {
758 // already selected, then remove it from detectors
759 myE1Detectors.erase(it);
760 // and remove it from parameters
761 myTLSEditorParent->myEditedDef->unsetParameter(laneID);
762 myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
763 // mark TL as modified
764 myTLSEditorParent->myTLSPrograms->markAsModified();
765 return true;
766 } else if (laneID == it->first) {
767 // there is another E1 in the same lane, then swap
768 myE1Detectors.erase(it);
769 myE1Detectors[laneID] = E1->getID();
770 // also in parameters
771 myTLSEditorParent->myEditedDef->setParameter(laneID, E1->getID());
772 myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
773 // mark TL as modified
774 myTLSEditorParent->myTLSPrograms->markAsModified();
775 return true;
776 }
777 }
778 // add it in parameters
779 myE1Detectors[laneID] = E1->getID();
780 myTLSEditorParent->myEditedDef->setParameter(laneID, E1->getID());
781 myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
782 // mark TL as modified
783 myTLSEditorParent->myTLSPrograms->markAsModified();
784 return true;
785}
786
787
788const std::map<std::string, std::string>&
792
793
794void
798
799
800long
802 if (isValidOffset()) {
803 myTLSEditorParent->myTLSPrograms->markAsModified();
804 myTLSEditorParent->myEditedDef->setOffset(getOffset());
805 myOffsetTextField->killFocus();
806 myTLSEditorParent->updateModules();
807 }
808 return 1;
809}
810
811
812long
814 if (isValidParameters()) {
815 myTLSEditorParent->myTLSPrograms->markAsModified();
816 myTLSEditorParent->myEditedDef->setParametersStr(getParameters());
817 myParametersTextField->killFocus();
818 myTLSEditorParent->updateModules();
819 }
820 return 1;
821}
822
823
824long
826 auto GNEApp = myTLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows();
827 // continue depending of myEditedDef
828 if (myTLSEditorParent->myEditedDef) {
829 // get previous parameters
830 const auto previousParameters = getParameters();
831 // open parameters dialog
832 const GNEParametersDialog parametersDialog(GNEApp, myTLSEditorParent->myEditedDef->getParametersMap());
833 // continue depending of result
834 if (parametersDialog.getResult() == GNEDialog::Result::ACCEPT) {
835 // set parameters in myEditedDef
836 myTLSEditorParent->myEditedDef->setParameters(parametersDialog.getEditedParameters());
837 // set parameters in textfield
838 setParameters(myTLSEditorParent->myEditedDef->getParametersStr());
839 // only mark as modified if parameters are different
840 if (getParameters() != previousParameters) {
841 myTLSEditorParent->myTLSPrograms->markAsModified();
842 }
843 }
844 myTLSEditorParent->updateModules();
845 }
846 return 1;
847}
848
849
850long
852 if (mySetDetectorsToggleButton->getState()) {
853 // set special color
854 mySetDetectorsToggleButton->setBackColor(FXRGBA(253, 255, 206, 255));
855 } else {
856 // restore default color
857 mySetDetectorsToggleButton->setBackColor(4293980400);
858 }
859 myTLSEditorParent->updateModules();
860 // update view
861 myTLSEditorParent->getViewNet()->update();
862 return 1;
863}
864
865
866void
868 // first clear E1 detectors
869 myE1Detectors.clear();
870 // iterate over parameters
871 for (const auto& parameter : myTLSEditorParent->myEditedDef->getParametersMap()) {
872 // check if both lane and E1 exists
873 if (myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveLane(parameter.first, false) &&
874 myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_INDUCTION_LOOP, parameter.second, false)) {
875 // add it into list
876 myE1Detectors[parameter.first] = parameter.second;
877 }
878 }
879 myTLSEditorParent->updateModules();
880 // update view net
881 myTLSEditorParent->getViewNet()->update();
882}
883
884// ---------------------------------------------------------------------------
885// GNETLSEditorFrame::TLSJunction - methods
886// ---------------------------------------------------------------------------
887
889 GNEGroupBoxModule(TLSEditorParent, TL("Traffic Light")),
890 myTLSEditorParent(TLSEditorParent),
891 myCurrentJunction(nullptr) {
892 const auto staticTooltip = TLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();
893 // Create frame for junction IDs
894 FXHorizontalFrame* junctionIDFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
895 myJunctionIDLabel = new FXLabel(junctionIDFrame, TL("Junction ID"), nullptr, GUIDesignLabelThickedFixed(100));
896 myJunctionIDTextField = new MFXTextFieldIcon(junctionIDFrame, staticTooltip, GUIIcon::EMPTY, nullptr, 0, GUIDesignTextField);
897 // junction ID remains always disabled
898 myJunctionIDTextField->disable();
899 // Create frame for TLS Program ID
900 FXHorizontalFrame* TLSIDFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
901 new FXLabel(TLSIDFrame, TL("TLS ID"), nullptr, GUIDesignLabelThickedFixed(100));
903 // create frame, label and textfield for type
904 FXHorizontalFrame* typeFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
905 new FXLabel(typeFrame, toString(SUMO_ATTR_TYPE).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
906 myTLSTypeComboBox = new MFXComboBoxIcon(typeFrame, staticTooltip, false, GUIDesignComboBoxVisibleItems,
908 // fill comboBox (only certain TL types)
909 myTLSTypeComboBox->appendIconItem(toString(TrafficLightType::STATIC).c_str());
910 myTLSTypeComboBox->appendIconItem(toString(TrafficLightType::ACTUATED).c_str());
912 myTLSTypeComboBox->appendIconItem(toString(TrafficLightType::NEMA).c_str());
913 // create frame for join buttons
914 FXHorizontalFrame* joinButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
915 // create join states button
916 myJoinTLSToggleButton = new MFXToggleButtonTooltip(joinButtons, staticTooltip,
917 TL("Join") + std::string("\t") + TL("Enable join mode") + std::string("\t") + TL("Join TLS and junctions in the current junction."),
918 TL("Join") + std::string("\t") + TL("Disable join mode") + std::string("\t") + TL("Join TLS and junctions in the current junction."),
921 myDisjoinTLSButton = new MFXButtonTooltip(joinButtons, staticTooltip,
922 TL("Disjoin") + std::string("\t") + TL("Disjoin current TLS") + std::string("\t") + TL("Disjoin current TLS."),
924 // create frame for join control buttons
926 // create create tlDef button
927 GUIDesigns::buildFXButton(myJoinControlButtons, TL("Accept"), "", TL("Finish join."),
929 GUIDesigns::buildFXButton(myJoinControlButtons, TL("Cancel"), "", TL("Cancel Join."),
931 // update junction description after creation
933 // show TLS Junction
934 show();
935}
936
937
939
940
941void
943 if ((myCurrentJunction == nullptr) ||
944 (myCurrentJunction->getNBNode()->getControllingTLS().size() == 0)) {
945 // no TLS
946 myJunctionIDTextField->setText(TL("No junction selected"));
947 myTLSIDTextField->setText("");
948 myTLSIDTextField->disable();
949 myTLSTypeComboBox->disable();
950 myJoinTLSToggleButton->disable();
951 myDisjoinTLSButton->disable();
952 myJoinControlButtons->hide();
953 } else {
954 // get first controled TLS
955 const auto TLS = (*myCurrentJunction->getNBNode()->getControllingTLS().begin());
956 // set TLS type in comboBox
957 const int index = myTLSTypeComboBox->findItem(myCurrentJunction->getAttribute(SUMO_ATTR_TLTYPE).c_str());
958 if (index != -1) {
959 myTLSTypeComboBox->setCurrentItem(index, FALSE);
960 }
961 // set text field IDs
962 myJunctionIDTextField->setText(myCurrentJunction->getID().c_str());
963 myTLSIDTextField->setText(TLS->getID().c_str());
964 // continue with more options
965 if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled() ||
966 myTLSEditorParent->myTLSPrograms->checkHaveModifications()) {
967 // disable if selecting selecting detectors or we modified the program
968 myTLSIDTextField->setText("");
969 myTLSIDTextField->disable();
970 myTLSTypeComboBox->disable();
971 myJoinTLSToggleButton->disable();
972 myDisjoinTLSButton->disable();
973 myJoinControlButtons->hide();
974 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
975 // partial disable due joining
976 myTLSIDTextField->setText("");
977 myTLSIDTextField->disable();
978 myTLSTypeComboBox->disable();
979 myDisjoinTLSButton->disable();
980 // enable join TLS and show control buttons
981 myJoinTLSToggleButton->enable();
982 myJoinControlButtons->show();
983 } else {
984 // enable
985 myTLSIDTextField->enable();
986 myTLSTypeComboBox->enable();
987 myJoinTLSToggleButton->enable();
988 // disjoint button only if we have more than one TLS controlled
989 if (TLS->getNodes().size() == 1) {
990 myDisjoinTLSButton->disable();
991 } else {
992 myDisjoinTLSButton->enable();
993 }
994 }
995 }
996}
997
998
1003
1004
1005void
1007 myCurrentJunction = junction;
1008 // resfresh module
1010}
1011
1012
1013bool
1015 return (myJoinTLSToggleButton->getState() == TRUE);
1016}
1017
1018
1019bool
1021 return (std::find(mySelectedJunctionIDs.begin(), mySelectedJunctionIDs.end(), junction->getID()) != mySelectedJunctionIDs.end());
1022}
1023
1024
1025void
1027 // avoid current junction
1028 if (junction != myCurrentJunction) {
1029 // find ID in selected junctions
1030 auto it = std::find(mySelectedJunctionIDs.begin(), mySelectedJunctionIDs.end(), junction->getID());
1031 // check if add or remove
1032 if (it == mySelectedJunctionIDs.end()) {
1033 mySelectedJunctionIDs.push_back(junction->getID());
1034 } else {
1035 mySelectedJunctionIDs.erase(it);
1036 }
1037 }
1038}
1039
1040
1041const std::vector<std::string>&
1045
1046
1047long
1049 // get IDs
1050 const std::string currentTLID = (*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getID();
1051 const std::string newTLID = myTLSIDTextField->getText().text();
1052 // check if ID is valid
1053 if (newTLID.empty() || (newTLID == currentTLID)) {
1054 // same ID or empty
1056 myTLSIDTextField->setText(currentTLID.c_str());
1057 myTLSIDTextField->killFocus();
1058 myTLSEditorParent->update();
1059 // show all moduls
1060 myTLSEditorParent->myTLSPrograms->showTLSPrograms();
1061 myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1062 myTLSEditorParent->myTLSPhases->showTLSPhases();
1063 myTLSEditorParent->myTLSFile->showTLSFile();
1064 } else if (!SUMOXMLDefinitions::isValidNetID(newTLID) || myCurrentJunction->getNet()->getTLLogicCont().exist(newTLID)) {
1065 // set invalid color
1067 // hide moduls
1068 myTLSEditorParent->myTLSPrograms->hideTLSPrograms();
1069 myTLSEditorParent->myTLSAttributes->hideTLSAttributes();
1070 myTLSEditorParent->myTLSPhases->hideTLSPhases();
1071 myTLSEditorParent->myTLSFile->hideTLSFile();
1072 } else {
1073 // make a copy of myCurrentJunction and current tlDef (because will be reset after calling discardChanges)
1074 auto junction = myCurrentJunction;
1075 const auto tlDef = myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms();
1076 // restore color
1078 myTLSIDTextField->killFocus();
1079 myTLSEditorParent->update();
1080 // discard previous changes
1081 myTLSEditorParent->myTLSPrograms->discardChanges(false);
1082 // change name using undo-List
1083 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("rename TLS"));
1084 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, tlDef, newTLID), true);
1085 myTLSEditorParent->getViewNet()->getUndoList()->end();
1086 // show all moduls
1087 myTLSEditorParent->myTLSPrograms->showTLSPrograms();
1088 myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1089 myTLSEditorParent->myTLSPhases->showTLSPhases();
1090 myTLSEditorParent->myTLSFile->showTLSFile();
1091 // edit junction again
1092 myTLSEditorParent->editJunction(junction);
1093 }
1094 myTLSEditorParent->updateModules();
1095 return 1;
1096}
1097
1098
1099long
1101 // get IDs
1102 const std::string currentTLType = toString((*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getType());
1103 const std::string newTLType = myTLSTypeComboBox->getText().text();
1104 // check if ID is valid
1105 if (newTLType.empty() || (newTLType == currentTLType)) {
1106 // same ID or empty, don't change
1108 // set value
1109 const int index = myTLSTypeComboBox->findItem(currentTLType.c_str());
1110 if (index == -1) {
1111 myTLSTypeComboBox->disable();
1112 } else {
1113 myTLSTypeComboBox->setCurrentItem(index);
1114 myTLSTypeComboBox->enable();
1115 }
1116 myTLSTypeComboBox->killFocus();
1117 myTLSEditorParent->update();
1118 // show all moduls
1119 myTLSEditorParent->myTLSPrograms->showTLSPrograms();
1120 myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1121 myTLSEditorParent->myTLSPhases->showTLSPhases();
1122 myTLSEditorParent->myTLSFile->showTLSFile();
1123 } else if (!SUMOXMLDefinitions::TrafficLightTypes.hasString(newTLType)) {
1124 // set invalid color
1126 // hide moduls
1127 myTLSEditorParent->myTLSPrograms->hideTLSPrograms();
1128 myTLSEditorParent->myTLSAttributes->hideTLSAttributes();
1129 myTLSEditorParent->myTLSPhases->hideTLSPhases();
1130 myTLSEditorParent->myTLSFile->hideTLSFile();
1131 } else {
1132 // reset color
1134 myTLSTypeComboBox->killFocus();
1135 myTLSEditorParent->update();
1136 // make a copy of myCurrentJunction (because will be reset after calling discardChanges)
1137 auto junction = myCurrentJunction;
1138 // discard previous changes
1139 myTLSEditorParent->myTLSPrograms->discardChanges(false);
1140 // change name using undo-List
1141 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("change TLS type"));
1142 junction->setAttribute(SUMO_ATTR_TLTYPE, newTLType, myTLSEditorParent->getViewNet()->getUndoList());
1143 myTLSEditorParent->getViewNet()->getUndoList()->end();
1144 // show all moduls
1145 myTLSEditorParent->myTLSPrograms->showTLSPrograms();
1146 myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1147 myTLSEditorParent->myTLSPhases->showTLSPhases();
1148 myTLSEditorParent->myTLSFile->showTLSFile();
1149 // edit junction again
1150 myTLSEditorParent->editJunction(junction);
1151 }
1152 myTLSEditorParent->updateModules();
1153 return 1;
1154
1155}
1156
1157
1158long
1160 if (myJoinTLSToggleButton->getState()) {
1161 // set special color
1162 myJoinTLSToggleButton->setBackColor(FXRGBA(253, 255, 206, 255));
1163 // clear and fill mySelectedJunctionIDs
1164 mySelectedJunctionIDs.clear();
1165 // get all nodes controlled by this TLS
1166 const auto TLNodes = (*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getNodes();
1167 // fill mySelectedJunctionIDs with TLNodes
1168 mySelectedJunctionIDs.clear();
1169 for (const auto& TLNode : TLNodes) {
1170 mySelectedJunctionIDs.push_back(TLNode->getID());
1171 }
1172 // make a copy of selected junctions
1174 // show control buttons
1175 myJoinControlButtons->show();
1176 getCollapsableFrame()->recalc();
1177 } else {
1178 // hide control buttons
1179 myJoinControlButtons->hide();
1180 getCollapsableFrame()->recalc();
1181 // make a copy of current junction
1182 const auto currentJunction = myCurrentJunction;
1183 // declare vectors for junctions
1184 std::vector<GNEJunction*> selectedJunctions, resetTLJunctions;
1185 // get selected junctions (all except current
1186 for (const auto& selectedJunctionID : mySelectedJunctionIDs) {
1187 if (selectedJunctionID != currentJunction->getID()) {
1188 selectedJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(selectedJunctionID));
1189 }
1190 }
1191 // get junctions to reset TL (all TL nodes except current)
1192 for (const auto& TLNBNode : (*currentJunction->getNBNode()->getControllingTLS().begin())->getNodes()) {
1193 if (TLNBNode != currentJunction->getNBNode()) {
1194 resetTLJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLNBNode->getID()));
1195 }
1196 }
1197 // discard changes
1198 myTLSEditorParent->myTLSPrograms->discardChanges(false);
1199 // begin undo list
1200 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("join TLS"));
1201 // remove tl from TLNBNode
1202 for (const auto& resetTLJunction : resetTLJunctions) {
1203 resetTLJunction->setAttribute(SUMO_ATTR_TYPE, "priority", myTLSEditorParent->getViewNet()->getUndoList());
1204 }
1205 // now update it in all joined junctions
1206 for (const auto& selectedJunction : selectedJunctions) {
1207 selectedJunction->setAttribute(SUMO_ATTR_TYPE, currentJunction->getAttribute(SUMO_ATTR_TYPE), myTLSEditorParent->getViewNet()->getUndoList());
1208 selectedJunction->setAttribute(SUMO_ATTR_TLID, currentJunction->getAttribute(SUMO_ATTR_TLID), myTLSEditorParent->getViewNet()->getUndoList());
1209 }
1210 // end undo list
1211 myTLSEditorParent->getViewNet()->getUndoList()->end();
1212 // restore default color
1213 myJoinTLSToggleButton->setBackColor(4293980400);
1214 // clear selected junction IDs
1215 mySelectedJunctionIDs.clear();
1216 // edit junction again
1217 myTLSEditorParent->editJunction(currentJunction);
1218 }
1219 myTLSEditorParent->updateModules();
1220 // update view
1221 myTLSEditorParent->getViewNet()->update();
1222 return 1;
1223}
1224
1225
1226long
1228 // make a copy of current junction
1229 const auto currentJunction = myCurrentJunction;
1230 // declare vectors for junctions
1231 std::vector<GNEJunction*> resetTLJunctions;
1232 // get junctions to reset TL
1233 for (const auto& TLNBNode : (*currentJunction->getNBNode()->getControllingTLS().begin())->getNodes()) {
1234 resetTLJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLNBNode->getID()));
1235 }
1236 // save TL types
1237 const auto type = resetTLJunctions.front()->getAttribute(SUMO_ATTR_TYPE);
1238 const auto tlType = resetTLJunctions.front()->getAttribute(SUMO_ATTR_TLTYPE);
1239 // discard changes
1240 myTLSEditorParent->myTLSPrograms->discardChanges(false);
1241 // begin undo list
1242 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("disjoin TLS"));
1243 // the disjoint tlIds will be the junction ids. Ensure that there is no name clash with the current tlId
1244 NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1245 const std::string oldId = currentJunction->getAttribute(SUMO_ATTR_TLID);
1246 const std::string tmpIdBase = oldId + "_TMP";
1247 int tmpIndex = 0;
1248 std::string tmpId = tmpIdBase + toString(tmpIndex);
1249 while (tllCont.exist(tmpId)) {
1250 tmpId = tmpIdBase + toString(++tmpIndex);
1251 }
1252 for (NBTrafficLightDefinition* tlDef : currentJunction->getNBNode()->getControllingTLS()) {
1253 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(currentJunction, tlDef, tmpId), true);
1254 }
1255 // remove tl from TLNBNode and the re-initialize as single traffic light
1256 for (const auto& resetTLJunction : resetTLJunctions) {
1257 resetTLJunction->setAttribute(SUMO_ATTR_TYPE, "priority", myTLSEditorParent->getViewNet()->getUndoList());
1258 resetTLJunction->setAttribute(SUMO_ATTR_TYPE, type, myTLSEditorParent->getViewNet()->getUndoList());
1259 resetTLJunction->setAttribute(SUMO_ATTR_TLTYPE, tlType, myTLSEditorParent->getViewNet()->getUndoList());
1260 }
1261 // end undo list
1262 myTLSEditorParent->getViewNet()->getUndoList()->end();
1263 // restore default color
1264 myJoinTLSToggleButton->setBackColor(4293980400);
1265 // clear selected junction IDs
1266 mySelectedJunctionIDs.clear();
1267 // edit junction again
1268 myTLSEditorParent->editJunction(currentJunction);
1269 myTLSEditorParent->updateModules();
1270 return 1;
1271}
1272
1273
1274long
1276 myJoinTLSToggleButton->setState(FALSE, TRUE);
1277 myTLSEditorParent->updateModules();
1278 return 1;
1279}
1280
1281
1282long
1284 // restore selected junction
1286 myJoinTLSToggleButton->setState(FALSE, TRUE);
1287 myTLSEditorParent->updateModules();
1288 return 1;
1289}
1290
1291
1292void
1294 // first reset junction label
1295 myJunctionIDLabel->setText(TL("Junction ID"));
1296 // clear selected junctions
1297 mySelectedJunctionIDs.clear();
1298 // cancel joining junction mode
1299 onCmdCancelJoin(nullptr, 0, nullptr);
1300 // continue depending of current junction
1301 if (myCurrentJunction == nullptr) {
1302 myJunctionIDTextField->setText(TL("No junction selected"));
1303 } else {
1304 // get all TLS assigned to this node
1305 const auto& TLSs = myCurrentJunction->getNBNode()->getControllingTLS();
1306 // check if junction is controlled
1307 if (TLSs.size() > 0) {
1308 // get first TLS
1309 const auto TLS = (*TLSs.begin());
1310 // update junction ID text field
1311 if (TLS->getNodes().size() > 1) {
1312 // declare string
1313 std::string TLSNodesStr;
1314 for (auto it = TLS->getNodes().begin(); it != TLS->getNodes().end(); it++) {
1315 if (it == (TLS->getNodes().end() - 1)) {
1316 TLSNodesStr += (*it)->getID();
1317 } else {
1318 TLSNodesStr += (*it)->getID() + ", ";
1319 }
1320 }
1321 // updated junction fields
1322 myJunctionIDTextField->setText(TLSNodesStr.c_str());
1323 // update junction label if we have multiple nodes
1324 if (TLS->getNodes().size() > 1) {
1325 myJunctionIDLabel->setText(TL("Junction IDs"));
1326 }
1327 // set TLS type in comboBox
1328 const int index = myTLSTypeComboBox->findItem(myCurrentJunction->getAttribute(SUMO_ATTR_TLTYPE).c_str());
1329 if (index != -1) {
1330 myTLSTypeComboBox->setCurrentItem(index, FALSE);
1331 }
1332 }
1333 } else {
1334 // update junction ID text field
1335 myJunctionIDTextField->setText(myCurrentJunction->getID().c_str());
1336 myTLSTypeComboBox->setCurrentItem(0, FALSE);
1337 }
1338 }
1339 // update TLS junction
1341}
1342
1343// ---------------------------------------------------------------------------
1344// GNETLSEditorFrame::TLSPrograms - methods
1345// ---------------------------------------------------------------------------
1346
1348 GNEGroupBoxModule(TLSEditorParent, TL("Traffic Light Programs")),
1349 myTLSEditorParent(TLSEditorParent) {
1350 // create frame, label and comboBox for programID
1351 FXHorizontalFrame* programFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1352 new FXLabel(programFrame, toString(SUMO_ATTR_PROGRAMID).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
1355 myProgramComboBox->disable();
1356 // create auxiliar frames
1357 FXHorizontalFrame* horizontalFrameAux = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
1358 FXVerticalFrame* verticalFrameAuxA = new FXVerticalFrame(horizontalFrameAux, GUIDesignAuxiliarHorizontalFrame);
1359 FXVerticalFrame* verticalFrameAuxB = new FXVerticalFrame(horizontalFrameAux, GUIDesignAuxiliarHorizontalFrame);
1360 // create create tlDef button
1361 myCreateButton = GUIDesigns::buildFXButton(verticalFrameAuxA, TL("Create TLS"), "", TL("Create a new traffic light program."),
1363 myCreateButton->disable();
1364 // create delete tlDef button
1365 myDeleteButton = GUIDesigns::buildFXButton(verticalFrameAuxA, TL("Delete"), "", TL("Delete a traffic light program. If all programs are deleted the junction turns into a priority junction."),
1367 myDeleteButton->disable();
1368 // create reset current tlDef button
1369 myResetSingleButton = GUIDesigns::buildFXButton(verticalFrameAuxB, TL("Reset single"), "", TL("Reset current TLS program."),
1371 myResetSingleButton->disable();
1372 // create reset all tlDefs button
1373 myResetAllButton = GUIDesigns::buildFXButton(verticalFrameAuxB, TL("Reset all"), "", TL("Reset all TLS programs."),
1375 myResetAllButton->disable();
1376 // create save modifications button
1377 mySaveButon = GUIDesigns::buildFXButton(verticalFrameAuxA, TL("Save"), "", TL("Save program modifications. (Enter)"),
1379 mySaveButon->disable();
1380 // create cancel modifications buttons
1381 myCancelButon = GUIDesigns::buildFXButton(verticalFrameAuxB, TL("Cancel"), "", TL("Discard program modifications. (Esc)"),
1383 myCancelButon->disable();
1384 // show GroupBox
1385 show();
1386}
1387
1388
1390
1391
1392void
1394 if (getNumberOfPrograms() == 0) {
1395 // no TLS Programs, disable buttons except create (if we have a junction)
1396 if (myTLSEditorParent->getTLSJunction()->getCurrentJunction() != nullptr) {
1397 myCreateButton->enable();
1398 } else {
1399 myCreateButton->disable();
1400 }
1401 myDeleteButton->disable();
1402 myResetSingleButton->disable();
1403 myProgramComboBox->disable();
1404 myResetAllButton->disable();
1405 mySaveButon->disable();
1406 myCancelButon->disable();
1407 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1408 // selecting E1, disable buttons
1409 myCreateButton->disable();
1410 myDeleteButton->disable();
1411 myResetSingleButton->disable();
1412 myProgramComboBox->disable();
1413 myResetAllButton->disable();
1414 mySaveButon->disable();
1415 myCancelButon->disable();
1416 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1417 // joining TLSs, disable button
1418 myCreateButton->disable();
1419 myDeleteButton->disable();
1420 myResetSingleButton->disable();
1421 myProgramComboBox->disable();
1422 myResetAllButton->disable();
1423 mySaveButon->disable();
1424 myCancelButon->disable();
1425 } else if (myHaveModifications) {
1426 // modifications, disable button
1427 myCreateButton->disable();
1428 myDeleteButton->disable();
1429 myResetSingleButton->disable();
1430 myProgramComboBox->disable();
1431 myResetAllButton->disable();
1432 // enable save and cancel buttons
1433 mySaveButon->enable();
1434 myCancelButon->enable();
1435 } else {
1436 myCreateButton->enable();
1437 myDeleteButton->enable();
1438 myResetSingleButton->enable();
1439 myProgramComboBox->enable();
1440 // disable save and cancel buttons
1441 mySaveButon->disable();
1442 myCancelButon->disable();
1443 // check if enable reset all
1444 if (getNumberOfPrograms() > 1) {
1445 myResetAllButton->enable();
1446 } else {
1447 myResetAllButton->disable();
1448 }
1449 }
1450 // get current junction
1451 const auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1452 // update button text
1453 if (currentJunction == nullptr) {
1454 myCreateButton->setText(TL("Create"));
1455 } else if (currentJunction->getNBNode()->isTLControlled()) {
1456 myCreateButton->setText(TL("Duplicate"));
1457 } else {
1458 myCreateButton->setText(TL("Create"));
1459 }
1460}
1461
1462
1463void
1467
1468
1469void
1473
1474
1475bool
1477 // get current edited junction
1478 const auto junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1479 if (junction == nullptr) {
1480 throw ProcessError("Junction cannot be NULL");
1481 } else {
1482 // clear definitions
1483 myTLSPrograms.clear();
1484 // obtain TLSs sorted by ID
1485 std::set<std::string> programIDs;
1486 for (const auto& TLS : junction->getNBNode()->getControllingTLS()) {
1487 myTLSPrograms.push_back(TLS);
1488 programIDs.insert(TLS->getProgramID());
1489 }
1490 for (const auto& programID : programIDs) {
1491 myProgramComboBox->appendIconItem(programID.c_str());
1492 }
1493 // check if enable TLS definitions
1494 if (myTLSPrograms.size() > 0) {
1495 myProgramComboBox->enable();
1496 myProgramComboBox->setCurrentItem(0);
1497 // switch TLS Program
1498 return switchProgram();
1499 }
1500 return false;
1501 }
1502}
1503
1504
1505void
1507 // clear definitions
1508 myTLSPrograms.clear();
1509 // clear and disable myProgramComboBox
1510 myProgramComboBox->clearItems();
1511 myProgramComboBox->disable();
1512}
1513
1514
1515int
1519
1520
1521bool
1525
1526
1527void
1532
1533
1536 // find TLS definition
1537 for (const auto& TLSPrograms : myTLSPrograms) {
1538 if (TLSPrograms->getProgramID() == myProgramComboBox->getText().text()) {
1539 return TLSPrograms;
1540 }
1541 }
1542 throw ProcessError(TL("TLSPrograms cannot be found"));
1543}
1544
1545
1546const std::string
1548 if (myProgramComboBox->getNumItems() == 0) {
1549 return "";
1550 } else {
1551 return myProgramComboBox->getText().text();
1552 }
1553}
1554
1555
1556void
1558 // get junction copy
1559 auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1560 if (currentJunction != nullptr) {
1561 myTLSEditorParent->getViewNet()->getUndoList()->abortAllChangeGroups();
1562 myTLSEditorParent->cleanup();
1563 myTLSEditorParent->getViewNet()->updateViewNet();
1564 // edit junction again
1565 if (editJunctionAgain) {
1566 myTLSEditorParent->editJunction(currentJunction);
1567 }
1568 }
1569 myTLSEditorParent->updateModules();
1570}
1571
1572
1573long
1574GNETLSEditorFrame::TLSPrograms::onCmdCreate(FXObject*, FXSelector, void*) {
1575 auto GNEApp = myTLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows();
1576 // get current edited junction (needed because onCmdDiscardChanges clear junction)
1577 GNEJunction* currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1578 // abort because we onCmdOk assumes we wish to save an edited definition
1579 discardChanges(false);
1580 // check number of edges
1581 if (currentJunction->getGNEIncomingEdges().empty() && currentJunction->getGNEOutgoingEdges().empty()) {
1582 // open warning dialog
1583 GNEWarningBasicDialog(GNEApp,
1584 TL("TLS cannot be created"),
1585 TL("Traffic Light cannot be created because junction must have"),
1586 TL("at least one incoming edge and one outgoing edge.")
1587 );
1588 return 1;
1589 }
1590 // check number of connections
1591 if (currentJunction->getGNEConnections().empty()) {
1592 // open warning dialog
1593 GNEWarningBasicDialog(GNEApp,
1594 TL("TLS cannot be created"),
1595 TL("Traffic Light cannot be created because junction"),
1596 TL("must have at least one connection.")
1597 );
1598 return 1;
1599 }
1600 // check uncontrolled connections
1601 bool connectionControlled = false;
1602 for (const auto& connection : currentJunction->getGNEConnections()) {
1603 if (!connection->getNBEdgeConnection().uncontrolled) {
1604 connectionControlled = true;
1605 }
1606 }
1607 if (!connectionControlled) {
1608 // open warning dialog
1609 GNEWarningBasicDialog(GNEApp,
1610 TL("TLS cannot be created"),
1611 TL("Traffic Light cannot be created because junction"),
1612 TL("must have at least one controlled connection.")
1613 );
1614 return 1;
1615 }
1616 // all checks ok, then create TLS in junction
1617 createTLS(currentJunction);
1618 // edit junction
1619 myTLSEditorParent->editJunction(currentJunction);
1620 // switch to the last program
1621 myProgramComboBox->setCurrentItem(myProgramComboBox->getNumItems() - 1, TRUE);
1622 myTLSEditorParent->updateModules();
1623 return 1;
1624}
1625
1626
1627long
1628GNETLSEditorFrame::TLSPrograms::onCmdDelete(FXObject*, FXSelector, void*) {
1629 // get current junction
1630 GNEJunction* currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1631 // get current edited tlDef
1632 NBTrafficLightDefinition* tlDef = myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms();
1633 // check if remove entire TLS or only one program
1634 const bool changeJunctionType = (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() == 1);
1635 // abort because onCmdOk assumes we wish to save an edited definition
1636 discardChanges(false);
1637 // check if change junction type
1638 if (changeJunctionType) {
1639 currentJunction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::PRIORITY), myTLSEditorParent->getViewNet()->getUndoList());
1640 } else {
1641 // just remove TLDef
1642 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(currentJunction, tlDef, false), true);
1643 // edit junction again
1644 myTLSEditorParent->editJunction(currentJunction);
1645 }
1646 myTLSEditorParent->updateModules();
1647 return 1;
1648}
1649
1650
1651long
1653 // obtain junction and old definitions
1654 GNEJunction* junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1655 NBTrafficLightDefinition* oldDef = myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms();
1656 const std::string programID = oldDef->getProgramID();
1657 // discard changes
1658 discardChanges(false);
1659 // begin undo
1660 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("reset current program"));
1661 // remove old definition
1662 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, oldDef, false), true);
1663 // create new definition, and add it
1664 NBOwnTLDef* newDef = new NBOwnTLDef(oldDef->getID(), oldDef->getNodes(), oldDef->getOffset(), oldDef->getType());
1665 newDef->setProgramID(programID);
1666 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newDef, true, true), true);
1667 // set old index
1668 // end undo
1669 myTLSEditorParent->getViewNet()->getUndoList()->end();
1670 // inspect junction again
1671 myTLSEditorParent->editJunction(junction);
1672 // switch to programID
1673 int index = -1;
1674 for (int i = 0; i < myProgramComboBox->getNumItems(); i++) {
1675 if (myProgramComboBox->getItemText(i) == programID) {
1676 index = i;
1677 }
1678 }
1679 if (index != -1) {
1680 myProgramComboBox->setCurrentItem(index, TRUE);
1681 }
1682 myTLSEditorParent->updateModules();
1683 return 1;
1684}
1685
1686
1687long
1689 // obtain junction and old definitions
1690 GNEJunction* junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1691 NBTrafficLightDefinition* oldDef = myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms();
1692 // get a list of all affected nodes
1693 std::vector<GNEJunction*> TLSJunctions;
1694 for (const auto& TLSNode : oldDef->getNodes()) {
1695 TLSJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLSNode->getID()));
1696 }
1697 // discard all previous changes
1698 discardChanges(false);
1699 // begin undo
1700 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("reset TLS"));
1701 // set junction as priority (this will also remove all program, see GNEJunction::setJunctionType)
1702 for (const auto& TLSJunction : TLSJunctions) {
1703 TLSJunction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::PRIORITY), myTLSEditorParent->getViewNet()->getUndoList());
1704 }
1705 // create TLS in junction
1706 createTLS(junction);
1707 // set TLS in all other junctions
1708 for (const auto& TLSJunction : TLSJunctions) {
1709 if (TLSJunction != junction) {
1710 TLSJunction->setAttribute(SUMO_ATTR_TYPE, TLSJunction->getAttribute(SUMO_ATTR_TYPE), myTLSEditorParent->getViewNet()->getUndoList());
1711 TLSJunction->setAttribute(SUMO_ATTR_TLID, TLSJunction->getAttribute(SUMO_ATTR_TLID), myTLSEditorParent->getViewNet()->getUndoList());
1712 }
1713 }
1714 // end undo
1715 myTLSEditorParent->getViewNet()->getUndoList()->end();
1716 // edit junction
1717 myTLSEditorParent->editJunction(junction);
1718 return 1;
1719}
1720
1721
1722long
1724 // check if program is valid (user may input arbitrary text)
1725 bool found = false;
1726 for (const auto& TLSPrograms : myTLSPrograms) {
1727 if (TLSPrograms->getProgramID() == myProgramComboBox->getText().text()) {
1728 found = true;
1729 break;
1730 }
1731 }
1732 if (!found) {
1733 // reset field to a valid program
1734 myProgramComboBox->setText(myTLSPrograms.front()->getProgramID().c_str());
1735 }
1736 switchProgram();
1737 return 1;
1738}
1739
1740
1741long
1743 // get junction copy
1744 const auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1745 // get current program
1746 const auto currentProgram = myProgramComboBox->getCurrentItem();
1747 // check that junction is valid
1748 if (currentJunction != nullptr) {
1749 const auto oldDefinition = getCurrentTLSPrograms();
1750 std::vector<NBNode*> nodes = oldDefinition->getNodes();
1751 GNEUndoList* undoList = myTLSEditorParent->getViewNet()->getUndoList();
1752 for (const auto& node : nodes) {
1753 GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(node->getID());
1754 undoList->add(new GNEChange_TLS(junction, oldDefinition, false), true);
1755 undoList->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, true), true);
1756 // synchronize crossing tl-indices in case they were changed (via onCmdCleanStates)
1757 for (const auto& gc : junction->getGNECrossings()) {
1758 NBNode::Crossing* c = gc->getNBCrossing();
1759 if (c) {
1760 gc->setAttribute(SUMO_ATTR_TLLINKINDEX, toString(c->tlLinkIndex), undoList);
1761 gc->setAttribute(SUMO_ATTR_TLLINKINDEX2, toString(c->tlLinkIndex2), undoList);
1762 }
1763 }
1764
1765
1766 }
1767 // end change
1768 myTLSEditorParent->getViewNet()->getUndoList()->end();
1769 // mark as saved
1770 myHaveModifications = false;
1771 // reset myEditedDef (because is already in eine undo-list)
1772 myTLSEditorParent->myEditedDef = nullptr;
1773 myTLSEditorParent->cleanup();
1774 myTLSEditorParent->getViewNet()->updateViewNet();
1775 // edit junction again
1776 myTLSEditorParent->editJunction(currentJunction);
1777 // change program
1778 myProgramComboBox->setCurrentItem(currentProgram, TRUE);
1779 } else {
1780 // discard changes inspecting junction again
1781 discardChanges(true);
1782 }
1783 myTLSEditorParent->updateModules();
1784 return 1;
1785}
1786
1787
1788long
1790 // discard changes inspecting junction again
1791 discardChanges(true);
1792 return 1;
1793}
1794
1795
1796void
1798 // get current TLS program id
1799 const auto currentTLS = getCurrentTLSProgramID();
1800 // check conditions
1801 if (junction == nullptr) {
1802 throw ProcessError("junction cannot be null");
1804 // set junction as TLS
1805 junction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::TRAFFIC_LIGHT), myTLSEditorParent->getViewNet()->getUndoList());
1806 } else if (junction->getNBNode()->isTLControlled()) {
1807 // use existing traffic light as template for type, signal groups, controlled nodes etc
1808 NBTrafficLightDefinition* tpl = nullptr;
1809 for (const auto& TLS : junction->getNBNode()->getControllingTLS()) {
1810 if (TLS->getProgramID() == currentTLS) {
1811 tpl = TLS;
1812 }
1813 }
1814 // if template is empty, use first TLS
1815 if (tpl == nullptr) {
1816 tpl = *junction->getNBNode()->getControllingTLS().begin();
1817 }
1818 // create new logic
1820 // create new TLDef
1821 NBLoadedSUMOTLDef* newDef = new NBLoadedSUMOTLDef(*tpl, *newLogic);
1822 NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1823 newDef->setProgramID(tllCont.getNextProgramID(newDef->getID()));
1824 // remove new logic
1825 delete newLogic;
1826 // add it using GNEChange_TLS
1827 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TLF("duplicate program '%' of traffic light '%'", tpl->getProgramID(), tpl->getID()));
1828 for (NBNode* node : newDef->getNodes()) {
1829 GNEJunction* j = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(node->getID());
1830 // not forcing insertion because we already ensured a new id and multiple junctions will attempt insertion
1831 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(j, newDef, true, false), true);
1832 }
1833 myTLSEditorParent->getViewNet()->getUndoList()->end();
1834 } else {
1835 // for some reason the traffic light was not built, try again
1836 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, nullptr, true, true), true);
1837 }
1838}
1839
1840
1841bool
1843 if (myTLSEditorParent->myTLSJunction->getCurrentJunction() == nullptr) {
1844 throw ProcessError("Junction cannot be NULL");
1845 } else {
1846 // reset save flag
1847 myHaveModifications = false;
1848 // get current definition
1850 // logic may not have been recomputed yet. recompute to be sure
1851 NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1852 // compute junction
1853 myTLSEditorParent->getViewNet()->getNet()->computeJunction(myTLSEditorParent->myTLSJunction->getCurrentJunction());
1854 // obtain TrafficLight logic vinculated with tlDef
1855 NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
1856 // check that tllLogic exist
1857 if (tllogic != nullptr) {
1858 // now we can be sure that the tlDef is up to date (i.e. re-guessed)
1859 myTLSEditorParent->buildInternalLanes(tlDef);
1860 // create working duplicate from original def
1861 delete myTLSEditorParent->myEditedDef;
1862 myTLSEditorParent->myEditedDef = new NBLoadedSUMOTLDef(*tlDef, *tllogic);
1863 // set values
1864 myTLSEditorParent->myTLSAttributes->setOffset(myTLSEditorParent->myEditedDef->getLogic()->getOffset());
1865 myTLSEditorParent->myTLSAttributes->setParameters(myTLSEditorParent->myEditedDef->getLogic()->getParametersStr());
1866 // init phaseTable with the new TLS
1867 myTLSEditorParent->myTLSPhases->initPhaseTable();
1868 } else {
1869 // tlDef has no valid logic (probably because id does not control any links
1870 discardChanges(false);
1871 myTLSEditorParent->getViewNet()->setStatusBarText(TL("Traffic Light does not control any links"));
1872 return false;
1873 }
1874 }
1875 return true;
1876}
1877
1878// ---------------------------------------------------------------------------
1879// GNETLSEditorFrame::TLSPhases - methods
1880// ---------------------------------------------------------------------------
1881
1884 myTLSEditorParent(TLSEditorParent) {
1885 // create GNETLSTable
1886 myPhaseTable = new GNETLSTable(this);
1887 // hide phase table
1888 myPhaseTable->hide();
1889 FXHorizontalFrame* phaseButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
1890 FXVerticalFrame* col1 = new FXVerticalFrame(phaseButtons, GUIDesignAuxiliarHorizontalFrame); // left button columm
1891 FXVerticalFrame* col2 = new FXVerticalFrame(phaseButtons, GUIDesignAuxiliarHorizontalFrame); // right button column
1892 // create cleanup states button
1894 TL("Clean States") + std::string("\t") +
1895 TL("Clean unused states from all phase") + std::string("\t") +
1896 TL("Clean unused states from all phase. (Not allowed for multiple programs)"),
1898 myCleanStatesButton->disable();
1899 // add unused states button
1901 TL("Add States") + std::string("\t") +
1902 TL("Extend the state vector for all phases by one entry") + std::string("\t") +
1903 TL("Extend the state vector for all phases by one entry. (Unused until a connection or crossing is assigned to the new index)"),
1905 myAddStates->disable();
1906 // group states button
1908 TL("Group Sig.") + std::string("\t") +
1909 TL("Shorten state definition by letting connections with the same signal states use the same index") + std::string("\t") +
1910 TL("Shorten state definition by letting connections with the same signal states use the same index. (Not allowed for multiple programs)"),
1912 myGroupSignalsButton->disable();
1913 // ungroup states button
1915 TL("Ungroup Sig.") + std::string("\t") +
1916 TL("Let every connection use a distinct index (reverse state grouping)") + std::string("\t") +
1917 TL("Let every connection use a distinct index (reverse state grouping). (Not allowed for multiple programs)"),
1919 myUngroupSignalsButton->disable();
1920 // show TLSFile
1921 show();
1922}
1923
1924
1927
1928
1929void
1931 if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1932 // selecting E1, disable buttons
1933 myPhaseTable->disable();
1934 myCleanStatesButton->disable();
1935 myAddStates->disable();
1936 myGroupSignalsButton->disable();
1937 myUngroupSignalsButton->disable();
1938 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1939 // joining TLSs, disable buttons
1940 myPhaseTable->disable();
1941 myCleanStatesButton->disable();
1942 myAddStates->disable();
1943 myGroupSignalsButton->disable();
1944 myUngroupSignalsButton->disable();
1945 myUngroupSignalsButton->disable();
1946 } else if (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() == 0) {
1947 // no TLSs, disable buttons
1948 myPhaseTable->disable();
1949 myCleanStatesButton->disable();
1950 myAddStates->disable();
1951 myGroupSignalsButton->disable();
1952 myUngroupSignalsButton->disable();
1953 } else if (myTLSEditorParent->myEditedDef == nullptr) {
1954 // no edited definition, disable buttons
1955 myPhaseTable->disable();
1956 myCleanStatesButton->disable();
1957 myAddStates->disable();
1958 myGroupSignalsButton->disable();
1959 myUngroupSignalsButton->disable();
1960 } else {
1961 myPhaseTable->enable();
1962 myCleanStatesButton->enable();
1963 myAddStates->enable();
1964 myGroupSignalsButton->enable();
1965 if (myTLSEditorParent->myEditedDef->usingSignalGroups()) {
1966 myUngroupSignalsButton->enable();
1967 } else {
1968 myUngroupSignalsButton->disable();
1969 }
1970 }
1971}
1972
1973
1974void
1978
1979
1980void
1984
1985
1990
1991
1996
1997
1998void
2000 // first clear table
2002 if (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() > 0) {
2003 if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC) {
2005 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::ACTUATED) {
2007 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::DELAYBASED) {
2009 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA) {
2011 }
2012 // select first element (by default)
2013 myPhaseTable->selectRow(0);
2014 // recalc width and show
2015 myPhaseTable->recalcTableWidth();
2016 myPhaseTable->show();
2017 } else {
2018 myPhaseTable->hide();
2019 }
2020 update();
2021}
2022
2023
2024void
2028
2029
2030bool
2031GNETLSEditorFrame::TLSPhases::changePhaseValue(const int col, const int row, const std::string& value) {
2032 // Declare columns
2033 int colDuration = 1;
2034 int colState = -1;
2035 int colNext = -1;
2036 int colName = -1;
2037 int colMinDur = -1;
2038 int colMaxDur = -1;
2039 int colEarliestEnd = -1;
2040 int colLatestEnd = -1;
2041 int colVehExt = -1;
2042 int colYellow = -1;
2043 int colRed = -1;
2044 // set columns depending of traffic light type
2045 if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC) {
2046 colState = 2;
2047 colNext = 3;
2048 colName = 4;
2049 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::ACTUATED) {
2050 colMinDur = 2;
2051 colMaxDur = 3;
2052 colState = 4;
2053 colEarliestEnd = 5;
2054 colLatestEnd = 6;
2055 colNext = 7;
2056 colName = 8;
2057 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::DELAYBASED) {
2058 colMinDur = 2;
2059 colMaxDur = 3;
2060 colState = 4;
2061 colNext = 5;
2062 colName = 6;
2063 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA) {
2064 colMinDur = 2;
2065 colMaxDur = 3;
2066 colState = 4;
2067 colVehExt = 5;
2068 colYellow = 6;
2069 colRed = 7;
2070 colNext = 8;
2071 colName = 9;
2072 }
2073 // check column
2074 if (col == colDuration) {
2075 return setDuration(col, row, value);
2076 } else if (col == colState) {
2077 return setState(col, row, value);
2078 } else if (col == colNext) {
2079 return setNext(row, value);
2080 } else if (col == colName) {
2081 return setName(row, value);
2082 } else if (col == colMinDur) {
2083 return setMinDur(row, value);
2084 } else if (col == colMaxDur) {
2085 return setMaxDur(row, value);
2086 } else if (col == colEarliestEnd) {
2087 return setEarliestEnd(row, value);
2088 } else if (col == colLatestEnd) {
2089 return setLatestEnd(row, value);
2090 } else if (col == colVehExt) {
2091 return setVehExt(row, value);
2092 } else if (col == colYellow) {
2093 return setYellow(row, value);
2094 } else if (col == colRed) {
2095 return setRed(row, value);
2096 } else {
2097 throw ProcessError(TL("invalid column"));
2098 }
2099}
2100
2101
2102void
2103GNETLSEditorFrame::TLSPhases::addPhase(const int row, const char c) {
2104 // mark TLS as modified
2105 myTLSEditorParent->myTLSPrograms->markAsModified();
2106 // build default phase
2107 const int newIndex = buildDefaultPhase(row);
2108 // check if override state
2109 switch (c) {
2110 case 'r':
2111 case 'y':
2112 case 'g':
2113 case 'G':
2114 myTLSEditorParent->myEditedDef->getLogic()->overrideState(newIndex, c);
2115 break;
2116 default:
2117 break;
2118 }
2119 // check if "next" phase settings are impacted by the new row
2120 for (int i = (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1; i > row; --i) {
2121 updateNextPhase(i, i + 1);
2122 }
2123 // int phase table again
2125 // mark new row as selected
2126 myPhaseTable->selectRow(newIndex);
2127 // set focus in table
2128 getPhaseTable()->setFocus();
2129}
2130
2131
2132void
2134 // mark TLS as modified
2135 myTLSEditorParent->myTLSPrograms->markAsModified();
2136 // build default phase
2137 const int newIndex = buildDefaultPhase(row);
2138 // coply old phase in the new phase
2139 myTLSEditorParent->myEditedDef->getLogic()->copyPhase(row, row + 1);
2140 // int phase table again
2142 // mark new row as selected
2143 myPhaseTable->selectRow(newIndex);
2144 // set focus in table
2145 getPhaseTable()->setFocus();
2146}
2147
2148
2149void
2151 // mark TLS ad modified
2152 myTLSEditorParent->myTLSPrograms->markAsModified();
2153 // calculate new row
2154 const auto newRow = MAX2(0, (row - 1));
2155 // delete selected row
2156 myTLSEditorParent->myEditedDef->getLogic()->deletePhase(row);
2157 updateNextPhase(row, -1);
2158 for (int i = row; i < (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() + 1; ++i) {
2159 updateNextPhase(i, i - 1);
2160 }
2161 // int phase table again
2163 // mark new row as selected
2164 myPhaseTable->selectRow(newRow);
2165 // set focus in table
2166 getPhaseTable()->setFocus();
2167}
2168
2169
2170void
2172 // mark TLS ad modified
2173 myTLSEditorParent->myTLSPrograms->markAsModified();
2174 // delete selected row
2175 if (row == 0) {
2176 myTLSEditorParent->myEditedDef->getLogic()->swapfirstPhase();
2177 updateNextPhase(row, (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1, true);
2178 } else {
2179 myTLSEditorParent->myEditedDef->getLogic()->swapPhase(row, row - 1);
2180 updateNextPhase(row, row - 1, true);
2181 }
2182 // int phase table again
2184 // mark new row as selected
2185 if (row == 0) {
2186 myPhaseTable->selectRow((int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1);
2187 } else {
2188 myPhaseTable->selectRow(row - 1);
2189 }
2190 // set focus in table
2191 getPhaseTable()->setFocus();
2192}
2193
2194
2195void
2197 // mark TLS ad modified
2198 myTLSEditorParent->myTLSPrograms->markAsModified();
2199 // delete selected row
2200 if (row == (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1) {
2201 myTLSEditorParent->myEditedDef->getLogic()->swaplastPhase();
2202 updateNextPhase((int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1, 0, true);
2203 } else {
2204 myTLSEditorParent->myEditedDef->getLogic()->swapPhase(row, row + 1);
2205 updateNextPhase(row, row + 1, true);
2206 }
2207 // int phase table again
2209 // mark new row as selected
2210 if (row == (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1) {
2211 myPhaseTable->selectRow(0);
2212 } else {
2213 myPhaseTable->selectRow(row + 1);
2214 }
2215 // set focus in table
2216 getPhaseTable()->setFocus();
2217}
2218
2219
2220void
2222 // get phase
2223 const auto& phase = myTLSEditorParent->getPhase(myPhaseTable->getCurrentSelectedRow());
2224 // need not hold since links could have been deleted somewhere else and indices may be reused
2225 for (const auto& internalLane : myTLSEditorParent->myInternalLanes) {
2226 int tlIndex = internalLane.first;
2227 std::vector<GNEInternalLane*> lanes = internalLane.second;
2229 if (tlIndex >= 0 && tlIndex < (int)phase.state.size()) {
2230 state = (LinkState)phase.state[tlIndex];
2231 }
2232 for (const auto& lane : lanes) {
2233 lane->setLinkState(state);
2234 }
2235 }
2236 // update view net (for coloring)
2237 myTLSEditorParent->getViewNet()->updateViewNet();
2238}
2239
2240
2241long
2243 if (myTLSEditorParent->myEditedDef->cleanupStates()) {
2244 myTLSEditorParent->myTLSPrograms->markAsModified();
2245 }
2246 myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2248 myPhaseTable->setFocus();
2249 myTLSEditorParent->myTLSPrograms->markAsModified();
2250 myTLSEditorParent->updateModules();
2251 return 1;
2252}
2253
2254
2255long
2257 myTLSEditorParent->myEditedDef->getLogic()->setStateLength(myTLSEditorParent->myEditedDef->getLogic()->getNumLinks() + 1);
2258 myTLSEditorParent->myTLSPrograms->markAsModified();
2260 myPhaseTable->setFocus();
2261 myTLSEditorParent->updateModules();
2262 return 1;
2263}
2264
2265
2266long
2268 myTLSEditorParent->myEditedDef->groupSignals();
2269 myTLSEditorParent->myTLSPrograms->markAsModified();
2270 myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2272 myPhaseTable->setFocus();
2273 myTLSEditorParent->updateModules();
2274 return 1;
2275}
2276
2277
2278long
2280 myTLSEditorParent->myEditedDef->setParticipantsInformation();
2281 myTLSEditorParent->myEditedDef->ungroupSignals();
2282 myTLSEditorParent->myTLSPrograms->markAsModified();
2283 myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2285 myPhaseTable->setFocus();
2286 myTLSEditorParent->updateModules();
2287 return 1;
2288}
2289
2290
2291void
2293 // declare constants for columns
2294 const int colDuration = 1;
2295 const int colState = 2;
2296 const int colNext = 3;
2297 const int colName = 4;
2298 // get phases
2299 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2300 // adjust table
2301 myPhaseTable->setTableSize("sup-midtb", (int)phases.size());
2302 // fill rows
2303 for (int row = 0; row < (int)phases.size(); row++) {
2304 myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2305 myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2306 myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2307 myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2308 }
2309 // set columns
2310 myPhaseTable->setColumnLabelTop(colDuration, "dur");
2311 myPhaseTable->setColumnLabelTop(colState, "state");
2312 myPhaseTable->setColumnLabelTop(colNext, "next");
2313 myPhaseTable->setColumnLabelTop(colName, "name");
2314 // set bot labels
2315 updateCycleDuration(colDuration);
2316 updateStateSize(colState);
2317 // set focus
2318 myPhaseTable->setFocus();
2319}
2320
2321
2322void
2324 // declare constants for columns
2325 const int colDuration = 1;
2326 const int colMinDur = 2;
2327 const int colMaxDur = 3;
2328 const int colState = 4;
2329 const int colEarliestEnd = 5;
2330 const int colLatestEnd = 6;
2331 const int colNext = 7;
2332 const int colName = 8;
2333 // get phases
2334 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2335 // adjust table
2336 myPhaseTable->setTableSize("suffpff-midtb", (int)phases.size());
2337 // fill rows
2338 for (int row = 0; row < (int)phases.size(); row++) {
2339 myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2340 myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2341 myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2342 myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2343 myPhaseTable->setItemText(row, colEarliestEnd, varDurString(phases.at(row).earliestEnd).c_str());
2344 myPhaseTable->setItemText(row, colLatestEnd, varDurString(phases.at(row).latestEnd).c_str());
2345 myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2346 myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2347 }
2348 // set columns
2349 myPhaseTable->setColumnLabelTop(colDuration, "dur");
2350 myPhaseTable->setColumnLabelTop(colMinDur, "min");
2351 myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2352 myPhaseTable->setColumnLabelTop(colEarliestEnd, "ear.end", "earlyEnd");
2353 myPhaseTable->setColumnLabelTop(colLatestEnd, "lat.end", "latestEnd");
2354 myPhaseTable->setColumnLabelTop(colState, "state");
2355 myPhaseTable->setColumnLabelTop(colNext, "next");
2356 myPhaseTable->setColumnLabelTop(colName, "name");
2357 // set bot labels
2358 updateCycleDuration(colDuration);
2359 updateStateSize(colState);
2360 // set focus
2361 myPhaseTable->setFocus();
2362}
2363
2364
2365void
2367 // declare constants for columns
2368 const int colDuration = 1;
2369 const int colMinDur = 2;
2370 const int colMaxDur = 3;
2371 const int colState = 4;
2372 const int colNext = 5;
2373 const int colName = 6;
2374 // get phases
2375 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2376 // adjust table
2377 myPhaseTable->setTableSize("suffp-midtb", (int)phases.size());
2378 // fill rows
2379 for (int row = 0; row < (int)phases.size(); row++) {
2380 myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2381 myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2382 myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2383 myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2384 myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2385 myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2386 }
2387 // set columns
2388 myPhaseTable->setColumnLabelTop(colDuration, "dur");
2389 myPhaseTable->setColumnLabelTop(colMinDur, "min");
2390 myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2391 myPhaseTable->setColumnLabelTop(colState, "state");
2392 myPhaseTable->setColumnLabelTop(colNext, "next");
2393 myPhaseTable->setColumnLabelTop(colName, "name");
2394 // set bot labels
2395 updateCycleDuration(colDuration);
2396 updateStateSize(colState);
2397 // set focus
2398 myPhaseTable->setFocus();
2399}
2400
2401
2402void
2404 // declare constants for columns
2405 const int colDuration = 1;
2406 const int colMinDur = 2;
2407 const int colMaxDur = 3;
2408 const int colState = 4;
2409 const int colVehExt = 5;
2410 const int colYellow = 6;
2411 const int colRed = 7;
2412 const int colNext = 8;
2413 const int colName = 9;
2414 // get phases
2415 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2416 // adjust table
2417 myPhaseTable->setTableSize("suffpfff-midtb", (int)phases.size());
2418 // fill rows
2419 for (int row = 0; row < (int)phases.size(); row++) {
2420 myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2421 myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2422 myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2423 myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2424 myPhaseTable->setItemText(row, colVehExt, varDurString(phases.at(row).vehExt).c_str());
2425 myPhaseTable->setItemText(row, colYellow, varDurString(phases.at(row).yellow).c_str());
2426 myPhaseTable->setItemText(row, colRed, varDurString(phases.at(row).red).c_str());
2427 myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2428 myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2429 }
2430 // set columns
2431 myPhaseTable->setColumnLabelTop(colDuration, "dur");
2432 myPhaseTable->setColumnLabelTop(colMinDur, "min");
2433 myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2434 myPhaseTable->setColumnLabelTop(colState, "state");
2435 myPhaseTable->setColumnLabelTop(colVehExt, "vehExt", "vehicle extension");
2436 myPhaseTable->setColumnLabelTop(colYellow, "yellow");
2437 myPhaseTable->setColumnLabelTop(colRed, "red");
2438 myPhaseTable->setColumnLabelTop(colNext, "next");
2439 myPhaseTable->setColumnLabelTop(colName, "name");
2440 // set bot labels
2441 updateCycleDuration(colDuration);
2442 updateStateSize(colState);
2443 // set focus
2444 myPhaseTable->setFocus();
2445}
2446
2447
2448int
2450 // get option container
2451 const auto& neteditOptions = OptionsCont::getOptions();
2452 // check if TLS is static
2453 const bool TLSStatic = (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC);
2454 const bool NEMA = (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA);
2455 // calculate new index
2456 const int newIndex = row + 1;
2457 // duplicate current row
2458 auto duration = getSUMOTime(myPhaseTable->getItemText(row, 1));
2459 const auto oldState = myPhaseTable->getItemText(row, TLSStatic ? 2 : 4);
2460 auto state = oldState;
2461 // update crossingINdices
2462 std::set<int> crossingIndices;
2463 for (const auto& node : myTLSEditorParent->myEditedDef->getNodes()) {
2464 for (const auto& crossing : node->getCrossings()) {
2465 crossingIndices.insert(crossing->tlLinkIndex);
2466 crossingIndices.insert(crossing->tlLinkIndex2);
2467 }
2468 }
2469 // smart adapations for new state
2470 bool haveGreen = false;
2471 bool haveYellow = false;
2472 for (const auto& linkStateChar : state) {
2473 if ((linkStateChar == LINKSTATE_TL_GREEN_MAJOR) || (linkStateChar == LINKSTATE_TL_GREEN_MINOR)) {
2474 haveGreen = true;
2475 } else if ((linkStateChar == LINKSTATE_TL_YELLOW_MAJOR) || (linkStateChar == LINKSTATE_TL_YELLOW_MINOR)) {
2476 haveYellow = true;
2477 }
2478 }
2479 if (haveGreen && haveYellow) {
2480 // guess left-mover state
2481 duration = TIME2STEPS(neteditOptions.getInt("tls.left-green.time"));
2482 for (int i = 0; i < (int)state.size(); i++) {
2483 if ((state[i] == LINKSTATE_TL_YELLOW_MAJOR) || (state[i] == LINKSTATE_TL_YELLOW_MINOR)) {
2484 state[i] = LINKSTATE_TL_RED;
2485 } else if (state[i] == LINKSTATE_TL_GREEN_MINOR) {
2486 state[i] = LINKSTATE_TL_GREEN_MAJOR;
2487 }
2488 }
2489 } else if (haveGreen) {
2490 // guess yellow state
2491 myTLSEditorParent->myEditedDef->setParticipantsInformation();
2492 duration = TIME2STEPS(myTLSEditorParent->myEditedDef->computeBrakingTime(neteditOptions.getFloat("tls.yellow.min-decel")));
2493 for (int i = 0; i < (int)state.size(); i++) {
2494 if ((state[i] == LINKSTATE_TL_GREEN_MAJOR) || (state[i] == LINKSTATE_TL_GREEN_MINOR)) {
2495 if (crossingIndices.count(i) == 0) {
2496 state[i] = LINKSTATE_TL_YELLOW_MINOR;
2497 } else {
2498 state[i] = LINKSTATE_TL_RED;
2499 }
2500 }
2501 }
2502 } else if (haveYellow) {
2503 duration = TIME2STEPS(neteditOptions.isDefault("tls.allred.time") ? 2 : neteditOptions.getInt("tls.allred.time"));
2504 // guess all-red state
2505 for (int i = 0; i < (int)state.size(); i++) {
2506 if ((state[i] == LINKSTATE_TL_YELLOW_MAJOR) || (state[i] == LINKSTATE_TL_YELLOW_MINOR)) {
2507 state[i] = LINKSTATE_TL_RED;
2508 }
2509 }
2510 }
2511 // fix continuous green states
2512 if (myPhaseTable->getNumRows() > 1) {
2513 const int nextIndex = (myPhaseTable->getNumRows() > newIndex) ? newIndex : 0;
2514 const std::string state2 = myPhaseTable->getItemText(nextIndex, (TLSStatic ? 2 : 4));
2515 for (int i = 0; i < (int)state.size(); i++) {
2516 if (((oldState[i] == LINKSTATE_TL_GREEN_MAJOR) || (oldState[i] == LINKSTATE_TL_GREEN_MINOR)) &&
2517 ((state2[i] == LINKSTATE_TL_GREEN_MAJOR) || (state2[i] == LINKSTATE_TL_GREEN_MINOR))) {
2518 state[i] = oldState[i];
2519 }
2520 }
2521 }
2522 // add new step
2523 if (NEMA) {
2524 myTLSEditorParent->myEditedDef->getLogic()->addStep(string2time("90"), state, string2time("5"), string2time("50"),
2526 string2time("2"), string2time("3"), string2time("2"), "1", std::vector<int>(), newIndex);
2527 } else {
2528 myTLSEditorParent->myEditedDef->getLogic()->addStep(duration, state, std::vector<int>(), "", newIndex);
2529 }
2530 // return new index
2531 return newIndex;
2532}
2533
2534
2535bool
2536GNETLSEditorFrame::TLSPhases::setDuration(const int col, const int row, const std::string& value) {
2537 // check value
2538 if (value.empty()) {
2539 // input empty, reset
2540 getPhaseTable()->setItemText(row, col, getSteps2Time(myTLSEditorParent->getPhase(row).duration).c_str());
2541 return true;
2543 const auto duration = getSUMOTime(value);
2544 // check that duration > 0
2545 if (duration > 0) {
2546 myTLSEditorParent->myEditedDef->getLogic()->setPhaseDuration(row, duration);
2547 myTLSEditorParent->myTLSPrograms->markAsModified();
2548 // update Cycle duration
2550 return true;
2551 } else {
2552 return false;
2553 }
2554 } else {
2555 return false;
2556 }
2557}
2558
2559
2560bool
2561GNETLSEditorFrame::TLSPhases::setState(const int col, const int row, const std::string& value) {
2562 // get state
2563 const auto& phase = myTLSEditorParent->getPhase(row);
2564 // declare new state. If value is empty, use previous value (reset)
2565 const auto newState = value.empty() ? phase.state : value;
2566 // insert phase
2567 try {
2568 myTLSEditorParent->myEditedDef->getLogic()->addStep(phase.duration, newState, phase.next, phase.name, row);
2569 } catch (ProcessError&) {
2570 // invalid character in newState
2571 return false;
2572 }
2573 // delete next phase
2574 try {
2575 myTLSEditorParent->myEditedDef->getLogic()->deletePhase(row + 1);
2576 } catch (InvalidArgument&) {
2577 WRITE_ERROR(TL("Error deleting phase '") + toString(row + 1) + "'");
2578 return false;
2579 }
2580 // mark TLS as modified depending of value
2581 if (value.size() > 0) {
2582 myTLSEditorParent->myTLSPrograms->markAsModified();
2583 // select row
2584 myPhaseTable->selectRow(row);
2585 } else {
2586 // input empty, reset
2587 getPhaseTable()->setItemText(row, col, newState);
2588 }
2589 // update state size
2590 updateStateSize(col);
2591 return true;
2592}
2593
2594
2595bool
2596GNETLSEditorFrame::TLSPhases::setNext(const int row, const std::string& value) {
2597 // check next
2598 if (GNEAttributeCarrier::canParse<std::vector<int> >(value)) {
2599 const auto nextEdited = GNEAttributeCarrier::parse<std::vector<int> >(value);
2600 for (const auto nextPhase : nextEdited) {
2601 if ((nextPhase < 0) || (nextPhase >= myPhaseTable->getNumRows())) {
2602 return false;
2603 }
2604 }
2605 // set new next
2606 myTLSEditorParent->myEditedDef->getLogic()->setPhaseNext(row, nextEdited);
2607 myTLSEditorParent->myTLSPrograms->markAsModified();
2608 return true;
2609 } else {
2610 return false;
2611 }
2612}
2613
2614
2615bool
2616GNETLSEditorFrame::TLSPhases::setName(const int row, const std::string& value) {
2617 // update name (currently no check needed)
2618 myTLSEditorParent->myEditedDef->getLogic()->setPhaseName(row, value);
2619 myTLSEditorParent->myTLSPrograms->markAsModified();
2620 return true;
2621}
2622
2623
2624bool
2625GNETLSEditorFrame::TLSPhases::setMinDur(const int row, const std::string& value) {
2626 // check value
2627 if (value.empty()) {
2628 // set empty value
2629 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2630 myTLSEditorParent->myTLSPrograms->markAsModified();
2631 return true;
2633 const auto minDur = getSUMOTime(value);
2634 // check that minDur > 0
2635 if (minDur > 0) {
2636 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, minDur);
2637 myTLSEditorParent->myTLSPrograms->markAsModified();
2638 return true;
2639 } else {
2640 return false;
2641 }
2642 } else if (StringUtils::prune(value).empty()) {
2643 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2644 myTLSEditorParent->myTLSPrograms->markAsModified();
2645 return true;
2646 } else {
2647 return false;
2648 }
2649}
2650
2651
2652bool
2653GNETLSEditorFrame::TLSPhases::setMaxDur(const int row, const std::string& value) {
2654 // check value
2655 if (value.empty()) {
2656 // set empty value
2657 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2658 myTLSEditorParent->myTLSPrograms->markAsModified();
2659 return true;
2661 const auto maxDur = getSUMOTime(value);
2662 // check that minDur > 0
2663 if (maxDur > 0) {
2664 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, maxDur);
2665 myTLSEditorParent->myTLSPrograms->markAsModified();
2666 return true;
2667 } else {
2668 return false;
2669 }
2670 } else if (StringUtils::prune(value).empty()) {
2671 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2672 myTLSEditorParent->myTLSPrograms->markAsModified();
2673 return true;
2674 } else {
2675 return false;
2676 }
2677}
2678
2679
2680bool
2681GNETLSEditorFrame::TLSPhases::setEarliestEnd(const int row, const std::string& value) {
2682 // check value
2683 if (value.empty()) {
2684 // set empty value
2685 myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2686 myTLSEditorParent->myTLSPrograms->markAsModified();
2687 return true;
2689 const auto earliestEnd = getSUMOTime(value);
2690 // check that earliestEnd > 0
2691 if (earliestEnd > 0) {
2692 myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, earliestEnd);
2693 myTLSEditorParent->myTLSPrograms->markAsModified();
2694 return true;
2695 } else {
2696 return false;
2697 }
2698 } else if (StringUtils::prune(value).empty()) {
2699 myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2700 myTLSEditorParent->myTLSPrograms->markAsModified();
2701 return true;
2702 } else {
2703 return false;
2704 }
2705}
2706
2707
2708bool
2709GNETLSEditorFrame::TLSPhases::setLatestEnd(const int row, const std::string& value) {
2710 // check value
2711 if (value.empty()) {
2712 // set empty value
2713 myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2714 myTLSEditorParent->myTLSPrograms->markAsModified();
2715 return true;
2717 const auto latestEnd = getSUMOTime(value);
2718 // check that latestEnd > 0
2719 if (latestEnd > 0) {
2720 myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, latestEnd);
2721 myTLSEditorParent->myTLSPrograms->markAsModified();
2722 return true;
2723 } else {
2724 return false;
2725 }
2726 } else if (StringUtils::prune(value).empty()) {
2727 myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2728 myTLSEditorParent->myTLSPrograms->markAsModified();
2729 return true;
2730 } else {
2731 return false;
2732 }
2733}
2734
2735
2736bool
2737GNETLSEditorFrame::TLSPhases::setVehExt(const int row, const std::string& value) {
2738 // check value
2739 if (value.empty()) {
2740 // set empty value
2741 myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2742 myTLSEditorParent->myTLSPrograms->markAsModified();
2743 return true;
2745 const auto vehExt = getSUMOTime(value);
2746 // check that vehExt > 0
2747 if (vehExt > 0) {
2748 myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, vehExt);
2749 myTLSEditorParent->myTLSPrograms->markAsModified();
2750 return true;
2751 } else {
2752 return false;
2753 }
2754 } else if (StringUtils::prune(value).empty()) {
2755 myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2756 myTLSEditorParent->myTLSPrograms->markAsModified();
2757 return true;
2758 } else {
2759 return false;
2760 }
2761}
2762
2763
2764bool
2765GNETLSEditorFrame::TLSPhases::setYellow(const int row, const std::string& value) {
2766 // check value
2767 if (value.empty()) {
2768 // set empty value
2769 myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2770 myTLSEditorParent->myTLSPrograms->markAsModified();
2771 return true;
2773 const auto yellow = getSUMOTime(value);
2774 // check that yellow > 0
2775 if (yellow > 0) {
2776 myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, yellow);
2777 myTLSEditorParent->myTLSPrograms->markAsModified();
2778 return true;
2779 } else {
2780 return false;
2781 }
2782 } else if (StringUtils::prune(value).empty()) {
2783 myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2784 myTLSEditorParent->myTLSPrograms->markAsModified();
2785 return true;
2786 } else {
2787 return false;
2788 }
2789}
2790
2791
2792bool
2793GNETLSEditorFrame::TLSPhases::setRed(const int row, const std::string& value) {
2794 // check value
2795 if (value.empty()) {
2796 // set empty value
2797 myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2798 myTLSEditorParent->myTLSPrograms->markAsModified();
2799 return true;
2801 const auto red = getSUMOTime(value);
2802 // check that red > 0
2803 if (red > 0) {
2804 myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, red);
2805 myTLSEditorParent->myTLSPrograms->markAsModified();
2806 return true;
2807 } else {
2808 return false;
2809 }
2810 } else if (StringUtils::prune(value).empty()) {
2811 myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2812 myTLSEditorParent->myTLSPrograms->markAsModified();
2813 return true;
2814 } else {
2815 return false;
2816 }
2817}
2818
2819
2820void
2822 SUMOTime cycleDuration = 0;
2823 for (const auto& phase : myTLSEditorParent->myEditedDef->getLogic()->getPhases()) {
2824 cycleDuration += phase.duration;
2825 }
2826 // update bot label with cycle duration
2827 myPhaseTable->setColumnLabelBot(col, getSteps2Time(cycleDuration));
2828}
2829
2830
2831void
2833 // update bot label with number of links
2834 myPhaseTable->setColumnLabelBot(col, "Links: " + toString(myTLSEditorParent->myEditedDef->getLogic()->getNumLinks()));
2835}
2836
2837
2838void
2839GNETLSEditorFrame::TLSPhases::updateNextPhase(const int oldNext, const int newNext, const bool swap) {
2840 // get phases
2841 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2842 int i = 0;
2843 for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++, ++i) {
2844 bool oldRef = std::find(it->next.begin(), it->next.end(), oldNext) != it->next.end();
2845 bool newRef = std::find(it->next.begin(), it->next.end(), newNext) != it->next.end();
2846 std::vector<int> nextPhases(it->next);
2847 bool changed = false;
2848 if (swap) {
2849 if (oldRef && newRef) {
2850 std::replace(nextPhases.begin(), nextPhases.end(), oldNext, -1);
2851 std::replace(nextPhases.begin(), nextPhases.end(), newNext, oldNext);
2852 std::replace(nextPhases.begin(), nextPhases.end(), -1, newNext);
2853 changed = true;
2854 } else if (oldRef) {
2855 std::replace(nextPhases.begin(), nextPhases.end(), oldNext, newNext);
2856 changed = true;
2857 } else if (newRef) {
2858 std::replace(nextPhases.begin(), nextPhases.end(), newNext, oldNext);
2859 changed = true;
2860 }
2861 } else if (oldRef) {
2862 if (newNext < 0) {
2863 nextPhases.erase(std::find(nextPhases.begin(), nextPhases.end(), oldNext));
2864 } else {
2865 std::replace(nextPhases.begin(), nextPhases.end(), oldNext, newNext);
2866 }
2867 changed = true;
2868 }
2869 if (changed) {
2870 myTLSEditorParent->myEditedDef->getLogic()->setPhaseNext(i, nextPhases);
2871 }
2872 }
2873}
2874
2875// ---------------------------------------------------------------------------
2876// GNETLSEditorFrame::TLSFile - methods
2877// ---------------------------------------------------------------------------
2878
2880 GNEGroupBoxModule(TLSEditorParent, TL("TLS Program File")),
2881 myTLSEditorParent(TLSEditorParent) {
2882 FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
2883 // create create tlDef button
2884 myLoadButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Load"), "", TL("Load TLS program from additional file"), GUIIconSubSys::getIcon(GUIIcon::OPEN), this, MID_GNE_TLSFRAME_FILE_LOADPROGRAM, GUIDesignButton);
2885 myLoadButton->disable();
2886 // create create tlDef button
2887 mySaveButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Save"), "", TL("Save TLS program to additional file"), GUIIconSubSys::getIcon(GUIIcon::SAVE), this, MID_GNE_TLSFRAME_FILE_SAVEPROGRAM, GUIDesignButton);
2888 mySaveButton->disable();
2889 // show TLSFile
2890 show();
2891}
2892
2893
2895
2896
2897void
2899 if (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() == 0) {
2900 myLoadButton->disable();
2901 mySaveButton->disable();
2902 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
2903 // selecting E1, disable buttons
2904 myLoadButton->disable();
2905 mySaveButton->disable();
2906 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
2907 // joining TLSs, disable button
2908 myLoadButton->disable();
2909 mySaveButton->disable();
2910 } else {
2911 myLoadButton->enable();
2912 mySaveButton->enable();
2913 }
2914}
2915
2916
2917void
2921
2922
2923void
2927
2928
2929long
2931 FXFileDialog opendialog(getCollapsableFrame(), "Load TLS Program");
2932 opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::MODETLS));
2933 opendialog.setSelectMode(SELECTFILE_EXISTING);
2934 opendialog.setPatternList(SUMOXMLDefinitions::XMLFileExtensions.getMultilineString().c_str());
2935 if (gCurrentFolder.length() != 0) {
2936 opendialog.setDirectory(gCurrentFolder);
2937 }
2938 if (opendialog.execute()) {
2939 // run parser
2940 NBTrafficLightLogicCont tmpTLLCont;
2941 NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myTLSEditorParent->getViewNet()->getNet()->getEdgeCont(), true);
2942 tmpTLLCont.insert(myTLSEditorParent->myEditedDef);
2943 XMLSubSys::runParser(tllHandler, opendialog.getFilename().text());
2944
2945 NBLoadedSUMOTLDef* newDefSameProgram = nullptr;
2946 std::set<NBLoadedSUMOTLDef*> newDefsOtherProgram;
2947 for (auto item : tmpTLLCont.getPrograms(myTLSEditorParent->myEditedDef->getID())) {
2948 if (item.second != myTLSEditorParent->myEditedDef) {
2949 NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(item.second);
2950 if (item.first == myTLSEditorParent->myEditedDef->getProgramID()) {
2951 newDefSameProgram = sdef;
2952 } else {
2953 newDefsOtherProgram.insert(sdef);
2954 }
2955 }
2956 }
2957 const int newPrograms = (int)newDefsOtherProgram.size();
2958 if (newPrograms > 0 || newDefSameProgram != nullptr) {
2959 std::vector<NBNode*> nodes = myTLSEditorParent->myEditedDef->getNodes();
2960 for (auto newProg : newDefsOtherProgram) {
2961 for (auto it_node : nodes) {
2962 GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
2963 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newProg, true), true);
2964 }
2965 }
2966 if (newPrograms > 0) {
2967 WRITE_MESSAGE(TL("Loaded ") + toString(newPrograms) + TL(" new programs for tlLogic '") + myTLSEditorParent->myEditedDef->getID() + "'");
2968 }
2969 if (newDefSameProgram != nullptr) {
2970 // replace old program when loading the same program ID
2971 myTLSEditorParent->myEditedDef = newDefSameProgram;
2972 WRITE_MESSAGE(TL("Updated program '") + newDefSameProgram->getProgramID() + TL("' for tlLogic '") + myTLSEditorParent->myEditedDef->getID() + "'");
2973 }
2974 } else {
2975 if (tllHandler.getSeenIDs().count(myTLSEditorParent->myEditedDef->getID()) == 0) {
2976 myTLSEditorParent->getViewNet()->setStatusBarText(TL("No programs found for traffic light '") + myTLSEditorParent->myEditedDef->getID() + "'");
2977 }
2978 }
2979
2980 // clean up temporary container to avoid deletion of defs when its destruct is called
2981 for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
2982 tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
2983 }
2984
2985 myTLSEditorParent->myTLSPhases->initPhaseTable();
2986 myTLSEditorParent->myTLSPrograms->markAsModified();
2987 }
2988 myTLSEditorParent->updateModules();
2989 return 0;
2990}
2991
2992
2993long
2995 FXString file = MFXUtils::getFilename2Write(this, TL("Save TLS Program as"),
2996 SUMOXMLDefinitions::XMLFileExtensions.getMultilineString().c_str(),
2998 // check file
2999 if (file != "") {
3000 // add xml extension
3001 file = FileHelpers::addExtension(file.text(), ".xml").c_str();
3002 OutputDevice& device = OutputDevice::getDevice(file.text());
3003 // save program
3004 device.writeXMLHeader("additional", "additional_file.xsd");
3005 NWWriter_SUMO::writeTrafficLight(device, myTLSEditorParent->myEditedDef->getLogic());
3006 device.close();
3007 }
3008 myTLSEditorParent->updateModules();
3009 return 1;
3010}
3011
3012
3013std::string
3015 const double time = STEPS2TIME(steps);
3016 if (time == std::floor(time)) {
3017 return toString(int(time));
3018 } else {
3019 return toString(time);
3020 }
3021}
3022
3023/****************************************************************************/
FXDEFMAP(GNETLSEditorFrame::TLSJunction) TLSJunctionMap[]
long long int SUMOTime
Definition GUI.h:36
@ MID_GNE_TLSFRAME_TLSJUNCTION_DISJOIN
Disjoin TLS.
@ MID_GNE_TLSFRAME_DEFINITION_RESETCURRENT
reset current (single) TLS program
@ MID_GNE_TLSFRAME_PHASES_ADDUNUSED
add unused states
@ MID_GNE_TLSFRAME_ATTRIBUTES_TOGGLEDETECTOR
set detectors in TLS
@ MID_GNE_TLSFRAME_TLSJUNCTION_TOGGLEJOIN
join TLS
@ MID_GNE_TLSFRAME_PHASES_CLEANUP
cleanup unused states
@ MID_GNE_TLSFRAME_PHASES_GROUPSTATES
group states
@ MID_GNE_BUTTON_CANCEL
cancel button
@ MID_GNE_TLSFRAME_DEFINITION_DELETE
delete TLS
@ MID_GNE_TLSFRAME_FILE_SAVEPROGRAM
cleanup unused states
@ MID_GNE_TLSFRAME_PHASES_UNGROUPSTATES
ungroup states
@ MID_GNE_TLSFRAME_DEFINITION_CREATE
Create TLS.
@ MID_GNE_TLSFRAME_DEFINITION_SAVE
accept TLS modification
@ MID_GNE_TLSFRAME_DEFINITION_SWITCHPROGRAM
switch between programs
@ MID_GNE_TLSFRAME_DEFINITION_DISCARD
cancel TLS modification
@ MID_GNE_TLSFRAME_DEFINITION_RESETALL
reset all TLS programs
@ MID_GNE_TLSFRAME_TLSJUNCTION_TYPE
current TLS ID
@ MID_GNE_TLSFRAME_TLSJUNCTION_ID
current TLS ID
@ MID_GNE_BUTTON_ACCEPT
accept button
@ MID_GNE_TLSFRAME_ATTRIBUTES_OFFSET
TLS offset.
@ MID_GNE_TLSFRAME_ATTRIBUTES_PARAMETERSDIALOG
TLS parameters.
@ MID_GNE_TLSFRAME_FILE_LOADPROGRAM
Load Program.
@ MID_GNE_TLSFRAME_ATTRIBUTES_PARAMETERS
TLS parameters.
#define GUIDesignButtonAttribute
button extended over over column with thick and raise frame
Definition GUIDesigns.h:106
#define GUIDesignTextColorRed
red color (for invalid text)
Definition GUIDesigns.h:44
#define GUIDesignButton
Definition GUIDesigns.h:100
#define GUIDesignComboBoxAttribute
Combo box static (cannot be edited) extended over the matrix column.
Definition GUIDesigns.h:304
#define GUIDesignTextField
Definition GUIDesigns.h:74
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:430
#define GUIDesignAuxiliarHorizontalFrameUniform
design for auxiliar (Without borders) horizontal frame used to pack another frames uniform
Definition GUIDesigns.h:436
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition GUIDesigns.h:92
#define GUIDesignComboBoxVisibleItems
Definition GUIDesigns.h:64
#define GUIDesignTextColorBlack
black color (for correct text)
Definition GUIDesigns.h:38
#define GUIDesignLabelThickedFixed(width)
label thicked, icon before text, text centered and custom width
Definition GUIDesigns.h:254
FXString gCurrentFolder
The folder used as last.
@ MODETLS
Definition GUIIcons.h:371
@ DISJOIN
Definition GUIIcons.h:129
@ OPEN
open icons
Definition GUIIcons.h:79
@ EMPTY
Definition GUIIcons.h:59
@ SAVE
save icons
Definition GUIIcons.h:92
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:288
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
const std::string invalid_return< std::string >::value
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define TIME2STEPS(x)
Definition SUMOTime.h:60
@ SUMO_TAG_INDUCTION_LOOP
alternative tag for e1 detector
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_TL_YELLOW_MAJOR
The link has yellow light, may pass.
@ LINKSTATE_TL_GREEN_MAJOR
The link has green light, may pass.
@ LINKSTATE_DEADEND
This is a dead end link.
@ LINKSTATE_TL_YELLOW_MINOR
The link has yellow light, has to brake anyway.
@ LINKSTATE_TL_RED
The link has red light (must brake).
@ LINKSTATE_TL_GREEN_MINOR
The link has green light, has to brake.
@ SUMO_ATTR_TLLINKINDEX2
link: the index of the opposite direction link of a pedestrian crossing
@ SUMO_ATTR_OFFSET
@ SUMO_ATTR_TLTYPE
node: the type of traffic light
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_PROGRAMID
@ SUMO_ATTR_TLLINKINDEX
link: the index of the link within the traffic light
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
const unsigned char TLS[]
Definition TLS.cpp:22
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
static std::string addExtension(const std::string &path, const std::string &extension)
Add an extension to the given file path.
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
const std::string getID() const override
get ID (all Attribute Carriers have one)
static T parse(const std::string &string)
parses a value of type T from string (used for basic types: int, double, bool, etc....
static bool canParse(const std::string &string)
true if a value of type T can be parsed from string
const GNETagProperties * getTagProperty() const
get tagProperty associated with this Attribute Carrier
Result getResult() const
get result to indicate if this dialog was closed accepting or rejecting changes
GNEViewNet * getViewNet() const
get view net
Definition GNEFrame.cpp:145
GNEViewNet * myViewNet
FOX need this.
Definition GNEFrame.h:122
virtual void show()
show Frame
Definition GNEFrame.cpp:110
virtual void hide()
hide Frame
Definition GNEFrame.cpp:119
GNEFrame(GNEViewParent *viewParent, GNEViewNet *viewNet, const std::string &frameLabel)
Constructor.
Definition GNEFrame.cpp:42
GNEGroupBoxModule (based on FXGroupBox).
Options
GroupBoxModule options.
GNEGroupBoxModule(GNEFrame *frame, const std::string &text, const int options=Options::COLLAPSIBLE)
constructor for frames
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
const GNEHierarchicalContainerChildren< GNELane * > & getChildLanes() const
get child lanes
LinkState getLinkState() const
whether link state has been modified
int getTLIndex() const
get Traffic Light index
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
std::string getAttribute(SumoXMLAttr key) const override
std::vector< GNEConnection * > getGNEConnections() const
Returns all GNEConnections vinculated with this junction.
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList) override
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
NBNode * getNBNode() const
Return net build node.
GNEEdge * getParentEdge() const
get parent edge
Definition GNELane.cpp:214
std::vector< std::pair< std::string, std::string > > getEditedParameters() const
get edited parameters
long onCmdSetParameters(FXObject *, FXSelector, void *)
Called when the user changes parameters of a TLS.
long onCmdSetOffset(FXObject *, FXSelector, void *)
bool isValidOffset()
is current offset valid
long onCmdParametersDialog(FXObject *, FXSelector, void *ptr)
Called when user press edit parameters button.
MFXToggleButtonTooltip * mySetDetectorsToggleButton
toggle button for set detectors mode
bool isSetDetectorsToggleButtonEnabled() const
toggle button for set detectors mode
bool isValidParameters()
are current parameter valid
void updateTLSAttributes()
update TLSAttributes module
FXTextField * myOffsetTextField
the TextField for modifying offset
void disableE1DetectorMode()
disable detector mode
SUMOTime getOffset() const
get current offset in string format
void setParameters(const std::string &parameters)
set new parameters
const std::map< std::string, std::string > & getE1Detectors() const
get E1 detectors vinculated with this TLS
void clearTLSAttributes()
clear TLS attributes
void setOffset(const SUMOTime &offset)
set new offset
std::map< std::string, std::string > myE1Detectors
set with E1 detector IDs and their lanes vinculated with the TLS <laneID, E1ID>
std::string getParameters() const
get current parameters in string format
bool toggleE1DetectorSelection(const GNEAdditional *E1)
select or unselect E1 detector in the current TLS
void initTLSAttributes()
initializes the definitions and corresponding listbox
FXButton * myButtonEditParameters
button for edit parameters
TLSAttributes(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
FXTextField * myParametersTextField
the TextField for modifying parameters
void hideTLSAttributes()
hide TLSAttributes
void showTLSAttributes()
show TLSAttributes
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditorParent
long onCmdToggleDetectorMode(FXObject *, FXSelector, void *ptr)
Called when user toggle set detector mode.
void updateTLSFile()
update TLSFile module
FXButton * myLoadButton
load button
FXButton * mySaveButton
save button
long onCmdLoadTLSProgram(FXObject *, FXSelector, void *)
load TLS Program from an additional file
TLSFile(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
std::string writeSUMOTime(SUMOTime steps)
FOX needs this.
long onCmdSaveTLSProgram(FXObject *, FXSelector, void *)
save TLS Program to an additional file
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
long onCmdChangeType(FXObject *, FXSelector, void *)
Called when the user change TLS Type.
long onCmdDisjoinTLS(FXObject *, FXSelector, void *)
Called when the user join TLS.
std::vector< std::string > mySelectedJunctionIDs
selected junction (used for join)
GNETLSEditorFrame * myTLSEditorParent
TLS editor frame parent.
void refreshTLSJunction()
FOX needs this.
FXHorizontalFrame * myJoinControlButtons
frame for accept/cancel buttons
const std::vector< std::string > & getSelectedJunctionIDs() const
get selected junction IDs
long onCmdToggleJoinTLS(FXObject *, FXSelector, void *)
Called when the user join TLS.
std::vector< std::string > myOriginalSelectedJunctionIDs
original selected junction (used for join)
long onCmdRenameTLS(FXObject *, FXSelector, void *)
TLSJunction(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
long onCmdCancelJoin(FXObject *, FXSelector, void *)
cancel join
MFXComboBoxIcon * myTLSTypeComboBox
ComboBox for TLS Types.
MFXToggleButtonTooltip * myJoinTLSToggleButton
Toggle button for join TLS.
void updateTLSJunction()
update TLSJunction module
void toggleJunctionSelected(const GNEJunction *junction)
select or unselect junction in the current TLS
long onCmdAcceptJoin(FXObject *, FXSelector, void *)
accept join
GNEJunction * getCurrentJunction() const
get current modified junction
void setCurrentJunction(GNEJunction *junction)
set current junction
FXLabel * myJunctionIDLabel
label for junction ID
GNEJunction * myCurrentJunction
the junction of the tls is being modified
bool isJunctionSelected(const GNEJunction *junction) const
check if given junction is selected (used fo joining)
MFXTextFieldIcon * myJunctionIDTextField
text field for junction ID
MFXButtonTooltip * myDisjoinTLSButton
button for disjoin TLS
bool isJoiningJunctions() const
is joining junctions
MFXTextFieldIcon * myTLSIDTextField
text field for junction ID
bool setEarliestEnd(const int row, const std::string &value)
set earliestEnd
long onCmdUngroupStates(FXObject *, FXSelector, void *)
Called when the user ungroups states.
GNETLSTable * myPhaseTable
table for selecting and rearranging phases and for changing duration
long onCmdCleanStates(FXObject *, FXSelector, void *)
long onCmdGroupStates(FXObject *, FXSelector, void *)
Called when the user groups states.
void clearPhaseTable()
clear phase thable
MFXButtonTooltip * myGroupSignalsButton
group signals button
bool setVehExt(const int row, const std::string &value)
set vehExt
MFXButtonTooltip * myAddStates
add states button
int buildDefaultPhase(const int row)
build default phase
void updateTLSPhases()
update TLSPhases module
TLSPhases(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
void movePhaseDown(const int row)
move phase down
void initActuatedPhaseTable()
init actuated phase table
void initPhaseTable()
initializes the phase table
void initNEMAPhaseTable()
init NEMA phase table
bool setYellow(const int row, const std::string &value)
set yellow
bool changePhaseValue(const int col, const int row, const std::string &value)
change phase value (state, name, next, etc.)
void initDelayBasePhaseTable()
init delayBase phase table
void movePhaseUp(const int row)
move phase up
bool setMinDur(const int row, const std::string &value)
set minDur
bool setLatestEnd(const int row, const std::string &value)
set latestEnd
MFXButtonTooltip * myCleanStatesButton
clean states button
void updateStateSize(const int col)
update state size
MFXButtonTooltip * myUngroupSignalsButton
ungroup signals button
long onCmdAddUnusedStates(FXObject *, FXSelector, void *)
Called when the user cleans up states.
void updateNextPhase(const int oldNext, const int newNext=-1, const bool swap=false)
update phase references given in next field
void initStaticPhaseTable()
init static phase table
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
bool setDuration(const int col, const int row, const std::string &value)
set duration
bool setMaxDur(const int row, const std::string &value)
set maxDur
void updateTLSColoring()
update TLS coloring
GNETLSTable * getPhaseTable() const
get phase table
void removePhase(const int row)
delete phase
bool setRed(const int row, const std::string &value)
set red
bool setName(const int row, const std::string &value)
set name
bool setState(const int col, const int row, const std::string &value)
set state
void duplicatePhase(const int row)
duplicate phase
void addPhase(const int row, const char c=' ')
add phase
GNETLSEditorFrame * getTLSEditorParent() const
get TLSEditor Parent
bool setNext(const int row, const std::string &value)
set next
void updateCycleDuration(const int col)
recomputes cycle duration and updates label
bool checkHaveModifications() const
check if current TLS was modified
FXButton * mySaveButon
button for save TLS program
void updateTLSPrograms()
update TLSPrograms module
bool initTLSPrograms()
init TLS Definitions
long onCmdDefSwitchTLSProgram(FXObject *, FXSelector, void *)
Called when the user switches a TLS.
MFXComboBoxIcon * myProgramComboBox
the comboBox for selecting the tl-definition to edit
GNETLSEditorFrame * myTLSEditorParent
pointer to GNETLSEditorFrame parent
FXButton * myCancelButon
button for cancel TLS program
void clearTLSProgramss()
clear TLS Definitions
int getNumberOfPrograms() const
get number of programs
long onCmdSaveChanges(FXObject *, FXSelector, void *)
Called when the user presses the save-Button.
void hideTLSPrograms()
hide TLSPrograms
void createTLS(GNEJunction *junction)
FOX needs this.
bool myHaveModifications
whether the current tls was modified
std::vector< NBTrafficLightDefinition * > myTLSPrograms
the list of Definitions for the current junction
FXButton * myDeleteButton
button for delete existent TLS program
long onCmdDiscardChanges(FXObject *, FXSelector, void *)
Called when the user presses the Cancel-button.
void discardChanges(const bool editJunctionAgain)
discard changes
long onCmdCreate(FXObject *, FXSelector, void *)
FXButton * myResetAllButton
button for reset all TLS program
long onCmdResetAll(FXObject *, FXSelector, void *)
Called when the user press button reset all TLS Programs.
FXButton * myResetSingleButton
button for reset TLS program
long onCmdResetCurrentProgram(FXObject *, FXSelector, void *)
Called when the user press button reset current TLS Program.
NBTrafficLightDefinition * getCurrentTLSPrograms() const
get current definition
TLSPrograms(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
void showTLSPrograms()
show TLSPrograms
void markAsModified()
mark Program as modified
long onCmdDelete(FXObject *, FXSelector, void *)
Called when the user press button delete TLS Program.
const std::string getCurrentTLSProgramID() const
get current program ID
FXButton * myCreateButton
button for create new TLS program
GNETLSEditorFrame::TLSFile * myTLSFile
module for load/Save TLS Programs
GNETLSEditorFrame::TLSPrograms * myTLSPrograms
module for TLS Definition
void handleChange(GNEInternalLane *lane)
update phase definition for the current traffic light and phase
GNEOverlappedInspection * myOverlappedInspection
Overlapped Inspection.
GNETLSEditorFrame::TLSPhases * getTLSPhases() const
get module for TLS Phases
GNETLSEditorFrame::TLSAttributes * getTLSAttributes() const
get module for TLS attributes
GNETLSEditorFrame::TLSAttributes * myTLSAttributes
module for TLS attributes
static std::string varDurString(SUMOTime dur)
convert duration (potentially undefined) to string
bool isTLSSaved()
check if modifications in TLS was saved
void editJunction(GNEJunction *junction)
edits the traffic light for the given junction
GNETLSEditorFrame::TLSPhases * myTLSPhases
module for TLS Phases
void selectedOverlappedElement(GNEAttributeCarrier *AC)
open GNEAttributesCreator extended dialog (can be reimplemented in frame children)
GNETLSEditorFrame(GNEViewParent *viewParent, GNEViewNet *viewNet)
Constructor.
std::map< int, std::vector< GNEInternalLane * > > myInternalLanes
the internal lanes belonging to the current junction indexed by their tl-index
void updateModules()
update modules
bool parseTLSPrograms(const std::string &file)
parse TLS Programs from a file
bool controlsEdge(GNEEdge *edge) const
whether the given edge is controlled by the currently edited tlDef
static const std::string getSteps2Time(const SUMOTime value)
converts to SUMOTime
void buildInternalLanes(const NBTrafficLightDefinition *tlDef)
builds internal lanes for the given tlDef
const NBTrafficLightLogic::PhaseDefinition & getPhase(const int index)
get certain phase of the current traffic light
void handleMultiChange(GNELane *lane, FXObject *obj, FXSelector sel, void *data)
update phase definition for the current traffic light and phase
GNETLSEditorFrame::TLSJunction * getTLSJunction() const
get module for TLS Junction
static SUMOTime getSUMOTime(const std::string &value)
converts to SUMOTime
~GNETLSEditorFrame()
Destructor.
NBLoadedSUMOTLDef * myEditedDef
the traffic light definition being edited
void frameWidthUpdated()
function called after setting new width in current frame
void editTLS(GNEViewNetHelper::ViewObjectsSelector &viewObjects, const Position &clickedPosition, const bool shiftKeyPressed)
edits the traffic light for the given clicked junction
GNETLSEditorFrame::TLSJunction * myTLSJunction
module for TLS Junction
GNETLSEditorFrame::TLSPrograms * getTLSPrograms() const
get module for TLS Definition
void cleanup()
cleans up previous lanes
void show()
show inspector frame
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
void add(GNEChange *command, bool doit=false, bool merge=true)
Add new command, executing it if desired. The new command will be merged with the previous command if...
class used to group all variables related with objects under cursor after a click over view
GNEAdditional * getAdditionalFront() const
get front additional element or a pointer to nullptr
GNEJunction * getJunctionFront() const
get front junction or a pointer to nullptr
const std::vector< GNEJunction * > & getJunctions() const
get vector with junctions
GNEViewParent * getViewParent() const
get the net object
A single child window which contains a view of the simulation area.
GNEApplicationWindow * getGNEAppWindows() const
get GNE Application Windows
static FXButton * buildFXButton(FXComposite *p, const std::string &text, const std::string &tip, const std::string &help, FXIcon *ic, FXObject *tgt, FXSelector sel, FXuint opts=BUTTON_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0, FXint pl=DEFAULT_PAD, FXint pr=DEFAULT_PAD, FXint pt=DEFAULT_PAD, FXint pb=DEFAULT_PAD)
build button
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
MFXStaticToolTip * getStaticTooltipMenu() const
get static toolTip for menus
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extensions, FXIcon *icon, FXString &currentFolder)
Returns the file name to write.
Definition MFXUtils.cpp:117
static FXColor getFXColor(const RGBColor &col)
converts FXColor to RGBColor
Definition MFXUtils.cpp:146
A loaded (complete) traffic light logic.
void setProgramID(const std::string &programID)
Sets the programID.
A definition of a pedestrian crossing.
Definition NBNode.h:135
int tlLinkIndex
the traffic light index of this crossing (if controlled)
Definition NBNode.h:162
Represents a single node (junction) during network building.
Definition NBNode.h:66
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node).
Definition NBNode.h:345
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition NBNode.h:336
A traffic light logics which must be computed (only nodes/edges are given).
Definition NBOwnTLDef.h:44
The base class for traffic light logic definitions.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
const std::string & getProgramID() const
Returns the ProgramID.
TrafficLightType getType() const
get the algorithm type (static etc..)
virtual void setProgramID(const std::string &programID)
Sets the programID.
NBTrafficLightLogic * compute(const OptionsCont &oc)
Computes the traffic light logic.
SUMOTime getOffset()
Returns the offset.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
static const SUMOTime UNSPECIFIED_DURATION
The definition of a single phase of the logic.
A container for traffic light definitions and built programs.
bool exist(const std::string &newID, bool requireComputed=true) const
check if exists a definition with the given ID
bool removeProgram(const std::string id, const std::string programID, bool del=true)
Removes a program of a logic definition from the dictionary.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
NBTrafficLightLogic * getLogic(const std::string &id, const std::string &programID) const
Returns the computed logic for the given name.
std::string getNextProgramID(const std::string &id) const
Returns a new (unused) programID for the given traffic light.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
A SUMO-compliant built logic for a traffic light.
Importer for edge connections stored in XML.
const std::set< std::string > & getSeenIDs()
static void writeTrafficLight(OutputDevice &into, const NBTrafficLightLogic *logic)
writes a single traffic light logic to the given device
const std::string & getID() const
Returns the id.
Definition Named.h:73
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
void close()
Closes the device and removes it from the dictionary.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
static bool areParametersValid(const std::string &value, bool report=false, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to a parameters map "key1=value1|key2=value2|....
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
A list of positions.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
PositionVector reverse() const
reverse position vector
static const RGBColor BLACK
Definition RGBColor.h:200
static const RGBColor RED
named colors
Definition RGBColor.h:192
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
static StringBijection< XMLFileExtension > XMLFileExtensions
XML file Extensions.
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
A structure which describes a connection between edges or lanes.
Definition NBEdge.h:201
PositionVector viaShape
shape of via
Definition NBEdge.h:282
PositionVector shape
shape of Connection
Definition NBEdge.h:270