Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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/common/ToString.h>
29 : #include <utils/foxtools/MFXLinkLabel.h>
30 : #include <utils/geom/GeoConvHelper.h>
31 : #include <utils/gui/div/GUIGlobalSelection.h>
32 : #include <utils/gui/div/GUIParameterTableWindow.h>
33 : #include <utils/gui/div/GUIUserIO.h>
34 : #include <utils/gui/globjects/GUIGlObject.h>
35 : #include <utils/gui/windows/GUIAppEnum.h>
36 : #include <utils/gui/windows/GUIMainWindow.h>
37 : #include <utils/gui/windows/GUISUMOAbstractView.h>
38 :
39 : #include "GUIGLObjectPopupMenu.h"
40 :
41 : // ===========================================================================
42 : // FOX callback mapping
43 : // ===========================================================================
44 : FXDEFMAP(GUIGLObjectPopupMenu) GUIGLObjectPopupMenuMap[] = {
45 : FXMAPFUNC(SEL_COMMAND, MID_CENTER, GUIGLObjectPopupMenu::onCmdCenter),
46 : FXMAPFUNC(SEL_COMMAND, MID_COPY_NAME, GUIGLObjectPopupMenu::onCmdCopyName),
47 : FXMAPFUNC(SEL_COMMAND, MID_COPY_TYPED_NAME, GUIGLObjectPopupMenu::onCmdCopyTypedName),
48 : FXMAPFUNC(SEL_COMMAND, MID_COPY_EDGE_NAME, GUIGLObjectPopupMenu::onCmdCopyEdgeName),
49 : FXMAPFUNC(SEL_COMMAND, MID_COPY_TEST_COORDINATES, GUIGLObjectPopupMenu::onCmdCopyTestCoordinates),
50 : FXMAPFUNC(SEL_COMMAND, MID_COPY_CURSOR_POSITION, GUIGLObjectPopupMenu::onCmdCopyCursorPosition),
51 : FXMAPFUNC(SEL_COMMAND, MID_COPY_CURSOR_GEOPOSITION, GUIGLObjectPopupMenu::onCmdCopyCursorGeoPosition),
52 : FXMAPFUNC(SEL_COMMAND, MID_COPY_VIEW_GEOBOUNDARY, GUIGLObjectPopupMenu::onCmdCopyViewGeoBoundary),
53 : FXMAPFUNC(SEL_COMMAND, MID_SHOW_GEOPOSITION_ONLINE, GUIGLObjectPopupMenu::onCmdShowCursorGeoPositionOnline),
54 : FXMAPFUNC(SEL_COMMAND, MID_SHOWPARS, GUIGLObjectPopupMenu::onCmdShowPars),
55 : FXMAPFUNC(SEL_COMMAND, MID_SHOWPARS_PARENT, GUIGLObjectPopupMenu::onCmdShowParsParent),
56 : FXMAPFUNC(SEL_COMMAND, MID_SHOWTYPEPARS, GUIGLObjectPopupMenu::onCmdShowTypePars),
57 : FXMAPFUNC(SEL_COMMAND, MID_ADDSELECT, GUIGLObjectPopupMenu::onCmdAddSelected),
58 : FXMAPFUNC(SEL_COMMAND, MID_REMOVESELECT, GUIGLObjectPopupMenu::onCmdRemoveSelected),
59 : FXMAPFUNC(SEL_COMMAND, MID_DELETE, GUIGLObjectPopupMenu::onCmdDelete)
60 : };
61 :
62 : // Object implementation
63 0 : FXIMPLEMENT(GUIGLObjectPopupMenu, FXMenuPane, GUIGLObjectPopupMenuMap, ARRAYNUMBER(GUIGLObjectPopupMenuMap))
64 :
65 :
66 : // ===========================================================================
67 : // method definitions
68 : // ===========================================================================
69 :
70 0 : GUIGLObjectPopupMenu::GUIGLObjectPopupMenu(GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
71 : FXMenuPane(&parent),
72 0 : myParent(&parent),
73 0 : myObject(o),
74 0 : myApplication(&app),
75 0 : myPopupType(PopupType::ATTRIBUTES),
76 0 : myNetworkPosition(parent.getPositionInformation()),
77 0 : myTestCoordinates((toString(parent.getWindowCursorPosition().x() - 24.0) + " " + toString(parent.getWindowCursorPosition().y() - 25.0))) {
78 0 : }
79 :
80 :
81 0 : GUIGLObjectPopupMenu::GUIGLObjectPopupMenu(GUIMainWindow* app, GUISUMOAbstractView* parent, PopupType popupType) :
82 : FXMenuPane(parent),
83 0 : myParent(parent),
84 0 : myObject(nullptr),
85 0 : myApplication(app),
86 0 : myPopupType(popupType),
87 0 : myNetworkPosition(parent->getPositionInformation()) {
88 0 : }
89 :
90 :
91 0 : GUIGLObjectPopupMenu::~GUIGLObjectPopupMenu() {
92 : // Delete MenuPane children
93 0 : for (const auto& pane : myMenuPanes) {
94 0 : delete pane;
95 : }
96 0 : }
97 :
98 :
99 : void
100 0 : GUIGLObjectPopupMenu::insertMenuPaneChild(FXMenuPane* child) {
101 : // Check that MenuPaneChild isn't NULL
102 0 : if (child == nullptr) {
103 0 : throw ProcessError("MenuPaneChild cannot be NULL");
104 : }
105 : // Check that MenuPaneChild wasn't already inserted
106 0 : for (const auto& pane : myMenuPanes) {
107 0 : if (pane == child) {
108 0 : throw ProcessError("MenuPaneChild already inserted");
109 : }
110 : }
111 : // Insert MenuPaneChild
112 0 : myMenuPanes.push_back(child);
113 0 : }
114 :
115 :
116 : void
117 0 : GUIGLObjectPopupMenu::removePopupFromObject() {
118 : // remove popup menu from object
119 0 : if (myObject) {
120 0 : myObject->removedPopupMenu();
121 : }
122 0 : }
123 :
124 : GUISUMOAbstractView*
125 0 : GUIGLObjectPopupMenu::getParentView() {
126 0 : return myParent;
127 : }
128 :
129 :
130 : GUIGlObject*
131 0 : GUIGLObjectPopupMenu::getGLObject() const {
132 0 : return myObject;
133 : }
134 :
135 :
136 : GUIGLObjectPopupMenu::PopupType
137 0 : GUIGLObjectPopupMenu::getPopupType() const {
138 0 : return myPopupType;
139 : }
140 :
141 :
142 : long
143 0 : GUIGLObjectPopupMenu::onCmdCenter(FXObject*, FXSelector, void*) {
144 : // we already know where the object is since we clicked on it -> zoom on Boundary
145 0 : if (myObject) {
146 0 : myParent->centerTo(myObject->getGlID(), true, -1);
147 : } else {
148 0 : throw ProcessError("Object is NULL");
149 : }
150 0 : return 1;
151 : }
152 :
153 :
154 : long
155 0 : GUIGLObjectPopupMenu::onCmdCopyName(FXObject*, FXSelector, void*) {
156 0 : if (myObject) {
157 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), myObject->getMicrosimID());
158 : } else {
159 0 : throw ProcessError("Object is NULL");
160 : }
161 0 : return 1;
162 : }
163 :
164 :
165 : long
166 0 : GUIGLObjectPopupMenu::onCmdCopyTypedName(FXObject*, FXSelector, void*) {
167 0 : if (myObject) {
168 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), myObject->getFullName());
169 : } else {
170 0 : throw ProcessError("Object is NULL");
171 : }
172 0 : return 1;
173 : }
174 :
175 :
176 : long
177 0 : GUIGLObjectPopupMenu::onCmdCopyEdgeName(FXObject*, FXSelector, void*) {
178 0 : if (myObject == nullptr) {
179 0 : throw ProcessError("Object is NULL");
180 0 : } else if (myObject->getType() != GLO_LANE) {
181 0 : throw ProcessError(TL("Object must be a lane"));
182 : } else {
183 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), myObject->getParentName());
184 : }
185 0 : return 1;
186 : }
187 :
188 :
189 : long
190 0 : GUIGLObjectPopupMenu::onCmdCopyTestCoordinates(FXObject*, FXSelector, void*) {
191 0 : if (myObject) {
192 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), myTestCoordinates);
193 : } else {
194 0 : throw ProcessError("Object is NULL");
195 : }
196 0 : return 1;
197 : }
198 :
199 :
200 : long
201 0 : GUIGLObjectPopupMenu::onCmdCopyCursorPosition(FXObject*, FXSelector, void*) {
202 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), toString(myNetworkPosition));
203 0 : return 1;
204 : }
205 :
206 :
207 : long
208 0 : GUIGLObjectPopupMenu::onCmdCopyCursorGeoPosition(FXObject*, FXSelector, void*) {
209 0 : Position pos = myNetworkPosition;
210 0 : GeoConvHelper::getFinal().cartesian2geo(pos);
211 : // formatted for pasting into google maps
212 0 : const std::string posString = toString(pos.y(), gPrecisionGeo) + ", " + toString(pos.x(), gPrecisionGeo);
213 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), posString);
214 0 : return 1;
215 : }
216 :
217 :
218 : long
219 0 : GUIGLObjectPopupMenu::onCmdCopyViewGeoBoundary(FXObject*, FXSelector, void*) {
220 0 : const Boundary b = myParent->getVisibleBoundary();
221 0 : Position lowLeft(b.xmin(), b.ymin());
222 0 : GeoConvHelper::getFinal().cartesian2geo(lowLeft);
223 0 : Position upRight(b.xmax(), b.ymax());
224 0 : GeoConvHelper::getFinal().cartesian2geo(upRight);
225 : // formatted for usage with osmconvert
226 0 : const std::string posString = toString(lowLeft.x(), gPrecisionGeo) + "," + toString(lowLeft.y(), gPrecisionGeo) + "," +
227 0 : toString(upRight.x(), gPrecisionGeo) + "," + toString(upRight.y(), gPrecisionGeo);
228 0 : GUIUserIO::copyToClipboard(*myParent->getApp(), posString);
229 0 : return 1;
230 : }
231 :
232 :
233 : long
234 0 : GUIGLObjectPopupMenu::onCmdShowCursorGeoPositionOnline(FXObject* item, FXSelector, void*) {
235 0 : FXMenuCommand* const mc = dynamic_cast<FXMenuCommand*>(item);
236 0 : Position pos = myNetworkPosition;
237 0 : GeoConvHelper::getFinal().cartesian2geo(pos);
238 0 : std::string url = myApplication->getOnlineMaps().find(mc->getText().text())->second;
239 0 : url = StringUtils::replace(StringUtils::replace(url, "%lat", toString(pos.y(), gPrecisionGeo)), "%lon", toString(pos.x(), gPrecisionGeo));
240 0 : MFXLinkLabel::fxexecute(url.c_str());
241 0 : return 1;
242 : }
243 :
244 :
245 : long
246 0 : GUIGLObjectPopupMenu::onCmdShowPars(FXObject*, FXSelector, void*) {
247 0 : if (myObject) {
248 0 : myObject->getParameterWindow(*myApplication, *myParent);
249 : } else {
250 0 : throw ProcessError("Object is NULL");
251 : }
252 0 : return 1;
253 : }
254 :
255 :
256 : long
257 0 : GUIGLObjectPopupMenu::onCmdShowParsParent(FXObject*, FXSelector, void*) {
258 0 : if (myObject && myObject->getGLObjectParent()) {
259 0 : myObject->getGLObjectParent()->getParameterWindow(*myApplication, *myParent);
260 : } else {
261 0 : throw ProcessError("Object is NULL");
262 : }
263 0 : return 1;
264 : }
265 :
266 :
267 : long
268 0 : GUIGLObjectPopupMenu::onCmdShowTypePars(FXObject*, FXSelector, void*) {
269 0 : if (myObject) {
270 0 : myObject->getTypeParameterWindow(*myApplication, *myParent);
271 : } else {
272 0 : throw ProcessError("Object is NULL");
273 : }
274 0 : return 1;
275 : }
276 :
277 :
278 : long
279 0 : GUIGLObjectPopupMenu::onCmdAddSelected(FXObject*, FXSelector, void*) {
280 0 : if (myObject) {
281 0 : gSelected.select(myObject->getGlID());
282 0 : myParent->update();
283 : } else {
284 0 : throw ProcessError("Object is NULL");
285 : }
286 0 : return 1;
287 : }
288 :
289 :
290 : long
291 0 : GUIGLObjectPopupMenu::onCmdRemoveSelected(FXObject*, FXSelector, void*) {
292 0 : if (myObject) {
293 0 : gSelected.deselect(myObject->getGlID());
294 0 : myParent->update();
295 : } else {
296 0 : throw ProcessError("Object is NULL");
297 : }
298 0 : return 1;
299 : }
300 :
301 :
302 : long
303 0 : GUIGLObjectPopupMenu::onCmdDelete(FXObject*, FXSelector, void*) {
304 0 : if (myObject) {
305 0 : myObject->deleteGLObject();
306 : } else {
307 0 : throw ProcessError("Object is NULL");
308 : }
309 0 : return 1;
310 : }
311 :
312 :
313 0 : GUIGLObjectPopupMenu::GUIGLObjectPopupMenu() :
314 : FXMenuPane(),
315 0 : myParent(nullptr),
316 0 : myObject(nullptr),
317 0 : myApplication(nullptr),
318 0 : myPopupType(PopupType::PROPERTIES) {
319 0 : }
320 :
321 : /****************************************************************************/
|