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-2023 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
18// The Widget for modifying traffic lights
19/****************************************************************************/
20#include <config.h>
21
23#include <netbuild/NBOwnTLDef.h>
24#include <netedit/GNENet.h>
25#include <netedit/GNEUndoList.h>
26#include <netedit/GNEViewNet.h>
41#include <utils/xml/XMLSubSys.h>
42
43#include "GNETLSEditorFrame.h"
44
45
46// ===========================================================================
47// FOX callback mapping
48// ===========================================================================
49
62
78};
79
89
100
107
108// Object implementation
109FXIMPLEMENT(GNETLSEditorFrame::TLSJunction, MFXGroupBoxModule, TLSJunctionMap, ARRAYNUMBER(TLSJunctionMap))
110FXIMPLEMENT(GNETLSEditorFrame::TLSDefinition, MFXGroupBoxModule, TLSDefinitionMap, ARRAYNUMBER(TLSDefinitionMap))
111FXIMPLEMENT(GNETLSEditorFrame::TLSAttributes, MFXGroupBoxModule, TLSAttributesMap, ARRAYNUMBER(TLSAttributesMap))
112FXIMPLEMENT(GNETLSEditorFrame::TLSPhases, MFXGroupBoxModule, TLSPhasesMap, ARRAYNUMBER(TLSPhasesMap))
113FXIMPLEMENT(GNETLSEditorFrame::TLSFile, MFXGroupBoxModule, TLSFileMap, ARRAYNUMBER(TLSFileMap))
114
115
116// ===========================================================================
117// method definitions
118// ===========================================================================
119
121 GNEFrame(viewParent, viewNet, TL("Edit Traffic Light")),
122 myEditedDef(nullptr) {
123
124 // Create Overlapped Inspection module
125 myOverlappedInspection = new GNEOverlappedInspection(this, SUMO_TAG_JUNCTION);
126
127 // create TLSJunction module
128 myTLSJunction = new GNETLSEditorFrame::TLSJunction(this);
129
130 // create TLSDefinition module
131 myTLSDefinition = new GNETLSEditorFrame::TLSDefinition(this);
132
133 // create TLSAttributes module
134 myTLSAttributes = new GNETLSEditorFrame::TLSAttributes(this);
135
136 // create TLSPhases module
137 myTLSPhases = new GNETLSEditorFrame::TLSPhases(this);
138
139 // create TLSFile module
140 myTLSFile = new GNETLSEditorFrame::TLSFile(this);
141}
142
143
147
148
149void
151 // hide myOverlappedInspection
153 // show
155}
156
157
158void
163
164
165void
166GNETLSEditorFrame::editTLS(const Position& clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor& objectsUnderCursor) {
167 // first check if in objectsUnderCursor there is a junction
168 if (objectsUnderCursor.getJunctionFront()) {
169 // show objects under cursor
170 myOverlappedInspection->showOverlappedInspection(objectsUnderCursor, clickedPosition);
171 // hide if we inspect only one junction
174 }
175 // check if we're adding or removing joined TLSs
178 } else {
179 editJunction(objectsUnderCursor.getJunctionFront());
180 }
181 } else if (objectsUnderCursor.getAdditionalFront() && myTLSAttributes->isSetDetectorsToggleButtonEnabled() &&
182 (objectsUnderCursor.getAdditionalFront()->getTagProperty().getTag() == SUMO_TAG_INDUCTION_LOOP)) {
184 } else {
185 myViewNet->setStatusBarText(TL("Click over a junction to edit a TLS"));
186 }
187}
188
189
190bool
193 // write warning if netedit is running in testing mode
194 WRITE_DEBUG("Opening question FXMessageBox 'save TLS'");
195 // open question box
196 FXuint answer = FXMessageBox::question(this, MBOX_YES_NO_CANCEL,
197 TL("Save TLS Changes"), "%s",
198 TL("There is unsaved changes in current edited traffic light.\nDo you want to save it before changing mode?"));
199 if (answer == MBOX_CLICKED_YES) { //1:yes, 2:no, 4:esc/cancel
200 // write warning if netedit is running in testing mode
201 WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'YES'");
202 // save modifications
203 myTLSDefinition->onCmdSaveChanges(nullptr, 0, nullptr);
204 return true;
205 } else if (answer == MBOX_CLICKED_NO) {
206 // write warning if netedit is running in testing mode
207 WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'No'");
208 // cancel modifications
209 myTLSDefinition->onCmdSaveChanges(nullptr, 0, nullptr);
210 return true;
211 } else {
212 // write warning if netedit is running in testing mode
213 WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'Cancel'");
214 // abort changing mode
215 return false;
216 }
217 } else {
218 return true;
219 }
220}
221
222
223bool
224GNETLSEditorFrame::parseTLSPrograms(const std::string& file) {
226 NBTrafficLightLogicCont tmpTLLCont;
227 NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myViewNet->getNet()->getEdgeCont());
228 // existing definitions must be available to update their programs
229 std::set<NBTrafficLightDefinition*> origDefs;
230 for (NBTrafficLightDefinition* def : tllCont.getDefinitions()) {
231 // make a duplicate of every program
232 NBTrafficLightLogic* logic = tllCont.getLogic(def->getID(), def->getProgramID());
233 if (logic != nullptr) {
234 NBTrafficLightDefinition* duplicate = new NBLoadedSUMOTLDef(*def, *logic);
235 std::vector<NBNode*> nodes = def->getNodes();
236 for (auto it_node : nodes) {
237 GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
238 myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, false, false), true);
239 myViewNet->getUndoList()->add(new GNEChange_TLS(junction, duplicate, true), true);
240 }
241 tmpTLLCont.insert(duplicate);
242 origDefs.insert(duplicate);
243 } else {
244 WRITE_WARNINGF(TL("tlLogic '%', program '%' could not be built"), def->getID(), def->getProgramID());
245 }
246 }
247 //std::cout << " initialized tmpCont with " << origDefs.size() << " defs\n";
248 XMLSubSys::runParser(tllHandler, file);
249
250 std::vector<NBLoadedSUMOTLDef*> loadedTLS;
251 for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
252 NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
253 if (sdef != nullptr) {
254 loadedTLS.push_back(sdef);
255 }
256 }
257 myViewNet->setStatusBarText(TL("Loaded ") + toString(loadedTLS.size()) + TL(" programs"));
258 for (auto def : loadedTLS) {
259 if (origDefs.count(def) != 0) {
260 // already add to undolist before
261 //std::cout << " skip " << def->getDescription() << "\n";
262 continue;
263 }
264 std::vector<NBNode*> nodes = def->getNodes();
265 //std::cout << " add " << def->getDescription() << " for nodes=" << toString(nodes) << "\n";
266 for (auto it_node : nodes) {
267 GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
268 //myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, false), true);
269 myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, true), true);
270 }
271 }
272 // clean up temporary container to avoid deletion of defs when it's destruct is called
273 for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
274 tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
275 }
276 return true;
277}
278
279
280void
284
285
286void
291 for (const auto& node : myTLSDefinition->getCurrentTLSDefinition()->getNodes()) {
292 myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(node->getID())->selectTLS(false);
293 }
294 }
295 }
296 // clean data structures
298 // check if delete myEditedDef
299 if (myEditedDef) {
300 delete myEditedDef;
301 myEditedDef = nullptr;
302 }
303 // clear internal lanes
304 buildInternalLanes(nullptr);
305 // clean up attributes
307 // clean up attributes
309 // only clears when there are no definitions
311}
312
313
318
319
324
325
330
331
332void
334 // clean up previous internal lanes
335 for (const auto& internalLanes : myInternalLanes) {
336 for (const auto& internalLane : internalLanes.second) {
337 // remove internal lane from grid
339 // delete internal lane
340 delete internalLane;
341 }
342 }
343 // clear container
344 myInternalLanes.clear();
345 // create new internal lanes
346 if (tlDef != nullptr) {
347 const int NUM_POINTS = 10;
348 const NBNode* nbnCurrentJunction = myTLSJunction->getCurrentJunction()->getNBNode();
349 // get innerID NWWriter_SUMO::writeInternalEdges
350 const std::string innerID = ":" + nbnCurrentJunction->getID();
351 const NBConnectionVector& links = tlDef->getControlledLinks();
352 // iterate over links
353 for (const auto& link : links) {
354 int tlIndex = link.getTLIndex();
355 PositionVector shape;
356 try {
357 const NBEdge::Connection& con = link.getFrom()->getConnection(link.getFromLane(), link.getTo(), link.getToLane());
358 shape = con.shape;
359 shape.append(con.viaShape);
360 } catch (ProcessError&) {
361 shape = link.getFrom()->getToNode()->computeInternalLaneShape(link.getFrom(), NBEdge::Connection(link.getFromLane(),
362 link.getTo(), link.getToLane()), NUM_POINTS);
363 }
364 if (shape.length() < 2) {
365 // enlarge shape to ensure visibility
366 shape.clear();
367 const PositionVector laneShapeFrom = link.getFrom()->getLaneShape(link.getFromLane());
368 const PositionVector laneShapeTo = link.getTo()->getLaneShape(link.getToLane());
369 shape.push_back(laneShapeFrom.positionAtOffset(MAX2(0.0, laneShapeFrom.length() - 1)));
370 shape.push_back(laneShapeTo.positionAtOffset(MIN2(1.0, laneShapeFrom.length())));
371 }
372 GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), innerID + '_' + toString(tlIndex), shape, tlIndex);
373 // due GNEInternalLane aren't attribute carriers, we need to use the net grid
374 myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
375 myInternalLanes[tlIndex].push_back(internalLane);
376 }
377 // iterate over crossings
378 for (const auto& nbn : tlDef->getNodes()) {
379 for (const auto& crossing : nbn->getCrossings()) {
380 if (crossing->tlLinkIndex2 > 0 && crossing->tlLinkIndex2 != crossing->tlLinkIndex) {
381 // draw both directions
382 PositionVector forward = crossing->shape;
383 forward.move2side(crossing->width / 4);
384 GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, forward, crossing->tlLinkIndex);
385 // due GNEInternalLane aren't attribute carriers, we need to use the net grid
386 myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
387 myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
388 PositionVector backward = crossing->shape.reverse();
389 backward.move2side(crossing->width / 4);
390 GNEInternalLane* internalLaneReverse = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id + "_r", backward, crossing->tlLinkIndex2);
391 // due GNEInternalLane aren't attribute carriers, we need to use the net grid
392 myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLaneReverse);
393 myInternalLanes[crossing->tlLinkIndex2].push_back(internalLaneReverse);
394 } else {
395 // draw only one lane for both directions
396 GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, crossing->shape, crossing->tlLinkIndex);
397 // due GNEInternalLane aren't attribute carriers, we need to use the net grid
398 myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
399 myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
400 }
401 }
402 }
403 }
404}
405
406
407std::string
411
412
415 if ((index >= 0) || (index < (int)myEditedDef->getLogic()->getPhases().size())) {
416 return myEditedDef->getLogic()->getPhases().at(index);
417 } else {
418 throw ProcessError(TL("Invalid phase index"));
419 }
420}
421
422
423void
426 // get current selected row
427 const auto selectedRow = myTLSPhases->getPhaseTable()->getCurrentSelectedRow();
428 if (myViewNet->changeAllPhases()) {
429 for (int row = 0; row < (int)myEditedDef->getLogic()->getPhases().size(); row++) {
430 myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
431 }
432 } else {
434 }
435 // init phaseTable
437 // select row
438 myTLSPhases->getPhaseTable()->selectRow(selectedRow);
439 // focus table
440 myTLSPhases->getPhaseTable()->setFocus();
441}
442
443
444void
445GNETLSEditorFrame::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* eventData) {
446 if (myEditedDef != nullptr) {
449 std::set<std::string> fromIDs;
450 fromIDs.insert(lane->getMicrosimID());
451 // if neither the lane nor its edge are selected, apply changes to the whole edge
453 for (auto it_lane : lane->getParentEdge()->getLanes()) {
454 fromIDs.insert(it_lane->getMicrosimID());
455 }
456 } else {
457 // if the edge is selected, apply changes to all lanes of all selected edges
459 const auto selectedEdge = myViewNet->getNet()->getAttributeCarriers()->getSelectedEdges();
460 for (const auto& edge : selectedEdge) {
461 for (auto it_lane : edge->getLanes()) {
462 fromIDs.insert(it_lane->getMicrosimID());
463 }
464 }
465 }
466 // if the lane is selected, apply changes to all selected lanes
467 if (lane->isAttributeCarrierSelected()) {
468 const auto selectedLanes = myViewNet->getNet()->getAttributeCarriers()->getSelectedLanes();
469 for (auto it_lane : selectedLanes) {
470 fromIDs.insert(it_lane->getMicrosimID());
471 }
472 }
473
474 }
475 // set new state for all connections from the chosen lane IDs
476 for (auto it : links) {
477 if (fromIDs.count(it.getFrom()->getLaneID(it.getFromLane())) > 0) {
478 std::vector<GNEInternalLane*> lanes = myInternalLanes[it.getTLIndex()];
479 for (auto it_lane : lanes) {
480 it_lane->onDefault(obj, sel, eventData);
481 }
482 }
483 }
484 }
485}
486
487
488bool
490 if (myEditedDef != nullptr) {
492 for (auto it : links) {
493 if (it.getFrom()->getID() == edge->getMicrosimID()) {
494 return true;
495 }
496 }
497 }
498 return false;
499}
500
501
502void
505 // discard previous changes
507 // set junction
509 // init TLS definitions
511 // init TLSAttributes
513 // begin undo-list
514 myViewNet->getUndoList()->begin(GUIIcon::MODETLS, TL("modifying TLS definition"));
515 // only select TLS if getCurrentJunction exist
518 }
521 myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(node->getID())->selectTLS(true);
522 }
523 // update color
525 }
526 }
527 } else {
528 myViewNet->setStatusBarText(TL("Unsaved modifications. Abort or Save"));
529 }
530}
531
532
534GNETLSEditorFrame::getSUMOTime(const std::string& string) {
535 return TIME2STEPS(GNEAttributeCarrier::parse<double>(string));
536}
537
538const std::string
540 return toString(STEPS2TIME(value));
541}
542
543// ---------------------------------------------------------------------------
544// GNETLSEditorFrame::TLSAttributes - methods
545// ---------------------------------------------------------------------------
546
548 MFXGroupBoxModule(TLSEditorParent, TL("Traffic light Attributes")),
549 myTLSEditorParent(TLSEditorParent) {
550 // create frame, label and TextField for Offset (By default disabled)
551 FXHorizontalFrame* horizontalFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
552 new FXLabel(horizontalFrame, toString(SUMO_ATTR_OFFSET).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
554 myOffsetTextField->disable();
555 // create frame, label and TextField for parameters (By default disabled)
556 horizontalFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
557 myButtonEditParameters = new FXButton(horizontalFrame, TL("parameters"), nullptr, this, MID_GNE_TLSFRAME_ATTRIBUTES_PARAMETERSDIALOG, GUIDesignButtonAttribute);
559 myButtonEditParameters->disable();
560 myParametersTextField->disable();
561 // create Checkable button
564 TL("Assign E1 detectors") + std::string("\t") + TL("Enable assign E1 mode") + std::string("\t") + TL("Assign E1 detectors to the current TLS"),
565 TL("Assign E1 detectors") + std::string("\t") + TL("Disable assign E1 mode") + std::string("\t") + TL("Assign E1 detectors to the current TLS"),
568}
569
570
572
573
574void
578
579
580void
584
585
586void
588 // get current edited junction
589 const auto junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
590 if (junction == nullptr) {
591 throw ProcessError("Junction cannot be NULL");
592 } else {
593 // enable Offset
594 myOffsetTextField->enable();
595 myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
596 // enable parameters
597 myButtonEditParameters->enable();
598 myParametersTextField->enable();
599 myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
600 // reset mySetDetectorsToggleButton
601 disableE1DetectorMode();
602 }
603}
604
605
606void
608 // clear and disable Offset TextField
609 myOffsetTextField->setText("");
610 myOffsetTextField->disable();
611 myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
612 // clear and disable parameters TextField
613 myButtonEditParameters->disable();
614 myParametersTextField->setText("");
615 myParametersTextField->disable();
616 myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
617}
618
619
622 return getSUMOTime(myOffsetTextField->getText().text());
623}
624
625
626void
628 myOffsetTextField->setText(getSteps2Time(offset).c_str());
629 myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
630}
631
632
633bool
635 if (GNEAttributeCarrier::canParse<SUMOTime>(myOffsetTextField->getText().text())) {
636 myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
637 return true;
638 } else {
639 myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::RED));
640 return false;
641 }
642}
643
644
645std::string
647 return myParametersTextField->getText().text();
648}
649
650
651void
653 myParametersTextField->setText(parameters.c_str());
654 myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
655 // update E1 detectors
656 if (myTLSEditorParent->myEditedDef->getType() != TrafficLightType::STATIC) {
657 updateE1Detectors();
658 }
659}
660
661
662bool
664 if (Parameterised::areParametersValid(myParametersTextField->getText().text())) {
665 myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
666 return true;
667 } else {
668 myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::RED));
669 return false;
670 }
671}
672
673
674bool
676 return (mySetDetectorsToggleButton->getState() == TRUE);
677}
678
679
680bool
682 // get E1 lane ID
683 const auto laneID = E1->getParentLanes().front()->getID();
684 // iterate over all E1 detectors
685 for (auto it = myE1Detectors.begin(); it != myE1Detectors.end(); it++) {
686 if (E1->getID() == it->second) {
687 // already selected, then remove it from detectors
688 myE1Detectors.erase(it);
689 // and remove it from parameters
690 myTLSEditorParent->myEditedDef->unsetParameter(laneID);
691 myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
692 // mark TL as modified
693 myTLSEditorParent->myTLSDefinition->markAsModified();
694 return true;
695 } else if (laneID == it->first) {
696 // there is another E1 in the same lane, then swap
697 myE1Detectors.erase(it);
698 myE1Detectors[laneID] = E1->getID();
699 // also in parameters
700 myTLSEditorParent->myEditedDef->setParameter(laneID, E1->getID());
701 myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
702 // mark TL as modified
703 myTLSEditorParent->myTLSDefinition->markAsModified();
704 return true;
705 }
706 }
707 // add it in parameters
708 myE1Detectors[laneID] = E1->getID();
709 myTLSEditorParent->myEditedDef->setParameter(laneID, E1->getID());
710 myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
711 // mark TL as modified
712 myTLSEditorParent->myTLSDefinition->markAsModified();
713 return true;
714}
715
716
717const std::map<std::string, std::string>&
719 return myE1Detectors;
720}
721
722
723void
725 mySetDetectorsToggleButton->setState(FALSE, TRUE);
726}
727
728
729long
731 if (isValidOffset()) {
732 myTLSEditorParent->myTLSDefinition->markAsModified();
733 myTLSEditorParent->myEditedDef->setOffset(getOffset());
734 myOffsetTextField->killFocus();
735 myTLSEditorParent->update();
736 }
737 return 1;
738}
739
740
741long
743 if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() == 0) {
744 myOffsetTextField->disable();
745 // clear E1 detectors
746 if (myE1Detectors.size() > 0) {
747 myE1Detectors.clear();
748 myTLSEditorParent->getViewNet()->update();
749 }
750 } else if (isSetDetectorsToggleButtonEnabled()) {
751 myOffsetTextField->disable();
752 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
753 // joining TLSs, disable button
754 myOffsetTextField->disable();
755 } else {
756 myOffsetTextField->enable();
757 }
758 return 1;
759}
760
761
762long
764 if (isValidParameters()) {
765 myTLSEditorParent->myTLSDefinition->markAsModified();
766 myTLSEditorParent->myEditedDef->setParametersStr(getParameters());
767 myParametersTextField->killFocus();
768 myTLSEditorParent->update();
769 }
770 return 1;
771}
772
773
774long
776 // continue depending of myEditedDef
777 if (myTLSEditorParent->myEditedDef) {
778 // get previous parameters
779 const auto previousParameters = getParameters();
780 // write debug information
781 WRITE_DEBUG("Open single parameters dialog");
782 if (GNESingleParametersDialog(myTLSEditorParent->getViewNet()->getApp(), myTLSEditorParent->myEditedDef).execute()) {
783 // write debug information
784 WRITE_DEBUG("Close single parameters dialog");
785 // set parameters in textfield
786 setParameters(myTLSEditorParent->myEditedDef->getParametersStr());
787 // only mark as modified if parameters are different
788 if (getParameters() != previousParameters) {
789 myTLSEditorParent->myTLSDefinition->markAsModified();
790 }
791 } else {
792 // write debug information
793 WRITE_DEBUG("Cancel single parameters dialog");
794 }
795 }
796 return 1;
797}
798
799
800long
802 if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() == 0) {
803 myButtonEditParameters->disable();
804 myParametersTextField->disable();
805 // clear E1 detectors
806 if (myE1Detectors.size() > 0) {
807 myE1Detectors.clear();
808 myTLSEditorParent->getViewNet()->update();
809 }
810 } else if (isSetDetectorsToggleButtonEnabled()) {
811 myButtonEditParameters->disable();
812 myParametersTextField->disable();
813 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
814 // joining TLSs, disable button
815 myButtonEditParameters->disable();
816 myParametersTextField->disable();
817 } else {
818 myButtonEditParameters->enable();
819 myParametersTextField->enable();
820 }
821 return 1;
822}
823
824
825long
827 if (mySetDetectorsToggleButton->getState()) {
828 // set special color
829 mySetDetectorsToggleButton->setBackColor(FXRGBA(253, 255, 206, 255));
830 } else {
831 // restore default color
832 mySetDetectorsToggleButton->setBackColor(4293980400);
833 }
834 // update view
835 myTLSEditorParent->getViewNet()->update();
836 return 1;
837}
838
839
840long
842 if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() == 0) {
843 disableE1DetectorMode();
844 mySetDetectorsToggleButton->disable();
845 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
846 // joining TLSs, disable button
847 disableE1DetectorMode();
848 mySetDetectorsToggleButton->disable();
849 } else if (myTLSEditorParent->myTLSDefinition->getCurrentTLSDefinition()->getType() == TrafficLightType::STATIC) {
850 disableE1DetectorMode();
851 mySetDetectorsToggleButton->disable();
852 } else {
853 mySetDetectorsToggleButton->enable();
854 }
855 return 1;
856}
857
858
859void
861 // first clear E1 detectors
862 myE1Detectors.clear();
863 // iterate over parameters
864 for (const auto& parameter : myTLSEditorParent->myEditedDef->getParametersMap()) {
865 // check if both lane and E1 exists
866 if (myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveLane(parameter.first, false) &&
867 myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_INDUCTION_LOOP, parameter.second, false)) {
868 // add it into list
869 myE1Detectors[parameter.first] = parameter.second;
870 }
871 }
872 // update view net
873 myTLSEditorParent->getViewNet()->update();
874}
875
876// ---------------------------------------------------------------------------
877// GNETLSEditorFrame::TLSJunction - methods
878// ---------------------------------------------------------------------------
879
881 MFXGroupBoxModule(TLSEditorParent, TL("Traffic Light")),
882 myTLSEditorParent(TLSEditorParent),
883 myCurrentJunction(nullptr) {
884 // Create frame for junction IDs
885 FXHorizontalFrame* junctionIDFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
886 myJunctionIDLabel = new FXLabel(junctionIDFrame, TL("Junction ID"), nullptr, GUIDesignLabelThickedFixed(100));
887 myJunctionIDTextField = new MFXTextFieldTooltip(junctionIDFrame,
890 myJunctionIDTextField->disable();
891 // Create frame for TLS Program ID
892 FXHorizontalFrame* TLSIDFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
893 new FXLabel(TLSIDFrame, TL("TLS ID"), nullptr, GUIDesignLabelThickedFixed(100));
894 myTLSIDTextField = new MFXTextFieldTooltip(TLSIDFrame,
897 // create frame, label and textfield for type
898 FXHorizontalFrame* typeFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
899 new FXLabel(typeFrame, toString(SUMO_ATTR_TYPE).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
901 // fill comboBox (only certain TL types)
907 // create frame for join buttons
908 FXHorizontalFrame* joinButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
909 // create join states button
912 TL("Join") + std::string("\t") + TL("Enable join mode") + std::string("\t") + TL("Join TLS and junctions in the current junction."),
913 TL("Join") + std::string("\t") + TL("Disable join mode") + std::string("\t") + TL("Join TLS and junctions in the current junction."),
916 myDisjoinTLSButton = new MFXButtonTooltip(joinButtons,
918 TL("Disjoin") + std::string("\t") + TL("Disjoin current TLS") + std::string("\t") + TL("Disjoin current TLS."),
920 // create frame for join control buttons
922 // create create tlDef button
923 new FXButton(myJoinControlButtons, (TL("Accept") + std::string("\t\t") + TL("Finish join.")).c_str(),
925 new FXButton(myJoinControlButtons, (TL("Cancel") + std::string("\t\t") + TL("Cancel Join.")).c_str(),
927 myJoinControlButtons->hide();
928 // update junction description after creation
930 // show TLS Junction
931 show();
932}
933
934
936
937
940 return myCurrentJunction;
941}
942
943
944void
946 myCurrentJunction = junction;
947 // update junction description
948 updateJunctionDescription();
949}
950
951
952void
954 // first reset junction label
955 myJunctionIDLabel->setText(TL("Junction ID"));
956 // clear selected junctions
957 mySelectedJunctionIDs.clear();
958 // cancel joining junction mode
959 onCmdCancelJoin(nullptr, 0, nullptr);
960 // continue depending of current junction
961 if (myCurrentJunction == nullptr) {
962 myJunctionIDTextField->setText(TL("no junction selected"));
963 } else {
964 const auto nbn = myCurrentJunction->getNBNode();
965 // update junction ID text field
966 myJunctionIDTextField->setText(nbn->getID().c_str());
967 // check if junction is controlled
968 if (nbn->getControllingTLS().size() > 0) {
969 // get all nodes controlled by this TLS
970 const auto NBNodes = (*nbn->getControllingTLS().begin())->getNodes();
971 // declare string
972 std::string nodesStr;
973 for (auto it = NBNodes.begin(); it != NBNodes.end(); it++) {
974 if (it == (NBNodes.end() - 1)) {
975 nodesStr += (*it)->getID();
976 } else {
977 nodesStr += (*it)->getID() + ", ";
978 }
979 }
980 // updated junction fields
981 myJunctionIDTextField->setText(nodesStr.c_str());
982 // update junction label
983 if (NBNodes.size() > 1) {
984 myJunctionIDLabel->setText(TL("Junction IDs"));
985 }
986 // update TLS ID text field
987 myTLSIDTextField->setText((*nbn->getControllingTLS().begin())->getID().c_str());
988 // set TLS type
989 myTLSTypeComboBox->setText(myCurrentJunction->getAttribute(SUMO_ATTR_TLTYPE).c_str());
990 }
991 }
992}
993
994bool
996 return (myJoinTLSToggleButton->getState() == TRUE);
997}
998
999
1000bool
1002 return (std::find(mySelectedJunctionIDs.begin(), mySelectedJunctionIDs.end(), junction->getID()) != mySelectedJunctionIDs.end());
1003}
1004
1005
1006void
1008 // avoid current junction
1009 if (junction != myCurrentJunction) {
1010 // find ID in selected junctions
1011 auto it = std::find(mySelectedJunctionIDs.begin(), mySelectedJunctionIDs.end(), junction->getID());
1012 // check if add or remove
1013 if (it == mySelectedJunctionIDs.end()) {
1014 mySelectedJunctionIDs.push_back(junction->getID());
1015 } else {
1016 mySelectedJunctionIDs.erase(it);
1017 }
1018 }
1019}
1020
1021
1022const std::vector<std::string>&
1024 return mySelectedJunctionIDs;
1025}
1026
1027
1028long
1030 // get IDs
1031 const std::string currentTLID = (*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getID();
1032 const std::string newTLID = myTLSIDTextField->getText().text();
1033 // check if ID is valid
1034 if (newTLID.empty() || (newTLID == currentTLID)) {
1035 // same ID or empty
1036 myTLSIDTextField->setTextColor(FXRGB(0, 0, 0));
1037 myTLSIDTextField->setText(currentTLID.c_str());
1038 myTLSIDTextField->killFocus();
1039 myTLSEditorParent->update();
1040 // show all moduls
1041 myTLSEditorParent->myTLSDefinition->showTLSDefinition();
1042 myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1043 myTLSEditorParent->myTLSPhases->showTLSPhases();
1044 myTLSEditorParent->myTLSFile->showTLSFile();
1045 } else if (!SUMOXMLDefinitions::isValidNetID(newTLID) || myCurrentJunction->getNet()->getTLLogicCont().exist(newTLID)) {
1046 // set invalid color
1047 myTLSIDTextField->setTextColor(FXRGB(255, 0, 0));
1048 // hide moduls
1049 myTLSEditorParent->myTLSDefinition->hideTLSDefinition();
1050 myTLSEditorParent->myTLSAttributes->hideTLSAttributes();
1051 myTLSEditorParent->myTLSPhases->hideTLSPhases();
1052 myTLSEditorParent->myTLSFile->hideTLSFile();
1053 } else {
1054 // make a copy of myCurrentJunction and current tlDef (because will be reset after calling discardChanges)
1055 auto junction = myCurrentJunction;
1056 const auto tlDef = myTLSEditorParent->myTLSDefinition->getCurrentTLSDefinition();
1057 // restore color
1058 myTLSIDTextField->setTextColor(FXRGB(0, 0, 0));
1059 myTLSIDTextField->killFocus();
1060 myTLSEditorParent->update();
1061 // discard previous changes
1062 myTLSEditorParent->myTLSDefinition->discardChanges(false);
1063 // change name using undo-List
1064 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("rename TLS"));
1065 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, tlDef, newTLID), true);
1066 myTLSEditorParent->getViewNet()->getUndoList()->end();
1067 // show all moduls
1068 myTLSEditorParent->myTLSDefinition->showTLSDefinition();
1069 myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1070 myTLSEditorParent->myTLSPhases->showTLSPhases();
1071 myTLSEditorParent->myTLSFile->showTLSFile();
1072 // edit junction again
1073 myTLSEditorParent->editJunction(junction);
1074 }
1075 return 1;
1076}
1077
1078
1079long
1080GNETLSEditorFrame::TLSJunction::onUpdTLSID(FXObject*, FXSelector, void*) {
1081 if (myCurrentJunction == nullptr) {
1082 // no junction, disable and clear
1083 myTLSIDTextField->setText("");
1084 myTLSIDTextField->disable();
1085 } else if (myCurrentJunction->getNBNode()->getControllingTLS().size() == 0) {
1086 // no TLSs in Junctions, disable
1087 myTLSIDTextField->disable();
1088 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1089 // selecting E1, disable button
1090 myTLSIDTextField->disable();
1091 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1092 // joining TLSs, disable button
1093 myTLSIDTextField->disable();
1094 } else if (myTLSEditorParent->myTLSDefinition->checkHaveModifications()) {
1095 // current TLS modified, disable
1096 myTLSIDTextField->disable();
1097 } else if (isJoiningJunctions()) {
1098 // joining TLSs, disable button
1099 myTLSIDTextField->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1100 } else {
1101 // enable
1102 myTLSIDTextField->enable();
1103 }
1104 return 1;
1105}
1106
1107
1108long
1110 // get IDs
1111 const std::string currentTLType = toString((*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getType());
1112 const std::string newTLType = myTLSTypeComboBox->getText().text();
1113 // check if ID is valid
1114 if (newTLType.empty() || (newTLType == currentTLType)) {
1115 // same ID or empty, don't change
1116 myTLSTypeComboBox->setTextColor(FXRGB(0, 0, 0));
1117 myTLSTypeComboBox->setText(currentTLType.c_str());
1118 myTLSTypeComboBox->killFocus();
1119 myTLSEditorParent->update();
1120 // show all moduls
1121 myTLSEditorParent->myTLSDefinition->showTLSDefinition();
1122 myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1123 myTLSEditorParent->myTLSPhases->showTLSPhases();
1124 myTLSEditorParent->myTLSFile->showTLSFile();
1125 } else if (!SUMOXMLDefinitions::TrafficLightTypes.hasString(newTLType)) {
1126 // set invalid color
1127 myTLSTypeComboBox->setTextColor(FXRGB(255, 0, 0));
1128 // hide moduls
1129 myTLSEditorParent->myTLSDefinition->hideTLSDefinition();
1130 myTLSEditorParent->myTLSAttributes->hideTLSAttributes();
1131 myTLSEditorParent->myTLSPhases->hideTLSPhases();
1132 myTLSEditorParent->myTLSFile->hideTLSFile();
1133 } else {
1134 // reset color
1135 myTLSTypeComboBox->setTextColor(FXRGB(0, 0, 0));
1136 myTLSTypeComboBox->killFocus();
1137 myTLSEditorParent->update();
1138 // make a copy of myCurrentJunction (because will be reset after calling discardChanges)
1139 auto junction = myCurrentJunction;
1140 // discard previous changes
1141 myTLSEditorParent->myTLSDefinition->discardChanges(false);
1142 // change name using undo-List
1143 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("change TLS type"));
1144 junction->setAttribute(SUMO_ATTR_TLTYPE, newTLType, myTLSEditorParent->getViewNet()->getUndoList());
1145 myTLSEditorParent->getViewNet()->getUndoList()->end();
1146 // show all moduls
1147 myTLSEditorParent->myTLSDefinition->showTLSDefinition();
1148 myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1149 myTLSEditorParent->myTLSPhases->showTLSPhases();
1150 myTLSEditorParent->myTLSFile->showTLSFile();
1151 // edit junction again
1152 myTLSEditorParent->editJunction(junction);
1153 }
1154 return 1;
1155
1156}
1157
1158
1159long
1161 if (myCurrentJunction == nullptr) {
1162 // no junction, disable and clear
1163 myTLSTypeComboBox->setText("");
1164 myTLSTypeComboBox->disable();
1165 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1166 // selecting E1, disable button
1167 myTLSTypeComboBox->disable();
1168 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1169 // joining TLSs, disable button
1170 myTLSTypeComboBox->disable();
1171 } else if (myCurrentJunction->getNBNode()->getControllingTLS().size() == 0) {
1172 // no TLSs in Junctions, disable
1173 myTLSTypeComboBox->disable();
1174 } else if (myTLSEditorParent->myTLSDefinition->checkHaveModifications()) {
1175 // current TLS modified, disable
1176 myTLSTypeComboBox->disable();
1177 } else {
1178 // enable
1179 myTLSTypeComboBox->enable();
1180 }
1181 return 1;
1182}
1183
1184
1185long
1187 if (myJoinTLSToggleButton->getState()) {
1188 // set special color
1189 myJoinTLSToggleButton->setBackColor(FXRGBA(253, 255, 206, 255));
1190 // clear and fill mySelectedJunctionIDs
1191 mySelectedJunctionIDs.clear();
1192 // get all nodes controlled by this TLS
1193 const auto TLNodes = (*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getNodes();
1194 // fill mySelectedJunctionIDs with TLNodes
1195 mySelectedJunctionIDs.clear();
1196 for (const auto& TLNode : TLNodes) {
1197 mySelectedJunctionIDs.push_back(TLNode->getID());
1198 }
1199 // make a copy of selected junctions
1200 myOriginalSelectedJunctionIDs = mySelectedJunctionIDs;
1201 // show control buttons
1202 myJoinControlButtons->show();
1203 getCollapsableFrame()->recalc();
1204 } else {
1205 // hide control buttons
1206 myJoinControlButtons->hide();
1207 getCollapsableFrame()->recalc();
1208 // make a copy of current junction
1209 const auto currentJunction = myCurrentJunction;
1210 // declare vectors for junctions
1211 std::vector<GNEJunction*> selectedJunctions, resetTLJunctions;
1212 // get selected junctions (all except current
1213 for (const auto& selectedJunctionID : mySelectedJunctionIDs) {
1214 if (selectedJunctionID != currentJunction->getID()) {
1215 selectedJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(selectedJunctionID));
1216 }
1217 }
1218 // get junctions to reset TL (all TL nodes except current)
1219 for (const auto& TLNBNode : (*currentJunction->getNBNode()->getControllingTLS().begin())->getNodes()) {
1220 if (TLNBNode != currentJunction->getNBNode()) {
1221 resetTLJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLNBNode->getID()));
1222 }
1223 }
1224 // discard changes
1225 myTLSEditorParent->myTLSDefinition->discardChanges(false);
1226 // begin undo list
1227 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("join TLS"));
1228 // remove tl from TLNBNode
1229 for (const auto& resetTLJunction : resetTLJunctions) {
1230 resetTLJunction->setAttribute(SUMO_ATTR_TYPE, "priority", myTLSEditorParent->getViewNet()->getUndoList());
1231 }
1232 // now update it in all joined junctions
1233 for (const auto& selectedJunction : selectedJunctions) {
1234 selectedJunction->setAttribute(SUMO_ATTR_TYPE, currentJunction->getAttribute(SUMO_ATTR_TYPE), myTLSEditorParent->getViewNet()->getUndoList());
1235 selectedJunction->setAttribute(SUMO_ATTR_TLID, currentJunction->getAttribute(SUMO_ATTR_TLID), myTLSEditorParent->getViewNet()->getUndoList());
1236 }
1237 // end undo list
1238 myTLSEditorParent->getViewNet()->getUndoList()->end();
1239 // restore default color
1240 myJoinTLSToggleButton->setBackColor(4293980400);
1241 // clear selected junction IDs
1242 mySelectedJunctionIDs.clear();
1243 // edit junction again
1244 myTLSEditorParent->editJunction(currentJunction);
1245 }
1246 // update view
1247 myTLSEditorParent->getViewNet()->update();
1248 return 1;
1249}
1250
1251
1252long
1253GNETLSEditorFrame::TLSJunction::onUpdJoinTLS(FXObject* sender, FXSelector, void*) {
1254 if (myCurrentJunction == nullptr) {
1255 // no junction, disable
1256 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1257 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1258 // selecting E1, disable
1259 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1260 } else if (myTLSEditorParent->myTLSDefinition->checkHaveModifications()) {
1261 // current TLS modified, disable
1262 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1263 } else if (myCurrentJunction->getNBNode()->getControllingTLS().size() == 0) {
1264 // no TLSs in Junctions, disable
1265 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1266 } else {
1267 // enable
1268 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
1269 }
1270}
1271
1272
1273long
1275 // make a copy of current junction
1276 const auto currentJunction = myCurrentJunction;
1277 // declare vectors for junctions
1278 std::vector<GNEJunction*> resetTLJunctions;
1279 // get junctions to reset TL
1280 for (const auto& TLNBNode : (*currentJunction->getNBNode()->getControllingTLS().begin())->getNodes()) {
1281 resetTLJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLNBNode->getID()));
1282 }
1283 // save TL types
1284 const auto type = resetTLJunctions.front()->getAttribute(SUMO_ATTR_TYPE);
1285 const auto tlType = resetTLJunctions.front()->getAttribute(SUMO_ATTR_TLTYPE);
1286 // discard changes
1287 myTLSEditorParent->myTLSDefinition->discardChanges(false);
1288 // begin undo list
1289 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("disjoin TLS"));
1290 // the disjoint tlIds will be the junction ids. Ensure that there is no name clash with the current tlId
1291 NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1292 const std::string oldId = currentJunction->getAttribute(SUMO_ATTR_TLID);
1293 const std::string tmpIdBase = oldId + "_TMP";
1294 int tmpIndex = 0;
1295 std::string tmpId = tmpIdBase + toString(tmpIndex);
1296 while (tllCont.exist(tmpId)) {
1297 tmpId = tmpIdBase + toString(++tmpIndex);
1298 }
1299 for (NBTrafficLightDefinition* tlDef : currentJunction->getNBNode()->getControllingTLS()) {
1300 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(currentJunction, tlDef, tmpId), true);
1301 }
1302 // remove tl from TLNBNode and the re-initialize as single traffic light
1303 for (const auto& resetTLJunction : resetTLJunctions) {
1304 resetTLJunction->setAttribute(SUMO_ATTR_TYPE, "priority", myTLSEditorParent->getViewNet()->getUndoList());
1305 resetTLJunction->setAttribute(SUMO_ATTR_TYPE, type, myTLSEditorParent->getViewNet()->getUndoList());
1306 resetTLJunction->setAttribute(SUMO_ATTR_TLTYPE, tlType, myTLSEditorParent->getViewNet()->getUndoList());
1307 }
1308 // end undo list
1309 myTLSEditorParent->getViewNet()->getUndoList()->end();
1310 // restore default color
1311 myJoinTLSToggleButton->setBackColor(4293980400);
1312 // clear selected junction IDs
1313 mySelectedJunctionIDs.clear();
1314 // edit junction again
1315 myTLSEditorParent->editJunction(currentJunction);
1316 return 1;
1317}
1318
1319
1320long
1321GNETLSEditorFrame::TLSJunction::onUpdDisjoinTLS(FXObject* sender, FXSelector, void*) {
1322 if (myCurrentJunction == nullptr) {
1323 // no junction, disable
1324 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1325 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1326 // selecting E1, disable
1327 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1328 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1329 // joining TLSs, disable button
1330 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1331 } else if (myTLSEditorParent->myTLSDefinition->checkHaveModifications()) {
1332 // current TLS modified, disable
1333 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1334 } else if (myCurrentJunction->getNBNode()->getControllingTLS().size() == 0) {
1335 // no TLSs in Junctions, disable
1336 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1337 } else if ((*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getNodes().size() == 1) {
1338 // TLS only control one junction, disable
1339 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1340 } else {
1341 // enable
1342 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
1343 }
1344}
1345
1346
1347long
1349 myJoinTLSToggleButton->setState(FALSE, TRUE);
1350 return 1;
1351}
1352
1353
1354long
1356 // restore selected junction
1357 mySelectedJunctionIDs = myOriginalSelectedJunctionIDs;
1358 myJoinTLSToggleButton->setState(FALSE, TRUE);
1359 return 1;
1360}
1361
1362
1363// ---------------------------------------------------------------------------
1364// GNETLSEditorFrame::TLSDefinition - methods
1365// ---------------------------------------------------------------------------
1366
1368 MFXGroupBoxModule(TLSEditorParent, TL("Traffic Light Programs")),
1369 myTLSEditorParent(TLSEditorParent) {
1370 // create frame, label and comboBox for programID
1371 FXHorizontalFrame* programFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1372 new FXLabel(programFrame, toString(SUMO_ATTR_PROGRAMID).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
1374 myProgramComboBox->setEditable(false);
1375 myProgramComboBox->disable();
1376 // create auxiliar frames
1377 FXHorizontalFrame* horizontalFrameAux = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
1378 FXVerticalFrame* verticalFrameAuxA = new FXVerticalFrame(horizontalFrameAux, GUIDesignAuxiliarHorizontalFrame);
1379 FXVerticalFrame* verticalFrameAuxB = new FXVerticalFrame(horizontalFrameAux, GUIDesignAuxiliarHorizontalFrame);
1380 // create create tlDef button
1381 myCreateButton = new FXButton(verticalFrameAuxA, (TL("Create TLS") + std::string("\t\t") + TL("Create a new traffic light program.")).c_str(),
1383 // create delete tlDef button
1384 new FXButton(verticalFrameAuxA, (TL("Delete") + std::string("\t\t") + TL("Delete a traffic light program. If all programs are deleted the junction turns into a priority junction.")).c_str(),
1386 // create reset current tlDef button
1387 new FXButton(verticalFrameAuxB, (TL("Reset single") + std::string("\t\t") + TL("Reset current TLS program.")).c_str(),
1389 // create reset all tlDefs button
1390 new FXButton(verticalFrameAuxB, (TL("Reset all") + std::string("\t\t") + TL("Reset all TLS programs.")).c_str(),
1392 // create save modifications button
1393 new FXButton(verticalFrameAuxA, (TL("Save") + std::string("\t\t") + TL("Save program modifications. (Enter)")).c_str(),
1395 // create discard modifications buttons
1396 new FXButton(verticalFrameAuxB, (TL("Cancel") + std::string("\t\t") + TL("Discard program modifications. (Esc)")).c_str(),
1398 // show GroupBox
1399 show();
1400}
1401
1402
1404
1405
1406void
1410
1411
1412void
1416
1417
1418bool
1420 // get current edited junction
1421 const auto junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1422 if (junction == nullptr) {
1423 throw ProcessError("Junction cannot be NULL");
1424 } else {
1425 // clear definitions
1426 myTLSDefinitions.clear();
1427 // obtain TLSs sorted by ID
1428 std::set<std::string> programIDs;
1429 for (const auto& TLS : junction->getNBNode()->getControllingTLS()) {
1430 myTLSDefinitions.push_back(TLS);
1431 programIDs.insert(TLS->getProgramID());
1432 }
1433 for (const auto& programID : programIDs) {
1434 myProgramComboBox->appendItem(programID.c_str());
1435 }
1436 // check if enable TLS definitions
1437 if (myTLSDefinitions.size() > 0) {
1438 myProgramComboBox->enable();
1439 myProgramComboBox->setCurrentItem(0);
1440 myProgramComboBox->setNumVisible(myProgramComboBox->getNumItems());
1441 // switch TLS Program
1442 return switchProgram();
1443 }
1444 return false;
1445 }
1446}
1447
1448
1449void
1451 // clear definitions
1452 myTLSDefinitions.clear();
1453 // clear and disable myProgramComboBox
1454 myProgramComboBox->clearItems();
1455 myProgramComboBox->disable();
1456}
1457
1458
1459int
1461 return myProgramComboBox->getNumItems();
1462}
1463
1464
1465int
1467 return (int)myTLSDefinitions.size();
1468}
1469
1470
1471bool
1473 return myHaveModifications;
1474}
1475
1476
1477void
1479 myHaveModifications = true;
1480}
1481
1482
1485 // find TLS definition
1486 for (const auto& TLSDefinition : myTLSDefinitions) {
1487 if (TLSDefinition->getProgramID() == myProgramComboBox->getText().text()) {
1488 return TLSDefinition;
1489 }
1490 }
1491 throw ProcessError(TL("TLSDefinition cannot be found"));
1492}
1493
1494
1495const std::string
1497 if (myProgramComboBox->getNumItems() == 0) {
1498 return "";
1499 } else {
1500 return myProgramComboBox->getText().text();
1501 }
1502}
1503
1504
1505void
1507 // get junction copy
1508 auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1509 if (currentJunction != nullptr) {
1510 myTLSEditorParent->getViewNet()->getUndoList()->abortAllChangeGroups();
1511 myTLSEditorParent->cleanup();
1512 myTLSEditorParent->getViewNet()->updateViewNet();
1513 // edit junction again
1514 if (editJunctionAgain) {
1515 myTLSEditorParent->editJunction(currentJunction);
1516 }
1517 }
1518}
1519
1520
1521long
1523 // get current edited junction (needed because onCmdDiscardChanges clear junction)
1524 GNEJunction* currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1525 // abort because we onCmdOk assumes we wish to save an edited definition
1526 discardChanges(false);
1527 // check number of edges
1528 if (currentJunction->getGNEIncomingEdges().empty() && currentJunction->getGNEOutgoingEdges().empty()) {
1529 // write warning if netedit is running in testing mode
1530 WRITE_DEBUG("Opening warning FXMessageBox 'invalid TLS'");
1531 // open question box
1532 FXMessageBox::warning(this, MBOX_OK,
1533 TL("TLS cannot be created"), "%s",
1534 (TL("Traffic Light cannot be created because junction must have") + std::string("\n") +
1535 TL("at least one incoming edge and one outgoing edge.")).c_str());
1536 // write warning if netedit is running in testing mode
1537 WRITE_DEBUG("Closed FXMessageBox 'invalid TLS'");
1538 return 1;
1539 }
1540 // check number of connections
1541 if (currentJunction->getGNEConnections().empty()) {
1542 // write warning if netedit is running in testing mode
1543 WRITE_DEBUG("Opening warning FXMessageBox 'invalid TLS'");
1544 // open question box
1545 FXMessageBox::warning(this, MBOX_OK,
1546 TL("TLS cannot be created"), "%s",
1547 (TL("Traffic Light cannot be created because junction") + std::string("\n") +
1548 TL("must have at least one connection.")).c_str());
1549 // write warning if netedit is running in testing mode
1550 WRITE_DEBUG("Closed FXMessageBox 'invalid TLS'");
1551 return 1;
1552 }
1553 // check uncontrolled connections
1554 bool connectionControlled = false;
1555 for (const auto& connection : currentJunction->getGNEConnections()) {
1556 if (!connection->getNBEdgeConnection().uncontrolled) {
1557 connectionControlled = true;
1558 }
1559 }
1560 if (connectionControlled == false) {
1561 // write warning if netedit is running in testing mode
1562 WRITE_DEBUG("Opening warning FXMessageBox 'invalid TLS'");
1563 // open question box
1564 FXMessageBox::warning(this, MBOX_OK,
1565 TL("TLS cannot be created"), "%s",
1566 (TL("Traffic Light cannot be created because junction") + std::string("\n") +
1567 TL("must have at least one controlled connection.")).c_str());
1568 // write warning if netedit is running in testing mode
1569 WRITE_DEBUG("Closed FXMessageBox 'invalid TLS'");
1570 return 1;
1571 }
1572 // all checks ok, then create TLS in junction
1573 createTLS(currentJunction);
1574 // edit junction
1575 myTLSEditorParent->editJunction(currentJunction);
1576 // switch to the last program
1577 myProgramComboBox->setCurrentItem(myProgramComboBox->getNumItems() - 1, TRUE);
1578 return 1;
1579}
1580
1581
1582long
1583GNETLSEditorFrame::TLSDefinition::onUpdCreate(FXObject* sender, FXSelector, void*) {
1584 // get current junction
1585 const auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1586 // check conditions
1587 if (currentJunction == nullptr) {
1588 // no junction, disable button
1589 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1590 } else if (myHaveModifications) {
1591 // wait for modifications, disable button
1592 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1593 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1594 // selecting E1, disable button
1595 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1596 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1597 // joining TLSs, disable button
1598 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1599 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1600 // joining TLSs, disable button
1601 sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1602 } else {
1603 // enable button
1604 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
1605 }
1606 // update button text
1607 if (currentJunction == nullptr) {
1608 myCreateButton->setText(TL("Create"));
1609 } else if (currentJunction->getNBNode()->isTLControlled()) {
1610 myCreateButton->setText(TL("Duplicate"));
1611 } else {
1612 myCreateButton->setText(TL("Create"));
1613 }
1614 return 1;
1615}
1616
1617
1618long
1620 // get current junction
1621 GNEJunction* currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1622 // get current edited tlDef
1623 NBTrafficLightDefinition* tlDef = myTLSEditorParent->myTLSDefinition->getCurrentTLSDefinition();
1624 // check if remove entire TLS or only one program
1625 const bool changeJunctionType = (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() == 1);
1626 // abort because onCmdOk assumes we wish to save an edited definition
1627 discardChanges(false);
1628 // check if change junction type
1629 if (changeJunctionType) {
1630 currentJunction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::PRIORITY), myTLSEditorParent->getViewNet()->getUndoList());
1631 } else {
1632 // just remove TLDef
1633 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(currentJunction, tlDef, false), true);
1634 // edit junction again
1635 myTLSEditorParent->editJunction(currentJunction);
1636 }
1637 return 1;
1638}
1639
1640
1641long
1643 // obtain junction and old definitions
1644 GNEJunction* junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1645 NBTrafficLightDefinition* oldDef = myTLSEditorParent->myTLSDefinition->getCurrentTLSDefinition();
1646 const std::string programID = oldDef->getProgramID();
1647 // discard changes
1648 discardChanges(false);
1649 // begin undo
1650 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("reset current program"));
1651 // remove old definition
1652 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, oldDef, false), true);
1653 // create new definition, and add it
1654 NBOwnTLDef* newDef = new NBOwnTLDef(oldDef->getID(), oldDef->getNodes(), oldDef->getOffset(), oldDef->getType());
1655 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newDef, true, true), true);
1656 // set old index
1657 newDef->setProgramID(programID);
1658 // end undo
1659 myTLSEditorParent->getViewNet()->getUndoList()->end();
1660 // inspect junction again
1661 myTLSEditorParent->editJunction(junction);
1662 // switch to programID
1663 int index = -1;
1664 for (int i = 0; i < myProgramComboBox->getNumItems(); i++) {
1665 if (myProgramComboBox->getItem(i).text() == programID) {
1666 index = i;
1667 }
1668 }
1669 if (index != -1) {
1670 myProgramComboBox->setCurrentItem(index, TRUE);
1671 }
1672 return 1;
1673}
1674
1675
1676long
1678 // obtain junction and old definitions
1679 GNEJunction* junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1680 NBTrafficLightDefinition* oldDef = myTLSEditorParent->myTLSDefinition->getCurrentTLSDefinition();
1681 // get a list of all affected nodes
1682 std::vector<GNEJunction*> TLSJunctions;
1683 for (const auto& TLSNode : oldDef->getNodes()) {
1684 TLSJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLSNode->getID()));
1685 }
1686 // discard all previous changes
1687 discardChanges(false);
1688 // begin undo
1689 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("reset TLS"));
1690 // set junction as priority (this will also remove all program, see GNEJunction::setJunctionType)
1691 for (const auto& TLSJunction : TLSJunctions) {
1692 TLSJunction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::PRIORITY), myTLSEditorParent->getViewNet()->getUndoList());
1693 }
1694 // create TLS in junction
1695 createTLS(junction);
1696 // set TLS in all other junctions
1697 for (const auto& TLSJunction : TLSJunctions) {
1698 if (TLSJunction != junction) {
1699 TLSJunction->setAttribute(SUMO_ATTR_TYPE, TLSJunction->getAttribute(SUMO_ATTR_TYPE), myTLSEditorParent->getViewNet()->getUndoList());
1700 TLSJunction->setAttribute(SUMO_ATTR_TLID, TLSJunction->getAttribute(SUMO_ATTR_TLID), myTLSEditorParent->getViewNet()->getUndoList());
1701 }
1702 }
1703 // end undo
1704 myTLSEditorParent->getViewNet()->getUndoList()->end();
1705 // edit junction
1706 myTLSEditorParent->editJunction(junction);
1707 return 1;
1708}
1709
1710
1711long
1713 // just switch program
1714 switchProgram();
1715 return 1;
1716}
1717
1718
1719long
1721 if (getNumberOfTLSDefinitions() == 0) {
1722 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1723 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1724 // selecting E1, disable button
1725 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1726 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1727 // joining TLSs, disable button
1728 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1729 } else if (myHaveModifications) {
1730 // modifications, enable button
1731 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
1732 } else {
1733 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1734 }
1735}
1736
1737
1738long
1740 if (getNumberOfTLSDefinitions() == 0) {
1741 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1742 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1743 // selecting E1, disable button
1744 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1745 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1746 // joining TLSs, disable button
1747 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1748 } else if (myHaveModifications) {
1749 // modifications, disable button
1750 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1751 } else {
1752 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
1753 }
1754}
1755
1756
1757long
1759 if (getNumberOfTLSDefinitions() <= 1) {
1760 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1761 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1762 // selecting E1, disable button
1763 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1764 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1765 // joining TLSs, disable button
1766 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1767 } else if (myHaveModifications) {
1768 // modifications, disable button
1769 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
1770 } else {
1771 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
1772 }
1773}
1774
1775
1776long
1778 // get junction copy
1779 const auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1780 // get current program
1781 const auto currentProgram = myProgramComboBox->getCurrentItem();
1782 // check that junction is valid
1783 if (currentJunction != nullptr) {
1784 const auto oldDefinition = getCurrentTLSDefinition();
1785 std::vector<NBNode*> nodes = oldDefinition->getNodes();
1786 for (const auto& node : nodes) {
1787 GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(node->getID());
1788 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, oldDefinition, false), true);
1789 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, true), true);
1790 }
1791 // end change
1792 myTLSEditorParent->getViewNet()->getUndoList()->end();
1793 // mark as saved
1794 myHaveModifications = false;
1795 // reset myEditedDef (because is already in eine undo-list)
1796 myTLSEditorParent->myEditedDef = nullptr;
1797 myTLSEditorParent->cleanup();
1798 myTLSEditorParent->getViewNet()->updateViewNet();
1799 // edit junction again
1800 myTLSEditorParent->editJunction(currentJunction);
1801 // change program
1802 myProgramComboBox->setCurrentItem(currentProgram, TRUE);
1803 } else {
1804 // discard changes inspecting junction again
1805 discardChanges(true);
1806 }
1807 return 1;
1808}
1809
1810
1811long
1813 // discard changes inspecting junction again
1814 discardChanges(true);
1815 return 1;
1816}
1817
1818
1819void
1821 // get current TLS program id
1822 const auto currentTLS = getCurrentTLSProgramID();
1823 // check conditions
1824 if (junction == nullptr) {
1825 throw ProcessError("junction cannot be null");
1827 // set junction as TLS
1828 junction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::TRAFFIC_LIGHT), myTLSEditorParent->getViewNet()->getUndoList());
1829 } else if (junction->getNBNode()->isTLControlled()) {
1830 // use existing traffic light as template for type, signal groups, controlled nodes etc
1831 NBTrafficLightDefinition* tpl = nullptr;
1832 for (const auto& TLS : junction->getNBNode()->getControllingTLS()) {
1833 if (TLS->getProgramID() == currentTLS) {
1834 tpl = TLS;
1835 }
1836 }
1837 // if template is empty, use first TLS
1838 if (tpl == nullptr) {
1839 tpl = *junction->getNBNode()->getControllingTLS().begin();
1840 }
1841 // create new logic
1843 // create new TLDef
1844 NBLoadedSUMOTLDef* newDef = new NBLoadedSUMOTLDef(*tpl, *newLogic);
1845 NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1846 newDef->setProgramID(tllCont.getNextProgramID(newDef->getID()));
1847 // remove new logic
1848 delete newLogic;
1849 // add it using GNEChange_TLS
1850 myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TLF("duplicate program '%' of traffic light '%'", tpl->getProgramID(), tpl->getID()));
1851 for (NBNode* node : newDef->getNodes()) {
1852 GNEJunction* j = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(node->getID());
1853 // not forcing insertion because we already ensured a new id and multiple junctions will attempt insertion
1854 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(j, newDef, true, false), true);
1855 }
1856 myTLSEditorParent->getViewNet()->getUndoList()->end();
1857 } else {
1858 // for some reason the traffic light was not built, try again
1859 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, nullptr, true, true), true);
1860 }
1861}
1862
1863
1864bool
1866 if (myTLSEditorParent->myTLSJunction->getCurrentJunction() == nullptr) {
1867 throw ProcessError("Junction cannot be NULL");
1868 } else if (getNumberOfTLSDefinitions() != getNumberOfPrograms()) {
1869 throw ProcessError("myProgramComboBox must have the same number of TLSDefinitions");
1870 } else {
1871 // reset save flag
1872 myHaveModifications = false;
1873 // get current definition
1874 NBTrafficLightDefinition* tlDef = getCurrentTLSDefinition();
1875 // logic may not have been recomputed yet. recompute to be sure
1876 NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1877 // compute junction
1878 myTLSEditorParent->getViewNet()->getNet()->computeJunction(myTLSEditorParent->myTLSJunction->getCurrentJunction());
1879 // obtain TrafficLight logic vinculated with tlDef
1880 NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
1881 // check that tllLogic exist
1882 if (tllogic != nullptr) {
1883 // now we can be sure that the tlDef is up to date (i.e. re-guessed)
1884 myTLSEditorParent->buildInternalLanes(tlDef);
1885 // create working duplicate from original def
1886 delete myTLSEditorParent->myEditedDef;
1887 myTLSEditorParent->myEditedDef = new NBLoadedSUMOTLDef(*tlDef, *tllogic);
1888 // set values
1889 myTLSEditorParent->myTLSAttributes->setOffset(myTLSEditorParent->myEditedDef->getLogic()->getOffset());
1890 myTLSEditorParent->myTLSAttributes->setParameters(myTLSEditorParent->myEditedDef->getLogic()->getParametersStr());
1891 // init phaseTable with the new TLS
1892 myTLSEditorParent->myTLSPhases->initPhaseTable();
1893 } else {
1894 // tlDef has no valid logic (probably because id does not control any links
1895 discardChanges(false);
1896 myTLSEditorParent->getViewNet()->setStatusBarText(TL("Traffic light does not control any links"));
1897 return false;
1898 }
1899 }
1900 return true;
1901}
1902
1903// ---------------------------------------------------------------------------
1904// GNETLSEditorFrame::TLSPhases - methods
1905// ---------------------------------------------------------------------------
1906
1908 MFXGroupBoxModule(TLSEditorParent, TL("Phases"), MFXGroupBoxModule::Options::COLLAPSIBLE | MFXGroupBoxModule::Options::EXTENSIBLE),
1909 myTLSEditorParent(TLSEditorParent) {
1910 // create GNETLSTable
1911 myPhaseTable = new GNETLSTable(this);
1912 // hide phase table
1913 myPhaseTable->hide();
1914 FXHorizontalFrame* phaseButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
1915 FXVerticalFrame* col1 = new FXVerticalFrame(phaseButtons, GUIDesignAuxiliarHorizontalFrame); // left button columm
1916 FXVerticalFrame* col2 = new FXVerticalFrame(phaseButtons, GUIDesignAuxiliarHorizontalFrame); // right button column
1917 // create cleanup states button
1919 TL("Clean States") + std::string("\t") +
1920 TL("Clean unused states from all phase") + std::string("\t") +
1921 TL("Clean unused states from all phase. (Not allowed for multiple programs)"),
1923 // add unused states button
1925 TL("Add States") + std::string("\t") +
1926 TL("Extend the state vector for all phases by one entry") + std::string("\t") +
1927 TL("Extend the state vector for all phases by one entry. (Unused until a connection or crossing is assigned to the new index)"),
1929 // group states button
1931 TL("Group Sig.") + std::string("\t") +
1932 TL("Shorten state definition by letting connections with the same signal states use the same index") + std::string("\t") +
1933 TL("Shorten state definition by letting connections with the same signal states use the same index. (Not allowed for multiple programs)"),
1935 // ungroup states button
1937 TL("Ungroup Sig.") + std::string("\t") +
1938 TL("Let every connection use a distinct index (reverse state grouping)") + std::string("\t") +
1939 TL("Let every connection use a distinct index (reverse state grouping). (Not allowed for multiple programs)"),
1941 // show TLSFile
1942 show();
1943}
1944
1945
1948
1949
1950void
1954
1955
1956void
1960
1961
1964 return myTLSEditorParent;
1965}
1966
1967
1970 return myPhaseTable;
1971}
1972
1973
1974void
1976 // first clear table
1977 myPhaseTable->clearTable();
1978 if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() > 0) {
1979 if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC) {
1980 initStaticPhaseTable();
1981 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::ACTUATED) {
1982 initActuatedPhaseTable();
1983 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::DELAYBASED) {
1984 initDelayBasePhaseTable();
1985 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA) {
1986 initNEMAPhaseTable();
1987 }
1988 // select first element (by default)
1989 myPhaseTable->selectRow(0);
1990 // recalc width and show
1991 myPhaseTable->recalcTableWidth();
1992 myPhaseTable->show();
1993 } else {
1994 myPhaseTable->hide();
1995 }
1996 update();
1997}
1998
1999
2000bool
2001GNETLSEditorFrame::TLSPhases::changePhaseValue(const int col, const int row, const std::string& value) {
2002 // Declare columns
2003 int colDuration = 1;
2004 int colState = -1;
2005 int colNext = -1;
2006 int colName = -1;
2007 int colMinDur = -1;
2008 int colMaxDur = -1;
2009 int colEarliestEnd = -1;
2010 int colLatestEnd = -1;
2011 int colVehExt = -1;
2012 int colYellow = -1;
2013 int colRed = -1;
2014 // set columns depending of traffic light type
2015 if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC) {
2016 colState = 2;
2017 colNext = 3;
2018 colName = 4;
2019 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::ACTUATED) {
2020 colMinDur = 2;
2021 colMaxDur = 3;
2022 colState = 4;
2023 colEarliestEnd = 5;
2024 colLatestEnd = 6;
2025 colNext = 7;
2026 colName = 8;
2027 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::DELAYBASED) {
2028 colMinDur = 2;
2029 colMaxDur = 3;
2030 colState = 4;
2031 colNext = 5;
2032 colName = 6;
2033 } else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA) {
2034 colMinDur = 2;
2035 colMaxDur = 3;
2036 colState = 4;
2037 colVehExt = 5;
2038 colYellow = 6;
2039 colRed = 7;
2040 colNext = 8;
2041 colName = 9;
2042 }
2043 // check column
2044 if (col == colDuration) {
2045 return setDuration(col, row, value);
2046 } else if (col == colState) {
2047 return setState(col, row, value);
2048 } else if (col == colNext) {
2049 return setNext(row, value);
2050 } else if (col == colName) {
2051 return setName(row, value);
2052 } else if (col == colMinDur) {
2053 return setMinDur(row, value);
2054 } else if (col == colMaxDur) {
2055 return setMaxDur(row, value);
2056 } else if (col == colEarliestEnd) {
2057 return setEarliestEnd(row, value);
2058 } else if (col == colLatestEnd) {
2059 return setLatestEnd(row, value);
2060 } else if (col == colVehExt) {
2061 return setVehExt(row, value);
2062 } else if (col == colYellow) {
2063 return setYellow(row, value);
2064 } else if (col == colRed) {
2065 return setRed(row, value);
2066 } else {
2067 throw ProcessError(TL("invalid column"));
2068 }
2069}
2070
2071
2072void
2073GNETLSEditorFrame::TLSPhases::addPhase(const int row, const char c) {
2074 // mark TLS as modified
2075 myTLSEditorParent->myTLSDefinition->markAsModified();
2076 // build default phase
2077 const int newIndex = buildDefaultPhase(row);
2078 // check if override state
2079 switch (c) {
2080 case 'r':
2081 case 'y':
2082 case 'g':
2083 case 'G':
2084 myTLSEditorParent->myEditedDef->getLogic()->overrideState(newIndex, c);
2085 break;
2086 default:
2087 break;
2088 }
2089 // Write debug
2090 if (c == ' ') {
2091 WRITE_DEBUG("Add default phase in row " + toString(row));
2092 } else {
2093 WRITE_DEBUG("Add new phase in row " + toString(row) + " of type: " + c);
2094 }
2095 // int phase table again
2096 initPhaseTable();
2097 // mark new row as selected
2098 myPhaseTable->selectRow(newIndex);
2099 // set focus in table
2100 getPhaseTable()->setFocus();
2101}
2102
2103
2104void
2106 // mark TLS as modified
2107 myTLSEditorParent->myTLSDefinition->markAsModified();
2108 // build default phase
2109 const int newIndex = buildDefaultPhase(row);
2110 // coply old phase in the new phase
2111 myTLSEditorParent->myEditedDef->getLogic()->copyPhase(row, row + 1);
2112 // Write debug
2113 WRITE_DEBUG("Duplicated phase " + toString(row));
2114 // int phase table again
2115 initPhaseTable();
2116 // mark new row as selected
2117 myPhaseTable->selectRow(newIndex);
2118 // set focus in table
2119 getPhaseTable()->setFocus();
2120}
2121
2122
2123void
2125 // mark TLS ad modified
2126 myTLSEditorParent->myTLSDefinition->markAsModified();
2127 // calculate new row
2128 const auto newRow = MAX2(0, (row - 1));
2129 // delete selected row
2130 myTLSEditorParent->myEditedDef->getLogic()->deletePhase(row);
2131 // Write debug
2132 WRITE_DEBUG("removed phase " + toString(row));
2133 // int phase table again
2134 initPhaseTable();
2135 // mark new row as selected
2136 myPhaseTable->selectRow(newRow);
2137 // set focus in table
2138 getPhaseTable()->setFocus();
2139}
2140
2141
2142void
2144 // mark TLS ad modified
2145 myTLSEditorParent->myTLSDefinition->markAsModified();
2146 // Write debug
2147 WRITE_DEBUG("Move up phase " + toString(row));
2148 // delete selected row
2149 if (row == 0) {
2150 myTLSEditorParent->myEditedDef->getLogic()->swapfirstPhase();
2151 } else {
2152 myTLSEditorParent->myEditedDef->getLogic()->swapPhase(row, row - 1);
2153 }
2154 // int phase table again
2155 initPhaseTable();
2156 // mark new row as selected
2157 if (row == 0) {
2158 myPhaseTable->selectRow((int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1);
2159 } else {
2160 myPhaseTable->selectRow(row - 1);
2161 }
2162 // set focus in table
2163 getPhaseTable()->setFocus();
2164}
2165
2166
2167void
2169 // mark TLS ad modified
2170 myTLSEditorParent->myTLSDefinition->markAsModified();
2171 // Write debug
2172 WRITE_DEBUG("Move down phase " + toString(row));
2173 // delete selected row
2174 if (row == (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1) {
2175 myTLSEditorParent->myEditedDef->getLogic()->swaplastPhase();
2176 } else {
2177 myTLSEditorParent->myEditedDef->getLogic()->swapPhase(row, row + 1);
2178 }
2179 // int phase table again
2180 initPhaseTable();
2181 // mark new row as selected
2182 if (row == (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1) {
2183 myPhaseTable->selectRow(0);
2184 } else {
2185 myPhaseTable->selectRow(row + 1);
2186 }
2187 // set focus in table
2188 getPhaseTable()->setFocus();
2189}
2190
2191
2192void
2194 // get phase
2195 const auto& phase = myTLSEditorParent->getPhase(myPhaseTable->getCurrentSelectedRow());
2196 // need not hold since links could have been deleted somewhere else and indices may be reused
2197 for (const auto& internalLane : myTLSEditorParent->myInternalLanes) {
2198 int tlIndex = internalLane.first;
2199 std::vector<GNEInternalLane*> lanes = internalLane.second;
2201 if (tlIndex >= 0 && tlIndex < (int)phase.state.size()) {
2202 state = (LinkState)phase.state[tlIndex];
2203 }
2204 for (const auto& lane : lanes) {
2205 lane->setLinkState(state);
2206 }
2207 }
2208 // update view net (for coloring)
2209 myTLSEditorParent->getViewNet()->updateViewNet();
2210}
2211
2212
2213long
2214GNETLSEditorFrame::TLSPhases::onUpdNeedsDef(FXObject* sender, FXSelector, void*) {
2215 if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
2216 // selecting E1, disable buttons
2217 sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2218 // also disable table
2219 myPhaseTable->disable();
2220 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
2221 // joining TLSs, disable button
2222 sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2223 // also disable table
2224 myPhaseTable->disable();
2225 } else if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() > 0) {
2226 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), nullptr);
2227 // also enable table
2228 myPhaseTable->enable();
2229 } else {
2230 sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2231 // also disable table
2232 myPhaseTable->disable();
2233 }
2234 return 1;
2235}
2236
2237
2238long
2239GNETLSEditorFrame::TLSPhases::onUpdNeedsDefAndPhase(FXObject* sender, FXSelector, void*) {
2240 if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
2241 // selecting E1, disable buttons
2242 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2243 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
2244 // joining TLSs, disable button
2245 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2246 } else if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() == 0) {
2247 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2248 } else if (myPhaseTable->getNumRows() <= 1) {
2249 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2250 } else {
2251 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), nullptr);
2252 }
2253}
2254
2255
2256long
2258 if (myTLSEditorParent->myEditedDef->cleanupStates()) {
2259 myTLSEditorParent->myTLSDefinition->markAsModified();
2260 }
2261 myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2262 initPhaseTable();
2263 myPhaseTable->setFocus();
2264 myTLSEditorParent->myTLSDefinition->markAsModified();
2265 WRITE_DEBUG("Clean states");
2266 return 1;
2267}
2268
2269
2270long
2272 myTLSEditorParent->myEditedDef->getLogic()->setStateLength(myTLSEditorParent->myEditedDef->getLogic()->getNumLinks() + 1);
2273 myTLSEditorParent->myTLSDefinition->markAsModified();
2274 initPhaseTable();
2275 myPhaseTable->setFocus();
2276 WRITE_DEBUG("Add unused states");
2277 return 1;
2278}
2279
2280
2281long
2283 myTLSEditorParent->myEditedDef->groupSignals();
2284 myTLSEditorParent->myTLSDefinition->markAsModified();
2285 myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2286 initPhaseTable();
2287 myPhaseTable->setFocus();
2288 WRITE_DEBUG("Group states");
2289 return 1;
2290}
2291
2292
2293long
2295 myTLSEditorParent->myEditedDef->setParticipantsInformation();
2296 myTLSEditorParent->myEditedDef->ungroupSignals();
2297 myTLSEditorParent->myTLSDefinition->markAsModified();
2298 myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2299 initPhaseTable();
2300 myPhaseTable->setFocus();
2301 WRITE_DEBUG("Ungroup states");
2302 return 1;
2303}
2304
2305
2306long
2307GNETLSEditorFrame::TLSPhases::onUpdNeedsSingleDef(FXObject* sender, FXSelector, void*) {
2308 if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
2309 // selecting E1, disable buttons
2310 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2311 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
2312 // joining TLSs, disable button
2313 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2314 } else if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() == 1) {
2315 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), nullptr);
2316 } else {
2317 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2318 }
2319}
2320
2321
2322long
2323GNETLSEditorFrame::TLSPhases::onUpdUngroupStates(FXObject* sender, FXSelector, void*) {
2324 if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
2325 // selecting E1, disable buttons
2326 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2327 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
2328 // joining TLSs, disable button
2329 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2330 } else if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() != 1) {
2331 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2332 } else if (myTLSEditorParent->myEditedDef == nullptr) {
2333 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2334 } else if (myTLSEditorParent->myEditedDef->usingSignalGroups()) {
2335 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
2336 } else {
2337 return sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), nullptr);
2338 }
2339}
2340
2341
2342void
2344 // declare constants for columns
2345 const int colDuration = 1;
2346 const int colState = 2;
2347 const int colNext = 3;
2348 const int colName = 4;
2349 // get phases
2350 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2351 // adjust table
2352 myPhaseTable->setTableSize("sup-midtb", (int)phases.size());
2353 // fill rows
2354 for (int row = 0; row < (int)phases.size(); row++) {
2355 myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2356 myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2357 myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2358 myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2359 }
2360 // set columns
2361 myPhaseTable->setColumnLabelTop(colDuration, "dur");
2362 myPhaseTable->setColumnLabelTop(colState, "state");
2363 myPhaseTable->setColumnLabelTop(colNext, "next");
2364 myPhaseTable->setColumnLabelTop(colName, "name");
2365 // set bot labels
2366 updateCycleDuration(colDuration);
2367 updateStateSize(colState);
2368 // set focus
2369 myPhaseTable->setFocus();
2370}
2371
2372
2373void
2375 // declare constants for columns
2376 const int colDuration = 1;
2377 const int colMinDur = 2;
2378 const int colMaxDur = 3;
2379 const int colState = 4;
2380 const int colEarliestEnd = 5;
2381 const int colLatestEnd = 6;
2382 const int colNext = 7;
2383 const int colName = 8;
2384 // get phases
2385 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2386 // adjust table
2387 myPhaseTable->setTableSize("suffpff-midtb", (int)phases.size());
2388 // fill rows
2389 for (int row = 0; row < (int)phases.size(); row++) {
2390 myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2391 myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2392 myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2393 myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2394 myPhaseTable->setItemText(row, colEarliestEnd, varDurString(phases.at(row).earliestEnd).c_str());
2395 myPhaseTable->setItemText(row, colLatestEnd, varDurString(phases.at(row).latestEnd).c_str());
2396 myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2397 myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2398 }
2399 // set columns
2400 myPhaseTable->setColumnLabelTop(colDuration, "dur");
2401 myPhaseTable->setColumnLabelTop(colMinDur, "min");
2402 myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2403 myPhaseTable->setColumnLabelTop(colEarliestEnd, "ear.end", "earlyEnd");
2404 myPhaseTable->setColumnLabelTop(colLatestEnd, "lat.end", "latestEnd");
2405 myPhaseTable->setColumnLabelTop(colState, "state");
2406 myPhaseTable->setColumnLabelTop(colNext, "next");
2407 myPhaseTable->setColumnLabelTop(colName, "name");
2408 // set bot labels
2409 updateCycleDuration(colDuration);
2410 updateStateSize(colState);
2411 // set focus
2412 myPhaseTable->setFocus();
2413}
2414
2415
2416void
2418 // declare constants for columns
2419 const int colDuration = 1;
2420 const int colMinDur = 2;
2421 const int colMaxDur = 3;
2422 const int colState = 4;
2423 const int colNext = 5;
2424 const int colName = 6;
2425 // get phases
2426 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2427 // adjust table
2428 myPhaseTable->setTableSize("suffp-midtb", (int)phases.size());
2429 // fill rows
2430 for (int row = 0; row < (int)phases.size(); row++) {
2431 myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2432 myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2433 myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2434 myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2435 myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2436 myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2437 }
2438 // set columns
2439 myPhaseTable->setColumnLabelTop(colDuration, "dur");
2440 myPhaseTable->setColumnLabelTop(colMinDur, "min");
2441 myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2442 myPhaseTable->setColumnLabelTop(colState, "state");
2443 myPhaseTable->setColumnLabelTop(colNext, "next");
2444 myPhaseTable->setColumnLabelTop(colName, "name");
2445 // set bot labels
2446 updateCycleDuration(colDuration);
2447 updateStateSize(colState);
2448 // set focus
2449 myPhaseTable->setFocus();
2450}
2451
2452
2453void
2455 // declare constants for columns
2456 const int colDuration = 1;
2457 const int colMinDur = 2;
2458 const int colMaxDur = 3;
2459 const int colState = 4;
2460 const int colVehExt = 5;
2461 const int colYellow = 6;
2462 const int colRed = 7;
2463 const int colNext = 8;
2464 const int colName = 9;
2465 // get phases
2466 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2467 // adjust table
2468 myPhaseTable->setTableSize("suffpfff-midtb", (int)phases.size());
2469 // fill rows
2470 for (int row = 0; row < (int)phases.size(); row++) {
2471 myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2472 myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2473 myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2474 myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2475 myPhaseTable->setItemText(row, colVehExt, varDurString(phases.at(row).vehExt).c_str());
2476 myPhaseTable->setItemText(row, colYellow, varDurString(phases.at(row).yellow).c_str());
2477 myPhaseTable->setItemText(row, colRed, varDurString(phases.at(row).red).c_str());
2478 myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2479 myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2480 }
2481 // set columns
2482 myPhaseTable->setColumnLabelTop(colDuration, "dur");
2483 myPhaseTable->setColumnLabelTop(colMinDur, "min");
2484 myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2485 myPhaseTable->setColumnLabelTop(colState, "state");
2486 myPhaseTable->setColumnLabelTop(colVehExt, "vehExt", "vehicle extension");
2487 myPhaseTable->setColumnLabelTop(colYellow, "yellow");
2488 myPhaseTable->setColumnLabelTop(colRed, "red");
2489 myPhaseTable->setColumnLabelTop(colNext, "next");
2490 myPhaseTable->setColumnLabelTop(colName, "name");
2491 // set bot labels
2492 updateCycleDuration(colDuration);
2493 updateStateSize(colState);
2494 // set focus
2495 myPhaseTable->setFocus();
2496}
2497
2498
2499int
2501 // get option container
2502 const auto& neteditOptions = OptionsCont::getOptions();
2503 // check if TLS is static
2504 const bool TLSStatic = (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC);
2505 const bool NEMA = (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA);
2506 // calculate new index
2507 const int newIndex = row + 1;
2508 // duplicate current row
2509 auto duration = getSUMOTime(myPhaseTable->getItemText(row, 1));
2510 const auto oldState = myPhaseTable->getItemText(row, TLSStatic ? 2 : 4);
2511 auto state = oldState;
2512 // update crossingINdices
2513 std::set<int> crossingIndices;
2514 for (const auto& node : myTLSEditorParent->myEditedDef->getNodes()) {
2515 for (const auto& crossing : node->getCrossings()) {
2516 crossingIndices.insert(crossing->tlLinkIndex);
2517 crossingIndices.insert(crossing->tlLinkIndex2);
2518 }
2519 }
2520 // smart adapations for new state
2521 bool haveGreen = false;
2522 bool haveYellow = false;
2523 for (const auto& linkStateChar : state) {
2524 if ((linkStateChar == LINKSTATE_TL_GREEN_MAJOR) || (linkStateChar == LINKSTATE_TL_GREEN_MINOR)) {
2525 haveGreen = true;
2526 } else if ((linkStateChar == LINKSTATE_TL_YELLOW_MAJOR) || (linkStateChar == LINKSTATE_TL_YELLOW_MINOR)) {
2527 haveYellow = true;
2528 }
2529 }
2530 if (haveGreen && haveYellow) {
2531 // guess left-mover state
2532 duration = TIME2STEPS(neteditOptions.getInt("tls.left-green.time"));
2533 for (int i = 0; i < (int)state.size(); i++) {
2534 if ((state[i] == LINKSTATE_TL_YELLOW_MAJOR) || (state[i] == LINKSTATE_TL_YELLOW_MINOR)) {
2535 state[i] = LINKSTATE_TL_RED;
2536 } else if (state[i] == LINKSTATE_TL_GREEN_MINOR) {
2537 state[i] = LINKSTATE_TL_GREEN_MAJOR;
2538 }
2539 }
2540 } else if (haveGreen) {
2541 // guess yellow state
2542 myTLSEditorParent->myEditedDef->setParticipantsInformation();
2543 duration = TIME2STEPS(myTLSEditorParent->myEditedDef->computeBrakingTime(neteditOptions.getFloat("tls.yellow.min-decel")));
2544 for (int i = 0; i < (int)state.size(); i++) {
2545 if ((state[i] == LINKSTATE_TL_GREEN_MAJOR) || (state[i] == LINKSTATE_TL_GREEN_MINOR)) {
2546 if (crossingIndices.count(i) == 0) {
2547 state[i] = LINKSTATE_TL_YELLOW_MINOR;
2548 } else {
2549 state[i] = LINKSTATE_TL_RED;
2550 }
2551 }
2552 }
2553 } else if (haveYellow) {
2554 duration = TIME2STEPS(neteditOptions.isDefault("tls.allred.time") ? 2 : neteditOptions.getInt("tls.allred.time"));
2555 // guess all-red state
2556 for (int i = 0; i < (int)state.size(); i++) {
2557 if ((state[i] == LINKSTATE_TL_YELLOW_MAJOR) || (state[i] == LINKSTATE_TL_YELLOW_MINOR)) {
2558 state[i] = LINKSTATE_TL_RED;
2559 }
2560 }
2561 }
2562 // fix continuous green states
2563 const int nextIndex = (myPhaseTable->getNumRows() > newIndex) ? newIndex : 0;
2564 const std::string state2 = myPhaseTable->getItemText(nextIndex, (TLSStatic ? 2 : 4));
2565 for (int i = 0; i < (int)state.size(); i++) {
2566 if (((oldState[i] == LINKSTATE_TL_GREEN_MAJOR) || (oldState[i] == LINKSTATE_TL_GREEN_MINOR)) &&
2567 ((state2[i] == LINKSTATE_TL_GREEN_MAJOR) || (state2[i] == LINKSTATE_TL_GREEN_MINOR))) {
2568 state[i] = oldState[i];
2569 }
2570 }
2571 // add new step
2572 if (NEMA) {
2573 myTLSEditorParent->myEditedDef->getLogic()->addStep(string2time("90"), state, string2time("5"), string2time("50"),
2575 string2time("2"), string2time("3"), string2time("2"), "1", std::vector<int>(), newIndex);
2576 } else {
2577 myTLSEditorParent->myEditedDef->getLogic()->addStep(duration, state, std::vector<int>(), "", newIndex);
2578 }
2579 // return new index
2580 return newIndex;
2581}
2582
2583
2584bool
2585GNETLSEditorFrame::TLSPhases::setDuration(const int col, const int row, const std::string& value) {
2586 // check value
2587 if (value.empty()) {
2588 // input empty, reset
2589 getPhaseTable()->setItemText(row, col, getSteps2Time(myTLSEditorParent->getPhase(row).duration).c_str());
2590 return true;
2591 } else if (GNEAttributeCarrier::canParse<double>(value)) {
2592 const auto duration = getSUMOTime(value);
2593 // check that duration > 0
2594 if (duration > 0) {
2595 myTLSEditorParent->myEditedDef->getLogic()->setPhaseDuration(row, duration);
2596 myTLSEditorParent->myTLSDefinition->markAsModified();
2597 // update Cycle duration
2598 updateCycleDuration(col);
2599 return true;
2600 } else {
2601 return false;
2602 }
2603 } else {
2604 return false;
2605 }
2606}
2607
2608
2609bool
2610GNETLSEditorFrame::TLSPhases::setState(const int col, const int row, const std::string& value) {
2611 // get state
2612 const auto& phase = myTLSEditorParent->getPhase(row);
2613 // declare new state. If value is empty, use previous value (reset)
2614 const auto newState = value.empty() ? phase.state : value;
2615 // insert phase
2616 try {
2617 myTLSEditorParent->myEditedDef->getLogic()->addStep(phase.duration, newState, phase.next, phase.name, row);
2618 } catch (ProcessError&) {
2619 // invalid character in newState
2620 return false;
2621 }
2622 // delete next phase
2623 try {
2624 myTLSEditorParent->myEditedDef->getLogic()->deletePhase(row + 1);
2625 } catch (InvalidArgument&) {
2626 WRITE_ERROR(TL("Error deleting phase '") + toString(row + 1) + "'");
2627 return false;
2628 }
2629 // mark TLS as modified depending of value
2630 if (value.size() > 0) {
2631 myTLSEditorParent->myTLSDefinition->markAsModified();
2632 // select row
2633 myPhaseTable->selectRow(row);
2634 } else {
2635 // input empty, reset
2636 getPhaseTable()->setItemText(row, col, newState);
2637 }
2638 // update state size
2639 updateStateSize(col);
2640 return true;
2641}
2642
2643
2644bool
2645GNETLSEditorFrame::TLSPhases::setNext(const int row, const std::string &value) {
2646 // check next
2647 if (GNEAttributeCarrier::canParse<std::vector<int> >(value)) {
2648 const auto nextEdited = GNEAttributeCarrier::parse<std::vector<int> >(value);
2649 for (const auto nextPhase : nextEdited) {
2650 if ((nextPhase < 0) || (nextPhase >= myPhaseTable->getNumRows())) {
2651 return false;
2652 }
2653 }
2654 // set new next
2655 myTLSEditorParent->myEditedDef->getLogic()->setPhaseNext(row, nextEdited);
2656 myTLSEditorParent->myTLSDefinition->markAsModified();
2657 return true;
2658 } else {
2659 return false;
2660 }
2661}
2662
2663
2664bool
2665GNETLSEditorFrame::TLSPhases::setName(const int row, const std::string& value) {
2666 // update name (currently no check needed)
2667 myTLSEditorParent->myEditedDef->getLogic()->setPhaseName(row, value);
2668 myTLSEditorParent->myTLSDefinition->markAsModified();
2669 return true;
2670}
2671
2672
2673bool
2674GNETLSEditorFrame::TLSPhases::setMinDur(const int row, const std::string& value) {
2675 // check value
2676 if (value.empty()) {
2677 // set empty value
2678 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2679 myTLSEditorParent->myTLSDefinition->markAsModified();
2680 return true;
2681 } else if (GNEAttributeCarrier::canParse<double>(value)) {
2682 const auto minDur = getSUMOTime(value);
2683 // check that minDur > 0
2684 if (minDur > 0) {
2685 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, minDur);
2686 myTLSEditorParent->myTLSDefinition->markAsModified();
2687 return true;
2688 } else {
2689 return false;
2690 }
2691 } else if (StringUtils::prune(value).empty()) {
2692 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2693 myTLSEditorParent->myTLSDefinition->markAsModified();
2694 return true;
2695 } else {
2696 return false;
2697 }
2698}
2699
2700
2701bool
2702GNETLSEditorFrame::TLSPhases::setMaxDur(const int row, const std::string& value) {
2703 // check value
2704 if (value.empty()) {
2705 // set empty value
2706 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2707 myTLSEditorParent->myTLSDefinition->markAsModified();
2708 return true;
2709 } else if (GNEAttributeCarrier::canParse<double>(value)) {
2710 const auto maxDur = getSUMOTime(value);
2711 // check that minDur > 0
2712 if (maxDur > 0) {
2713 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, maxDur);
2714 myTLSEditorParent->myTLSDefinition->markAsModified();
2715 return true;
2716 } else {
2717 return false;
2718 }
2719 } else if (StringUtils::prune(value).empty()) {
2720 myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2721 myTLSEditorParent->myTLSDefinition->markAsModified();
2722 return true;
2723 } else {
2724 return false;
2725 }
2726}
2727
2728
2729bool
2730GNETLSEditorFrame::TLSPhases::setEarliestEnd(const int row, const std::string& value) {
2731 // check value
2732 if (value.empty()) {
2733 // set empty value
2734 myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2735 myTLSEditorParent->myTLSDefinition->markAsModified();
2736 return true;
2737 } else if (GNEAttributeCarrier::canParse<double>(value)) {
2738 const auto earliestEnd = getSUMOTime(value);
2739 // check that earliestEnd > 0
2740 if (earliestEnd > 0) {
2741 myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, earliestEnd);
2742 myTLSEditorParent->myTLSDefinition->markAsModified();
2743 return true;
2744 } else {
2745 return false;
2746 }
2747 } else if (StringUtils::prune(value).empty()) {
2748 myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2749 myTLSEditorParent->myTLSDefinition->markAsModified();
2750 return true;
2751 } else {
2752 return false;
2753 }
2754}
2755
2756
2757bool
2758GNETLSEditorFrame::TLSPhases::setLatestEnd(const int row, const std::string& value) {
2759 // check value
2760 if (value.empty()) {
2761 // set empty value
2762 myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2763 myTLSEditorParent->myTLSDefinition->markAsModified();
2764 return true;
2765 } else if (GNEAttributeCarrier::canParse<double>(value)) {
2766 const auto latestEnd = getSUMOTime(value);
2767 // check that latestEnd > 0
2768 if (latestEnd > 0) {
2769 myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, latestEnd);
2770 myTLSEditorParent->myTLSDefinition->markAsModified();
2771 return true;
2772 } else {
2773 return false;
2774 }
2775 } else if (StringUtils::prune(value).empty()) {
2776 myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2777 myTLSEditorParent->myTLSDefinition->markAsModified();
2778 return true;
2779 } else {
2780 return false;
2781 }
2782}
2783
2784
2785bool
2786GNETLSEditorFrame::TLSPhases::setVehExt(const int row, const std::string& value) {
2787 // check value
2788 if (value.empty()) {
2789 // set empty value
2790 myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2791 myTLSEditorParent->myTLSDefinition->markAsModified();
2792 return true;
2793 } else if (GNEAttributeCarrier::canParse<double>(value)) {
2794 const auto vehExt = getSUMOTime(value);
2795 // check that vehExt > 0
2796 if (vehExt > 0) {
2797 myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, vehExt);
2798 myTLSEditorParent->myTLSDefinition->markAsModified();
2799 return true;
2800 } else {
2801 return false;
2802 }
2803 } else if (StringUtils::prune(value).empty()) {
2804 myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2805 myTLSEditorParent->myTLSDefinition->markAsModified();
2806 return true;
2807 } else {
2808 return false;
2809 }
2810}
2811
2812
2813bool
2814GNETLSEditorFrame::TLSPhases::setYellow(const int row, const std::string& value) {
2815 // check value
2816 if (value.empty()) {
2817 // set empty value
2818 myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2819 myTLSEditorParent->myTLSDefinition->markAsModified();
2820 return true;
2821 } else if (GNEAttributeCarrier::canParse<double>(value)) {
2822 const auto yellow = getSUMOTime(value);
2823 // check that yellow > 0
2824 if (yellow > 0) {
2825 myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, yellow);
2826 myTLSEditorParent->myTLSDefinition->markAsModified();
2827 return true;
2828 } else {
2829 return false;
2830 }
2831 } else if (StringUtils::prune(value).empty()) {
2832 myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2833 myTLSEditorParent->myTLSDefinition->markAsModified();
2834 return true;
2835 } else {
2836 return false;
2837 }
2838}
2839
2840
2841bool
2842GNETLSEditorFrame::TLSPhases::setRed(const int row, const std::string& value) {
2843 // check value
2844 if (value.empty()) {
2845 // set empty value
2846 myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2847 myTLSEditorParent->myTLSDefinition->markAsModified();
2848 return true;
2849 } else if (GNEAttributeCarrier::canParse<double>(value)) {
2850 const auto red = getSUMOTime(value);
2851 // check that red > 0
2852 if (red > 0) {
2853 myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, red);
2854 myTLSEditorParent->myTLSDefinition->markAsModified();
2855 return true;
2856 } else {
2857 return false;
2858 }
2859 } else if (StringUtils::prune(value).empty()) {
2860 myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2861 myTLSEditorParent->myTLSDefinition->markAsModified();
2862 return true;
2863 } else {
2864 return false;
2865 }
2866}
2867
2868
2869void
2871 SUMOTime cycleDuration = 0;
2872 for (const auto& phase : myTLSEditorParent->myEditedDef->getLogic()->getPhases()) {
2873 cycleDuration += phase.duration;
2874 }
2875 // update bot label with cycle duration
2876 myPhaseTable->setColumnLabelBot(col, getSteps2Time(cycleDuration));
2877}
2878
2879
2880void
2882 // update bot label with number of links
2883 myPhaseTable->setColumnLabelBot(col, "Links: " + toString(myTLSEditorParent->myEditedDef->getLogic()->getNumLinks()));
2884}
2885
2886// ---------------------------------------------------------------------------
2887// GNETLSEditorFrame::TLSFile - methods
2888// ---------------------------------------------------------------------------
2889
2891 MFXGroupBoxModule(TLSEditorParent, TL("TLS Program File")),
2892 myTLSEditorParent(TLSEditorParent) {
2893 FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
2894 // create create tlDef button
2895 new FXButton(buttonsFrame, (TL("Load") + std::string("\t\t") + TL("Load TLS program from additional file")).c_str(), GUIIconSubSys::getIcon(GUIIcon::OPEN), this, MID_GNE_TLSFRAME_FILE_LOADPROGRAM, GUIDesignButton);
2896 // create create tlDef button
2897 new FXButton(buttonsFrame, (TL("Save") + std::string("\t\t") + TL("Save TLS program to additional file")).c_str(), GUIIconSubSys::getIcon(GUIIcon::SAVE), this, MID_GNE_TLSFRAME_FILE_SAVEPROGRAM, GUIDesignButton);
2898 // show TLSFile
2899 show();
2900}
2901
2902
2904
2905
2906void
2910
2911
2912void
2916
2917
2918long
2920 FXFileDialog opendialog(getCollapsableFrame(), "Load TLS Program");
2921 opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::MODETLS));
2922 opendialog.setSelectMode(SELECTFILE_EXISTING);
2923 opendialog.setPatternList("XML files (*.xml,*.xml.gz)\nAll files (*)");
2924 if (gCurrentFolder.length() != 0) {
2925 opendialog.setDirectory(gCurrentFolder);
2926 }
2927 if (opendialog.execute()) {
2928 // run parser
2929 NBTrafficLightLogicCont tmpTLLCont;
2930 NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myTLSEditorParent->getViewNet()->getNet()->getEdgeCont(), true);
2931 tmpTLLCont.insert(myTLSEditorParent->myEditedDef);
2932 XMLSubSys::runParser(tllHandler, opendialog.getFilename().text());
2933
2934 NBLoadedSUMOTLDef* newDefSameProgram = nullptr;
2935 std::set<NBLoadedSUMOTLDef*> newDefsOtherProgram;
2936 for (auto item : tmpTLLCont.getPrograms(myTLSEditorParent->myEditedDef->getID())) {
2937 if (item.second != myTLSEditorParent->myEditedDef) {
2938 NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(item.second);
2939 if (item.first == myTLSEditorParent->myEditedDef->getProgramID()) {
2940 newDefSameProgram = sdef;
2941 } else {
2942 newDefsOtherProgram.insert(sdef);
2943 }
2944 }
2945 }
2946 const int newPrograms = (int)newDefsOtherProgram.size();
2947 if (newPrograms > 0 || newDefSameProgram != nullptr) {
2948 std::vector<NBNode*> nodes = myTLSEditorParent->myEditedDef->getNodes();
2949 for (auto newProg : newDefsOtherProgram) {
2950 for (auto it_node : nodes) {
2951 GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
2952 myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newProg, true), true);
2953 }
2954 }
2955 if (newPrograms > 0) {
2956 WRITE_MESSAGE(TL("Loaded ") + toString(newPrograms) + TL(" new programs for tlLogic '") + myTLSEditorParent->myEditedDef->getID() + "'");
2957 }
2958 if (newDefSameProgram != nullptr) {
2959 // replace old program when loading the same program ID
2960 myTLSEditorParent->myEditedDef = newDefSameProgram;
2961 WRITE_MESSAGE(TL("Updated program '") + newDefSameProgram->getProgramID() + TL("' for tlLogic '") + myTLSEditorParent->myEditedDef->getID() + "'");
2962 }
2963 } else {
2964 if (tllHandler.getSeenIDs().count(myTLSEditorParent->myEditedDef->getID()) == 0) {
2965 myTLSEditorParent->getViewNet()->setStatusBarText(TL("No programs found for traffic light '") + myTLSEditorParent->myEditedDef->getID() + "'");
2966 }
2967 }
2968
2969 // clean up temporary container to avoid deletion of defs when it's destruct is called
2970 for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
2971 tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
2972 }
2973
2974 myTLSEditorParent->myTLSPhases->initPhaseTable();
2975 myTLSEditorParent->myTLSDefinition->markAsModified();
2976 }
2977 return 0;
2978}
2979
2980
2981long
2983 FXString file = MFXUtils::getFilename2Write(this,
2984 TL("Save TLS Program as"), ".xml",
2987 // check file
2988 if (file != "") {
2989 // add xml extension
2990 file = FileHelpers::addExtension(file.text(), ".xml").c_str();
2991 OutputDevice& device = OutputDevice::getDevice(file.text());
2992 // save program
2993 device.writeXMLHeader("additional", "additional_file.xsd");
2994 device.openTag(SUMO_TAG_TLLOGIC);
2995 device.writeAttr(SUMO_ATTR_ID, myTLSEditorParent->myEditedDef->getLogic()->getID());
2996 device.writeAttr(SUMO_ATTR_TYPE, myTLSEditorParent->myEditedDef->getLogic()->getType());
2997 device.writeAttr(SUMO_ATTR_PROGRAMID, myTLSEditorParent->myEditedDef->getLogic()->getProgramID());
2998 device.writeAttr(SUMO_ATTR_OFFSET, writeSUMOTime(myTLSEditorParent->myEditedDef->getLogic()->getOffset()));
2999 myTLSEditorParent->myEditedDef->writeParams(device);
3000 // write the phases
3001 const bool TLSActuated = (myTLSEditorParent->myEditedDef->getLogic()->getType() == TrafficLightType::ACTUATED);
3002 const bool TLSDelayBased = (myTLSEditorParent->myEditedDef->getLogic()->getType() == TrafficLightType::DELAYBASED);
3003 const bool TLSNEMA = (myTLSEditorParent->myEditedDef->getLogic()->getType() == TrafficLightType::NEMA);
3004 // write the phases
3005 const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
3006 for (const auto& phase : phases) {
3007 device.openTag(SUMO_TAG_PHASE);
3008 device.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(phase.duration));
3009 device.writeAttr(SUMO_ATTR_STATE, phase.state);
3010 // write specific actuated parameters
3011 if (TLSActuated || TLSDelayBased) {
3013 device.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
3014 }
3016 device.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
3017 }
3018 if (phase.earliestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
3019 device.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
3020 }
3021 if (phase.earliestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
3022 device.writeAttr(SUMO_ATTR_EARLIEST_END, writeSUMOTime(phase.maxDur));
3023 }
3024 if (phase.latestEnd != NBTrafficLightDefinition::UNSPECIFIED_DURATION) {
3025 device.writeAttr(SUMO_ATTR_LATEST_END, writeSUMOTime(phase.maxDur));
3026 }
3027 }
3028 // write specific NEMA parameters
3029 if (TLSNEMA) {
3031 device.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.minDur));
3032 }
3034 device.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.maxDur));
3035 }
3037 device.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(phase.vehExt));
3038 }
3040 device.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.red));
3041 }
3043 device.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(phase.yellow));
3044 }
3045 }
3046 device.closeTag();
3047 }
3048 device.close();
3049 }
3050 return 1;
3051}
3052
3053
3054std::string
3056 const double time = STEPS2TIME(steps);
3057 if (time == std::floor(time)) {
3058 return toString(int(time));
3059 } else {
3060 return toString(time);
3061 }
3062}
3063
3064
3065long
3066GNETLSEditorFrame::TLSFile::onUpdButtons(FXObject* sender, FXSelector, void*) {
3067 if (myTLSEditorParent->myTLSDefinition->getNumberOfTLSDefinitions() == 0) {
3068 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
3069 } else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
3070 // selecting E1, disable buttons
3071 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
3072 } else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
3073 // joining TLSs, disable button
3074 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
3075 } else {
3076 return sender->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), nullptr);
3077 }
3078}
3079
3080/****************************************************************************/
static const int NUM_POINTS
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:77
#define GUIDesignButton
Definition GUIDesigns.h:74
#define GUIDesignComboBoxAttribute
Combo box static (cannot be edited) extended over the matrix column.
Definition GUIDesigns.h:297
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition GUIDesigns.h:306
#define GUIDesignTextField
Definition GUIDesigns.h:51
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:394
#define GUIDesignAuxiliarHorizontalFrameUniform
design for auxiliar (Without borders) horizontal frame used to pack another frames uniform
Definition GUIDesigns.h:397
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition GUIDesigns.h:66
#define GUIDesignLabelThickedFixed(width)
label thicked, icon before text, text centered and custom width
Definition GUIDesigns.h:247
FXString gCurrentFolder
The folder used as last.
@ OPEN
open icons
@ SAVE
save icons
#define WRITE_DEBUG(msg)
Definition MsgHandler.h:281
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:271
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:272
#define WRITE_ERROR(msg)
Definition MsgHandler.h:279
#define TL(string)
Definition MsgHandler.h:287
#define TLF(string,...)
Definition MsgHandler.h:288
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define TIME2STEPS(x)
Definition SUMOTime.h:57
@ SUMO_TAG_PHASE
a single phase description
@ SUMO_TAG_TLLOGIC
a traffic light logic
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ 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_LATEST_END
The maximum time within the cycle for switching (for coordinated actuation)
@ 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_ID
@ SUMO_ATTR_MAXDURATION
maximum duration of a phase
@ SUMO_ATTR_PROGRAMID
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_MINDURATION
@ SUMO_ATTR_STATE
The state of a link.
@ SUMO_ATTR_EARLIEST_END
The minimum time within the cycle for switching (for coordinated actuation)
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
static std::string addExtension(const std::string &path, const std::string &extension)
Add an extension to the given file path.
An Element which don't belong to GNENet but has influence in the simulation.
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
static bool canParse(const std::string &string)
true if a value of type T can be parsed from string
GNENet * getNet() const
get pointer to net
A road/street connecting two junctions (netedit-version)
Definition GNEEdge.h:53
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition GNEEdge.cpp:840
GNEViewNet * getViewNet() const
get view net
Definition GNEFrame.cpp:150
GNEViewNet * myViewNet
FOX need this.
Definition GNEFrame.h:117
virtual void show()
show Frame
Definition GNEFrame.cpp:115
virtual void hide()
hide Frame
Definition GNEFrame.cpp:124
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
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.
std::string getAttribute(SumoXMLAttr key) const
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
std::vector< GNEConnection * > getGNEConnections() const
Returns all GNEConnections vinculated with this junction.
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
NBNode * getNBNode() const
Return net build node.
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition GNELane.h:46
GNEEdge * getParentEdge() const
get parent edge
Definition GNELane.cpp:118
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
std::vector< GNELane * > getSelectedLanes() const
get selected lanes
std::vector< GNEEdge * > getSelectedEdges() const
return all edges
SUMORTree & getGrid()
Returns the RTree used for visualisation speed-up.
Definition GNENet.cpp:145
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition GNENet.cpp:2036
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:120
NBEdgeCont & getEdgeCont()
returns the NBEdgeCont of the underlying netbuilder
Definition GNENet.cpp:2042
void hideOverlappedInspection()
hide template editor
int getNumberOfOverlappedACs() const
get number of overlapped ACSs
void showOverlappedInspection(const GNEViewNetHelper::ObjectsUnderCursor &objectsUnderCursor, const Position &clickedPosition)
show template editor
Dialog for edit 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.
long onUpdParameters(FXObject *, FXSelector, void *)
Called when the offset is updated.
MFXToggleButtonTooltip * mySetDetectorsToggleButton
toggle button for set detectors mode
bool isSetDetectorsToggleButtonEnabled() const
toggle button for set detectors mode
bool isValidParameters()
are current parameter valid
FXTextField * myOffsetTextField
the TextField for modifying offset
void disableE1DetectorMode()
disable detector mode
SUMOTime getOffset() const
get current offset in string format
long onUpdSetDetectorMode(FXObject *, FXSelector, void *)
Called when occurs an update of set detector mode.
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
long onUpdOffset(FXObject *, FXSelector, void *)
Called when the offset is updated.
void setOffset(const SUMOTime &offset)
set new offset
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
long onCmdToggleDetectorMode(FXObject *, FXSelector, void *ptr)
Called when user toggle set detector mode.
void createTLS(GNEJunction *junction)
FOX needs this.
void clearTLSDefinitions()
clear TLS Definitions
long onCmdDefSwitchTLSProgram(FXObject *, FXSelector, void *)
Called when the user switches a TLS.
long onUpdTLSDisableResetAll(FXObject *, FXSelector, void *)
Called when occurs an update of switch definition.
bool checkHaveModifications() const
check if current TLS was modified
void hideTLSDefinition()
hide TLSDefinition
long onCmdSaveChanges(FXObject *, FXSelector, void *)
Called when the user presses the save-Button.
long onCmdDiscardChanges(FXObject *, FXSelector, void *)
Called when the user presses the Cancel-button.
void markAsModified()
mark Program as modified
FXComboBox * myProgramComboBox
the comboBox for selecting the tl-definition to edit
const std::string getCurrentTLSProgramID() const
get current program ID
int getNumberOfTLSDefinitions() const
get number of TLS definitions
long onCmdResetCurrentProgram(FXObject *, FXSelector, void *)
Called when the user press button reset current TLS Program.
long onCmdDelete(FXObject *, FXSelector, void *)
Called when the user press button delete TLS Program.
int getNumberOfPrograms() const
get number of programs
void showTLSDefinition()
show TLSDefinition
long onUpdCreate(FXObject *, FXSelector, void *)
Called when occurs an update of create definition.
bool initTLSDefinitions()
init TLS Definitions
NBTrafficLightDefinition * getCurrentTLSDefinition() const
get current definition
long onCmdCreate(FXObject *, FXSelector, void *)
TLSDefinition(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
void discardChanges(const bool editJunctionAgain)
discard changes
long onUpdTLSEnableModified(FXObject *, FXSelector, void *)
Called when occurs an update of switch definition.
long onCmdResetAll(FXObject *, FXSelector, void *)
Called when the user press button reset all TLS Programs.
FXButton * myCreateButton
button for create new Traffic light program
long onUpdTLSDisableModified(FXObject *, FXSelector, void *)
Called when occurs an update of switch definition.
long onCmdLoadTLSProgram(FXObject *, FXSelector, void *)
TLSFile(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
std::string writeSUMOTime(SUMOTime steps)
convert SUMOTime into string
long onUpdButtons(FXObject *, FXSelector, void *)
enable buttons, only when a tlLogic is being edited
long onCmdSaveTLSProgram(FXObject *, FXSelector, void *)
save TLS Program to an additional file
long onCmdChangeType(FXObject *, FXSelector, void *)
Called when the user change TLS Type.
long onCmdDisjoinTLS(FXObject *, FXSelector, void *)
Called when the user join TLS.
FXHorizontalFrame * myJoinControlButtons
frame for accept/cancel buttons
const std::vector< std::string > & getSelectedJunctionIDs() const
get selected junction IDs
long onUpdTLSType(FXObject *, FXSelector, void *)
Called when occurs an update of modified.
long onCmdToggleJoinTLS(FXObject *, FXSelector, void *)
Called when the user join TLS.
long onCmdRenameTLS(FXObject *, FXSelector, void *)
TLSJunction(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
long onCmdCancelJoin(FXObject *, FXSelector, void *)
cancel join
long onUpdJoinTLS(FXObject *, FXSelector, void *)
Called when update join TLS.
MFXComboBoxIcon * myTLSTypeComboBox
ComboBox for TLS Types.
MFXToggleButtonTooltip * myJoinTLSToggleButton
Toggle button for join TLS.
void updateJunctionDescription()
update junction description
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
long onUpdDisjoinTLS(FXObject *, FXSelector, void *)
Called when update join TLS.
FXLabel * myJunctionIDLabel
label for junction ID
bool isJunctionSelected(const GNEJunction *junction) const
check if given junction is selected (used fo joining)
MFXButtonTooltip * myDisjoinTLSButton
button for disjoin TLS
bool isJoiningJunctions() const
is joining junctions
MFXTextFieldTooltip * myTLSIDTextField
text field for junction ID
long onUpdTLSID(FXObject *, FXSelector, void *)
Called when occurs an update of modified.
MFXTextFieldTooltip * myJunctionIDTextField
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.
bool setVehExt(const int row, const std::string &value)
set vehExt
int buildDefaultPhase(const int row)
build default phase
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.)
long onUpdNeedsSingleDef(FXObject *, FXSelector, void *)
Called to buttons that modify link indices.
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
void updateStateSize(const int col)
update state size
long onCmdAddUnusedStates(FXObject *, FXSelector, void *)
Called when the user cleans up states.
void initStaticPhaseTable()
FOX needs this.
long onUpdUngroupStates(FXObject *, FXSelector, void *)
Called to update the ungroups states button.
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
long onUpdNeedsDef(FXObject *, FXSelector, void *)
enable buttons, only when a tlLogic is being edited
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
long onUpdNeedsDefAndPhase(FXObject *, FXSelector, void *)
Called when occurs an update of needs definition and phase.
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
void handleChange(GNEInternalLane *lane)
update phase definition for the current traffic light and phase
GNEOverlappedInspection * myOverlappedInspection
Overlapped Inspection.
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)
std::map< int, std::vector< GNEInternalLane * > > myInternalLanes
the internal lanes belonging the the current junction indexed by their tl-index
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::TLSDefinition * myTLSDefinition
module for TLS Definition
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
GNETLSEditorFrame::TLSJunction * myTLSJunction
module for TLS Junction
void editTLS(const Position &clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor &objectsUnderCursor)
edits the traffic light for the given clicked junction
void cleanup()
cleans up previous lanes
GNETLSEditorFrame::TLSDefinition * getTLSDefinition() const
get module for TLS Definition
void show()
show inspector frame
void clearTable()
clear table
void selectRow(const int rowIndex)
Select a row.
int getCurrentSelectedRow() const
Get current selected row.
void recalcTableWidth()
recalc width (call when all labels and contents are fill)
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
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
GNENet * getNet() const
get the net object
bool changeAllPhases() const
change all phases
GNEViewParent * getViewParent() const
get the net object
GNEUndoList * getUndoList() const
get the undoList object
void setStatusBarText(const std::string &text)
set statusBar text
A single child window which contains a view of the simulation area.
GNEApplicationWindow * getGNEAppWindows() const
get GNE Application Windows
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
ComboBox with icon.
FXint getNumItems() const
Return the number of items in the list.
void setNumVisible(FXint nvis)
Set the number of visible items in the drop down list.
FXint appendIconItem(const FXString &text, FXIcon *icon=nullptr, FXColor bgColor=FXRGB(255, 255, 255), void *ptr=nullptr)
append icon
MFXGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
Options
GroupBoxModule options.
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extension, FXIcon *icon, FXString &currentFolder)
Returns the file name to write.
Definition MFXUtils.cpp:82
static FXColor getFXColor(const RGBColor &col)
converts FXColor to RGBColor
Definition MFXUtils.cpp:112
A loaded (complete) traffic light logic.
NBTrafficLightLogic * getLogic()
Returns the internal logic.
void setProgramID(const std::string &programID)
Sets the programID.
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:334
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition NBNode.h:329
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 removeProgram(const std::string id, const std::string programID, bool del=true)
Removes a program of a logic definition from the dictionary.
bool exist(const std::string &newID) const
check if exists a definition with the given ID
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.
void setPhaseState(int phaseIndex, int tlIndex, LinkState linkState)
Modifies the state for an existing phase (used by netedit)
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
Importer for edge connections stored in XML.
const std::set< std::string > & getSeenIDs()
const std::string & getID() const
Returns the id.
Definition Named.h:74
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
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 ammount
PositionVector reverse() const
reverse position vector
static const RGBColor BLACK
Definition RGBColor.h:193
static const RGBColor RED
named colors
Definition RGBColor.h:185
void addAdditionalGLObject(GUIGlObject *o, const double exaggeration=1)
Adds an additional object (detector/shape/trigger) for visualisation.
Definition SUMORTree.h:124
void removeAdditionalGLObject(GUIGlObject *o, const double exaggeration=1)
Removes an additional object (detector/shape/trigger) from being visualised.
Definition SUMORTree.h:160
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
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