SUMO - Simulation of Urban MObility
GNETLSEditor.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // The Widget for modifying traffic lights
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
10 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
11 /****************************************************************************/
12 //
13 // This file is part of SUMO.
14 // SUMO is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #ifdef _MSC_VER
26 #include <windows_config.h>
27 #else
28 #include <config.h>
29 #endif
30 
31 #ifdef HAVE_VERSION_H
32 #include <version.h>
33 #endif
34 
35 #include <iostream>
45 #include "GNETLSEditor.h"
46 #include "GNEViewNet.h"
47 #include "GNENet.h"
48 #include "GNEJunction.h"
49 #include "GNEEdge.h"
50 #include "GNELane.h"
51 #include "GNEUndoList.h"
52 #include "GNEInternalLane.h"
53 #include "GNEChange_TLS.h"
54 
55 #ifdef CHECK_MEMORY_LEAKS
56 #include <foreign/nvwa/debug_new.h>
57 #endif // CHECK_MEMORY_LEAKS
58 
59 // ===========================================================================
60 // FOX callback mapping
61 // ===========================================================================
62 FXDEFMAP(GNETLSEditor) GNETLSEditorMap[] = {
63  FXMAPFUNC(SEL_COMMAND, MID_CANCEL, GNETLSEditor::onCmdCancel),
64  FXMAPFUNC(SEL_COMMAND, MID_OK, GNETLSEditor::onCmdOK),
65  FXMAPFUNC(SEL_COMMAND, MID_GNE_DEF_CREATE, GNETLSEditor::onCmdDefCreate),
66  FXMAPFUNC(SEL_COMMAND, MID_GNE_DEF_DELETE, GNETLSEditor::onCmdDefDelete),
67  FXMAPFUNC(SEL_COMMAND, MID_GNE_DEF_SWITCH, GNETLSEditor::onCmdDefSwitch),
68  FXMAPFUNC(SEL_COMMAND, MID_GNE_DEF_OFFSET, GNETLSEditor::onCmdDefOffset),
69  FXMAPFUNC(SEL_COMMAND, MID_GNE_DEF_RENAME, GNETLSEditor::onCmdDefRename),
71  FXMAPFUNC(SEL_COMMAND, MID_GNE_DEF_ADDOFF, GNETLSEditor::onCmdDefAddOff),
72  FXMAPFUNC(SEL_COMMAND, MID_GNE_GUESS_PROGRAM, GNETLSEditor::onCmdGuess),
75  FXMAPFUNC(SEL_SELECTED, MID_GNE_PHASE_TABLE, GNETLSEditor::onCmdPhaseSwitch),
76  FXMAPFUNC(SEL_DESELECTED, MID_GNE_PHASE_TABLE, GNETLSEditor::onCmdPhaseSwitch),
77  FXMAPFUNC(SEL_CHANGED, MID_GNE_PHASE_TABLE, GNETLSEditor::onCmdPhaseSwitch),
78  FXMAPFUNC(SEL_REPLACED, MID_GNE_PHASE_TABLE, GNETLSEditor::onCmdPhaseEdit),
79 
80  FXMAPFUNC(SEL_UPDATE, MID_GNE_DEF_CREATE, GNETLSEditor::onUpdDefCreate),
81  FXMAPFUNC(SEL_UPDATE, MID_GNE_DEF_DELETE, GNETLSEditor::onUpdDefSwitch),
82  FXMAPFUNC(SEL_UPDATE, MID_GNE_DEF_SWITCH, GNETLSEditor::onUpdDefSwitch),
83  FXMAPFUNC(SEL_UPDATE, MID_GNE_DEF_OFFSET, GNETLSEditor::onUpdNeedsDef),
84  FXMAPFUNC(SEL_UPDATE, MID_GNE_PHASE_CREATE, GNETLSEditor::onUpdNeedsDef),
86  FXMAPFUNC(SEL_UPDATE, MID_CANCEL, GNETLSEditor::onUpdModified),
87  FXMAPFUNC(SEL_UPDATE, MID_OK, GNETLSEditor::onUpdModified),
88 };
89 
90 
91 // Object implementation
92 FXIMPLEMENT(GNETLSEditor, FXScrollWindow, GNETLSEditorMap, ARRAYNUMBER(GNETLSEditorMap))
93 
94 // ===========================================================================
95 // static members
96 // ===========================================================================
97 const int GNETLSEditor::WIDTH = 140;
98 
99 // ===========================================================================
100 // method definitions
101 // ===========================================================================
102 GNETLSEditor::GNETLSEditor(FXComposite* parent, GNEViewNet* updateTarget, GNEUndoList* undoList):
103  FXScrollWindow(parent, LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, WIDTH, 0),
104  myHeaderFont(new FXFont(getApp(), "Arial", 11, FXFont::Bold)),
105  myTableFont(new FXFont(getApp(), "Courier New", 9)),
106  myCurrentJunction(0),
107  myUndoList(undoList),
108  myUpdateTarget(updateTarget),
109  myHaveModifications(false),
110  myEditedDef(0) {
111  // heading
112  myContentFrame = new FXVerticalFrame(this, LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, WIDTH, 0);
113  FXLabel* heading = new FXLabel(myContentFrame, "Edit Traffic Light", 0, JUSTIFY_LEFT);
114  heading->setFont(myHeaderFont);
115  myDescription = new FXLabel(myContentFrame, "", 0, JUSTIFY_LEFT);
116  new FXHorizontalSeparator(myContentFrame, SEPARATOR_GROOVE | LAYOUT_FILL_X, 0, 0, 0, 2, 2, 2, 4, 4);
117 
118  // create tlDef button
119  new FXButton(myContentFrame, "Create TLS\t\tCreate a new traffic light program", 0, this, MID_GNE_DEF_CREATE,
120  ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
121  0, 0, 0, 0, 4, 4, 3, 3);
122 
123  // delete tlDef button
124  new FXButton(myContentFrame,
125  "Delete TLS\t\tDelete a traffic light program. If all programs are deleted the junction turns into a priority junction.",
126  0, this, MID_GNE_DEF_DELETE, ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
127  0, 0, 0, 0, 4, 4, 3, 3);
128 
129  // definitions list
130  new FXLabel(myContentFrame, "Name, Program");
131  myDefBox = new FXListBox(myContentFrame, this, MID_GNE_DEF_SWITCH,
132  FRAME_SUNKEN | FRAME_THICK | LISTBOX_NORMAL | LAYOUT_FIX_WIDTH, 0, 0, WIDTH - 4);
133 
134  // offset control
135  new FXLabel(myContentFrame, "Offset");
136  myOffset = new FXTextField(myContentFrame, 6,
137  this, MID_GNE_DEF_OFFSET, TEXTFIELD_NORMAL | TEXTFIELD_REAL, 0, 0, 0, 0, 4, 2, 0, 2);
138 
139  new FXHorizontalSeparator(myContentFrame, SEPARATOR_GROOVE | LAYOUT_FILL_X, 0, 0, 0, 2, 2, 2, 4, 4);
140 
141  // phase table
142  new FXLabel(myContentFrame, "Phases");
143  myPhaseTable = new FXTable(myContentFrame, this, MID_GNE_PHASE_TABLE, LAYOUT_FIX_HEIGHT | LAYOUT_FIX_WIDTH);
144  myPhaseTable->setColumnHeaderMode(LAYOUT_FIX_HEIGHT);
145  myPhaseTable->setColumnHeaderHeight(0);
146  myPhaseTable->setRowHeaderMode(LAYOUT_FIX_WIDTH);
147  myPhaseTable->setRowHeaderWidth(0);
148  myPhaseTable->hide();
149  myPhaseTable->setFont(myTableFont);
150  myPhaseTable->setHelpText("phase duration in seconds | phase state");
151 
152  // total duration info
153  myCycleDuration = new FXLabel(myContentFrame, "");
154 
155  // insert new phase button
156  new FXButton(myContentFrame, "Copy Phase\t\tInsert duplicate phase after selected phase", 0, this, MID_GNE_PHASE_CREATE,
157  ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
158  0, 0, 0, 0, 4, 4, 3, 3);
159 
160  // delete phase button
161  new FXButton(myContentFrame, "Delete Phase\t\tDelete selected phase", 0, this, MID_GNE_PHASE_DELETE,
162  ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
163  0, 0, 0, 0, 4, 4, 3, 3);
164 
165  new FXHorizontalSeparator(myContentFrame, SEPARATOR_GROOVE | LAYOUT_FILL_X, 0, 0, 0, 2, 2, 2, 4, 4);
166  // buttons
167  // "Cancel"
168  new FXButton(myContentFrame, "Cancel\t\tDiscard program modifications (Esc)", 0, this, MID_CANCEL,
169  ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
170  0, 0, 0, 0, 4, 4, 3, 3);
171  // "OK"
172  new FXButton(myContentFrame, "Save\t\tSave program modifications (Enter)", 0, this, MID_OK,
173  ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
174  0, 0, 0, 0, 4, 4, 3, 3);
175  new FXHorizontalSeparator(myContentFrame, SEPARATOR_GROOVE | LAYOUT_FILL_X, 0, 0, 0, 2, 2, 2, 4, 4);
176  // "Add 'off' program"
177  /*
178  new FXButton(myContentFrame, "Add \"Off\"-Program\t\tAdds a program for switching off this traffic light",
179  0, this, MID_GNE_DEF_ADDOFF,
180  ICON_BEFORE_TEXT|LAYOUT_FILL_X|FRAME_THICK|FRAME_RAISED,
181  0, 0, 0, 0, 4, 4, 3, 3);
182  */
183 }
184 
185 
187  delete myHeaderFont;
188  delete myTableFont;
189  cleanup();
190 }
191 
192 
193 void
195  if (myCurrentJunction == 0 || (!myHaveModifications && (junction != myCurrentJunction))) {
196  onCmdCancel(0, 0, 0);
197  myUndoList->p_begin("modifying traffic light definition");
198  myCurrentJunction = junction;
200  initDefinitions();
201  } else {
202  myUpdateTarget->setStatusBarText("Unsaved modifications. Abort or Save");
203  }
204 }
205 
206 
207 long
208 GNETLSEditor::onCmdCancel(FXObject*, FXSelector, void*) {
209  if (myCurrentJunction != 0) {
210  myUndoList->p_abort();
211  cleanup();
212  myUpdateTarget->update();
213  }
214  return 1;
215 }
216 
217 
218 long
219 GNETLSEditor::onCmdOK(FXObject*, FXSelector, void*) {
220  if (myCurrentJunction != 0) {
221  if (myHaveModifications) {
222  NBTrafficLightDefinition* old = myDefinitions[myDefBox->getCurrentItem()];
223  std::vector<NBNode*> nodes = old->getNodes();
224  for (std::vector<NBNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
225  GNEJunction* junction = myUpdateTarget->getNet()->retrieveJunction((*it)->getID());
226  myUndoList->add(new GNEChange_TLS(junction, old, false), true);
227  myUndoList->add(new GNEChange_TLS(junction, myEditedDef, true), true);
228  }
229  myEditedDef = 0;
230  myUndoList->p_end();
231  cleanup();
232  myUpdateTarget->update();
233  } else {
234  onCmdCancel(0, 0, 0);
235  }
236  }
237  return 1;
238 }
239 
240 
241 long
242 GNETLSEditor::onCmdDefCreate(FXObject*, FXSelector, void*) {
243  GNEJunction* junction = myCurrentJunction;
244  onCmdCancel(0, 0, 0); // abort because we onCmdOk assumes we wish to save an edited definition
247  } else {
248  myUndoList->add(new GNEChange_TLS(junction, 0, true, true), true);
249  }
250  editJunction(junction);
251  return 1;
252 }
253 
254 
255 long
256 GNETLSEditor::onCmdDefDelete(FXObject*, FXSelector, void*) {
257  GNEJunction* junction = myCurrentJunction;
258  const bool changeType = myDefinitions.size() == 1;
259  onCmdCancel(0, 0, 0); // abort because onCmdOk assumes we wish to save an edited definition
260  if (changeType) {
262  } else {
263  NBTrafficLightDefinition* tlDef = myDefinitions[myDefBox->getCurrentItem()];
264  myUndoList->add(new GNEChange_TLS(junction, tlDef, false), true);
265  }
266  return 1;
267 }
268 
269 
270 long
271 GNETLSEditor::onCmdDefSwitch(FXObject*, FXSelector, void*) {
272  assert(myCurrentJunction != 0);
273  assert((int)myDefinitions.size() == myDefBox->getNumItems());
274  NBTrafficLightDefinition* tlDef = myDefinitions[myDefBox->getCurrentItem()];
275  // logic may not have been recomputed yet. recompute to be sure
278  NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
279  if (tllogic != 0) {
280  // now we can be sure that the tlDef is up to date (i.e. re-guessed)
281  buildIinternalLanes(tlDef);
282  // create working copy from original def
283  delete myEditedDef;
284  myEditedDef = new NBLoadedSUMOTLDef(tlDef, tllogic);
285  myOffset->setText(toString(STEPS2TIME(myEditedDef->getLogic()->getOffset())).c_str());
286  initPhaseTable();
288  } else {
289  // tlDef has no valid logic (probably because id does not control any links
290  onCmdCancel(0, 0, 0);
291  myUpdateTarget->setStatusBarText("Traffic light does not control any links");
292  }
293  return 1;
294 }
295 
296 
297 long
298 GNETLSEditor::onUpdDefSwitch(FXObject* o, FXSelector, void*) {
299  const bool enable = myDefinitions.size() > 0 && !myHaveModifications;
300  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
301  return 1;
302 }
303 
304 
305 long
306 GNETLSEditor::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
307  const bool enable = myDefinitions.size() > 0;
308  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
309  return 1;
310 }
311 
312 
313 long
314 GNETLSEditor::onUpdNeedsDefAndPhase(FXObject* o, FXSelector, void*) {
315  // do not delete the last phase
316  const bool enable = myDefinitions.size() > 0 && myPhaseTable->getNumRows() > 1;
317  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
318  return 1;
319 }
320 
321 
322 long
323 GNETLSEditor::onUpdDefCreate(FXObject* o, FXSelector, void*) {
324  const bool enable = myCurrentJunction != 0 && !myHaveModifications;
325  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
326  return 1;
327 }
328 
329 
330 long
331 GNETLSEditor::onUpdModified(FXObject* o, FXSelector, void*) {
332  bool enable = myHaveModifications;
333  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
334  return 1;
335 }
336 
337 
338 
339 long
340 GNETLSEditor::onCmdDefOffset(FXObject*, FXSelector, void*) {
341  myHaveModifications = true;
343  return 1;
344 }
345 
346 
347 long
348 GNETLSEditor::onCmdDefRename(FXObject*, FXSelector, void*) {
349  return 1;
350 }
351 
352 
353 long
354 GNETLSEditor::onCmdDefSubRename(FXObject*, FXSelector, void*) {
355  return 1;
356 }
357 
358 
359 long
360 GNETLSEditor::onCmdDefAddOff(FXObject*, FXSelector, void*) {
361  return 1;
362 }
363 
364 
365 long
366 GNETLSEditor::onCmdGuess(FXObject*, FXSelector, void*) {
367  return 1;
368 }
369 
370 
371 long
372 GNETLSEditor::onCmdPhaseSwitch(FXObject*, FXSelector, void*) {
373  const unsigned int index = myPhaseTable->getCurrentRow();
374  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[index];
375  myPhaseTable->selectRow(index);
376  // need not hold since links could have been deleted somewhere else and indices may be reused
377  // assert(phase.state.size() == myInternalLanes.size());
378  for (TLIndexMap::iterator it = myInternalLanes.begin(); it != myInternalLanes.end(); it++) {
379  int tlIndex = it->first;
380  std::vector<GNEInternalLane*> lanes = it->second;
381  assert(tlIndex >= 0);
382  assert(tlIndex < (int)phase.state.size());
383  for (std::vector<GNEInternalLane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
384  (*it_lane)->setLinkState((LinkState)phase.state[tlIndex]);
385  }
386  }
387  myUpdateTarget->update();
388  return 1;
389 }
390 
391 
392 long
393 GNETLSEditor::onCmdPhaseCreate(FXObject*, FXSelector, void*) {
394  myHaveModifications = true;
395  // allows insertion at first position by deselecting via arrow keys
396  unsigned int newIndex = myPhaseTable->getSelStartRow() + 1;
397  unsigned int oldIndex = MAX2(0, myPhaseTable->getSelStartRow());
398  // copy current row
399  const SUMOTime duration = getSUMOTime(myPhaseTable->getItemText(oldIndex, 0));
400  const std::string state = myPhaseTable->getItemText(oldIndex, 1).text();
401  myEditedDef->getLogic()->addStep(duration, state, newIndex);
402  myPhaseTable->setCurrentItem(newIndex, 0);
403  initPhaseTable(newIndex);
404  myPhaseTable->setFocus();
405  return 1;
406 }
407 
408 
409 long
410 GNETLSEditor::onCmdPhaseDelete(FXObject*, FXSelector, void*) {
411  myHaveModifications = true;
412  const int newRow = MAX2((int)0, (int)myPhaseTable->getCurrentRow() - 1);
413  myEditedDef->getLogic()->deletePhase(myPhaseTable->getCurrentRow());
414  initPhaseTable(newRow);
415  myPhaseTable->setFocus();
416  return 1;
417 }
418 
419 
420 long
421 GNETLSEditor::onCmdPhaseEdit(FXObject*, FXSelector, void* ptr) {
422  /* @note: there is a bug when copying/pasting rows: when this handler is
423  * called the value of the cell is not yet updated. This means you have to
424  * click inside the cell and hit enter to actually update the value */
425  FXTablePos* tp = (FXTablePos*)ptr;
426  FXString value = myPhaseTable->getItemText(tp->row, tp->col);
427  if (tp->col == 0) {
428  // duration edited
429  if (GNEAttributeCarrier::canParse<SUMOReal>(value.text())) {
430  SUMOTime duration = getSUMOTime(value);
431  if (duration > 0) {
432  myEditedDef->getLogic()->setPhaseDuration(tp->row, duration);
433  myHaveModifications = true;
435  return 1;
436  }
437  }
438  // input error, reset value
439  myPhaseTable->setItemText(tp->row, 0, toString(STEPS2TIME(getPhases()[tp->row].duration)).c_str());
440  } else {
441  // state edited
442  try {
443  // insert phase with new step and delete the old phase
444  myEditedDef->getLogic()->addStep(getPhases()[tp->row].duration, value.text(), tp->row);
445  myEditedDef->getLogic()->deletePhase(tp->row + 1);
446  myHaveModifications = true;
447  onCmdPhaseSwitch(0, 0, 0);
448  } catch (ProcessError) {
449  // input error, reset value
450  myPhaseTable->setItemText(tp->row, 1, getPhases()[tp->row].state.c_str());
451  }
452  }
453  return 1;
454 }
455 
456 
457 void
459  std::string description;
460  if (myCurrentJunction == 0) {
461  description = "No Junction Selected\n";
462  } else {
464  description = "Junction '" + nbn->getID() + "'\n(";
465  if (!nbn->isTLControlled()) {
466  description += "uncontrolled, ";
467  }
468  description += (myHaveModifications ? "modified)" : "unmodified)");
469  }
470  myDescription->setText(description.c_str());
471 }
472 
473 
474 void
476  if (myCurrentJunction) {
478  }
479  // clean data structures
480  myCurrentJunction = 0;
481  myHaveModifications = false;
482  delete myEditedDef;
483  myEditedDef = 0;
484  buildIinternalLanes(0); // only clears
485  // clean up controls
486  myOffset->setText("");
487  myDefinitions.clear();
488  myDefBox->hide();
489  initPhaseTable(); // only clears when there are no definitions
490  myCycleDuration->hide();
492 }
493 
494 
495 void
497  // clean up previous objects
499  for (TLIndexMap::iterator it = myInternalLanes.begin(); it != myInternalLanes.end(); it++) {
500  std::vector<GNEInternalLane*> lanes = it->second;
501  for (std::vector<GNEInternalLane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
502  rtree.removeAdditionalGLObject(*it_lane);
503  delete *it_lane;
504  }
505  }
506  myInternalLanes.clear();
507  if (tlDef != 0) {
508  const int NUM_POINTS = 10;
509  assert(myCurrentJunction);
512  std::string innerID = ":" + nbn->getID(); // see NWWriter_SUMO::writeInternalEdges
513  const NBConnectionVector& links = tlDef->getControlledLinks();
514  for (NBConnectionVector::const_iterator it = links.begin(); it != links.end(); it++) {
515  int tlIndex = it->getTLIndex();
516  PositionVector shape = nbn->computeInternalLaneShape(it->getFrom(), NBEdge::Connection(it->getFromLane(),
517  it->getTo(), it->getToLane()), NUM_POINTS);
518  GNEInternalLane* ilane = new GNEInternalLane(this, innerID + '_' + toString(tlIndex), shape, tlIndex);
519  rtree.addAdditionalGLObject(ilane);
520  myInternalLanes[tlIndex].push_back(ilane);
521  }
522  const std::vector<NBNode::Crossing>& crossings = nbn->getCrossings();
523  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
524  const NBNode::Crossing& c = *it;
525  GNEInternalLane* ilane = new GNEInternalLane(this, c.id, c.shape, c.tlLinkNo);
526  rtree.addAdditionalGLObject(ilane);
527  myInternalLanes[c.tlLinkNo].push_back(ilane);
528  }
529  }
530 }
531 
532 
533 void
535  myDefinitions.clear();
536  myDefBox->clearItems();
537  assert(myCurrentJunction);
539  std::set<NBTrafficLightDefinition*> tldefs = nbn->getControllingTLS();
540  for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
541  myDefinitions.push_back(*it);
542  std::string item = (*it)->getID() + ", " + (*it)->getProgramID();
543  myDefBox->appendItem(item.c_str());
544  }
545  if (myDefinitions.size() > 0) {
546  myDefBox->setCurrentItem(0);
547  myDefBox->setNumVisible(myDefBox->getNumItems());
548  myDefBox->show();
549  onCmdDefSwitch(0, 0, 0);
550  }
552 }
553 
554 
555 void
556 GNETLSEditor::initPhaseTable(unsigned int index) {
557  myPhaseTable->setVisibleRows(1);
558  myPhaseTable->setVisibleColumns(2);
559  myPhaseTable->hide();
560  if (myDefinitions.size() > 0) {
561  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
562  myPhaseTable->setTableSize((int)phases.size(), 2);
563  myPhaseTable->setVisibleRows((int)phases.size());
564  myPhaseTable->setVisibleColumns(2);
565  for (unsigned int row = 0; row < phases.size(); row++) {
566  myPhaseTable->setItemText(row, 0, toString(STEPS2TIME(phases[row].duration)).c_str());
567  myPhaseTable->setItemText(row, 1, phases[row].state.c_str());
568  myPhaseTable->getItem(row, 1)->setJustify(FXTableItem::LEFT);
569  }
570  myPhaseTable->fitColumnsToContents(0, 2);
571  const int maxWidth = WIDTH - 4;
572  int desiredWidth = myPhaseTable->getColumnWidth(0) +
573  myPhaseTable->getColumnWidth(1) + 3;
574  int spaceForScrollBar = desiredWidth > maxWidth ? 15 : 0;
575  myPhaseTable->setHeight((int)phases.size() * 21 + spaceForScrollBar); // experimental
576  myPhaseTable->setWidth(MIN2(desiredWidth, maxWidth));
577  myPhaseTable->setCurrentItem(index, 0);
578  myPhaseTable->selectRow(index, true);
579  myPhaseTable->show();
580  myPhaseTable->setFocus();
581  }
582  update();
583 }
584 
585 
586 const std::vector<NBTrafficLightLogic::PhaseDefinition>&
588  return myEditedDef->getLogic()->getPhases();
589 }
590 
591 
592 void
594  myHaveModifications = true;
596  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
597  for (unsigned int row = 0; row < phases.size(); row++) {
598  myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
599  }
600  } else {
601  myEditedDef->getLogic()->setPhaseState(myPhaseTable->getCurrentRow(), lane->getTLIndex(), lane->getLinkState());
602  }
603  initPhaseTable(myPhaseTable->getCurrentRow());
604  myPhaseTable->setFocus();
605 }
606 
607 
608 void
609 GNETLSEditor::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* data) {
610  if (myEditedDef != 0) {
611  myHaveModifications = true;
613  std::set<std::string> fromIDs;
614  fromIDs.insert(lane->getMicrosimID());
615  GNEEdge& edge = lane->getParentEdge();
616  // if neither the lane nor its edge are selected, apply changes to the whole edge
618  for (GNEEdge::LaneVector::const_iterator it_lane = edge.getLanes().begin(); it_lane != edge.getLanes().end(); it_lane++) {
619  fromIDs.insert((*it_lane)->getMicrosimID());
620  }
621  } else {
622  // if the edge is selected, apply changes to all lanes of all selected edges
623  if (gSelected.isSelected(GLO_EDGE, edge.getGlID())) {
624  std::vector<GNEEdge*> edges = myUpdateTarget->getNet()->retrieveEdges(true);
625  for (std::vector<GNEEdge*>::iterator it = edges.begin(); it != edges.end(); it++) {
626  for (GNEEdge::LaneVector::const_iterator it_lane = (*it)->getLanes().begin(); it_lane != (*it)->getLanes().end(); it_lane++) {
627  fromIDs.insert((*it_lane)->getMicrosimID());
628  }
629  }
630  }
631  // if the lane is selected, apply changes to all selected lanes
632  if (gSelected.isSelected(GLO_LANE, lane->getGlID())) {
633  std::vector<GNELane*> lanes = myUpdateTarget->getNet()->retrieveLanes(true);
634  for (std::vector<GNELane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
635  fromIDs.insert((*it_lane)->getMicrosimID());
636  }
637  }
638 
639  }
640  // set new state for all connections from the chosen lane IDs
641  for (NBConnectionVector::const_iterator it = links.begin(); it != links.end(); it++) {
642  const NBConnection& c = *it;
643  if (fromIDs.count(c.getFrom()->getLaneID(c.getFromLane())) > 0) {
644  std::vector<GNEInternalLane*> lanes = myInternalLanes[c.getTLIndex()];
645  for (std::vector<GNEInternalLane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
646  (*it_lane)->onDefault(obj, sel, data);
647  }
648  }
649  }
650  }
651 }
652 
653 
654 bool
656  if (myEditedDef != 0) {
658  for (NBConnectionVector::const_iterator it = links.begin(); it != links.end(); it++) {
659  if ((*it).getFrom()->getID() == edge.getMicrosimID()) {
660  return true;
661  }
662  }
663  }
664  return false;
665 }
666 
667 
668 SUMOTime
669 GNETLSEditor::getSUMOTime(const FXString& string) {
670  assert(GNEAttributeCarrier::canParse<SUMOReal>(string.text()));
671  return TIME2STEPS(GNEAttributeCarrier::parse<SUMOReal>(string.text()));
672 }
673 
674 
675 void
677  SUMOTime cycleDuration = 0;
678  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = getPhases().begin(); it != getPhases().end(); it++) {
679  cycleDuration += it->duration;
680  }
681  std::string text = "Cycle time: " + toString(STEPS2TIME(cycleDuration));
682  myCycleDuration->setText(text.c_str());
683 }
684 
685 
686 /****************************************************************************/
bool controlsEdge(GNEEdge &edge) const
whether the given edge is controlled by the currently edited tlDef
long onCmdDefOffset(FXObject *, FXSelector, void *)
std::vector< GNELane * > retrieveLanes(bool onlySelected=false)
return all lanes
Definition: GNENet.cpp:565
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:148
const std::vector< NBTrafficLightLogic::PhaseDefinition > & getPhases()
the phase of the current traffic light
long long int SUMOTime
Definition: SUMOTime.h:43
GNEJunction * myCurrentJunction
the junction of the tls is being modified
Definition: GNETLSEditor.h:146
int getTLIndex() const
Definition: NBConnection.h:101
bool changeAllPhases() const
Definition: GNEViewNet.h:207
GNEViewNet * myUpdateTarget
Definition: GNETLSEditor.h:152
FXLabel * myCycleDuration
Definition: GNETLSEditor.h:173
std::string id
the (edge)-id of this crossing
Definition: NBNode.h:145
void setOffset(SUMOTime offset)
Sets the offset of this tls.
A loaded (complete) traffic light logic.
A container for traffic light definitions and built programs.
A SUMO-compliant built logic for a traffic light.
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:304
void handleMultiChange(GNELane *lane, FXObject *obj, FXSelector sel, void *data)
update phase definition for the current traffic light and phase
long onCmdDefDelete(FXObject *, FXSelector, void *)
GNEEdge & getParentEdge()
Returns underlying parent edge.
Definition: GNELane.h:108
int getFromLane() const
returns the from-lane
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
FXDEFMAP(GNETLSEditor) GNETLSEditorMap[]
void removeAdditionalGLObject(GUIGlObject *o)
Removes an additional object (detector/shape/trigger) from being visualised.
Definition: SUMORTree.h:141
long onCmdDefCreate(FXObject *, FXSelector, void *)
TLIndexMap myInternalLanes
Definition: GNETLSEditor.h:159
const std::vector< Crossing > & getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.h:640
The base class for traffic light logic definitions.
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
Definition: GUIGlObject.h:167
T MAX2(T a, T b)
Definition: StdDefs.h:75
long onCmdDefSwitch(FXObject *, FXSelector, void *)
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.h:337
bool isSelected(GUIGlObjectType type, GUIGlID id)
Returns the information whether the object with the given type and id is selected.
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:56
PositionVector shape
The lane&#39;s shape.
Definition: NBNode.h:141
void p_begin(const std::string &description)
Definition: GNEUndoList.cpp:75
void updateDescription() const
GNENet * getNet()
Definition: GNEViewNet.h:173
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
Definition: GNEJunction.h:146
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
The definition of a single phase of the logic.
long onUpdModified(FXObject *, FXSelector, void *)
A RT-tree for efficient storing of SUMO&#39;s GL-objects.
Definition: SUMORTree.h:74
void initPhaseTable(unsigned int index=0)
FXTextField * myOffset
the control for modifying offset
Definition: GNETLSEditor.h:171
NBEdge * getFrom() const
returns the from-edge (start of the connection)
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GUIGlObject.h:123
long onUpdDefCreate(FXObject *, FXSelector, void *)
~GNETLSEditor()
Destructor.
#define new
Definition: debug_new.h:121
const std::string & getID() const
Returns the id.
Definition: Named.h:65
void cleanup()
cleans up previous lanes
long onCmdPhaseCreate(FXObject *, FXSelector, void *)
void updateCycleDuration()
recomputes cycle duration and updates label
long onCmdDefSubRename(FXObject *, FXSelector, void *)
NBLoadedSUMOTLDef * myEditedDef
the traffic light definition being edited
Definition: GNETLSEditor.h:165
long onUpdNeedsDefAndPhase(FXObject *, FXSelector, void *)
LinkState getLinkState()
whether link state has been modfied
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node.
Definition: NBNode.h:318
std::string getLaneID(unsigned int lane) const
Definition: NBEdge.cpp:2166
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
FXListBox * myDefBox
the listbox for selecting the tl-definition to edit
Definition: GNETLSEditor.h:168
void p_end()
Definition: GNEUndoList.cpp:82
long onCmdPhaseSwitch(FXObject *, FXSelector, void *)
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true)
get junction by id
Definition: GNENet.cpp:529
A list of positions.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
long onCmdCancel(FXObject *, FXSelector, void *)
Called when the user presses the Cancel-button discards any modifications.
void initDefinitions()
void setPhaseDuration(unsigned int phaseIndex, SUMOTime duration)
Modifies the duration for an existing phase (used by NETEDIT)
Cancel-button pressed.
Definition: GUIAppEnum.h:65
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
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)
Definition: GNENet.cpp:709
void handleChange(GNEInternalLane *lane)
update phase definition for the current traffic light and phase
T MIN2(T a, T b)
Definition: StdDefs.h:69
NBNode * getNBNode()
returns the internal NBNode
Definition: GNEJunction.h:153
NBTrafficLightLogic * getLogic()
Returns the internal logic.
void setPhaseState(unsigned int phaseIndex, unsigned int tlIndex, LinkState linkState)
Modifies the state for an existing phase (used by NETEDIT)
int getTLIndex() const
static SUMOTime getSUMOTime(const FXString &string)
converts to SUMOTime
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:54
void p_abort()
reverts and discards ALL active command groups
Definition: GNEUndoList.cpp:96
GNEUndoList * myUndoList
the undolist with wich to register changes
Definition: GNETLSEditor.h:149
FXTable * myPhaseTable
table for selecting and rearranging phases and for changing duration
Definition: GNETLSEditor.h:176
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
long onCmdPhaseEdit(FXObject *, FXSelector, void *)
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
FXFont * myTableFont
font for the phase table
Definition: GNETLSEditor.h:140
SUMOTime getOffset() const
Returns the offset of first switch.
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:61
NBTrafficLightLogic * getLogic(const std::string &id, const std::string &programID) const
Returns the computed logic for the given name.
SUMORTree & getVisualisationSpeedUp()
Returns the RTree used for visualisation speed-up.
Definition: GNENet.h:154
PositionVector computeInternalLaneShape(NBEdge *fromE, const NBEdge::Connection &con, int numPoints) const
Compute the shape for an internal lane.
Definition: NBNode.cpp:559
void deletePhase(unsigned int index)
std::vector< GNEEdge * > retrieveEdges(bool onlySelected=false)
return all edges
Definition: GNENet.cpp:553
tls mode messages
Definition: GUIAppEnum.h:410
void addAdditionalGLObject(GUIGlObject *o)
Adds an additional object (detector/shape/trigger) for visualisation.
Definition: SUMORTree.h:129
int tlLinkNo
the traffic light index of this crossing (if controlled)
Definition: NBNode.h:153
Ok-button pressed.
Definition: GUIAppEnum.h:63
void editJunction(GNEJunction *junction)
edits the traffic light for the given junction
an edge
long onUpdNeedsDef(FXObject *, FXSelector, void *)
Represents a single node (junction) during network building.
Definition: NBNode.h:74
FXLabel * myDescription
the label that shows the current editing state
Definition: GNETLSEditor.h:143
A definition of a pedestrian crossing.
Definition: NBNode.h:132
void setStatusBarText(const std::string &text)
Definition: GNEViewNet.cpp:310
long onCmdDefAddOff(FXObject *, FXSelector, void *)
bool myHaveModifications
whether the current tls was modified
Definition: GNETLSEditor.h:155
std::vector< NBTrafficLightDefinition * > myDefinitions
the list of Definitions for the current junction
Definition: GNETLSEditor.h:162
std::string getAttribute(SumoXMLAttr key) const
void buildIinternalLanes(NBTrafficLightDefinition *tlDef)
void addStep(SUMOTime duration, const std::string &state, int index=-1)
Adds a phase to the logic.
long onCmdDefRename(FXObject *, FXSelector, void *)
long onCmdGuess(FXObject *, FXSelector, void *)
long onUpdDefSwitch(FXObject *, FXSelector, void *)
long onCmdPhaseDelete(FXObject *, FXSelector, void *)
GUISelectedStorage gSelected
A global holder of selected objects.
long onCmdOK(FXObject *, FXSelector, void *)
Called when the user presses the OK-Button saves any modifications.
FXFont * myHeaderFont
Font for the widget.
Definition: GNETLSEditor.h:137
const LaneVector & getLanes()
Definition: GNEEdge.h:219
static const int WIDTH
the width of the widget
Definition: GNETLSEditor.h:182