Eclipse SUMO - Simulation of Urban MObility
GNETLSEditorFrame.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
15 // The Widget for modifying traffic lights
16 /****************************************************************************/
17 
18 
19 // ===========================================================================
20 // included modules
21 // ===========================================================================
22 #include <config.h>
23 
27 #include <utils/xml/XMLSubSys.h>
30 #include <netedit/GNEViewNet.h>
31 #include <netedit/GNENet.h>
35 #include <netedit/GNEUndoList.h>
38 
39 #include "GNETLSEditorFrame.h"
40 
41 // ===========================================================================
42 // FOX callback mapping
43 // ===========================================================================
44 
45 FXDEFMAP(GNETLSEditorFrame) GNETLSEditorFrameMap[] = {
46  FXMAPFUNC(SEL_COMMAND, MID_CANCEL, GNETLSEditorFrame::onCmdCancel),
47  FXMAPFUNC(SEL_UPDATE, MID_CANCEL, GNETLSEditorFrame::onUpdModified),
48  FXMAPFUNC(SEL_COMMAND, MID_OK, GNETLSEditorFrame::onCmdOK),
49  FXMAPFUNC(SEL_UPDATE, MID_OK, GNETLSEditorFrame::onUpdModified),
74 };
75 
76 FXDEFMAP(GNETLSEditorFrame::TLSFile) TLSFileMap[] = {
81 };
82 
83 // Object implementation
84 FXIMPLEMENT(GNETLSEditorFrame, FXVerticalFrame, GNETLSEditorFrameMap, ARRAYNUMBER(GNETLSEditorFrameMap))
85 FXIMPLEMENT(GNETLSEditorFrame::TLSFile, FXGroupBox, TLSFileMap, ARRAYNUMBER(TLSFileMap))
86 
87 
88 // ===========================================================================
89 // method definitions
90 // ===========================================================================
91 
92 GNETLSEditorFrame::GNETLSEditorFrame(FXHorizontalFrame* horizontalFrameParent, GNEViewNet* viewNet):
93  GNEFrame(horizontalFrameParent, viewNet, "Edit Traffic Light"),
94  myEditedDef(nullptr) {
95 
96  // create TLSJunction modul
97  myTLSJunction = new GNETLSEditorFrame::TLSJunction(this);
98 
99  // create TLSDefinition modul
100  myTLSDefinition = new GNETLSEditorFrame::TLSDefinition(this);
101 
102  // create TLSAttributes modul
103  myTLSAttributes = new GNETLSEditorFrame::TLSAttributes(this);
104 
105  // create TLSModifications modul
106  myTLSModifications = new GNETLSEditorFrame::TLSModifications(this);
107 
108  // create TLSPhases modul
109  myTLSPhases = new GNETLSEditorFrame::TLSPhases(this);
110 
111  // create TLSFile modul
112  myTLSFile = new GNETLSEditorFrame::TLSFile(this);
113 
114  // "Add 'off' program"
115  /*
116  new FXButton(myContentFrame, "Add \"Off\"-Program\t\tAdds a program for switching off this traffic light",
117  0, this, MID_GNE_TLSFRAME_ADDOFF, GUIDesignButton);
118  */
119 }
120 
121 
123  cleanup();
124 }
125 
126 
127 void
130  onCmdCancel(nullptr, 0, nullptr);
131  myViewNet->getUndoList()->p_begin("modifying traffic light definition");
138  myViewNet->getNet()->retrieveJunction(node->getID())->selectTLS(true);
139  }
140  }
141  } else {
142  myViewNet->setStatusBarText("Unsaved modifications. Abort or Save");
143  }
144 }
145 
146 
147 bool
150  // write warning if netedit is running in testing mode
151  WRITE_DEBUG("Opening question FXMessageBox 'save TLS'");
152  // open question box
153  FXuint answer = FXMessageBox::question(this, MBOX_YES_NO_CANCEL,
154  "Save TLS Changes", "%s",
155  "There is unsaved changes in current edited traffic light.\nDo you want to save it before changing mode?");
156  if (answer == MBOX_CLICKED_YES) { //1:yes, 2:no, 4:esc/cancel
157  // write warning if netedit is running in testing mode
158  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'YES'");
159  // save modifications
160  onCmdOK(nullptr, 0, nullptr);
161  return true;
162  } else if (answer == MBOX_CLICKED_NO) {
163  // write warning if netedit is running in testing mode
164  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'No'");
165  // cancel modifications
166  onCmdCancel(nullptr, 0, nullptr);
167  return true;
168  } else {
169  // write warning if netedit is running in testing mode
170  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'Cancel'");
171  // abort changing mode
172  return false;
173  }
174  } else {
175  return true;
176  }
177 }
178 
179 
180 bool
181 GNETLSEditorFrame::parseTLSPrograms(const std::string& file) {
183  NBTrafficLightLogicCont tmpTLLCont;;
184  NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myViewNet->getNet()->getEdgeCont());
185  // existing definitions must be available to update their programs
186  std::set<NBTrafficLightDefinition*> origDefs;
187  for (NBTrafficLightDefinition* def : tllCont.getDefinitions()) {
188  // make a copy of every program
189  NBTrafficLightLogic* logic = tllCont.getLogic(def->getID(), def->getProgramID());
190  if (logic != nullptr) {
191  NBTrafficLightDefinition* copy = new NBLoadedSUMOTLDef(def, logic);
192  std::vector<NBNode*> nodes = def->getNodes();
193  for (auto it_node : nodes) {
194  GNEJunction* junction = myViewNet->getNet()->retrieveJunction(it_node->getID());
195  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, false, false), true);
196  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, copy, true), true);
197  }
198  tmpTLLCont.insert(copy);
199  origDefs.insert(copy);
200  } else {
201  WRITE_WARNING("tlLogic '" + def->getID() + "', program '" + def->getProgramID() + "' could not be built");
202  }
203  }
204  //std::cout << " initialized tmpCont with " << origDefs.size() << " defs\n";
205  XMLSubSys::runParser(tllHandler, file);
206 
207  std::vector<NBLoadedSUMOTLDef*> loadedTLS;
208  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
209  NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
210  if (sdef != nullptr) {
211  loadedTLS.push_back(sdef);
212  }
213  }
214  myViewNet->setStatusBarText("Loaded " + toString(loadedTLS.size()) + " programs");
215  for (auto def : loadedTLS) {
216  if (origDefs.count(def) != 0) {
217  // already add to undolist before
218  //std::cout << " skip " << def->getDescription() << "\n";
219  continue;
220  }
221  std::vector<NBNode*> nodes = def->getNodes();
222  //std::cout << " add " << def->getDescription() << " for nodes=" << toString(nodes) << "\n";
223  for (auto it_node : nodes) {
224  GNEJunction* junction = myViewNet->getNet()->retrieveJunction(it_node->getID());
225  //myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, false), true);
226  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, true), true);
227  }
228  }
229  // clean up temporary container to avoid deletion of defs when it's destruct is called
230  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
231  tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
232  }
233  return true;
234 }
235 
236 
237 long
238 GNETLSEditorFrame::onCmdCancel(FXObject*, FXSelector, void*) {
239  if (myTLSJunction->getCurrentJunction() != nullptr) {
241  cleanup();
242  myViewNet->update();
243  }
244  return 1;
245 }
246 
247 
248 long
249 GNETLSEditorFrame::onCmdOK(FXObject*, FXSelector, void*) {
250  if (myTLSJunction->getCurrentJunction() != nullptr) {
253  std::vector<NBNode*> nodes = oldDefinition->getNodes();
254  for (auto it : nodes) {
255  GNEJunction* junction = myViewNet->getNet()->retrieveJunction(it->getID());
256  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, oldDefinition, false), true);
257  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myEditedDef, true), true);
258  }
259  myEditedDef = nullptr;
261  cleanup();
262  myViewNet->update();
263  } else {
264  onCmdCancel(nullptr, 0, nullptr);
265  }
266  }
267  return 1;
268 }
269 
270 
271 long
272 GNETLSEditorFrame::onCmdDefCreate(FXObject*, FXSelector, void*) {
274  // abort because we onCmdOk assumes we wish to save an edited definition
275  onCmdCancel(nullptr, 0, nullptr);
276  // check that current junction has two or more edges
277  if ((junction->getGNEIncomingEdges().size() > 0) && (junction->getGNEOutgoingEdges().size() > 0)) {
280  } else {
281  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, nullptr, true, true), true);
282  }
283  editJunction(junction);
284  } else {
285  // write warning if netedit is running in testing mode
286  WRITE_DEBUG("Opening warning FXMessageBox 'invalid TLS'");
287  // open question box
288  FXMessageBox::warning(this, MBOX_OK,
289  "TLS cannot be created", "%s",
290  "Traffic Light cannot be created because junction must have\n at least one incoming edge and one outgoing edge.");
291  // write warning if netedit is running in testing mode
292  WRITE_DEBUG("Closed FXMessageBox 'invalid TLS'");
293  }
294  return 1;
295 }
296 
297 
298 long
299 GNETLSEditorFrame::onCmdDefDelete(FXObject*, FXSelector, void*) {
301  const bool changeType = myTLSAttributes->getNumberOfTLSDefinitions() == 1;
303  onCmdCancel(nullptr, 0, nullptr); // abort because onCmdOk assumes we wish to save an edited definition
304  if (changeType) {
306  } else {
307  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, tlDef, false), true);
308  }
309  return 1;
310 }
311 
312 
313 long
314 GNETLSEditorFrame::onCmdDefSwitch(FXObject*, FXSelector, void*) {
315  assert(myTLSJunction->getCurrentJunction() != 0);
318  // logic may not have been recomputed yet. recompute to be sure
321  NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
322  if (tllogic != nullptr) {
323  // now we can be sure that the tlDef is up to date (i.e. re-guessed)
324  buildIinternalLanes(tlDef);
325  // create working copy from original def
326  delete myEditedDef;
327  myEditedDef = new NBLoadedSUMOTLDef(tlDef, tllogic);
332  } else {
333  // tlDef has no valid logic (probably because id does not control any links
334  onCmdCancel(nullptr, 0, nullptr);
335  myViewNet->setStatusBarText("Traffic light does not control any links");
336  }
337  return 1;
338 }
339 
340 
341 long
342 GNETLSEditorFrame::onUpdDefSwitch(FXObject* o, FXSelector, void*) {
344  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
345  return 1;
346 }
347 
348 
349 long
350 GNETLSEditorFrame::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
351  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0;
352  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
353  return 1;
354 }
355 
356 
357 long
358 GNETLSEditorFrame::onUpdNeedsDefAndPhase(FXObject* o, FXSelector, void*) {
359  // do not delete the last phase
360  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0 && myTLSPhases->getPhaseTable()->getNumRows() > 1;
361  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
362  return 1;
363 }
364 
365 
366 long
367 GNETLSEditorFrame::onUpdDefCreate(FXObject* o, FXSelector, void*) {
368  const bool enable = myTLSJunction->getCurrentJunction() != nullptr && !myTLSModifications->checkHaveModifications();
369  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
370  return 1;
371 }
372 
373 
374 long
375 GNETLSEditorFrame::onUpdModified(FXObject* o, FXSelector, void*) {
377  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
378  return 1;
379 }
380 
381 
382 
383 long
384 GNETLSEditorFrame::onCmdDefOffset(FXObject*, FXSelector, void*) {
387  return 1;
388 }
389 
390 
391 long
392 GNETLSEditorFrame::onCmdDefRename(FXObject*, FXSelector, void*) {
393  return 1;
394 }
395 
396 
397 long
398 GNETLSEditorFrame::onCmdDefSubRename(FXObject*, FXSelector, void*) {
399  return 1;
400 }
401 
402 
403 long
404 GNETLSEditorFrame::onCmdDefAddOff(FXObject*, FXSelector, void*) {
405  return 1;
406 }
407 
408 
409 long
410 GNETLSEditorFrame::onCmdGuess(FXObject*, FXSelector, void*) {
411  return 1;
412 }
413 
414 
415 long
416 GNETLSEditorFrame::onCmdPhaseSwitch(FXObject*, FXSelector, void*) {
417  const int index = myTLSPhases->getPhaseTable()->getCurrentRow();
418  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[index];
419  myTLSPhases->getPhaseTable()->selectRow(index);
420  // need not hold since links could have been deleted somewhere else and indices may be reused
421  // assert(phase.state.size() == myInternalLanes.size());
422  for (auto it : myInternalLanes) {
423  int tlIndex = it.first;
424  std::vector<GNEInternalLane*> lanes = it.second;
426  if (tlIndex >= 0 && tlIndex < (int)phase.state.size()) {
427  state = (LinkState)phase.state[tlIndex];
428  }
429  for (auto it_lane : lanes) {
430  it_lane->setLinkState(state);
431  }
432  }
433  myViewNet->update();
434  return 1;
435 }
436 
437 bool
439  assert(myEditedDef != nullptr);
440  return myEditedDef->getType() == TLTYPE_STATIC;
441 }
442 
443 long
444 GNETLSEditorFrame::onCmdPhaseCreate(FXObject*, FXSelector, void*) {
446  // allows insertion at first position by deselecting via arrow keys
447  int newIndex = myTLSPhases->getPhaseTable()->getSelStartRow() + 1;
448  int oldIndex = MAX2(0, myTLSPhases->getPhaseTable()->getSelStartRow());
449  // copy current row
450  SUMOTime duration = getSUMOTime(myTLSPhases->getPhaseTable()->getItemText(oldIndex, 0));
451  std::string state = myTLSPhases->getPhaseTable()->getItemText(oldIndex, fixedDuration() ? 1 : 3).text();
452 
453  std::set<int> crossingIndices;
454  for (NBNode* n : myEditedDef->getNodes()) {
455  for (NBNode::Crossing* c : n->getCrossings()) {
456  crossingIndices.insert(c->tlLinkIndex);
457  crossingIndices.insert(c->tlLinkIndex2);
458  }
459  }
460 
461  // smart adapations for new state
462  bool haveGreen = false;
463  bool haveYellow = false;
464  for (char c : state) {
466  haveGreen = true;
467  } else if (c == LINKSTATE_TL_YELLOW_MAJOR || c == LINKSTATE_TL_YELLOW_MINOR) {
468  haveYellow = true;
469  }
470  }
471  const OptionsCont& oc = OptionsCont::getOptions();
472  if (haveGreen && haveYellow) {
473  // guess left-mover state
474  duration = TIME2STEPS(oc.getInt("tls.left-green.time"));
475  for (int i = 0; i < (int)state.size(); i++) {
476  if (state[i] == LINKSTATE_TL_YELLOW_MAJOR || state[i] == LINKSTATE_TL_YELLOW_MINOR) {
477  state[i] = LINKSTATE_TL_RED;
478  } else if (state[i] == LINKSTATE_TL_GREEN_MINOR) {
479  state[i] = LINKSTATE_TL_GREEN_MAJOR;
480  }
481  }
482  } else if (haveGreen) {
483  // guess yellow state
485  duration = TIME2STEPS(myEditedDef->computeBrakingTime(oc.getFloat("tls.yellow.min-decel")));
486  for (int i = 0; i < (int)state.size(); i++) {
487  if (state[i] == LINKSTATE_TL_GREEN_MAJOR || state[i] == LINKSTATE_TL_GREEN_MINOR) {
488  if (crossingIndices.count(i) == 0) {
489  state[i] = LINKSTATE_TL_YELLOW_MINOR;
490  } else {
491  state[i] = LINKSTATE_TL_RED;
492  }
493  }
494  }
495  } else if (haveYellow) {
496  duration = TIME2STEPS(oc.isDefault("tls.allred.time") ? 2 : oc.getInt("tls.allred.time"));
497  // guess all-red state
498  for (int i = 0; i < (int)state.size(); i++) {
499  if (state[i] == LINKSTATE_TL_YELLOW_MAJOR || state[i] == LINKSTATE_TL_YELLOW_MINOR) {
500  state[i] = LINKSTATE_TL_RED;
501  }
502  }
503  }
504 
505  myEditedDef->getLogic()->addStep(duration, state, std::vector<int>(), "", newIndex);
506  myTLSPhases->getPhaseTable()->setCurrentItem(newIndex, 0);
507  myTLSPhases->initPhaseTable(newIndex);
508  myTLSPhases->getPhaseTable()->setFocus();
509  return 1;
510 }
511 
512 
513 long
514 GNETLSEditorFrame::onCmdPhaseDelete(FXObject*, FXSelector, void*) {
516  const int newRow = MAX2((int)0, (int)myTLSPhases->getPhaseTable()->getCurrentRow() - 1);
517  myEditedDef->getLogic()->deletePhase(myTLSPhases->getPhaseTable()->getCurrentRow());
518  myTLSPhases->initPhaseTable(newRow);
519  myTLSPhases->getPhaseTable()->setFocus();
520  return 1;
521 }
522 
523 
524 long
525 GNETLSEditorFrame::onCmdCleanup(FXObject*, FXSelector, void*) {
528  myTLSPhases->getPhaseTable()->setFocus();
529  return 1;
530 }
531 
532 
533 long
534 GNETLSEditorFrame::onCmdAddUnused(FXObject*, FXSelector, void*) {
536  myEditedDef->getLogic()->getNumLinks() + 1);
539  myTLSPhases->getPhaseTable()->setFocus();
540  return 1;
541 }
542 
543 
544 long
545 GNETLSEditorFrame::onCmdPhaseEdit(FXObject*, FXSelector, void* ptr) {
546  /* @note: there is a bug when copying/pasting rows: when this handler is
547  * called the value of the cell is not yet updated. This means you have to
548  * click inside the cell and hit enter to actually update the value */
549  FXTablePos* tp = (FXTablePos*)ptr;
550  FXString value = myTLSPhases->getPhaseTable()->getItemText(tp->row, tp->col);
551  const int colDuration = 0;
552  const int colMinDur = fixedDuration() ? -1 : 1;
553  const int colMaxDur = fixedDuration() ? -1 : 2;
554  const int colState = fixedDuration() ? 1 : 3;
555  const int colNext = fixedDuration() ? 2 : 4;
556  const int colName = fixedDuration() ? 3 : 5;
557 
558  if (tp->col == colDuration) {
559  // duration edited
560  if (GNEAttributeCarrier::canParse<double>(value.text())) {
561  SUMOTime duration = getSUMOTime(value);
562  if (duration > 0) {
563  myEditedDef->getLogic()->setPhaseDuration(tp->row, duration);
566  return 1;
567  }
568  }
569  // input error, reset value
570  myTLSPhases->getPhaseTable()->setItemText(tp->row, colDuration, toString(STEPS2TIME(getPhases()[tp->row].duration)).c_str());
571  } else if (tp->col == colMinDur) {
572  // minDur edited
573  if (GNEAttributeCarrier::canParse<double>(value.text())) {
574  SUMOTime minDur = getSUMOTime(value);
575  if (minDur > 0) {
576  myEditedDef->getLogic()->setPhaseMinDuration(tp->row, minDur);
578  return 1;
579  }
580  } else if (StringUtils::prune(value.text()).empty()) {
583  return 1;
584  }
585  // input error, reset value
586  myTLSPhases->getPhaseTable()->setItemText(tp->row, colMinDur, varDurString(getPhases()[tp->row].minDur).c_str());
587  } else if (tp->col == colMaxDur) {
588  // maxDur edited
589  if (GNEAttributeCarrier::canParse<double>(value.text())) {
590  SUMOTime maxDur = getSUMOTime(value);
591  if (maxDur > 0) {
592  myEditedDef->getLogic()->setPhaseMaxDuration(tp->row, maxDur);
594  return 1;
595  }
596  } else if (StringUtils::prune(value.text()).empty()) {
599  return 1;
600  }
601  // input error, reset value
602  myTLSPhases->getPhaseTable()->setItemText(tp->row, colMaxDur, varDurString(getPhases()[tp->row].maxDur).c_str());
603  } else if (tp->col == colState) {
604  // state edited
605  try {
606  // insert phase with new step and delete the old phase
607  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[tp->row];
608  myEditedDef->getLogic()->addStep(phase.duration, value.text(), phase.next, phase.name, tp->row);
609  myEditedDef->getLogic()->deletePhase(tp->row + 1);
611  onCmdPhaseSwitch(nullptr, 0, nullptr);
612  } catch (ProcessError&) {
613  // input error, reset value
614  myTLSPhases->getPhaseTable()->setItemText(tp->row, colState, getPhases()[tp->row].state.c_str());
615  }
616  } else if (tp->col == colNext) {
617  // next edited
618  bool ok = true;
619  if (GNEAttributeCarrier::canParse<std::vector<int> >(value.text())) {
620  std::vector<int> next = GNEAttributeCarrier::parse<std::vector<int> >(value.text());
621  for (int n : next) {
622  if (n < 0 || n >= myTLSPhases->getPhaseTable()->getNumRows()) {
623  ok = false;
624  break;
625  }
626  }
627  if (ok) {
628  myEditedDef->getLogic()->setPhaseNext(tp->row, next);
630  return 1;
631  }
632  }
633  // input error, reset value
634  myTLSPhases->getPhaseTable()->setItemText(tp->row, colNext, "");
635  } else if (tp->col == colName) {
636  // name edited
637  myEditedDef->getLogic()->setPhaseName(tp->row, value.text());
639  return 1;
640  }
641  return 1;
642 }
643 
644 
645 void
651  myViewNet->getNet()->retrieveJunction(node->getID())->selectTLS(false);
652  }
653  }
654  }
655  // clean data structures
658  delete myEditedDef;
659  myEditedDef = nullptr;
660  buildIinternalLanes(nullptr); // only clears
661  // clean up controls
663  myTLSPhases->initPhaseTable(); // only clears when there are no definitions
666 }
667 
668 
669 void
672  // clean up previous objects
673  for (auto it : myInternalLanes) {
674  for (auto it_intLanes : it.second) {
675  rtree.removeAdditionalGLObject(it_intLanes);
676  delete it_intLanes;
677  }
678  }
679  myInternalLanes.clear();
680  // create new internal lanes
681  if (tlDef != nullptr) {
682  const int NUM_POINTS = 10;
685  std::string innerID = ":" + nbn->getID(); // see NWWriter_SUMO::writeInternalEdges
686  const NBConnectionVector& links = tlDef->getControlledLinks();
687  for (auto it : links) {
688  int tlIndex = it.getTLIndex();
689  PositionVector shape = it.getFrom()->getToNode()->computeInternalLaneShape(it.getFrom(), NBEdge::Connection(it.getFromLane(),
690  it.getTo(), it.getToLane()), NUM_POINTS);
691  if (shape.length() < 2) {
692  // enlarge shape to ensure visibility
693  shape.clear();
694  PositionVector laneShapeFrom = it.getFrom()->getLaneShape(it.getFromLane());
695  PositionVector laneShapeTo = it.getTo()->getLaneShape(it.getToLane());
696  shape.push_back(laneShapeFrom.positionAtOffset(MAX2(0.0, laneShapeFrom.length() - 1)));
697  shape.push_back(laneShapeTo.positionAtOffset(MIN2(1.0, laneShapeFrom.length())));
698  }
699  GNEInternalLane* ilane = new GNEInternalLane(this, innerID + '_' + toString(tlIndex), shape, tlIndex);
700  rtree.addAdditionalGLObject(ilane);
701  myInternalLanes[tlIndex].push_back(ilane);
702  }
703  for (NBNode* nbn : tlDef->getNodes()) {
704  for (auto c : nbn->getCrossings()) {
705  if (c->tlLinkIndex2 > 0 && c->tlLinkIndex2 != c->tlLinkIndex) {
706  // draw both directions
707  PositionVector forward = c->shape;
708  forward.move2side(c->width / 4);
709  GNEInternalLane* ilane = new GNEInternalLane(this, c->id, forward, c->tlLinkIndex);
710  rtree.addAdditionalGLObject(ilane);
711  myInternalLanes[c->tlLinkIndex].push_back(ilane);
712 
713  PositionVector backward = c->shape.reverse();
714  backward.move2side(c->width / 4);
715  GNEInternalLane* ilane2 = new GNEInternalLane(this, c->id + "_r", backward, c->tlLinkIndex2);
716  rtree.addAdditionalGLObject(ilane2);
717  myInternalLanes[c->tlLinkIndex2].push_back(ilane2);
718  } else {
719  // draw only one lane for both directions
720  GNEInternalLane* ilane = new GNEInternalLane(this, c->id, c->shape, c->tlLinkIndex);
721  rtree.addAdditionalGLObject(ilane);
722  myInternalLanes[c->tlLinkIndex].push_back(ilane);
723  }
724  }
725  }
726  }
727 }
728 
729 
730 std::string
733 }
734 
735 
736 const std::vector<NBTrafficLightLogic::PhaseDefinition>&
738  return myEditedDef->getLogic()->getPhases();
739 }
740 
741 
742 void
745  if (myViewNet->changeAllPhases()) {
746  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
747  for (int row = 0; row < (int)phases.size(); row++) {
748  myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
749  }
750  } else {
751  myEditedDef->getLogic()->setPhaseState(myTLSPhases->getPhaseTable()->getCurrentRow(), lane->getTLIndex(), lane->getLinkState());
752  }
753  myTLSPhases->initPhaseTable(myTLSPhases->getPhaseTable()->getCurrentRow());
754  myTLSPhases->getPhaseTable()->setFocus();
755 }
756 
757 
758 void
759 GNETLSEditorFrame::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* eventData) {
760  if (myEditedDef != nullptr) {
763  std::set<std::string> fromIDs;
764  fromIDs.insert(lane->getMicrosimID());
765  GNEEdge& edge = lane->getParentEdge();
766  // if neither the lane nor its edge are selected, apply changes to the whole edge
767  if (!edge.isAttributeCarrierSelected() && !lane->isAttributeCarrierSelected()) {
768  for (auto it_lane : edge.getLanes()) {
769  fromIDs.insert(it_lane->getMicrosimID());
770  }
771  } else {
772  // if the edge is selected, apply changes to all lanes of all selected edges
773  if (edge.isAttributeCarrierSelected()) {
774  std::vector<GNEEdge*> edges = myViewNet->getNet()->retrieveEdges(true);
775  for (auto it : edges) {
776  for (auto it_lane : it->getLanes()) {
777  fromIDs.insert(it_lane->getMicrosimID());
778  }
779  }
780  }
781  // if the lane is selected, apply changes to all selected lanes
782  if (lane->isAttributeCarrierSelected()) {
783  std::vector<GNELane*> lanes = myViewNet->getNet()->retrieveLanes(true);
784  for (auto it_lane : lanes) {
785  fromIDs.insert(it_lane->getMicrosimID());
786  }
787  }
788 
789  }
790  // set new state for all connections from the chosen lane IDs
791  for (auto it : links) {
792  if (fromIDs.count(it.getFrom()->getLaneID(it.getFromLane())) > 0) {
793  std::vector<GNEInternalLane*> lanes = myInternalLanes[it.getTLIndex()];
794  for (auto it_lane : lanes) {
795  it_lane->onDefault(obj, sel, eventData);
796  }
797  }
798  }
799  }
800 }
801 
802 
803 bool
805  if (myEditedDef != nullptr) {
807  for (auto it : links) {
808  if (it.getFrom()->getID() == edge.getMicrosimID()) {
809  return true;
810  }
811  }
812  }
813  return false;
814 }
815 
816 
817 SUMOTime
818 GNETLSEditorFrame::getSUMOTime(const FXString& string) {
819  assert(GNEAttributeCarrier::canParse<double>(string.text()));
820  return TIME2STEPS(GNEAttributeCarrier::parse<double>(string.text()));
821 }
822 
823 // ---------------------------------------------------------------------------
824 // GNETLSEditorFrame::TLSAttributes - methods
825 // ---------------------------------------------------------------------------
826 
828  FXGroupBox(TLSEditorParent->myContentFrame, "Traffic light Attributes", GUIDesignGroupBoxFrame),
829  myTLSEditorParent(TLSEditorParent) {
830 
831  // create frame, label and textfield for name (By default disabled)
832  FXHorizontalFrame* nameFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
833  myNameLabel = new FXLabel(nameFrame, "ID", nullptr, GUIDesignLabelAttribute);
835  myNameTextField->disable();
836 
837  // create frame, label and comboBox for Program (By default hidden)
838  FXHorizontalFrame* programFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
839  myProgramLabel = new FXLabel(programFrame, "Program", nullptr, GUIDesignLabelAttribute);
841  myProgramComboBox->disable();
842 
843  // create frame, label and TextField for Offset (By default disabled)
844  FXHorizontalFrame* offsetFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
845  myOffsetLabel = new FXLabel(offsetFrame, "Offset", nullptr, GUIDesignLabelAttribute);
847  myOffsetTextField->disable();
848 }
849 
850 
852 
853 
854 void
856  assert(junction);
857  myTLSDefinitions.clear();
858  // enable name TextField
859  myNameTextField->enable();
860  // enable Offset
861  myOffsetTextField->enable();
862  // obtain TLSs
863  for (auto it : junction->getNBNode()->getControllingTLS()) {
864  myTLSDefinitions.push_back(it);
865  myNameTextField->setText(it->getID().c_str());
866  myNameTextField->enable();
867  myProgramComboBox->appendItem(it->getProgramID().c_str());
868  }
869  if (myTLSDefinitions.size() > 0) {
870  myProgramComboBox->enable();
871  myProgramComboBox->setCurrentItem(0);
872  myProgramComboBox->setNumVisible(myProgramComboBox->getNumItems());
873  myTLSEditorParent->onCmdDefSwitch(nullptr, 0, nullptr);
874  }
875 }
876 
877 
878 void
880  // clear definitions
881  myTLSDefinitions.clear();
882  // clear and disable name TextField
883  myNameTextField->setText("");
884  myNameTextField->disable();
885  // clear and disable myProgramComboBox
886  myProgramComboBox->clearItems();
887  myProgramComboBox->disable();
888  // clear and disable Offset TextField
889  myOffsetTextField->setText("");
890  myOffsetTextField->disable();
891 }
892 
893 
896  return myTLSDefinitions.at(myProgramComboBox->getCurrentItem());
897 }
898 
899 
900 int
902  return (int)myTLSDefinitions.size();
903 }
904 
905 
906 int
908  return myProgramComboBox->getNumItems();
909 }
910 
911 
912 SUMOTime
914  return getSUMOTime(myOffsetTextField->getText());
915 }
916 
917 
918 void
920  myOffsetTextField->setText(toString(STEPS2TIME(offset)).c_str());
921 }
922 
923 // ---------------------------------------------------------------------------
924 // GNETLSEditorFrame::TLSJunction - methods
925 // ---------------------------------------------------------------------------
926 
928  FXGroupBox(TLSEditorParent->myContentFrame, "Junction", GUIDesignGroupBoxFrame),
929  myTLSEditorParent(TLSEditorParent),
930  myCurrentJunction(nullptr) {
931  // Create frame for junction ID
932  FXHorizontalFrame* junctionIDFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
933  myLabelJunctionID = new FXLabel(junctionIDFrame, "Junction ID", nullptr, GUIDesignLabelAttribute);
935  myTextFieldJunctionID->setEditable(false);
936  // create frame for junction status
937  FXHorizontalFrame* junctionIDStatus = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
938  myLabelJunctionStatus = new FXLabel(junctionIDStatus, "Status", nullptr, GUIDesignLabelAttribute);
940  myTextFieldJunctionStatus->setEditable(false);
941  // update junction description after creation
943  // show TLS Junction
944  show();
945 }
946 
947 
949 
950 
953  return myCurrentJunction;
954 }
955 
956 
957 void
959  myCurrentJunction = junction;
960 }
961 
962 
963 void
965  if (myCurrentJunction == nullptr) {
966  myTextFieldJunctionID->setText("");
967  myTextFieldJunctionStatus->setText("");
968  } else {
970  myTextFieldJunctionID->setText(nbn->getID().c_str());
971  if (!nbn->isTLControlled()) {
972  myTextFieldJunctionStatus->setText("uncontrolled");
973  } else {
975  }
976  }
977 }
978 
979 // ---------------------------------------------------------------------------
980 // GNETLSEditorFrame::TLSDefinition - methods
981 // ---------------------------------------------------------------------------
982 
984  FXGroupBox(TLSEditorParent->myContentFrame, "Traffic lights definition", GUIDesignGroupBoxFrame) {
985  // create create tlDef button
986  myNewTLProgram = new FXButton(this, "Create TLS\t\tCreate a new traffic light program",
988  // create delete tlDef button
989  myDeleteTLProgram = new FXButton(this, "Delete TLS\t\tDelete a traffic light program. If all programs are deleted the junction turns into a priority junction.",
991  // show TLS TLSDefinition
992  show();
993 }
994 
995 
997 
998 // ---------------------------------------------------------------------------
999 // GNETLSEditorFrame::TLSPhases - methods
1000 // ---------------------------------------------------------------------------
1001 
1003  FXGroupBox(TLSEditorParent->myContentFrame, "Phases", GUIDesignGroupBoxFrame),
1004  myTLSEditorParent(TLSEditorParent),
1005  myTableFont(new FXFont(getApp(), "Courier New", 9)) {
1006 
1007  // create and configure phase table
1008  myTableScroll = new FXScrollWindow(this, LAYOUT_FILL_X | LAYOUT_FIX_HEIGHT);
1010  myPhaseTable->setColumnHeaderMode(LAYOUT_FIX_HEIGHT);
1011  myPhaseTable->setColumnHeaderHeight(getApp()->getNormalFont()->getFontHeight() + getApp()->getNormalFont()->getFontAscent() / 2);
1012  myPhaseTable->setRowHeaderMode(LAYOUT_FIX_WIDTH);
1013  myPhaseTable->setRowHeaderWidth(0);
1014  myPhaseTable->hide();
1015  myPhaseTable->setFont(myTableFont);
1016  myPhaseTable->setHelpText("phase duration in seconds | phase state");
1017 
1018  // create total duration info label
1019  myCycleDuration = new FXLabel(this, "", nullptr, GUIDesignLabelLeft);
1020 
1021  // create new phase button
1022  myInsertDuplicateButton = new FXButton(this, "Insert Phase\t\tInsert new phase after the selected phase. The new state is deduced from the selected phase.", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_PHASE_CREATE, GUIDesignButton);
1023 
1024  // create delete phase button
1025  myDeleteSelectedPhaseButton = new FXButton(this, "Delete Phase\t\tDelete selected phase", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_PHASE_DELETE, GUIDesignButton);
1026 
1027  // create cleanup states button
1028  new FXButton(this, "Cleanup States\t\tClean unused states from all phase.", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_CLEANUP, GUIDesignButton);
1029 
1030  // add unused states button
1031  new FXButton(this, "Add Unused States\t\tExtend the state vector for all phases by one entry.", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_ADDUNUSED, GUIDesignButton);
1032 
1033  // show TLSFile
1034  show();
1035 }
1036 
1037 
1039  delete myTableFont;
1040 }
1041 
1042 
1043 FXTable*
1045  return myPhaseTable;
1046 }
1047 
1048 
1049 void
1051  myPhaseTable->setVisibleRows(1);
1052  myPhaseTable->setVisibleColumns(2);
1053  myPhaseTable->hide();
1055  const bool fixed = myTLSEditorParent->fixedDuration();
1056  const int cols = fixed ? 4 : 6;
1057  const int colDuration = 0;
1058  const int colMinDur = fixed ? -1 : 1;
1059  const int colMaxDur = fixed ? -1 : 2;
1060  const int colState = fixed ? 1 : 3;
1061  const int colNext = fixed ? 2 : 4;
1062  const int colName = fixed ? 3 : 5;
1063 
1064  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = myTLSEditorParent->getPhases();
1065  myPhaseTable->setTableSize((int)phases.size(), cols);
1066  myPhaseTable->setVisibleRows((int)phases.size());
1067  myPhaseTable->setVisibleColumns(cols);
1068  for (int row = 0; row < (int)phases.size(); row++) {
1069  myPhaseTable->setItemText(row, colDuration, toString(STEPS2TIME(phases[row].duration)).c_str());
1070  if (!fixed) {
1071  myPhaseTable->setItemText(row, colMinDur, varDurString(phases[row].minDur).c_str());
1072  myPhaseTable->setItemText(row, colMaxDur, varDurString(phases[row].maxDur).c_str());
1073  }
1074  myPhaseTable->setItemText(row, colState, phases[row].state.c_str());
1075  myPhaseTable->setItemText(row, colNext, phases[row].next.size() > 0 ? toString(phases[row].next).c_str() : " ");
1076  myPhaseTable->setItemText(row, colName, phases[row].name.c_str());
1077  myPhaseTable->getItem(row, 1)->setJustify(FXTableItem::LEFT);
1078  }
1079  myPhaseTable->fitColumnsToContents(0, cols);
1080  myPhaseTable->setColumnText(colDuration, "dur");
1081  if (colMinDur >= 0) {
1082  myPhaseTable->setColumnText(colMinDur, "min");
1083  myPhaseTable->setColumnText(colMaxDur, "max");
1084  myPhaseTable->setColumnWidth(colMinDur, MAX2(myPhaseTable->getColumnWidth(colMinDur), 30));
1085  myPhaseTable->setColumnWidth(colMaxDur, MAX2(myPhaseTable->getColumnWidth(colMaxDur), 35));
1086  }
1087  myPhaseTable->setColumnText(colState, "state");
1088  myPhaseTable->setColumnText(colNext, "nxt");
1089  myPhaseTable->setColumnText(colName, "name");
1090  myPhaseTable->setColumnWidth(colNext, MAX2(myPhaseTable->getColumnWidth(colNext), 30));
1091  myPhaseTable->setColumnWidth(colName, MAX2(myPhaseTable->getColumnWidth(colName), 45));
1092 
1093  myPhaseTable->setHeight((int)phases.size() * 21 + 21); // experimental
1094  myPhaseTable->setCurrentItem(index, 0);
1095  myPhaseTable->selectRow(index, true);
1096  myPhaseTable->show();
1097  myPhaseTable->setFocus();
1098  myTableScroll->setHeight(myPhaseTable->getHeight() + 15);
1099 
1100  // neither my myPhaseTable->getWidth nor getDefaultWidth return the sum of column widths
1101  // however, the scroll pane uses getDefaultWidth to determine the
1102  // horizontal scrolling area which can only be changed via
1103  // getDefColumnWidth, hence the baroque work-around
1104 
1105  int neededWidth = 0;
1106  for (int i = 0; i < cols; i++) {
1107  neededWidth += myPhaseTable->getColumnWidth(i);
1108  }
1109  myPhaseTable->setDefColumnWidth(neededWidth / cols);
1110  }
1111  update();
1112 }
1113 
1114 
1115 void
1117  myCycleDuration->show();
1118 }
1119 
1120 
1121 void
1123  myCycleDuration->hide();
1124 }
1125 
1126 void
1128  SUMOTime cycleDuration = 0;
1129  for (auto it : myTLSEditorParent->getPhases()) {
1130  cycleDuration += it.duration;
1131  }
1132  std::string text = "Cycle time: " + toString(STEPS2TIME(cycleDuration));
1133  myCycleDuration->setText(text.c_str());
1134 }
1135 
1136 // ---------------------------------------------------------------------------
1137 // GNETLSEditorFrame::TLSModifications - methods
1138 // ---------------------------------------------------------------------------
1139 
1141  FXGroupBox(TLSEditorParent->myContentFrame, "Modifications", GUIDesignGroupBoxFrame),
1142  myTLSEditorParent(TLSEditorParent),
1143  myHaveModifications(false) {
1144  // create save modifications button
1145  mySaveModificationsButtons = new FXButton(this, "Save\t\tSave program modifications (Enter)",
1147  // create discard modifications buttons
1148  myDiscardModificationsButtons = new FXButton(this, "Cancel\t\tDiscard program modifications (Esc)",
1150  // show TLSModifications
1151  show();
1152 }
1153 
1154 
1156 
1157 
1158 bool
1160  return myHaveModifications;
1161 }
1162 
1163 
1164 void
1166  myHaveModifications = value;
1167 }
1168 
1169 // ---------------------------------------------------------------------------
1170 // GNETLSEditorFrame::TLSFile - methods
1171 // ---------------------------------------------------------------------------
1172 
1174  FXGroupBox(TLSEditorParent->myContentFrame, "TLS Program", GUIDesignGroupBoxFrame),
1175  myTLSEditorParent(TLSEditorParent) {
1176  // create create tlDef button
1177  myLoadTLSProgramButton = new FXButton(this, "Load TLS Program", nullptr, this, MID_GNE_TLSFRAME_LOAD_PROGRAM, GUIDesignButton);
1178  // create create tlDef button
1179  mySaveTLSProgramButton = new FXButton(this, "Save TLS Program", nullptr, this, MID_GNE_TLSFRAME_SAVE_PROGRAM, GUIDesignButton);
1180  // show TLSFile
1181  show();
1182 }
1183 
1184 
1186 
1187 
1188 long
1190  FXFileDialog opendialog(this, "Load TLS Program");
1191  opendialog.setIcon(GUIIconSubSys::getIcon(ICON_MODETLS));
1192  opendialog.setSelectMode(SELECTFILE_EXISTING);
1193  opendialog.setPatternList("*.xml");
1194  if (gCurrentFolder.length() != 0) {
1195  opendialog.setDirectory(gCurrentFolder);
1196  }
1197  if (opendialog.execute()) {
1198  // run parser
1199  NBTrafficLightLogicCont tmpTLLCont;;
1200  NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myTLSEditorParent->myViewNet->getNet()->getEdgeCont(), true);
1201  tmpTLLCont.insert(myTLSEditorParent->myEditedDef);
1202  XMLSubSys::runParser(tllHandler, opendialog.getFilename().text());
1203 
1204  NBLoadedSUMOTLDef* newDefSameProgram = nullptr;
1205  std::set<NBLoadedSUMOTLDef*> newDefsOtherProgram;
1206  for (auto item : tmpTLLCont.getPrograms(myTLSEditorParent->myEditedDef->getID())) {
1207  if (item.second != myTLSEditorParent->myEditedDef) {
1208  NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(item.second);
1209  if (item.first == myTLSEditorParent->myEditedDef->getProgramID()) {
1210  newDefSameProgram = sdef;
1211  } else {
1212  newDefsOtherProgram.insert(sdef);
1213  }
1214  }
1215  }
1216  const int newPrograms = (int)newDefsOtherProgram.size();
1217  if (newPrograms > 0 || newDefSameProgram != nullptr) {
1218  std::vector<NBNode*> nodes = myTLSEditorParent->myEditedDef->getNodes();
1219  for (auto newProg : newDefsOtherProgram) {
1220  for (auto it_node : nodes) {
1221  GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->retrieveJunction(it_node->getID());
1222  myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newProg, true), true);
1223  }
1224  }
1225  if (newPrograms > 0) {
1226  WRITE_MESSAGE("Loaded " + toString(newPrograms) + " new programs for tlLogic '" + myTLSEditorParent->myEditedDef->getID() + "'");
1227  }
1228  if (newDefSameProgram != nullptr) {
1229  // replace old program when loading the same program ID
1230  myTLSEditorParent->myEditedDef = newDefSameProgram;
1231  WRITE_MESSAGE("Updated program '" + newDefSameProgram->getProgramID() + "' for tlLogic '" + myTLSEditorParent->myEditedDef->getID() + "'");
1232  }
1233  } else {
1234  myTLSEditorParent->getViewNet()->setStatusBarText("No programs found for traffic light '" + myTLSEditorParent->myEditedDef->getID() + "'");
1235  }
1236 
1237  // clean up temporary container to avoid deletion of defs when it's destruct is called
1238  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
1239  tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
1240  }
1241 
1244  }
1245  return 0;
1246 }
1247 
1248 
1249 long
1251  FXString file = MFXUtils::getFilename2Write(this,
1252  "Save TLS Program as", ".xml",
1254  gCurrentFolder);
1255  if (file == "") {
1256  return 1;
1257  }
1258  OutputDevice& device = OutputDevice::getDevice(file.text());
1259 
1260  // save program
1261  device.writeXMLHeader("additional", "additional_file.xsd");
1262  device.openTag(SUMO_TAG_TLLOGIC);
1267  // write the phases
1268  const bool varPhaseLength = myTLSEditorParent->myEditedDef->getLogic()->getType() != TLTYPE_STATIC;
1269  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
1270  for (auto j : phases) {
1271  device.openTag(SUMO_TAG_PHASE);
1272  device.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(j.duration));
1273  device.writeAttr(SUMO_ATTR_STATE, j.state);
1274  if (varPhaseLength) {
1276  device.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(j.minDur));
1277  }
1279  device.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(j.maxDur));
1280  }
1281  }
1282  device.closeTag();
1283  }
1284  device.close();
1285  return 1;
1286 }
1287 
1288 
1289 std::string
1291  double time = STEPS2TIME(steps);
1292  if (time == std::floor(time)) {
1293  return toString(int(time));
1294  } else {
1295  return toString(time);
1296  }
1297 }
1298 
1299 long
1300 GNETLSEditorFrame::TLSFile::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
1301  const bool enable = myTLSEditorParent->myTLSAttributes->getNumberOfTLSDefinitions() > 0;
1302  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
1303  return 1;
1304 }
1305 /****************************************************************************/
int NUM_POINTS
GNETLSEditorFrame::TLSModifications * myTLSModifications
modul for load/Save TLS Modifications
TLIndexMap myInternalLanes
FXLabel * myLabelJunctionStatus
label for junction status
void setPhaseNext(int phaseIndex, const std::vector< int > &next)
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
The link has green light, may pass.
long onCmdGuess(FXObject *, FXSelector, void *)
Called when the user presses the button Guess.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
std::vector< GNELane * > retrieveLanes(bool onlySelected=false)
return all lanes
Definition: GNENet.cpp:1164
void close()
Closes the device and removes it from the dictionary.
TLSDefinition(GNETLSEditorFrame *TLSEditorParent)
constructor
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:184
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:233
long long int SUMOTime
Definition: SUMOTime.h:35
FXLabel * myCycleDuration
label with the cycle duration
long onUpdNeedsDefAndPhase(FXObject *, FXSelector, void *)
Called when occurs an update of needs definition an dphase.
long onCmdPhaseDelete(FXObject *, FXSelector, void *)
Called when the user deletes a Phase.
GNETLSEditorFrame::TLSPhases * myTLSPhases
modul for TLS Phases
bool removeProgram(const std::string id, const std::string programID, bool del=true)
Removes a program of a logic definition from the dictionary.
SUMOTime getOffset() const
Returns the offset of first switch.
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
bool parseTLSPrograms(const std::string &file)
parse TLS Programs from a file
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
long onCmdDefCreate(FXObject *, FXSelector, void *)
Called when the user creates a TLS.
FXButton * myDiscardModificationsButtons
button for cancel modifications
void setPhaseMaxDuration(int phaseIndex, SUMOTime duration)
FXLabel * myOffsetLabel
offset label
long onCmdSaveTLSProgram(FXObject *, FXSelector, void *)
save TLS Programm to an additional file
cleanup unused states
Definition: GUIAppEnum.h:755
void update() const
Mark the entire GNEViewNet to be repainted later.
Definition: GNEViewNet.cpp:292
void setOffset(SUMOTime offset)
Sets the offset of this tls.
int getNumLinks()
Returns the number of participating links.
A loaded (complete) traffic light logic.
FXFont * myTableFont
font for the phase table
GNEJunction * getCurrentJunction() const
get current modified junction
void setPhaseState(int phaseIndex, int tlIndex, LinkState linkState)
Modifies the state for an existing phase (used by NETEDIT)
A container for traffic light definitions and built programs.
A SUMO-compliant built logic for a traffic light.
#define GUIDesignTableLimitedHeight
design for table extended over frame but with limited Height
Definition: GUIDesigns.h:477
#define GUIDesignComboBoxAttribute
Combo box static (cannot be edited) extended over the matrix column.
Definition: GUIDesigns.h:227
The link has green light, has to brake.
long onCmdPhaseSwitch(FXObject *, FXSelector, void *)
Called when the user switchs a Phase.
TrafficLightType getType() const
get the algorithm type (static etc..)
FXTextField * myTextFieldJunctionStatus
text field for junction status
selected junction von TLS
Definition: GUIAppEnum.h:721
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
bool fixedDuration() const
whether the current traffic light uses fixed phase durations
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
void removeAdditionalGLObject(GUIGlObject *o)
Removes an additional object (detector/shape/trigger) from being visualised.
Definition: SUMORTree.h:157
select phase thable
Definition: GUIAppEnum.h:741
The base class for traffic light logic definitions.
void setPhaseMinDuration(int phaseIndex, SUMOTime duration)
This is a dead end link.
FXComboBox * myProgramComboBox
the comboBox for selecting the tl-definition to edit
T MAX2(T a, T b)
Definition: StdDefs.h:80
bool isTLSSaved()
check if modifications in TLS was saved
static const SUMOTime UNSPECIFIED_DURATION
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
void editJunction(GNEJunction *junction)
edits the traffic light for the given junction
long onCmdLoadTLSProgram(FXObject *, FXSelector, void *)
void initPhaseTable(int index=0)
initialies the phase table
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:73
PositionVector reverse() const
reverse position vector
FXString gCurrentFolder
The folder used as last.
int computeBrakingTime(double minDecel) const
Computes the time vehicles may need to brake.
const std::string & getProgramID() const
Returns the ProgramID.
add off to TLS
Definition: GUIAppEnum.h:739
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
definition related controls
Definition: GUIAppEnum.h:727
FXButton * mySaveTLSProgramButton
button for save TLS Programs
maximum duration of a phase
const std::string & getID() const
Returns the id.
Definition: Named.h:77
#define TIME2STEPS(x)
Definition: SUMOTime.h:59
void handleMultiChange(GNELane *lane, FXObject *obj, FXSelector sel, void *data)
update phase definition for the current traffic light and phase
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
The definition of a single phase of the logic.
FXLabel * myProgramLabel
program label
TLSJunction(GNETLSEditorFrame *TLSEditorParent)
constructor
long onUpdNeedsDef(FXObject *, FXSelector, void *)
Called when occurs an update of needs definition.
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:113
A RT-tree for efficient storing of SUMO&#39;s GL-objects.
Definition: SUMORTree.h:69
long onCmdCleanup(FXObject *, FXSelector, void *)
Called when the user cleans up states.
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extension, FXIcon *icon, FXString &currentFolder)
Returns the file name to write.
Definition: MFXUtils.cpp:84
bool myHaveModifications
whether the current tls was modified
LinkState getLinkState() const
whether link state has been modfied
long onCmdDefDelete(FXObject *, FXSelector, void *)
Called when the user deletes a TLS.
GNEViewNet * getViewNet() const
get view net
Definition: GNEFrame.cpp:133
long onCmdDefOffset(FXObject *, FXSelector, void *)
Called when the user changes the offset of a TLS.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
FXButton * myDeleteSelectedPhaseButton
delete phase button
long onCmdDefSwitch(FXObject *, FXSelector, void *)
Called when the user switchs a TLS.
long onCmdDefAddOff(FXObject *, FXSelector, void *)
Called when the user adds a OFF.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
delete phase thable
Definition: GUIAppEnum.h:745
SUMOTime duration
The duration of the phase in s.
bool changeAllPhases() const
change all phases
Definition: GNEViewNet.cpp:500
GNEViewNet * myViewNet
View Net.
Definition: GNEFrame.h:120
The state of a link.
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
FXScrollWindow * myTableScroll
window for oversized phase tables
void clearTLSAttributes()
clear TLS attributes
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:317
std::string getAttribute(SumoXMLAttr key) const
GNEUndoList * getUndoList() const
get the undoList object
Definition: GNEViewNet.cpp:933
FXTable * getPhaseTable() const
get phase table
void hideCycleDuration()
hide cycle duration
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditorParent
FXTextField * myNameTextField
name text field
#define GUIDesignTextField
Definition: GUIDesigns.h:34
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
FXVerticalFrame * myContentFrame
Vertical frame that holds all widgets of frame.
Definition: GNEFrame.h:123
void initTLSAttributes(GNEJunction *junction)
initializes the definitions and corresponding listbox
long onCmdCancel(FXObject *, FXSelector, void *)
Called when the user presses the Cancel-button.
GNEEdge & getParentEdge()
Returns underlying parent edge.
Definition: GNELane.cpp:1292
NBEdgeCont & getEdgeCont()
returns the NBEdgeCont of the underlying netbuilder
Definition: GNENet.cpp:2103
void addStep(SUMOTime duration, const std::string &state, const std::vector< int > &next=std::vector< int >(), const std::string &name="", int index=-1)
Adds a phase to the logic.
NBTrafficLightDefinition * getCurrentTLSDefinition() const
get current definition
GNETLSEditorFrame::TLSJunction * myTLSJunction
modul for TLS Junction
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise, the sub-group will be added as a new command into parent group. A matching begin() must have been called previously.
Definition: GNEUndoList.cpp:80
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true)
get junction by id
Definition: GNENet.cpp:1001
TLSAttributes(GNETLSEditorFrame *TLSEditorParent)
constructor
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames ...
Definition: GUIDesigns.h:289
A list of positions.
bool controlsEdge(GNEEdge &edge) const
whether the given edge is controlled by the currently edited tlDef
GNETLSEditorFrame::TLSAttributes * myTLSAttributes
modul for TLS attributes
long onUpdDefCreate(FXObject *, FXSelector, void *)
Called when occurs an update of create definition.
void buildIinternalLanes(NBTrafficLightDefinition *tlDef)
builds internal lanes for the given tlDef
std::vector< int > next
next phase indices or empty list
replace program with a newly guessed program
Definition: GUIAppEnum.h:725
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
cleanup unused states
Definition: GUIAppEnum.h:747
TLSPhases(GNETLSEditorFrame *TLSEditorParent)
constructor
bool checkHaveModifications() const
check if current TLS was modified
long onCmdPhaseEdit(FXObject *, FXSelector, void *)
Called when the user edits a Phase.
#define STEPS2TIME(x)
Definition: SUMOTime.h:57
std::string state
The state definition.
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
void computeJunction(GNEJunction *junction)
trigger recomputation of junction shape and logic param[in] window The window to inform about delay ...
Definition: GNENet.cpp:1502
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:840
~GNETLSEditorFrame()
Destructor.
void handleChange(GNEInternalLane *lane)
update phase definition for the current traffic light and phase
T MIN2(T a, T b)
Definition: StdDefs.h:74
int getTLIndex() const
get Traffic Light index
NBTrafficLightLogic * getLogic()
Returns the internal logic.
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
FXDEFMAP(GNETLSEditorFrame) GNETLSEditorFrameMap[]
void setPhaseName(int phaseIndex, const std::string &name)
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:246
const std::string & getProgramID() const
Returns the ProgramID.
void p_abort()
reverts and discards ALL active command groups
Definition: GNEUndoList.cpp:94
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
SUMORTree & getVisualisationSpeedUp()
Returns the RTree used for visualisation speed-up.
Definition: GNENet.cpp:302
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
long onCmdAddUnused(FXObject *, FXSelector, void *)
Called when the user cleans up states.
FXTable * myPhaseTable
table for selecting and rearranging phases and for changing duration
static SUMOTime getSUMOTime(const FXString &string)
converts to SUMOTime
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:50
int getNumberOfTLSDefinitions() const
get number of definitions
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:58
static bool canParse(const std::string &string)
true if a value of type T can be parsed from string
long onUpdDefSwitch(FXObject *, FXSelector, void *)
Called when occurs an update of switch definition.
create phase thable
Definition: GUIAppEnum.h:743
#define GUIDesignButton
Definition: GUIDesigns.h:66
GNEJunction * myCurrentJunction
the junction of the tls is being modified
static std::string varDurString(SUMOTime dur)
convert duration (potentially undefined) to string
std::string name
option phase name
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:47
FXButton * myLoadTLSProgramButton
button for load TLS Programs
double length() const
Returns the length.
void showCycleDuration()
show cycle duration
virtual void show()
show Frame
Definition: GNEFrame.cpp:108
void updateCycleDuration()
recomputes cycle duration and updates label
int getNumberOfPrograms() const
get number of programs
std::vector< GNEEdge * > retrieveEdges(bool onlySelected=false)
return all edges
Definition: GNENet.cpp:1151
The link has yellow light, may pass.
void addAdditionalGLObject(GUIGlObject *o)
Adds an additional object (detector/shape/trigger) for visualisation.
Definition: SUMORTree.h:127
#define GUIDesignGroupBoxFrame
Group box design extended over frame.
Definition: GUIDesigns.h:255
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
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:322
TrafficLightType getType() const
get the algorithm type (static etc..)
long onCmdOK(FXObject *, FXSelector, void *)
SUMOTime getOffset() const
get current offset in SUMOTIme
void updateJunctionDescription() const
update descrition
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
long onCmdDefSubRename(FXObject *, FXSelector, void *)
Called when the user sub-renames a TLS.
The link has red light (must brake)
A storage for options typed value containers)
Definition: OptionsCont.h:90
void setOffset(SUMOTime offset)
set new offset
Ok-button pressed.
Definition: GUIAppEnum.h:213
const std::vector< NBTrafficLightLogic::PhaseDefinition > & getPhases()
the phase of the current traffic light
void setPhaseDuration(int phaseIndex, SUMOTime duration)
Modifies the duration for an existing phase (used by NETEDIT)
Cancel-button pressed.
Definition: GUIAppEnum.h:215
GNENet * getNet() const
get the net object
Definition: GNEViewNet.cpp:927
#define GUIDesignTextFieldReal
text field extended over Frame with thick frame and limited to doubles/floats
Definition: GUIDesigns.h:40
long onCmdPhaseCreate(FXObject *, FXSelector, void *)
Called when the user creates a Phase.
FXButton * mySaveModificationsButtons
button for save modifications
Represents a single node (junction) during network building.
Definition: NBNode.h:68
long onUpdNeedsDef(FXObject *, FXSelector, void *)
enable buttons, only when a tlLogic is being edited
void setHaveModifications(bool value)
set if current TLS was modified
void setCurrentJunction(GNEJunction *junction)
set current junction
A definition of a pedestrian crossing.
Definition: NBNode.h:132
void setStatusBarText(const std::string &text)
set staturBar text
Definition: GNEViewNet.cpp:482
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setStateLength(int numLinks, LinkState fill=LINKSTATE_TL_RED)
std::string writeSUMOTime(SUMOTime steps)
convert SUMOTime into string
Importer for edge connections stored in XML.
a traffic light logic
#define GUIDesignLabelLeft
Definition: GUIDesigns.h:165
The link has yellow light, has to brake anyway.
FXLabel * myLabelJunctionID
label for junction ID
long onCmdDefRename(FXObject *, FXSelector, void *)
Called when the user renames a TLS.
long onUpdModified(FXObject *, FXSelector, void *)
Called when occurs an update of modified.
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
FXButton * myInsertDuplicateButton
insert new phase button
#define GUIDesignLabelAttribute
label extended over the matrix column with thick frame and height of 23
Definition: GUIDesigns.h:186
FXButton * myNewTLProgram
button for create new Traffic light program
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:240
FXTextField * myOffsetTextField
the control for modifying offset
FXButton * myDeleteTLProgram
button for delete traffic light program
NBNode * getNBNode() const
Return net build node.
NBTrafficLightLogic * getLogic(const std::string &id, const std::string &programID) const
Returns the computed logic for the given name.
FXTextField * myTextFieldJunctionID
text field for junction ID
mark unused states
Definition: GUIAppEnum.h:751
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:2097
NBLoadedSUMOTLDef * myEditedDef
the traffic light definition being edited
static FXIcon * getIcon(GUIIcon which)
returns a icon previously defined in the enum GUIIcon
std::vector< NBTrafficLightDefinition * > myTLSDefinitions
the list of Definitions for the current junction
a single phase description
void cleanup()
cleans up previous lanes
TLSModifications(GNETLSEditorFrame *TLSEditorParent)
constructor
switch between programs
Definition: GUIAppEnum.h:729
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.