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-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
17 // The Widget for modifying traffic lights
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #ifdef _MSC_VER
25 #include <windows_config.h>
26 #else
27 #include <config.h>
28 #endif
29 
30 #include <iostream>
40 
41 #include "GNETLSEditorFrame.h"
42 #include "GNEViewNet.h"
43 #include "GNEViewParent.h"
44 #include "GNENet.h"
45 #include "GNEJunction.h"
46 #include "GNEEdge.h"
47 #include "GNELane.h"
48 #include "GNEUndoList.h"
49 #include "GNEInternalLane.h"
50 #include "GNEChange_TLS.h"
51 
52 // ===========================================================================
53 // FOX callback mapping
54 // ===========================================================================
55 FXDEFMAP(GNETLSEditorFrame) GNETLSEditorFrameMap[] = {
56  FXMAPFUNC(SEL_COMMAND, MID_CANCEL, GNETLSEditorFrame::onCmdCancel),
57  FXMAPFUNC(SEL_UPDATE, MID_CANCEL, GNETLSEditorFrame::onUpdModified),
58  FXMAPFUNC(SEL_COMMAND, MID_OK, GNETLSEditorFrame::onCmdOK),
59  FXMAPFUNC(SEL_UPDATE, MID_OK, GNETLSEditorFrame::onUpdModified),
81 
82 
83 
84 };
85 
86 
87 // Object implementation
88 FXIMPLEMENT(GNETLSEditorFrame, FXVerticalFrame, GNETLSEditorFrameMap, ARRAYNUMBER(GNETLSEditorFrameMap))
89 
90 
91 // ===========================================================================
92 // method definitions
93 // ===========================================================================
94 GNETLSEditorFrame::GNETLSEditorFrame(FXHorizontalFrame* horizontalFrameParent, GNEViewNet* viewNet):
95  GNEFrame(horizontalFrameParent, viewNet, "Edit Traffic Light"),
96  myTableFont(new FXFont(getApp(), "Courier New", 9)),
97  myCurrentJunction(0),
98  myHaveModifications(false),
99  myEditedDef(0) {
100  // create groupbox for description
101  myGroupBoxJunction = new FXGroupBox(myContentFrame, "Junction", GUIDesignGroupBoxFrame);
102  // Create frame for junction ID
103  FXHorizontalFrame* junctionIDFrame = new FXHorizontalFrame(myGroupBoxJunction, GUIDesignAuxiliarHorizontalFrame);
104  myLabelJunctionID = new FXLabel(junctionIDFrame, "Junction ID", 0, GUIDesignLabelAttribute);
105  myTextFieldJunctionID = new FXTextField(junctionIDFrame, GUIDesignTextFieldNCol, this, MID_GNE_TLSFRAME_SELECT_JUNCTION, GUIDesignTextField);
106  myTextFieldJunctionID->setEditable(false);
107  // create frame for junction status
108  FXHorizontalFrame* junctionIDStatus = new FXHorizontalFrame(myGroupBoxJunction, GUIDesignAuxiliarHorizontalFrame);
109  myLabelJunctionStatus = new FXLabel(junctionIDStatus, "Status", 0, GUIDesignLabelAttribute);
110  myTextFieldJunctionStatus = new FXTextField(junctionIDStatus, GUIDesignTextFieldNCol, this, MID_GNE_TLSFRAME_UPDATE_STATUS, GUIDesignTextField);
111  myTextFieldJunctionStatus->setEditable(false);
112 
113  // create groupbox for tl df
114  myGroupBoxTLSDef = new FXGroupBox(myContentFrame, "Traffic lights definition", GUIDesignGroupBoxFrame);
115 
116  // create create tlDef button
117  myNewTLProgram = new FXButton(myGroupBoxTLSDef, "Create TLS\t\tCreate a new traffic light program", 0, this, MID_GNE_TLSFRAME_CREATE, GUIDesignButton);
118 
119  // create delete tlDef button
120  myDeleteTLProgram = new FXButton(myGroupBoxTLSDef, "Delete TLS\t\tDelete a traffic light program. If all programs are deleted the junction turns into a priority junction.", 0, this, MID_GNE_TLSFRAME_DELETE, GUIDesignButton);
121 
122  // create TLS attributes
123  myTLSAttributes = new TLSAttributes(myContentFrame, this);
124 
125  // create groupbox for phases
126  myGroupBoxPhases = new FXGroupBox(myContentFrame, "Phases", GUIDesignGroupBoxFrame);
127 
128  // create and configure phase table
129  myTableScroll = new FXScrollWindow(myGroupBoxPhases, LAYOUT_FILL_X | LAYOUT_FIX_HEIGHT);
130  myPhaseTable = new FXTable(myTableScroll, this, MID_GNE_TLSFRAME_PHASE_TABLE, GUIDesignTableLimitedHeight);
131  myPhaseTable->setColumnHeaderMode(LAYOUT_FIX_HEIGHT);
132  myPhaseTable->setColumnHeaderHeight(0);
133  myPhaseTable->setRowHeaderMode(LAYOUT_FIX_WIDTH);
134  myPhaseTable->setRowHeaderWidth(0);
135  myPhaseTable->hide();
136  myPhaseTable->setFont(myTableFont);
137  myPhaseTable->setHelpText("phase duration in seconds | phase state");
138 
139  // create total duration info label
140  myCycleDuration = new FXLabel(myGroupBoxPhases, "", 0, GUIDesignLabelLeft);
141 
142  // create new phase button
143  myInsertDuplicateButton = new FXButton(myGroupBoxPhases, "Copy Phase\t\tInsert duplicate phase after selected phase", 0, this, MID_GNE_TLSFRAME_PHASE_CREATE, GUIDesignButton);
144 
145  // create delete phase button
146  myDeleteSelectedPhaseButton = new FXButton(myGroupBoxPhases, "Delete Phase\t\tDelete selected phase", 0, this, MID_GNE_TLSFRAME_PHASE_DELETE, GUIDesignButton);
147  new FXButton(myGroupBoxPhases, "Cleanup States\t\tClean unused states from all phase.", 0, this, MID_GNE_TLSFRAME_CLEANUP, GUIDesignButton);
148 
149  // create groupbox for modifications
150  myGroupBoxModifications = new FXGroupBox(myContentFrame, "Modifications", GUIDesignGroupBoxFrame);
151 
152  // create discard modifications buttons
153  myDiscardModificationsButtons = new FXButton(myGroupBoxModifications, "Cancel\t\tDiscard program modifications (Esc)", 0, this, MID_CANCEL, GUIDesignButton);
154 
155  // create save modifications button
156  mySaveModificationsButtons = new FXButton(myGroupBoxModifications, "Save\t\tSave program modifications (Enter)", 0, this, MID_OK, GUIDesignButton);
157 
158 
159  // "Add 'off' program"
160  /*
161  new FXButton(myContentFrame, "Add \"Off\"-Program\t\tAdds a program for switching off this traffic light",
162  0, this, MID_GNE_TLSFRAME_ADDOFF, GUIDesignButton);
163  */
164 
165  updateDescription();
166 }
167 
168 
170  delete myTableFont;
171  cleanup();
172 }
173 
174 
175 void
177  if (myCurrentJunction == 0 || (!myHaveModifications && (junction != myCurrentJunction))) {
178  onCmdCancel(0, 0, 0);
179  myViewNet->getUndoList()->p_begin("modifying traffic light definition");
180  myCurrentJunction = junction;
184  } else {
185  myViewNet->setStatusBarText("Unsaved modifications. Abort or Save");
186  }
187 }
188 
189 
190 long
191 GNETLSEditorFrame::onCmdCancel(FXObject*, FXSelector, void*) {
192  if (myCurrentJunction != 0) {
194  cleanup();
195  myViewNet->update();
196  }
197  return 1;
198 }
199 
200 
201 long
202 GNETLSEditorFrame::onCmdOK(FXObject*, FXSelector, void*) {
203  if (myCurrentJunction != 0) {
204  if (myHaveModifications) {
206  std::vector<NBNode*> nodes = oldDefinition->getNodes();
207  for (auto it : nodes) {
208  GNEJunction* junction = myViewNet->getNet()->retrieveJunction(it->getID());
209  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, oldDefinition, false), true);
210  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myEditedDef, true), true);
211  }
212  myEditedDef = 0;
214  cleanup();
215  myViewNet->update();
216  } else {
217  onCmdCancel(0, 0, 0);
218  }
219  }
220  return 1;
221 }
222 
223 
224 long
225 GNETLSEditorFrame::onCmdDefCreate(FXObject*, FXSelector, void*) {
226  GNEJunction* junction = myCurrentJunction;
227  onCmdCancel(0, 0, 0); // abort because we onCmdOk assumes we wish to save an edited definition
230  } else {
231  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, 0, true, true), true);
232  }
233  editJunction(junction);
234  return 1;
235 }
236 
237 
238 long
239 GNETLSEditorFrame::onCmdDefDelete(FXObject*, FXSelector, void*) {
240  GNEJunction* junction = myCurrentJunction;
241  const bool changeType = myTLSAttributes->getNumberOfTLSDefinitions() == 1;
242  onCmdCancel(0, 0, 0); // abort because onCmdOk assumes we wish to save an edited definition
243  if (changeType) {
245  } else {
247  myViewNet->getUndoList()->add(new GNEChange_TLS(junction, tlDef, false), true);
248  }
249  return 1;
250 }
251 
252 
253 long
254 GNETLSEditorFrame::onCmdDefSwitch(FXObject*, FXSelector, void*) {
255  assert(myCurrentJunction != 0);
258  // logic may not have been recomputed yet. recompute to be sure
261  NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
262  if (tllogic != 0) {
263  // now we can be sure that the tlDef is up to date (i.e. re-guessed)
264  buildIinternalLanes(tlDef);
265  // create working copy from original def
266  delete myEditedDef;
267  myEditedDef = new NBLoadedSUMOTLDef(tlDef, tllogic);
268 
270  initPhaseTable();
272  myCycleDuration->show();
273  } else {
274  // tlDef has no valid logic (probably because id does not control any links
275  onCmdCancel(0, 0, 0);
276  myViewNet->setStatusBarText("Traffic light does not control any links");
277  }
278  return 1;
279 }
280 
281 
282 long
283 GNETLSEditorFrame::onUpdDefSwitch(FXObject* o, FXSelector, void*) {
284  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0 && !myHaveModifications;
285  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
286  return 1;
287 }
288 
289 
290 long
291 GNETLSEditorFrame::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
292  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0;
293  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
294  return 1;
295 }
296 
297 
298 long
299 GNETLSEditorFrame::onUpdNeedsDefAndPhase(FXObject* o, FXSelector, void*) {
300  // do not delete the last phase
301  const bool enable = myTLSAttributes->getNumberOfTLSDefinitions() > 0 && myPhaseTable->getNumRows() > 1;
302  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
303  return 1;
304 }
305 
306 
307 long
308 GNETLSEditorFrame::onUpdDefCreate(FXObject* o, FXSelector, void*) {
309  const bool enable = myCurrentJunction != 0 && !myHaveModifications;
310  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
311  return 1;
312 }
313 
314 
315 long
316 GNETLSEditorFrame::onUpdModified(FXObject* o, FXSelector, void*) {
317  bool enable = myHaveModifications;
318  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
319  return 1;
320 }
321 
322 
323 
324 long
325 GNETLSEditorFrame::onCmdDefOffset(FXObject*, FXSelector, void*) {
326  myHaveModifications = true;
328  return 1;
329 }
330 
331 
332 long
333 GNETLSEditorFrame::onCmdDefRename(FXObject*, FXSelector, void*) {
334  return 1;
335 }
336 
337 
338 long
339 GNETLSEditorFrame::onCmdDefSubRename(FXObject*, FXSelector, void*) {
340  return 1;
341 }
342 
343 
344 long
345 GNETLSEditorFrame::onCmdDefAddOff(FXObject*, FXSelector, void*) {
346  return 1;
347 }
348 
349 
350 long
351 GNETLSEditorFrame::onCmdGuess(FXObject*, FXSelector, void*) {
352  return 1;
353 }
354 
355 
356 long
357 GNETLSEditorFrame::onCmdPhaseSwitch(FXObject*, FXSelector, void*) {
358  const int index = myPhaseTable->getCurrentRow();
359  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[index];
360  myPhaseTable->selectRow(index);
361  // need not hold since links could have been deleted somewhere else and indices may be reused
362  // assert(phase.state.size() == myInternalLanes.size());
363  for (auto it : myInternalLanes) {
364  int tlIndex = it.first;
365  std::vector<GNEInternalLane*> lanes = it.second;
366  assert(tlIndex >= 0);
367  assert(tlIndex < (int)phase.state.size());
368  for (auto it_lane : lanes) {
369  it_lane->setLinkState((LinkState)phase.state[tlIndex]);
370  }
371  }
372  myViewNet->update();
373  return 1;
374 }
375 
376 
377 long
378 GNETLSEditorFrame::onCmdPhaseCreate(FXObject*, FXSelector, void*) {
379  myHaveModifications = true;
380  // allows insertion at first position by deselecting via arrow keys
381  int newIndex = myPhaseTable->getSelStartRow() + 1;
382  int oldIndex = MAX2(0, myPhaseTable->getSelStartRow());
383  // copy current row
384  const bool fixed = myEditedDef->getType() == TLTYPE_STATIC;
385  const SUMOTime duration = getSUMOTime(myPhaseTable->getItemText(oldIndex, 0));
386  const std::string state = myPhaseTable->getItemText(oldIndex, fixed ? 1 : 3).text();
387  myEditedDef->getLogic()->addStep(duration, state, newIndex);
388  myPhaseTable->setCurrentItem(newIndex, 0);
389  initPhaseTable(newIndex);
390  myPhaseTable->setFocus();
391  return 1;
392 }
393 
394 
395 long
396 GNETLSEditorFrame::onCmdPhaseDelete(FXObject*, FXSelector, void*) {
397  myHaveModifications = true;
398  const int newRow = MAX2((int)0, (int)myPhaseTable->getCurrentRow() - 1);
399  myEditedDef->getLogic()->deletePhase(myPhaseTable->getCurrentRow());
400  initPhaseTable(newRow);
401  myPhaseTable->setFocus();
402  return 1;
403 }
404 
405 
406 long
407 GNETLSEditorFrame::onCmdCleanup(FXObject*, FXSelector, void*) {
409  initPhaseTable(0);
410  myPhaseTable->setFocus();
411  return 1;
412 }
413 
414 
415 long
416 GNETLSEditorFrame::onCmdPhaseEdit(FXObject*, FXSelector, void* ptr) {
417  /* @note: there is a bug when copying/pasting rows: when this handler is
418  * called the value of the cell is not yet updated. This means you have to
419  * click inside the cell and hit enter to actually update the value */
420  FXTablePos* tp = (FXTablePos*)ptr;
421  FXString value = myPhaseTable->getItemText(tp->row, tp->col);
422  const bool fixed = myEditedDef->getType() == TLTYPE_STATIC;
423  if (tp->col == 0) {
424  // duration edited
425  if (GNEAttributeCarrier::canParse<double>(value.text())) {
426  SUMOTime duration = getSUMOTime(value);
427  if (duration > 0) {
428  myEditedDef->getLogic()->setPhaseDuration(tp->row, duration);
429  myHaveModifications = true;
431  return 1;
432  }
433  }
434  // input error, reset value
435  myPhaseTable->setItemText(tp->row, 0, toString(STEPS2TIME(getPhases()[tp->row].duration)).c_str());
436  } else if (!fixed && tp->col == 1) {
437  // minDur edited
438  if (GNEAttributeCarrier::canParse<double>(value.text())) {
439  SUMOTime minDur = getSUMOTime(value);
440  if (minDur > 0) {
441  myEditedDef->getLogic()->setPhaseMinDuration(tp->row, minDur);
442  myHaveModifications = true;
443  return 1;
444  }
445  } else if (StringUtils::prune(value.text()).empty()) {
447  myHaveModifications = true;
448  return 1;
449  }
450  // input error, reset value
451  myPhaseTable->setItemText(tp->row, 1, varDurString(getPhases()[tp->row].minDur).c_str());
452  } else if (!fixed && tp->col == 2) {
453  // minDur edited
454  if (GNEAttributeCarrier::canParse<double>(value.text())) {
455  SUMOTime maxDur = getSUMOTime(value);
456  if (maxDur > 0) {
457  myEditedDef->getLogic()->setPhaseMaxDuration(tp->row, maxDur);
458  myHaveModifications = true;
459  return 1;
460  }
461  } else if (StringUtils::prune(value.text()).empty()) {
463  myHaveModifications = true;
464  return 1;
465  }
466  // input error, reset value
467  myPhaseTable->setItemText(tp->row, 2, varDurString(getPhases()[tp->row].maxDur).c_str());
468  } else {
469  // state edited
470  try {
471  // insert phase with new step and delete the old phase
472  myEditedDef->getLogic()->addStep(getPhases()[tp->row].duration, value.text(), tp->row);
473  myEditedDef->getLogic()->deletePhase(tp->row + 1);
474  myHaveModifications = true;
475  onCmdPhaseSwitch(0, 0, 0);
476  } catch (ProcessError) {
477  // input error, reset value
478  myPhaseTable->setItemText(tp->row, 1, getPhases()[tp->row].state.c_str());
479  }
480  }
481  return 1;
482 }
483 
484 
485 void
487  if (myCurrentJunction == 0) {
488  myTextFieldJunctionID->setText("");
489  myTextFieldJunctionStatus->setText("");
490  } else {
492  myTextFieldJunctionID->setText(nbn->getID().c_str());
493  if (!nbn->isTLControlled()) {
494  myTextFieldJunctionStatus->setText("uncontrolled");
495  } else {
496  myTextFieldJunctionStatus->setText(myHaveModifications ? "modified" : "unmodified");
497  }
498  }
499 }
500 
501 
502 void
504  if (myCurrentJunction) {
506  }
507  // clean data structures
508  myCurrentJunction = 0;
509  myHaveModifications = false;
510  delete myEditedDef;
511  myEditedDef = 0;
512  buildIinternalLanes(0); // only clears
513  // clean up controls
515  initPhaseTable(); // only clears when there are no definitions
516  myCycleDuration->hide();
518 }
519 
520 
521 void
524  // clean up previous objects
525  for (auto it : myInternalLanes) {
526  for (auto it_intLanes : it.second) {
527  rtree.removeAdditionalGLObject(it_intLanes);
528  delete it_intLanes;
529  }
530  }
531  myInternalLanes.clear();
532  // create new internal lanes
533  if (tlDef != 0) {
534  const int NUM_POINTS = 10;
535  assert(myCurrentJunction);
537  std::string innerID = ":" + nbn->getID(); // see NWWriter_SUMO::writeInternalEdges
538  const NBConnectionVector& links = tlDef->getControlledLinks();
539  for (auto it : links) {
540  int tlIndex = it.getTLIndex();
541  PositionVector shape = nbn->computeInternalLaneShape(it.getFrom(), NBEdge::Connection(it.getFromLane(),
542  it.getTo(), it.getToLane()), NUM_POINTS);
543  GNEInternalLane* ilane = new GNEInternalLane(this, innerID + '_' + toString(tlIndex), shape, tlIndex);
544  rtree.addAdditionalGLObject(ilane);
545  myInternalLanes[tlIndex].push_back(ilane);
546  }
547  for (auto c : nbn->getCrossings()) {
548  GNEInternalLane* ilane = new GNEInternalLane(this, c->id, c->shape, c->tlLinkNo);
549  rtree.addAdditionalGLObject(ilane);
550  myInternalLanes[c->tlLinkNo].push_back(ilane);
551  }
552  }
553 }
554 
555 
556 std::string
559 }
560 
561 void
563  myPhaseTable->setVisibleRows(1);
564  myPhaseTable->setVisibleColumns(2);
565  myPhaseTable->hide();
567  const bool fixed = myEditedDef->getType() == TLTYPE_STATIC;
568  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
569  myPhaseTable->setTableSize((int)phases.size(), fixed ? 2 : 4);
570  myPhaseTable->setVisibleRows((int)phases.size());
571  myPhaseTable->setVisibleColumns(fixed ? 2 : 4);
572  for (int row = 0; row < (int)phases.size(); row++) {
573  myPhaseTable->setItemText(row, 0, toString(STEPS2TIME(phases[row].duration)).c_str());
574  if (!fixed) {
575  myPhaseTable->setItemText(row, 1, varDurString(phases[row].minDur).c_str());
576  myPhaseTable->setItemText(row, 2, varDurString(phases[row].maxDur).c_str());
577  }
578  myPhaseTable->setItemText(row, fixed ? 1 : 3, phases[row].state.c_str());
579  myPhaseTable->getItem(row, 1)->setJustify(FXTableItem::LEFT);
580  }
581  myPhaseTable->fitColumnsToContents(0, fixed ? 2 : 4);
582  myPhaseTable->setHeight((int)phases.size() * 21); // experimental
583  myPhaseTable->setCurrentItem(index, 0);
584  myPhaseTable->selectRow(index, true);
585  myPhaseTable->show();
586  myPhaseTable->setFocus();
587 
588  myTableScroll->setHeight(myPhaseTable->getHeight() + 10);
589  }
590  update();
591 }
592 
593 
594 const std::vector<NBTrafficLightLogic::PhaseDefinition>&
596  return myEditedDef->getLogic()->getPhases();
597 }
598 
599 
600 void
602  myHaveModifications = true;
603  if (myViewNet->changeAllPhases()) {
604  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
605  for (int row = 0; row < (int)phases.size(); row++) {
606  myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
607  }
608  } else {
609  myEditedDef->getLogic()->setPhaseState(myPhaseTable->getCurrentRow(), lane->getTLIndex(), lane->getLinkState());
610  }
611  initPhaseTable(myPhaseTable->getCurrentRow());
612  myPhaseTable->setFocus();
613 }
614 
615 
616 void
617 GNETLSEditorFrame::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* eventData) {
618  if (myEditedDef != 0) {
619  myHaveModifications = true;
621  std::set<std::string> fromIDs;
622  fromIDs.insert(lane->getMicrosimID());
623  GNEEdge& edge = lane->getParentEdge();
624  // if neither the lane nor its edge are selected, apply changes to the whole edge
626  for (auto it_lane : edge.getLanes()) {
627  fromIDs.insert(it_lane->getMicrosimID());
628  }
629  } else {
630  // if the edge is selected, apply changes to all lanes of all selected edges
631  if (gSelected.isSelected(GLO_EDGE, edge.getGlID())) {
632  std::vector<GNEEdge*> edges = myViewNet->getNet()->retrieveEdges(true);
633  for (auto it : edges) {
634  for (auto it_lane : it->getLanes()) {
635  fromIDs.insert(it_lane->getMicrosimID());
636  }
637  }
638  }
639  // if the lane is selected, apply changes to all selected lanes
640  if (gSelected.isSelected(GLO_LANE, lane->getGlID())) {
641  std::vector<GNELane*> lanes = myViewNet->getNet()->retrieveLanes(true);
642  for (auto it_lane : lanes) {
643  fromIDs.insert(it_lane->getMicrosimID());
644  }
645  }
646 
647  }
648  // set new state for all connections from the chosen lane IDs
649  for (auto it : links) {
650  if (fromIDs.count(it.getFrom()->getLaneID(it.getFromLane())) > 0) {
651  std::vector<GNEInternalLane*> lanes = myInternalLanes[it.getTLIndex()];
652  for (auto it_lane : lanes) {
653  it_lane->onDefault(obj, sel, eventData);
654  }
655  }
656  }
657  }
658 }
659 
660 
661 bool
663  if (myEditedDef != 0) {
665  for (auto it : links) {
666  if (it.getFrom()->getID() == edge.getMicrosimID()) {
667  return true;
668  }
669  }
670  }
671  return false;
672 }
673 
674 
675 SUMOTime
676 GNETLSEditorFrame::getSUMOTime(const FXString& string) {
677  assert(GNEAttributeCarrier::canParse<double>(string.text()));
678  return TIME2STEPS(GNEAttributeCarrier::parse<double>(string.text()));
679 }
680 
681 
682 void
684  SUMOTime cycleDuration = 0;
685  for (auto it : getPhases()) {
686  cycleDuration += it.duration;
687  }
688  std::string text = "Cycle time: " + toString(STEPS2TIME(cycleDuration));
689  myCycleDuration->setText(text.c_str());
690 }
691 
692 
693 // ---------------------------------------------------------------------------
694 // GNETLSEditorFrame::TLSAttributes - methods
695 // ---------------------------------------------------------------------------
696 
698  FXGroupBox(parent, "Traffic light Attributes", GUIDesignGroupBoxFrame),
699  myTLSEditorParent(TLSEditorParent) {
700 
701  // create frame, label and textfield for name (By default disabled)
702  FXHorizontalFrame* nameFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
703  myNameLabel = new FXLabel(nameFrame, "ID", 0, GUIDesignLabelAttribute);
705  myNameTextField->disable();
706 
707  // create frame, label and comboBox for Program (By default hidden)
708  FXHorizontalFrame* programFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
709  myProgramLabel = new FXLabel(programFrame, "Program", 0, GUIDesignLabelAttribute);
711  myProgramComboBox->disable();
712 
713  // create frame, label and TextField for Offset (By default disabled)
714  FXHorizontalFrame* offsetFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
715  myOffsetLabel = new FXLabel(offsetFrame, "Offset", 0, GUIDesignLabelAttribute);
717  myOffsetTextField->disable();
718 }
719 
720 
722 
723 
724 void
726  assert(junction);
727  myTLSDefinitions.clear();
728  // enable name TextField
729  myNameTextField->enable();
730  // enable Offset
731  myOffsetTextField->enable();
732  // obtain TLSs
733  for (auto it : junction->getNBNode()->getControllingTLS()) {
734  myTLSDefinitions.push_back(it);
735  myNameTextField->setText(it->getID().c_str());
736  myNameTextField->enable();
737  myProgramComboBox->appendItem(it->getProgramID().c_str());
738  }
739  if (myTLSDefinitions.size() > 0) {
740  myProgramComboBox->enable();
741  myProgramComboBox->setCurrentItem(0);
742  myProgramComboBox->setNumVisible(myProgramComboBox->getNumItems());
744  }
745 }
746 
747 
748 void
750  // clear definitions
751  myTLSDefinitions.clear();
752  // clear and disable name TextField
753  myNameTextField->setText("");
754  myNameTextField->disable();
755  // clear and disable myProgramComboBox
756  myProgramComboBox->clearItems();
757  myProgramComboBox->disable();
758  // clear and disable Offset TextField
759  myOffsetTextField->setText("");
760  myOffsetTextField->disable();
761 }
762 
763 
766  return myTLSDefinitions.at(myProgramComboBox->getCurrentItem());
767 }
768 
769 
770 int
772  return (int)myTLSDefinitions.size();
773 }
774 
775 
776 int
778  return myProgramComboBox->getNumItems();
779 }
780 
781 
782 SUMOTime
784  return getSUMOTime(myOffsetTextField->getText());
785 }
786 
787 
788 void
790  myOffsetTextField->setText(toString(STEPS2TIME(offset)).c_str());
791 }
792 
793 /****************************************************************************/
int NUM_POINTS
TLIndexMap myInternalLanes
selected junction von TLS
Definition: GUIAppEnum.h:587
long onCmdGuess(FXObject *, FXSelector, void *)
Called when the user presses the button Guess.
std::vector< GNELane * > retrieveLanes(bool onlySelected=false)
return all lanes
Definition: GNENet.cpp:986
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:161
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:199
FXTable * myPhaseTable
table for selecting and rearranging phases and for changing 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.
SUMOTime getOffset() const
Returns the offset of first switch.
long onCmdDefCreate(FXObject *, FXSelector, void *)
Called when the user creates a TLS.
void setPhaseMaxDuration(int phaseIndex, SUMOTime duration)
FXLabel * myOffsetLabel
offset label
void setOffset(SUMOTime offset)
Sets the offset of this tls.
Ok-button pressed.
Definition: GUIAppEnum.h:62
A loaded (complete) traffic light logic.
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:408
TLSAttributes * myTLSAttributes
TLS attributes.
PositionVector computeInternalLaneShape(NBEdge *fromE, const NBEdge::Connection &con, int numPoints, NBNode *recordError=0) const
Compute the shape for an internal lane.
Definition: NBNode.cpp:626
#define GUIDesignComboBoxAttribute
Combo box static (cannot be edited) extended over the matrix column.
Definition: GUIDesigns.h:195
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.cpp:2038
long onCmdPhaseSwitch(FXObject *, FXSelector, void *)
Called when the user switchs a Phase.
TrafficLightType getType() const
get the algorithm type (static etc..)
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
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:140
The base class for traffic light logic definitions.
FXScrollWindow * myTableScroll
window for oversized phase tables
void setPhaseMinDuration(int phaseIndex, SUMOTime duration)
FXComboBox * myProgramComboBox
the comboBox for selecting the tl-definition to edit
T MAX2(T a, T b)
Definition: StdDefs.h:73
bool isSelected(GUIGlObjectType type, GUIGlID id)
Returns the information whether the object with the given type and id is selected.
static const SUMOTime UNSPECIFIED_DURATION
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:53
void editJunction(GNEJunction *junction)
edits the traffic light for the given junction
Cancel-button pressed.
Definition: GUIAppEnum.h:64
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:84
switch between programs
Definition: GUIAppEnum.h:595
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
replace program with a newly guessed program
Definition: GUIAppEnum.h:591
const std::string & getID() const
Returns the id.
Definition: Named.h:65
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
void handleMultiChange(GNELane *lane, FXObject *obj, FXSelector sel, void *data)
update phase definition for the current traffic light and phase
The definition of a single phase of the logic.
FXLabel * myProgramLabel
program label
long onUpdNeedsDef(FXObject *, FXSelector, void *)
Called when occurs an update of needs definition.
A RT-tree for efficient storing of SUMO&#39;s GL-objects.
Definition: SUMORTree.h:73
FXFont * myTableFont
font for the phase table
long onCmdCleanup(FXObject *, FXSelector, void *)
Called when the user cleans up states.
LinkState getLinkState() const
whether link state has been modfied
long onCmdDefDelete(FXObject *, FXSelector, void *)
Called when the user deletes a TLS.
long onCmdDefOffset(FXObject *, FXSelector, void *)
Called when the user changes the offset of a TLS.
long onCmdDefSwitch(FXObject *, FXSelector, void *)
Called when the user switchs a TLS.
long onCmdDefAddOff(FXObject *, FXSelector, void *)
Called when the user adds a OFF.
bool changeAllPhases() const
change all phases
Definition: GNEViewNet.cpp:358
GNEViewNet * myViewNet
View Net for changes.
Definition: GNEFrame.h:337
void clearTLSAttributes()
clear TLS attributes
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:297
std::string getAttribute(SumoXMLAttr key) const
This functions has to be implemented in all GNEAttributeCarriers.
GNEUndoList * getUndoList() const
get the undoList object
GNETLSEditorFrame * myTLSEditorParent
pointer to TLSEditorParent
FXTextField * myNameTextField
name text field
#define GUIDesignTextField
Definition: GUIDesigns.h:40
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
create phase thable
Definition: GUIAppEnum.h:609
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:1121
NBTrafficLightDefinition * getCurrentTLSDefinition() const
get current definition
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:91
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true)
get junction by id
Definition: GNENet.cpp:889
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames ...
Definition: GUIDesigns.h:246
A list of positions.
bool controlsEdge(GNEEdge &edge) const
whether the given edge is controlled by the currently edited tlDef
long onUpdDefCreate(FXObject *, FXSelector, void *)
Called when occurs an update of create definition.
void buildIinternalLanes(NBTrafficLightDefinition *tlDef)
builds internal lanes for the given tlDef
bool myHaveModifications
whether the current tls was modified
cleanup unused states
Definition: GUIAppEnum.h:613
long onCmdPhaseEdit(FXObject *, FXSelector, void *)
Called when the user edits a Phase.
#define STEPS2TIME(x)
Definition: SUMOTime.h:64
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:1292
~GNETLSEditorFrame()
Destructor.
void handleChange(GNEInternalLane *lane)
update phase definition for the current traffic light and phase
int getTLIndex() const
get Traffic Light index
NBTrafficLightLogic * getLogic()
Returns the internal logic.
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
FXDEFMAP(GNETLSEditorFrame) GNETLSEditorFrameMap[]
add off to TLS
Definition: GUIAppEnum.h:605
void p_abort()
reverts and discards ALL active command groups
SUMORTree & getVisualisationSpeedUp()
Returns the RTree used for visualisation speed-up.
Definition: GNENet.cpp:300
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
static SUMOTime getSUMOTime(const FXString &string)
converts to SUMOTime
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:56
int getNumberOfTLSDefinitions() const
get number of definitions
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:49
long onUpdDefSwitch(FXObject *, FXSelector, void *)
Called when occurs an update of switch definition.
#define GUIDesignButton
Definition: GUIDesigns.h:56
void updateCycleDuration()
recomputes cycle duration and updates label
static std::string varDurString(SUMOTime dur)
convert duration (potentially undefined) to string
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:51
const std::vector< GNELane * > & getLanes()
returns a reference to the lane vector
Definition: GNEEdge.cpp:653
int getNumberOfPrograms() const
get number of programs
std::vector< GNEEdge * > retrieveEdges(bool onlySelected=false)
return all edges
Definition: GNENet.cpp:974
void addAdditionalGLObject(GUIGlObject *o)
Adds an additional object (detector/shape/trigger) for visualisation.
Definition: SUMORTree.h:128
#define GUIDesignGroupBoxFrame
Group box design extended over frame.
Definition: GUIDesigns.h:221
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:302
TLSAttributes(FXComposite *parent, GNETLSEditorFrame *TLSEditorParent)
constructor
long onCmdOK(FXObject *, FXSelector, void *)
SUMOTime getOffset() const
get current offset in SUMOTIme
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.
an edge
void setOffset(SUMOTime offset)
set new offset
GNEJunction * myCurrentJunction
the junction of the tls is being modified
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)
GNENet * getNet() const
get the net object
#define GUIDesignTextFieldReal
text field extended over Frame with thick frame and limited to Doubles/doubles
Definition: GUIDesigns.h:46
long onCmdPhaseCreate(FXObject *, FXSelector, void *)
Called when the user creates a Phase.
Represents a single node (junction) during network building.
Definition: NBNode.h:74
GUIGlID getGlID() const
Returns the numerical id of the object.
void setStatusBarText(const std::string &text)
set staturBar text
Definition: GNEViewNet.cpp:322
FXTextField * myTextFieldJunctionStatus
text field for junction status
long long int SUMOTime
Definition: TraCIDefs.h:51
definition related controls
Definition: GUIAppEnum.h:593
select phase thable
Definition: GUIAppEnum.h:607
#define GUIDesignLabelLeft
Definition: GUIDesigns.h:143
void addStep(SUMOTime duration, const std::string &state, int index=-1)
Adds a phase to the logic.
long onCmdDefRename(FXObject *, FXSelector, void *)
Called when the user renames a TLS.
long onUpdModified(FXObject *, FXSelector, void *)
Called when occurs an update of modified.
#define GUIDesignLabelAttribute
label extended over the matrix column with thick frame and height of 23
Definition: GUIDesigns.h:164
FXTextField * myOffsetTextField
the control for modifying offset
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.
GUISelectedStorage gSelected
A global holder of selected objects.
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:1613
NBLoadedSUMOTLDef * myEditedDef
the traffic light definition being edited
void updateDescription() const
update descrition
FXTextField * myTextFieldJunctionID
text field for junction ID
std::vector< NBTrafficLightDefinition * > myTLSDefinitions
the list of Definitions for the current junction
void cleanup()
cleans up previous lanes
delete phase thable
Definition: GUIAppEnum.h:611
FXLabel * myCycleDuration
label with the cycle duration
void initPhaseTable(int index=0)
initialies the phase table