Path: blob/main/src/netedit/dialogs/GNEVClassesDialog.cpp
169678 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 GNEVClassesDialog.cpp14/// @author Pablo Alvarez Lopez15/// @date April 201616///17// Dialog for edit allow VClass attribute18/****************************************************************************/1920#include <netedit/GNEApplicationWindow.h>21#include <utils/common/MsgHandler.h>22#include <utils/common/StringTokenizer.h>23#include <utils/gui/div/GUIDesigns.h>2425#include "GNEVClassesDialog.h"2627// ===========================================================================28// FOX callback mapping29// ===========================================================================3031FXDEFMAP(GNEVClassesDialog::VClassRow) VClassRowMap[] = {32FXMAPFUNC(SEL_COMMAND, MID_GNE_ALLOWVCLASSES_TOGGLE, GNEVClassesDialog::VClassRow::onCmdToggleVClass),33};3435FXDEFMAP(GNEVClassesDialog) GNEVClassesDialogMap[] = {36FXMAPFUNC(SEL_COMMAND, MID_GNE_ALLOWVCLASSES_SELECTALL, GNEVClassesDialog::onCmdSelectAll),37FXMAPFUNC(SEL_COMMAND, MID_GNE_ALLOWVCLASSES_UNSELECTALL, GNEVClassesDialog::onCmdUnselectAll),38FXMAPFUNC(SEL_COMMAND, MID_GNE_ALLOWVCLASSES_ONLY_ROAD, GNEVClassesDialog::onCmdSelectOnlyRoad),39FXMAPFUNC(SEL_COMMAND, MID_GNE_ALLOWVCLASSES_ONLY_RAIL, GNEVClassesDialog::onCmdSelectOnlyRail),40};4142// Object implementation43FXIMPLEMENT(GNEVClassesDialog::VClassRow, FXHorizontalFrame, VClassRowMap, ARRAYNUMBER(VClassRowMap))44FXIMPLEMENT(GNEVClassesDialog, GNEDialog, GNEVClassesDialogMap, ARRAYNUMBER(GNEVClassesDialogMap))4546// ===========================================================================47// member method definitions48// ===========================================================================4950// ---------------------------------------------------------------------------51// GNEVClassesDialog::VClassRow - methods52// ---------------------------------------------------------------------------5354GNEVClassesDialog::VClassRow::VClassRow(FXVerticalFrame* contentsFrame, SUMOVehicleClass vClass,55GUIIcon vClassIcon, const std::string& description) :56FXHorizontalFrame(contentsFrame, GUIDesignAuxiliarHorizontalFrame),57myVClassString(getVehicleClassNames(vClass)) {58// add frame for vehicle icons59FXLabel* labelVehicleIcon = new FXLabel(this, "", GUIIconSubSys::getIcon(vClassIcon), GUIDesignLabelIcon64x32Thicked);60labelVehicleIcon->setBackColor(FXRGBA(255, 255, 255, 255));61// create frame for information and button62FXVerticalFrame* buttonAndInformationFrame = new FXVerticalFrame(this, GUIDesignAuxiliarHorizontalFrame);63FXHorizontalFrame* buttonAndStatusFrame = new FXHorizontalFrame(buttonAndInformationFrame, GUIDesignAuxiliarHorizontalFrame);64// create button for enable/disable vehicle class65myVClassButton = GUIDesigns::buildFXButton(buttonAndStatusFrame, "", "", "", GUIIconSubSys::getIcon(GUIIcon::EMPTY),66this, MID_GNE_ALLOWVCLASSES_TOGGLE, GUIDesignButtonIcon);67// create label for vehicle class name68new FXLabel(buttonAndStatusFrame, myVClassString.c_str(), nullptr, GUIDesignLabelThick(JUSTIFY_LEFT));69// create label for description of vehicle70new FXLabel(buttonAndInformationFrame, description.c_str(), nullptr, GUIDesignLabelThick(JUSTIFY_LEFT));71}727374GNEVClassesDialog::VClassRow::~VClassRow() {7576}777879const std::string&80GNEVClassesDialog::VClassRow::getVClassString() const {81return myVClassString;82}838485void86GNEVClassesDialog::VClassRow::setVClassButtonStatus(const bool enabled) {87if (enabled) {88myVClassButton->setIcon(GUIIconSubSys::getIcon(GUIIcon::ACCEPT));89} else {90myVClassButton->setIcon(GUIIconSubSys::getIcon(GUIIcon::CANCEL));91}92}939495bool96GNEVClassesDialog::VClassRow::isVClassButtonEnabled() const {97return (myVClassButton->getIcon() == GUIIconSubSys::getIcon(GUIIcon::ACCEPT));98}99100101long102GNEVClassesDialog::VClassRow::onCmdToggleVClass(FXObject*, FXSelector, void*) {103if (myVClassButton->getIcon() == GUIIconSubSys::getIcon(GUIIcon::ACCEPT)) {104setVClassButtonStatus(false);105} else {106setVClassButtonStatus(true);107}108return 1;109}110111// ---------------------------------------------------------------------------112// GNEVClassesDialog - methods113// ---------------------------------------------------------------------------114115GNEVClassesDialog::GNEVClassesDialog(GNEApplicationWindow* mainWindow, SumoXMLAttr attr,116const std::string originalVClasses) :117GNEDialog(mainWindow, TLF("Edit vClasses of attribute '%'", toString(attr)), GUIIcon::GREENVEHICLE,118DialogType::VCLASS, GNEDialog::Buttons::ACCEPT_CANCEL_RESET, OpenType::MODAL, ResizeMode::STATIC),119myOriginalVClasses(originalVClasses),120myEditedVClasses(originalVClasses) {121// label for selection options122new FXLabel(getContentFrame(), TL("Selection options"), nullptr, GUIDesignLabel(JUSTIFY_NORMAL));123// horizontal frame uniform for options124FXHorizontalFrame* optionsFrame = new FXHorizontalFrame(getContentFrame(), GUIDesignAuxiliarHorizontalFrameUniform);125// allow all126GUIDesigns::buildFXButton(optionsFrame, "", "", "", GUIIconSubSys::getIcon(GUIIcon::OK), this, MID_GNE_ALLOWVCLASSES_SELECTALL, GUIDesignButtonIcon);127new FXLabel(optionsFrame, TL("Allow all vehicles"), nullptr, GUIDesignLabelThick(JUSTIFY_LEFT));128// only road129GUIDesigns::buildFXButton(optionsFrame, "", "", "", GUIIconSubSys::getIcon(GUIIcon::OK), this, MID_GNE_ALLOWVCLASSES_ONLY_ROAD, GUIDesignButtonIcon);130new FXLabel(optionsFrame, TL("Allow only road vehicles"), nullptr, GUIDesignLabelThick(JUSTIFY_LEFT));131// only rail132GUIDesigns::buildFXButton(optionsFrame, "", "", "", GUIIconSubSys::getIcon(GUIIcon::OK), this, MID_GNE_ALLOWVCLASSES_ONLY_RAIL, GUIDesignButtonIcon);133new FXLabel(optionsFrame, TL("Allow only rail vehicles"), nullptr, GUIDesignLabelThick(JUSTIFY_LEFT));134// disallow all135GUIDesigns::buildFXButton(optionsFrame, "", "", "", GUIIconSubSys::getIcon(GUIIcon::CANCEL), this, MID_GNE_ALLOWVCLASSES_UNSELECTALL, GUIDesignButtonIcon);136new FXLabel(optionsFrame, TL("Disallow all vehicles"), nullptr, GUIDesignLabelThick(JUSTIFY_LEFT));137// label for select vClasses138new FXLabel(getContentFrame(), TL("Select vClasses"), nullptr, GUIDesignLabel(JUSTIFY_NORMAL));139// Create frame for vehicles's columns140FXHorizontalFrame* myVehiclesFrame = new FXHorizontalFrame(getContentFrame(), GUIDesignContentsFrame);141// create left frame and fill it142FXVerticalFrame* vehiclesLeftFrame = new FXVerticalFrame(myVehiclesFrame, GUIDesignAuxiliarFrame);143myVClassMap[SVC_PASSENGER] = new VClassRow(vehiclesLeftFrame, SVC_PASSENGER, GUIIcon::VCLASS_PASSENGER, TL("Default vehicle class"));144myVClassMap[SVC_PRIVATE] = new VClassRow(vehiclesLeftFrame, SVC_PRIVATE, GUIIcon::VCLASS_PRIVATE, TL("A passenger car assigned for private use"));145myVClassMap[SVC_TAXI] = new VClassRow(vehiclesLeftFrame, SVC_TAXI, GUIIcon::VCLASS_TAXI, TL("Vehicle for hire with a driver"));146myVClassMap[SVC_BUS] = new VClassRow(vehiclesLeftFrame, SVC_BUS, GUIIcon::VCLASS_BUS, TL("Urban line traffic"));147myVClassMap[SVC_COACH] = new VClassRow(vehiclesLeftFrame, SVC_COACH, GUIIcon::VCLASS_COACH, TL("Overland transport"));148myVClassMap[SVC_DELIVERY] = new VClassRow(vehiclesLeftFrame, SVC_DELIVERY, GUIIcon::VCLASS_DELIVERY, TL("Vehicles specialized in delivering goods"));149myVClassMap[SVC_TRUCK] = new VClassRow(vehiclesLeftFrame, SVC_TRUCK, GUIIcon::VCLASS_TRUCK, TL("Vehicle designed to transport cargo"));150myVClassMap[SVC_TRAILER] = new VClassRow(vehiclesLeftFrame, SVC_TRAILER, GUIIcon::VCLASS_TRAILER, TL("Truck with trailer"));151myVClassMap[SVC_EMERGENCY] = new VClassRow(vehiclesLeftFrame, SVC_EMERGENCY, GUIIcon::VCLASS_EMERGENCY, TL("Vehicle designated to respond to an emergency"));152myVClassMap[SVC_MOTORCYCLE] = new VClassRow(vehiclesLeftFrame, SVC_MOTORCYCLE, GUIIcon::VCLASS_MOTORCYCLE, TL("Two- or three-wheeled motor vehicle"));153myVClassMap[SVC_MOPED] = new VClassRow(vehiclesLeftFrame, SVC_MOPED, GUIIcon::VCLASS_MOPED, TL("Motorcycle not allowed in motorways"));154// create center frame and fill it155FXVerticalFrame* vehiclesCenterFrame = new FXVerticalFrame(myVehiclesFrame, GUIDesignAuxiliarFrame);156myVClassMap[SVC_BICYCLE] = new VClassRow(vehiclesCenterFrame, SVC_BICYCLE, GUIIcon::VCLASS_BICYCLE, TL("Human-powered, pedal-driven vehicle"));157myVClassMap[SVC_SCOOTER] = new VClassRow(vehiclesCenterFrame, SVC_SCOOTER, GUIIcon::VCLASS_SCOOTER, TL("An electric scooter or a kick scooter"));158myVClassMap[SVC_PEDESTRIAN] = new VClassRow(vehiclesCenterFrame, SVC_PEDESTRIAN, GUIIcon::VCLASS_PEDESTRIAN, TL("Person traveling on foot"));159myVClassMap[SVC_WHEELCHAIR] = new VClassRow(vehiclesCenterFrame, SVC_WHEELCHAIR, GUIIcon::VCLASS_WHEELCHAIR, TL("A mobility impaired person"));160myVClassMap[SVC_TRAM] = new VClassRow(vehiclesCenterFrame, SVC_TRAM, GUIIcon::VCLASS_TRAM, TL("Rail vehicle which runs on tracks"));161myVClassMap[SVC_RAIL_ELECTRIC] = new VClassRow(vehiclesCenterFrame, SVC_RAIL_ELECTRIC, GUIIcon::VCLASS_RAIL_ELECTRIC, TL("Rail electric vehicle"));162myVClassMap[SVC_RAIL_FAST] = new VClassRow(vehiclesCenterFrame, SVC_RAIL_FAST, GUIIcon::VCLASS_RAIL_FAST, TL("High-speed rail vehicle"));163myVClassMap[SVC_RAIL_URBAN] = new VClassRow(vehiclesCenterFrame, SVC_RAIL_URBAN, GUIIcon::VCLASS_RAIL_URBAN, TL("Heavier than tram"));164myVClassMap[SVC_RAIL] = new VClassRow(vehiclesCenterFrame, SVC_RAIL, GUIIcon::VCLASS_RAIL, TL("Heavy rail vehicle"));165myVClassMap[SVC_CABLE_CAR] = new VClassRow(vehiclesCenterFrame, SVC_CABLE_CAR, GUIIcon::VCLASS_CABLE_CAR, TL("A conveyance suspended on a cable"));166myVClassMap[SVC_SUBWAY] = new VClassRow(vehiclesCenterFrame, SVC_SUBWAY, GUIIcon::VCLASS_SUBWAY, TL("A railway that mostly runs underground"));167// create right frame and fill it (8 vehicles)168FXVerticalFrame* vehiclesRightFrame = new FXVerticalFrame(myVehiclesFrame, GUIDesignAuxiliarFrame);169myVClassMap[SVC_E_VEHICLE] = new VClassRow(vehiclesRightFrame, SVC_E_VEHICLE, GUIIcon::VCLASS_EVEHICLE, TL("Future electric mobility vehicles"));170myVClassMap[SVC_ARMY] = new VClassRow(vehiclesRightFrame, SVC_ARMY, GUIIcon::VCLASS_ARMY, TL("Vehicle designed for military forces"));171myVClassMap[SVC_SHIP] = new VClassRow(vehiclesRightFrame, SVC_SHIP, GUIIcon::VCLASS_SHIP, TL("Basic class for navigating waterway"));172myVClassMap[SVC_AUTHORITY] = new VClassRow(vehiclesRightFrame, SVC_AUTHORITY, GUIIcon::VCLASS_AUTHORITY, TL("Vehicle of a governmental security agency"));173myVClassMap[SVC_VIP] = new VClassRow(vehiclesRightFrame, SVC_VIP, GUIIcon::VCLASS_VIP, TL("A civilian security armored car used by VIPs"));174myVClassMap[SVC_HOV] = new VClassRow(vehiclesRightFrame, SVC_HOV, GUIIcon::VCLASS_HOV, TL("High-Occupancy Vehicle (two or more passengers)"));175myVClassMap[SVC_CONTAINER] = new VClassRow(vehiclesRightFrame, SVC_CONTAINER, GUIIcon::VCLASS_CONTAINER, TL("A transport container"));176myVClassMap[SVC_AIRCRAFT] = new VClassRow(vehiclesRightFrame, SVC_AIRCRAFT, GUIIcon::VCLASS_AIRCRAFT, TL("An airplane"));177myVClassMap[SVC_DRONE] = new VClassRow(vehiclesRightFrame, SVC_DRONE, GUIIcon::VCLASS_DRONE, TL("A small unmanned robot"));178myVClassMap[SVC_CUSTOM1] = new VClassRow(vehiclesRightFrame, SVC_CUSTOM1, GUIIcon::VCLASS_CUSTOM1, TL("Reserved for user-defined semantics"));179myVClassMap[SVC_CUSTOM2] = new VClassRow(vehiclesRightFrame, SVC_CUSTOM2, GUIIcon::VCLASS_CUSTOM2, TL("Reserved for user-defined semantics"));180// reset dialog181onCmdReset(nullptr, 0, nullptr);182// open modal dialog183openDialog();184}185186187GNEVClassesDialog::~GNEVClassesDialog() {188}189190191void192GNEVClassesDialog::runInternalTest(const InternalTestStep::DialogArgument* dialogArgument) {193if (dialogArgument->getCustomAction() == "allVehicles") {194onCmdSelectAll(nullptr, 0, nullptr);195} else if (dialogArgument->getCustomAction() == "disallowAll") {196onCmdUnselectAll(nullptr, 0, nullptr);197} else if (dialogArgument->getCustomAction() == "onlyRoadVehicles") {198onCmdSelectOnlyRoad(nullptr, 0, nullptr);199} else if (dialogArgument->getCustomAction() == "onlyRailVehicles") {200onCmdSelectOnlyRail(nullptr, 0, nullptr);201} else if (SumoVehicleClassStrings.hasString(dialogArgument->getCustomAction())) {202myVClassMap[getVehicleClassID(dialogArgument->getCustomAction())]->onCmdToggleVClass(nullptr, 0, nullptr);203} else {204WRITE_ERROR("Invalid dialog argument " + dialogArgument->getCustomAction() + " used in GNEVClassesDialog::runInternalTest");205}206}207208209std::string210GNEVClassesDialog::getModifiedVClasses() const {211return myEditedVClasses;212}213214215long216GNEVClassesDialog::onCmdSelectAll(FXObject*, FXSelector, void*) {217// change all icons to accept218for (const auto& vClass : myVClassMap) {219vClass.second->setVClassButtonStatus(true);220}221return 1;222}223224225long226GNEVClassesDialog::onCmdUnselectAll(FXObject*, FXSelector, void*) {227// change all icons to cancel228for (const auto& vClass : myVClassMap) {229vClass.second->setVClassButtonStatus(false);230}231return 1;232}233234235long236GNEVClassesDialog::onCmdSelectOnlyRoad(FXObject*, FXSelector, void*) {237// change all non-road icons to disallow, and allow for the rest238for (const auto& vClass : myVClassMap) {239if ((vClass.first & (SVC_PEDESTRIAN | SVC_NON_ROAD)) == 0) {240vClass.second->setVClassButtonStatus(true);241} else {242vClass.second->setVClassButtonStatus(false);243}244}245return 1;246}247248249long250GNEVClassesDialog::onCmdSelectOnlyRail(FXObject*, FXSelector, void*) {251// change all non-road icons to disallow, and allow for the rest252for (const auto& vClass : myVClassMap) {253if ((vClass.first & SVC_RAIL_CLASSES) != 0) {254vClass.second->setVClassButtonStatus(true);255} else {256vClass.second->setVClassButtonStatus(false);257}258}259return 1;260}261262263long264GNEVClassesDialog::onCmdAccept(FXObject*, FXSelector, void*) {265bool allSelected = true;266// clear allow and disallow VClasses267std::vector<std::string> allowedVehicles;268for (const auto& vClass : myVClassMap) {269// check if vehicle is allowed depending on the Icon270if (vClass.second->isVClassButtonEnabled()) {271allowedVehicles.push_back(vClass.second->getVClassString());272} else {273allSelected = false;274}275}276if (allSelected) {277myEditedVClasses = "all";278} else {279myEditedVClasses = joinToString(allowedVehicles, " ");280}281// Stop Modal if we have a different classes from original282if (myEditedVClasses != myOriginalVClasses) {283return closeDialogAccepting();284} else {285return closeDialogCanceling();286}287}288289290long291GNEVClassesDialog::onCmdCancel(FXObject*, FXSelector, void*) {292// reset vClasses293myEditedVClasses = myOriginalVClasses;294// cancel295return closeDialogCanceling();296}297298299long300GNEVClassesDialog::onCmdReset(FXObject*, FXSelector, void*) {301// reset vClasses302myEditedVClasses = myOriginalVClasses;303// continue depending of allow304if (myEditedVClasses == "all") {305// iterate over myVClassMap and set all icons as true306for (const auto& vClass : myVClassMap) {307vClass.second->setVClassButtonStatus(true);308}309} else {310// declare string vector for saving all vclasses311const std::vector<std::string>& allowStringVector = StringTokenizer(myEditedVClasses).getVector();312const std::set<std::string> allowSet(allowStringVector.begin(), allowStringVector.end());313// iterate over myVClassMap and set icons314for (const auto& vClass : myVClassMap) {315if (allowSet.count(getVehicleClassNames(vClass.first)) > 0) {316vClass.second->setVClassButtonStatus(true);317} else {318vClass.second->setVClassButtonStatus(false);319}320}321}322return 1;323}324325/****************************************************************************/326327328