Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file GUIGLObjectPopupMenu.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // The popup menu of a globject
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <iostream>
25 : #include <cassert>
26 : #include <utils/common/StringTokenizer.h>
27 : #include <utils/common/StringUtils.h>
28 : #include <utils/geom/GeoConvHelper.h>
29 : #include <utils/gui/windows/GUISUMOAbstractView.h>
30 : #include <utils/gui/globjects/GUIGlObject.h>
31 : #include <utils/gui/windows/GUIAppEnum.h>
32 : #include <utils/gui/windows/GUIMainWindow.h>
33 : #include <utils/gui/div/GUIParameterTableWindow.h>
34 : #include <utils/gui/div/GUIGlobalSelection.h>
35 : #include <utils/gui/div/GUIUserIO.h>
36 : #include <utils/common/ToString.h>
37 : #include "GUIGLObjectPopupMenu.h"
38 : #include <utils/foxtools/MFXLinkLabel.h>
39 :
40 : // ===========================================================================
41 : // FOX callback mapping
42 : // ===========================================================================
43 : FXDEFMAP(GUIGLObjectPopupMenu) GUIGLObjectPopupMenuMap[] = {
44 : FXMAPFUNC(SEL_COMMAND, MID_CENTER, GUIGLObjectPopupMenu::onCmdCenter),
45 : FXMAPFUNC(SEL_COMMAND, MID_COPY_NAME, GUIGLObjectPopupMenu::onCmdCopyName),
46 : FXMAPFUNC(SEL_COMMAND, MID_COPY_TYPED_NAME, GUIGLObjectPopupMenu::onCmdCopyTypedName),
47 : FXMAPFUNC(SEL_COMMAND, MID_COPY_EDGE_NAME, GUIGLObjectPopupMenu::onCmdCopyEdgeName),
48 : FXMAPFUNC(SEL_COMMAND, MID_COPY_TEST_COORDINATES, GUIGLObjectPopupMenu::onCmdCopyTestCoordinates),
49 : FXMAPFUNC(SEL_COMMAND, MID_COPY_CURSOR_POSITION, GUIGLObjectPopupMenu::onCmdCopyCursorPosition),
50 : FXMAPFUNC(SEL_COMMAND, MID_COPY_CURSOR_GEOPOSITION, GUIGLObjectPopupMenu::onCmdCopyCursorGeoPosition),
51 : FXMAPFUNC(SEL_COMMAND, MID_COPY_VIEW_GEOBOUNDARY, GUIGLObjectPopupMenu::onCmdCopyViewGeoBoundary),
52 : FXMAPFUNC(SEL_COMMAND, MID_SHOW_GEOPOSITION_ONLINE, GUIGLObjectPopupMenu::onCmdShowCursorGeoPositionOnline),
53 : FXMAPFUNC(SEL_COMMAND, MID_SHOWPARS, GUIGLObjectPopupMenu::onCmdShowPars),
54 : FXMAPFUNC(SEL_COMMAND, MID_SHOWTYPEPARS, GUIGLObjectPopupMenu::onCmdShowTypePars),
55 : FXMAPFUNC(SEL_COMMAND, MID_ADDSELECT, GUIGLObjectPopupMenu::onCmdAddSelected),
56 : FXMAPFUNC(SEL_COMMAND, MID_REMOVESELECT, GUIGLObjectPopupMenu::onCmdRemoveSelected)
57 : };
58 :
59 : // Object implementation
60 0 : FXIMPLEMENT(GUIGLObjectPopupMenu, FXMenuPane, GUIGLObjectPopupMenuMap, ARRAYNUMBER(GUIGLObjectPopupMenuMap))
61 :
62 :
63 : // ===========================================================================
64 : // method definitions
65 : // ===========================================================================
66 :
67 0 : GUIGLObjectPopupMenu::GUIGLObjectPopupMenu(GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
68 : FXMenuPane(&parent),
69 0 : myParent(&parent),
70 0 : myObject(o),
71 0 : myApplication(&app),
72 0 : myPopupType(PopupType::ATTRIBUTES),
73 0 : myNetworkPosition(parent.getPositionInformation()),
74 0 : myTestCoordinates((toString(parent.getWindowCursorPosition().x() - 24.0) + " " + toString(parent.getWindowCursorPosition().y() - 25.0))) {
75 0 : }
76 :
77 :
78 0 : GUIGLObjectPopupMenu::GUIGLObjectPopupMenu(GUIMainWindow* app, GUISUMOAbstractView* parent, PopupType popupType) :
79 : FXMenuPane(parent),
80 0 : myParent(parent),
81 0 : myObject(nullptr),
82 0 : myApplication(app),
83 0 : myPopupType(popupType),
84 0 : myNetworkPosition(parent->getPositionInformation()) {
85 0 : }
86 :
87 :
88 0 : GUIGLObjectPopupMenu::~GUIGLObjectPopupMenu() {
89 : // Delete MenuPane children
90 0 : for (const auto& pane : myMenuPanes) {
91 0 : delete pane;
92 : }
93 0 : }
94 :
95 :
96 : void
97 0 : GUIGLObjectPopupMenu::insertMenuPaneChild(FXMenuPane* child) {
98 : // Check that MenuPaneChild isn't NULL
99 0 : if (child == nullptr) {
100 0 : throw ProcessError("MenuPaneChild cannot be NULL");
101 : }
102 : // Check that MenuPaneChild wasn't already inserted
103 0 : for (const auto& pane : myMenuPanes) {
104 0 : if (pane == child) {
105 0 : throw ProcessError("MenuPaneChild already inserted");
106 : }
107 : }
108 : // Insert MenuPaneChild
109 0 : myMenuPanes.push_back(child);
110 0 : }
111 :
112 :
113 : void
114 0 : GUIGLObjectPopupMenu::removePopupFromObject() {
115 : // remove popup menu from object
116 0 : if (myObject) {
117 0 : myObject->removedPopupMenu();
118 : }
119 0 : }
120 :
121 : GUISUMOAbstractView*
122 0 : GUIGLObjectPopupMenu::getParentView() {
123 0 : return myParent;
124 : }
125 :
126 :
127 : GUIGlObject*
128 0 : GUIGLObjectPopupMenu::getGLObject() const {
129 0 : return myObject;
130 : }
131 :
132 :
133 : GUIGLObjectPopupMenu::PopupType
134 0 : GUIGLObjectPopupMenu::getPopupType() const {
135 0 : return myPopupType;
136 : }
137 :
138 :
139 : long
140 0 : GUIGLObjectPopupMenu::onCmdCenter(FXObject*, FXSelector, void*) {
141 : // we already know where the object is since we clicked on it -> zoom on Boundary
142 0 : if (myObject) {
143 0 : myParent->centerTo(myObject->getGlID(), true, -1);
144 : } else {
145 0 : throw ProcessError("Object is NULL");
146 : }
147 0 : return 1;
148 : }
149 :
150 :
151 : long
152 0 : GUIGLObjectPopupMenu::onCmdCopyName(FXObject*, FXSelector, void*) {
153 0 : if (myObject) {
154 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), myObject->getMicrosimID());
155 : } else {
156 0 : throw ProcessError("Object is NULL");
157 : }
158 0 : return 1;
159 : }
160 :
161 :
162 : long
163 0 : GUIGLObjectPopupMenu::onCmdCopyTypedName(FXObject*, FXSelector, void*) {
164 0 : if (myObject) {
165 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), myObject->getFullName());
166 : } else {
167 0 : throw ProcessError("Object is NULL");
168 : }
169 0 : return 1;
170 : }
171 :
172 :
173 : long
174 0 : GUIGLObjectPopupMenu::onCmdCopyEdgeName(FXObject*, FXSelector, void*) {
175 0 : if (myObject == nullptr) {
176 0 : throw ProcessError("Object is NULL");
177 0 : } else if (myObject->getType() != GLO_LANE) {
178 0 : throw ProcessError(TL("Object must be a lane"));
179 : } else {
180 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), myObject->getParentName());
181 : }
182 0 : return 1;
183 : }
184 :
185 :
186 : long
187 0 : GUIGLObjectPopupMenu::onCmdCopyTestCoordinates(FXObject*, FXSelector, void*) {
188 0 : if (myObject) {
189 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), myTestCoordinates);
190 : } else {
191 0 : throw ProcessError("Object is NULL");
192 : }
193 0 : return 1;
194 : }
195 :
196 :
197 : long
198 0 : GUIGLObjectPopupMenu::onCmdCopyCursorPosition(FXObject*, FXSelector, void*) {
199 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), toString(myNetworkPosition));
200 0 : return 1;
201 : }
202 :
203 :
204 : long
205 0 : GUIGLObjectPopupMenu::onCmdCopyCursorGeoPosition(FXObject*, FXSelector, void*) {
206 0 : Position pos = myNetworkPosition;
207 0 : GeoConvHelper::getFinal().cartesian2geo(pos);
208 : // formatted for pasting into google maps
209 0 : const std::string posString = toString(pos.y(), gPrecisionGeo) + ", " + toString(pos.x(), gPrecisionGeo);
210 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), posString);
211 0 : return 1;
212 : }
213 :
214 :
215 : long
216 0 : GUIGLObjectPopupMenu::onCmdCopyViewGeoBoundary(FXObject*, FXSelector, void*) {
217 0 : const Boundary b = myParent->getVisibleBoundary();
218 0 : Position lowLeft(b.xmin(), b.ymin());
219 0 : GeoConvHelper::getFinal().cartesian2geo(lowLeft);
220 0 : Position upRight(b.xmax(), b.ymax());
221 0 : GeoConvHelper::getFinal().cartesian2geo(upRight);
222 : // formatted for usage with osmconvert
223 0 : const std::string posString = toString(lowLeft.x(), gPrecisionGeo) + "," + toString(lowLeft.y(), gPrecisionGeo) + "," +
224 0 : toString(upRight.x(), gPrecisionGeo) + "," + toString(upRight.y(), gPrecisionGeo);
225 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), posString);
226 0 : return 1;
227 : }
228 :
229 :
230 : long
231 0 : GUIGLObjectPopupMenu::onCmdShowCursorGeoPositionOnline(FXObject* item, FXSelector, void*) {
232 0 : FXMenuCommand* const mc = dynamic_cast<FXMenuCommand*>(item);
233 0 : Position pos = myNetworkPosition;
234 0 : GeoConvHelper::getFinal().cartesian2geo(pos);
235 0 : std::string url = myApplication->getOnlineMaps().find(mc->getText().text())->second;
236 0 : url = StringUtils::replace(StringUtils::replace(url, "%lat", toString(pos.y(), gPrecisionGeo)), "%lon", toString(pos.x(), gPrecisionGeo));
237 0 : MFXLinkLabel::fxexecute(url.c_str());
238 0 : return 1;
239 : }
240 :
241 :
242 : long
243 0 : GUIGLObjectPopupMenu::onCmdShowPars(FXObject*, FXSelector, void*) {
244 0 : if (myObject) {
245 0 : myObject->getParameterWindow(*myApplication, *myParent);
246 : } else {
247 0 : throw ProcessError("Object is NULL");
248 : }
249 0 : return 1;
250 : }
251 :
252 :
253 :
254 : long
255 0 : GUIGLObjectPopupMenu::onCmdShowTypePars(FXObject*, FXSelector, void*) {
256 0 : if (myObject) {
257 0 : myObject->getTypeParameterWindow(*myApplication, *myParent);
258 : } else {
259 0 : throw ProcessError("Object is NULL");
260 : }
261 0 : return 1;
262 : }
263 :
264 :
265 : long
266 0 : GUIGLObjectPopupMenu::onCmdAddSelected(FXObject*, FXSelector, void*) {
267 0 : if (myObject) {
268 0 : gSelected.select(myObject->getGlID());
269 0 : myParent->update();
270 : } else {
271 0 : throw ProcessError("Object is NULL");
272 : }
273 0 : return 1;
274 : }
275 :
276 :
277 : long
278 0 : GUIGLObjectPopupMenu::onCmdRemoveSelected(FXObject*, FXSelector, void*) {
279 0 : if (myObject) {
280 0 : gSelected.deselect(myObject->getGlID());
281 0 : myParent->update();
282 : } else {
283 0 : throw ProcessError("Object is NULL");
284 : }
285 0 : return 1;
286 : }
287 :
288 :
289 0 : GUIGLObjectPopupMenu::GUIGLObjectPopupMenu() :
290 : FXMenuPane(),
291 0 : myParent(nullptr),
292 0 : myObject(nullptr),
293 0 : myApplication(nullptr),
294 0 : myPopupType(PopupType::PROPERTIES) {
295 0 : }
296 :
297 : /****************************************************************************/
|