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