Path: blob/main/src/netedit/frames/network/GNECreateEdgeFrame.cpp
193735 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GNECreateEdgeFrame.cpp14/// @author Pablo Alvarez Lopez15/// @date Dec 201816///17// The Widget for create edges (and junctions)18/****************************************************************************/1920#include <netedit/GNENet.h>21#include <netedit/GNEUndoList.h>22#include <netedit/GNEViewParent.h>23#include <netedit/GNEApplicationWindow.h>24#include <netedit/changes/GNEChange_EdgeType.h>25#include <netedit/elements/network/GNEEdgeTemplate.h>26#include <netedit/elements/network/GNEEdgeType.h>27#include <netedit/elements/network/GNELaneTemplate.h>28#include <netedit/elements/network/GNELaneType.h>29#include <netedit/frames/GNEAttributesEditor.h>30#include <netedit/frames/common/GNEInspectorFrame.h>31#include <utils/foxtools/MFXDynamicLabel.h>32#include <utils/gui/div/GUIDesigns.h>33#include <utils/gui/windows/GUIAppEnum.h>3435#include "GNECreateEdgeFrame.h"3637// ===========================================================================38// FOX callback mapping39// ===========================================================================4041FXDEFMAP(GNECreateEdgeFrame::EdgeTypeSelector) EdgeTypeSelectorMap[] = {42FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GNECreateEdgeFrame::EdgeTypeSelector::onCmdRadioButton),43FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_ADD, GNECreateEdgeFrame::EdgeTypeSelector::onCmdAddEdgeType),44FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_DELETE, GNECreateEdgeFrame::EdgeTypeSelector::onCmdDeleteEdgeType),45FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_SELECTTEMPLATE, GNECreateEdgeFrame::EdgeTypeSelector::onCmdSelectEdgeTypeOrTemplate),46FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_CREATEFROMTEMPLATE, GNECreateEdgeFrame::EdgeTypeSelector::onCmdCreateFromTemplate),47FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GNECreateEdgeFrame::EdgeTypeSelector::onUpdCheckButtons),48};4950FXDEFMAP(GNECreateEdgeFrame::LaneTypeSelector) LaneTypeSelectorMap[] = {51FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_ADD, GNECreateEdgeFrame::LaneTypeSelector::onCmdAddLaneType),52FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_DELETE, GNECreateEdgeFrame::LaneTypeSelector::onCmdDeleteLaneType),53FXMAPFUNC(SEL_COMMAND, MID_GNE_CREATEEDGEFRAME_SELECTLANE, GNECreateEdgeFrame::LaneTypeSelector::onCmdSelectLaneType),54};5556// Object implementation57FXIMPLEMENT(GNECreateEdgeFrame::EdgeTypeSelector, GNEGroupBoxModule, EdgeTypeSelectorMap, ARRAYNUMBER(EdgeTypeSelectorMap))58FXIMPLEMENT(GNECreateEdgeFrame::LaneTypeSelector, GNEGroupBoxModule, LaneTypeSelectorMap, ARRAYNUMBER(LaneTypeSelectorMap))596061// ===========================================================================62// method definitions63// ===========================================================================6465// ---------------------------------------------------------------------------66// GNECreateEdgeFrame::EdgeTypeSelector - methods67// ---------------------------------------------------------------------------6869GNECreateEdgeFrame::EdgeTypeSelector::EdgeTypeSelector(GNECreateEdgeFrame* createEdgeFrameParent) :70GNEGroupBoxModule(createEdgeFrameParent, TL("Template selector")),71myCreateEdgeFrameParent(createEdgeFrameParent),72myCurrentIndex(0) {73// default edge radio button74myCreateDefaultEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Create default edge"),75this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);76// default short radio button77myCreateDefaultShortEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Create default edge short"),78this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);79// checkboxes80myNoPedestriansCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Disallow for pedestrians"),81this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);82myAddSidewalkCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Add sidewalk"),83this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);84myAddBikelaneCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Add bikelane"),85this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);86// use custom edge radio button87myCreateCustomEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Use edgeType/template"),88this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);89// edge types combo box90myEdgeTypesComboBox = new MFXComboBoxIcon(getCollapsableFrame(), createEdgeFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),91true, GUIDesignComboBoxVisibleItems, this, MID_GNE_CREATEEDGEFRAME_SELECTTEMPLATE, GUIDesignComboBoxAttribute);92// create horizontal frame93FXHorizontalFrame* horizontalFrameButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);94// create new edge type button95myAddEdgeTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Add"), "", TL("Add edge type"), GUIIconSubSys::getIcon(GUIIcon::ADD),96this, MID_GNE_CREATEEDGEFRAME_ADD, GUIDesignButton);97// create delete edge type button98myDeleteEdgeTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Delete"), "", TL("Delete edge type"), GUIIconSubSys::getIcon(GUIIcon::REMOVE),99this, MID_GNE_CREATEEDGEFRAME_DELETE, GUIDesignButton);100// create delete edge type button101myCreateFromTemplate = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Create from template"), "", TL("Create edgeType from template"), GUIIconSubSys::getIcon(GUIIcon::EDGE),102this, MID_GNE_CREATEEDGEFRAME_CREATEFROMTEMPLATE, GUIDesignButton);103// by default, create custom edge104myCreateDefaultEdgeType->setCheck(TRUE);105// check if enable disable pedestrians106for (const auto& junction : createEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getJunctions()) {107if (junction.second->getNBNode()->getCrossings().size() > 0) {108enableCheckBoxDisablePedestrians();109}110}111}112113114GNECreateEdgeFrame::EdgeTypeSelector::~EdgeTypeSelector() {115}116117118void119GNECreateEdgeFrame::EdgeTypeSelector::refreshEdgeTypeSelector() {120// get template editor121const GNEInspectorFrame::TemplateEditor* templateEditor = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor();122// get current item123const int index = myEdgeTypesComboBox->getCurrentItem();124// fill combo box125fillComboBox();126// continue depending of radio buttons127if (myCreateDefaultEdgeType->getCheck() || myCreateDefaultShortEdgeType->getCheck()) {128// enable check boxes129myAddSidewalkCheckButton->enable();130myAddBikelaneCheckButton->enable();131myNoPedestriansCheckButton->enable();132// disable create from template133myCreateFromTemplate->disable();134// disable comboBox135myEdgeTypesComboBox->disable();136// disable buttons137myAddEdgeTypeButton->disable();138myDeleteEdgeTypeButton->disable();139// show default edgeType attributes140myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myCreateEdgeFrameParent->getViewNet()->getNet()->getACTemplates()->getDefaultEdgeType(), true);141// show lane attributes142myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();143} else if (myCreateCustomEdgeType->getCheck()) {144// disable check boxes145myAddSidewalkCheckButton->disable();146myAddBikelaneCheckButton->disable();147myNoPedestriansCheckButton->disable();148// enable buttons149myAddEdgeTypeButton->enable();150myDeleteEdgeTypeButton->enable();151// check conditions152if (myEdgeTypesComboBox->getNumItems() == 0) {153// disable comboBox and edgeType154myEdgeTypesComboBox->disable();155myDeleteEdgeTypeButton->disable();156// hide attributes creators157myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->hideAttributesEditor();158myCreateEdgeFrameParent->myLaneTypeAttributesEditor->hideAttributesEditor();159} else if (templateEditor->getEdgeTemplate() && (index == 0)) {160// enable create from template161myCreateFromTemplate->enable();162// enable comboBox163myEdgeTypesComboBox->enable();164// disable delete edge type button (because templates cannot be deleted)165myDeleteEdgeTypeButton->disable();166// show edgeType attributes and disable167myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(templateEditor->getEdgeTemplate(), true);168myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->disableAttributesEditor();169// show lane attributes (will be automatic disabled)170myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();171} else {172// disable create from template173myCreateFromTemplate->disable();174// enable comboBox175myEdgeTypesComboBox->enable();176// get edgeType177myEdgeTypeSelected = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveEdgeType(myEdgeTypesComboBox->getText().text(), false);178// check if exist179if (myEdgeTypeSelected) {180// show edgeType attributes181myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myEdgeTypeSelected, true);182// show lane attributes183myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();184} else {185// hide edgeType attributes186myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->hideAttributesEditor();187// hide lane attributes188myCreateEdgeFrameParent->myLaneTypeSelector->hideLaneTypeSelector();189// set comboBox text190myEdgeTypesComboBox->setTextColor(GUIDesignTextColorRed);191}192}193}194// recalc195recalc();196}197198199void200GNECreateEdgeFrame::EdgeTypeSelector::updateIDinComboBox(const std::string& oldID, const std::string& newID) {201for (int i = 0; i < myEdgeTypesComboBox->getNumItems(); i++) {202if (myEdgeTypesComboBox->getItemText(i) == oldID) {203myEdgeTypesComboBox->updateIconItem(i, newID.c_str());204}205}206}207208209bool210GNECreateEdgeFrame::EdgeTypeSelector::useDefaultEdgeType() const {211return (myCreateDefaultEdgeType->getCheck() == TRUE);212}213214215bool216GNECreateEdgeFrame::EdgeTypeSelector::useDefaultEdgeTypeShort() const {217return (myCreateDefaultShortEdgeType->getCheck() == TRUE);218}219220221bool222GNECreateEdgeFrame::EdgeTypeSelector::useEdgeTemplate() const {223if (myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate()) {224if ((myCreateCustomEdgeType->getCheck() == TRUE) && (myEdgeTypesComboBox->getCurrentItem() == 0)) {225return true;226} else {227return false;228}229} else {230return false;231}232}233234235void236GNECreateEdgeFrame::EdgeTypeSelector::enableCheckBoxDisablePedestrians() {237myNoPedestriansCheckButton->setCheck(TRUE);238}239240241GNEEdgeType*242GNECreateEdgeFrame::EdgeTypeSelector::getEdgeTypeSelected() const {243if ((myCreateDefaultEdgeType->getCheck() == TRUE) || (myCreateDefaultShortEdgeType->getCheck() == TRUE)) {244return myCreateEdgeFrameParent->getViewNet()->getNet()->getACTemplates()->getDefaultEdgeType();245} else {246return myEdgeTypeSelected;247}248}249250251bool252GNECreateEdgeFrame::EdgeTypeSelector::isNoPedestriansEnabled() const {253return (myNoPedestriansCheckButton->getCheck() == TRUE);254}255256257bool258GNECreateEdgeFrame::EdgeTypeSelector::isAddSidewalkEnabled() const {259return (myAddSidewalkCheckButton->getCheck() == TRUE);260}261262263bool264GNECreateEdgeFrame::EdgeTypeSelector::isAddBikelaneEnabled() const {265return (myAddBikelaneCheckButton->getCheck() == TRUE);266}267268269void270GNECreateEdgeFrame::EdgeTypeSelector::clearEdgeTypeSelected() {271myEdgeTypeSelected = nullptr;272myCurrentIndex--;273if (myCurrentIndex < 0) {274myCurrentIndex = 0;275}276}277278279void280GNECreateEdgeFrame::EdgeTypeSelector::setCurrentEdgeType(const GNEEdgeType* edgeType) {281for (int i = 0; i < myEdgeTypesComboBox->getNumItems(); i++) {282if (myEdgeTypesComboBox->getItemText(i) == edgeType->getID()) {283// set current item and index284myEdgeTypesComboBox->setCurrentItem(i);285myCurrentIndex = i;286// set buttons287myCreateDefaultEdgeType->setCheck(FALSE);288myCreateDefaultShortEdgeType->setCheck(FALSE);289myCreateCustomEdgeType->setCheck(TRUE);290// refresh291refreshEdgeTypeSelector();292}293}294}295296297void298GNECreateEdgeFrame::EdgeTypeSelector::useTemplate() {299myCreateDefaultEdgeType->setCheck(FALSE);300myCreateDefaultShortEdgeType->setCheck(FALSE);301myCreateCustomEdgeType->setCheck(TRUE);302refreshEdgeTypeSelector();303}304305306long307GNECreateEdgeFrame::EdgeTypeSelector::onCmdRadioButton(FXObject* obj, FXSelector, void*) {308// update radio buttons309if (obj == myCreateDefaultEdgeType) {310myCreateDefaultEdgeType->setCheck(TRUE);311myCreateDefaultShortEdgeType->setCheck(FALSE);312myCreateCustomEdgeType->setCheck(FALSE);313} else if (obj == myCreateDefaultShortEdgeType) {314myCreateDefaultEdgeType->setCheck(FALSE);315myCreateDefaultShortEdgeType->setCheck(TRUE);316myCreateCustomEdgeType->setCheck(FALSE);317} else {318myCreateDefaultEdgeType->setCheck(FALSE);319myCreateDefaultShortEdgeType->setCheck(FALSE);320myCreateCustomEdgeType->setCheck(TRUE);321}322// refresh template selector323refreshEdgeTypeSelector();324return 0;325}326327328long329GNECreateEdgeFrame::EdgeTypeSelector::onCmdAddEdgeType(FXObject*, FXSelector, void*) {330// create new edge type331auto net = myCreateEdgeFrameParent->getViewNet()->getNet();332GNEEdgeType* edgeType = new GNEEdgeType(net, net->getAttributeCarriers()->generateEdgeTypeID());333// add it using undoList334myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("create new edge type"));335myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, true), true);336myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();337// update myEdgeTypeSelected338myEdgeTypeSelected = edgeType;339// select last item340myCurrentIndex = (myEdgeTypesComboBox->getNumItems() - 1);341// refresh EdgeTypeSelector342refreshEdgeTypeSelector();343return 0;344}345346347long348GNECreateEdgeFrame::EdgeTypeSelector::onCmdDeleteEdgeType(FXObject*, FXSelector, void*) {349// first check if we have to reset myEdgeTypeSelected350if (myEdgeTypeSelected && (myEdgeTypeSelected->getID() == myEdgeTypesComboBox->getText().text())) {351myEdgeTypeSelected = nullptr;352}353// get edgeType to remove354GNEEdgeType* edgeType = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveEdgeType(myEdgeTypesComboBox->getText().text());355// remove it using undoList356myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("delete edge type"));357myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);358myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();359// refresh EdgeTypeSelector360refreshEdgeTypeSelector();361return 0;362}363364365long366GNECreateEdgeFrame::EdgeTypeSelector::onCmdSelectEdgeTypeOrTemplate(FXObject*, FXSelector, void*) {367// update current index368myCurrentIndex = myEdgeTypesComboBox->getCurrentItem();369// refresh edgeType selector370refreshEdgeTypeSelector();371return 0;372}373374375long376GNECreateEdgeFrame::EdgeTypeSelector::onCmdCreateFromTemplate(FXObject*, FXSelector, void*) {377if (myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate()) {378// create new edge type379auto net = myCreateEdgeFrameParent->getViewNet()->getNet();380GNEEdgeType* edgeType = new GNEEdgeType(net, net->getAttributeCarriers()->generateEdgeTypeID());381// copy all template values382edgeType->copyTemplate(myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate());383// add it using undoList384myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("create new edge type"));385myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, true), true);386myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();387// update myEdgeTypeSelected388myEdgeTypeSelected = edgeType;389// select last item390myCurrentIndex = (myEdgeTypesComboBox->getNumItems() - 1);391// refresh EdgeTypeSelector392refreshEdgeTypeSelector();393}394return 0;395}396397398long399GNECreateEdgeFrame::EdgeTypeSelector::onUpdCheckButtons(FXObject*, FXSelector, void*) {400if (myAddSidewalkCheckButton->getCheck() == TRUE) {401myNoPedestriansCheckButton->setCheck(TRUE);402myNoPedestriansCheckButton->disable();403} else {404myNoPedestriansCheckButton->enable();405}406// show default edgeType attributes again (for refresh sidewalk and bike widths)407myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myCreateEdgeFrameParent->getViewNet()->getNet()->getACTemplates()->getDefaultEdgeType(), true);408return 1;409}410411412void413GNECreateEdgeFrame::EdgeTypeSelector::fillComboBox() {414// get template editor415const GNEInspectorFrame::TemplateEditor* templateEditor = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor();416// get edge types417const auto& edgeTypes = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdgeTypes();418// clear edge types419myEdgeTypesComboBox->clearItems();420// set comboBox text color421myEdgeTypesComboBox->setTextColor(GUIDesignTextColorBlack);422// add template423if (templateEditor->getEdgeTemplate()) {424myEdgeTypesComboBox->appendIconItem((TL("template: ") + templateEditor->getEdgeTemplate()->getID()).c_str(), nullptr);425}426if (edgeTypes.size() > 0) {427// add edge types428for (const auto& edgeType : edgeTypes) {429myEdgeTypesComboBox->appendIconItem(edgeType.second->getID().c_str(), edgeType.second->getACIcon());430}431// set current item432if ((myCurrentIndex < 0) || (myCurrentIndex >= myEdgeTypesComboBox->getNumItems())) {433myCurrentIndex = myEdgeTypesComboBox->getNumItems() - 1;434}435myEdgeTypesComboBox->setCurrentItem(myCurrentIndex);436myEdgeTypesComboBox->enable();437} else {438myEdgeTypesComboBox->disable();439}440}441442// ---------------------------------------------------------------------------443// GNECreateEdgeFrame::LaneTypeSelector - methods444// ---------------------------------------------------------------------------445446GNECreateEdgeFrame::LaneTypeSelector::LaneTypeSelector(GNECreateEdgeFrame* createEdgeFrameParent) :447GNEGroupBoxModule(createEdgeFrameParent, TL("LaneType selector")),448myCreateEdgeFrameParent(createEdgeFrameParent),449myLaneIndex(0) {450// lane types combo box451myLaneTypesComboBox = new MFXComboBoxIcon(getCollapsableFrame(), createEdgeFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),452false, GUIDesignComboBoxVisibleItems, this, MID_GNE_CREATEEDGEFRAME_SELECTLANE, GUIDesignComboBoxAttribute);453// create horizontal frame454FXHorizontalFrame* horizontalFrameButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);455// create new lane type button456myAddLaneTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Add"), "", TL("Add lane type"), GUIIconSubSys::getIcon(GUIIcon::ADD),457this, MID_GNE_CREATEEDGEFRAME_ADD, GUIDesignButton);458// create delete lane type button459myDeleteLaneTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Delete"), "", TL("Delete lane type"), GUIIconSubSys::getIcon(GUIIcon::REMOVE),460this, MID_GNE_CREATEEDGEFRAME_DELETE, GUIDesignButton);461}462463464GNECreateEdgeFrame::LaneTypeSelector::~LaneTypeSelector() {465}466467468void469GNECreateEdgeFrame::LaneTypeSelector::showLaneTypeSelector() {470// start at first lane471myLaneIndex = 0;472// refresh laneTypeSelector473refreshLaneTypeSelector();474// show475show();476}477478479void480GNECreateEdgeFrame::LaneTypeSelector::hideLaneTypeSelector() {481// hide attributes creator module482myCreateEdgeFrameParent->myLaneTypeAttributesEditor->hideAttributesEditor();483// hide484hide();485}486487488void489GNECreateEdgeFrame::LaneTypeSelector::refreshLaneTypeSelector() {490// clear lane types491myLaneTypesComboBox->clearItems();492// first check if use template493if (myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {494const GNEEdgeTemplate* edgeTemplate = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate();495// fill comboBox496for (const auto& laneTemplate : edgeTemplate->getLaneTemplates()) {497myLaneTypesComboBox->appendIconItem(laneTemplate->getAttribute(SUMO_ATTR_ID).c_str(), laneTemplate->getACIcon());498}499// update comboBox500updateComboBox();501// show laneTypeAttributes502myCreateEdgeFrameParent->myLaneTypeAttributesEditor->showAttributesEditor(edgeTemplate->getLaneTemplates().at(myLaneIndex), false);503// disable laneAttributes (because is a template)504myCreateEdgeFrameParent->myLaneTypeAttributesEditor->disableAttributesEditor();505// disable add and remove buttons506myAddLaneTypeButton->disable();507myDeleteLaneTypeButton->disable();508} else {509// get edgeType510const GNEEdgeType* edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();511// fill comboBox512for (const auto& laneType : edgeType->getLaneTypes()) {513myLaneTypesComboBox->appendIconItem(laneType->getAttribute(SUMO_ATTR_ID).c_str(), laneType->getACIcon());514}515// update comboBox516updateComboBox();517// show laneTypeAttributes518myCreateEdgeFrameParent->myLaneTypeAttributesEditor->showAttributesEditor(edgeType->getLaneTypes().at(myLaneIndex), false);519// enable add and remove buttons520myAddLaneTypeButton->enable();521// check if enable or disable remove lane button522if (edgeType->getLaneTypes().size() > 1) {523myDeleteLaneTypeButton->enable();524} else {525myDeleteLaneTypeButton->disable();526}527}528// recalc529recalc();530}531532533long534GNECreateEdgeFrame::LaneTypeSelector::onCmdAddLaneType(FXObject*, FXSelector, void*) {535// check what edgeType is being edited536if (myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeType() ||537myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeTypeShort()) {538// add new lane in default edge type539auto edgeType = myCreateEdgeFrameParent->getViewNet()->getNet()->getACTemplates()->getDefaultEdgeType();540edgeType->addLaneType(new GNELaneType(edgeType));541// refresh laneTypeSelector542refreshLaneTypeSelector();543// set combo box544myLaneTypesComboBox->setCurrentItem(myLaneTypesComboBox->getNumItems() - 1);545} else if (!myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {546// get selected547const auto edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();548if (edgeType) {549// create new edgeType550GNEEdgeType* newEdgeType = new GNEEdgeType(edgeType);551// create laneTypes552for (const auto& laneType : edgeType->getLaneTypes()) {553newEdgeType->addLaneType(new GNELaneType(newEdgeType, laneType));554}555// add new lane556newEdgeType->addLaneType(new GNELaneType(newEdgeType));557// remove old edgeTyp und and newEdgeType558myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::LANETYPE, TL("add laneType"));559myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);560myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(newEdgeType, true), true);561myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();562// update index563myLaneIndex = myLaneTypesComboBox->getNumItems() - 1;564// set current edgeType in selector565myCreateEdgeFrameParent->myEdgeTypeSelector->setCurrentEdgeType(newEdgeType);566}567}568return 0;569}570571572long573GNECreateEdgeFrame::LaneTypeSelector::onCmdDeleteLaneType(FXObject*, FXSelector, void*) {574// check what edgeType is being edited575if (myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeType() ||576myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeTypeShort()) {577// add new lane in default edge type578myCreateEdgeFrameParent->getViewNet()->getNet()->getACTemplates()->getDefaultEdgeType()->removeLaneType(myLaneIndex);579// refresh laneTypeSelector580refreshLaneTypeSelector();581// set combo box582myLaneTypesComboBox->setCurrentItem(0);583} else if (!myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {584// get selected585const auto edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();586if (edgeType) {587// create new edgeType588GNEEdgeType* newEdgeType = new GNEEdgeType(edgeType);589// create laneTypes (except current)590for (int i = 0; i < (int)edgeType->getLaneTypes().size(); i++) {591if (i != myLaneIndex) {592newEdgeType->addLaneType(new GNELaneType(newEdgeType, edgeType->getLaneTypes().at(i)));593}594}595// remove old edgeTyp und and newEdgeType596myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::LANETYPE, TL("remove laneType"));597myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);598myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(newEdgeType, true), true);599myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();600// update index601myLaneIndex = myLaneTypesComboBox->getNumItems() - 1;602// set current edgeType in selector603myCreateEdgeFrameParent->myEdgeTypeSelector->setCurrentEdgeType(newEdgeType);604}605}606return 0;607}608609610long611GNECreateEdgeFrame::LaneTypeSelector::onCmdSelectLaneType(FXObject*, FXSelector, void*) {612// update index613myLaneIndex = myLaneTypesComboBox->getCurrentItem();614// refresh laneType selector615refreshLaneTypeSelector();616return 0;617}618619620void621GNECreateEdgeFrame::LaneTypeSelector::updateComboBox() {622// check lane index623if (myLaneIndex > myLaneTypesComboBox->getNumItems()) {624myLaneIndex = 0;625}626// set current item627myLaneTypesComboBox->setCurrentItem(myLaneIndex);628}629630// ---------------------------------------------------------------------------631// GNECreateEdgeFrame::Legend - methods632// ---------------------------------------------------------------------------633634GNECreateEdgeFrame::Legend::Legend(GNECreateEdgeFrame* createEdgeFrameParent) :635GNEGroupBoxModule(createEdgeFrameParent, TL("Information")) {636std::ostringstream information;637// add label for shift+click638information639<< "- " << TL("ESC:") << "\n"640<< " " << TL("Deselect origin") << "\n"641<< "- " << TL("Control+Click:") << "\n"642<< " " << TL("Move view") << "\n"643<< "- " << TL("Shift+Click:") << "\n"644<< " " << TL("Splits edge in both directions") << "\n"645<< "- " << TL("Alt+Shift+Click:") << "\n"646<< " " << TL("Splits edge in one direction");647// create label648new MFXDynamicLabel(getCollapsableFrame(), information.str().c_str(), 0, GUIDesignLabelFrameInformation);649}650651652GNECreateEdgeFrame::Legend::~Legend() {}653654// ---------------------------------------------------------------------------655// GNECreateEdgeFrame - methods656// ---------------------------------------------------------------------------657658GNECreateEdgeFrame::GNECreateEdgeFrame(GNEViewParent* viewParent, GNEViewNet* viewNet) :659GNEFrame(viewParent, viewNet, TL("Create Edge")),660myJunctionSource(nullptr) {661// create custom edge selector662myEdgeTypeSelector = new EdgeTypeSelector(this);663// Create edgeType parameters664myEdgeTypeAttributesEditor = new GNEAttributesEditor(this, GNEAttributesEditorType::EditorType::CREATOR);665// lane type selector666myLaneTypeSelector = new LaneTypeSelector(this);667// Create laneType parameters668myLaneTypeAttributesEditor = new GNEAttributesEditor(this, GNEAttributesEditorType::EditorType::CREATOR);669// create edge selector legend670myLegend = new Legend(this);671}672673674GNECreateEdgeFrame::~GNECreateEdgeFrame() {}675676677void678GNECreateEdgeFrame::processClick(const Position& clickedPosition, const GNEViewNetHelper::ViewObjectsSelector& viewObjects,679const bool oppositeEdge, const bool chainEdge) {680// first check if there is an edge template, an edge type (default or custom)681if (!myEdgeTypeSelector->useDefaultEdgeType() && !myEdgeTypeSelector->useDefaultEdgeTypeShort() &&682!myEdgeTypeSelector->useEdgeTemplate() && (myEdgeTypeSelector->getEdgeTypeSelected() == nullptr)) {683WRITE_WARNING(TL("Select either default edgeType or short edge or a custom edgeType or template"));684} else if (myEdgeTypeAttributesEditor->checkAttributes(true) && myLaneTypeAttributesEditor->checkAttributes(true)) {685// get edge type686auto edgeType = myViewNet->getNet()->getACTemplates()->getDefaultEdgeType();687// if grid is enabled and currently there isn't a junction under mouse, make a new search snapping position to grid688if ((viewObjects.getJunctionFront() == nullptr) && myViewNet->getVisualisationSettings().showGrid) {689myViewNet->updateObjectsInPosition(myViewNet->snapToActiveGrid(clickedPosition));690}691// obtain junction depending of gridEnabled692GNEJunction* junction = viewObjects.getJunctionFront();693// begin undo list694if (!myViewNet->getUndoList()->hasCommandGroup()) {695myViewNet->getUndoList()->begin(GUIIcon::EDGE, TL("create new edge"));696}697// if we didn't clicked over another junction, then create a new698if (junction == nullptr) {699junction = myViewNet->getNet()->createJunction(myViewNet->snapToActiveGrid(clickedPosition), myViewNet->getUndoList());700}701// now check if we have to create a new edge702if (myJunctionSource == nullptr) {703// check if create edge type short704if (myEdgeTypeSelector->useDefaultEdgeTypeShort()) {705// create new junction706auto newJunction = myViewNet->getNet()->createJunction(myViewNet->snapToActiveGrid(clickedPosition) + Position(5, 0), myViewNet->getUndoList());707// create new small edge708GNEEdge* newEdge = myViewNet->getNet()->createEdge(junction, newJunction, nullptr, myViewNet->getUndoList());709// set parameters710newEdge->copyEdgeType(edgeType, myViewNet->getUndoList());711// check pedestrians and sidewalks712if (myEdgeTypeSelector->isNoPedestriansEnabled()) {713disablePedestrians(newEdge);714}715// check if add bikelane716if (myEdgeTypeSelector->isAddBikelaneEnabled()) {717addBikelane(newEdge, edgeType->getAttribute(SUMO_ATTR_BIKELANEWIDTH));718}719// check if add sidewalk720if (myEdgeTypeSelector->isAddSidewalkEnabled()) {721addSidewalk(newEdge, edgeType->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));722}723// end undo list724if (myViewNet->getUndoList()->hasCommandGroup()) {725myViewNet->getUndoList()->end();726} else {727std::cout << "edge created without an open CommandGroup" << std::endl;728}729} else {730myJunctionSource = junction;731myJunctionSource->markAsCreateEdgeSource();732}733update();734} else {735// make sure that junctions source and destination are different736if (myJunctionSource != junction) {737// may fail to prevent double edges738GNEEdge* newEdge = myViewNet->getNet()->createEdge(myJunctionSource, junction, nullptr, myViewNet->getUndoList());739// check if edge was successfully created740if (newEdge) {741// set parameters742if (myEdgeTypeSelector->useEdgeTemplate()) {743newEdge->copyTemplate(myViewNet->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate(), myViewNet->getUndoList());744} else if (myEdgeTypeSelector->useDefaultEdgeType()) {745newEdge->copyEdgeType(edgeType, myViewNet->getUndoList());746// check pedestrians and sidewalks747if (myEdgeTypeSelector->isNoPedestriansEnabled()) {748disablePedestrians(newEdge);749}750// check if add bikelane751if (myEdgeTypeSelector->isAddBikelaneEnabled()) {752addBikelane(newEdge, edgeType->getAttribute(SUMO_ATTR_BIKELANEWIDTH));753}754// check if add sidewalk755if (myEdgeTypeSelector->isAddSidewalkEnabled()) {756addSidewalk(newEdge, edgeType->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));757}758} else {759newEdge->copyEdgeType(myEdgeTypeSelector->getEdgeTypeSelected(), myViewNet->getUndoList());760}761// create another edge, if create opposite edge is enabled762if (oppositeEdge && (myViewNet->getNet()->getAttributeCarriers()->retrieveEdges(junction, myJunctionSource).size() == 0)) {763GNEEdge* newOppositeEdge = myViewNet->getNet()->createEdge(junction, myJunctionSource, nullptr,764myViewNet->getUndoList(), "-" + newEdge->getNBEdge()->getID());765// set parameters766if (myEdgeTypeSelector->useEdgeTemplate()) {767newOppositeEdge->copyTemplate(myViewNet->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate(), myViewNet->getUndoList());768} else if (myEdgeTypeSelector->useDefaultEdgeType()) {769newOppositeEdge->copyEdgeType(edgeType, myViewNet->getUndoList());770// check pedestrians and sidewalks771if (myEdgeTypeSelector->isNoPedestriansEnabled()) {772disablePedestrians(newOppositeEdge);773}774// check if add bikelane775if (myEdgeTypeSelector->isAddBikelaneEnabled()) {776addBikelane(newOppositeEdge, edgeType->getAttribute(SUMO_ATTR_BIKELANEWIDTH));777}778// check if add sidewalk779if (myEdgeTypeSelector->isAddSidewalkEnabled()) {780addSidewalk(newOppositeEdge, edgeType->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));781}782} else {783newOppositeEdge->copyEdgeType(myEdgeTypeSelector->getEdgeTypeSelected(), myViewNet->getUndoList());784}785}786// edge created, then unmark as create edge source787myJunctionSource->unMarkAsCreateEdgeSource();788// end undo list789if (myViewNet->getUndoList()->hasCommandGroup()) {790myViewNet->getUndoList()->end();791} else {792std::cout << "edge created without an open CommandGroup" << std::endl;793}794// if we're creating edges in chain mode, mark junction as junction edge source795if (chainEdge) {796myJunctionSource = junction;797myJunctionSource->markAsCreateEdgeSource();798myViewNet->getUndoList()->begin(GUIIcon::EDGE, TL("create new edge"));799} else {800myJunctionSource = nullptr;801}802} else {803myViewNet->setStatusBarText(TL("An edge with the same geometry already exists!"));804}805} else {806myViewNet->setStatusBarText(TL("Start- and endpoint for an edge must be distinct!"));807}808update();809}810}811}812813814void815GNECreateEdgeFrame::abortEdgeCreation() {816// if myCreateEdgeSource exist, unmark ist as create edge source817if (myJunctionSource != nullptr) {818// remove current created edge source819myJunctionSource->unMarkAsCreateEdgeSource();820myJunctionSource = nullptr;821}822}823824825const GNEJunction*826GNECreateEdgeFrame::getJunctionSource() const {827return myJunctionSource;828}829830831void832GNECreateEdgeFrame::show() {833// refresh template selector834myEdgeTypeSelector->refreshEdgeTypeSelector();835// show frame836GNEFrame::show();837}838839840void841GNECreateEdgeFrame::hide() {842// hide frame843GNEFrame::hide();844}845846847GNECreateEdgeFrame::EdgeTypeSelector*848GNECreateEdgeFrame::getEdgeTypeSelector() const {849return myEdgeTypeSelector;850}851852853GNEAttributesEditor*854GNECreateEdgeFrame::getEdgeTypeAttributes() const {855return myEdgeTypeAttributesEditor;856}857858859GNECreateEdgeFrame::LaneTypeSelector*860GNECreateEdgeFrame::getLaneTypeSelector() {861return myLaneTypeSelector;862}863864865GNEAttributesEditor*866GNECreateEdgeFrame::getLaneTypeAttributes() const {867return myLaneTypeAttributesEditor;868}869870871void872GNECreateEdgeFrame::setUseEdgeTemplate() {873myEdgeTypeSelector->useTemplate();874myEdgeTypeSelector->refreshEdgeTypeSelector();875}876877878void879GNECreateEdgeFrame::disablePedestrians(GNEEdge* edge) const {880// iterate over lanes881for (const auto& lane : edge->getChildLanes()) {882// avoid sidewalks883if (lane->getAttribute(SUMO_ATTR_ALLOW) != "pedestrian") {884// extract disallow list885std::vector<std::string> disallowList = GNEAttributeCarrier::parse<std::vector<std::string> >(lane->getAttribute(SUMO_ATTR_DISALLOW));886// check if append pedestrian to disallow887if (std::find(disallowList.begin(), disallowList.end(), "pedestrian") == disallowList.end()) {888disallowList.push_back("pedestrian");889}890// update attribute891lane->setAttribute(SUMO_ATTR_DISALLOW, toString(disallowList), myViewNet->getUndoList());892}893}894}895896897void898GNECreateEdgeFrame::addBikelane(GNEEdge* edge, const std::string& bikelaneWidth) const {899bool bikelaneFound = false;900// iterate over lanes901for (const auto& lane : edge->getChildLanes()) {902// check if there is already a SideWalk903if (lane->getAttribute(SUMO_ATTR_ALLOW) == "bicycle") {904bikelaneFound = true;905}906}907// only add if previously there is no bikelanes908if (!bikelaneFound) {909edge->getNet()->getViewNet()->addRestrictedLane(edge->getChildLanes().at(0), SVC_BICYCLE, false);910// set width911if (bikelaneWidth != "default") {912edge->getChildLanes().at(0)->setAttribute(SUMO_ATTR_WIDTH, bikelaneWidth, myViewNet->getUndoList());913}914}915}916917918void919GNECreateEdgeFrame::addSidewalk(GNEEdge* edge, const std::string& sidewalkWidth) const {920bool sidewalkFound = false;921// iterate over lanes922for (const auto& lane : edge->getChildLanes()) {923// check if there is already a SideWalk924if (lane->getAttribute(SUMO_ATTR_ALLOW) == "pedestrian") {925sidewalkFound = true;926}927}928// only add if previously there is no Sidewalk929if (!sidewalkFound) {930edge->getNet()->getViewNet()->addRestrictedLane(edge->getChildLanes().at(0), SVC_PEDESTRIAN, false);931// set width932if (sidewalkWidth != "default") {933edge->getChildLanes().at(0)->setAttribute(SUMO_ATTR_WIDTH, sidewalkWidth, myViewNet->getUndoList());934}935}936}937938/****************************************************************************/939940941