Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/frames/network/GNECreateEdgeFrame.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 GNECreateEdgeFrame.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Dec 2018
17
///
18
// The Widget for create edges (and junctions)
19
/****************************************************************************/
20
21
#include <netedit/GNENet.h>
22
#include <netedit/GNEUndoList.h>
23
#include <netedit/GNEViewParent.h>
24
#include <netedit/GNEApplicationWindow.h>
25
#include <netedit/changes/GNEChange_EdgeType.h>
26
#include <netedit/elements/network/GNEEdgeTemplate.h>
27
#include <netedit/elements/network/GNEEdgeType.h>
28
#include <netedit/elements/network/GNELaneTemplate.h>
29
#include <netedit/elements/network/GNELaneType.h>
30
#include <netedit/frames/GNEAttributesEditor.h>
31
#include <netedit/frames/common/GNEInspectorFrame.h>
32
#include <utils/foxtools/MFXDynamicLabel.h>
33
#include <utils/gui/div/GUIDesigns.h>
34
#include <utils/gui/windows/GUIAppEnum.h>
35
36
#include "GNECreateEdgeFrame.h"
37
38
// ===========================================================================
39
// FOX callback mapping
40
// ===========================================================================
41
42
FXDEFMAP(GNECreateEdgeFrame::EdgeTypeSelector) EdgeTypeSelectorMap[] = {
43
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GNECreateEdgeFrame::EdgeTypeSelector::onCmdRadioButton),
44
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_ADD, GNECreateEdgeFrame::EdgeTypeSelector::onCmdAddEdgeType),
45
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_DELETE, GNECreateEdgeFrame::EdgeTypeSelector::onCmdDeleteEdgeType),
46
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_SELECTTEMPLATE, GNECreateEdgeFrame::EdgeTypeSelector::onCmdSelectEdgeTypeOrTemplate),
47
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_CREATEFROMTEMPLATE, GNECreateEdgeFrame::EdgeTypeSelector::onCmdCreateFromTemplate),
48
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GNECreateEdgeFrame::EdgeTypeSelector::onUpdCheckButtons),
49
};
50
51
FXDEFMAP(GNECreateEdgeFrame::LaneTypeSelector) LaneTypeSelectorMap[] = {
52
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_ADD, GNECreateEdgeFrame::LaneTypeSelector::onCmdAddLaneType),
53
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_DELETE, GNECreateEdgeFrame::LaneTypeSelector::onCmdDeleteLaneType),
54
FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_SELECTLANE, GNECreateEdgeFrame::LaneTypeSelector::onCmdSelectLaneType),
55
};
56
57
// Object implementation
58
FXIMPLEMENT(GNECreateEdgeFrame::EdgeTypeSelector, MFXGroupBoxModule, EdgeTypeSelectorMap, ARRAYNUMBER(EdgeTypeSelectorMap))
59
FXIMPLEMENT(GNECreateEdgeFrame::LaneTypeSelector, MFXGroupBoxModule, LaneTypeSelectorMap, ARRAYNUMBER(LaneTypeSelectorMap))
60
61
62
// ===========================================================================
63
// method definitions
64
// ===========================================================================
65
66
// ---------------------------------------------------------------------------
67
// GNECreateEdgeFrame::EdgeTypeSelector - methods
68
// ---------------------------------------------------------------------------
69
70
GNECreateEdgeFrame::EdgeTypeSelector::EdgeTypeSelector(GNECreateEdgeFrame* createEdgeFrameParent) :
71
MFXGroupBoxModule(createEdgeFrameParent, TL("Template selector")),
72
myCreateEdgeFrameParent(createEdgeFrameParent),
73
myDefaultEdgeType(new GNEEdgeType(createEdgeFrameParent)),
74
myCurrentIndex(0) {
75
// default edge radio button
76
myCreateDefaultEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Create default edge"),
77
this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);
78
// default short radio button
79
myCreateDefaultShortEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Create default edge short"),
80
this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);
81
// checkboxes
82
myNoPedestriansCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Disallow for pedestrians"),
83
this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);
84
myAddSidewalkCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Add sidewalk"),
85
this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);
86
myAddBikelaneCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Add bikelane"),
87
this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);
88
// use custom edge radio button
89
myCreateCustomEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Use edgeType/template"),
90
this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);
91
// edge types combo box
92
myEdgeTypesComboBox = new MFXComboBoxIcon(getCollapsableFrame(), createEdgeFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
93
true, GUIDesignComboBoxVisibleItems, this, MID_GNE_CREATEEDGEFRAME_SELECTTEMPLATE, GUIDesignComboBoxAttribute);
94
// create horizontal frame
95
FXHorizontalFrame* horizontalFrameButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
96
// create new edge type button
97
myAddEdgeTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Add"), "", TL("Add edge type"), GUIIconSubSys::getIcon(GUIIcon::ADD),
98
this, MID_GNE_CREATEEDGEFRAME_ADD, GUIDesignButton);
99
// create delete edge type button
100
myDeleteEdgeTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Delete"), "", TL("Delete edge type"), GUIIconSubSys::getIcon(GUIIcon::REMOVE),
101
this, MID_GNE_CREATEEDGEFRAME_DELETE, GUIDesignButton);
102
// create delete edge type button
103
myCreateFromTemplate = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Create from template"), "", TL("Create edgeType from template"), GUIIconSubSys::getIcon(GUIIcon::EDGE),
104
this, MID_GNE_CREATEEDGEFRAME_CREATEFROMTEMPLATE, GUIDesignButton);
105
// by default, create custom edge
106
myCreateDefaultEdgeType->setCheck(TRUE);
107
// check if enable disable pedestrians
108
for (const auto& junction : createEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getJunctions()) {
109
if (junction.second->getNBNode()->getCrossings().size() > 0) {
110
enableCheckBoxDisablePedestrians();
111
}
112
}
113
}
114
115
116
GNECreateEdgeFrame::EdgeTypeSelector::~EdgeTypeSelector() {
117
delete myDefaultEdgeType;
118
}
119
120
121
void
122
GNECreateEdgeFrame::EdgeTypeSelector::refreshEdgeTypeSelector() {
123
// get template editor
124
const GNEInspectorFrame::TemplateEditor* templateEditor = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor();
125
// get current item
126
const int index = myEdgeTypesComboBox->getCurrentItem();
127
// fill combo box
128
fillComboBox();
129
// continue depending of radio buttons
130
if (myCreateDefaultEdgeType->getCheck() || myCreateDefaultShortEdgeType->getCheck()) {
131
// enable check boxes
132
myAddSidewalkCheckButton->enable();
133
myAddBikelaneCheckButton->enable();
134
myNoPedestriansCheckButton->enable();
135
// disable create from template
136
myCreateFromTemplate->disable();
137
// disable comboBox
138
myEdgeTypesComboBox->disable();
139
// disable buttons
140
myAddEdgeTypeButton->disable();
141
myDeleteEdgeTypeButton->disable();
142
// show default edgeType attributes
143
myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myDefaultEdgeType, true);
144
// show lane attributes
145
myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();
146
} else if (myCreateCustomEdgeType->getCheck()) {
147
// disable check boxes
148
myAddSidewalkCheckButton->disable();
149
myAddBikelaneCheckButton->disable();
150
myNoPedestriansCheckButton->disable();
151
// enable buttons
152
myAddEdgeTypeButton->enable();
153
myDeleteEdgeTypeButton->enable();
154
// check conditions
155
if (myEdgeTypesComboBox->getNumItems() == 0) {
156
// disable comboBox and edgeType
157
myEdgeTypesComboBox->disable();
158
myDeleteEdgeTypeButton->disable();
159
// hide attributes creators
160
myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->hideAttributesEditor();
161
myCreateEdgeFrameParent->myLaneTypeAttributesEditor->hideAttributesEditor();
162
} else if (templateEditor->getEdgeTemplate() && (index == 0)) {
163
// enable create from template
164
myCreateFromTemplate->enable();
165
// enable comboBox
166
myEdgeTypesComboBox->enable();
167
// disable delete edge type button (because templates cannot be deleted)
168
myDeleteEdgeTypeButton->disable();
169
// show edgeType attributes and disable
170
myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(templateEditor->getEdgeTemplate(), true);
171
myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->disableAttributesEditor();
172
// show lane attributes (will be automatic disabled)
173
myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();
174
} else {
175
// disable create from template
176
myCreateFromTemplate->disable();
177
// enable comboBox
178
myEdgeTypesComboBox->enable();
179
// get edgeType
180
myEdgeTypeSelected = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveEdgeType(myEdgeTypesComboBox->getText().text(), false);
181
// check if exist
182
if (myEdgeTypeSelected) {
183
// show edgeType attributes
184
myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myEdgeTypeSelected, true);
185
// show lane attributes
186
myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();
187
} else {
188
// hide edgeType attributes
189
myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->hideAttributesEditor();
190
// hide lane attributes
191
myCreateEdgeFrameParent->myLaneTypeSelector->hideLaneTypeSelector();
192
// set comboBox text
193
myEdgeTypesComboBox->setTextColor(GUIDesignTextColorRed);
194
}
195
}
196
}
197
// recalc
198
recalc();
199
}
200
201
202
void
203
GNECreateEdgeFrame::EdgeTypeSelector::updateIDinComboBox(const std::string& oldID, const std::string& newID) {
204
for (int i = 0; i < myEdgeTypesComboBox->getNumItems(); i++) {
205
if (myEdgeTypesComboBox->getItemText(i) == oldID) {
206
myEdgeTypesComboBox->updateIconItem(i, newID.c_str());
207
}
208
}
209
}
210
211
212
bool
213
GNECreateEdgeFrame::EdgeTypeSelector::useDefaultEdgeType() const {
214
return (myCreateDefaultEdgeType->getCheck() == TRUE);
215
}
216
217
218
bool
219
GNECreateEdgeFrame::EdgeTypeSelector::useDefaultEdgeTypeShort() const {
220
return (myCreateDefaultShortEdgeType->getCheck() == TRUE);
221
}
222
223
224
bool
225
GNECreateEdgeFrame::EdgeTypeSelector::useEdgeTemplate() const {
226
if (myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate()) {
227
if ((myCreateCustomEdgeType->getCheck() == TRUE) && (myEdgeTypesComboBox->getCurrentItem() == 0)) {
228
return true;
229
} else {
230
return false;
231
}
232
} else {
233
return false;
234
}
235
}
236
237
238
void
239
GNECreateEdgeFrame::EdgeTypeSelector::enableCheckBoxDisablePedestrians() {
240
myNoPedestriansCheckButton->setCheck(TRUE);
241
}
242
243
244
GNEEdgeType*
245
GNECreateEdgeFrame::EdgeTypeSelector::getDefaultEdgeType() const {
246
return myDefaultEdgeType;
247
}
248
249
250
GNEEdgeType*
251
GNECreateEdgeFrame::EdgeTypeSelector::getEdgeTypeSelected() const {
252
if ((myCreateDefaultEdgeType->getCheck() == TRUE) || (myCreateDefaultShortEdgeType->getCheck() == TRUE)) {
253
return myDefaultEdgeType;
254
} else {
255
return myEdgeTypeSelected;
256
}
257
}
258
259
260
bool
261
GNECreateEdgeFrame::EdgeTypeSelector::isNoPedestriansEnabled() const {
262
return (myNoPedestriansCheckButton->getCheck() == TRUE);
263
}
264
265
266
bool
267
GNECreateEdgeFrame::EdgeTypeSelector::isAddSidewalkEnabled() const {
268
return (myAddSidewalkCheckButton->getCheck() == TRUE);
269
}
270
271
272
bool
273
GNECreateEdgeFrame::EdgeTypeSelector::isAddBikelaneEnabled() const {
274
return (myAddBikelaneCheckButton->getCheck() == TRUE);
275
}
276
277
278
void
279
GNECreateEdgeFrame::EdgeTypeSelector::clearEdgeTypeSelected() {
280
myEdgeTypeSelected = nullptr;
281
myCurrentIndex--;
282
if (myCurrentIndex < 0) {
283
myCurrentIndex = 0;
284
}
285
}
286
287
288
void
289
GNECreateEdgeFrame::EdgeTypeSelector::setCurrentEdgeType(const GNEEdgeType* edgeType) {
290
for (int i = 0; i < myEdgeTypesComboBox->getNumItems(); i++) {
291
if (myEdgeTypesComboBox->getItemText(i) == edgeType->getID()) {
292
// set current item and index
293
myEdgeTypesComboBox->setCurrentItem(i);
294
myCurrentIndex = i;
295
// set buttons
296
myCreateDefaultEdgeType->setCheck(FALSE);
297
myCreateDefaultShortEdgeType->setCheck(FALSE);
298
myCreateCustomEdgeType->setCheck(TRUE);
299
// refresh
300
refreshEdgeTypeSelector();
301
}
302
}
303
}
304
305
306
void
307
GNECreateEdgeFrame::EdgeTypeSelector::useTemplate() {
308
myCreateDefaultEdgeType->setCheck(FALSE);
309
myCreateDefaultShortEdgeType->setCheck(FALSE);
310
myCreateCustomEdgeType->setCheck(TRUE);
311
refreshEdgeTypeSelector();
312
}
313
314
315
long
316
GNECreateEdgeFrame::EdgeTypeSelector::onCmdRadioButton(FXObject* obj, FXSelector, void*) {
317
// update radio buttons
318
if (obj == myCreateDefaultEdgeType) {
319
myCreateDefaultEdgeType->setCheck(TRUE);
320
myCreateDefaultShortEdgeType->setCheck(FALSE);
321
myCreateCustomEdgeType->setCheck(FALSE);
322
} else if (obj == myCreateDefaultShortEdgeType) {
323
myCreateDefaultEdgeType->setCheck(FALSE);
324
myCreateDefaultShortEdgeType->setCheck(TRUE);
325
myCreateCustomEdgeType->setCheck(FALSE);
326
} else {
327
myCreateDefaultEdgeType->setCheck(FALSE);
328
myCreateDefaultShortEdgeType->setCheck(FALSE);
329
myCreateCustomEdgeType->setCheck(TRUE);
330
}
331
// refresh template selector
332
refreshEdgeTypeSelector();
333
return 0;
334
}
335
336
337
long
338
GNECreateEdgeFrame::EdgeTypeSelector::onCmdAddEdgeType(FXObject*, FXSelector, void*) {
339
// create new edge type
340
GNEEdgeType* edgeType = new GNEEdgeType(myCreateEdgeFrameParent->getViewNet()->getNet());
341
// add it using undoList
342
myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("create new edge type"));
343
myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, true), true);
344
myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();
345
// update myEdgeTypeSelected
346
myEdgeTypeSelected = edgeType;
347
// select last item
348
myCurrentIndex = (myEdgeTypesComboBox->getNumItems() - 1);
349
// refresh EdgeTypeSelector
350
refreshEdgeTypeSelector();
351
return 0;
352
}
353
354
355
long
356
GNECreateEdgeFrame::EdgeTypeSelector::onCmdDeleteEdgeType(FXObject*, FXSelector, void*) {
357
// first check if we have to reset myEdgeTypeSelected
358
if (myEdgeTypeSelected && (myEdgeTypeSelected->getID() == myEdgeTypesComboBox->getText().text())) {
359
myEdgeTypeSelected = nullptr;
360
}
361
// get edgeType to remove
362
GNEEdgeType* edgeType = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveEdgeType(myEdgeTypesComboBox->getText().text());
363
// remove it using undoList
364
myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("delete edge type"));
365
myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);
366
myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();
367
// refresh EdgeTypeSelector
368
refreshEdgeTypeSelector();
369
return 0;
370
}
371
372
373
long
374
GNECreateEdgeFrame::EdgeTypeSelector::onCmdSelectEdgeTypeOrTemplate(FXObject*, FXSelector, void*) {
375
// update current index
376
myCurrentIndex = myEdgeTypesComboBox->getCurrentItem();
377
// refresh edgeType selector
378
refreshEdgeTypeSelector();
379
return 0;
380
}
381
382
383
long
384
GNECreateEdgeFrame::EdgeTypeSelector::onCmdCreateFromTemplate(FXObject*, FXSelector, void*) {
385
if (myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate()) {
386
// create new edge type
387
GNEEdgeType* edgeType = new GNEEdgeType(myCreateEdgeFrameParent->getViewNet()->getNet());
388
// copy all template values
389
edgeType->copyTemplate(myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate());
390
// add it using undoList
391
myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("create new edge type"));
392
myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, true), true);
393
myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();
394
// update myEdgeTypeSelected
395
myEdgeTypeSelected = edgeType;
396
// select last item
397
myCurrentIndex = (myEdgeTypesComboBox->getNumItems() - 1);
398
// refresh EdgeTypeSelector
399
refreshEdgeTypeSelector();
400
}
401
return 0;
402
}
403
404
405
long
406
GNECreateEdgeFrame::EdgeTypeSelector::onUpdCheckButtons(FXObject*, FXSelector, void*) {
407
if (myAddSidewalkCheckButton->getCheck() == TRUE) {
408
myNoPedestriansCheckButton->setCheck(TRUE);
409
myNoPedestriansCheckButton->disable();
410
} else {
411
myNoPedestriansCheckButton->enable();
412
}
413
// show default edgeType attributes again (for refresh sidewalk and bike widths)
414
myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myDefaultEdgeType, true);
415
return 1;
416
}
417
418
419
void
420
GNECreateEdgeFrame::EdgeTypeSelector::fillComboBox() {
421
// get template editor
422
const GNEInspectorFrame::TemplateEditor* templateEditor = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor();
423
// get edge types
424
const auto& edgeTypes = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdgeTypes();
425
// clear edge types
426
myEdgeTypesComboBox->clearItems();
427
// set comboBox text color
428
myEdgeTypesComboBox->setTextColor(GUIDesignTextColorBlack);
429
// add template
430
if (templateEditor->getEdgeTemplate()) {
431
myEdgeTypesComboBox->appendIconItem((TL("template: ") + templateEditor->getEdgeTemplate()->getID()).c_str(), nullptr);
432
}
433
if (edgeTypes.size() > 0) {
434
// add edge types
435
for (const auto& edgeType : edgeTypes) {
436
myEdgeTypesComboBox->appendIconItem(edgeType.second->getID().c_str(), edgeType.second->getACIcon());
437
}
438
// set current item
439
if ((myCurrentIndex < 0) || (myCurrentIndex >= myEdgeTypesComboBox->getNumItems())) {
440
myCurrentIndex = myEdgeTypesComboBox->getNumItems() - 1;
441
}
442
myEdgeTypesComboBox->setCurrentItem(myCurrentIndex);
443
myEdgeTypesComboBox->enable();
444
} else {
445
myEdgeTypesComboBox->disable();
446
}
447
}
448
449
// ---------------------------------------------------------------------------
450
// GNECreateEdgeFrame::LaneTypeSelector - methods
451
// ---------------------------------------------------------------------------
452
453
GNECreateEdgeFrame::LaneTypeSelector::LaneTypeSelector(GNECreateEdgeFrame* createEdgeFrameParent) :
454
MFXGroupBoxModule(createEdgeFrameParent, TL("LaneType selector")),
455
myCreateEdgeFrameParent(createEdgeFrameParent),
456
myLaneIndex(0) {
457
// lane types combo box
458
myLaneTypesComboBox = new MFXComboBoxIcon(getCollapsableFrame(), createEdgeFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),
459
false, GUIDesignComboBoxVisibleItems, this, MID_GNE_CREATEEDGEFRAME_SELECTLANE, GUIDesignComboBoxAttribute);
460
// create horizontal frame
461
FXHorizontalFrame* horizontalFrameButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
462
// create new lane type button
463
myAddLaneTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Add"), "", TL("Add lane type"), GUIIconSubSys::getIcon(GUIIcon::ADD),
464
this, MID_GNE_CREATEEDGEFRAME_ADD, GUIDesignButton);
465
// create delete lane type button
466
myDeleteLaneTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Delete"), "", TL("Delete lane type"), GUIIconSubSys::getIcon(GUIIcon::REMOVE),
467
this, MID_GNE_CREATEEDGEFRAME_DELETE, GUIDesignButton);
468
}
469
470
471
GNECreateEdgeFrame::LaneTypeSelector::~LaneTypeSelector() {
472
}
473
474
475
void
476
GNECreateEdgeFrame::LaneTypeSelector::showLaneTypeSelector() {
477
// start at first lane
478
myLaneIndex = 0;
479
// refresh laneTypeSelector
480
refreshLaneTypeSelector();
481
// show
482
show();
483
}
484
485
486
void
487
GNECreateEdgeFrame::LaneTypeSelector::hideLaneTypeSelector() {
488
// hide attributes creator module
489
myCreateEdgeFrameParent->myLaneTypeAttributesEditor->hideAttributesEditor();
490
// hide
491
hide();
492
}
493
494
495
void
496
GNECreateEdgeFrame::LaneTypeSelector::refreshLaneTypeSelector() {
497
// clear lane types
498
myLaneTypesComboBox->clearItems();
499
// first check if use template
500
if (myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {
501
const GNEEdgeTemplate* edgeTemplate = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate();
502
// fill comboBox
503
for (const auto& laneTemplate : edgeTemplate->getLaneTemplates()) {
504
myLaneTypesComboBox->appendIconItem(laneTemplate->getAttribute(SUMO_ATTR_ID).c_str(), laneTemplate->getACIcon());
505
}
506
// update comboBox
507
updateComboBox();
508
// show laneTypeAttributes
509
myCreateEdgeFrameParent->myLaneTypeAttributesEditor->showAttributesEditor(edgeTemplate->getLaneTemplates().at(myLaneIndex), false);
510
// disable laneAttributes (because is a template)
511
myCreateEdgeFrameParent->myLaneTypeAttributesEditor->disableAttributesEditor();
512
// disable add and remove buttons
513
myAddLaneTypeButton->disable();
514
myDeleteLaneTypeButton->disable();
515
} else {
516
// get edgeType
517
const GNEEdgeType* edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();
518
// fill comboBox
519
for (const auto& laneType : edgeType->getLaneTypes()) {
520
myLaneTypesComboBox->appendIconItem(laneType->getAttribute(SUMO_ATTR_ID).c_str(), laneType->getACIcon());
521
}
522
// update comboBox
523
updateComboBox();
524
// show laneTypeAttributes
525
myCreateEdgeFrameParent->myLaneTypeAttributesEditor->showAttributesEditor(edgeType->getLaneTypes().at(myLaneIndex), false);
526
// enable add and remove buttons
527
myAddLaneTypeButton->enable();
528
// check if enable or disable remove lane button
529
if (edgeType->getLaneTypes().size() > 1) {
530
myDeleteLaneTypeButton->enable();
531
} else {
532
myDeleteLaneTypeButton->disable();
533
}
534
}
535
// recalc
536
recalc();
537
}
538
539
540
long
541
GNECreateEdgeFrame::LaneTypeSelector::onCmdAddLaneType(FXObject*, FXSelector, void*) {
542
// check what edgeType is being edited
543
if (myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeType() ||
544
myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeTypeShort()) {
545
// add new lane in default edge type
546
myCreateEdgeFrameParent->myEdgeTypeSelector->getDefaultEdgeType()->addLaneType(new GNELaneType(myCreateEdgeFrameParent->myEdgeTypeSelector->getDefaultEdgeType()));
547
// refresh laneTypeSelector
548
refreshLaneTypeSelector();
549
// set combo box
550
myLaneTypesComboBox->setCurrentItem(myLaneTypesComboBox->getNumItems() - 1);
551
} else if (!myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {
552
// get selected
553
const auto edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();
554
if (edgeType) {
555
// create new edgeType
556
GNEEdgeType* newEdgeType = new GNEEdgeType(edgeType);
557
// create laneTypes
558
for (const auto& laneType : edgeType->getLaneTypes()) {
559
newEdgeType->addLaneType(new GNELaneType(newEdgeType, laneType));
560
}
561
// add new lane
562
newEdgeType->addLaneType(new GNELaneType(newEdgeType));
563
// remove old edgeTyp und and newEdgeType
564
myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::LANETYPE, TL("add laneType"));
565
myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);
566
myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(newEdgeType, true), true);
567
myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();
568
// update index
569
myLaneIndex = myLaneTypesComboBox->getNumItems() - 1;
570
// set current edgeType in selector
571
myCreateEdgeFrameParent->myEdgeTypeSelector->setCurrentEdgeType(newEdgeType);
572
}
573
}
574
return 0;
575
}
576
577
578
long
579
GNECreateEdgeFrame::LaneTypeSelector::onCmdDeleteLaneType(FXObject*, FXSelector, void*) {
580
// check what edgeType is being edited
581
if (myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeType() ||
582
myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeTypeShort()) {
583
// add new lane in default edge type
584
myCreateEdgeFrameParent->myEdgeTypeSelector->getDefaultEdgeType()->removeLaneType(myLaneIndex);
585
// refresh laneTypeSelector
586
refreshLaneTypeSelector();
587
// set combo box
588
myLaneTypesComboBox->setCurrentItem(0);
589
} else if (!myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {
590
// get selected
591
const auto edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();
592
if (edgeType) {
593
// create new edgeType
594
GNEEdgeType* newEdgeType = new GNEEdgeType(edgeType);
595
// create laneTypes (except current)
596
for (int i = 0; i < (int)edgeType->getLaneTypes().size(); i++) {
597
if (i != myLaneIndex) {
598
newEdgeType->addLaneType(new GNELaneType(newEdgeType, edgeType->getLaneTypes().at(i)));
599
}
600
}
601
// remove old edgeTyp und and newEdgeType
602
myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::LANETYPE, TL("remove laneType"));
603
myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);
604
myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(newEdgeType, true), true);
605
myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();
606
// update index
607
myLaneIndex = myLaneTypesComboBox->getNumItems() - 1;
608
// set current edgeType in selector
609
myCreateEdgeFrameParent->myEdgeTypeSelector->setCurrentEdgeType(newEdgeType);
610
}
611
}
612
return 0;
613
}
614
615
616
long
617
GNECreateEdgeFrame::LaneTypeSelector::onCmdSelectLaneType(FXObject*, FXSelector, void*) {
618
// update index
619
myLaneIndex = myLaneTypesComboBox->getCurrentItem();
620
// refresh laneType selector
621
refreshLaneTypeSelector();
622
return 0;
623
}
624
625
626
void
627
GNECreateEdgeFrame::LaneTypeSelector::updateComboBox() {
628
// check lane index
629
if (myLaneIndex > myLaneTypesComboBox->getNumItems()) {
630
myLaneIndex = 0;
631
}
632
// set current item
633
myLaneTypesComboBox->setCurrentItem(myLaneIndex);
634
}
635
636
// ---------------------------------------------------------------------------
637
// GNECreateEdgeFrame::Legend - methods
638
// ---------------------------------------------------------------------------
639
640
GNECreateEdgeFrame::Legend::Legend(GNECreateEdgeFrame* createEdgeFrameParent) :
641
MFXGroupBoxModule(createEdgeFrameParent, TL("Information")) {
642
std::ostringstream information;
643
// add label for shift+click
644
information
645
<< "- " << TL("ESC:") << "\n"
646
<< " " << TL("Deselect origin") << "\n"
647
<< "- " << TL("Control+Click:") << "\n"
648
<< " " << TL("Move view") << "\n"
649
<< "- " << TL("Shift+Click:") << "\n"
650
<< " " << TL("Splits edge in both directions") << "\n"
651
<< "- " << TL("Alt+Shift+Click:") << "\n"
652
<< " " << TL("Splits edge in one direction");
653
// create label
654
new MFXDynamicLabel(getCollapsableFrame(), information.str().c_str(), 0, GUIDesignLabelFrameInformation);
655
}
656
657
658
GNECreateEdgeFrame::Legend::~Legend() {}
659
660
// ---------------------------------------------------------------------------
661
// GNECreateEdgeFrame - methods
662
// ---------------------------------------------------------------------------
663
664
GNECreateEdgeFrame::GNECreateEdgeFrame(GNEViewParent* viewParent, GNEViewNet* viewNet) :
665
GNEFrame(viewParent, viewNet, TL("Create Edge")),
666
myJunctionSource(nullptr) {
667
// create custom edge selector
668
myEdgeTypeSelector = new EdgeTypeSelector(this);
669
// Create edgeType parameters
670
myEdgeTypeAttributesEditor = new GNEAttributesEditor(this, GNEAttributesEditorType::EditorType::CREATOR);
671
// lane type selector
672
myLaneTypeSelector = new LaneTypeSelector(this);
673
// Create laneType parameters
674
myLaneTypeAttributesEditor = new GNEAttributesEditor(this, GNEAttributesEditorType::EditorType::CREATOR);
675
// create edge selector legend
676
myLegend = new Legend(this);
677
}
678
679
680
GNECreateEdgeFrame::~GNECreateEdgeFrame() {}
681
682
683
void
684
GNECreateEdgeFrame::processClick(const Position& clickedPosition, const GNEViewNetHelper::ViewObjectsSelector& viewObjects,
685
const bool oppositeEdge, const bool chainEdge) {
686
// first check if there is an edge template, an edge type (default or custom)
687
if (!myEdgeTypeSelector->useDefaultEdgeType() && !myEdgeTypeSelector->useDefaultEdgeTypeShort() &&
688
!myEdgeTypeSelector->useEdgeTemplate() && (myEdgeTypeSelector->getEdgeTypeSelected() == nullptr)) {
689
WRITE_WARNING(TL("Select either default edgeType or short edge or a custom edgeType or template"));
690
} else if (myEdgeTypeAttributesEditor->checkAttributes(true) && myLaneTypeAttributesEditor->checkAttributes(true)) {
691
// if grid is enabled and currently there isn't a junction under mouse, make a new search snapping position to grid
692
if ((viewObjects.getJunctionFront() == nullptr) && myViewNet->getVisualisationSettings().showGrid) {
693
myViewNet->updateObjectsInPosition(myViewNet->snapToActiveGrid(clickedPosition));
694
}
695
// obtain junction depending of gridEnabled
696
GNEJunction* junction = viewObjects.getJunctionFront();
697
// begin undo list
698
if (!myViewNet->getUndoList()->hasCommandGroup()) {
699
myViewNet->getUndoList()->begin(GUIIcon::EDGE, TL("create new edge"));
700
}
701
// if we didn't clicked over another junction, then create a new
702
if (junction == nullptr) {
703
junction = myViewNet->getNet()->createJunction(myViewNet->snapToActiveGrid(clickedPosition), myViewNet->getUndoList());
704
}
705
// now check if we have to create a new edge
706
if (myJunctionSource == nullptr) {
707
// check if create edge type short
708
if (myEdgeTypeSelector->useDefaultEdgeTypeShort()) {
709
// create new junction
710
auto newJunction = myViewNet->getNet()->createJunction(myViewNet->snapToActiveGrid(clickedPosition) + Position(5, 0), myViewNet->getUndoList());
711
// create new small edge
712
GNEEdge* newEdge = myViewNet->getNet()->createEdge(junction, newJunction, nullptr, myViewNet->getUndoList());
713
// set parameters
714
newEdge->copyEdgeType(myEdgeTypeSelector->getDefaultEdgeType(), myViewNet->getUndoList());
715
// check pedestrians and sidewalks
716
if (myEdgeTypeSelector->isNoPedestriansEnabled()) {
717
disablePedestrians(newEdge);
718
}
719
// check if add bikelane
720
if (myEdgeTypeSelector->isAddBikelaneEnabled()) {
721
addBikelane(newEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_BIKELANEWIDTH));
722
}
723
// check if add sidewalk
724
if (myEdgeTypeSelector->isAddSidewalkEnabled()) {
725
addSidewalk(newEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));
726
}
727
// end undo list
728
if (myViewNet->getUndoList()->hasCommandGroup()) {
729
myViewNet->getUndoList()->end();
730
} else {
731
std::cout << "edge created without an open CommandGroup" << std::endl;
732
}
733
} else {
734
myJunctionSource = junction;
735
myJunctionSource->markAsCreateEdgeSource();
736
}
737
update();
738
} else {
739
// make sure that junctions source and destination are different
740
if (myJunctionSource != junction) {
741
// may fail to prevent double edges
742
GNEEdge* newEdge = myViewNet->getNet()->createEdge(myJunctionSource, junction, nullptr, myViewNet->getUndoList());
743
// check if edge was successfully created
744
if (newEdge) {
745
// set parameters
746
if (myEdgeTypeSelector->useEdgeTemplate()) {
747
newEdge->copyTemplate(myViewNet->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate(), myViewNet->getUndoList());
748
} else if (myEdgeTypeSelector->useDefaultEdgeType()) {
749
newEdge->copyEdgeType(myEdgeTypeSelector->getDefaultEdgeType(), myViewNet->getUndoList());
750
// check pedestrians and sidewalks
751
if (myEdgeTypeSelector->isNoPedestriansEnabled()) {
752
disablePedestrians(newEdge);
753
}
754
// check if add bikelane
755
if (myEdgeTypeSelector->isAddBikelaneEnabled()) {
756
addBikelane(newEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_BIKELANEWIDTH));
757
}
758
// check if add sidewalk
759
if (myEdgeTypeSelector->isAddSidewalkEnabled()) {
760
addSidewalk(newEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));
761
}
762
} else {
763
newEdge->copyEdgeType(myEdgeTypeSelector->getEdgeTypeSelected(), myViewNet->getUndoList());
764
}
765
// create another edge, if create opposite edge is enabled
766
if (oppositeEdge && (myViewNet->getNet()->getAttributeCarriers()->retrieveEdges(junction, myJunctionSource).size() == 0)) {
767
GNEEdge* newOppositeEdge = myViewNet->getNet()->createEdge(junction, myJunctionSource, nullptr,
768
myViewNet->getUndoList(), "-" + newEdge->getNBEdge()->getID());
769
// set parameters
770
if (myEdgeTypeSelector->useEdgeTemplate()) {
771
newOppositeEdge->copyTemplate(myViewNet->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate(), myViewNet->getUndoList());
772
} else if (myEdgeTypeSelector->useDefaultEdgeType()) {
773
newOppositeEdge->copyEdgeType(myEdgeTypeSelector->getDefaultEdgeType(), myViewNet->getUndoList());
774
// check pedestrians and sidewalks
775
if (myEdgeTypeSelector->isNoPedestriansEnabled()) {
776
disablePedestrians(newOppositeEdge);
777
}
778
// check if add bikelane
779
if (myEdgeTypeSelector->isAddBikelaneEnabled()) {
780
addBikelane(newOppositeEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_BIKELANEWIDTH));
781
}
782
// check if add sidewalk
783
if (myEdgeTypeSelector->isAddSidewalkEnabled()) {
784
addSidewalk(newOppositeEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));
785
}
786
} else {
787
newOppositeEdge->copyEdgeType(myEdgeTypeSelector->getEdgeTypeSelected(), myViewNet->getUndoList());
788
}
789
}
790
// edge created, then unmark as create edge source
791
myJunctionSource->unMarkAsCreateEdgeSource();
792
// end undo list
793
if (myViewNet->getUndoList()->hasCommandGroup()) {
794
myViewNet->getUndoList()->end();
795
} else {
796
std::cout << "edge created without an open CommandGroup" << std::endl;
797
}
798
// if we're creating edges in chain mode, mark junction as junction edge source
799
if (chainEdge) {
800
myJunctionSource = junction;
801
myJunctionSource->markAsCreateEdgeSource();
802
myViewNet->getUndoList()->begin(GUIIcon::EDGE, TL("create new edge"));
803
} else {
804
myJunctionSource = nullptr;
805
}
806
} else {
807
myViewNet->setStatusBarText(TL("An edge with the same geometry already exists!"));
808
}
809
} else {
810
myViewNet->setStatusBarText(TL("Start- and endpoint for an edge must be distinct!"));
811
}
812
update();
813
}
814
}
815
}
816
817
818
void
819
GNECreateEdgeFrame::abortEdgeCreation() {
820
// if myCreateEdgeSource exist, unmark ist as create edge source
821
if (myJunctionSource != nullptr) {
822
// remove current created edge source
823
myJunctionSource->unMarkAsCreateEdgeSource();
824
myJunctionSource = nullptr;
825
}
826
}
827
828
829
const GNEJunction*
830
GNECreateEdgeFrame::getJunctionSource() const {
831
return myJunctionSource;
832
}
833
834
835
void
836
GNECreateEdgeFrame::show() {
837
// refresh template selector
838
myEdgeTypeSelector->refreshEdgeTypeSelector();
839
// show frame
840
GNEFrame::show();
841
}
842
843
844
void
845
GNECreateEdgeFrame::hide() {
846
// hide frame
847
GNEFrame::hide();
848
}
849
850
851
GNECreateEdgeFrame::EdgeTypeSelector*
852
GNECreateEdgeFrame::getEdgeTypeSelector() const {
853
return myEdgeTypeSelector;
854
}
855
856
857
GNEAttributesEditor*
858
GNECreateEdgeFrame::getEdgeTypeAttributes() const {
859
return myEdgeTypeAttributesEditor;
860
}
861
862
863
GNECreateEdgeFrame::LaneTypeSelector*
864
GNECreateEdgeFrame::getLaneTypeSelector() {
865
return myLaneTypeSelector;
866
}
867
868
869
GNEAttributesEditor*
870
GNECreateEdgeFrame::getLaneTypeAttributes() const {
871
return myLaneTypeAttributesEditor;
872
}
873
874
875
void
876
GNECreateEdgeFrame::setUseEdgeTemplate() {
877
myEdgeTypeSelector->useTemplate();
878
myEdgeTypeSelector->refreshEdgeTypeSelector();
879
}
880
881
882
void
883
GNECreateEdgeFrame::disablePedestrians(GNEEdge* edge) const {
884
// iterate over lanes
885
for (const auto& lane : edge->getChildLanes()) {
886
// avoid sidewalks
887
if (lane->getAttribute(SUMO_ATTR_ALLOW) != "pedestrian") {
888
// extract disallow list
889
std::vector<std::string> disallowList = GNEAttributeCarrier::parse<std::vector<std::string> >(lane->getAttribute(SUMO_ATTR_DISALLOW));
890
// check if append pedestrian to disallow
891
if (std::find(disallowList.begin(), disallowList.end(), "pedestrian") == disallowList.end()) {
892
disallowList.push_back("pedestrian");
893
}
894
// update attribute
895
lane->setAttribute(SUMO_ATTR_DISALLOW, toString(disallowList), myViewNet->getUndoList());
896
}
897
}
898
}
899
900
901
void
902
GNECreateEdgeFrame::addBikelane(GNEEdge* edge, const std::string& bikelaneWidth) const {
903
bool bikelaneFound = false;
904
// iterate over lanes
905
for (const auto& lane : edge->getChildLanes()) {
906
// check if there is already a SideWalk
907
if (lane->getAttribute(SUMO_ATTR_ALLOW) == "bicycle") {
908
bikelaneFound = true;
909
}
910
}
911
// only add if previously there is no bikelanes
912
if (!bikelaneFound) {
913
edge->getNet()->getViewNet()->addRestrictedLane(edge->getChildLanes().at(0), SVC_BICYCLE, false);
914
// set width
915
if (bikelaneWidth != "default") {
916
edge->getChildLanes().at(0)->setAttribute(SUMO_ATTR_WIDTH, bikelaneWidth, myViewNet->getUndoList());
917
}
918
}
919
}
920
921
922
void
923
GNECreateEdgeFrame::addSidewalk(GNEEdge* edge, const std::string& sidewalkWidth) const {
924
bool sidewalkFound = false;
925
// iterate over lanes
926
for (const auto& lane : edge->getChildLanes()) {
927
// check if there is already a SideWalk
928
if (lane->getAttribute(SUMO_ATTR_ALLOW) == "pedestrian") {
929
sidewalkFound = true;
930
}
931
}
932
// only add if previously there is no Sidewalk
933
if (!sidewalkFound) {
934
edge->getNet()->getViewNet()->addRestrictedLane(edge->getChildLanes().at(0), SVC_PEDESTRIAN, false);
935
// set width
936
if (sidewalkWidth != "default") {
937
edge->getChildLanes().at(0)->setAttribute(SUMO_ATTR_WIDTH, sidewalkWidth, myViewNet->getUndoList());
938
}
939
}
940
}
941
942
/****************************************************************************/
943
944