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-2022 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 <netedit/GNENet.h>
24 #include <netedit/GNEUndoList.h>
25 #include <netedit/GNEViewNet.h>
33 #include <utils/xml/XMLSubSys.h>
34 
35 #include "GNETLSEditorFrame.h"
36 
37 // ===========================================================================
38 // FOX callback mapping
39 // ===========================================================================
40 
41 FXDEFMAP(GNETLSEditorFrame) GNETLSEditorFrameMap[] = {
42  FXMAPFUNC(SEL_COMMAND, MID_CANCEL, GNETLSEditorFrame::onCmdCancel),
43  FXMAPFUNC(SEL_UPDATE, MID_CANCEL, GNETLSEditorFrame::onUpdModified),
44  FXMAPFUNC(SEL_COMMAND, MID_OK, GNETLSEditorFrame::onCmdOK),
45  FXMAPFUNC(SEL_UPDATE, MID_OK, GNETLSEditorFrame::onUpdModified),
77 };
78 
84 };
85 
86 // Object implementation
87 FXIMPLEMENT(GNETLSEditorFrame, FXVerticalFrame, GNETLSEditorFrameMap, ARRAYNUMBER(GNETLSEditorFrameMap))
88 FXIMPLEMENT(GNETLSEditorFrame::TLSFile, FXGroupBoxModule, TLSFileMap, ARRAYNUMBER(TLSFileMap))
89 
90 
91 // ===========================================================================
92 // method definitions
93 // ===========================================================================
94 
95 GNETLSEditorFrame::GNETLSEditorFrame(FXHorizontalFrame* horizontalFrameParent, GNEViewNet* viewNet):
96  GNEFrame(horizontalFrameParent, viewNet, "Edit Traffic Light"),
97  myEditedDef(nullptr) {
98 
99  // Create Overlapped Inspection modul
100  myOverlappedInspection = new GNEFrameModules::OverlappedInspection(this, SUMO_TAG_JUNCTION);
101 
102  // create TLSJunction modul
103  myTLSJunction = new GNETLSEditorFrame::TLSJunction(this);
104 
105  // create TLSDefinition modul
106  myTLSDefinition = new GNETLSEditorFrame::TLSDefinition(this);
107 
108  // create TLSAttributes modul
109  myTLSAttributes = new GNETLSEditorFrame::TLSAttributes(this);
110 
111  // create TLSModifications modul
112  myTLSModifications = new GNETLSEditorFrame::TLSModifications(this);
113 
114  // create TLSPhases modul
115  myTLSPhases = new GNETLSEditorFrame::TLSPhases(this);
116 
117  // create TLSFile modul
118  myTLSFile = new GNETLSEditorFrame::TLSFile(this);
119 
120  // "Add 'off' program"
121  /*
122  new FXButton(myContentFrame, "Add \"Off\"-Program\t\tAdds a program for switching off this traffic light",
123  0, this, MID_GNE_TLSFRAME_ADDOFF, GUIDesignButton);
124  */
125 }
126 
127 
129  cleanup();
130 }
131 
132 
133 void
135  // hide myOverlappedInspection
137  GNEFrame::show();
138 }
139 
140 void
141 GNETLSEditorFrame::editTLS(const Position& clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor& objectsUnderCursor) {
142  // first check if in objectsUnderCursor there is a junction
143  if (objectsUnderCursor.getJunctionFront()) {
144  // show objects under cursor
145  myOverlappedInspection->showOverlappedInspection(objectsUnderCursor, clickedPosition);
146  // hide if we inspect only one junction
149  }
150  // set junction
151  editJunction(objectsUnderCursor.getJunctionFront());
152  } else {
153  myViewNet->setStatusBarText("Click over a junction to edit a TLS");
154  }
155 }
156 
157 
158 bool
161  // write warning if netedit is running in testing mode
162  WRITE_DEBUG("Opening question FXMessageBox 'save TLS'");
163  // open question box
164  FXuint answer = FXMessageBox::question(this, MBOX_YES_NO_CANCEL,
165  "Save TLS Changes", "%s",
166  "There is unsaved changes in current edited traffic light.\nDo you want to save it before changing mode?");
167  if (answer == MBOX_CLICKED_YES) { //1:yes, 2:no, 4:esc/cancel
168  // write warning if netedit is running in testing mode
169  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'YES'");
170  // save modifications
171  onCmdOK(nullptr, 0, nullptr);
172  return true;
173  } else if (answer == MBOX_CLICKED_NO) {
174  // write warning if netedit is running in testing mode
175  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'No'");
176  // cancel modifications
177  onCmdCancel(nullptr, 0, nullptr);
178  return true;
179  } else {
180  // write warning if netedit is running in testing mode
181  WRITE_DEBUG("Closed FXMessageBox 'save TLS' with 'Cancel'");
182  // abort changing mode
183  return false;
184  }
185  } else {
186  return true;
187  }
188 }
189 
190 
191 bool
192 GNETLSEditorFrame::parseTLSPrograms(const std::string& file) {
194  NBTrafficLightLogicCont tmpTLLCont;
195  NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myViewNet->getNet()->getEdgeCont());
196  // existing definitions must be available to update their programs
197  std::set<NBTrafficLightDefinition*> origDefs;
198  for (NBTrafficLightDefinition* def : tllCont.getDefinitions()) {
199  // make a copy of every program
200  NBTrafficLightLogic* logic = tllCont.getLogic(def->getID(), def->getProgramID());
201  if (logic != nullptr) {
202  NBTrafficLightDefinition* copy = new NBLoadedSUMOTLDef(*def, *logic);
203  std::vector<NBNode*> nodes = def->getNodes();
204  for (auto it_node : nodes) {
205  GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
206  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, false, false), true);
207  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, copy, true), true);
208  }
209  tmpTLLCont.insert(copy);
210  origDefs.insert(copy);
211  } else {
212  WRITE_WARNING("tlLogic '" + def->getID() + "', program '" + def->getProgramID() + "' could not be built");
213  }
214  }
215  //std::cout << " initialized tmpCont with " << origDefs.size() << " defs\n";
216  XMLSubSys::runParser(tllHandler, file);
217 
218  std::vector<NBLoadedSUMOTLDef*> loadedTLS;
219  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
220  NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
221  if (sdef != nullptr) {
222  loadedTLS.push_back(sdef);
223  }
224  }
225  myViewNet->setStatusBarText("Loaded " + toString(loadedTLS.size()) + " programs");
226  for (auto def : loadedTLS) {
227  if (origDefs.count(def) != 0) {
228  // already add to undolist before
229  //std::cout << " skip " << def->getDescription() << "\n";
230  continue;
231  }
232  std::vector<NBNode*> nodes = def->getNodes();
233  //std::cout << " add " << def->getDescription() << " for nodes=" << toString(nodes) << "\n";
234  for (auto it_node : nodes) {
235  GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
236  //myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, false), true);
237  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, true), true);
238  }
239  }
240  // clean up temporary container to avoid deletion of defs when it's destruct is called
241  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
242  tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
243  }
244  return true;
245 }
246 
247 
248 long
249 GNETLSEditorFrame::onCmdCancel(FXObject*, FXSelector, void*) {
250  if (myTLSJunction->getCurrentJunction() != nullptr) {
252  cleanup();
254  }
255  return 1;
256 }
257 
258 
259 long
260 GNETLSEditorFrame::onCmdOK(FXObject*, FXSelector, void*) {
261  if (myTLSJunction->getCurrentJunction() != nullptr) {
264  std::vector<NBNode*> nodes = oldDefinition->getNodes();
265  for (auto it : nodes) {
266  GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it->getID());
267  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, oldDefinition, false), true);
268  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myEditedDef, true), true);
269  }
270  myEditedDef = nullptr;
271  myViewNet->getUndoList()->end();
272  cleanup();
274  } else {
275  onCmdCancel(nullptr, 0, nullptr);
276  }
277  }
278  return 1;
279 }
280 
281 
282 long
283 GNETLSEditorFrame::onCmdDefCreate(FXObject*, FXSelector, void*) {
285  // get current TLS program id
286  const auto currentTLS = myTLSAttributes->getCurrentTLSProgramID();
287  // abort because we onCmdOk assumes we wish to save an edited definition
288  onCmdCancel(nullptr, 0, nullptr);
289  // check that current junction has two or more edges
290  if ((junction->getGNEIncomingEdges().size() > 0) && (junction->getGNEOutgoingEdges().size() > 0)) {
293  } else {
294  if (junction->getNBNode()->isTLControlled()) {
295  // use existing traffic light as template for type, signal groups, controlled nodes etc
296  NBTrafficLightDefinition* tpl = nullptr;
297  for (const auto& TLS : junction->getNBNode()->getControllingTLS()) {
298  if (TLS->getProgramID() == currentTLS) {
299  tpl = TLS;
300  }
301  }
302  if (tpl == nullptr) {
303  tpl = *junction->getNBNode()->getControllingTLS().begin();
304  }
306  NBLoadedSUMOTLDef* newDef = new NBLoadedSUMOTLDef(*tpl, *newLogic);
307  delete newLogic;
308  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, newDef, true, true), true);
309  } else {
310  // for some reason the traffic light was not built, try again
311  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, nullptr, true, true), true);
312  }
313  }
314  editJunction(junction);
315  } else {
316  // write warning if netedit is running in testing mode
317  WRITE_DEBUG("Opening warning FXMessageBox 'invalid TLS'");
318  // open question box
319  FXMessageBox::warning(this, MBOX_OK,
320  "TLS cannot be created", "%s",
321  "Traffic Light cannot be created because junction must have\n at least one incoming edge and one outgoing edge.");
322  // write warning if netedit is running in testing mode
323  WRITE_DEBUG("Closed FXMessageBox 'invalid TLS'");
324  }
325  return 1;
326 }
327 
328 
329 long
330 GNETLSEditorFrame::onCmdDefDelete(FXObject*, FXSelector, void*) {
332  const bool changeType = myTLSAttributes->getNumberOfTLSDefinitions() == 1;
334  onCmdCancel(nullptr, 0, nullptr); // abort because onCmdOk assumes we wish to save an edited definition
335  if (changeType) {
337  } else {
338  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, tlDef, false), true);
339  }
340  return 1;
341 }
342 
343 
344 long
345 GNETLSEditorFrame::onCmdDefSwitch(FXObject*, FXSelector, void*) {
346  assert(myTLSJunction->getCurrentJunction() != 0);
349  // logic may not have been recomputed yet. recompute to be sure
352  NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
353  if (tllogic != nullptr) {
354  // now we can be sure that the tlDef is up to date (i.e. re-guessed)
355  buildInternalLanes(tlDef);
356  // create working copy from original def
357  delete myEditedDef;
358  myEditedDef = new NBLoadedSUMOTLDef(*tlDef, *tllogic);
364  } else {
365  // tlDef has no valid logic (probably because id does not control any links
366  onCmdCancel(nullptr, 0, nullptr);
367  myViewNet->setStatusBarText("Traffic light does not control any links");
368  }
369  return 1;
370 }
371 
372 
373 long
374 GNETLSEditorFrame::onUpdDefSwitch(FXObject* o, FXSelector, void*) {
376  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
377  return 1;
378 }
379 
380 
381 long
382 GNETLSEditorFrame::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
383  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0;
384  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
385  return 1;
386 }
387 
388 
389 long
390 GNETLSEditorFrame::onUpdNeedsDefAndPhase(FXObject* o, FXSelector, void*) {
391  // do not delete the last phase
392  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0 && myTLSPhases->getPhaseTable()->getNumRows() > 1;
393  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
394  return 1;
395 }
396 
397 
398 long
399 GNETLSEditorFrame::onUpdDefCreate(FXObject* o, FXSelector, void*) {
401  const bool enable = junction != nullptr && !myTLSModifications->checkHaveModifications();
402  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
403  const bool copy = junction != nullptr && junction->getNBNode()->isTLControlled();
404  static_cast<FXButton*>(o)->setText(copy ? "Copy" : "Create");
405  return 1;
406 }
407 
408 
409 long
410 GNETLSEditorFrame::onUpdModified(FXObject* o, FXSelector, void*) {
412  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
413  return 1;
414 }
415 
416 
417 
418 long
419 GNETLSEditorFrame::onCmdSetOffset(FXObject*, FXSelector, void*) {
423  }
424  return 1;
425 }
426 
427 
428 long
429 GNETLSEditorFrame::onCmdSetParameters(FXObject*, FXSelector, void*) {
433  }
434  return 1;
435 }
436 
437 
438 long
439 GNETLSEditorFrame::onCmdDefRename(FXObject*, FXSelector, void*) {
440  return 1;
441 }
442 
443 
444 long
445 GNETLSEditorFrame::onCmdDefSubRename(FXObject*, FXSelector, void*) {
446  return 1;
447 }
448 
449 
450 long
451 GNETLSEditorFrame::onCmdDefAddOff(FXObject*, FXSelector, void*) {
452  return 1;
453 }
454 
455 
456 long
457 GNETLSEditorFrame::onCmdGuess(FXObject*, FXSelector, void*) {
458  return 1;
459 }
460 
461 
462 long
463 GNETLSEditorFrame::onCmdPhaseSwitch(FXObject*, FXSelector, void*) {
464  const int index = myTLSPhases->getPhaseTable()->getCurrentRow();
465  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[index];
466  myTLSPhases->getPhaseTable()->selectRow(index);
467  // need not hold since links could have been deleted somewhere else and indices may be reused
468  // assert(phase.state.size() == myInternalLanes.size());
469  for (auto it : myInternalLanes) {
470  int tlIndex = it.first;
471  std::vector<GNEInternalLane*> lanes = it.second;
473  if (tlIndex >= 0 && tlIndex < (int)phase.state.size()) {
474  state = (LinkState)phase.state[tlIndex];
475  }
476  for (auto it_lane : lanes) {
477  it_lane->setLinkState(state);
478  }
479  }
481  return 1;
482 }
483 
484 
485 bool
487  assert(myEditedDef != nullptr);
489 }
490 
491 
492 void
494  editJunction(dynamic_cast<GNEJunction*>(AC));
495 }
496 
497 
498 long
499 GNETLSEditorFrame::onCmdPhaseCreate(FXObject*, FXSelector, void*) {
501  // allows insertion at first position by deselecting via arrow keys
502  int newIndex = myTLSPhases->getPhaseTable()->getSelStartRow() + 1;
503  int oldIndex = MAX2(0, myTLSPhases->getPhaseTable()->getSelStartRow());
504  // copy current row
505  SUMOTime duration = getSUMOTime(myTLSPhases->getPhaseTable()->getItemText(oldIndex, 0));
506  const std::string oldState = myTLSPhases->getPhaseTable()->getItemText(oldIndex, fixedDuration() ? 1 : 3).text();
507  std::string state = oldState;
508 
509  std::set<int> crossingIndices;
510  for (NBNode* n : myEditedDef->getNodes()) {
511  for (NBNode::Crossing* c : n->getCrossings()) {
512  crossingIndices.insert(c->tlLinkIndex);
513  crossingIndices.insert(c->tlLinkIndex2);
514  }
515  }
516 
517  // smart adapations for new state
518  bool haveGreen = false;
519  bool haveYellow = false;
520  for (char c : state) {
522  haveGreen = true;
523  } else if (c == LINKSTATE_TL_YELLOW_MAJOR || c == LINKSTATE_TL_YELLOW_MINOR) {
524  haveYellow = true;
525  }
526  }
527  const OptionsCont& oc = OptionsCont::getOptions();
528  if (haveGreen && haveYellow) {
529  // guess left-mover state
530  duration = TIME2STEPS(oc.getInt("tls.left-green.time"));
531  for (int i = 0; i < (int)state.size(); i++) {
532  if (state[i] == LINKSTATE_TL_YELLOW_MAJOR || state[i] == LINKSTATE_TL_YELLOW_MINOR) {
533  state[i] = LINKSTATE_TL_RED;
534  } else if (state[i] == LINKSTATE_TL_GREEN_MINOR) {
535  state[i] = LINKSTATE_TL_GREEN_MAJOR;
536  }
537  }
538  } else if (haveGreen) {
539  // guess yellow state
541  duration = TIME2STEPS(myEditedDef->computeBrakingTime(oc.getFloat("tls.yellow.min-decel")));
542  for (int i = 0; i < (int)state.size(); i++) {
543  if (state[i] == LINKSTATE_TL_GREEN_MAJOR || state[i] == LINKSTATE_TL_GREEN_MINOR) {
544  if (crossingIndices.count(i) == 0) {
545  state[i] = LINKSTATE_TL_YELLOW_MINOR;
546  } else {
547  state[i] = LINKSTATE_TL_RED;
548  }
549  }
550  }
551  } else if (haveYellow) {
552  duration = TIME2STEPS(oc.isDefault("tls.allred.time") ? 2 : oc.getInt("tls.allred.time"));
553  // guess all-red state
554  for (int i = 0; i < (int)state.size(); i++) {
555  if (state[i] == LINKSTATE_TL_YELLOW_MAJOR || state[i] == LINKSTATE_TL_YELLOW_MINOR) {
556  state[i] = LINKSTATE_TL_RED;
557  }
558  }
559  }
560  // fix continuous green states
561  const int nextIndex = myTLSPhases->getPhaseTable()->getNumRows() > newIndex ? newIndex : 0;
562  const std::string state2 = myTLSPhases->getPhaseTable()->getItemText(nextIndex, fixedDuration() ? 1 : 3).text();
563  for (int i = 0; i < (int)state.size(); i++) {
564  if ((oldState[i] == LINKSTATE_TL_GREEN_MAJOR || oldState[i] == LINKSTATE_TL_GREEN_MINOR)
565  && (state2[i] == LINKSTATE_TL_GREEN_MAJOR || state2[i] == LINKSTATE_TL_GREEN_MINOR)) {
566  state[i] = oldState[i];
567  }
568  }
569 
570  myEditedDef->getLogic()->addStep(duration, state, std::vector<int>(), "", newIndex);
571  myTLSPhases->getPhaseTable()->setCurrentItem(newIndex, 0);
572  myTLSPhases->initPhaseTable(newIndex);
574  myTLSPhases->getPhaseTable()->setFocus();
575  return 1;
576 }
577 
578 
579 long
580 GNETLSEditorFrame::onCmdPhaseDelete(FXObject*, FXSelector, void*) {
582  const int newRow = MAX2((int)0, (int)myTLSPhases->getPhaseTable()->getCurrentRow() - 1);
583  myEditedDef->getLogic()->deletePhase(myTLSPhases->getPhaseTable()->getCurrentRow());
584  myTLSPhases->initPhaseTable(newRow);
586  myTLSPhases->getPhaseTable()->setFocus();
587  return 1;
588 }
589 
590 
591 long
592 GNETLSEditorFrame::onCmdCleanup(FXObject*, FXSelector, void*) {
596  myTLSPhases->getPhaseTable()->setFocus();
598  return 1;
599 }
600 
601 
602 long
603 GNETLSEditorFrame::onCmdAddUnused(FXObject*, FXSelector, void*) {
605  myEditedDef->getLogic()->getNumLinks() + 1);
608  myTLSPhases->getPhaseTable()->setFocus();
609  return 1;
610 }
611 
612 
613 long
614 GNETLSEditorFrame::onCmdGroupStates(FXObject*, FXSelector, void*) {
619  myTLSPhases->getPhaseTable()->setFocus();
620  return 1;
621 }
622 
623 
624 long
625 GNETLSEditorFrame::onCmdUngroupStates(FXObject*, FXSelector, void*) {
631  myTLSPhases->getPhaseTable()->setFocus();
632  return 1;
633 }
634 
635 
636 long
637 GNETLSEditorFrame::onUpdNeedsSingleDef(FXObject* o, FXSelector, void*) {
638  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() == 1;
639  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
640  return 1;
641 }
642 
643 
644 long
645 GNETLSEditorFrame::onUpdUngroupStates(FXObject* o, FXSelector, void*) {
646  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() == 1 && myEditedDef != nullptr && myEditedDef->usingSignalGroups();
647  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
648  return 1;
649 }
650 
651 
652 long
653 GNETLSEditorFrame::onCmdPhaseEdit(FXObject*, FXSelector, void* ptr) {
654  /* @note: there is a bug when copying/pasting rows: when this handler is
655  * called the value of the cell is not yet updated. This means you have to
656  * click inside the cell and hit enter to actually update the value */
657  FXTablePos* tp = (FXTablePos*)ptr;
658  FXString value = myTLSPhases->getPhaseTable()->getItemText(tp->row, tp->col);
659  const int colDuration = 0;
660  const int colMinDur = fixedDuration() ? -1 : 1;
661  const int colMaxDur = fixedDuration() ? -1 : 2;
662  const int colState = fixedDuration() ? 1 : 3;
663  const int colNext = fixedDuration() ? 2 : 4;
664  const int colName = fixedDuration() ? 3 : 5;
665  if (tp->col == colDuration) {
666  // duration edited
667  if (GNEAttributeCarrier::canParse<double>(value.text())) {
668  SUMOTime duration = getSUMOTime(value);
669  if (duration > 0) {
670  myEditedDef->getLogic()->setPhaseDuration(tp->row, duration);
673  return 1;
674  }
675  }
676  // input error, reset value
677  myTLSPhases->getPhaseTable()->setItemText(tp->row, colDuration, toString(STEPS2TIME(getPhases()[tp->row].duration)).c_str());
678  } else if (tp->col == colMinDur) {
679  // minDur edited
680  if (GNEAttributeCarrier::canParse<double>(value.text())) {
681  SUMOTime minDur = getSUMOTime(value);
682  if (minDur > 0) {
683  myEditedDef->getLogic()->setPhaseMinDuration(tp->row, minDur);
685  return 1;
686  }
687  } else if (StringUtils::prune(value.text()).empty()) {
690  return 1;
691  }
692  // input error, reset value
693  myTLSPhases->getPhaseTable()->setItemText(tp->row, colMinDur, varDurString(getPhases()[tp->row].minDur).c_str());
694  } else if (tp->col == colMaxDur) {
695  // maxDur edited
696  if (GNEAttributeCarrier::canParse<double>(value.text())) {
697  SUMOTime maxDur = getSUMOTime(value);
698  if (maxDur > 0) {
699  myEditedDef->getLogic()->setPhaseMaxDuration(tp->row, maxDur);
701  return 1;
702  }
703  } else if (StringUtils::prune(value.text()).empty()) {
706  return 1;
707  }
708  // input error, reset value
709  myTLSPhases->getPhaseTable()->setItemText(tp->row, colMaxDur, varDurString(getPhases()[tp->row].maxDur).c_str());
710  } else if (tp->col == colState) {
711  // state edited
712  try {
713  // insert phase with new step and delete the old phase
714  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[tp->row];
715  myEditedDef->getLogic()->addStep(phase.duration, value.text(), phase.next, phase.name, tp->row);
716  myEditedDef->getLogic()->deletePhase(tp->row + 1);
718  onCmdPhaseSwitch(nullptr, 0, nullptr);
719  } catch (ProcessError&) {
720  // input error, reset value
721  myTLSPhases->getPhaseTable()->setItemText(tp->row, colState, getPhases()[tp->row].state.c_str());
722  }
723  } else if (tp->col == colNext) {
724  // next edited
725  bool ok = true;
726  if (GNEAttributeCarrier::canParse<std::vector<int> >(value.text())) {
727  std::vector<int> nextEdited = GNEAttributeCarrier::parse<std::vector<int> >(value.text());
728  for (int n : nextEdited) {
729  if (n < 0 || n >= myTLSPhases->getPhaseTable()->getNumRows()) {
730  ok = false;
731  break;
732  }
733  }
734  if (ok) {
735  myEditedDef->getLogic()->setPhaseNext(tp->row, nextEdited);
737  return 1;
738  }
739  }
740  // input error, reset value
741  myTLSPhases->getPhaseTable()->setItemText(tp->row, colNext, "");
742  } else if (tp->col == colName) {
743  // name edited
744  myEditedDef->getLogic()->setPhaseName(tp->row, value.text());
746  return 1;
747  }
748  return 1;
749 }
750 
751 
752 long
753 GNETLSEditorFrame::onCmdEditParameters(FXObject*, FXSelector, void*) {
754  // continue depending of myEditedDef
755  if (myEditedDef) {
756  // write debug information
757  WRITE_DEBUG("Open single parameters dialog");
758  if (GNESingleParametersDialog(myViewNet->getApp(), myEditedDef).execute()) {
759  // write debug information
760  WRITE_DEBUG("Close single parameters dialog");
761  // set parameters in textfield
763  } else {
764  // write debug information
765  WRITE_DEBUG("Cancel single parameters dialog");
766  }
767  }
768  return 1;
769 }
770 
771 
772 void
778  myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(node->getID())->selectTLS(false);
779  }
780  }
781  }
782  // clean data structures
785  delete myEditedDef;
786  myEditedDef = nullptr;
787  // clear internal lanes
788  buildInternalLanes(nullptr);
789  // clean up controls
791  // only clears when there are no definitions
795 }
796 
797 
798 void
800  // clean up previous internal lanes
801  for (const auto& internalLanes : myInternalLanes) {
802  for (const auto& internalLane : internalLanes.second) {
803  // remove internal lane from grid
804  myViewNet->getNet()->getGrid().removeAdditionalGLObject(internalLane);
805  // delete internal lane
806  delete internalLane;
807  }
808  }
809  // clear container
810  myInternalLanes.clear();
811  // create new internal lanes
812  if (tlDef != nullptr) {
813  const int NUM_POINTS = 10;
814  const NBNode* nbnCurrentJunction = myTLSJunction->getCurrentJunction()->getNBNode();
815  // get innerID NWWriter_SUMO::writeInternalEdges
816  const std::string innerID = ":" + nbnCurrentJunction->getID();
817  const NBConnectionVector& links = tlDef->getControlledLinks();
818  // iterate over links
819  for (const auto& link : links) {
820  int tlIndex = link.getTLIndex();
821  PositionVector shape;
822  try {
823  const NBEdge::Connection& con = link.getFrom()->getConnectionRef(link.getFromLane(), link.getTo(), link.getToLane());
824  shape = con.shape;
825  shape.append(con.viaShape);
826  } catch (ProcessError&) {
827  shape = link.getFrom()->getToNode()->computeInternalLaneShape(link.getFrom(), NBEdge::Connection(link.getFromLane(),
828  link.getTo(), link.getToLane()), NUM_POINTS);
829  }
830  if (shape.length() < 2) {
831  // enlarge shape to ensure visibility
832  shape.clear();
833  const PositionVector laneShapeFrom = link.getFrom()->getLaneShape(link.getFromLane());
834  const PositionVector laneShapeTo = link.getTo()->getLaneShape(link.getToLane());
835  shape.push_back(laneShapeFrom.positionAtOffset(MAX2(0.0, laneShapeFrom.length() - 1)));
836  shape.push_back(laneShapeTo.positionAtOffset(MIN2(1.0, laneShapeFrom.length())));
837  }
838  GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), innerID + '_' + toString(tlIndex), shape, tlIndex);
839  // due GNEInternalLane aren't attribute carriers, we need to use the net grid
840  myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
841  myInternalLanes[tlIndex].push_back(internalLane);
842  }
843  // iterate over crossings
844  for (const auto& nbn : tlDef->getNodes()) {
845  for (const auto& crossing : nbn->getCrossings()) {
846  if (crossing->tlLinkIndex2 > 0 && crossing->tlLinkIndex2 != crossing->tlLinkIndex) {
847  // draw both directions
848  PositionVector forward = crossing->shape;
849  forward.move2side(crossing->width / 4);
850  GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, forward, crossing->tlLinkIndex);
851  // due GNEInternalLane aren't attribute carriers, we need to use the net grid
852  myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
853  myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
854  PositionVector backward = crossing->shape.reverse();
855  backward.move2side(crossing->width / 4);
856  GNEInternalLane* internalLaneReverse = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id + "_r", backward, crossing->tlLinkIndex2);
857  // due GNEInternalLane aren't attribute carriers, we need to use the net grid
858  myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLaneReverse);
859  myInternalLanes[crossing->tlLinkIndex2].push_back(internalLaneReverse);
860  } else {
861  // draw only one lane for both directions
862  GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, crossing->shape, crossing->tlLinkIndex);
863  // due GNEInternalLane aren't attribute carriers, we need to use the net grid
864  myViewNet->getNet()->getGrid().addAdditionalGLObject(internalLane);
865  myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
866  }
867  }
868  }
869  }
870 }
871 
872 
873 std::string
876 }
877 
878 
879 const std::vector<NBTrafficLightLogic::PhaseDefinition>&
881  return myEditedDef->getLogic()->getPhases();
882 }
883 
884 
885 void
888  if (myViewNet->changeAllPhases()) {
889  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
890  for (int row = 0; row < (int)phases.size(); row++) {
891  myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
892  }
893  } else {
894  myEditedDef->getLogic()->setPhaseState(myTLSPhases->getPhaseTable()->getCurrentRow(), lane->getTLIndex(), lane->getLinkState());
895  }
896  myTLSPhases->initPhaseTable(myTLSPhases->getPhaseTable()->getCurrentRow());
897  myTLSPhases->getPhaseTable()->setFocus();
898 }
899 
900 
901 void
902 GNETLSEditorFrame::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* eventData) {
903  if (myEditedDef != nullptr) {
906  std::set<std::string> fromIDs;
907  fromIDs.insert(lane->getMicrosimID());
908  // if neither the lane nor its edge are selected, apply changes to the whole edge
910  for (auto it_lane : lane->getParentEdge()->getLanes()) {
911  fromIDs.insert(it_lane->getMicrosimID());
912  }
913  } else {
914  // if the edge is selected, apply changes to all lanes of all selected edges
915  if (lane->getParentEdge()->isAttributeCarrierSelected()) {
916  const auto selectedEdge = myViewNet->getNet()->getAttributeCarriers()->getSelectedEdges();
917  for (const auto& edge : selectedEdge) {
918  for (auto it_lane : edge->getLanes()) {
919  fromIDs.insert(it_lane->getMicrosimID());
920  }
921  }
922  }
923  // if the lane is selected, apply changes to all selected lanes
924  if (lane->isAttributeCarrierSelected()) {
925  const auto selectedLanes = myViewNet->getNet()->getAttributeCarriers()->getSelectedLanes();
926  for (auto it_lane : selectedLanes) {
927  fromIDs.insert(it_lane->getMicrosimID());
928  }
929  }
930 
931  }
932  // set new state for all connections from the chosen lane IDs
933  for (auto it : links) {
934  if (fromIDs.count(it.getFrom()->getLaneID(it.getFromLane())) > 0) {
935  std::vector<GNEInternalLane*> lanes = myInternalLanes[it.getTLIndex()];
936  for (auto it_lane : lanes) {
937  it_lane->onDefault(obj, sel, eventData);
938  }
939  }
940  }
941  }
942 }
943 
944 
945 bool
947  if (myEditedDef != nullptr) {
949  for (auto it : links) {
950  if (it.getFrom()->getID() == edge->getMicrosimID()) {
951  return true;
952  }
953  }
954  }
955  return false;
956 }
957 
958 
959 void
962  onCmdCancel(nullptr, 0, nullptr);
963  myViewNet->getUndoList()->begin(GUIIcon::MODETLS, "modifying traffic light definition");
967  // only select TLS if getCurrentJunction exist
970  }
973  myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(node->getID())->selectTLS(true);
974  }
975  }
976  } else {
977  myViewNet->setStatusBarText("Unsaved modifications. Abort or Save");
978  }
979 }
980 
981 
982 SUMOTime
983 GNETLSEditorFrame::getSUMOTime(const FXString& string) {
984  return TIME2STEPS(GNEAttributeCarrier::parse<double>(string.text()));
985 }
986 
987 // ---------------------------------------------------------------------------
988 // GNETLSEditorFrame::TLSAttributes - methods
989 // ---------------------------------------------------------------------------
990 
992  FXGroupBoxModule(TLSEditorParent->myContentFrame, "Traffic light Attributes"),
993  myTLSEditorParent(TLSEditorParent) {
994 
995  // create frame, label and textfield for name (By default disabled)
996  FXHorizontalFrame* nameFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
997  new FXLabel(nameFrame, toString(SUMO_ATTR_ID).c_str(), nullptr, GUIDesignLabelAttribute);
999  myNameTextField->disable();
1000 
1001  // create frame, label and comboBox for Program (By default hidden)
1002  FXHorizontalFrame* programFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1003  new FXLabel(programFrame, "program", nullptr, GUIDesignLabelAttribute);
1005  myProgramComboBox->disable();
1006 
1007  // create frame, label and TextField for Offset (By default disabled)
1008  FXHorizontalFrame* offsetFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1009  new FXLabel(offsetFrame, toString(SUMO_ATTR_OFFSET).c_str(), nullptr, GUIDesignLabelAttribute);
1011  myOffsetTextField->disable();
1012 
1013  // create frame, label and TextField for Offset (By default disabled)
1014  FXHorizontalFrame* parametersFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1015  myButtonEditParameters = new FXButton(parametersFrame, "parameters", nullptr, myTLSEditorParent, MID_GNE_OPEN_PARAMETERS_DIALOG, GUIDesignButtonAttribute);
1017  myButtonEditParameters->disable();
1018  myParametersTextField->disable();
1019 }
1020 
1021 
1023 
1024 
1025 void
1027  assert(junction);
1028  myTLSDefinitions.clear();
1029  // enable name TextField
1030  myNameTextField->enable();
1031  // enable Offset
1032  myOffsetTextField->enable();
1033  myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
1034  // enable parameters
1035  myButtonEditParameters->enable();
1036  myParametersTextField->enable();
1037  myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
1038  // obtain TLSs
1039  for (auto it : junction->getNBNode()->getControllingTLS()) {
1040  myTLSDefinitions.push_back(it);
1041  myNameTextField->setText(it->getID().c_str());
1042  myNameTextField->enable();
1043  myProgramComboBox->appendItem(it->getProgramID().c_str());
1044  }
1045  if (myTLSDefinitions.size() > 0) {
1046  myProgramComboBox->enable();
1047  myProgramComboBox->setCurrentItem(0);
1048  myProgramComboBox->setNumVisible(myProgramComboBox->getNumItems());
1049  myTLSEditorParent->onCmdDefSwitch(nullptr, 0, nullptr);
1050  }
1051 }
1052 
1053 
1054 void
1056  // clear definitions
1057  myTLSDefinitions.clear();
1058  // clear and disable name TextField
1059  myNameTextField->setText("");
1060  myNameTextField->disable();
1061  // clear and disable myProgramComboBox
1062  myProgramComboBox->clearItems();
1063  myProgramComboBox->disable();
1064  // clear and disable Offset TextField
1065  myOffsetTextField->setText("");
1066  myOffsetTextField->disable();
1067  myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
1068  // clear and disable parameters TextField
1069  myButtonEditParameters->disable();
1070  myParametersTextField->setText("");
1071  myParametersTextField->disable();
1072  myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
1073 }
1074 
1075 
1078  return myTLSDefinitions.at(myProgramComboBox->getCurrentItem());
1079 }
1080 
1081 
1082 const std::string
1084  if (myProgramComboBox->getNumItems() == 0) {
1085  return "";
1086  } else {
1087  return myProgramComboBox->getText().text();
1088  }
1089 }
1090 
1091 
1092 int
1094  return (int)myTLSDefinitions.size();
1095 }
1096 
1097 
1098 int
1100  return myProgramComboBox->getNumItems();
1101 }
1102 
1103 
1104 SUMOTime
1106  return getSUMOTime(myOffsetTextField->getText().text());
1107 }
1108 
1109 
1110 void
1112  myOffsetTextField->setText(toString(STEPS2TIME(offset)).c_str());
1113  myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
1114 }
1115 
1116 
1117 bool
1119  if (GNEAttributeCarrier::canParse<SUMOTime>(myOffsetTextField->getText().text())) {
1120  myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
1121  return true;
1122  } else {
1123  myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::RED));
1124  return false;
1125  }
1126 }
1127 
1128 
1129 std::string
1131  return myParametersTextField->getText().text();
1132 }
1133 
1134 
1135 void
1136 GNETLSEditorFrame::TLSAttributes::setParameters(const std::string& parameters) {
1137  myParametersTextField->setText(parameters.c_str());
1138  myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
1139 }
1140 
1141 
1142 bool
1144  if (Parameterised::areParametersValid(myParametersTextField->getText().text())) {
1145  myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
1146  return true;
1147  } else {
1148  myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::RED));
1149  return false;
1150  }
1151 }
1152 
1153 // ---------------------------------------------------------------------------
1154 // GNETLSEditorFrame::TLSJunction - methods
1155 // ---------------------------------------------------------------------------
1156 
1158  FXGroupBoxModule(tlsEditorParent->myContentFrame, "Junction"),
1159  myCurrentJunction(nullptr) {
1160  // Create frame for junction ID
1161  FXHorizontalFrame* junctionIDFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1162  myLabelJunctionID = new FXLabel(junctionIDFrame, "Junction ID", nullptr, GUIDesignLabelAttribute);
1164  myTextFieldJunctionID->setEditable(false);
1165  // update junction description after creation
1167  // show TLS Junction
1168  show();
1169 }
1170 
1171 
1173 
1174 
1175 GNEJunction*
1177  return myCurrentJunction;
1178 }
1179 
1180 
1181 void
1183  myCurrentJunction = junction;
1184 }
1185 
1186 
1187 void
1189  if (myCurrentJunction == nullptr) {
1190  myTextFieldJunctionID->setText("");
1191  } else {
1192  NBNode* nbn = myCurrentJunction->getNBNode();
1193  myTextFieldJunctionID->setText(nbn->getID().c_str());
1194  }
1195 }
1196 
1197 // ---------------------------------------------------------------------------
1198 // GNETLSEditorFrame::TLSDefinition - methods
1199 // ---------------------------------------------------------------------------
1200 
1202  FXGroupBoxModule(TLSEditorParent->myContentFrame, "Traffic Light Programs") {
1203  FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1204  // create create tlDef button
1205  myNewTLProgram = new FXButton(buttonsFrame, "Create\t\tCreate a new traffic light program",
1207  // create delete tlDef button
1208  myDeleteTLProgram = new FXButton(buttonsFrame, "Delete\t\tDelete a traffic light program. If all programs are deleted the junction turns into a priority junction.",
1210  // show TLS TLSDefinition
1211  show();
1212 }
1213 
1214 
1216 
1217 // ---------------------------------------------------------------------------
1218 // GNETLSEditorFrame::TLSPhases - methods
1219 // ---------------------------------------------------------------------------
1220 
1222  FXGroupBoxModule(TLSEditorParent->myContentFrame, "Phases"),
1223  myTLSEditorParent(TLSEditorParent),
1224  myTableFont(new FXFont(getApp(), "Courier New", 9)) {
1225 
1226  // create and configure phase table
1227  myTableScroll = new FXScrollWindow(getCollapsableFrame(), LAYOUT_FILL_X | LAYOUT_FIX_HEIGHT);
1229  myPhaseTable->setColumnHeaderMode(LAYOUT_FIX_HEIGHT);
1230  myPhaseTable->setColumnHeaderHeight(getApp()->getNormalFont()->getFontHeight() + getApp()->getNormalFont()->getFontAscent() / 2);
1231  myPhaseTable->setRowHeaderMode(LAYOUT_FIX_WIDTH);
1232  myPhaseTable->setRowHeaderWidth(0);
1233  myPhaseTable->hide();
1234  myPhaseTable->setFont(myTableFont);
1235  myPhaseTable->setHelpText("phase duration in seconds | phase state");
1236 
1237  // create total duration info label
1238  myCycleDuration = new FXLabel(getCollapsableFrame(), "", nullptr, GUIDesignLabelLeft);
1239 
1240  // using FXMatrix for tabular button layout would have been cleaner but the
1241  // below attempt did not make the buttons fill available horizontal space
1242  // FXMatrix* phaseButtons = new FXMatrix(getCollapsableFrame(), 2, LAYOUT_FILL_X | MATRIX_BY_COLUMNS);
1243 
1244  FXHorizontalFrame* phaseButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1245  FXVerticalFrame* col1 = new FXVerticalFrame(phaseButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // left button columm
1246  FXVerticalFrame* col2 = new FXVerticalFrame(phaseButtons, LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // right button column
1247 
1248  // create new phase button
1249  myInsertDuplicateButton = new FXButton(col1, "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);
1250  // create delete phase button
1251  myDeleteSelectedPhaseButton = new FXButton(col2, "Delete Phase\t\tDelete selected phase", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_PHASE_DELETE, GUIDesignButton);
1252 
1253  // create cleanup states button
1254  new FXButton(col1, "Clean States\t\tClean unused states from all phase. (Not allowed for multiple programs)", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_CLEANUP, GUIDesignButton);
1255 
1256  // add unused states button
1257  new FXButton(col2, "Add States\t\tExtend the state vector for all phases by one entry (unused until a connection or crossing is assigned to the new index).", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_ADDUNUSED, GUIDesignButton);
1258 
1259  // group states button
1260  new FXButton(col1, "Group Signals\t\tShorten state definition by letting connections with the same signal states use the same index. (Not allowed for multiple programs)", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_GROUP_STATES, GUIDesignButton);
1261 
1262  // ungroup states button
1263  new FXButton(col2, "Ungroup Signals\t\tLet every connection use a distinct index (reverse state grouping). (Not allowed for multiple programs)", nullptr, myTLSEditorParent, MID_GNE_TLSFRAME_UNGROUP_STATES, GUIDesignButton);
1264  // show TLSFile
1265  show();
1266 }
1267 
1268 
1270  delete myTableFont;
1271 }
1272 
1273 
1274 FXTable*
1276  return myPhaseTable;
1277 }
1278 
1279 
1280 void
1282  myPhaseTable->setVisibleRows(1);
1283  myPhaseTable->setVisibleColumns(2);
1284  myPhaseTable->hide();
1285  if (myTLSEditorParent->myTLSAttributes->getNumberOfTLSDefinitions() > 0) {
1286  const bool fixed = myTLSEditorParent->fixedDuration();
1287  const int cols = fixed ? 4 : 6;
1288  const int colDuration = 0;
1289  const int colMinDur = fixed ? -1 : 1;
1290  const int colMaxDur = fixed ? -1 : 2;
1291  const int colState = fixed ? 1 : 3;
1292  const int colNext = fixed ? 2 : 4;
1293  const int colName = fixed ? 3 : 5;
1294 
1295  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = myTLSEditorParent->getPhases();
1296  myPhaseTable->setTableSize((int)phases.size(), cols);
1297  myPhaseTable->setVisibleRows((int)phases.size());
1298  myPhaseTable->setVisibleColumns(cols);
1299  for (int row = 0; row < (int)phases.size(); row++) {
1300  myPhaseTable->setItemText(row, colDuration, toString(STEPS2TIME(phases[row].duration)).c_str());
1301  if (!fixed) {
1302  myPhaseTable->setItemText(row, colMinDur, varDurString(phases[row].minDur).c_str());
1303  myPhaseTable->setItemText(row, colMaxDur, varDurString(phases[row].maxDur).c_str());
1304  }
1305  myPhaseTable->setItemText(row, colState, phases[row].state.c_str());
1306  myPhaseTable->setItemText(row, colNext, phases[row].next.size() > 0 ? toString(phases[row].next).c_str() : " ");
1307  myPhaseTable->setItemText(row, colName, phases[row].name.c_str());
1308  myPhaseTable->getItem(row, 1)->setJustify(FXTableItem::LEFT);
1309  }
1310  myPhaseTable->fitColumnsToContents(0, cols);
1311  myPhaseTable->setColumnText(colDuration, "dur");
1312  if (colMinDur >= 0) {
1313  myPhaseTable->setColumnText(colMinDur, "min");
1314  myPhaseTable->setColumnText(colMaxDur, "max");
1315  myPhaseTable->setColumnWidth(colMinDur, MAX2(myPhaseTable->getColumnWidth(colMinDur), 30));
1316  myPhaseTable->setColumnWidth(colMaxDur, MAX2(myPhaseTable->getColumnWidth(colMaxDur), 35));
1317  }
1318  myPhaseTable->setColumnText(colState, "state");
1319  myPhaseTable->setColumnText(colNext, "nxt");
1320  myPhaseTable->setColumnText(colName, "name");
1321  myPhaseTable->setColumnWidth(colNext, MAX2(myPhaseTable->getColumnWidth(colNext), 30));
1322  myPhaseTable->setColumnWidth(colName, MAX2(myPhaseTable->getColumnWidth(colName), 45));
1323 
1324  myPhaseTable->setHeight((int)phases.size() * 21 + 21); // experimental
1325  myPhaseTable->setCurrentItem(index, 0);
1326  myPhaseTable->selectRow(index, true);
1327  myPhaseTable->show();
1328  myPhaseTable->setFocus();
1329  myTableScroll->setHeight(myPhaseTable->getHeight() + 15);
1330 
1331  // neither my myPhaseTable->getWidth nor getDefaultWidth return the sum of column widths
1332  // however, the scroll pane uses getDefaultWidth to determine the
1333  // horizontal scrolling area which can only be changed via
1334  // getDefColumnWidth, hence the baroque work-around
1335 
1336  int neededWidth = 0;
1337  for (int i = 0; i < cols; i++) {
1338  neededWidth += myPhaseTable->getColumnWidth(i);
1339  }
1340  myPhaseTable->setDefColumnWidth(neededWidth / cols);
1341  }
1342  update();
1343 }
1344 
1345 
1346 void
1348  myCycleDuration->show();
1349 }
1350 
1351 
1352 void
1354  myCycleDuration->hide();
1355 }
1356 
1357 void
1359  SUMOTime cycleDuration = 0;
1360  for (auto it : myTLSEditorParent->getPhases()) {
1361  cycleDuration += it.duration;
1362  }
1363  std::string text = "Cycle time: " + toString(STEPS2TIME(cycleDuration));
1364  myCycleDuration->setText(text.c_str());
1365 }
1366 
1367 // ---------------------------------------------------------------------------
1368 // GNETLSEditorFrame::TLSModifications - methods
1369 // ---------------------------------------------------------------------------
1370 
1372  FXGroupBoxModule(TLSEditorParent->myContentFrame, "Modifications"),
1373  myTLSEditorParent(TLSEditorParent),
1374  myHaveModifications(false) {
1375  FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1376  // create save modifications button
1377  mySaveModificationsButtons = new FXButton(buttonsFrame, "Save\t\tSave program modifications (Enter)",
1379  // create discard modifications buttons
1380  myDiscardModificationsButtons = new FXButton(buttonsFrame, "Cancel\t\tDiscard program modifications (Esc)",
1382  // show TLSModifications
1383  show();
1384 }
1385 
1386 
1388 
1389 
1390 bool
1392  return myHaveModifications;
1393 }
1394 
1395 
1396 void
1398  myHaveModifications = value;
1399 }
1400 
1401 // ---------------------------------------------------------------------------
1402 // GNETLSEditorFrame::TLSFile - methods
1403 // ---------------------------------------------------------------------------
1404 
1406  FXGroupBoxModule(TLSEditorParent->myContentFrame, "TLS Program File"),
1407  myTLSEditorParent(TLSEditorParent) {
1408  FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1409  // create create tlDef button
1410  myLoadTLSProgramButton = new FXButton(buttonsFrame, "Load\t\tLoad TLS program from additional file", GUIIconSubSys::getIcon(GUIIcon::OPEN_CONFIG), this, MID_GNE_TLSFRAME_LOAD_PROGRAM, GUIDesignButton);
1411  // create create tlDef button
1412  mySaveTLSProgramButton = new FXButton(buttonsFrame, "Save\t\tSave TLS program to additional file", GUIIconSubSys::getIcon(GUIIcon::SAVE), this, MID_GNE_TLSFRAME_SAVE_PROGRAM, GUIDesignButton);
1413  // show TLSFile
1414  show();
1415 }
1416 
1417 
1419 
1420 
1421 long
1423  FXFileDialog opendialog(getCollapsableFrame(), "Load TLS Program");
1424  opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::MODETLS));
1425  opendialog.setSelectMode(SELECTFILE_EXISTING);
1426  opendialog.setPatternList("XML files (*.xml)\nAll files (*)");
1427  if (gCurrentFolder.length() != 0) {
1428  opendialog.setDirectory(gCurrentFolder);
1429  }
1430  if (opendialog.execute()) {
1431  // run parser
1432  NBTrafficLightLogicCont tmpTLLCont;
1433  NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myTLSEditorParent->myViewNet->getNet()->getEdgeCont(), true);
1434  tmpTLLCont.insert(myTLSEditorParent->myEditedDef);
1435  XMLSubSys::runParser(tllHandler, opendialog.getFilename().text());
1436 
1437  NBLoadedSUMOTLDef* newDefSameProgram = nullptr;
1438  std::set<NBLoadedSUMOTLDef*> newDefsOtherProgram;
1439  for (auto item : tmpTLLCont.getPrograms(myTLSEditorParent->myEditedDef->getID())) {
1440  if (item.second != myTLSEditorParent->myEditedDef) {
1441  NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(item.second);
1442  if (item.first == myTLSEditorParent->myEditedDef->getProgramID()) {
1443  newDefSameProgram = sdef;
1444  } else {
1445  newDefsOtherProgram.insert(sdef);
1446  }
1447  }
1448  }
1449  const int newPrograms = (int)newDefsOtherProgram.size();
1450  if (newPrograms > 0 || newDefSameProgram != nullptr) {
1451  std::vector<NBNode*> nodes = myTLSEditorParent->myEditedDef->getNodes();
1452  for (auto newProg : newDefsOtherProgram) {
1453  for (auto it_node : nodes) {
1454  GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
1455  myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newProg, true), true);
1456  }
1457  }
1458  if (newPrograms > 0) {
1459  WRITE_MESSAGE("Loaded " + toString(newPrograms) + " new programs for tlLogic '" + myTLSEditorParent->myEditedDef->getID() + "'");
1460  }
1461  if (newDefSameProgram != nullptr) {
1462  // replace old program when loading the same program ID
1463  myTLSEditorParent->myEditedDef = newDefSameProgram;
1464  WRITE_MESSAGE("Updated program '" + newDefSameProgram->getProgramID() + "' for tlLogic '" + myTLSEditorParent->myEditedDef->getID() + "'");
1465  }
1466  } else {
1467  if (tllHandler.getSeenIDs().count(myTLSEditorParent->myEditedDef->getID()) == 0) {
1468  myTLSEditorParent->getViewNet()->setStatusBarText("No programs found for traffic light '" + myTLSEditorParent->myEditedDef->getID() + "'");
1469  }
1470  }
1471 
1472  // clean up temporary container to avoid deletion of defs when it's destruct is called
1473  for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
1474  tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
1475  }
1476 
1477  myTLSEditorParent->myTLSPhases->initPhaseTable();
1478  myTLSEditorParent->myTLSModifications->setHaveModifications(true);
1479  }
1480  return 0;
1481 }
1482 
1483 
1484 long
1486  FXString file = MFXUtils::getFilename2Write(this,
1487  "Save TLS Program as", ".xml",
1489  gCurrentFolder);
1490  if (file == "") {
1491  return 1;
1492  }
1493  // add xml extension
1494  file = FileHelpers::addExtension(file.text(), ".xml").c_str();
1495  OutputDevice& device = OutputDevice::getDevice(file.text());
1496  // save program
1497  device.writeXMLHeader("additional", "additional_file.xsd");
1498  device.openTag(SUMO_TAG_TLLOGIC);
1499  device.writeAttr(SUMO_ATTR_ID, myTLSEditorParent->myEditedDef->getLogic()->getID());
1500  device.writeAttr(SUMO_ATTR_TYPE, myTLSEditorParent->myEditedDef->getLogic()->getType());
1501  device.writeAttr(SUMO_ATTR_PROGRAMID, myTLSEditorParent->myEditedDef->getLogic()->getProgramID());
1502  device.writeAttr(SUMO_ATTR_OFFSET, writeSUMOTime(myTLSEditorParent->myEditedDef->getLogic()->getOffset()));
1503  myTLSEditorParent->myEditedDef->writeParams(device);
1504  // write the phases
1505  const bool varPhaseLength = myTLSEditorParent->myEditedDef->getLogic()->getType() != TrafficLightType::STATIC;
1506  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
1507  for (auto j : phases) {
1508  device.openTag(SUMO_TAG_PHASE);
1509  device.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(j.duration));
1510  device.writeAttr(SUMO_ATTR_STATE, j.state);
1511  if (varPhaseLength) {
1513  device.writeAttr(SUMO_ATTR_MINDURATION, writeSUMOTime(j.minDur));
1514  }
1516  device.writeAttr(SUMO_ATTR_MAXDURATION, writeSUMOTime(j.maxDur));
1517  }
1518  }
1519  device.closeTag();
1520  }
1521  device.close();
1522  return 1;
1523 }
1524 
1525 
1526 std::string
1528  double time = STEPS2TIME(steps);
1529  if (time == std::floor(time)) {
1530  return toString(int(time));
1531  } else {
1532  return toString(time);
1533  }
1534 }
1535 
1536 long
1537 GNETLSEditorFrame::TLSFile::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
1538  const bool enable = myTLSEditorParent->myTLSAttributes->getNumberOfTLSDefinitions() > 0;
1539  o->handle(getCollapsableFrame(), FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), nullptr);
1540  return 1;
1541 }
1542 
1543 
1544 /****************************************************************************/
static const int NUM_POINTS
FXDEFMAP(GNETLSEditorFrame) GNETLSEditorFrameMap[]
@ MID_GNE_TLSFRAME_SUBRENAME
sub-rename TLS
Definition: GUIAppEnum.h:964
@ MID_GNE_TLSFRAME_PHASE_CREATE
create phase thable
Definition: GUIAppEnum.h:970
@ MID_CANCEL
Cancel-button pressed.
Definition: GUIAppEnum.h:255
@ MID_GNE_OPEN_PARAMETERS_DIALOG
open parameters dialog
Definition: GUIAppEnum.h:833
@ MID_GNE_TLSFRAME_ADDOFF
add off to TLS
Definition: GUIAppEnum.h:966
@ MID_GNE_TLSFRAME_SAVE_PROGRAM
cleanup unused states
Definition: GUIAppEnum.h:986
@ MID_GNE_TLSFRAME_GUESSPROGRAM
replace program with a newly guessed program
Definition: GUIAppEnum.h:950
@ MID_GNE_TLSFRAME_PARAMETERS
TLS parameters.
Definition: GUIAppEnum.h:954
@ MID_GNE_TLSFRAME_GROUP_STATES
group states
Definition: GUIAppEnum.h:980
@ MID_GNE_TLSFRAME_PHASE_DELETE
delete phase thable
Definition: GUIAppEnum.h:972
@ MID_GNE_TLSFRAME_CREATE
Create TLS.
Definition: GUIAppEnum.h:958
@ MID_GNE_TLSFRAME_ADDUNUSED
add unused states
Definition: GUIAppEnum.h:978
@ MID_OK
Ok-button pressed.
Definition: GUIAppEnum.h:253
@ MID_GNE_TLSFRAME_SWITCH
switch between programs
Definition: GUIAppEnum.h:956
@ MID_GNE_TLSFRAME_SELECT_JUNCTION
selected junction von TLS
Definition: GUIAppEnum.h:946
@ MID_GNE_TLSFRAME_OFFSET
TLS offset.
Definition: GUIAppEnum.h:952
@ MID_GNE_TLSFRAME_CLEANUP
cleanup unused states
Definition: GUIAppEnum.h:974
@ MID_GNE_TLSFRAME_LOAD_PROGRAM
Load Program.
Definition: GUIAppEnum.h:984
@ MID_GNE_TLSFRAME_UNGROUP_STATES
ungroup states
Definition: GUIAppEnum.h:982
@ MID_GNE_TLSFRAME_RENAME
rename TLS
Definition: GUIAppEnum.h:962
@ MID_GNE_TLSFRAME_PHASE_TABLE
select phase thable
Definition: GUIAppEnum.h:968
@ MID_GNE_TLSFRAME_DELETE
delete TLS
Definition: GUIAppEnum.h:960
#define GUIDesignLabelLeft
Definition: GUIDesigns.h:193
#define GUIDesignButtonAttribute
button extended over over column with thick and raise frame
Definition: GUIDesigns.h:71
#define GUIDesignButton
Definition: GUIDesigns.h:68
#define GUIDesignComboBoxAttribute
Combo box static (cannot be edited) extended over the matrix column.
Definition: GUIDesigns.h:276
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:285
#define GUIDesignTextField
Definition: GUIDesigns.h:42
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:343
#define GUIDesignLabelAttribute
label extended over the matrix column with thick frame
Definition: GUIDesigns.h:217
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:60
#define GUIDesignTableLimitedHeight
design for table extended over frame but with limited Height
Definition: GUIDesigns.h:556
FXString gCurrentFolder
The folder used as last.
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:290
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:282
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:32
@ 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
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_OFFSET
@ 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.
T MIN2(T a, T b)
Definition: StdDefs.h:74
T MAX2(T a, T b)
Definition: StdDefs.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
FXGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toogled)
static std::string addExtension(const std::string &path, const std::string &extension)
Add an extension to the given file path.
Definition: FileHelpers.cpp:91
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
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:782
GNEViewNet * myViewNet
View Net.
Definition: GNEFrame.h:114
FXVerticalFrame * myContentFrame
Vertical frame that holds all widgets of frame.
Definition: GNEFrame.h:117
virtual void show()
show Frame
Definition: GNEFrame.cpp:108
void showOverlappedInspection(const GNEViewNetHelper::ObjectsUnderCursor &objectsUnderCursor, const Position &clickedPosition)
show template editor
int getNumberOfOverlappedACs() const
get number of overlapped ACSs
void hideOverlappedInspection()
hide template editor
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 modfied
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)
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 arent edge
Definition: GNELane.cpp:113
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:144
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:1970
void computeJunction(GNEJunction *junction)
trigger recomputation of junction shape and logic param[in] window The window to inform about delay
Definition: GNENet.cpp:1323
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:125
NBEdgeCont & getEdgeCont()
returns the NBEdgeCont of the underlying netbuilder
Definition: GNENet.cpp:1976
Dialog for edit parameters.
void initTLSAttributes(GNEJunction *junction)
initializes the definitions and corresponding listbox
bool isValidOffset()
is current offset valid
bool isValidParameters()
are current parameter valid
FXTextField * myOffsetTextField
the TextField for modifying offset
int getNumberOfPrograms() const
get number of programs
SUMOTime getOffset() const
get current offset in string format
const std::string getCurrentTLSProgramID() const
get current program ID
void setParameters(const std::string &parameters)
set new parameters
void clearTLSAttributes()
clear TLS attributes
FXComboBox * myProgramComboBox
the comboBox for selecting the tl-definition to edit
void setOffset(const SUMOTime &offset)
set new offset
std::string getParameters() const
get current parameters in string format
int getNumberOfTLSDefinitions() const
get number of definitions
FXButton * myButtonEditParameters
button for edit parameters
TLSAttributes(GNETLSEditorFrame *TLSEditorParent)
constructor
NBTrafficLightDefinition * getCurrentTLSDefinition() const
get current definition
FXTextField * myParametersTextField
the TextField for modifying parameters
FXTextField * myNameTextField
name text field
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditorParent
FXButton * myNewTLProgram
button for create new Traffic light program
FXButton * myDeleteTLProgram
button for delete traffic light program
TLSDefinition(GNETLSEditorFrame *TLSEditorParent)
constructor
FXButton * mySaveTLSProgramButton
button for save TLS Programs
FXButton * myLoadTLSProgramButton
button for load TLS Programs
long onCmdLoadTLSProgram(FXObject *, FXSelector, void *)
TLSFile(GNETLSEditorFrame *TLSEditorParent)
FOX-declaration.
std::string writeSUMOTime(SUMOTime steps)
convert SUMOTime into string
long onCmdSaveTLSProgram(FXObject *, FXSelector, void *)
save TLS Programm to an additional file
long onUpdNeedsDef(FXObject *, FXSelector, void *)
enable buttons, only when a tlLogic is being edited
FXLabel * myLabelJunctionID
label for junction ID
FXTextField * myTextFieldJunctionID
text field for junction ID
GNEJunction * getCurrentJunction() const
get current modified junction
void setCurrentJunction(GNEJunction *junction)
set current junction
void updateJunctionDescription() const
update descrition
TLSJunction(GNETLSEditorFrame *tlsEditorParent)
constructor
TLSModifications(GNETLSEditorFrame *TLSEditorParent)
constructor
void setHaveModifications(bool value)
set if current TLS was modified
FXButton * myDiscardModificationsButtons
button for cancel modifications
bool checkHaveModifications() const
check if current TLS was modified
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
FXButton * mySaveModificationsButtons
button for save modifications
FXScrollWindow * myTableScroll
window for oversized phase tables
FXLabel * myCycleDuration
label with the cycle duration
void showCycleDuration()
show cycle duration
FXButton * myDeleteSelectedPhaseButton
delete phase button
FXFont * myTableFont
font for the phase table
FXButton * myInsertDuplicateButton
insert new phase button
TLSPhases(GNETLSEditorFrame *TLSEditorParent)
constructor
FXTable * myPhaseTable
table for selecting and rearranging phases and for changing duration
FXTable * getPhaseTable() const
get phase table
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditor Parent
void updateCycleDuration()
recomputes cycle duration and updates label
void initPhaseTable(int index=0)
initialies the phase table
void hideCycleDuration()
hide cycle duration
const std::vector< NBTrafficLightLogic::PhaseDefinition > & getPhases()
the phase of the current traffic light
long onCmdOK(FXObject *, FXSelector, void *)
void handleChange(GNEInternalLane *lane)
update phase definition for the current traffic light and phase
long onCmdGuess(FXObject *, FXSelector, void *)
Called when the user presses the button Guess.
void buildInternalLanes(NBTrafficLightDefinition *tlDef)
builds internal lanes for the given tlDef
GNETLSEditorFrame::TLSAttributes * myTLSAttributes
modul for TLS attributes
GNEFrameModules::OverlappedInspection * myOverlappedInspection
Overlapped Inspection.
static std::string varDurString(SUMOTime dur)
convert duration (potentially undefined) to string
long onCmdDefCreate(FXObject *, FXSelector, void *)
Called when the user creates a TLS.
long onCmdDefAddOff(FXObject *, FXSelector, void *)
Called when the user adds a OFF.
long onCmdDefDelete(FXObject *, FXSelector, void *)
Called when the user deletes a TLS.
bool isTLSSaved()
check if modifications in TLS was saved
void editJunction(GNEJunction *junction)
edits the traffic light for the given junction
GNETLSEditorFrame::TLSModifications * myTLSModifications
modul for load/Save TLS Modifications
long onCmdPhaseEdit(FXObject *, FXSelector, void *)
Called when the user edits a Phase.
long onUpdDefCreate(FXObject *, FXSelector, void *)
Called when occurs an update of create definition.
GNETLSEditorFrame::TLSPhases * myTLSPhases
modul for TLS Phases
void selectedOverlappedElement(GNEAttributeCarrier *AC)
open AttributesCreator extended dialog (can be reimplemented in frame children)
TLIndexMap myInternalLanes
long onUpdNeedsSingleDef(FXObject *, FXSelector, void *)
Called to buttons that modify link indices.
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
long onCmdDefSubRename(FXObject *, FXSelector, void *)
Called when the user sub-renames a TLS.
long onUpdUngroupStates(FXObject *, FXSelector, void *)
Called to update the ungroups states button.
long onCmdSetOffset(FXObject *, FXSelector, void *)
Called when the user changes the offset of a TLS.
long onCmdPhaseDelete(FXObject *, FXSelector, void *)
Called when the user deletes a Phase.
long onCmdCancel(FXObject *, FXSelector, void *)
Called when the user presses the Cancel-button.
long onCmdSetParameters(FXObject *, FXSelector, void *)
Called when the user changes parameters of a TLS.
long onUpdModified(FXObject *, FXSelector, void *)
Called when occurs an update of modified.
static SUMOTime getSUMOTime(const FXString &string)
converts to SUMOTime
void handleMultiChange(GNELane *lane, FXObject *obj, FXSelector sel, void *data)
update phase definition for the current traffic light and phase
long onCmdDefRename(FXObject *, FXSelector, void *)
Called when the user renames a TLS.
long onUpdNeedsDef(FXObject *, FXSelector, void *)
Called when occurs an update of needs definition.
long onUpdNeedsDefAndPhase(FXObject *, FXSelector, void *)
Called when occurs an update of needs definition an dphase.
long onCmdUngroupStates(FXObject *, FXSelector, void *)
Called when the user ungroups states.
~GNETLSEditorFrame()
Destructor.
long onCmdGroupStates(FXObject *, FXSelector, void *)
Called when the user groups states.
NBLoadedSUMOTLDef * myEditedDef
the traffic light definition being edited
long onUpdDefSwitch(FXObject *, FXSelector, void *)
Called when occurs an update of switch definition.
long onCmdPhaseCreate(FXObject *, FXSelector, void *)
Called when the user creates a Phase.
GNETLSEditorFrame::TLSJunction * myTLSJunction
modul for TLS Junction
bool fixedDuration() const
whether the current traffic light uses fixed phase durations
void editTLS(const Position &clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor &objectsUnderCursor)
edits the traffic light for the given clicked junction
long onCmdPhaseSwitch(FXObject *, FXSelector, void *)
Called when the user switchs a Phase.
long onCmdEditParameters(FXObject *, FXSelector, void *ptr)
Called when user press edit parameters button.
void cleanup()
cleans up previous lanes
long onCmdAddUnused(FXObject *, FXSelector, void *)
Called when the user cleans up states.
long onCmdDefSwitch(FXObject *, FXSelector, void *)
Called when the user switchs a TLS.
void show()
show inspector frame
long onCmdCleanup(FXObject *, FXSelector, void *)
Called when the user cleans up states.
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
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 abortAllChangeGroups()
reverts and discards ALL active chained change groups
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
GNEJunction * getJunctionFront() const
get front junction or a pointer to nullptr
GNENet * getNet() const
get the net object
bool changeAllPhases() const
change all phases
Definition: GNEViewNet.cpp:647
GNEUndoList * getUndoList() const
get the undoList object
void updateViewNet() const
Mark the entire GNEViewNet to be repainted later.
Definition: GNEViewNet.cpp:372
void setStatusBarText(const std::string &text)
set staturBar text
Definition: GNEViewNet.cpp:629
virtual 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
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.
bool usingSignalGroups() const
whether this definition uses signal group (multiple connections with the same link index)
void ungroupSignals()
let all connections use a distinct link index
void groupSignals()
let connections with the same state use the same link index
NBTrafficLightLogic * getLogic()
Returns the internal logic.
void setOffset(SUMOTime offset)
Sets the offset of this tls.
A definition of a pedestrian crossing.
Definition: NBNode.h:129
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:324
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:319
The base class for traffic light logic definitions.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
const std::string & getProgramID() const
Returns the ProgramID.
TrafficLightType getType() const
get the algorithm type (static etc..)
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
int computeBrakingTime(double minDecel) const
Computes the time vehicles may need to brake.
NBTrafficLightLogic * compute(OptionsCont &oc)
Computes the traffic light logic.
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
static const SUMOTime UNSPECIFIED_DURATION
The definition of a single phase of the logic.
std::string state
The state definition.
std::string name
option phase name
SUMOTime duration
The duration of the phase in s.
std::vector< int > next
next phase indices or empty list
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.
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.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
A SUMO-compliant built logic for a traffic light.
void setPhaseMinDuration(int phaseIndex, SUMOTime duration)
SUMOTime getOffset() const
Returns the offset of first switch.
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
void setPhaseName(int phaseIndex, const std::string &name)
void setPhaseDuration(int phaseIndex, SUMOTime duration)
Modifies the duration for an existing phase (used by NETEDIT)
void setPhaseState(int phaseIndex, int tlIndex, LinkState linkState)
Modifies the state for an existing phase (used by NETEDIT)
void setPhaseMaxDuration(int phaseIndex, SUMOTime duration)
int getNumLinks()
Returns the number of participating links.
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.
void setPhaseNext(int phaseIndex, const std::vector< int > &next)
void setStateLength(int numLinks, LinkState fill=LINKSTATE_TL_RED)
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
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:248
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
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 OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
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|....
void setParametersStr(const std::string &paramsString, const std::string kvsep="=", const std::string sep="|")
set the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN"
std::string getParametersStr(const std::string kvsep="=", const std::string sep="|") const
Returns the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN".
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:158
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:48
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:149
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:197
PositionVector viaShape
shape of via
Definition: NBEdge.h:291
PositionVector shape
shape of Connection
Definition: NBEdge.h:279