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-2015 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  myUndoList->add(new GNEChange_TLS(myCurrentJunction, old, false), true);
224  myUndoList->add(new GNEChange_TLS(myCurrentJunction, myEditedDef, true), true);
225  myEditedDef = 0;
226  myUndoList->p_end();
227  cleanup();
228  myUpdateTarget->update();
229  } else {
230  onCmdCancel(0, 0, 0);
231  }
232  }
233  return 1;
234 }
235 
236 
237 long
238 GNETLSEditor::onCmdDefCreate(FXObject*, FXSelector, void*) {
239  GNEJunction* junction = myCurrentJunction;
240  onCmdCancel(0, 0, 0); // abort because we onCmdOk assumes we wish to save an edited definition
243  } else {
244  myUndoList->add(new GNEChange_TLS(junction, 0, true, true), true);
245  }
246  editJunction(junction);
247  return 1;
248 }
249 
250 
251 long
252 GNETLSEditor::onCmdDefDelete(FXObject*, FXSelector, void*) {
253  GNEJunction* junction = myCurrentJunction;
254  const bool changeType = myDefinitions.size() == 1;
255  onCmdCancel(0, 0, 0); // abort because onCmdOk assumes we wish to save an edited definition
256  if (changeType) {
258  } else {
259  NBTrafficLightDefinition* tlDef = myDefinitions[myDefBox->getCurrentItem()];
260  myUndoList->add(new GNEChange_TLS(junction, tlDef, false), true);
261  }
262  return 1;
263 }
264 
265 
266 long
267 GNETLSEditor::onCmdDefSwitch(FXObject*, FXSelector, void*) {
268  assert(myCurrentJunction != 0);
269  assert((int)myDefinitions.size() == myDefBox->getNumItems());
270  NBTrafficLightDefinition* tlDef = myDefinitions[myDefBox->getCurrentItem()];
271  // logic may not have been recomputed yet. recompute to be sure
274  NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
275  if (tllogic != 0) {
276  // now we can be sure that the tlDef is up to date (i.e. re-guessed)
277  buildIinternalLanes(tlDef);
278  // create working copy from original def
279  delete myEditedDef;
280  myEditedDef = new NBLoadedSUMOTLDef(tlDef, tllogic);
281  myOffset->setText(toString(STEPS2TIME(myEditedDef->getLogic()->getOffset())).c_str());
282  initPhaseTable();
284  } else {
285  // tlDef has no valid logic (probably because id does not control any links
286  onCmdCancel(0, 0, 0);
287  myUpdateTarget->setStatusBarText("Traffic light does not control any links");
288  }
289  return 1;
290 }
291 
292 
293 long
294 GNETLSEditor::onUpdDefSwitch(FXObject* o, FXSelector, void*) {
295  const bool enable = myDefinitions.size() > 0 && !myHaveModifications;
296  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
297  return 1;
298 }
299 
300 
301 long
302 GNETLSEditor::onUpdNeedsDef(FXObject* o, FXSelector, void*) {
303  const bool enable = myDefinitions.size() > 0;
304  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
305  return 1;
306 }
307 
308 
309 long
310 GNETLSEditor::onUpdNeedsDefAndPhase(FXObject* o, FXSelector, void*) {
311  // do not delete the last phase
312  const bool enable = myDefinitions.size() > 0 && myPhaseTable->getNumRows() > 1;
313  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
314  return 1;
315 }
316 
317 
318 long
319 GNETLSEditor::onUpdDefCreate(FXObject* o, FXSelector, void*) {
320  const bool enable = myCurrentJunction != 0 && !myHaveModifications;
321  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
322  return 1;
323 }
324 
325 
326 long
327 GNETLSEditor::onUpdModified(FXObject* o, FXSelector, void*) {
328  bool enable = myHaveModifications;
329  o->handle(this, FXSEL(SEL_COMMAND, enable ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE), 0);
330  return 1;
331 }
332 
333 
334 
335 long
336 GNETLSEditor::onCmdDefOffset(FXObject*, FXSelector, void*) {
337  myHaveModifications = true;
339  return 1;
340 }
341 
342 
343 long
344 GNETLSEditor::onCmdDefRename(FXObject*, FXSelector, void*) {
345  return 1;
346 }
347 
348 
349 long
350 GNETLSEditor::onCmdDefSubRename(FXObject*, FXSelector, void*) {
351  return 1;
352 }
353 
354 
355 long
356 GNETLSEditor::onCmdDefAddOff(FXObject*, FXSelector, void*) {
357  return 1;
358 }
359 
360 
361 long
362 GNETLSEditor::onCmdGuess(FXObject*, FXSelector, void*) {
363  return 1;
364 }
365 
366 
367 long
368 GNETLSEditor::onCmdPhaseSwitch(FXObject*, FXSelector, void*) {
369  const unsigned int index = myPhaseTable->getCurrentRow();
370  const NBTrafficLightLogic::PhaseDefinition& phase = getPhases()[index];
371  myPhaseTable->selectRow(index);
372  // need not hold since links could have been deleted somewhere else and indices may be reused
373  // assert(phase.state.size() == myInternalLanes.size());
374  for (TLIndexMap::iterator it = myInternalLanes.begin(); it != myInternalLanes.end(); it++) {
375  int tlIndex = it->first;
376  std::vector<GNEInternalLane*> lanes = it->second;
377  assert(tlIndex >= 0);
378  assert(tlIndex < (int)phase.state.size());
379  for (std::vector<GNEInternalLane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
380  (*it_lane)->setLinkState((LinkState)phase.state[tlIndex]);
381  }
382  }
383  myUpdateTarget->update();
384  return 1;
385 }
386 
387 
388 long
389 GNETLSEditor::onCmdPhaseCreate(FXObject*, FXSelector, void*) {
390  myHaveModifications = true;
391  const unsigned int numLinks = myEditedDef->getLogic()->getNumLinks();
392  // allows insertion at first position by deselecting via arrow keys
393  unsigned int newIndex = myPhaseTable->getSelStartRow() + 1;
394  unsigned int oldIndex = MAX2(0, myPhaseTable->getSelStartRow());
395  // copy current row
396  const SUMOTime duration = getSUMOTime(myPhaseTable->getItemText(oldIndex, 0));
397  const std::string state = myPhaseTable->getItemText(oldIndex, 1).text();
398  myEditedDef->getLogic()->addStep(duration, state, newIndex);
399  myPhaseTable->setCurrentItem(newIndex, 0);
400  initPhaseTable(newIndex);
401  myPhaseTable->setFocus();
402  return 1;
403 }
404 
405 
406 long
407 GNETLSEditor::onCmdPhaseDelete(FXObject*, FXSelector, void*) {
408  myHaveModifications = true;
409  myEditedDef->getLogic()->deletePhase(myPhaseTable->getCurrentRow());
410  initPhaseTable(0);
411  myPhaseTable->setFocus();
412  return 1;
413 }
414 
415 
416 long
417 GNETLSEditor::onCmdPhaseEdit(FXObject*, FXSelector, void* ptr) {
418  /* @note: there is a bug when copying/pasting rows: when this handler is
419  * called the value of the cell is not yet updated. This means you have to
420  * click inside the cell and hit enter to actually update the value */
421  FXTablePos* tp = (FXTablePos*)ptr;
422  FXString value = myPhaseTable->getItemText(tp->row, tp->col);
423  if (tp->col == 0) {
424  // duration edited
425  if (GNEAttributeCarrier::canParse<SUMOReal>(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 {
437  // state edited
438  try {
439  // insert phase with new step and delete the old phase
440  myEditedDef->getLogic()->addStep(getPhases()[tp->row].duration, value.text(), tp->row);
441  myEditedDef->getLogic()->deletePhase(tp->row + 1);
442  myHaveModifications = true;
443  onCmdPhaseSwitch(0, 0, 0);
444  } catch (ProcessError) {
445  // input error, reset value
446  myPhaseTable->setItemText(tp->row, 1, getPhases()[tp->row].state.c_str());
447  }
448  }
449  return 1;
450 }
451 
452 
453 void
455  std::string description;
456  if (myCurrentJunction == 0) {
457  description = "No Junction Selected\n";
458  } else {
460  description = "Junction '" + nbn->getID() + "'\n(";
461  if (!nbn->isTLControlled()) {
462  description += "uncontrolled, ";
463  }
464  description += (myHaveModifications ? "modified)" : "unmodified)");
465  }
466  myDescription->setText(description.c_str());
467 }
468 
469 
470 void
472  if (myCurrentJunction) {
474  }
475  // clean data structures
476  myCurrentJunction = 0;
477  myHaveModifications = false;
478  delete myEditedDef;
479  myEditedDef = 0;
480  buildIinternalLanes(0); // only clears
481  // clean up controls
482  myOffset->setText("");
483  myDefinitions.clear();
484  myDefBox->hide();
485  initPhaseTable(); // only clears when there are no definitions
486  myCycleDuration->hide();
488 }
489 
490 
491 void
493  // clean up previous objects
495  for (TLIndexMap::iterator it = myInternalLanes.begin(); it != myInternalLanes.end(); it++) {
496  std::vector<GNEInternalLane*> lanes = it->second;
497  for (std::vector<GNEInternalLane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
498  rtree.removeAdditionalGLObject(*it_lane);
499  delete *it_lane;
500  }
501  }
502  myInternalLanes.clear();
503  if (tlDef != 0) {
504  const int NUM_POINTS = 10;
505  assert(myCurrentJunction);
508  std::string innerID = ":" + nbn->getID(); // see NWWriter_SUMO::writeInternalEdges
509  const NBConnectionVector& links = tlDef->getControlledLinks();
510  for (NBConnectionVector::const_iterator it = links.begin(); it != links.end(); it++) {
511  int tlIndex = it->getTLIndex();
512  PositionVector shape = nbn->computeInternalLaneShape(it->getFrom(), NBEdge::Connection(it->getFromLane(),
513  it->getTo(), it->getToLane()), NUM_POINTS);
514  GNEInternalLane* ilane = new GNEInternalLane(this, innerID + '_' + toString(tlIndex), shape, tlIndex);
515  rtree.addAdditionalGLObject(ilane);
516  myInternalLanes[tlIndex].push_back(ilane);
517  }
518  const std::vector<NBNode::Crossing>& crossings = nbn->getCrossings();
519  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
520  const NBNode::Crossing& c = *it;
521  GNEInternalLane* ilane = new GNEInternalLane(this, c.id, c.shape, c.tlLinkNo);
522  rtree.addAdditionalGLObject(ilane);
523  myInternalLanes[c.tlLinkNo].push_back(ilane);
524  }
525  }
526 }
527 
528 
529 void
531  myDefinitions.clear();
532  myDefBox->clearItems();
533  assert(myCurrentJunction);
535  std::set<NBTrafficLightDefinition*> tldefs = nbn->getControllingTLS();
536  for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
537  myDefinitions.push_back(*it);
538  std::string item = (*it)->getID() + ", " + (*it)->getProgramID();
539  myDefBox->appendItem(item.c_str());
540  }
541  if (myDefinitions.size() > 0) {
542  myDefBox->setCurrentItem(0);
543  myDefBox->setNumVisible(myDefBox->getNumItems());
544  myDefBox->show();
545  onCmdDefSwitch(0, 0, 0);
546  }
548 }
549 
550 
551 void
552 GNETLSEditor::initPhaseTable(unsigned int index) {
553  myPhaseTable->setVisibleRows(1);
554  myPhaseTable->setVisibleColumns(2);
555  myPhaseTable->hide();
556  if (myDefinitions.size() > 0) {
557  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
558  myPhaseTable->setTableSize((int)phases.size(), 2);
559  myPhaseTable->setVisibleRows((int)phases.size());
560  myPhaseTable->setVisibleColumns(2);
561  for (unsigned int row = 0; row < phases.size(); row++) {
562  myPhaseTable->setItemText(row, 0, toString(STEPS2TIME(phases[row].duration)).c_str());
563  myPhaseTable->setItemText(row, 1, phases[row].state.c_str());
564  myPhaseTable->getItem(row, 1)->setJustify(FXTableItem::LEFT);
565  }
566  myPhaseTable->fitColumnsToContents(0, 2);
567  const int maxWidth = WIDTH - 4;
568  int desiredWidth = myPhaseTable->getColumnWidth(0) +
569  myPhaseTable->getColumnWidth(1) + 3;
570  int spaceForScrollBar = desiredWidth > maxWidth ? 15 : 0;
571  myPhaseTable->setHeight((int)phases.size() * 21 + spaceForScrollBar); // experimental
572  myPhaseTable->setWidth(MIN2(desiredWidth, maxWidth));
573  myPhaseTable->setCurrentItem(index, 0);
574  myPhaseTable->selectRow(index, true);
575  myPhaseTable->show();
576  myPhaseTable->setFocus();
577  }
578  update();
579 }
580 
581 
582 const std::vector<NBTrafficLightLogic::PhaseDefinition>&
584  return myEditedDef->getLogic()->getPhases();
585 }
586 
587 
588 void
590  myHaveModifications = true;
592  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = getPhases();
593  for (unsigned int row = 0; row < phases.size(); row++) {
594  myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
595  }
596  } else {
597  myEditedDef->getLogic()->setPhaseState(myPhaseTable->getCurrentRow(), lane->getTLIndex(), lane->getLinkState());
598  }
599  initPhaseTable(myPhaseTable->getCurrentRow());
600  myPhaseTable->setFocus();
601 }
602 
603 
604 void
605 GNETLSEditor::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* data) {
606  if (myEditedDef != 0) {
607  myHaveModifications = true;
609  std::set<std::string> fromIDs;
610  fromIDs.insert(lane->getMicrosimID());
611  GNEEdge& edge = lane->getParentEdge();
612  // if neither the lane nor its edge are selected, apply changes to the whole edge
614  for (GNEEdge::LaneVector::const_iterator it_lane = edge.getLanes().begin(); it_lane != edge.getLanes().end(); it_lane++) {
615  fromIDs.insert((*it_lane)->getMicrosimID());
616  }
617  } else {
618  // if the edge is selected, apply changes to all lanes of all selected edges
619  if (gSelected.isSelected(GLO_EDGE, edge.getGlID())) {
620  std::vector<GNEEdge*> edges = myUpdateTarget->getNet()->retrieveEdges(true);
621  for (std::vector<GNEEdge*>::iterator it = edges.begin(); it != edges.end(); it++) {
622  for (GNEEdge::LaneVector::const_iterator it_lane = (*it)->getLanes().begin(); it_lane != (*it)->getLanes().end(); it_lane++) {
623  fromIDs.insert((*it_lane)->getMicrosimID());
624  }
625  }
626  }
627  // if the lane is selected, apply changes to all selected lanes
628  if (gSelected.isSelected(GLO_LANE, lane->getGlID())) {
629  std::vector<GNELane*> lanes = myUpdateTarget->getNet()->retrieveLanes(true);
630  for (std::vector<GNELane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
631  fromIDs.insert((*it_lane)->getMicrosimID());
632  }
633  }
634 
635  }
636  // set new state for all connections from the chosen lane IDs
637  for (NBConnectionVector::const_iterator it = links.begin(); it != links.end(); it++) {
638  const NBConnection& c = *it;
639  if (fromIDs.count(c.getFrom()->getLaneID(c.getFromLane())) > 0) {
640  std::vector<GNEInternalLane*> lanes = myInternalLanes[c.getTLIndex()];
641  for (std::vector<GNEInternalLane*>::iterator it_lane = lanes.begin(); it_lane != lanes.end(); it_lane++) {
642  (*it_lane)->onDefault(obj, sel, data);
643  }
644  }
645  }
646  }
647 }
648 
649 
650 bool
652  if (myEditedDef != 0) {
654  for (NBConnectionVector::const_iterator it = links.begin(); it != links.end(); it++) {
655  if ((*it).getFrom()->getID() == edge.getMicrosimID()) {
656  return true;
657  }
658  }
659  }
660  return false;
661 }
662 
663 
664 SUMOTime
665 GNETLSEditor::getSUMOTime(const FXString& string) {
666  assert(GNEAttributeCarrier::canParse<SUMOReal>(string.text()));
667  return TIME2STEPS(GNEAttributeCarrier::parse<SUMOReal>(string.text()));
668 }
669 
670 
671 void
673  SUMOTime cycleDuration = 0;
674  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = getPhases().begin(); it != getPhases().end(); it++) {
675  cycleDuration += it->duration;
676  }
677  std::string text = "Cycle time: " + toString(STEPS2TIME(cycleDuration));
678  myCycleDuration->setText(text.c_str());
679 }
680 
681 
682 /****************************************************************************/
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:210
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:154
T MAX2(T a, T b)
Definition: StdDefs.h:79
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:176
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
Definition: GNEJunction.h:142
#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:2135
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 *)
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:73
NBNode * getNBNode()
returns the internal NBNode
Definition: GNEJunction.h:149
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:53
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
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:408
void addAdditionalGLObject(GUIGlObject *o)
Adds an additional object (detector/shape/trigger) for visualisation.
Definition: SUMORTree.h:129
unsigned int getNumLinks()
Returns the number of participating links.
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