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