Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/frames/network/GNETLSEditorFrame.cpp
193867 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file GNETLSEditorFrame.cpp
15
/// @author Jakob Erdmann
16
/// @date May 2011
17
///
18
// The Widget for modifying traffic lights
19
/****************************************************************************/
20
21
#include <netbuild/NBLoadedSUMOTLDef.h>
22
#include <netbuild/NBOwnTLDef.h>
23
#include <netedit/GNEApplicationWindow.h>
24
#include <netedit/GNENet.h>
25
#include <netedit/GNETagProperties.h>
26
#include <netedit/GNEUndoList.h>
27
#include <netedit/GNEInternalTest.h>
28
#include <netedit/GNEViewParent.h>
29
#include <netedit/changes/GNEChange_TLS.h>
30
#include <netedit/dialogs/basic/GNEQuestionBasicDialog.h>
31
#include <netedit/dialogs/basic/GNEWarningBasicDialog.h>
32
#include <netedit/dialogs/GNEParametersDialog.h>
33
#include <netedit/elements/network/GNEConnection.h>
34
#include <netedit/elements/network/GNECrossing.h>
35
#include <netedit/elements/network/GNEInternalLane.h>
36
#include <netedit/frames/GNEOverlappedInspection.h>
37
#include <netedit/frames/GNETLSTable.h>
38
#include <netimport/NIXMLTrafficLightsHandler.h>
39
#include <netwrite/NWWriter_SUMO.h>
40
#include <utils/foxtools/MFXTextFieldIcon.h>
41
#include <utils/foxtools/MFXToggleButtonTooltip.h>
42
#include <utils/gui/div/GUIDesigns.h>
43
#include <utils/xml/XMLSubSys.h>
44
45
#include "GNETLSEditorFrame.h"
46
47
// ===========================================================================
48
// FOX callback mapping
49
// ===========================================================================
50
51
FXDEFMAP(GNETLSEditorFrame::TLSJunction) TLSJunctionMap[] = {
52
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_TLSJUNCTION_ID, GNETLSEditorFrame::TLSJunction::onCmdRenameTLS),
53
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_TLSJUNCTION_TYPE, GNETLSEditorFrame::TLSJunction::onCmdChangeType),
54
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_TLSJUNCTION_TOGGLEJOIN, GNETLSEditorFrame::TLSJunction::onCmdToggleJoinTLS),
55
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_TLSJUNCTION_DISJOIN, GNETLSEditorFrame::TLSJunction::onCmdDisjoinTLS),
56
FXMAPFUNC(SEL_COMMAND, MID_GNE_BUTTON_ACCEPT, GNETLSEditorFrame::TLSJunction::onCmdAcceptJoin),
57
FXMAPFUNC(SEL_COMMAND, MID_GNE_BUTTON_CANCEL, GNETLSEditorFrame::TLSJunction::onCmdCancelJoin)
58
};
59
60
FXDEFMAP(GNETLSEditorFrame::TLSPrograms) TLSProgramsMap[] = {
61
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_DEFINITION_CREATE, GNETLSEditorFrame::TLSPrograms::onCmdCreate),
62
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_DEFINITION_DELETE, GNETLSEditorFrame::TLSPrograms::onCmdDelete),
63
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_DEFINITION_RESETCURRENT, GNETLSEditorFrame::TLSPrograms::onCmdResetCurrentProgram),
64
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_DEFINITION_RESETALL, GNETLSEditorFrame::TLSPrograms::onCmdResetAll),
65
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_DEFINITION_SWITCHPROGRAM, GNETLSEditorFrame::TLSPrograms::onCmdDefSwitchTLSProgram),
66
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_DEFINITION_SAVE, GNETLSEditorFrame::TLSPrograms::onCmdSaveChanges),
67
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_DEFINITION_DISCARD, GNETLSEditorFrame::TLSPrograms::onCmdDiscardChanges),
68
};
69
70
FXDEFMAP(GNETLSEditorFrame::TLSAttributes) TLSAttributesMap[] = {
71
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_ATTRIBUTES_OFFSET, GNETLSEditorFrame::TLSAttributes::onCmdSetOffset),
72
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_ATTRIBUTES_PARAMETERS, GNETLSEditorFrame::TLSAttributes::onCmdSetParameters),
73
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_ATTRIBUTES_PARAMETERSDIALOG, GNETLSEditorFrame::TLSAttributes::onCmdParametersDialog),
74
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_ATTRIBUTES_TOGGLEDETECTOR, GNETLSEditorFrame::TLSAttributes::onCmdToggleDetectorMode),
75
};
76
77
FXDEFMAP(GNETLSEditorFrame::TLSPhases) TLSPhasesMap[] = {
78
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_PHASES_CLEANUP, GNETLSEditorFrame::TLSPhases::onCmdCleanStates),
79
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_PHASES_ADDUNUSED, GNETLSEditorFrame::TLSPhases::onCmdAddUnusedStates),
80
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_PHASES_GROUPSTATES, GNETLSEditorFrame::TLSPhases::onCmdGroupStates),
81
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_PHASES_UNGROUPSTATES, GNETLSEditorFrame::TLSPhases::onCmdUngroupStates),
82
};
83
84
FXDEFMAP(GNETLSEditorFrame::TLSFile) TLSFileMap[] = {
85
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_FILE_LOADPROGRAM, GNETLSEditorFrame::TLSFile::onCmdLoadTLSProgram),
86
FXMAPFUNC(SEL_COMMAND, MID_GNE_TLSFRAME_FILE_SAVEPROGRAM, GNETLSEditorFrame::TLSFile::onCmdSaveTLSProgram),
87
};
88
89
// Object implementation
90
FXIMPLEMENT(GNETLSEditorFrame::TLSJunction, GNEGroupBoxModule, TLSJunctionMap, ARRAYNUMBER(TLSJunctionMap))
91
FXIMPLEMENT(GNETLSEditorFrame::TLSPrograms, GNEGroupBoxModule, TLSProgramsMap, ARRAYNUMBER(TLSProgramsMap))
92
FXIMPLEMENT(GNETLSEditorFrame::TLSAttributes, GNEGroupBoxModule, TLSAttributesMap, ARRAYNUMBER(TLSAttributesMap))
93
FXIMPLEMENT(GNETLSEditorFrame::TLSPhases, GNEGroupBoxModule, TLSPhasesMap, ARRAYNUMBER(TLSPhasesMap))
94
FXIMPLEMENT(GNETLSEditorFrame::TLSFile, GNEGroupBoxModule, TLSFileMap, ARRAYNUMBER(TLSFileMap))
95
96
97
// ===========================================================================
98
// method definitions
99
// ===========================================================================
100
101
GNETLSEditorFrame::GNETLSEditorFrame(GNEViewParent* viewParent, GNEViewNet* viewNet):
102
GNEFrame(viewParent, viewNet, TL("Edit Traffic Light")),
103
myEditedDef(nullptr) {
104
105
// Create Overlapped Inspection module only for junctions
106
myOverlappedInspection = new GNEOverlappedInspection(this, true);
107
108
// create TLSJunction module
109
myTLSJunction = new GNETLSEditorFrame::TLSJunction(this);
110
111
// create TLSPrograms module
112
myTLSPrograms = new GNETLSEditorFrame::TLSPrograms(this);
113
114
// create TLSAttributes module
115
myTLSAttributes = new GNETLSEditorFrame::TLSAttributes(this);
116
117
// create TLSPhases module
118
myTLSPhases = new GNETLSEditorFrame::TLSPhases(this);
119
120
// create TLSFile module
121
myTLSFile = new GNETLSEditorFrame::TLSFile(this);
122
}
123
124
125
GNETLSEditorFrame::~GNETLSEditorFrame() {
126
myTLSPhases->clearPhaseTable();
127
}
128
129
130
void
131
GNETLSEditorFrame::show() {
132
myOverlappedInspection->clearOverlappedInspection();
133
// show
134
GNEFrame::show();
135
}
136
137
138
void
139
GNETLSEditorFrame::frameWidthUpdated() {
140
// recalc table width
141
myTLSPhases->getPhaseTable()->recalcTableWidth();
142
}
143
144
145
void
146
GNETLSEditorFrame::updateModules() {
147
if (myTLSJunction) {
148
myTLSJunction->updateTLSJunction();
149
}
150
if (myTLSPrograms) {
151
myTLSPrograms->updateTLSPrograms();
152
}
153
if (myTLSAttributes) {
154
myTLSAttributes->updateTLSAttributes();
155
}
156
if (myTLSPhases) {
157
myTLSPhases->updateTLSPhases();
158
}
159
if (myTLSFile) {
160
myTLSFile->updateTLSFile();
161
}
162
update();
163
}
164
165
166
void
167
GNETLSEditorFrame::editTLS(GNEViewNetHelper::ViewObjectsSelector& viewObjects, const Position& clickedPosition, const bool shiftKeyPressed) {
168
// first check if in viewObjects there is a junction
169
if (viewObjects.getJunctionFront()) {
170
// check if we're adding or removing joined TLSs
171
if (myTLSJunction->isJoiningJunctions()) {
172
myTLSJunction->toggleJunctionSelected(viewObjects.getJunctionFront());
173
} else {
174
// show objects under cursor
175
myOverlappedInspection->showOverlappedInspection(viewObjects, clickedPosition, shiftKeyPressed);
176
// hide if we inspect only one junction
177
if (myOverlappedInspection->getNumberOfOverlappedACs()) {
178
if (myOverlappedInspection->getNumberOfOverlappedACs() == 1) {
179
myOverlappedInspection->hiderOverlappedInspection();
180
}
181
for (const auto& junction : viewObjects.getJunctions()) {
182
if (junction == myOverlappedInspection->getCurrentAC()) {
183
editJunction(junction);
184
}
185
}
186
}
187
}
188
} else if (viewObjects.getAdditionalFront() && myTLSAttributes->isSetDetectorsToggleButtonEnabled() &&
189
(viewObjects.getAdditionalFront()->getTagProperty()->getTag() == SUMO_TAG_INDUCTION_LOOP)) {
190
myTLSAttributes->toggleE1DetectorSelection(viewObjects.getAdditionalFront());
191
}
192
myViewNet->update();
193
}
194
195
196
bool
197
GNETLSEditorFrame::isTLSSaved() {
198
if (myTLSPrograms->checkHaveModifications()) {
199
// show question dialog
200
const GNEQuestionBasicDialog questionDialog(myViewNet->getViewParent()->getGNEAppWindows(),
201
GNEDialog::Buttons::YES_NO_CANCEL,
202
TL("Save TLS Changes"),
203
TL("There are unsaved changes in the currently edited traffic light."),
204
TL("Do you want to save it before changing mode?"));
205
// continue depending of result
206
if (questionDialog.getResult() == GNEDialog::Result::ACCEPT) {
207
// save modifications
208
myTLSPrograms->onCmdSaveChanges(nullptr, 0, nullptr);
209
return true;
210
} else if (questionDialog.getResult() == GNEDialog::Result::CANCEL) {
211
// cancel modifications
212
myTLSPrograms->onCmdDiscardChanges(nullptr, 0, nullptr);
213
return true;
214
} else {
215
// abort changing mode
216
return false;
217
}
218
} else {
219
return true;
220
}
221
}
222
223
224
bool
225
GNETLSEditorFrame::parseTLSPrograms(const std::string& file) {
226
NBTrafficLightLogicCont& tllCont = myViewNet->getNet()->getTLLogicCont();
227
NBTrafficLightLogicCont tmpTLLCont;
228
NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myViewNet->getNet()->getEdgeCont());
229
// existing definitions must be available to update their programs
230
std::set<NBTrafficLightDefinition*> origDefs;
231
for (NBTrafficLightDefinition* def : tllCont.getDefinitions()) {
232
// make a duplicate of every program
233
NBTrafficLightLogic* logic = tllCont.getLogic(def->getID(), def->getProgramID());
234
if (logic != nullptr) {
235
NBTrafficLightDefinition* duplicate = new NBLoadedSUMOTLDef(*def, *logic);
236
std::vector<NBNode*> nodes = def->getNodes();
237
for (auto it_node : nodes) {
238
GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
239
myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, false, false), true);
240
myViewNet->getUndoList()->add(new GNEChange_TLS(junction, duplicate, true), true);
241
}
242
tmpTLLCont.insert(duplicate);
243
origDefs.insert(duplicate);
244
} else {
245
WRITE_WARNINGF(TL("tlLogic '%', program '%' could not be built"), def->getID(), def->getProgramID());
246
}
247
}
248
//std::cout << " initialized tmpCont with " << origDefs.size() << " defs\n";
249
XMLSubSys::runParser(tllHandler, file);
250
251
std::vector<NBLoadedSUMOTLDef*> loadedTLS;
252
for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
253
NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
254
if (sdef != nullptr) {
255
loadedTLS.push_back(sdef);
256
}
257
}
258
myViewNet->setStatusBarText(TL("Loaded ") + toString(loadedTLS.size()) + TL(" programs"));
259
for (auto def : loadedTLS) {
260
if (origDefs.count(def) != 0) {
261
// already add to undolist before
262
//std::cout << " skip " << def->getDescription() << "\n";
263
continue;
264
}
265
std::vector<NBNode*> nodes = def->getNodes();
266
//std::cout << " add " << def->getDescription() << " for nodes=" << toString(nodes) << "\n";
267
for (auto it_node : nodes) {
268
GNEJunction* junction = myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
269
//myViewNet->getUndoList()->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, false), true);
270
myViewNet->getUndoList()->add(new GNEChange_TLS(junction, def, true), true);
271
}
272
}
273
// clean up temporary container to avoid deletion of defs when its destruct is called
274
for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
275
tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
276
}
277
return true;
278
}
279
280
281
void
282
GNETLSEditorFrame::selectedOverlappedElement(GNEAttributeCarrier* AC) {
283
auto junction = dynamic_cast<GNEJunction*>(AC);
284
if (junction) {
285
editJunction(junction);
286
}
287
}
288
289
290
void
291
GNETLSEditorFrame::cleanup() {
292
if (myTLSJunction->getCurrentJunction()) {
293
myTLSJunction->getCurrentJunction()->selectTLS(false);
294
if (myTLSPrograms->getNumberOfPrograms() > 0) {
295
for (const auto& node : myTLSPrograms->getCurrentTLSPrograms()->getNodes()) {
296
myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(node->getID())->selectTLS(false);
297
}
298
}
299
}
300
// clean data structures
301
myTLSJunction->setCurrentJunction(nullptr);
302
// check if delete myEditedDef
303
if (myEditedDef) {
304
delete myEditedDef;
305
myEditedDef = nullptr;
306
}
307
// clear internal lanes
308
buildInternalLanes(nullptr);
309
// clean up attributes
310
myTLSPrograms->clearTLSProgramss();
311
// clean up attributes
312
myTLSAttributes->clearTLSAttributes();
313
// only clears when there are no definitions
314
myTLSPhases->initPhaseTable();
315
}
316
317
318
GNETLSEditorFrame::TLSJunction*
319
GNETLSEditorFrame::getTLSJunction() const {
320
return myTLSJunction;
321
}
322
323
324
GNETLSEditorFrame::TLSPrograms*
325
GNETLSEditorFrame::getTLSPrograms() const {
326
return myTLSPrograms;
327
}
328
329
330
GNETLSEditorFrame::TLSAttributes*
331
GNETLSEditorFrame::getTLSAttributes() const {
332
return myTLSAttributes;
333
}
334
335
336
GNETLSEditorFrame::TLSPhases*
337
GNETLSEditorFrame::getTLSPhases() const {
338
return myTLSPhases;
339
}
340
341
342
void
343
GNETLSEditorFrame::buildInternalLanes(const NBTrafficLightDefinition* tlDef) {
344
// clean up previous internal lanes
345
for (const auto& internalLanes : myInternalLanes) {
346
for (const auto& internalLane : internalLanes.second) {
347
// remove internal lane from ACs
348
myViewNet->getNet()->getAttributeCarriers()->deleteInternalLane(internalLane);
349
// delete internal lane
350
delete internalLane;
351
}
352
}
353
// clear container
354
myInternalLanes.clear();
355
// create new internal lanes
356
if (tlDef != nullptr) {
357
const int NUM_POINTS = 10;
358
const NBNode* nbnCurrentJunction = myTLSJunction->getCurrentJunction()->getNBNode();
359
// get innerID NWWriter_SUMO::writeInternalEdges
360
const std::string innerID = ":" + nbnCurrentJunction->getID();
361
const NBConnectionVector& links = tlDef->getControlledLinks();
362
// iterate over links
363
for (const auto& link : links) {
364
int tlIndex = link.getTLIndex();
365
PositionVector shape;
366
try {
367
const NBEdge::Connection& con = link.getFrom()->getConnection(link.getFromLane(), link.getTo(), link.getToLane());
368
shape = con.shape;
369
shape.append(con.viaShape);
370
} catch (ProcessError&) {
371
shape = link.getFrom()->getToNode()->computeInternalLaneShape(link.getFrom(), NBEdge::Connection(link.getFromLane(),
372
link.getTo(), link.getToLane()), NUM_POINTS);
373
}
374
if (shape.length() < 2) {
375
// enlarge shape to ensure visibility
376
shape.clear();
377
const PositionVector laneShapeFrom = link.getFrom()->getLaneShape(link.getFromLane());
378
const PositionVector laneShapeTo = link.getTo()->getLaneShape(link.getToLane());
379
shape.push_back(laneShapeFrom.positionAtOffset(MAX2(0.0, laneShapeFrom.length() - 1)));
380
shape.push_back(laneShapeTo.positionAtOffset(MIN2(1.0, laneShapeFrom.length())));
381
}
382
GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), innerID + '_' + toString(tlIndex), shape, tlIndex);
383
// add into atribute carriers
384
myViewNet->getNet()->getAttributeCarriers()->insertInternalLane(internalLane);
385
myInternalLanes[tlIndex].push_back(internalLane);
386
}
387
// iterate over crossings
388
for (const auto& nbn : tlDef->getNodes()) {
389
for (const auto& crossing : nbn->getCrossings()) {
390
if (crossing->tlLinkIndex2 > 0 && crossing->tlLinkIndex2 != crossing->tlLinkIndex) {
391
// draw both directions
392
PositionVector forward = crossing->shape;
393
forward.move2side(crossing->width / 4);
394
GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, forward, crossing->tlLinkIndex);
395
// add into atribute carriers
396
myViewNet->getNet()->getAttributeCarriers()->insertInternalLane(internalLane);
397
myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
398
PositionVector backward = crossing->shape.reverse();
399
backward.move2side(crossing->width / 4);
400
GNEInternalLane* internalLaneReverse = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id + "_r", backward, crossing->tlLinkIndex2);
401
// add into atribute carriers
402
myViewNet->getNet()->getAttributeCarriers()->insertInternalLane(internalLaneReverse);
403
myInternalLanes[crossing->tlLinkIndex2].push_back(internalLaneReverse);
404
} else {
405
// draw only one lane for both directions
406
GNEInternalLane* internalLane = new GNEInternalLane(this, myTLSJunction->getCurrentJunction(), crossing->id, crossing->shape, crossing->tlLinkIndex);
407
// add into atribute carriers
408
myViewNet->getNet()->getAttributeCarriers()->insertInternalLane(internalLane);
409
myInternalLanes[crossing->tlLinkIndex].push_back(internalLane);
410
}
411
}
412
}
413
}
414
}
415
416
417
std::string
418
GNETLSEditorFrame::varDurString(SUMOTime dur) {
419
return (dur == NBTrafficLightDefinition::UNSPECIFIED_DURATION) ? "" : getSteps2Time(dur);
420
}
421
422
423
const NBTrafficLightLogic::PhaseDefinition&
424
GNETLSEditorFrame::getPhase(const int index) {
425
if ((index >= 0) || (index < (int)myEditedDef->getLogic()->getPhases().size())) {
426
return myEditedDef->getLogic()->getPhases().at(index);
427
} else {
428
throw ProcessError(TL("Invalid phase index"));
429
}
430
}
431
432
433
void
434
GNETLSEditorFrame::handleChange(GNEInternalLane* lane) {
435
myTLSPrograms->markAsModified();
436
// get current selected row
437
const auto selectedRow = myTLSPhases->getPhaseTable()->getCurrentSelectedRow();
438
if (myViewNet->changeAllPhases()) {
439
for (int row = 0; row < (int)myEditedDef->getLogic()->getPhases().size(); row++) {
440
myEditedDef->getLogic()->setPhaseState(row, lane->getTLIndex(), lane->getLinkState());
441
}
442
} else {
443
myEditedDef->getLogic()->setPhaseState(myTLSPhases->getPhaseTable()->getCurrentSelectedRow(), lane->getTLIndex(), lane->getLinkState());
444
}
445
// init phaseTable
446
myTLSPhases->initPhaseTable();
447
// select row
448
myTLSPhases->getPhaseTable()->selectRow(selectedRow);
449
// focus table
450
myTLSPhases->getPhaseTable()->setFocus();
451
}
452
453
454
void
455
GNETLSEditorFrame::handleMultiChange(GNELane* lane, FXObject* obj, FXSelector sel, void* eventData) {
456
if (myEditedDef != nullptr) {
457
myTLSPrograms->markAsModified();
458
const NBConnectionVector& links = myEditedDef->getControlledLinks();
459
std::set<std::string> fromIDs;
460
fromIDs.insert(lane->getMicrosimID());
461
// if neither the lane nor its edge are selected, apply changes to the whole edge
462
if (!lane->getParentEdge()->isAttributeCarrierSelected() && !lane->isAttributeCarrierSelected()) {
463
for (auto it_lane : lane->getParentEdge()->getChildLanes()) {
464
fromIDs.insert(it_lane->getMicrosimID());
465
}
466
} else {
467
// if the edge is selected, apply changes to all lanes of all selected edges
468
if (lane->getParentEdge()->isAttributeCarrierSelected()) {
469
const auto selectedEdge = myViewNet->getNet()->getAttributeCarriers()->getSelectedEdges();
470
for (const auto& edge : selectedEdge) {
471
for (auto it_lane : edge->getChildLanes()) {
472
fromIDs.insert(it_lane->getMicrosimID());
473
}
474
}
475
}
476
// if the lane is selected, apply changes to all selected lanes
477
if (lane->isAttributeCarrierSelected()) {
478
const auto selectedLanes = myViewNet->getNet()->getAttributeCarriers()->getSelectedLanes();
479
for (auto it_lane : selectedLanes) {
480
fromIDs.insert(it_lane->getMicrosimID());
481
}
482
}
483
484
}
485
// set new state for all connections from the chosen lane IDs
486
for (auto it : links) {
487
if (fromIDs.count(it.getFrom()->getLaneID(it.getFromLane())) > 0) {
488
std::vector<GNEInternalLane*> lanes = myInternalLanes[it.getTLIndex()];
489
for (auto it_lane : lanes) {
490
it_lane->onDefault(obj, sel, eventData);
491
}
492
}
493
}
494
}
495
}
496
497
498
bool
499
GNETLSEditorFrame::controlsEdge(GNEEdge* edge) const {
500
if (myEditedDef != nullptr) {
501
const NBConnectionVector& links = myEditedDef->getControlledLinks();
502
for (auto it : links) {
503
if (it.getFrom()->getID() == edge->getMicrosimID()) {
504
return true;
505
}
506
}
507
}
508
return false;
509
}
510
511
512
void
513
GNETLSEditorFrame::editJunction(GNEJunction* junction) {
514
if ((myTLSJunction->getCurrentJunction() == nullptr) || (!myTLSPrograms->checkHaveModifications() && (junction != myTLSJunction->getCurrentJunction()))) {
515
// discard previous changes
516
myTLSPrograms->discardChanges(false);
517
// set junction
518
myTLSJunction->setCurrentJunction(junction);
519
// init TLS definitions
520
if (myTLSPrograms->initTLSPrograms()) {
521
// init TLSAttributes
522
myTLSAttributes->initTLSAttributes();
523
// begin undo-list
524
myViewNet->getUndoList()->begin(GUIIcon::MODETLS, TL("modifying TLS definition"));
525
// only select TLS if getCurrentJunction exist
526
if (myTLSJunction->getCurrentJunction()) {
527
myTLSJunction->getCurrentJunction()->selectTLS(true);
528
}
529
if (myTLSPrograms->getNumberOfPrograms() > 0) {
530
for (NBNode* node : myTLSPrograms->getCurrentTLSPrograms()->getNodes()) {
531
myViewNet->getNet()->getAttributeCarriers()->retrieveJunction(node->getID())->selectTLS(true);
532
}
533
// update color
534
myTLSPhases->updateTLSColoring();
535
}
536
}
537
} else {
538
myViewNet->setStatusBarText(TL("Unsaved modifications. Abort or Save"));
539
}
540
updateModules();
541
}
542
543
544
SUMOTime
545
GNETLSEditorFrame::getSUMOTime(const std::string& string) {
546
return TIME2STEPS(GNEAttributeCarrier::parse<double>(string));
547
}
548
549
const std::string
550
GNETLSEditorFrame::getSteps2Time(const SUMOTime value) {
551
return toString(STEPS2TIME(value));
552
}
553
554
// ---------------------------------------------------------------------------
555
// GNETLSEditorFrame::TLSAttributes - methods
556
// ---------------------------------------------------------------------------
557
558
GNETLSEditorFrame::TLSAttributes::TLSAttributes(GNETLSEditorFrame* TLSEditorParent) :
559
GNEGroupBoxModule(TLSEditorParent, TL("Traffic Light Attributes")),
560
myTLSEditorParent(TLSEditorParent) {
561
// create frame, label and TextField for Offset (By default disabled)
562
FXHorizontalFrame* horizontalFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
563
new FXLabel(horizontalFrame, toString(SUMO_ATTR_OFFSET).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
564
myOffsetTextField = new FXTextField(horizontalFrame, GUIDesignTextFieldNCol, this, MID_GNE_TLSFRAME_ATTRIBUTES_OFFSET, GUIDesignTextField);
565
myOffsetTextField->disable();
566
// create frame, label and TextField for parameters (By default disabled)
567
horizontalFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
568
myButtonEditParameters = GUIDesigns::buildFXButton(horizontalFrame, TL("parameters"), "", "", nullptr, this, MID_GNE_TLSFRAME_ATTRIBUTES_PARAMETERSDIALOG, GUIDesignButtonAttribute);
569
myParametersTextField = new FXTextField(horizontalFrame, GUIDesignTextFieldNCol, this, MID_GNE_TLSFRAME_ATTRIBUTES_PARAMETERS, GUIDesignTextField);
570
myButtonEditParameters->disable();
571
myParametersTextField->disable();
572
// create set detectors button (By default disabled)
573
mySetDetectorsToggleButton = new MFXToggleButtonTooltip(getCollapsableFrame(),
574
TLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
575
TL("Assign E1 detectors") + std::string("\t") + TL("Enable assign E1 mode") + std::string("\t") + TL("Assign E1 detectors to the current TLS"),
576
TL("Assign E1 detectors") + std::string("\t") + TL("Disable assign E1 mode") + std::string("\t") + TL("Assign E1 detectors to the current TLS"),
577
GUIIconSubSys::getIcon(GUIIcon::E1), GUIIconSubSys::getIcon(GUIIcon::E1),
578
this, MID_GNE_TLSFRAME_ATTRIBUTES_TOGGLEDETECTOR, GUIDesignButton);
579
mySetDetectorsToggleButton->disable();
580
}
581
582
583
GNETLSEditorFrame::TLSAttributes::~TLSAttributes() {}
584
585
586
void
587
GNETLSEditorFrame::TLSAttributes::updateTLSAttributes() {
588
if (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() == 0) {
589
// no TLS programs, disable elements
590
myOffsetTextField->disable();
591
myButtonEditParameters->disable();
592
myParametersTextField->disable();
593
// disable E1 detector mode
594
disableE1DetectorMode();
595
mySetDetectorsToggleButton->disable();
596
// clear E1 detectors
597
if (myE1Detectors.size() > 0) {
598
myE1Detectors.clear();
599
myTLSEditorParent->getViewNet()->update();
600
}
601
} else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
602
// joining TLSs, disable button
603
myOffsetTextField->disable();
604
myButtonEditParameters->disable();
605
myParametersTextField->disable();
606
// disable E1 detector mode
607
disableE1DetectorMode();
608
mySetDetectorsToggleButton->disable();
609
// clear E1 detectors
610
if (myE1Detectors.size() > 0) {
611
myE1Detectors.clear();
612
myTLSEditorParent->getViewNet()->update();
613
}
614
} else if (isSetDetectorsToggleButtonEnabled()) {
615
// set detectors toggle button is enabled, disable elements
616
myOffsetTextField->disable();
617
myButtonEditParameters->disable();
618
myParametersTextField->disable();
619
} else {
620
myOffsetTextField->enable();
621
myButtonEditParameters->enable();
622
myParametersTextField->enable();
623
// disable E1 detector mode in static
624
if (myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms()->getType() != TrafficLightType::ACTUATED) {
625
// disable E1 detector mode
626
disableE1DetectorMode();
627
mySetDetectorsToggleButton->disable();
628
// clear E1 detectors
629
if (myE1Detectors.size() > 0) {
630
myE1Detectors.clear();
631
myTLSEditorParent->getViewNet()->update();
632
}
633
} else {
634
mySetDetectorsToggleButton->enable();
635
}
636
}
637
}
638
639
640
void
641
GNETLSEditorFrame::TLSAttributes::showTLSAttributes() {
642
show();
643
}
644
645
646
void
647
GNETLSEditorFrame::TLSAttributes::hideTLSAttributes() {
648
hide();
649
}
650
651
652
void
653
GNETLSEditorFrame::TLSAttributes::initTLSAttributes() {
654
// get current edited junction
655
const auto junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
656
if (junction == nullptr) {
657
throw ProcessError("Junction cannot be NULL");
658
} else {
659
// enable Offset
660
myOffsetTextField->enable();
661
myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
662
// enable parameters
663
myButtonEditParameters->enable();
664
myParametersTextField->enable();
665
myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
666
// reset mySetDetectorsToggleButton
667
disableE1DetectorMode();
668
}
669
}
670
671
672
void
673
GNETLSEditorFrame::TLSAttributes::clearTLSAttributes() {
674
// clear and disable Offset TextField
675
myOffsetTextField->setText("");
676
myOffsetTextField->disable();
677
myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
678
// clear and disable parameters TextField
679
myButtonEditParameters->disable();
680
myParametersTextField->setText("");
681
myParametersTextField->disable();
682
myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
683
}
684
685
686
SUMOTime
687
GNETLSEditorFrame::TLSAttributes::getOffset() const {
688
return getSUMOTime(myOffsetTextField->getText().text());
689
}
690
691
692
void
693
GNETLSEditorFrame::TLSAttributes::setOffset(const SUMOTime& offset) {
694
myOffsetTextField->setText(getSteps2Time(offset).c_str());
695
myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
696
}
697
698
699
bool
700
GNETLSEditorFrame::TLSAttributes::isValidOffset() {
701
if (GNEAttributeCarrier::canParse<SUMOTime>(myOffsetTextField->getText().text())) {
702
myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
703
return true;
704
} else {
705
myOffsetTextField->setTextColor(MFXUtils::getFXColor(RGBColor::RED));
706
return false;
707
}
708
}
709
710
711
std::string
712
GNETLSEditorFrame::TLSAttributes::getParameters() const {
713
return myParametersTextField->getText().text();
714
}
715
716
717
void
718
GNETLSEditorFrame::TLSAttributes::setParameters(const std::string& parameters) {
719
myParametersTextField->setText(parameters.c_str());
720
myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
721
// update E1 detectors
722
if (myTLSEditorParent->myEditedDef->getType() != TrafficLightType::STATIC) {
723
updateE1Detectors();
724
}
725
}
726
727
728
bool
729
GNETLSEditorFrame::TLSAttributes::isValidParameters() {
730
if (Parameterised::areParametersValid(myParametersTextField->getText().text())) {
731
myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
732
return true;
733
} else {
734
myParametersTextField->setTextColor(MFXUtils::getFXColor(RGBColor::RED));
735
return false;
736
}
737
}
738
739
740
bool
741
GNETLSEditorFrame::TLSAttributes::isSetDetectorsToggleButtonEnabled() const {
742
return (mySetDetectorsToggleButton->getState() == TRUE);
743
}
744
745
746
bool
747
GNETLSEditorFrame::TLSAttributes::toggleE1DetectorSelection(const GNEAdditional* E1) {
748
// get E1 lane ID
749
const auto laneID = E1->getParentLanes().front()->getID();
750
// iterate over all E1 detectors
751
for (auto it = myE1Detectors.begin(); it != myE1Detectors.end(); it++) {
752
if (E1->getID() == it->second) {
753
// already selected, then remove it from detectors
754
myE1Detectors.erase(it);
755
// and remove it from parameters
756
myTLSEditorParent->myEditedDef->unsetParameter(laneID);
757
myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
758
// mark TL as modified
759
myTLSEditorParent->myTLSPrograms->markAsModified();
760
return true;
761
} else if (laneID == it->first) {
762
// there is another E1 in the same lane, then swap
763
myE1Detectors.erase(it);
764
myE1Detectors[laneID] = E1->getID();
765
// also in parameters
766
myTLSEditorParent->myEditedDef->setParameter(laneID, E1->getID());
767
myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
768
// mark TL as modified
769
myTLSEditorParent->myTLSPrograms->markAsModified();
770
return true;
771
}
772
}
773
// add it in parameters
774
myE1Detectors[laneID] = E1->getID();
775
myTLSEditorParent->myEditedDef->setParameter(laneID, E1->getID());
776
myParametersTextField->setText(myTLSEditorParent->myEditedDef->getParametersStr().c_str());
777
// mark TL as modified
778
myTLSEditorParent->myTLSPrograms->markAsModified();
779
return true;
780
}
781
782
783
const std::map<std::string, std::string>&
784
GNETLSEditorFrame::TLSAttributes::getE1Detectors() const {
785
return myE1Detectors;
786
}
787
788
789
void
790
GNETLSEditorFrame::TLSAttributes::disableE1DetectorMode() {
791
mySetDetectorsToggleButton->setState(FALSE, TRUE);
792
}
793
794
795
long
796
GNETLSEditorFrame::TLSAttributes::onCmdSetOffset(FXObject*, FXSelector, void*) {
797
if (isValidOffset()) {
798
myTLSEditorParent->myTLSPrograms->markAsModified();
799
myTLSEditorParent->myEditedDef->setOffset(getOffset());
800
myOffsetTextField->killFocus();
801
myTLSEditorParent->updateModules();
802
}
803
return 1;
804
}
805
806
807
long
808
GNETLSEditorFrame::TLSAttributes::onCmdSetParameters(FXObject*, FXSelector, void*) {
809
if (isValidParameters()) {
810
myTLSEditorParent->myTLSPrograms->markAsModified();
811
myTLSEditorParent->myEditedDef->setParametersStr(getParameters());
812
myParametersTextField->killFocus();
813
myTLSEditorParent->updateModules();
814
}
815
return 1;
816
}
817
818
819
long
820
GNETLSEditorFrame::TLSAttributes::onCmdParametersDialog(FXObject*, FXSelector, void*) {
821
auto GNEApp = myTLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows();
822
// continue depending of myEditedDef
823
if (myTLSEditorParent->myEditedDef) {
824
// get previous parameters
825
const auto previousParameters = getParameters();
826
// open parameters dialog
827
const GNEParametersDialog parametersDialog(GNEApp, myTLSEditorParent->myEditedDef->getParametersMap());
828
// continue depending of result
829
if (parametersDialog.getResult() == GNEDialog::Result::ACCEPT) {
830
// set parameters in myEditedDef
831
myTLSEditorParent->myEditedDef->setParameters(parametersDialog.getEditedParameters());
832
// set parameters in textfield
833
setParameters(myTLSEditorParent->myEditedDef->getParametersStr());
834
// only mark as modified if parameters are different
835
if (getParameters() != previousParameters) {
836
myTLSEditorParent->myTLSPrograms->markAsModified();
837
}
838
}
839
myTLSEditorParent->updateModules();
840
}
841
return 1;
842
}
843
844
845
long
846
GNETLSEditorFrame::TLSAttributes::onCmdToggleDetectorMode(FXObject*, FXSelector, void*) {
847
if (mySetDetectorsToggleButton->getState()) {
848
// set special color
849
mySetDetectorsToggleButton->setBackColor(FXRGBA(253, 255, 206, 255));
850
} else {
851
// restore default color
852
mySetDetectorsToggleButton->setBackColor(4293980400);
853
}
854
myTLSEditorParent->updateModules();
855
// update view
856
myTLSEditorParent->getViewNet()->update();
857
return 1;
858
}
859
860
861
void
862
GNETLSEditorFrame::TLSAttributes::updateE1Detectors() {
863
// first clear E1 detectors
864
myE1Detectors.clear();
865
// iterate over parameters
866
for (const auto& parameter : myTLSEditorParent->myEditedDef->getParametersMap()) {
867
// check if both lane and E1 exists
868
if (myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveLane(parameter.first, false) &&
869
myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_INDUCTION_LOOP, parameter.second, false)) {
870
// add it into list
871
myE1Detectors[parameter.first] = parameter.second;
872
}
873
}
874
myTLSEditorParent->updateModules();
875
// update view net
876
myTLSEditorParent->getViewNet()->update();
877
}
878
879
// ---------------------------------------------------------------------------
880
// GNETLSEditorFrame::TLSJunction - methods
881
// ---------------------------------------------------------------------------
882
883
GNETLSEditorFrame::TLSJunction::TLSJunction(GNETLSEditorFrame* TLSEditorParent) :
884
GNEGroupBoxModule(TLSEditorParent, TL("Traffic Light")),
885
myTLSEditorParent(TLSEditorParent),
886
myCurrentJunction(nullptr) {
887
const auto staticTooltip = TLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();
888
// Create frame for junction IDs
889
FXHorizontalFrame* junctionIDFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
890
myJunctionIDLabel = new FXLabel(junctionIDFrame, TL("Junction ID"), nullptr, GUIDesignLabelThickedFixed(100));
891
myJunctionIDTextField = new MFXTextFieldIcon(junctionIDFrame, staticTooltip, GUIIcon::EMPTY, nullptr, 0, GUIDesignTextField);
892
// junction ID remains always disabled
893
myJunctionIDTextField->disable();
894
// Create frame for TLS Program ID
895
FXHorizontalFrame* TLSIDFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
896
new FXLabel(TLSIDFrame, TL("TLS ID"), nullptr, GUIDesignLabelThickedFixed(100));
897
myTLSIDTextField = new MFXTextFieldIcon(TLSIDFrame, staticTooltip, GUIIcon::EMPTY, this, MID_GNE_TLSFRAME_TLSJUNCTION_ID, GUIDesignTextField);
898
// create frame, label and textfield for type
899
FXHorizontalFrame* typeFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
900
new FXLabel(typeFrame, toString(SUMO_ATTR_TYPE).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
901
myTLSTypeComboBox = new MFXComboBoxIcon(typeFrame, staticTooltip, false, GUIDesignComboBoxVisibleItems,
902
this, MID_GNE_TLSFRAME_TLSJUNCTION_TYPE, GUIDesignComboBoxAttribute);
903
// fill comboBox (only certain TL types)
904
myTLSTypeComboBox->appendIconItem(toString(TrafficLightType::STATIC).c_str());
905
myTLSTypeComboBox->appendIconItem(toString(TrafficLightType::ACTUATED).c_str());
906
myTLSTypeComboBox->appendIconItem(toString(TrafficLightType::DELAYBASED).c_str());
907
myTLSTypeComboBox->appendIconItem(toString(TrafficLightType::NEMA).c_str());
908
// create frame for join buttons
909
FXHorizontalFrame* joinButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
910
// create join states button
911
myJoinTLSToggleButton = new MFXToggleButtonTooltip(joinButtons, staticTooltip,
912
TL("Join") + std::string("\t") + TL("Enable join mode") + std::string("\t") + TL("Join TLS and junctions in the current junction."),
913
TL("Join") + std::string("\t") + TL("Disable join mode") + std::string("\t") + TL("Join TLS and junctions in the current junction."),
914
GUIIconSubSys::getIcon(GUIIcon::JOIN), GUIIconSubSys::getIcon(GUIIcon::JOIN),
915
this, MID_GNE_TLSFRAME_TLSJUNCTION_TOGGLEJOIN, GUIDesignButton);
916
myDisjoinTLSButton = new MFXButtonTooltip(joinButtons, staticTooltip,
917
TL("Disjoin") + std::string("\t") + TL("Disjoin current TLS") + std::string("\t") + TL("Disjoin current TLS."),
918
GUIIconSubSys::getIcon(GUIIcon::DISJOIN), this, MID_GNE_TLSFRAME_TLSJUNCTION_DISJOIN, GUIDesignButton);
919
// create frame for join control buttons
920
myJoinControlButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
921
// create create tlDef button
922
GUIDesigns::buildFXButton(myJoinControlButtons, TL("Accept"), "", TL("Finish join."),
923
GUIIconSubSys::getIcon(GUIIcon::ACCEPT), this, MID_GNE_BUTTON_ACCEPT, GUIDesignButton);
924
GUIDesigns::buildFXButton(myJoinControlButtons, TL("Cancel"), "", TL("Cancel Join."),
925
GUIIconSubSys::getIcon(GUIIcon::CANCEL), this, MID_GNE_BUTTON_CANCEL, GUIDesignButton);
926
// update junction description after creation
927
refreshTLSJunction();
928
// show TLS Junction
929
show();
930
}
931
932
933
GNETLSEditorFrame::TLSJunction::~TLSJunction() {}
934
935
936
void
937
GNETLSEditorFrame::TLSJunction::updateTLSJunction() {
938
if ((myCurrentJunction == nullptr) ||
939
(myCurrentJunction->getNBNode()->getControllingTLS().size() == 0)) {
940
// no TLS
941
myJunctionIDTextField->setText(TL("No junction selected"));
942
myTLSIDTextField->setText("");
943
myTLSIDTextField->disable();
944
myTLSTypeComboBox->disable();
945
myJoinTLSToggleButton->disable();
946
myDisjoinTLSButton->disable();
947
myJoinControlButtons->hide();
948
} else {
949
// get first controled TLS
950
const auto TLS = (*myCurrentJunction->getNBNode()->getControllingTLS().begin());
951
// set TLS type in comboBox
952
const int index = myTLSTypeComboBox->findItem(myCurrentJunction->getAttribute(SUMO_ATTR_TLTYPE).c_str());
953
if (index != -1) {
954
myTLSTypeComboBox->setCurrentItem(index, FALSE);
955
}
956
// set text field IDs
957
myJunctionIDTextField->setText(myCurrentJunction->getID().c_str());
958
myTLSIDTextField->setText(TLS->getID().c_str());
959
// continue with more options
960
if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled() ||
961
myTLSEditorParent->myTLSPrograms->checkHaveModifications()) {
962
// disable if selecting selecting detectors or we modified the program
963
myTLSIDTextField->setText("");
964
myTLSIDTextField->disable();
965
myTLSTypeComboBox->disable();
966
myJoinTLSToggleButton->disable();
967
myDisjoinTLSButton->disable();
968
myJoinControlButtons->hide();
969
} else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
970
// partial disable due joining
971
myTLSIDTextField->setText("");
972
myTLSIDTextField->disable();
973
myTLSTypeComboBox->disable();
974
myDisjoinTLSButton->disable();
975
// enable join TLS and show control buttons
976
myJoinTLSToggleButton->enable();
977
myJoinControlButtons->show();
978
} else {
979
// enable
980
myTLSIDTextField->enable();
981
myTLSTypeComboBox->enable();
982
myJoinTLSToggleButton->enable();
983
// disjoint button only if we have more than one TLS controlled
984
if (TLS->getNodes().size() == 1) {
985
myDisjoinTLSButton->disable();
986
} else {
987
myDisjoinTLSButton->enable();
988
}
989
}
990
}
991
}
992
993
994
GNEJunction*
995
GNETLSEditorFrame::TLSJunction::getCurrentJunction() const {
996
return myCurrentJunction;
997
}
998
999
1000
void
1001
GNETLSEditorFrame::TLSJunction::setCurrentJunction(GNEJunction* junction) {
1002
myCurrentJunction = junction;
1003
// resfresh module
1004
refreshTLSJunction();
1005
}
1006
1007
1008
bool
1009
GNETLSEditorFrame::TLSJunction::isJoiningJunctions() const {
1010
return (myJoinTLSToggleButton->getState() == TRUE);
1011
}
1012
1013
1014
bool
1015
GNETLSEditorFrame::TLSJunction::isJunctionSelected(const GNEJunction* junction) const {
1016
return (std::find(mySelectedJunctionIDs.begin(), mySelectedJunctionIDs.end(), junction->getID()) != mySelectedJunctionIDs.end());
1017
}
1018
1019
1020
void
1021
GNETLSEditorFrame::TLSJunction::toggleJunctionSelected(const GNEJunction* junction) {
1022
// avoid current junction
1023
if (junction != myCurrentJunction) {
1024
// find ID in selected junctions
1025
auto it = std::find(mySelectedJunctionIDs.begin(), mySelectedJunctionIDs.end(), junction->getID());
1026
// check if add or remove
1027
if (it == mySelectedJunctionIDs.end()) {
1028
mySelectedJunctionIDs.push_back(junction->getID());
1029
} else {
1030
mySelectedJunctionIDs.erase(it);
1031
}
1032
}
1033
}
1034
1035
1036
const std::vector<std::string>&
1037
GNETLSEditorFrame::TLSJunction::getSelectedJunctionIDs() const {
1038
return mySelectedJunctionIDs;
1039
}
1040
1041
1042
long
1043
GNETLSEditorFrame::TLSJunction::onCmdRenameTLS(FXObject*, FXSelector, void*) {
1044
// get IDs
1045
const std::string currentTLID = (*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getID();
1046
const std::string newTLID = myTLSIDTextField->getText().text();
1047
// check if ID is valid
1048
if (newTLID.empty() || (newTLID == currentTLID)) {
1049
// same ID or empty
1050
myTLSIDTextField->setTextColor(GUIDesignTextColorBlack);
1051
myTLSIDTextField->setText(currentTLID.c_str());
1052
myTLSIDTextField->killFocus();
1053
myTLSEditorParent->update();
1054
// show all moduls
1055
myTLSEditorParent->myTLSPrograms->showTLSPrograms();
1056
myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1057
myTLSEditorParent->myTLSPhases->showTLSPhases();
1058
myTLSEditorParent->myTLSFile->showTLSFile();
1059
} else if (!SUMOXMLDefinitions::isValidNetID(newTLID) || myCurrentJunction->getNet()->getTLLogicCont().exist(newTLID)) {
1060
// set invalid color
1061
myTLSIDTextField->setTextColor(GUIDesignTextColorRed);
1062
// hide moduls
1063
myTLSEditorParent->myTLSPrograms->hideTLSPrograms();
1064
myTLSEditorParent->myTLSAttributes->hideTLSAttributes();
1065
myTLSEditorParent->myTLSPhases->hideTLSPhases();
1066
myTLSEditorParent->myTLSFile->hideTLSFile();
1067
} else {
1068
// make a copy of myCurrentJunction and current tlDef (because will be reset after calling discardChanges)
1069
auto junction = myCurrentJunction;
1070
const auto tlDef = myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms();
1071
// restore color
1072
myTLSIDTextField->setTextColor(GUIDesignTextColorBlack);
1073
myTLSIDTextField->killFocus();
1074
myTLSEditorParent->update();
1075
// discard previous changes
1076
myTLSEditorParent->myTLSPrograms->discardChanges(false);
1077
// change name using undo-List
1078
myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("rename TLS"));
1079
myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, tlDef, newTLID), true);
1080
myTLSEditorParent->getViewNet()->getUndoList()->end();
1081
// show all moduls
1082
myTLSEditorParent->myTLSPrograms->showTLSPrograms();
1083
myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1084
myTLSEditorParent->myTLSPhases->showTLSPhases();
1085
myTLSEditorParent->myTLSFile->showTLSFile();
1086
// edit junction again
1087
myTLSEditorParent->editJunction(junction);
1088
}
1089
myTLSEditorParent->updateModules();
1090
return 1;
1091
}
1092
1093
1094
long
1095
GNETLSEditorFrame::TLSJunction::onCmdChangeType(FXObject*, FXSelector, void*) {
1096
// get IDs
1097
const std::string currentTLType = toString((*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getType());
1098
const std::string newTLType = myTLSTypeComboBox->getText().text();
1099
// check if ID is valid
1100
if (newTLType.empty() || (newTLType == currentTLType)) {
1101
// same ID or empty, don't change
1102
myTLSTypeComboBox->setTextColor(GUIDesignTextColorBlack);
1103
// set value
1104
const int index = myTLSTypeComboBox->findItem(currentTLType.c_str());
1105
if (index == -1) {
1106
myTLSTypeComboBox->disable();
1107
} else {
1108
myTLSTypeComboBox->setCurrentItem(index);
1109
myTLSTypeComboBox->enable();
1110
}
1111
myTLSTypeComboBox->killFocus();
1112
myTLSEditorParent->update();
1113
// show all moduls
1114
myTLSEditorParent->myTLSPrograms->showTLSPrograms();
1115
myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1116
myTLSEditorParent->myTLSPhases->showTLSPhases();
1117
myTLSEditorParent->myTLSFile->showTLSFile();
1118
} else if (!SUMOXMLDefinitions::TrafficLightTypes.hasString(newTLType)) {
1119
// set invalid color
1120
myTLSTypeComboBox->setTextColor(GUIDesignTextColorRed);
1121
// hide moduls
1122
myTLSEditorParent->myTLSPrograms->hideTLSPrograms();
1123
myTLSEditorParent->myTLSAttributes->hideTLSAttributes();
1124
myTLSEditorParent->myTLSPhases->hideTLSPhases();
1125
myTLSEditorParent->myTLSFile->hideTLSFile();
1126
} else {
1127
// reset color
1128
myTLSTypeComboBox->setTextColor(GUIDesignTextColorBlack);
1129
myTLSTypeComboBox->killFocus();
1130
myTLSEditorParent->update();
1131
// make a copy of myCurrentJunction (because will be reset after calling discardChanges)
1132
auto junction = myCurrentJunction;
1133
// discard previous changes
1134
myTLSEditorParent->myTLSPrograms->discardChanges(false);
1135
// change name using undo-List
1136
myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("change TLS type"));
1137
junction->setAttribute(SUMO_ATTR_TLTYPE, newTLType, myTLSEditorParent->getViewNet()->getUndoList());
1138
myTLSEditorParent->getViewNet()->getUndoList()->end();
1139
// show all moduls
1140
myTLSEditorParent->myTLSPrograms->showTLSPrograms();
1141
myTLSEditorParent->myTLSAttributes->showTLSAttributes();
1142
myTLSEditorParent->myTLSPhases->showTLSPhases();
1143
myTLSEditorParent->myTLSFile->showTLSFile();
1144
// edit junction again
1145
myTLSEditorParent->editJunction(junction);
1146
}
1147
myTLSEditorParent->updateModules();
1148
return 1;
1149
1150
}
1151
1152
1153
long
1154
GNETLSEditorFrame::TLSJunction::onCmdToggleJoinTLS(FXObject*, FXSelector, void*) {
1155
if (myJoinTLSToggleButton->getState()) {
1156
// set special color
1157
myJoinTLSToggleButton->setBackColor(FXRGBA(253, 255, 206, 255));
1158
// clear and fill mySelectedJunctionIDs
1159
mySelectedJunctionIDs.clear();
1160
// get all nodes controlled by this TLS
1161
const auto TLNodes = (*myCurrentJunction->getNBNode()->getControllingTLS().begin())->getNodes();
1162
// fill mySelectedJunctionIDs with TLNodes
1163
mySelectedJunctionIDs.clear();
1164
for (const auto& TLNode : TLNodes) {
1165
mySelectedJunctionIDs.push_back(TLNode->getID());
1166
}
1167
// make a copy of selected junctions
1168
myOriginalSelectedJunctionIDs = mySelectedJunctionIDs;
1169
// show control buttons
1170
myJoinControlButtons->show();
1171
getCollapsableFrame()->recalc();
1172
} else {
1173
// hide control buttons
1174
myJoinControlButtons->hide();
1175
getCollapsableFrame()->recalc();
1176
// make a copy of current junction
1177
const auto currentJunction = myCurrentJunction;
1178
// declare vectors for junctions
1179
std::vector<GNEJunction*> selectedJunctions, resetTLJunctions;
1180
// get selected junctions (all except current
1181
for (const auto& selectedJunctionID : mySelectedJunctionIDs) {
1182
if (selectedJunctionID != currentJunction->getID()) {
1183
selectedJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(selectedJunctionID));
1184
}
1185
}
1186
// get junctions to reset TL (all TL nodes except current)
1187
for (const auto& TLNBNode : (*currentJunction->getNBNode()->getControllingTLS().begin())->getNodes()) {
1188
if (TLNBNode != currentJunction->getNBNode()) {
1189
resetTLJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLNBNode->getID()));
1190
}
1191
}
1192
// discard changes
1193
myTLSEditorParent->myTLSPrograms->discardChanges(false);
1194
// begin undo list
1195
myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("join TLS"));
1196
// remove tl from TLNBNode
1197
for (const auto& resetTLJunction : resetTLJunctions) {
1198
resetTLJunction->setAttribute(SUMO_ATTR_TYPE, "priority", myTLSEditorParent->getViewNet()->getUndoList());
1199
}
1200
// now update it in all joined junctions
1201
for (const auto& selectedJunction : selectedJunctions) {
1202
selectedJunction->setAttribute(SUMO_ATTR_TYPE, currentJunction->getAttribute(SUMO_ATTR_TYPE), myTLSEditorParent->getViewNet()->getUndoList());
1203
selectedJunction->setAttribute(SUMO_ATTR_TLID, currentJunction->getAttribute(SUMO_ATTR_TLID), myTLSEditorParent->getViewNet()->getUndoList());
1204
}
1205
// end undo list
1206
myTLSEditorParent->getViewNet()->getUndoList()->end();
1207
// restore default color
1208
myJoinTLSToggleButton->setBackColor(4293980400);
1209
// clear selected junction IDs
1210
mySelectedJunctionIDs.clear();
1211
// edit junction again
1212
myTLSEditorParent->editJunction(currentJunction);
1213
}
1214
myTLSEditorParent->updateModules();
1215
// update view
1216
myTLSEditorParent->getViewNet()->update();
1217
return 1;
1218
}
1219
1220
1221
long
1222
GNETLSEditorFrame::TLSJunction::onCmdDisjoinTLS(FXObject*, FXSelector, void*) {
1223
// make a copy of current junction
1224
const auto currentJunction = myCurrentJunction;
1225
// declare vectors for junctions
1226
std::vector<GNEJunction*> resetTLJunctions;
1227
// get junctions to reset TL
1228
for (const auto& TLNBNode : (*currentJunction->getNBNode()->getControllingTLS().begin())->getNodes()) {
1229
resetTLJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLNBNode->getID()));
1230
}
1231
// save TL types
1232
const auto type = resetTLJunctions.front()->getAttribute(SUMO_ATTR_TYPE);
1233
const auto tlType = resetTLJunctions.front()->getAttribute(SUMO_ATTR_TLTYPE);
1234
// discard changes
1235
myTLSEditorParent->myTLSPrograms->discardChanges(false);
1236
// begin undo list
1237
myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("disjoin TLS"));
1238
// the disjoint tlIds will be the junction ids. Ensure that there is no name clash with the current tlId
1239
NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1240
const std::string oldId = currentJunction->getAttribute(SUMO_ATTR_TLID);
1241
const std::string tmpIdBase = oldId + "_TMP";
1242
int tmpIndex = 0;
1243
std::string tmpId = tmpIdBase + toString(tmpIndex);
1244
while (tllCont.exist(tmpId)) {
1245
tmpId = tmpIdBase + toString(++tmpIndex);
1246
}
1247
for (NBTrafficLightDefinition* tlDef : currentJunction->getNBNode()->getControllingTLS()) {
1248
myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(currentJunction, tlDef, tmpId), true);
1249
}
1250
// remove tl from TLNBNode and the re-initialize as single traffic light
1251
for (const auto& resetTLJunction : resetTLJunctions) {
1252
resetTLJunction->setAttribute(SUMO_ATTR_TYPE, "priority", myTLSEditorParent->getViewNet()->getUndoList());
1253
resetTLJunction->setAttribute(SUMO_ATTR_TYPE, type, myTLSEditorParent->getViewNet()->getUndoList());
1254
resetTLJunction->setAttribute(SUMO_ATTR_TLTYPE, tlType, myTLSEditorParent->getViewNet()->getUndoList());
1255
}
1256
// end undo list
1257
myTLSEditorParent->getViewNet()->getUndoList()->end();
1258
// restore default color
1259
myJoinTLSToggleButton->setBackColor(4293980400);
1260
// clear selected junction IDs
1261
mySelectedJunctionIDs.clear();
1262
// edit junction again
1263
myTLSEditorParent->editJunction(currentJunction);
1264
myTLSEditorParent->updateModules();
1265
return 1;
1266
}
1267
1268
1269
long
1270
GNETLSEditorFrame::TLSJunction::onCmdAcceptJoin(FXObject*, FXSelector, void*) {
1271
myJoinTLSToggleButton->setState(FALSE, TRUE);
1272
myTLSEditorParent->updateModules();
1273
return 1;
1274
}
1275
1276
1277
long
1278
GNETLSEditorFrame::TLSJunction::onCmdCancelJoin(FXObject*, FXSelector, void*) {
1279
// restore selected junction
1280
mySelectedJunctionIDs = myOriginalSelectedJunctionIDs;
1281
myJoinTLSToggleButton->setState(FALSE, TRUE);
1282
myTLSEditorParent->updateModules();
1283
return 1;
1284
}
1285
1286
1287
void
1288
GNETLSEditorFrame::TLSJunction::refreshTLSJunction() {
1289
// first reset junction label
1290
myJunctionIDLabel->setText(TL("Junction ID"));
1291
// clear selected junctions
1292
mySelectedJunctionIDs.clear();
1293
// cancel joining junction mode
1294
onCmdCancelJoin(nullptr, 0, nullptr);
1295
// continue depending of current junction
1296
if (myCurrentJunction == nullptr) {
1297
myJunctionIDTextField->setText(TL("No junction selected"));
1298
} else {
1299
// get all TLS assigned to this node
1300
const auto& TLSs = myCurrentJunction->getNBNode()->getControllingTLS();
1301
// check if junction is controlled
1302
if (TLSs.size() > 0) {
1303
// get first TLS
1304
const auto TLS = (*TLSs.begin());
1305
// update junction ID text field
1306
if (TLS->getNodes().size() > 1) {
1307
// declare string
1308
std::string TLSNodesStr;
1309
for (auto it = TLS->getNodes().begin(); it != TLS->getNodes().end(); it++) {
1310
if (it == (TLS->getNodes().end() - 1)) {
1311
TLSNodesStr += (*it)->getID();
1312
} else {
1313
TLSNodesStr += (*it)->getID() + ", ";
1314
}
1315
}
1316
// updated junction fields
1317
myJunctionIDTextField->setText(TLSNodesStr.c_str());
1318
// update junction label if we have multiple nodes
1319
if (TLS->getNodes().size() > 1) {
1320
myJunctionIDLabel->setText(TL("Junction IDs"));
1321
}
1322
// set TLS type in comboBox
1323
const int index = myTLSTypeComboBox->findItem(myCurrentJunction->getAttribute(SUMO_ATTR_TLTYPE).c_str());
1324
if (index != -1) {
1325
myTLSTypeComboBox->setCurrentItem(index, FALSE);
1326
}
1327
}
1328
} else {
1329
// update junction ID text field
1330
myJunctionIDTextField->setText(myCurrentJunction->getID().c_str());
1331
myTLSTypeComboBox->setCurrentItem(0, FALSE);
1332
}
1333
}
1334
// update TLS junction
1335
updateTLSJunction();
1336
}
1337
1338
// ---------------------------------------------------------------------------
1339
// GNETLSEditorFrame::TLSPrograms - methods
1340
// ---------------------------------------------------------------------------
1341
1342
GNETLSEditorFrame::TLSPrograms::TLSPrograms(GNETLSEditorFrame* TLSEditorParent) :
1343
GNEGroupBoxModule(TLSEditorParent, TL("Traffic Light Programs")),
1344
myTLSEditorParent(TLSEditorParent) {
1345
// create frame, label and comboBox for programID
1346
FXHorizontalFrame* programFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
1347
new FXLabel(programFrame, toString(SUMO_ATTR_PROGRAMID).c_str(), nullptr, GUIDesignLabelThickedFixed(100));
1348
myProgramComboBox = new MFXComboBoxIcon(programFrame, TLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
1349
false, GUIDesignComboBoxVisibleItems, this, MID_GNE_TLSFRAME_DEFINITION_SWITCHPROGRAM, GUIDesignComboBoxAttribute);
1350
myProgramComboBox->disable();
1351
// create auxiliar frames
1352
FXHorizontalFrame* horizontalFrameAux = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
1353
FXVerticalFrame* verticalFrameAuxA = new FXVerticalFrame(horizontalFrameAux, GUIDesignAuxiliarHorizontalFrame);
1354
FXVerticalFrame* verticalFrameAuxB = new FXVerticalFrame(horizontalFrameAux, GUIDesignAuxiliarHorizontalFrame);
1355
// create create tlDef button
1356
myCreateButton = GUIDesigns::buildFXButton(verticalFrameAuxA, TL("Create TLS"), "", TL("Create a new traffic light program."),
1357
GUIIconSubSys::getIcon(GUIIcon::MODETLS), this, MID_GNE_TLSFRAME_DEFINITION_CREATE, GUIDesignButton);
1358
myCreateButton->disable();
1359
// create delete tlDef button
1360
myDeleteButton = GUIDesigns::buildFXButton(verticalFrameAuxA, TL("Delete"), "", TL("Delete a traffic light program. If all programs are deleted the junction turns into a priority junction."),
1361
GUIIconSubSys::getIcon(GUIIcon::REMOVE), this, MID_GNE_TLSFRAME_DEFINITION_DELETE, GUIDesignButton);
1362
myDeleteButton->disable();
1363
// create reset current tlDef button
1364
myResetSingleButton = GUIDesigns::buildFXButton(verticalFrameAuxB, TL("Reset single"), "", TL("Reset current TLS program."),
1365
GUIIconSubSys::getIcon(GUIIcon::RESET), this, MID_GNE_TLSFRAME_DEFINITION_RESETCURRENT, GUIDesignButton);
1366
myResetSingleButton->disable();
1367
// create reset all tlDefs button
1368
myResetAllButton = GUIDesigns::buildFXButton(verticalFrameAuxB, TL("Reset all"), "", TL("Reset all TLS programs."),
1369
GUIIconSubSys::getIcon(GUIIcon::RESET), this, MID_GNE_TLSFRAME_DEFINITION_RESETALL, GUIDesignButton);
1370
myResetAllButton->disable();
1371
// create save modifications button
1372
mySaveButon = GUIDesigns::buildFXButton(verticalFrameAuxA, TL("Save"), "", TL("Save program modifications. (Enter)"),
1373
GUIIconSubSys::getIcon(GUIIcon::OK), this, MID_GNE_TLSFRAME_DEFINITION_SAVE, GUIDesignButton);
1374
mySaveButon->disable();
1375
// create cancel modifications buttons
1376
myCancelButon = GUIDesigns::buildFXButton(verticalFrameAuxB, TL("Cancel"), "", TL("Discard program modifications. (Esc)"),
1377
GUIIconSubSys::getIcon(GUIIcon::CANCEL), this, MID_GNE_TLSFRAME_DEFINITION_DISCARD, GUIDesignButton);
1378
myCancelButon->disable();
1379
// show GroupBox
1380
show();
1381
}
1382
1383
1384
GNETLSEditorFrame::TLSPrograms::~TLSPrograms() {}
1385
1386
1387
void
1388
GNETLSEditorFrame::TLSPrograms::updateTLSPrograms() {
1389
if (getNumberOfPrograms() == 0) {
1390
// no TLS Programs, disable buttons except create (if we have a junction)
1391
if (myTLSEditorParent->getTLSJunction()->getCurrentJunction() != nullptr) {
1392
myCreateButton->enable();
1393
} else {
1394
myCreateButton->disable();
1395
}
1396
myDeleteButton->disable();
1397
myResetSingleButton->disable();
1398
myProgramComboBox->disable();
1399
myResetAllButton->disable();
1400
mySaveButon->disable();
1401
myCancelButon->disable();
1402
} else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1403
// selecting E1, disable buttons
1404
myCreateButton->disable();
1405
myDeleteButton->disable();
1406
myResetSingleButton->disable();
1407
myProgramComboBox->disable();
1408
myResetAllButton->disable();
1409
mySaveButon->disable();
1410
myCancelButon->disable();
1411
} else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1412
// joining TLSs, disable button
1413
myCreateButton->disable();
1414
myDeleteButton->disable();
1415
myResetSingleButton->disable();
1416
myProgramComboBox->disable();
1417
myResetAllButton->disable();
1418
mySaveButon->disable();
1419
myCancelButon->disable();
1420
} else if (myHaveModifications) {
1421
// modifications, disable button
1422
myCreateButton->disable();
1423
myDeleteButton->disable();
1424
myResetSingleButton->disable();
1425
myProgramComboBox->disable();
1426
myResetAllButton->disable();
1427
// enable save and cancel buttons
1428
mySaveButon->enable();
1429
myCancelButon->enable();
1430
} else {
1431
myCreateButton->enable();
1432
myDeleteButton->enable();
1433
myResetSingleButton->enable();
1434
myProgramComboBox->enable();
1435
// disable save and cancel buttons
1436
mySaveButon->disable();
1437
myCancelButon->disable();
1438
// check if enable reset all
1439
if (getNumberOfPrograms() > 1) {
1440
myResetAllButton->enable();
1441
} else {
1442
myResetAllButton->disable();
1443
}
1444
}
1445
// get current junction
1446
const auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1447
// update button text
1448
if (currentJunction == nullptr) {
1449
myCreateButton->setText(TL("Create"));
1450
} else if (currentJunction->getNBNode()->isTLControlled()) {
1451
myCreateButton->setText(TL("Duplicate"));
1452
} else {
1453
myCreateButton->setText(TL("Create"));
1454
}
1455
}
1456
1457
1458
void
1459
GNETLSEditorFrame::TLSPrograms::showTLSPrograms() {
1460
show();
1461
}
1462
1463
1464
void
1465
GNETLSEditorFrame::TLSPrograms::hideTLSPrograms() {
1466
hide();
1467
}
1468
1469
1470
bool
1471
GNETLSEditorFrame::TLSPrograms::initTLSPrograms() {
1472
// get current edited junction
1473
const auto junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1474
if (junction == nullptr) {
1475
throw ProcessError("Junction cannot be NULL");
1476
} else {
1477
// clear definitions
1478
myTLSPrograms.clear();
1479
// obtain TLSs sorted by ID
1480
std::set<std::string> programIDs;
1481
for (const auto& TLS : junction->getNBNode()->getControllingTLS()) {
1482
myTLSPrograms.push_back(TLS);
1483
programIDs.insert(TLS->getProgramID());
1484
}
1485
for (const auto& programID : programIDs) {
1486
myProgramComboBox->appendIconItem(programID.c_str());
1487
}
1488
// check if enable TLS definitions
1489
if (myTLSPrograms.size() > 0) {
1490
myProgramComboBox->enable();
1491
myProgramComboBox->setCurrentItem(0);
1492
// switch TLS Program
1493
return switchProgram();
1494
}
1495
return false;
1496
}
1497
}
1498
1499
1500
void
1501
GNETLSEditorFrame::TLSPrograms::clearTLSProgramss() {
1502
// clear definitions
1503
myTLSPrograms.clear();
1504
// clear and disable myProgramComboBox
1505
myProgramComboBox->clearItems();
1506
myProgramComboBox->disable();
1507
}
1508
1509
1510
int
1511
GNETLSEditorFrame::TLSPrograms::getNumberOfPrograms() const {
1512
return myProgramComboBox->getNumItems();
1513
}
1514
1515
1516
bool
1517
GNETLSEditorFrame::TLSPrograms::checkHaveModifications() const {
1518
return myHaveModifications;
1519
}
1520
1521
1522
void
1523
GNETLSEditorFrame::TLSPrograms::markAsModified() {
1524
myHaveModifications = true;
1525
myTLSEditorParent->updateModules();
1526
}
1527
1528
1529
NBTrafficLightDefinition*
1530
GNETLSEditorFrame::TLSPrograms::getCurrentTLSPrograms() const {
1531
// find TLS definition
1532
for (const auto& TLSPrograms : myTLSPrograms) {
1533
if (TLSPrograms->getProgramID() == myProgramComboBox->getText().text()) {
1534
return TLSPrograms;
1535
}
1536
}
1537
throw ProcessError(TL("TLSPrograms cannot be found"));
1538
}
1539
1540
1541
const std::string
1542
GNETLSEditorFrame::TLSPrograms::getCurrentTLSProgramID() const {
1543
if (myProgramComboBox->getNumItems() == 0) {
1544
return "";
1545
} else {
1546
return myProgramComboBox->getText().text();
1547
}
1548
}
1549
1550
1551
void
1552
GNETLSEditorFrame::TLSPrograms::discardChanges(const bool editJunctionAgain) {
1553
// get junction copy
1554
auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1555
if (currentJunction != nullptr) {
1556
myTLSEditorParent->getViewNet()->getUndoList()->abortAllChangeGroups();
1557
myTLSEditorParent->cleanup();
1558
myTLSEditorParent->getViewNet()->updateViewNet();
1559
// edit junction again
1560
if (editJunctionAgain) {
1561
myTLSEditorParent->editJunction(currentJunction);
1562
}
1563
}
1564
myTLSEditorParent->updateModules();
1565
}
1566
1567
1568
long
1569
GNETLSEditorFrame::TLSPrograms::onCmdCreate(FXObject*, FXSelector, void*) {
1570
auto GNEApp = myTLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows();
1571
// get current edited junction (needed because onCmdDiscardChanges clear junction)
1572
GNEJunction* currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1573
// abort because we onCmdOk assumes we wish to save an edited definition
1574
discardChanges(false);
1575
// check number of edges
1576
if (currentJunction->getGNEIncomingEdges().empty() && currentJunction->getGNEOutgoingEdges().empty()) {
1577
// open warning dialog
1578
GNEWarningBasicDialog(GNEApp,
1579
TL("TLS cannot be created"),
1580
TL("Traffic Light cannot be created because junction must have"),
1581
TL("at least one incoming edge and one outgoing edge.")
1582
);
1583
return 1;
1584
}
1585
// check number of connections
1586
if (currentJunction->getGNEConnections().empty()) {
1587
// open warning dialog
1588
GNEWarningBasicDialog(GNEApp,
1589
TL("TLS cannot be created"),
1590
TL("Traffic Light cannot be created because junction"),
1591
TL("must have at least one connection.")
1592
);
1593
return 1;
1594
}
1595
// check uncontrolled connections
1596
bool connectionControlled = false;
1597
for (const auto& connection : currentJunction->getGNEConnections()) {
1598
if (!connection->getNBEdgeConnection().uncontrolled) {
1599
connectionControlled = true;
1600
}
1601
}
1602
if (!connectionControlled) {
1603
// open warning dialog
1604
GNEWarningBasicDialog(GNEApp,
1605
TL("TLS cannot be created"),
1606
TL("Traffic Light cannot be created because junction"),
1607
TL("must have at least one controlled connection.")
1608
);
1609
return 1;
1610
}
1611
// all checks ok, then create TLS in junction
1612
createTLS(currentJunction);
1613
// edit junction
1614
myTLSEditorParent->editJunction(currentJunction);
1615
// switch to the last program
1616
myProgramComboBox->setCurrentItem(myProgramComboBox->getNumItems() - 1, TRUE);
1617
myTLSEditorParent->updateModules();
1618
return 1;
1619
}
1620
1621
1622
long
1623
GNETLSEditorFrame::TLSPrograms::onCmdDelete(FXObject*, FXSelector, void*) {
1624
// get current junction
1625
GNEJunction* currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1626
// get current edited tlDef
1627
NBTrafficLightDefinition* tlDef = myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms();
1628
// check if remove entire TLS or only one program
1629
const bool changeJunctionType = (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() == 1);
1630
// abort because onCmdOk assumes we wish to save an edited definition
1631
discardChanges(false);
1632
// check if change junction type
1633
if (changeJunctionType) {
1634
currentJunction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::PRIORITY), myTLSEditorParent->getViewNet()->getUndoList());
1635
} else {
1636
// just remove TLDef
1637
myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(currentJunction, tlDef, false), true);
1638
// edit junction again
1639
myTLSEditorParent->editJunction(currentJunction);
1640
}
1641
myTLSEditorParent->updateModules();
1642
return 1;
1643
}
1644
1645
1646
long
1647
GNETLSEditorFrame::TLSPrograms::onCmdResetCurrentProgram(FXObject*, FXSelector, void*) {
1648
// obtain junction and old definitions
1649
GNEJunction* junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1650
NBTrafficLightDefinition* oldDef = myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms();
1651
const std::string programID = oldDef->getProgramID();
1652
// discard changes
1653
discardChanges(false);
1654
// begin undo
1655
myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("reset current program"));
1656
// remove old definition
1657
myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, oldDef, false), true);
1658
// create new definition, and add it
1659
NBOwnTLDef* newDef = new NBOwnTLDef(oldDef->getID(), oldDef->getNodes(), oldDef->getOffset(), oldDef->getType());
1660
newDef->setProgramID(programID);
1661
myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newDef, true, true), true);
1662
// set old index
1663
// end undo
1664
myTLSEditorParent->getViewNet()->getUndoList()->end();
1665
// inspect junction again
1666
myTLSEditorParent->editJunction(junction);
1667
// switch to programID
1668
int index = -1;
1669
for (int i = 0; i < myProgramComboBox->getNumItems(); i++) {
1670
if (myProgramComboBox->getItemText(i) == programID) {
1671
index = i;
1672
}
1673
}
1674
if (index != -1) {
1675
myProgramComboBox->setCurrentItem(index, TRUE);
1676
}
1677
myTLSEditorParent->updateModules();
1678
return 1;
1679
}
1680
1681
1682
long
1683
GNETLSEditorFrame::TLSPrograms::onCmdResetAll(FXObject*, FXSelector, void*) {
1684
// obtain junction and old definitions
1685
GNEJunction* junction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1686
NBTrafficLightDefinition* oldDef = myTLSEditorParent->myTLSPrograms->getCurrentTLSPrograms();
1687
// get a list of all affected nodes
1688
std::vector<GNEJunction*> TLSJunctions;
1689
for (const auto& TLSNode : oldDef->getNodes()) {
1690
TLSJunctions.push_back(myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(TLSNode->getID()));
1691
}
1692
// discard all previous changes
1693
discardChanges(false);
1694
// begin undo
1695
myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TL("reset TLS"));
1696
// set junction as priority (this will also remove all program, see GNEJunction::setJunctionType)
1697
for (const auto& TLSJunction : TLSJunctions) {
1698
TLSJunction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::PRIORITY), myTLSEditorParent->getViewNet()->getUndoList());
1699
}
1700
// create TLS in junction
1701
createTLS(junction);
1702
// set TLS in all other junctions
1703
for (const auto& TLSJunction : TLSJunctions) {
1704
if (TLSJunction != junction) {
1705
TLSJunction->setAttribute(SUMO_ATTR_TYPE, TLSJunction->getAttribute(SUMO_ATTR_TYPE), myTLSEditorParent->getViewNet()->getUndoList());
1706
TLSJunction->setAttribute(SUMO_ATTR_TLID, TLSJunction->getAttribute(SUMO_ATTR_TLID), myTLSEditorParent->getViewNet()->getUndoList());
1707
}
1708
}
1709
// end undo
1710
myTLSEditorParent->getViewNet()->getUndoList()->end();
1711
// edit junction
1712
myTLSEditorParent->editJunction(junction);
1713
return 1;
1714
}
1715
1716
1717
long
1718
GNETLSEditorFrame::TLSPrograms::onCmdDefSwitchTLSProgram(FXObject*, FXSelector, void*) {
1719
// check if program is valid (user may input arbitrary text)
1720
bool found = false;
1721
for (const auto& TLSPrograms : myTLSPrograms) {
1722
if (TLSPrograms->getProgramID() == myProgramComboBox->getText().text()) {
1723
found = true;
1724
break;
1725
}
1726
}
1727
if (!found) {
1728
// reset field to a valid program
1729
myProgramComboBox->setText(myTLSPrograms.front()->getProgramID().c_str());
1730
}
1731
switchProgram();
1732
return 1;
1733
}
1734
1735
1736
long
1737
GNETLSEditorFrame::TLSPrograms::onCmdSaveChanges(FXObject*, FXSelector, void*) {
1738
// get junction copy
1739
const auto currentJunction = myTLSEditorParent->myTLSJunction->getCurrentJunction();
1740
// get current program
1741
const auto currentProgram = myProgramComboBox->getCurrentItem();
1742
// check that junction is valid
1743
if (currentJunction != nullptr) {
1744
const auto oldDefinition = getCurrentTLSPrograms();
1745
std::vector<NBNode*> nodes = oldDefinition->getNodes();
1746
GNEUndoList* undoList = myTLSEditorParent->getViewNet()->getUndoList();
1747
for (const auto& node : nodes) {
1748
GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(node->getID());
1749
undoList->add(new GNEChange_TLS(junction, oldDefinition, false), true);
1750
undoList->add(new GNEChange_TLS(junction, myTLSEditorParent->myEditedDef, true), true);
1751
// synchronize crossing tl-indices in case they were changed (via onCmdCleanStates)
1752
for (const auto& gc : junction->getGNECrossings()) {
1753
NBNode::Crossing* c = gc->getNBCrossing();
1754
if (c) {
1755
gc->setAttribute(SUMO_ATTR_TLLINKINDEX, toString(c->tlLinkIndex), undoList);
1756
gc->setAttribute(SUMO_ATTR_TLLINKINDEX2, toString(c->tlLinkIndex2), undoList);
1757
}
1758
}
1759
1760
1761
}
1762
// end change
1763
myTLSEditorParent->getViewNet()->getUndoList()->end();
1764
// mark as saved
1765
myHaveModifications = false;
1766
// reset myEditedDef (because is already in eine undo-list)
1767
myTLSEditorParent->myEditedDef = nullptr;
1768
myTLSEditorParent->cleanup();
1769
myTLSEditorParent->getViewNet()->updateViewNet();
1770
// edit junction again
1771
myTLSEditorParent->editJunction(currentJunction);
1772
// change program
1773
myProgramComboBox->setCurrentItem(currentProgram, TRUE);
1774
} else {
1775
// discard changes inspecting junction again
1776
discardChanges(true);
1777
}
1778
myTLSEditorParent->updateModules();
1779
return 1;
1780
}
1781
1782
1783
long
1784
GNETLSEditorFrame::TLSPrograms::onCmdDiscardChanges(FXObject*, FXSelector, void*) {
1785
// discard changes inspecting junction again
1786
discardChanges(true);
1787
return 1;
1788
}
1789
1790
1791
void
1792
GNETLSEditorFrame::TLSPrograms::createTLS(GNEJunction* junction) {
1793
// get current TLS program id
1794
const auto currentTLS = getCurrentTLSProgramID();
1795
// check conditions
1796
if (junction == nullptr) {
1797
throw ProcessError("junction cannot be null");
1798
} else if (junction->getAttribute(SUMO_ATTR_TYPE) != toString(SumoXMLNodeType::TRAFFIC_LIGHT)) {
1799
// set junction as TLS
1800
junction->setAttribute(SUMO_ATTR_TYPE, toString(SumoXMLNodeType::TRAFFIC_LIGHT), myTLSEditorParent->getViewNet()->getUndoList());
1801
} else if (junction->getNBNode()->isTLControlled()) {
1802
// use existing traffic light as template for type, signal groups, controlled nodes etc
1803
NBTrafficLightDefinition* tpl = nullptr;
1804
for (const auto& TLS : junction->getNBNode()->getControllingTLS()) {
1805
if (TLS->getProgramID() == currentTLS) {
1806
tpl = TLS;
1807
}
1808
}
1809
// if template is empty, use first TLS
1810
if (tpl == nullptr) {
1811
tpl = *junction->getNBNode()->getControllingTLS().begin();
1812
}
1813
// create new logic
1814
NBTrafficLightLogic* newLogic = tpl->compute(OptionsCont::getOptions());
1815
// create new TLDef
1816
NBLoadedSUMOTLDef* newDef = new NBLoadedSUMOTLDef(*tpl, *newLogic);
1817
NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1818
newDef->setProgramID(tllCont.getNextProgramID(newDef->getID()));
1819
// remove new logic
1820
delete newLogic;
1821
// add it using GNEChange_TLS
1822
myTLSEditorParent->getViewNet()->getUndoList()->begin(GUIIcon::MODETLS, TLF("duplicate program '%' of traffic light '%'", tpl->getProgramID(), tpl->getID()));
1823
for (NBNode* node : newDef->getNodes()) {
1824
GNEJunction* j = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(node->getID());
1825
// not forcing insertion because we already ensured a new id and multiple junctions will attempt insertion
1826
myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(j, newDef, true, false), true);
1827
}
1828
myTLSEditorParent->getViewNet()->getUndoList()->end();
1829
} else {
1830
// for some reason the traffic light was not built, try again
1831
myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, nullptr, true, true), true);
1832
}
1833
}
1834
1835
1836
bool
1837
GNETLSEditorFrame::TLSPrograms::switchProgram() {
1838
if (myTLSEditorParent->myTLSJunction->getCurrentJunction() == nullptr) {
1839
throw ProcessError("Junction cannot be NULL");
1840
} else {
1841
// reset save flag
1842
myHaveModifications = false;
1843
// get current definition
1844
NBTrafficLightDefinition* tlDef = getCurrentTLSPrograms();
1845
// logic may not have been recomputed yet. recompute to be sure
1846
NBTrafficLightLogicCont& tllCont = myTLSEditorParent->getViewNet()->getNet()->getTLLogicCont();
1847
// compute junction
1848
myTLSEditorParent->getViewNet()->getNet()->computeJunction(myTLSEditorParent->myTLSJunction->getCurrentJunction());
1849
// obtain TrafficLight logic vinculated with tlDef
1850
NBTrafficLightLogic* tllogic = tllCont.getLogic(tlDef->getID(), tlDef->getProgramID());
1851
// check that tllLogic exist
1852
if (tllogic != nullptr) {
1853
// now we can be sure that the tlDef is up to date (i.e. re-guessed)
1854
myTLSEditorParent->buildInternalLanes(tlDef);
1855
// create working duplicate from original def
1856
delete myTLSEditorParent->myEditedDef;
1857
myTLSEditorParent->myEditedDef = new NBLoadedSUMOTLDef(*tlDef, *tllogic);
1858
// set values
1859
myTLSEditorParent->myTLSAttributes->setOffset(myTLSEditorParent->myEditedDef->getLogic()->getOffset());
1860
myTLSEditorParent->myTLSAttributes->setParameters(myTLSEditorParent->myEditedDef->getLogic()->getParametersStr());
1861
// init phaseTable with the new TLS
1862
myTLSEditorParent->myTLSPhases->initPhaseTable();
1863
} else {
1864
// tlDef has no valid logic (probably because id does not control any links
1865
discardChanges(false);
1866
myTLSEditorParent->getViewNet()->setStatusBarText(TL("Traffic Light does not control any links"));
1867
return false;
1868
}
1869
}
1870
return true;
1871
}
1872
1873
// ---------------------------------------------------------------------------
1874
// GNETLSEditorFrame::TLSPhases - methods
1875
// ---------------------------------------------------------------------------
1876
1877
GNETLSEditorFrame::TLSPhases::TLSPhases(GNETLSEditorFrame* TLSEditorParent) :
1878
GNEGroupBoxModule(TLSEditorParent, TL("Phases"), GNEGroupBoxModule::Options::COLLAPSIBLE | GNEGroupBoxModule::Options::EXTENSIBLE),
1879
myTLSEditorParent(TLSEditorParent) {
1880
// create GNETLSTable
1881
myPhaseTable = new GNETLSTable(this);
1882
// hide phase table
1883
myPhaseTable->hide();
1884
FXHorizontalFrame* phaseButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrameUniform);
1885
FXVerticalFrame* col1 = new FXVerticalFrame(phaseButtons, GUIDesignAuxiliarHorizontalFrame); // left button columm
1886
FXVerticalFrame* col2 = new FXVerticalFrame(phaseButtons, GUIDesignAuxiliarHorizontalFrame); // right button column
1887
// create cleanup states button
1888
myCleanStatesButton = new MFXButtonTooltip(col1, TLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
1889
TL("Clean States") + std::string("\t") +
1890
TL("Clean unused states from all phase") + std::string("\t") +
1891
TL("Clean unused states from all phase. (Not allowed for multiple programs)"),
1892
nullptr, this, MID_GNE_TLSFRAME_PHASES_CLEANUP, GUIDesignButton);
1893
myCleanStatesButton->disable();
1894
// add unused states button
1895
myAddStates = new MFXButtonTooltip(col2, TLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
1896
TL("Add States") + std::string("\t") +
1897
TL("Extend the state vector for all phases by one entry") + std::string("\t") +
1898
TL("Extend the state vector for all phases by one entry. (Unused until a connection or crossing is assigned to the new index)"),
1899
nullptr, this, MID_GNE_TLSFRAME_PHASES_ADDUNUSED, GUIDesignButton);
1900
myAddStates->disable();
1901
// group states button
1902
myGroupSignalsButton = new MFXButtonTooltip(col1, TLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
1903
TL("Group Sig.") + std::string("\t") +
1904
TL("Shorten state definition by letting connections with the same signal states use the same index") + std::string("\t") +
1905
TL("Shorten state definition by letting connections with the same signal states use the same index. (Not allowed for multiple programs)"),
1906
nullptr, this, MID_GNE_TLSFRAME_PHASES_GROUPSTATES, GUIDesignButton);
1907
myGroupSignalsButton->disable();
1908
// ungroup states button
1909
myUngroupSignalsButton = new MFXButtonTooltip(col2, TLSEditorParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
1910
TL("Ungroup Sig.") + std::string("\t") +
1911
TL("Let every connection use a distinct index (reverse state grouping)") + std::string("\t") +
1912
TL("Let every connection use a distinct index (reverse state grouping). (Not allowed for multiple programs)"),
1913
nullptr, this, MID_GNE_TLSFRAME_PHASES_UNGROUPSTATES, GUIDesignButton);
1914
myUngroupSignalsButton->disable();
1915
// show TLSFile
1916
show();
1917
}
1918
1919
1920
GNETLSEditorFrame::TLSPhases::~TLSPhases() {
1921
}
1922
1923
1924
void
1925
GNETLSEditorFrame::TLSPhases::updateTLSPhases() {
1926
if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
1927
// selecting E1, disable buttons
1928
myPhaseTable->disable();
1929
myCleanStatesButton->disable();
1930
myAddStates->disable();
1931
myGroupSignalsButton->disable();
1932
myUngroupSignalsButton->disable();
1933
} else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
1934
// joining TLSs, disable buttons
1935
myPhaseTable->disable();
1936
myCleanStatesButton->disable();
1937
myAddStates->disable();
1938
myGroupSignalsButton->disable();
1939
myUngroupSignalsButton->disable();
1940
myUngroupSignalsButton->disable();
1941
} else if (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() == 0) {
1942
// no TLSs, disable buttons
1943
myPhaseTable->disable();
1944
myCleanStatesButton->disable();
1945
myAddStates->disable();
1946
myGroupSignalsButton->disable();
1947
myUngroupSignalsButton->disable();
1948
} else if (myTLSEditorParent->myEditedDef == nullptr) {
1949
// no edited definition, disable buttons
1950
myPhaseTable->disable();
1951
myCleanStatesButton->disable();
1952
myAddStates->disable();
1953
myGroupSignalsButton->disable();
1954
myUngroupSignalsButton->disable();
1955
} else {
1956
myPhaseTable->enable();
1957
myCleanStatesButton->enable();
1958
myAddStates->enable();
1959
myGroupSignalsButton->enable();
1960
if (myTLSEditorParent->myEditedDef->usingSignalGroups()) {
1961
myUngroupSignalsButton->enable();
1962
} else {
1963
myUngroupSignalsButton->disable();
1964
}
1965
}
1966
}
1967
1968
1969
void
1970
GNETLSEditorFrame::TLSPhases::showTLSPhases() {
1971
show();
1972
}
1973
1974
1975
void
1976
GNETLSEditorFrame::TLSPhases::hideTLSPhases() {
1977
hide();
1978
}
1979
1980
1981
GNETLSEditorFrame*
1982
GNETLSEditorFrame::TLSPhases::getTLSEditorParent() const {
1983
return myTLSEditorParent;
1984
}
1985
1986
1987
GNETLSTable*
1988
GNETLSEditorFrame::TLSPhases::getPhaseTable() const {
1989
return myPhaseTable;
1990
}
1991
1992
1993
void
1994
GNETLSEditorFrame::TLSPhases::initPhaseTable() {
1995
// first clear table
1996
clearPhaseTable();
1997
if (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() > 0) {
1998
if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC) {
1999
initStaticPhaseTable();
2000
} else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::ACTUATED) {
2001
initActuatedPhaseTable();
2002
} else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::DELAYBASED) {
2003
initDelayBasePhaseTable();
2004
} else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA) {
2005
initNEMAPhaseTable();
2006
}
2007
// select first element (by default)
2008
myPhaseTable->selectRow(0);
2009
// recalc width and show
2010
myPhaseTable->recalcTableWidth();
2011
myPhaseTable->show();
2012
} else {
2013
myPhaseTable->hide();
2014
}
2015
update();
2016
}
2017
2018
2019
void
2020
GNETLSEditorFrame::TLSPhases::clearPhaseTable() {
2021
myPhaseTable->clearTable();
2022
}
2023
2024
2025
bool
2026
GNETLSEditorFrame::TLSPhases::changePhaseValue(const int col, const int row, const std::string& value) {
2027
// Declare columns
2028
int colDuration = 1;
2029
int colState = -1;
2030
int colNext = -1;
2031
int colName = -1;
2032
int colMinDur = -1;
2033
int colMaxDur = -1;
2034
int colEarliestEnd = -1;
2035
int colLatestEnd = -1;
2036
int colVehExt = -1;
2037
int colYellow = -1;
2038
int colRed = -1;
2039
// set columns depending of traffic light type
2040
if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC) {
2041
colState = 2;
2042
colNext = 3;
2043
colName = 4;
2044
} else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::ACTUATED) {
2045
colMinDur = 2;
2046
colMaxDur = 3;
2047
colState = 4;
2048
colEarliestEnd = 5;
2049
colLatestEnd = 6;
2050
colNext = 7;
2051
colName = 8;
2052
} else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::DELAYBASED) {
2053
colMinDur = 2;
2054
colMaxDur = 3;
2055
colState = 4;
2056
colNext = 5;
2057
colName = 6;
2058
} else if (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA) {
2059
colMinDur = 2;
2060
colMaxDur = 3;
2061
colState = 4;
2062
colVehExt = 5;
2063
colYellow = 6;
2064
colRed = 7;
2065
colNext = 8;
2066
colName = 9;
2067
}
2068
// check column
2069
if (col == colDuration) {
2070
return setDuration(col, row, value);
2071
} else if (col == colState) {
2072
return setState(col, row, value);
2073
} else if (col == colNext) {
2074
return setNext(row, value);
2075
} else if (col == colName) {
2076
return setName(row, value);
2077
} else if (col == colMinDur) {
2078
return setMinDur(row, value);
2079
} else if (col == colMaxDur) {
2080
return setMaxDur(row, value);
2081
} else if (col == colEarliestEnd) {
2082
return setEarliestEnd(row, value);
2083
} else if (col == colLatestEnd) {
2084
return setLatestEnd(row, value);
2085
} else if (col == colVehExt) {
2086
return setVehExt(row, value);
2087
} else if (col == colYellow) {
2088
return setYellow(row, value);
2089
} else if (col == colRed) {
2090
return setRed(row, value);
2091
} else {
2092
throw ProcessError(TL("invalid column"));
2093
}
2094
}
2095
2096
2097
void
2098
GNETLSEditorFrame::TLSPhases::addPhase(const int row, const char c) {
2099
// mark TLS as modified
2100
myTLSEditorParent->myTLSPrograms->markAsModified();
2101
// build default phase
2102
const int newIndex = buildDefaultPhase(row);
2103
// check if override state
2104
switch (c) {
2105
case 'r':
2106
case 'y':
2107
case 'g':
2108
case 'G':
2109
myTLSEditorParent->myEditedDef->getLogic()->overrideState(newIndex, c);
2110
break;
2111
default:
2112
break;
2113
}
2114
// int phase table again
2115
initPhaseTable();
2116
// mark new row as selected
2117
myPhaseTable->selectRow(newIndex);
2118
// set focus in table
2119
getPhaseTable()->setFocus();
2120
}
2121
2122
2123
void
2124
GNETLSEditorFrame::TLSPhases::duplicatePhase(const int row) {
2125
// mark TLS as modified
2126
myTLSEditorParent->myTLSPrograms->markAsModified();
2127
// build default phase
2128
const int newIndex = buildDefaultPhase(row);
2129
// coply old phase in the new phase
2130
myTLSEditorParent->myEditedDef->getLogic()->copyPhase(row, row + 1);
2131
// int phase table again
2132
initPhaseTable();
2133
// mark new row as selected
2134
myPhaseTable->selectRow(newIndex);
2135
// set focus in table
2136
getPhaseTable()->setFocus();
2137
}
2138
2139
2140
void
2141
GNETLSEditorFrame::TLSPhases::removePhase(const int row) {
2142
// mark TLS ad modified
2143
myTLSEditorParent->myTLSPrograms->markAsModified();
2144
// calculate new row
2145
const auto newRow = MAX2(0, (row - 1));
2146
// delete selected row
2147
myTLSEditorParent->myEditedDef->getLogic()->deletePhase(row);
2148
// int phase table again
2149
initPhaseTable();
2150
// mark new row as selected
2151
myPhaseTable->selectRow(newRow);
2152
// set focus in table
2153
getPhaseTable()->setFocus();
2154
}
2155
2156
2157
void
2158
GNETLSEditorFrame::TLSPhases::movePhaseUp(const int row) {
2159
// mark TLS ad modified
2160
myTLSEditorParent->myTLSPrograms->markAsModified();
2161
// delete selected row
2162
if (row == 0) {
2163
myTLSEditorParent->myEditedDef->getLogic()->swapfirstPhase();
2164
} else {
2165
myTLSEditorParent->myEditedDef->getLogic()->swapPhase(row, row - 1);
2166
}
2167
// int phase table again
2168
initPhaseTable();
2169
// mark new row as selected
2170
if (row == 0) {
2171
myPhaseTable->selectRow((int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1);
2172
} else {
2173
myPhaseTable->selectRow(row - 1);
2174
}
2175
// set focus in table
2176
getPhaseTable()->setFocus();
2177
}
2178
2179
2180
void
2181
GNETLSEditorFrame::TLSPhases::movePhaseDown(const int row) {
2182
// mark TLS ad modified
2183
myTLSEditorParent->myTLSPrograms->markAsModified();
2184
// delete selected row
2185
if (row == (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1) {
2186
myTLSEditorParent->myEditedDef->getLogic()->swaplastPhase();
2187
} else {
2188
myTLSEditorParent->myEditedDef->getLogic()->swapPhase(row, row + 1);
2189
}
2190
// int phase table again
2191
initPhaseTable();
2192
// mark new row as selected
2193
if (row == (int)myTLSEditorParent->myEditedDef->getLogic()->getPhases().size() - 1) {
2194
myPhaseTable->selectRow(0);
2195
} else {
2196
myPhaseTable->selectRow(row + 1);
2197
}
2198
// set focus in table
2199
getPhaseTable()->setFocus();
2200
}
2201
2202
2203
void
2204
GNETLSEditorFrame::TLSPhases::updateTLSColoring() {
2205
// get phase
2206
const auto& phase = myTLSEditorParent->getPhase(myPhaseTable->getCurrentSelectedRow());
2207
// need not hold since links could have been deleted somewhere else and indices may be reused
2208
for (const auto& internalLane : myTLSEditorParent->myInternalLanes) {
2209
int tlIndex = internalLane.first;
2210
std::vector<GNEInternalLane*> lanes = internalLane.second;
2211
LinkState state = LINKSTATE_DEADEND;
2212
if (tlIndex >= 0 && tlIndex < (int)phase.state.size()) {
2213
state = (LinkState)phase.state[tlIndex];
2214
}
2215
for (const auto& lane : lanes) {
2216
lane->setLinkState(state);
2217
}
2218
}
2219
// update view net (for coloring)
2220
myTLSEditorParent->getViewNet()->updateViewNet();
2221
}
2222
2223
2224
long
2225
GNETLSEditorFrame::TLSPhases::onCmdCleanStates(FXObject*, FXSelector, void*) {
2226
if (myTLSEditorParent->myEditedDef->cleanupStates()) {
2227
myTLSEditorParent->myTLSPrograms->markAsModified();
2228
}
2229
myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2230
initPhaseTable();
2231
myPhaseTable->setFocus();
2232
myTLSEditorParent->myTLSPrograms->markAsModified();
2233
myTLSEditorParent->updateModules();
2234
return 1;
2235
}
2236
2237
2238
long
2239
GNETLSEditorFrame::TLSPhases::onCmdAddUnusedStates(FXObject*, FXSelector, void*) {
2240
myTLSEditorParent->myEditedDef->getLogic()->setStateLength(myTLSEditorParent->myEditedDef->getLogic()->getNumLinks() + 1);
2241
myTLSEditorParent->myTLSPrograms->markAsModified();
2242
initPhaseTable();
2243
myPhaseTable->setFocus();
2244
myTLSEditorParent->updateModules();
2245
return 1;
2246
}
2247
2248
2249
long
2250
GNETLSEditorFrame::TLSPhases::onCmdGroupStates(FXObject*, FXSelector, void*) {
2251
myTLSEditorParent->myEditedDef->groupSignals();
2252
myTLSEditorParent->myTLSPrograms->markAsModified();
2253
myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2254
initPhaseTable();
2255
myPhaseTable->setFocus();
2256
myTLSEditorParent->updateModules();
2257
return 1;
2258
}
2259
2260
2261
long
2262
GNETLSEditorFrame::TLSPhases::onCmdUngroupStates(FXObject*, FXSelector, void*) {
2263
myTLSEditorParent->myEditedDef->setParticipantsInformation();
2264
myTLSEditorParent->myEditedDef->ungroupSignals();
2265
myTLSEditorParent->myTLSPrograms->markAsModified();
2266
myTLSEditorParent->buildInternalLanes(myTLSEditorParent->myEditedDef);
2267
initPhaseTable();
2268
myPhaseTable->setFocus();
2269
myTLSEditorParent->updateModules();
2270
return 1;
2271
}
2272
2273
2274
void
2275
GNETLSEditorFrame::TLSPhases::initStaticPhaseTable() {
2276
// declare constants for columns
2277
const int colDuration = 1;
2278
const int colState = 2;
2279
const int colNext = 3;
2280
const int colName = 4;
2281
// get phases
2282
const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2283
// adjust table
2284
myPhaseTable->setTableSize("sup-midtb", (int)phases.size());
2285
// fill rows
2286
for (int row = 0; row < (int)phases.size(); row++) {
2287
myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2288
myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2289
myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2290
myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2291
}
2292
// set columns
2293
myPhaseTable->setColumnLabelTop(colDuration, "dur");
2294
myPhaseTable->setColumnLabelTop(colState, "state");
2295
myPhaseTable->setColumnLabelTop(colNext, "next");
2296
myPhaseTable->setColumnLabelTop(colName, "name");
2297
// set bot labels
2298
updateCycleDuration(colDuration);
2299
updateStateSize(colState);
2300
// set focus
2301
myPhaseTable->setFocus();
2302
}
2303
2304
2305
void
2306
GNETLSEditorFrame::TLSPhases::initActuatedPhaseTable() {
2307
// declare constants for columns
2308
const int colDuration = 1;
2309
const int colMinDur = 2;
2310
const int colMaxDur = 3;
2311
const int colState = 4;
2312
const int colEarliestEnd = 5;
2313
const int colLatestEnd = 6;
2314
const int colNext = 7;
2315
const int colName = 8;
2316
// get phases
2317
const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2318
// adjust table
2319
myPhaseTable->setTableSize("suffpff-midtb", (int)phases.size());
2320
// fill rows
2321
for (int row = 0; row < (int)phases.size(); row++) {
2322
myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2323
myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2324
myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2325
myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2326
myPhaseTable->setItemText(row, colEarliestEnd, varDurString(phases.at(row).earliestEnd).c_str());
2327
myPhaseTable->setItemText(row, colLatestEnd, varDurString(phases.at(row).latestEnd).c_str());
2328
myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2329
myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2330
}
2331
// set columns
2332
myPhaseTable->setColumnLabelTop(colDuration, "dur");
2333
myPhaseTable->setColumnLabelTop(colMinDur, "min");
2334
myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2335
myPhaseTable->setColumnLabelTop(colEarliestEnd, "ear.end", "earlyEnd");
2336
myPhaseTable->setColumnLabelTop(colLatestEnd, "lat.end", "latestEnd");
2337
myPhaseTable->setColumnLabelTop(colState, "state");
2338
myPhaseTable->setColumnLabelTop(colNext, "next");
2339
myPhaseTable->setColumnLabelTop(colName, "name");
2340
// set bot labels
2341
updateCycleDuration(colDuration);
2342
updateStateSize(colState);
2343
// set focus
2344
myPhaseTable->setFocus();
2345
}
2346
2347
2348
void
2349
GNETLSEditorFrame::TLSPhases::initDelayBasePhaseTable() {
2350
// declare constants for columns
2351
const int colDuration = 1;
2352
const int colMinDur = 2;
2353
const int colMaxDur = 3;
2354
const int colState = 4;
2355
const int colNext = 5;
2356
const int colName = 6;
2357
// get phases
2358
const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2359
// adjust table
2360
myPhaseTable->setTableSize("suffp-midtb", (int)phases.size());
2361
// fill rows
2362
for (int row = 0; row < (int)phases.size(); row++) {
2363
myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2364
myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2365
myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2366
myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2367
myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2368
myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2369
}
2370
// set columns
2371
myPhaseTable->setColumnLabelTop(colDuration, "dur");
2372
myPhaseTable->setColumnLabelTop(colMinDur, "min");
2373
myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2374
myPhaseTable->setColumnLabelTop(colState, "state");
2375
myPhaseTable->setColumnLabelTop(colNext, "next");
2376
myPhaseTable->setColumnLabelTop(colName, "name");
2377
// set bot labels
2378
updateCycleDuration(colDuration);
2379
updateStateSize(colState);
2380
// set focus
2381
myPhaseTable->setFocus();
2382
}
2383
2384
2385
void
2386
GNETLSEditorFrame::TLSPhases::initNEMAPhaseTable() {
2387
// declare constants for columns
2388
const int colDuration = 1;
2389
const int colMinDur = 2;
2390
const int colMaxDur = 3;
2391
const int colState = 4;
2392
const int colVehExt = 5;
2393
const int colYellow = 6;
2394
const int colRed = 7;
2395
const int colNext = 8;
2396
const int colName = 9;
2397
// get phases
2398
const auto& phases = myTLSEditorParent->myEditedDef->getLogic()->getPhases();
2399
// adjust table
2400
myPhaseTable->setTableSize("suffpfff-midtb", (int)phases.size());
2401
// fill rows
2402
for (int row = 0; row < (int)phases.size(); row++) {
2403
myPhaseTable->setItemText(row, colDuration, getSteps2Time(phases.at(row).duration).c_str());
2404
myPhaseTable->setItemText(row, colMinDur, varDurString(phases.at(row).minDur).c_str());
2405
myPhaseTable->setItemText(row, colMaxDur, varDurString(phases.at(row).maxDur).c_str());
2406
myPhaseTable->setItemText(row, colState, phases.at(row).state.c_str());
2407
myPhaseTable->setItemText(row, colVehExt, varDurString(phases.at(row).vehExt).c_str());
2408
myPhaseTable->setItemText(row, colYellow, varDurString(phases.at(row).yellow).c_str());
2409
myPhaseTable->setItemText(row, colRed, varDurString(phases.at(row).red).c_str());
2410
myPhaseTable->setItemText(row, colNext, phases.at(row).next.size() > 0 ? toString(phases.at(row).next).c_str() : "");
2411
myPhaseTable->setItemText(row, colName, phases.at(row).name.c_str());
2412
}
2413
// set columns
2414
myPhaseTable->setColumnLabelTop(colDuration, "dur");
2415
myPhaseTable->setColumnLabelTop(colMinDur, "min");
2416
myPhaseTable->setColumnLabelTop(colMaxDur, "max");
2417
myPhaseTable->setColumnLabelTop(colState, "state");
2418
myPhaseTable->setColumnLabelTop(colVehExt, "vehExt", "vehicle extension");
2419
myPhaseTable->setColumnLabelTop(colYellow, "yellow");
2420
myPhaseTable->setColumnLabelTop(colRed, "red");
2421
myPhaseTable->setColumnLabelTop(colNext, "next");
2422
myPhaseTable->setColumnLabelTop(colName, "name");
2423
// set bot labels
2424
updateCycleDuration(colDuration);
2425
updateStateSize(colState);
2426
// set focus
2427
myPhaseTable->setFocus();
2428
}
2429
2430
2431
int
2432
GNETLSEditorFrame::TLSPhases::buildDefaultPhase(const int row) {
2433
// get option container
2434
const auto& neteditOptions = OptionsCont::getOptions();
2435
// check if TLS is static
2436
const bool TLSStatic = (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::STATIC);
2437
const bool NEMA = (myTLSEditorParent->myEditedDef->getType() == TrafficLightType::NEMA);
2438
// calculate new index
2439
const int newIndex = row + 1;
2440
// duplicate current row
2441
auto duration = getSUMOTime(myPhaseTable->getItemText(row, 1));
2442
const auto oldState = myPhaseTable->getItemText(row, TLSStatic ? 2 : 4);
2443
auto state = oldState;
2444
// update crossingINdices
2445
std::set<int> crossingIndices;
2446
for (const auto& node : myTLSEditorParent->myEditedDef->getNodes()) {
2447
for (const auto& crossing : node->getCrossings()) {
2448
crossingIndices.insert(crossing->tlLinkIndex);
2449
crossingIndices.insert(crossing->tlLinkIndex2);
2450
}
2451
}
2452
// smart adapations for new state
2453
bool haveGreen = false;
2454
bool haveYellow = false;
2455
for (const auto& linkStateChar : state) {
2456
if ((linkStateChar == LINKSTATE_TL_GREEN_MAJOR) || (linkStateChar == LINKSTATE_TL_GREEN_MINOR)) {
2457
haveGreen = true;
2458
} else if ((linkStateChar == LINKSTATE_TL_YELLOW_MAJOR) || (linkStateChar == LINKSTATE_TL_YELLOW_MINOR)) {
2459
haveYellow = true;
2460
}
2461
}
2462
if (haveGreen && haveYellow) {
2463
// guess left-mover state
2464
duration = TIME2STEPS(neteditOptions.getInt("tls.left-green.time"));
2465
for (int i = 0; i < (int)state.size(); i++) {
2466
if ((state[i] == LINKSTATE_TL_YELLOW_MAJOR) || (state[i] == LINKSTATE_TL_YELLOW_MINOR)) {
2467
state[i] = LINKSTATE_TL_RED;
2468
} else if (state[i] == LINKSTATE_TL_GREEN_MINOR) {
2469
state[i] = LINKSTATE_TL_GREEN_MAJOR;
2470
}
2471
}
2472
} else if (haveGreen) {
2473
// guess yellow state
2474
myTLSEditorParent->myEditedDef->setParticipantsInformation();
2475
duration = TIME2STEPS(myTLSEditorParent->myEditedDef->computeBrakingTime(neteditOptions.getFloat("tls.yellow.min-decel")));
2476
for (int i = 0; i < (int)state.size(); i++) {
2477
if ((state[i] == LINKSTATE_TL_GREEN_MAJOR) || (state[i] == LINKSTATE_TL_GREEN_MINOR)) {
2478
if (crossingIndices.count(i) == 0) {
2479
state[i] = LINKSTATE_TL_YELLOW_MINOR;
2480
} else {
2481
state[i] = LINKSTATE_TL_RED;
2482
}
2483
}
2484
}
2485
} else if (haveYellow) {
2486
duration = TIME2STEPS(neteditOptions.isDefault("tls.allred.time") ? 2 : neteditOptions.getInt("tls.allred.time"));
2487
// guess all-red state
2488
for (int i = 0; i < (int)state.size(); i++) {
2489
if ((state[i] == LINKSTATE_TL_YELLOW_MAJOR) || (state[i] == LINKSTATE_TL_YELLOW_MINOR)) {
2490
state[i] = LINKSTATE_TL_RED;
2491
}
2492
}
2493
}
2494
// fix continuous green states
2495
const int nextIndex = (myPhaseTable->getNumRows() > newIndex) ? newIndex : 0;
2496
const std::string state2 = myPhaseTable->getItemText(nextIndex, (TLSStatic ? 2 : 4));
2497
for (int i = 0; i < (int)state.size(); i++) {
2498
if (((oldState[i] == LINKSTATE_TL_GREEN_MAJOR) || (oldState[i] == LINKSTATE_TL_GREEN_MINOR)) &&
2499
((state2[i] == LINKSTATE_TL_GREEN_MAJOR) || (state2[i] == LINKSTATE_TL_GREEN_MINOR))) {
2500
state[i] = oldState[i];
2501
}
2502
}
2503
// add new step
2504
if (NEMA) {
2505
myTLSEditorParent->myEditedDef->getLogic()->addStep(string2time("90"), state, string2time("5"), string2time("50"),
2506
NBTrafficLightDefinition::UNSPECIFIED_DURATION, NBTrafficLightDefinition::UNSPECIFIED_DURATION,
2507
string2time("2"), string2time("3"), string2time("2"), "1", std::vector<int>(), newIndex);
2508
} else {
2509
myTLSEditorParent->myEditedDef->getLogic()->addStep(duration, state, std::vector<int>(), "", newIndex);
2510
}
2511
// return new index
2512
return newIndex;
2513
}
2514
2515
2516
bool
2517
GNETLSEditorFrame::TLSPhases::setDuration(const int col, const int row, const std::string& value) {
2518
// check value
2519
if (value.empty()) {
2520
// input empty, reset
2521
getPhaseTable()->setItemText(row, col, getSteps2Time(myTLSEditorParent->getPhase(row).duration).c_str());
2522
return true;
2523
} else if (GNEAttributeCarrier::canParse<double>(value)) {
2524
const auto duration = getSUMOTime(value);
2525
// check that duration > 0
2526
if (duration > 0) {
2527
myTLSEditorParent->myEditedDef->getLogic()->setPhaseDuration(row, duration);
2528
myTLSEditorParent->myTLSPrograms->markAsModified();
2529
// update Cycle duration
2530
updateCycleDuration(col);
2531
return true;
2532
} else {
2533
return false;
2534
}
2535
} else {
2536
return false;
2537
}
2538
}
2539
2540
2541
bool
2542
GNETLSEditorFrame::TLSPhases::setState(const int col, const int row, const std::string& value) {
2543
// get state
2544
const auto& phase = myTLSEditorParent->getPhase(row);
2545
// declare new state. If value is empty, use previous value (reset)
2546
const auto newState = value.empty() ? phase.state : value;
2547
// insert phase
2548
try {
2549
myTLSEditorParent->myEditedDef->getLogic()->addStep(phase.duration, newState, phase.next, phase.name, row);
2550
} catch (ProcessError&) {
2551
// invalid character in newState
2552
return false;
2553
}
2554
// delete next phase
2555
try {
2556
myTLSEditorParent->myEditedDef->getLogic()->deletePhase(row + 1);
2557
} catch (InvalidArgument&) {
2558
WRITE_ERROR(TL("Error deleting phase '") + toString(row + 1) + "'");
2559
return false;
2560
}
2561
// mark TLS as modified depending of value
2562
if (value.size() > 0) {
2563
myTLSEditorParent->myTLSPrograms->markAsModified();
2564
// select row
2565
myPhaseTable->selectRow(row);
2566
} else {
2567
// input empty, reset
2568
getPhaseTable()->setItemText(row, col, newState);
2569
}
2570
// update state size
2571
updateStateSize(col);
2572
return true;
2573
}
2574
2575
2576
bool
2577
GNETLSEditorFrame::TLSPhases::setNext(const int row, const std::string& value) {
2578
// check next
2579
if (GNEAttributeCarrier::canParse<std::vector<int> >(value)) {
2580
const auto nextEdited = GNEAttributeCarrier::parse<std::vector<int> >(value);
2581
for (const auto nextPhase : nextEdited) {
2582
if ((nextPhase < 0) || (nextPhase >= myPhaseTable->getNumRows())) {
2583
return false;
2584
}
2585
}
2586
// set new next
2587
myTLSEditorParent->myEditedDef->getLogic()->setPhaseNext(row, nextEdited);
2588
myTLSEditorParent->myTLSPrograms->markAsModified();
2589
return true;
2590
} else {
2591
return false;
2592
}
2593
}
2594
2595
2596
bool
2597
GNETLSEditorFrame::TLSPhases::setName(const int row, const std::string& value) {
2598
// update name (currently no check needed)
2599
myTLSEditorParent->myEditedDef->getLogic()->setPhaseName(row, value);
2600
myTLSEditorParent->myTLSPrograms->markAsModified();
2601
return true;
2602
}
2603
2604
2605
bool
2606
GNETLSEditorFrame::TLSPhases::setMinDur(const int row, const std::string& value) {
2607
// check value
2608
if (value.empty()) {
2609
// set empty value
2610
myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2611
myTLSEditorParent->myTLSPrograms->markAsModified();
2612
return true;
2613
} else if (GNEAttributeCarrier::canParse<double>(value)) {
2614
const auto minDur = getSUMOTime(value);
2615
// check that minDur > 0
2616
if (minDur > 0) {
2617
myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, minDur);
2618
myTLSEditorParent->myTLSPrograms->markAsModified();
2619
return true;
2620
} else {
2621
return false;
2622
}
2623
} else if (StringUtils::prune(value).empty()) {
2624
myTLSEditorParent->myEditedDef->getLogic()->setPhaseMinDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2625
myTLSEditorParent->myTLSPrograms->markAsModified();
2626
return true;
2627
} else {
2628
return false;
2629
}
2630
}
2631
2632
2633
bool
2634
GNETLSEditorFrame::TLSPhases::setMaxDur(const int row, const std::string& value) {
2635
// check value
2636
if (value.empty()) {
2637
// set empty value
2638
myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2639
myTLSEditorParent->myTLSPrograms->markAsModified();
2640
return true;
2641
} else if (GNEAttributeCarrier::canParse<double>(value)) {
2642
const auto maxDur = getSUMOTime(value);
2643
// check that minDur > 0
2644
if (maxDur > 0) {
2645
myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, maxDur);
2646
myTLSEditorParent->myTLSPrograms->markAsModified();
2647
return true;
2648
} else {
2649
return false;
2650
}
2651
} else if (StringUtils::prune(value).empty()) {
2652
myTLSEditorParent->myEditedDef->getLogic()->setPhaseMaxDuration(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2653
myTLSEditorParent->myTLSPrograms->markAsModified();
2654
return true;
2655
} else {
2656
return false;
2657
}
2658
}
2659
2660
2661
bool
2662
GNETLSEditorFrame::TLSPhases::setEarliestEnd(const int row, const std::string& value) {
2663
// check value
2664
if (value.empty()) {
2665
// set empty value
2666
myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2667
myTLSEditorParent->myTLSPrograms->markAsModified();
2668
return true;
2669
} else if (GNEAttributeCarrier::canParse<double>(value)) {
2670
const auto earliestEnd = getSUMOTime(value);
2671
// check that earliestEnd > 0
2672
if (earliestEnd > 0) {
2673
myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, earliestEnd);
2674
myTLSEditorParent->myTLSPrograms->markAsModified();
2675
return true;
2676
} else {
2677
return false;
2678
}
2679
} else if (StringUtils::prune(value).empty()) {
2680
myTLSEditorParent->myEditedDef->getLogic()->setPhaseEarliestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2681
myTLSEditorParent->myTLSPrograms->markAsModified();
2682
return true;
2683
} else {
2684
return false;
2685
}
2686
}
2687
2688
2689
bool
2690
GNETLSEditorFrame::TLSPhases::setLatestEnd(const int row, const std::string& value) {
2691
// check value
2692
if (value.empty()) {
2693
// set empty value
2694
myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2695
myTLSEditorParent->myTLSPrograms->markAsModified();
2696
return true;
2697
} else if (GNEAttributeCarrier::canParse<double>(value)) {
2698
const auto latestEnd = getSUMOTime(value);
2699
// check that latestEnd > 0
2700
if (latestEnd > 0) {
2701
myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, latestEnd);
2702
myTLSEditorParent->myTLSPrograms->markAsModified();
2703
return true;
2704
} else {
2705
return false;
2706
}
2707
} else if (StringUtils::prune(value).empty()) {
2708
myTLSEditorParent->myEditedDef->getLogic()->setPhaseLatestEnd(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2709
myTLSEditorParent->myTLSPrograms->markAsModified();
2710
return true;
2711
} else {
2712
return false;
2713
}
2714
}
2715
2716
2717
bool
2718
GNETLSEditorFrame::TLSPhases::setVehExt(const int row, const std::string& value) {
2719
// check value
2720
if (value.empty()) {
2721
// set empty value
2722
myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2723
myTLSEditorParent->myTLSPrograms->markAsModified();
2724
return true;
2725
} else if (GNEAttributeCarrier::canParse<double>(value)) {
2726
const auto vehExt = getSUMOTime(value);
2727
// check that vehExt > 0
2728
if (vehExt > 0) {
2729
myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, vehExt);
2730
myTLSEditorParent->myTLSPrograms->markAsModified();
2731
return true;
2732
} else {
2733
return false;
2734
}
2735
} else if (StringUtils::prune(value).empty()) {
2736
myTLSEditorParent->myEditedDef->getLogic()->setPhaseVehExt(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2737
myTLSEditorParent->myTLSPrograms->markAsModified();
2738
return true;
2739
} else {
2740
return false;
2741
}
2742
}
2743
2744
2745
bool
2746
GNETLSEditorFrame::TLSPhases::setYellow(const int row, const std::string& value) {
2747
// check value
2748
if (value.empty()) {
2749
// set empty value
2750
myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2751
myTLSEditorParent->myTLSPrograms->markAsModified();
2752
return true;
2753
} else if (GNEAttributeCarrier::canParse<double>(value)) {
2754
const auto yellow = getSUMOTime(value);
2755
// check that yellow > 0
2756
if (yellow > 0) {
2757
myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, yellow);
2758
myTLSEditorParent->myTLSPrograms->markAsModified();
2759
return true;
2760
} else {
2761
return false;
2762
}
2763
} else if (StringUtils::prune(value).empty()) {
2764
myTLSEditorParent->myEditedDef->getLogic()->setPhaseYellow(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2765
myTLSEditorParent->myTLSPrograms->markAsModified();
2766
return true;
2767
} else {
2768
return false;
2769
}
2770
}
2771
2772
2773
bool
2774
GNETLSEditorFrame::TLSPhases::setRed(const int row, const std::string& value) {
2775
// check value
2776
if (value.empty()) {
2777
// set empty value
2778
myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2779
myTLSEditorParent->myTLSPrograms->markAsModified();
2780
return true;
2781
} else if (GNEAttributeCarrier::canParse<double>(value)) {
2782
const auto red = getSUMOTime(value);
2783
// check that red > 0
2784
if (red > 0) {
2785
myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, red);
2786
myTLSEditorParent->myTLSPrograms->markAsModified();
2787
return true;
2788
} else {
2789
return false;
2790
}
2791
} else if (StringUtils::prune(value).empty()) {
2792
myTLSEditorParent->myEditedDef->getLogic()->setPhaseRed(row, NBTrafficLightDefinition::UNSPECIFIED_DURATION);
2793
myTLSEditorParent->myTLSPrograms->markAsModified();
2794
return true;
2795
} else {
2796
return false;
2797
}
2798
}
2799
2800
2801
void
2802
GNETLSEditorFrame::TLSPhases::updateCycleDuration(const int col) {
2803
SUMOTime cycleDuration = 0;
2804
for (const auto& phase : myTLSEditorParent->myEditedDef->getLogic()->getPhases()) {
2805
cycleDuration += phase.duration;
2806
}
2807
// update bot label with cycle duration
2808
myPhaseTable->setColumnLabelBot(col, getSteps2Time(cycleDuration));
2809
}
2810
2811
2812
void
2813
GNETLSEditorFrame::TLSPhases::updateStateSize(const int col) {
2814
// update bot label with number of links
2815
myPhaseTable->setColumnLabelBot(col, "Links: " + toString(myTLSEditorParent->myEditedDef->getLogic()->getNumLinks()));
2816
}
2817
2818
// ---------------------------------------------------------------------------
2819
// GNETLSEditorFrame::TLSFile - methods
2820
// ---------------------------------------------------------------------------
2821
2822
GNETLSEditorFrame::TLSFile::TLSFile(GNETLSEditorFrame* TLSEditorParent) :
2823
GNEGroupBoxModule(TLSEditorParent, TL("TLS Program File")),
2824
myTLSEditorParent(TLSEditorParent) {
2825
FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
2826
// create create tlDef button
2827
myLoadButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Load"), "", TL("Load TLS program from additional file"), GUIIconSubSys::getIcon(GUIIcon::OPEN), this, MID_GNE_TLSFRAME_FILE_LOADPROGRAM, GUIDesignButton);
2828
myLoadButton->disable();
2829
// create create tlDef button
2830
mySaveButton = GUIDesigns::buildFXButton(buttonsFrame, TL("Save"), "", TL("Save TLS program to additional file"), GUIIconSubSys::getIcon(GUIIcon::SAVE), this, MID_GNE_TLSFRAME_FILE_SAVEPROGRAM, GUIDesignButton);
2831
mySaveButton->disable();
2832
// show TLSFile
2833
show();
2834
}
2835
2836
2837
GNETLSEditorFrame::TLSFile::~TLSFile() {}
2838
2839
2840
void
2841
GNETLSEditorFrame::TLSFile::updateTLSFile() {
2842
if (myTLSEditorParent->myTLSPrograms->getNumberOfPrograms() == 0) {
2843
myLoadButton->disable();
2844
mySaveButton->disable();
2845
} else if (myTLSEditorParent->myTLSAttributes->isSetDetectorsToggleButtonEnabled()) {
2846
// selecting E1, disable buttons
2847
myLoadButton->disable();
2848
mySaveButton->disable();
2849
} else if (myTLSEditorParent->myTLSJunction->isJoiningJunctions()) {
2850
// joining TLSs, disable button
2851
myLoadButton->disable();
2852
mySaveButton->disable();
2853
} else {
2854
myLoadButton->enable();
2855
mySaveButton->enable();
2856
}
2857
}
2858
2859
2860
void
2861
GNETLSEditorFrame::TLSFile::showTLSFile() {
2862
show();
2863
}
2864
2865
2866
void
2867
GNETLSEditorFrame::TLSFile::hideTLSFile() {
2868
hide();
2869
}
2870
2871
2872
long
2873
GNETLSEditorFrame::TLSFile::onCmdLoadTLSProgram(FXObject*, FXSelector, void*) {
2874
FXFileDialog opendialog(getCollapsableFrame(), "Load TLS Program");
2875
opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::MODETLS));
2876
opendialog.setSelectMode(SELECTFILE_EXISTING);
2877
opendialog.setPatternList(SUMOXMLDefinitions::XMLFileExtensions.getMultilineString().c_str());
2878
if (gCurrentFolder.length() != 0) {
2879
opendialog.setDirectory(gCurrentFolder);
2880
}
2881
if (opendialog.execute()) {
2882
// run parser
2883
NBTrafficLightLogicCont tmpTLLCont;
2884
NIXMLTrafficLightsHandler tllHandler(tmpTLLCont, myTLSEditorParent->getViewNet()->getNet()->getEdgeCont(), true);
2885
tmpTLLCont.insert(myTLSEditorParent->myEditedDef);
2886
XMLSubSys::runParser(tllHandler, opendialog.getFilename().text());
2887
2888
NBLoadedSUMOTLDef* newDefSameProgram = nullptr;
2889
std::set<NBLoadedSUMOTLDef*> newDefsOtherProgram;
2890
for (auto item : tmpTLLCont.getPrograms(myTLSEditorParent->myEditedDef->getID())) {
2891
if (item.second != myTLSEditorParent->myEditedDef) {
2892
NBLoadedSUMOTLDef* sdef = dynamic_cast<NBLoadedSUMOTLDef*>(item.second);
2893
if (item.first == myTLSEditorParent->myEditedDef->getProgramID()) {
2894
newDefSameProgram = sdef;
2895
} else {
2896
newDefsOtherProgram.insert(sdef);
2897
}
2898
}
2899
}
2900
const int newPrograms = (int)newDefsOtherProgram.size();
2901
if (newPrograms > 0 || newDefSameProgram != nullptr) {
2902
std::vector<NBNode*> nodes = myTLSEditorParent->myEditedDef->getNodes();
2903
for (auto newProg : newDefsOtherProgram) {
2904
for (auto it_node : nodes) {
2905
GNEJunction* junction = myTLSEditorParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveJunction(it_node->getID());
2906
myTLSEditorParent->getViewNet()->getUndoList()->add(new GNEChange_TLS(junction, newProg, true), true);
2907
}
2908
}
2909
if (newPrograms > 0) {
2910
WRITE_MESSAGE(TL("Loaded ") + toString(newPrograms) + TL(" new programs for tlLogic '") + myTLSEditorParent->myEditedDef->getID() + "'");
2911
}
2912
if (newDefSameProgram != nullptr) {
2913
// replace old program when loading the same program ID
2914
myTLSEditorParent->myEditedDef = newDefSameProgram;
2915
WRITE_MESSAGE(TL("Updated program '") + newDefSameProgram->getProgramID() + TL("' for tlLogic '") + myTLSEditorParent->myEditedDef->getID() + "'");
2916
}
2917
} else {
2918
if (tllHandler.getSeenIDs().count(myTLSEditorParent->myEditedDef->getID()) == 0) {
2919
myTLSEditorParent->getViewNet()->setStatusBarText(TL("No programs found for traffic light '") + myTLSEditorParent->myEditedDef->getID() + "'");
2920
}
2921
}
2922
2923
// clean up temporary container to avoid deletion of defs when its destruct is called
2924
for (NBTrafficLightDefinition* def : tmpTLLCont.getDefinitions()) {
2925
tmpTLLCont.removeProgram(def->getID(), def->getProgramID(), false);
2926
}
2927
2928
myTLSEditorParent->myTLSPhases->initPhaseTable();
2929
myTLSEditorParent->myTLSPrograms->markAsModified();
2930
}
2931
myTLSEditorParent->updateModules();
2932
return 0;
2933
}
2934
2935
2936
long
2937
GNETLSEditorFrame::TLSFile::onCmdSaveTLSProgram(FXObject*, FXSelector, void*) {
2938
FXString file = MFXUtils::getFilename2Write(this, TL("Save TLS Program as"),
2939
SUMOXMLDefinitions::XMLFileExtensions.getMultilineString().c_str(),
2940
GUIIconSubSys::getIcon(GUIIcon::MODETLS), gCurrentFolder);
2941
// check file
2942
if (file != "") {
2943
// add xml extension
2944
file = FileHelpers::addExtension(file.text(), ".xml").c_str();
2945
OutputDevice& device = OutputDevice::getDevice(file.text());
2946
// save program
2947
device.writeXMLHeader("additional", "additional_file.xsd");
2948
NWWriter_SUMO::writeTrafficLight(device, myTLSEditorParent->myEditedDef->getLogic());
2949
device.close();
2950
}
2951
myTLSEditorParent->updateModules();
2952
return 1;
2953
}
2954
2955
2956
std::string
2957
GNETLSEditorFrame::TLSFile::writeSUMOTime(SUMOTime steps) {
2958
const double time = STEPS2TIME(steps);
2959
if (time == std::floor(time)) {
2960
return toString(int(time));
2961
} else {
2962
return toString(time);
2963
}
2964
}
2965
2966
/****************************************************************************/
2967
2968