#include <config.h>
#include <string>
#include <stack>
#include <utils/common/MsgHandler.h>
#include <utils/common/ToString.h>
#include <utils/geom/GeoConvHelper.h>
#include <utils/gui/windows/GUISUMOAbstractView.h>
#include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
#include <utils/gui/div/GUIParameterTableWindow.h>
#include <utils/foxtools/MFXMenuHeader.h>
#include <utils/gui/images/GUIIconSubSys.h>
#include <utils/gui/windows/GUIAppEnum.h>
#include <utils/gui/windows/GUIMainWindow.h>
#include <utils/gui/div/GUIGlobalSelection.h>
#include <utils/gui/div/GLHelper.h>
#include <utils/gui/div/GLObjectValuePassConnector.h>
#include <utils/gui/div/GUIDesigns.h>
#include <utils/geom/GeomHelper.h>
#include <utils/gui/div/GUIGlobalViewObjectsHandler.h>
#include <utils/options/OptionsCont.h>
#include "GUIGlObject.h"
#include "GUIGlObjectStorage.h"
StringBijection<GUIGlObjectType>::Entry GUIGlObject::GUIGlObjectTypeNamesInitializer[] = {
{"network", GLO_NETWORK},
{"networkElement", GLO_NETWORKELEMENT},
{"edge", GLO_EDGE},
{"lane", GLO_LANE},
{"junction", GLO_JUNCTION},
{"connection", GLO_CONNECTION},
{"crossing", GLO_CROSSING},
{"walkingArea", GLO_WALKINGAREA},
{"tlLogic", GLO_TLLOGIC},
{"edgeType", GLO_EDGETYPE},
{"laneType", GLO_LANETYPE},
{"parentChildLine", GLO_PARENTCHILDLINE},
{"additional", GLO_ADDITIONALELEMENT},
{"stoppingPlace", GLO_STOPPING_PLACE},
{"busStop", GLO_BUS_STOP},
{"trainStop", GLO_TRAIN_STOP},
{"access", GLO_ACCESS},
{"taz", GLO_TAZ},
{"containerStop", GLO_CONTAINER_STOP},
{"chargingStation", GLO_CHARGING_STATION},
{"parkingArea", GLO_PARKING_AREA},
{"stoppingPlaceLast", GLO_STOPPING_PLACE_LAST},
{"parkingSpace", GLO_PARKING_SPACE},
{"e1Detector", GLO_E1DETECTOR},
{"e1DetectorME", GLO_E1DETECTOR_ME},
{"e1DetectorInstant", GLO_E1DETECTOR_INSTANT},
{"e2Detector", GLO_E2DETECTOR},
{"e3Detector", GLO_E3DETECTOR},
{"entryExitDetector", GLO_DET_ENTRYEXIT},
{"entryDetector", GLO_DET_ENTRY},
{"exitDetector", GLO_DET_EXIT},
{"rerouter", GLO_REROUTER},
{"rerouterInterval", GLO_REROUTER_INTERVAL},
{"closingreroute", GLO_REROUTER_CLOSINGREROUTE},
{"closingLaneReroute", GLO_REROUTER_CLOSINGLANEREROUTE},
{"parkingAreaReroute", GLO_REROUTER_PARKINGAREAREROUTE},
{"destProbReroute", GLO_REROUTER_DESTPROBREROUTE},
{"routeProbReroute", GLO_REROUTER_ROUTEPROBREROUTE},
{"rerouterEdge", GLO_REROUTER_EDGE},
{"variableSpeedSign", GLO_VSS},
{"variableSpeedSignStep", GLO_VSS_STEP},
{"calibrator", GLO_CALIBRATOR},
{"calibratorFlow", GLO_CALIBRATOR_FLOW},
{"routeProbe", GLO_ROUTEPROBE},
{"vaporizer", GLO_VAPORIZER},
{"wire", GLO_WIRE},
{"overheadWireSegment", GLO_OVERHEAD_WIRE_SEGMENT},
{"tractionsubstation", GLO_TRACTIONSUBSTATION},
{"additionalLast", GLO_ADDITIONALELEMENT_LAST},
{"laneArrows", GLO_LANEARROWS},
{"shape", GLO_SHAPE},
{"polygon", GLO_POLYGON},
{"poi", GLO_POI},
{"jupedsim.walkable_area", GLO_JPS_WALKABLEAREA},
{"jupedsim.obstacle", GLO_JPS_OBSTACLE},
{"shapeLast", GLO_SHAPE_LAST},
{"routeElement", GLO_ROUTEELEMENT},
{"vType", GLO_VTYPE},
{"vTypeRef", GLO_VTYPE_REF},
{"vTypeDistribution", GLO_VTYPE_DISTRIBUTION},
{"route", GLO_ROUTE},
{"routeEmbedded", GLO_ROUTE_EMBEDDED},
{"routeRef", GLO_ROUTE_REF},
{"routeDistribution", GLO_ROUTE_DISTRIBUTION},
{"ride", GLO_RIDE},
{"walk", GLO_WALK},
{"personTrip", GLO_PERSONTRIP},
{"transport", GLO_TRANSPORT},
{"tranship", GLO_TRANSHIP},
{"stop", GLO_STOP},
{"stopPlan", GLO_STOP_PLAN},
{"vehicle", GLO_VEHICLE},
{"trip", GLO_TRIP},
{"flow", GLO_FLOW},
{"routeFlow", GLO_ROUTEFLOW},
{"container", GLO_CONTAINER},
{"containerFlow", GLO_CONTAINERFLOW},
{"person", GLO_PERSON},
{"personFlow", GLO_PERSONFLOW},
{"edgeData", GLO_EDGEDATA},
{"edgeRelData", GLO_EDGERELDATA},
{"TAZRelData", GLO_TAZRELDATA},
{"meanData", GLO_MEANDATA},
{"dataSet", GLO_DATASET},
{"dataInterval", GLO_DATAINTERVAL},
{"lockIcon", GLO_LOCKICON},
{"textName", GLO_TEXTNAME},
{"frontElement", GLO_FRONTELEMENT},
{"geometryPoint", GLO_GEOMETRYPOINT},
{"dottedContour", GLO_DOTTEDCONTOUR},
{"vehicleLabels", GLO_VEHICLELABELS},
{"temporalShape", GLO_TEMPORALSHAPE},
{"rectangleSelection", GLO_RECTANGLESELECTION},
{"testElement", GLO_TESTELEMENT},
{"undefined", GLO_MAX}
};
StringBijection<GUIGlObjectType> GUIGlObject::TypeNames(GUIGlObjectTypeNamesInitializer, GLO_MAX);
const GUIGlID GUIGlObject::INVALID_ID = 0;
const double GUIGlObject::INVALID_PRIORITY(-std::numeric_limits<double>::max());
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4355)
#endif
GUIGlObject::GUIGlObject(GUIGlObjectType type, const std::string& microsimID, FXIcon* icon) :
myGlID(GUIGlObjectStorage::gIDStorage.registerObject(this)),
myGLObjectType(type),
myMicrosimID(microsimID),
myIcon(icon) {
assert(myGLObjectType != GLO_ADDITIONALELEMENT);
myFullName = createFullName();
GUIGlObjectStorage::gIDStorage.changeName(this, myFullName);
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
GUIGlObject::~GUIGlObject() {
for (const auto& paramWindow : myParamWindows) {
paramWindow->removeObject(this);
}
GLObjectValuePassConnector<double>::removeObject(*this);
GUIGlObjectStorage::gIDStorage.remove(getGlID());
}
std::string
GUIGlObject::getParentName() const {
return StringUtils::emptyString;
}
FXIcon*
GUIGlObject::getGLIcon() const {
return myIcon;
}
GUIParameterTableWindow*
GUIGlObject::getTypeParameterWindow(GUIMainWindow& app, GUISUMOAbstractView& parent) {
UNUSED_PARAMETER(&app);
UNUSED_PARAMETER(&parent);
return nullptr;
}
bool
GUIGlObject::isGLObjectLocked() const {
return false;
}
void
GUIGlObject::markAsFrontElement() {
}
void
GUIGlObject::deleteGLObject() {
}
void
GUIGlObject::selectGLObject() {
}
void
GUIGlObject::updateGLObject() {
}
const std::string
GUIGlObject::getOptionalName() const {
return "";
}
void
GUIGlObject::setMicrosimID(const std::string& newID) {
myMicrosimID = newID;
GUIGlObjectStorage::gIDStorage.changeName(this, createFullName());
myFullName = createFullName();
}
void
GUIGlObject::drawGLAdditional(GUISUMOAbstractView* const parent, const GUIVisualizationSettings& s) const {
UNUSED_PARAMETER(&s);
UNUSED_PARAMETER(parent);
}
#ifdef HAVE_OSG
osg::Node*
GUIGlObject::getNode() const {
return myOSGNode;
}
void
GUIGlObject::setNode(osg::Node* node) {
myOSGNode = node;
}
#endif
void
GUIGlObject::buildPopUpMenuCommonOptions(GUIGLObjectPopupMenu* ret, GUIMainWindow& app, GUISUMOAbstractView* parent,
const SumoXMLTag tag, const bool selected, bool addSeparator) {
buildPopupHeader(ret, app);
buildCenterPopupEntry(ret);
GUIDesigns::buildFXMenuCommand(ret, TLF("Copy % name to clipboard", toString(tag)), nullptr, ret, MID_COPY_NAME);
GUIDesigns::buildFXMenuCommand(ret, TLF("Copy % typed name to clipboard", toString(tag)), nullptr, ret, MID_COPY_TYPED_NAME);
new FXMenuSeparator(ret);
if (selected) {
GUIDesigns::buildFXMenuCommand(ret, TL("Remove from Selected"), GUIIconSubSys::getIcon(GUIIcon::FLAG_MINUS), parent, MID_REMOVESELECT);
} else {
GUIDesigns::buildFXMenuCommand(ret, TL("Add to Selected"), GUIIconSubSys::getIcon(GUIIcon::FLAG_PLUS), parent, MID_ADDSELECT);
}
new FXMenuSeparator(ret);
buildShowParamsPopupEntry(ret, true);
buildPositionCopyEntry(ret, app, addSeparator);
}
void
GUIGlObject::buildPopupHeader(GUIGLObjectPopupMenu* ret, GUIMainWindow& app, bool addSeparator) {
new MFXMenuHeader(ret, app.getBoldFont(), getFullName().c_str(), myIcon, nullptr, 0);
if (OptionsCont::getOptions().getBool("gui-testing")) {
GUIDesigns::buildFXMenuCommand(ret, TL("Copy test coordinates to clipboard"), nullptr, ret, MID_COPY_TEST_COORDINATES);
}
if (addSeparator) {
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::buildCenterPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
GUIDesigns::buildFXMenuCommand(ret, TL("Center"), GUIIconSubSys::getIcon(GUIIcon::RECENTERVIEW), ret, MID_CENTER);
if (addSeparator) {
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::buildNameCopyPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
GUIDesigns::buildFXMenuCommand(ret, TL("Copy name to clipboard"), nullptr, ret, MID_COPY_NAME);
GUIDesigns::buildFXMenuCommand(ret, TL("Copy typed name to clipboard"), nullptr, ret, MID_COPY_TYPED_NAME);
if (addSeparator) {
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::buildSelectionPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
if (gSelected.isSelected(getType(), getGlID())) {
GUIDesigns::buildFXMenuCommand(ret, TL("Remove From Selected"), GUIIconSubSys::getIcon(GUIIcon::FLAG_MINUS), ret, MID_REMOVESELECT);
} else {
GUIDesigns::buildFXMenuCommand(ret, TL("Add to Selected"), GUIIconSubSys::getIcon(GUIIcon::FLAG_PLUS), ret, MID_ADDSELECT);
}
if (addSeparator) {
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::buildShowParamsPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
GUIDesigns::buildFXMenuCommand(ret, TL("Show Parameter"), GUIIconSubSys::getIcon(GUIIcon::APP_TABLE), ret, MID_SHOWPARS);
if (addSeparator) {
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::buildShowTypeParamsPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
GUIDesigns::buildFXMenuCommand(ret, TL("Show Type Parameter"), GUIIconSubSys::getIcon(GUIIcon::APP_TABLE), ret, MID_SHOWTYPEPARS);
if (addSeparator) {
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::buildPositionCopyEntry(GUIGLObjectPopupMenu* ret, const GUIMainWindow& app, bool addSeparator) const {
GUIDesigns::buildFXMenuCommand(ret, TL("Copy cursor position to clipboard"), nullptr, ret, MID_COPY_CURSOR_POSITION);
if (GeoConvHelper::getFinal().usingGeoProjection()) {
GUIDesigns::buildFXMenuCommand(ret, TL("Copy cursor geo-position to clipboard"), nullptr, ret, MID_COPY_CURSOR_GEOPOSITION);
FXMenuPane* showCursorGeoPositionPane = new FXMenuPane(ret);
ret->insertMenuPaneChild(showCursorGeoPositionPane);
new FXMenuCascade(ret, TL("Show cursor geo-position in "), nullptr, showCursorGeoPositionPane);
for (const auto& mapper : app.getOnlineMaps()) {
if (mapper.first == "GeoHack") {
GUIDesigns::buildFXMenuCommand(showCursorGeoPositionPane, mapper.first, GUIIconSubSys::getIcon(GUIIcon::GEOHACK), ret, MID_SHOW_GEOPOSITION_ONLINE);
} else if (mapper.first == "Google Maps") {
GUIDesigns::buildFXMenuCommand(showCursorGeoPositionPane, mapper.first, GUIIconSubSys::getIcon(GUIIcon::GOOGLEMAPS), ret, MID_SHOW_GEOPOSITION_ONLINE);
} else if (mapper.first == "OSM") {
GUIDesigns::buildFXMenuCommand(showCursorGeoPositionPane, mapper.first, GUIIconSubSys::getIcon(GUIIcon::OSM), ret, MID_SHOW_GEOPOSITION_ONLINE);
} else {
GUIDesigns::buildFXMenuCommand(showCursorGeoPositionPane, mapper.first, nullptr, ret, MID_SHOW_GEOPOSITION_ONLINE);
}
}
}
if (addSeparator) {
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::buildShowManipulatorPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
GUIDesigns::buildFXMenuCommand(ret, TL("Open Manipulator..."), GUIIconSubSys::getIcon(GUIIcon::MANIP), ret, MID_MANIP);
if (addSeparator) {
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::addParameterTable(GUIParameterTableWindow* t) {
myParamWindows.insert(t);
}
void
GUIGlObject::removeParameterTable(GUIParameterTableWindow* t) {
std::set<GUIParameterTableWindow*>::iterator i = myParamWindows.find(t);
if (i != myParamWindows.end()) {
myParamWindows.erase(i);
}
}
void
GUIGlObject::buildShapePopupOptions(GUIMainWindow& app, GUIGLObjectPopupMenu* ret, const std::string& type) {
assert(ret);
buildPopupHeader(ret, app, false);
buildCenterPopupEntry(ret);
buildNameCopyPopupEntry(ret);
buildSelectionPopupEntry(ret);
buildShowParamsPopupEntry(ret, false);
buildPositionCopyEntry(ret, app);
if (type != "") {
GUIDesigns::buildFXMenuCommand(ret, TLF("type: %", type).c_str(), nullptr, nullptr, 0);
new FXMenuSeparator(ret);
}
}
void
GUIGlObject::buildAdditionalsPopupOptions(GUIMainWindow& app, GUIGLObjectPopupMenu* ret, const std::string& type) {
assert(ret);
buildPopupHeader(ret, app, false);
buildCenterPopupEntry(ret);
buildNameCopyPopupEntry(ret);
buildSelectionPopupEntry(ret);
buildShowParamsPopupEntry(ret, false);
buildPositionCopyEntry(ret, app);
if (type != "") {
GUIDesigns::buildFXMenuCommand(ret, TLF("type: %", type).c_str(), nullptr, nullptr, 0);
new FXMenuSeparator(ret);
}
}
std::string
GUIGlObject::createFullName() const {
return TypeNames.getString(myGLObjectType) + ":" + getMicrosimID();
}
void
GUIGlObject::drawName(const Position& pos, const double scale, const GUIVisualizationTextSettings& settings, const double angle, bool forceShow) const {
if (settings.show(this) || forceShow) {
GLHelper::drawTextSettings(settings, getMicrosimID(), pos, scale, angle);
}
}