Path: blob/main/src/netedit/frames/network/GNECreateEdgeFrame.cpp
169685 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 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, MFXGroupBoxModule, EdgeTypeSelectorMap, ARRAYNUMBER(EdgeTypeSelectorMap))58FXIMPLEMENT(GNECreateEdgeFrame::LaneTypeSelector, MFXGroupBoxModule, LaneTypeSelectorMap, ARRAYNUMBER(LaneTypeSelectorMap))596061// ===========================================================================62// method definitions63// ===========================================================================6465// ---------------------------------------------------------------------------66// GNECreateEdgeFrame::EdgeTypeSelector - methods67// ---------------------------------------------------------------------------6869GNECreateEdgeFrame::EdgeTypeSelector::EdgeTypeSelector(GNECreateEdgeFrame* createEdgeFrameParent) :70MFXGroupBoxModule(createEdgeFrameParent, TL("Template selector")),71myCreateEdgeFrameParent(createEdgeFrameParent),72myDefaultEdgeType(new GNEEdgeType(createEdgeFrameParent)),73myCurrentIndex(0) {74// default edge radio button75myCreateDefaultEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Create default edge"),76this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);77// default short radio button78myCreateDefaultShortEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Create default edge short"),79this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);80// checkboxes81myNoPedestriansCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Disallow for pedestrians"),82this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);83myAddSidewalkCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Add sidewalk"),84this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);85myAddBikelaneCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Add bikelane"),86this, MID_GNE_CREATEEDGEFRAME_CHECKBUTTON, GUIDesignCheckButton);87// use custom edge radio button88myCreateCustomEdgeType = new FXRadioButton(getCollapsableFrame(), TL("Use edgeType/template"),89this, MID_GNE_CREATEEDGEFRAME_SELECTRADIOBUTTON, GUIDesignRadioButton);90// edge types combo box91myEdgeTypesComboBox = new MFXComboBoxIcon(getCollapsableFrame(), createEdgeFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),92true, GUIDesignComboBoxVisibleItems, this, MID_GNE_CREATEEDGEFRAME_SELECTTEMPLATE, GUIDesignComboBoxAttribute);93// create horizontal frame94FXHorizontalFrame* horizontalFrameButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);95// create new edge type button96myAddEdgeTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Add"), "", TL("Add edge type"), GUIIconSubSys::getIcon(GUIIcon::ADD),97this, MID_GNE_CREATEEDGEFRAME_ADD, GUIDesignButton);98// create delete edge type button99myDeleteEdgeTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Delete"), "", TL("Delete edge type"), GUIIconSubSys::getIcon(GUIIcon::REMOVE),100this, MID_GNE_CREATEEDGEFRAME_DELETE, GUIDesignButton);101// create delete edge type button102myCreateFromTemplate = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Create from template"), "", TL("Create edgeType from template"), GUIIconSubSys::getIcon(GUIIcon::EDGE),103this, MID_GNE_CREATEEDGEFRAME_CREATEFROMTEMPLATE, GUIDesignButton);104// by default, create custom edge105myCreateDefaultEdgeType->setCheck(TRUE);106// check if enable disable pedestrians107for (const auto& junction : createEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getJunctions()) {108if (junction.second->getNBNode()->getCrossings().size() > 0) {109enableCheckBoxDisablePedestrians();110}111}112}113114115GNECreateEdgeFrame::EdgeTypeSelector::~EdgeTypeSelector() {116delete myDefaultEdgeType;117}118119120void121GNECreateEdgeFrame::EdgeTypeSelector::refreshEdgeTypeSelector() {122// get template editor123const GNEInspectorFrame::TemplateEditor* templateEditor = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor();124// get current item125const int index = myEdgeTypesComboBox->getCurrentItem();126// fill combo box127fillComboBox();128// continue depending of radio buttons129if (myCreateDefaultEdgeType->getCheck() || myCreateDefaultShortEdgeType->getCheck()) {130// enable check boxes131myAddSidewalkCheckButton->enable();132myAddBikelaneCheckButton->enable();133myNoPedestriansCheckButton->enable();134// disable create from template135myCreateFromTemplate->disable();136// disable comboBox137myEdgeTypesComboBox->disable();138// disable buttons139myAddEdgeTypeButton->disable();140myDeleteEdgeTypeButton->disable();141// show default edgeType attributes142myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myDefaultEdgeType, true);143// show lane attributes144myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();145} else if (myCreateCustomEdgeType->getCheck()) {146// disable check boxes147myAddSidewalkCheckButton->disable();148myAddBikelaneCheckButton->disable();149myNoPedestriansCheckButton->disable();150// enable buttons151myAddEdgeTypeButton->enable();152myDeleteEdgeTypeButton->enable();153// check conditions154if (myEdgeTypesComboBox->getNumItems() == 0) {155// disable comboBox and edgeType156myEdgeTypesComboBox->disable();157myDeleteEdgeTypeButton->disable();158// hide attributes creators159myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->hideAttributesEditor();160myCreateEdgeFrameParent->myLaneTypeAttributesEditor->hideAttributesEditor();161} else if (templateEditor->getEdgeTemplate() && (index == 0)) {162// enable create from template163myCreateFromTemplate->enable();164// enable comboBox165myEdgeTypesComboBox->enable();166// disable delete edge type button (because templates cannot be deleted)167myDeleteEdgeTypeButton->disable();168// show edgeType attributes and disable169myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(templateEditor->getEdgeTemplate(), true);170myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->disableAttributesEditor();171// show lane attributes (will be automatic disabled)172myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();173} else {174// disable create from template175myCreateFromTemplate->disable();176// enable comboBox177myEdgeTypesComboBox->enable();178// get edgeType179myEdgeTypeSelected = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveEdgeType(myEdgeTypesComboBox->getText().text(), false);180// check if exist181if (myEdgeTypeSelected) {182// show edgeType attributes183myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myEdgeTypeSelected, true);184// show lane attributes185myCreateEdgeFrameParent->myLaneTypeSelector->showLaneTypeSelector();186} else {187// hide edgeType attributes188myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->hideAttributesEditor();189// hide lane attributes190myCreateEdgeFrameParent->myLaneTypeSelector->hideLaneTypeSelector();191// set comboBox text192myEdgeTypesComboBox->setTextColor(GUIDesignTextColorRed);193}194}195}196// recalc197recalc();198}199200201void202GNECreateEdgeFrame::EdgeTypeSelector::updateIDinComboBox(const std::string& oldID, const std::string& newID) {203for (int i = 0; i < myEdgeTypesComboBox->getNumItems(); i++) {204if (myEdgeTypesComboBox->getItemText(i) == oldID) {205myEdgeTypesComboBox->updateIconItem(i, newID.c_str());206}207}208}209210211bool212GNECreateEdgeFrame::EdgeTypeSelector::useDefaultEdgeType() const {213return (myCreateDefaultEdgeType->getCheck() == TRUE);214}215216217bool218GNECreateEdgeFrame::EdgeTypeSelector::useDefaultEdgeTypeShort() const {219return (myCreateDefaultShortEdgeType->getCheck() == TRUE);220}221222223bool224GNECreateEdgeFrame::EdgeTypeSelector::useEdgeTemplate() const {225if (myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate()) {226if ((myCreateCustomEdgeType->getCheck() == TRUE) && (myEdgeTypesComboBox->getCurrentItem() == 0)) {227return true;228} else {229return false;230}231} else {232return false;233}234}235236237void238GNECreateEdgeFrame::EdgeTypeSelector::enableCheckBoxDisablePedestrians() {239myNoPedestriansCheckButton->setCheck(TRUE);240}241242243GNEEdgeType*244GNECreateEdgeFrame::EdgeTypeSelector::getDefaultEdgeType() const {245return myDefaultEdgeType;246}247248249GNEEdgeType*250GNECreateEdgeFrame::EdgeTypeSelector::getEdgeTypeSelected() const {251if ((myCreateDefaultEdgeType->getCheck() == TRUE) || (myCreateDefaultShortEdgeType->getCheck() == TRUE)) {252return myDefaultEdgeType;253} else {254return myEdgeTypeSelected;255}256}257258259bool260GNECreateEdgeFrame::EdgeTypeSelector::isNoPedestriansEnabled() const {261return (myNoPedestriansCheckButton->getCheck() == TRUE);262}263264265bool266GNECreateEdgeFrame::EdgeTypeSelector::isAddSidewalkEnabled() const {267return (myAddSidewalkCheckButton->getCheck() == TRUE);268}269270271bool272GNECreateEdgeFrame::EdgeTypeSelector::isAddBikelaneEnabled() const {273return (myAddBikelaneCheckButton->getCheck() == TRUE);274}275276277void278GNECreateEdgeFrame::EdgeTypeSelector::clearEdgeTypeSelected() {279myEdgeTypeSelected = nullptr;280myCurrentIndex--;281if (myCurrentIndex < 0) {282myCurrentIndex = 0;283}284}285286287void288GNECreateEdgeFrame::EdgeTypeSelector::setCurrentEdgeType(const GNEEdgeType* edgeType) {289for (int i = 0; i < myEdgeTypesComboBox->getNumItems(); i++) {290if (myEdgeTypesComboBox->getItemText(i) == edgeType->getID()) {291// set current item and index292myEdgeTypesComboBox->setCurrentItem(i);293myCurrentIndex = i;294// set buttons295myCreateDefaultEdgeType->setCheck(FALSE);296myCreateDefaultShortEdgeType->setCheck(FALSE);297myCreateCustomEdgeType->setCheck(TRUE);298// refresh299refreshEdgeTypeSelector();300}301}302}303304305void306GNECreateEdgeFrame::EdgeTypeSelector::useTemplate() {307myCreateDefaultEdgeType->setCheck(FALSE);308myCreateDefaultShortEdgeType->setCheck(FALSE);309myCreateCustomEdgeType->setCheck(TRUE);310refreshEdgeTypeSelector();311}312313314long315GNECreateEdgeFrame::EdgeTypeSelector::onCmdRadioButton(FXObject* obj, FXSelector, void*) {316// update radio buttons317if (obj == myCreateDefaultEdgeType) {318myCreateDefaultEdgeType->setCheck(TRUE);319myCreateDefaultShortEdgeType->setCheck(FALSE);320myCreateCustomEdgeType->setCheck(FALSE);321} else if (obj == myCreateDefaultShortEdgeType) {322myCreateDefaultEdgeType->setCheck(FALSE);323myCreateDefaultShortEdgeType->setCheck(TRUE);324myCreateCustomEdgeType->setCheck(FALSE);325} else {326myCreateDefaultEdgeType->setCheck(FALSE);327myCreateDefaultShortEdgeType->setCheck(FALSE);328myCreateCustomEdgeType->setCheck(TRUE);329}330// refresh template selector331refreshEdgeTypeSelector();332return 0;333}334335336long337GNECreateEdgeFrame::EdgeTypeSelector::onCmdAddEdgeType(FXObject*, FXSelector, void*) {338// create new edge type339GNEEdgeType* edgeType = new GNEEdgeType(myCreateEdgeFrameParent->getViewNet()->getNet());340// add it using undoList341myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("create new edge type"));342myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, true), true);343myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();344// update myEdgeTypeSelected345myEdgeTypeSelected = edgeType;346// select last item347myCurrentIndex = (myEdgeTypesComboBox->getNumItems() - 1);348// refresh EdgeTypeSelector349refreshEdgeTypeSelector();350return 0;351}352353354long355GNECreateEdgeFrame::EdgeTypeSelector::onCmdDeleteEdgeType(FXObject*, FXSelector, void*) {356// first check if we have to reset myEdgeTypeSelected357if (myEdgeTypeSelected && (myEdgeTypeSelected->getID() == myEdgeTypesComboBox->getText().text())) {358myEdgeTypeSelected = nullptr;359}360// get edgeType to remove361GNEEdgeType* edgeType = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveEdgeType(myEdgeTypesComboBox->getText().text());362// remove it using undoList363myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("delete edge type"));364myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);365myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();366// refresh EdgeTypeSelector367refreshEdgeTypeSelector();368return 0;369}370371372long373GNECreateEdgeFrame::EdgeTypeSelector::onCmdSelectEdgeTypeOrTemplate(FXObject*, FXSelector, void*) {374// update current index375myCurrentIndex = myEdgeTypesComboBox->getCurrentItem();376// refresh edgeType selector377refreshEdgeTypeSelector();378return 0;379}380381382long383GNECreateEdgeFrame::EdgeTypeSelector::onCmdCreateFromTemplate(FXObject*, FXSelector, void*) {384if (myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate()) {385// create new edge type386GNEEdgeType* edgeType = new GNEEdgeType(myCreateEdgeFrameParent->getViewNet()->getNet());387// copy all template values388edgeType->copyTemplate(myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate());389// add it using undoList390myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(edgeType, TL("create new edge type"));391myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, true), true);392myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();393// update myEdgeTypeSelected394myEdgeTypeSelected = edgeType;395// select last item396myCurrentIndex = (myEdgeTypesComboBox->getNumItems() - 1);397// refresh EdgeTypeSelector398refreshEdgeTypeSelector();399}400return 0;401}402403404long405GNECreateEdgeFrame::EdgeTypeSelector::onUpdCheckButtons(FXObject*, FXSelector, void*) {406if (myAddSidewalkCheckButton->getCheck() == TRUE) {407myNoPedestriansCheckButton->setCheck(TRUE);408myNoPedestriansCheckButton->disable();409} else {410myNoPedestriansCheckButton->enable();411}412// show default edgeType attributes again (for refresh sidewalk and bike widths)413myCreateEdgeFrameParent->myEdgeTypeAttributesEditor->showAttributesEditor(myDefaultEdgeType, true);414return 1;415}416417418void419GNECreateEdgeFrame::EdgeTypeSelector::fillComboBox() {420// get template editor421const GNEInspectorFrame::TemplateEditor* templateEditor = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor();422// get edge types423const auto& edgeTypes = myCreateEdgeFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdgeTypes();424// clear edge types425myEdgeTypesComboBox->clearItems();426// set comboBox text color427myEdgeTypesComboBox->setTextColor(GUIDesignTextColorBlack);428// add template429if (templateEditor->getEdgeTemplate()) {430myEdgeTypesComboBox->appendIconItem((TL("template: ") + templateEditor->getEdgeTemplate()->getID()).c_str(), nullptr);431}432if (edgeTypes.size() > 0) {433// add edge types434for (const auto& edgeType : edgeTypes) {435myEdgeTypesComboBox->appendIconItem(edgeType.second->getID().c_str(), edgeType.second->getACIcon());436}437// set current item438if ((myCurrentIndex < 0) || (myCurrentIndex >= myEdgeTypesComboBox->getNumItems())) {439myCurrentIndex = myEdgeTypesComboBox->getNumItems() - 1;440}441myEdgeTypesComboBox->setCurrentItem(myCurrentIndex);442myEdgeTypesComboBox->enable();443} else {444myEdgeTypesComboBox->disable();445}446}447448// ---------------------------------------------------------------------------449// GNECreateEdgeFrame::LaneTypeSelector - methods450// ---------------------------------------------------------------------------451452GNECreateEdgeFrame::LaneTypeSelector::LaneTypeSelector(GNECreateEdgeFrame* createEdgeFrameParent) :453MFXGroupBoxModule(createEdgeFrameParent, TL("LaneType selector")),454myCreateEdgeFrameParent(createEdgeFrameParent),455myLaneIndex(0) {456// lane types combo box457myLaneTypesComboBox = new MFXComboBoxIcon(getCollapsableFrame(), createEdgeFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu(),458false, GUIDesignComboBoxVisibleItems, this, MID_GNE_CREATEEDGEFRAME_SELECTLANE, GUIDesignComboBoxAttribute);459// create horizontal frame460FXHorizontalFrame* horizontalFrameButtons = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);461// create new lane type button462myAddLaneTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Add"), "", TL("Add lane type"), GUIIconSubSys::getIcon(GUIIcon::ADD),463this, MID_GNE_CREATEEDGEFRAME_ADD, GUIDesignButton);464// create delete lane type button465myDeleteLaneTypeButton = GUIDesigns::buildFXButton(horizontalFrameButtons, TL("Delete"), "", TL("Delete lane type"), GUIIconSubSys::getIcon(GUIIcon::REMOVE),466this, MID_GNE_CREATEEDGEFRAME_DELETE, GUIDesignButton);467}468469470GNECreateEdgeFrame::LaneTypeSelector::~LaneTypeSelector() {471}472473474void475GNECreateEdgeFrame::LaneTypeSelector::showLaneTypeSelector() {476// start at first lane477myLaneIndex = 0;478// refresh laneTypeSelector479refreshLaneTypeSelector();480// show481show();482}483484485void486GNECreateEdgeFrame::LaneTypeSelector::hideLaneTypeSelector() {487// hide attributes creator module488myCreateEdgeFrameParent->myLaneTypeAttributesEditor->hideAttributesEditor();489// hide490hide();491}492493494void495GNECreateEdgeFrame::LaneTypeSelector::refreshLaneTypeSelector() {496// clear lane types497myLaneTypesComboBox->clearItems();498// first check if use template499if (myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {500const GNEEdgeTemplate* edgeTemplate = myCreateEdgeFrameParent->getViewNet()->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate();501// fill comboBox502for (const auto& laneTemplate : edgeTemplate->getLaneTemplates()) {503myLaneTypesComboBox->appendIconItem(laneTemplate->getAttribute(SUMO_ATTR_ID).c_str(), laneTemplate->getACIcon());504}505// update comboBox506updateComboBox();507// show laneTypeAttributes508myCreateEdgeFrameParent->myLaneTypeAttributesEditor->showAttributesEditor(edgeTemplate->getLaneTemplates().at(myLaneIndex), false);509// disable laneAttributes (because is a template)510myCreateEdgeFrameParent->myLaneTypeAttributesEditor->disableAttributesEditor();511// disable add and remove buttons512myAddLaneTypeButton->disable();513myDeleteLaneTypeButton->disable();514} else {515// get edgeType516const GNEEdgeType* edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();517// fill comboBox518for (const auto& laneType : edgeType->getLaneTypes()) {519myLaneTypesComboBox->appendIconItem(laneType->getAttribute(SUMO_ATTR_ID).c_str(), laneType->getACIcon());520}521// update comboBox522updateComboBox();523// show laneTypeAttributes524myCreateEdgeFrameParent->myLaneTypeAttributesEditor->showAttributesEditor(edgeType->getLaneTypes().at(myLaneIndex), false);525// enable add and remove buttons526myAddLaneTypeButton->enable();527// check if enable or disable remove lane button528if (edgeType->getLaneTypes().size() > 1) {529myDeleteLaneTypeButton->enable();530} else {531myDeleteLaneTypeButton->disable();532}533}534// recalc535recalc();536}537538539long540GNECreateEdgeFrame::LaneTypeSelector::onCmdAddLaneType(FXObject*, FXSelector, void*) {541// check what edgeType is being edited542if (myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeType() ||543myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeTypeShort()) {544// add new lane in default edge type545myCreateEdgeFrameParent->myEdgeTypeSelector->getDefaultEdgeType()->addLaneType(new GNELaneType(myCreateEdgeFrameParent->myEdgeTypeSelector->getDefaultEdgeType()));546// refresh laneTypeSelector547refreshLaneTypeSelector();548// set combo box549myLaneTypesComboBox->setCurrentItem(myLaneTypesComboBox->getNumItems() - 1);550} else if (!myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {551// get selected552const auto edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();553if (edgeType) {554// create new edgeType555GNEEdgeType* newEdgeType = new GNEEdgeType(edgeType);556// create laneTypes557for (const auto& laneType : edgeType->getLaneTypes()) {558newEdgeType->addLaneType(new GNELaneType(newEdgeType, laneType));559}560// add new lane561newEdgeType->addLaneType(new GNELaneType(newEdgeType));562// remove old edgeTyp und and newEdgeType563myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::LANETYPE, TL("add laneType"));564myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);565myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(newEdgeType, true), true);566myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();567// update index568myLaneIndex = myLaneTypesComboBox->getNumItems() - 1;569// set current edgeType in selector570myCreateEdgeFrameParent->myEdgeTypeSelector->setCurrentEdgeType(newEdgeType);571}572}573return 0;574}575576577long578GNECreateEdgeFrame::LaneTypeSelector::onCmdDeleteLaneType(FXObject*, FXSelector, void*) {579// check what edgeType is being edited580if (myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeType() ||581myCreateEdgeFrameParent->myEdgeTypeSelector->useDefaultEdgeTypeShort()) {582// add new lane in default edge type583myCreateEdgeFrameParent->myEdgeTypeSelector->getDefaultEdgeType()->removeLaneType(myLaneIndex);584// refresh laneTypeSelector585refreshLaneTypeSelector();586// set combo box587myLaneTypesComboBox->setCurrentItem(0);588} else if (!myCreateEdgeFrameParent->myEdgeTypeSelector->useEdgeTemplate()) {589// get selected590const auto edgeType = myCreateEdgeFrameParent->myEdgeTypeSelector->getEdgeTypeSelected();591if (edgeType) {592// create new edgeType593GNEEdgeType* newEdgeType = new GNEEdgeType(edgeType);594// create laneTypes (except current)595for (int i = 0; i < (int)edgeType->getLaneTypes().size(); i++) {596if (i != myLaneIndex) {597newEdgeType->addLaneType(new GNELaneType(newEdgeType, edgeType->getLaneTypes().at(i)));598}599}600// remove old edgeTyp und and newEdgeType601myCreateEdgeFrameParent->getViewNet()->getUndoList()->begin(GUIIcon::LANETYPE, TL("remove laneType"));602myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(edgeType, false), true);603myCreateEdgeFrameParent->getViewNet()->getUndoList()->add(new GNEChange_EdgeType(newEdgeType, true), true);604myCreateEdgeFrameParent->getViewNet()->getUndoList()->end();605// update index606myLaneIndex = myLaneTypesComboBox->getNumItems() - 1;607// set current edgeType in selector608myCreateEdgeFrameParent->myEdgeTypeSelector->setCurrentEdgeType(newEdgeType);609}610}611return 0;612}613614615long616GNECreateEdgeFrame::LaneTypeSelector::onCmdSelectLaneType(FXObject*, FXSelector, void*) {617// update index618myLaneIndex = myLaneTypesComboBox->getCurrentItem();619// refresh laneType selector620refreshLaneTypeSelector();621return 0;622}623624625void626GNECreateEdgeFrame::LaneTypeSelector::updateComboBox() {627// check lane index628if (myLaneIndex > myLaneTypesComboBox->getNumItems()) {629myLaneIndex = 0;630}631// set current item632myLaneTypesComboBox->setCurrentItem(myLaneIndex);633}634635// ---------------------------------------------------------------------------636// GNECreateEdgeFrame::Legend - methods637// ---------------------------------------------------------------------------638639GNECreateEdgeFrame::Legend::Legend(GNECreateEdgeFrame* createEdgeFrameParent) :640MFXGroupBoxModule(createEdgeFrameParent, TL("Information")) {641std::ostringstream information;642// add label for shift+click643information644<< "- " << TL("ESC:") << "\n"645<< " " << TL("Deselect origin") << "\n"646<< "- " << TL("Control+Click:") << "\n"647<< " " << TL("Move view") << "\n"648<< "- " << TL("Shift+Click:") << "\n"649<< " " << TL("Splits edge in both directions") << "\n"650<< "- " << TL("Alt+Shift+Click:") << "\n"651<< " " << TL("Splits edge in one direction");652// create label653new MFXDynamicLabel(getCollapsableFrame(), information.str().c_str(), 0, GUIDesignLabelFrameInformation);654}655656657GNECreateEdgeFrame::Legend::~Legend() {}658659// ---------------------------------------------------------------------------660// GNECreateEdgeFrame - methods661// ---------------------------------------------------------------------------662663GNECreateEdgeFrame::GNECreateEdgeFrame(GNEViewParent* viewParent, GNEViewNet* viewNet) :664GNEFrame(viewParent, viewNet, TL("Create Edge")),665myJunctionSource(nullptr) {666// create custom edge selector667myEdgeTypeSelector = new EdgeTypeSelector(this);668// Create edgeType parameters669myEdgeTypeAttributesEditor = new GNEAttributesEditor(this, GNEAttributesEditorType::EditorType::CREATOR);670// lane type selector671myLaneTypeSelector = new LaneTypeSelector(this);672// Create laneType parameters673myLaneTypeAttributesEditor = new GNEAttributesEditor(this, GNEAttributesEditorType::EditorType::CREATOR);674// create edge selector legend675myLegend = new Legend(this);676}677678679GNECreateEdgeFrame::~GNECreateEdgeFrame() {}680681682void683GNECreateEdgeFrame::processClick(const Position& clickedPosition, const GNEViewNetHelper::ViewObjectsSelector& viewObjects,684const bool oppositeEdge, const bool chainEdge) {685// first check if there is an edge template, an edge type (default or custom)686if (!myEdgeTypeSelector->useDefaultEdgeType() && !myEdgeTypeSelector->useDefaultEdgeTypeShort() &&687!myEdgeTypeSelector->useEdgeTemplate() && (myEdgeTypeSelector->getEdgeTypeSelected() == nullptr)) {688WRITE_WARNING(TL("Select either default edgeType or short edge or a custom edgeType or template"));689} else if (myEdgeTypeAttributesEditor->checkAttributes(true) && myLaneTypeAttributesEditor->checkAttributes(true)) {690// if grid is enabled and currently there isn't a junction under mouse, make a new search snapping position to grid691if ((viewObjects.getJunctionFront() == nullptr) && myViewNet->getVisualisationSettings().showGrid) {692myViewNet->updateObjectsInPosition(myViewNet->snapToActiveGrid(clickedPosition));693}694// obtain junction depending of gridEnabled695GNEJunction* junction = viewObjects.getJunctionFront();696// begin undo list697if (!myViewNet->getUndoList()->hasCommandGroup()) {698myViewNet->getUndoList()->begin(GUIIcon::EDGE, TL("create new edge"));699}700// if we didn't clicked over another junction, then create a new701if (junction == nullptr) {702junction = myViewNet->getNet()->createJunction(myViewNet->snapToActiveGrid(clickedPosition), myViewNet->getUndoList());703}704// now check if we have to create a new edge705if (myJunctionSource == nullptr) {706// check if create edge type short707if (myEdgeTypeSelector->useDefaultEdgeTypeShort()) {708// create new junction709auto newJunction = myViewNet->getNet()->createJunction(myViewNet->snapToActiveGrid(clickedPosition) + Position(5, 0), myViewNet->getUndoList());710// create new small edge711GNEEdge* newEdge = myViewNet->getNet()->createEdge(junction, newJunction, nullptr, myViewNet->getUndoList());712// set parameters713newEdge->copyEdgeType(myEdgeTypeSelector->getDefaultEdgeType(), myViewNet->getUndoList());714// check pedestrians and sidewalks715if (myEdgeTypeSelector->isNoPedestriansEnabled()) {716disablePedestrians(newEdge);717}718// check if add bikelane719if (myEdgeTypeSelector->isAddBikelaneEnabled()) {720addBikelane(newEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_BIKELANEWIDTH));721}722// check if add sidewalk723if (myEdgeTypeSelector->isAddSidewalkEnabled()) {724addSidewalk(newEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));725}726// end undo list727if (myViewNet->getUndoList()->hasCommandGroup()) {728myViewNet->getUndoList()->end();729} else {730std::cout << "edge created without an open CommandGroup" << std::endl;731}732} else {733myJunctionSource = junction;734myJunctionSource->markAsCreateEdgeSource();735}736update();737} else {738// make sure that junctions source and destination are different739if (myJunctionSource != junction) {740// may fail to prevent double edges741GNEEdge* newEdge = myViewNet->getNet()->createEdge(myJunctionSource, junction, nullptr, myViewNet->getUndoList());742// check if edge was successfully created743if (newEdge) {744// set parameters745if (myEdgeTypeSelector->useEdgeTemplate()) {746newEdge->copyTemplate(myViewNet->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate(), myViewNet->getUndoList());747} else if (myEdgeTypeSelector->useDefaultEdgeType()) {748newEdge->copyEdgeType(myEdgeTypeSelector->getDefaultEdgeType(), myViewNet->getUndoList());749// check pedestrians and sidewalks750if (myEdgeTypeSelector->isNoPedestriansEnabled()) {751disablePedestrians(newEdge);752}753// check if add bikelane754if (myEdgeTypeSelector->isAddBikelaneEnabled()) {755addBikelane(newEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_BIKELANEWIDTH));756}757// check if add sidewalk758if (myEdgeTypeSelector->isAddSidewalkEnabled()) {759addSidewalk(newEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));760}761} else {762newEdge->copyEdgeType(myEdgeTypeSelector->getEdgeTypeSelected(), myViewNet->getUndoList());763}764// create another edge, if create opposite edge is enabled765if (oppositeEdge && (myViewNet->getNet()->getAttributeCarriers()->retrieveEdges(junction, myJunctionSource).size() == 0)) {766GNEEdge* newOppositeEdge = myViewNet->getNet()->createEdge(junction, myJunctionSource, nullptr,767myViewNet->getUndoList(), "-" + newEdge->getNBEdge()->getID());768// set parameters769if (myEdgeTypeSelector->useEdgeTemplate()) {770newOppositeEdge->copyTemplate(myViewNet->getViewParent()->getInspectorFrame()->getTemplateEditor()->getEdgeTemplate(), myViewNet->getUndoList());771} else if (myEdgeTypeSelector->useDefaultEdgeType()) {772newOppositeEdge->copyEdgeType(myEdgeTypeSelector->getDefaultEdgeType(), myViewNet->getUndoList());773// check pedestrians and sidewalks774if (myEdgeTypeSelector->isNoPedestriansEnabled()) {775disablePedestrians(newOppositeEdge);776}777// check if add bikelane778if (myEdgeTypeSelector->isAddBikelaneEnabled()) {779addBikelane(newOppositeEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_BIKELANEWIDTH));780}781// check if add sidewalk782if (myEdgeTypeSelector->isAddSidewalkEnabled()) {783addSidewalk(newOppositeEdge, myEdgeTypeSelector->getDefaultEdgeType()->getAttribute(SUMO_ATTR_SIDEWALKWIDTH));784}785} else {786newOppositeEdge->copyEdgeType(myEdgeTypeSelector->getEdgeTypeSelected(), myViewNet->getUndoList());787}788}789// edge created, then unmark as create edge source790myJunctionSource->unMarkAsCreateEdgeSource();791// end undo list792if (myViewNet->getUndoList()->hasCommandGroup()) {793myViewNet->getUndoList()->end();794} else {795std::cout << "edge created without an open CommandGroup" << std::endl;796}797// if we're creating edges in chain mode, mark junction as junction edge source798if (chainEdge) {799myJunctionSource = junction;800myJunctionSource->markAsCreateEdgeSource();801myViewNet->getUndoList()->begin(GUIIcon::EDGE, TL("create new edge"));802} else {803myJunctionSource = nullptr;804}805} else {806myViewNet->setStatusBarText(TL("An edge with the same geometry already exists!"));807}808} else {809myViewNet->setStatusBarText(TL("Start- and endpoint for an edge must be distinct!"));810}811update();812}813}814}815816817void818GNECreateEdgeFrame::abortEdgeCreation() {819// if myCreateEdgeSource exist, unmark ist as create edge source820if (myJunctionSource != nullptr) {821// remove current created edge source822myJunctionSource->unMarkAsCreateEdgeSource();823myJunctionSource = nullptr;824}825}826827828const GNEJunction*829GNECreateEdgeFrame::getJunctionSource() const {830return myJunctionSource;831}832833834void835GNECreateEdgeFrame::show() {836// refresh template selector837myEdgeTypeSelector->refreshEdgeTypeSelector();838// show frame839GNEFrame::show();840}841842843void844GNECreateEdgeFrame::hide() {845// hide frame846GNEFrame::hide();847}848849850GNECreateEdgeFrame::EdgeTypeSelector*851GNECreateEdgeFrame::getEdgeTypeSelector() const {852return myEdgeTypeSelector;853}854855856GNEAttributesEditor*857GNECreateEdgeFrame::getEdgeTypeAttributes() const {858return myEdgeTypeAttributesEditor;859}860861862GNECreateEdgeFrame::LaneTypeSelector*863GNECreateEdgeFrame::getLaneTypeSelector() {864return myLaneTypeSelector;865}866867868GNEAttributesEditor*869GNECreateEdgeFrame::getLaneTypeAttributes() const {870return myLaneTypeAttributesEditor;871}872873874void875GNECreateEdgeFrame::setUseEdgeTemplate() {876myEdgeTypeSelector->useTemplate();877myEdgeTypeSelector->refreshEdgeTypeSelector();878}879880881void882GNECreateEdgeFrame::disablePedestrians(GNEEdge* edge) const {883// iterate over lanes884for (const auto& lane : edge->getChildLanes()) {885// avoid sidewalks886if (lane->getAttribute(SUMO_ATTR_ALLOW) != "pedestrian") {887// extract disallow list888std::vector<std::string> disallowList = GNEAttributeCarrier::parse<std::vector<std::string> >(lane->getAttribute(SUMO_ATTR_DISALLOW));889// check if append pedestrian to disallow890if (std::find(disallowList.begin(), disallowList.end(), "pedestrian") == disallowList.end()) {891disallowList.push_back("pedestrian");892}893// update attribute894lane->setAttribute(SUMO_ATTR_DISALLOW, toString(disallowList), myViewNet->getUndoList());895}896}897}898899900void901GNECreateEdgeFrame::addBikelane(GNEEdge* edge, const std::string& bikelaneWidth) const {902bool bikelaneFound = false;903// iterate over lanes904for (const auto& lane : edge->getChildLanes()) {905// check if there is already a SideWalk906if (lane->getAttribute(SUMO_ATTR_ALLOW) == "bicycle") {907bikelaneFound = true;908}909}910// only add if previously there is no bikelanes911if (!bikelaneFound) {912edge->getNet()->getViewNet()->addRestrictedLane(edge->getChildLanes().at(0), SVC_BICYCLE, false);913// set width914if (bikelaneWidth != "default") {915edge->getChildLanes().at(0)->setAttribute(SUMO_ATTR_WIDTH, bikelaneWidth, myViewNet->getUndoList());916}917}918}919920921void922GNECreateEdgeFrame::addSidewalk(GNEEdge* edge, const std::string& sidewalkWidth) const {923bool sidewalkFound = false;924// iterate over lanes925for (const auto& lane : edge->getChildLanes()) {926// check if there is already a SideWalk927if (lane->getAttribute(SUMO_ATTR_ALLOW) == "pedestrian") {928sidewalkFound = true;929}930}931// only add if previously there is no Sidewalk932if (!sidewalkFound) {933edge->getNet()->getViewNet()->addRestrictedLane(edge->getChildLanes().at(0), SVC_PEDESTRIAN, false);934// set width935if (sidewalkWidth != "default") {936edge->getChildLanes().at(0)->setAttribute(SUMO_ATTR_WIDTH, sidewalkWidth, myViewNet->getUndoList());937}938}939}940941/****************************************************************************/942943944