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 GUICursorDialog.cpp
15 : /// @author Pablo Alvarez Lopez
16 : /// @date Sep 2022
17 : ///
18 : // Dialog for edit element under cursor
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <utils/gui/div/GUIDesigns.h>
23 : #include <utils/gui/div/GUIGlobalSelection.h>
24 : #include <utils/gui/windows/GUIAppEnum.h>
25 : #include <utils/gui/windows/GUIMainWindow.h>
26 : #include <utils/gui/windows/GUISUMOAbstractView.h>
27 :
28 : #include "GUICursorDialog.h"
29 :
30 :
31 : #define NUM_VISIBLE_ITEMS 10
32 :
33 : // ===========================================================================
34 : // FOX callback mapping
35 : // ===========================================================================
36 :
37 : FXDEFMAP(GUICursorDialog) GUICursorDialogMap[] = {
38 : FXMAPFUNC(SEL_COMMAND, MID_CURSORDIALOG_SETFRONTELEMENT, GUICursorDialog::onCmdSetFrontElement),
39 : FXMAPFUNC(SEL_COMMAND, MID_CURSORDIALOG_DELETEELEMENT, GUICursorDialog::onCmdDeleteElement),
40 : FXMAPFUNC(SEL_COMMAND, MID_CURSORDIALOG_SELECTELEMENT, GUICursorDialog::onCmdSelectElement),
41 : FXMAPFUNC(SEL_COMMAND, MID_CURSORDIALOG_PROPERTIES, GUICursorDialog::onCmdOpenPropertiesPopUp),
42 : FXMAPFUNC(SEL_COMMAND, MID_CURSORDIALOG_MOVEUP, GUICursorDialog::onCmdMoveListUp),
43 : FXMAPFUNC(SEL_COMMAND, MID_CURSORDIALOG_MOVEDOWN, GUICursorDialog::onCmdMoveListDown),
44 : FXMAPFUNC(SEL_COMMAND, MID_CURSORDIALOG_FRONT, GUICursorDialog::onCmdProcessFront),
45 : FXMAPFUNC(SEL_COMMAND, FXWindow::ID_UNPOST, GUICursorDialog::onCmdUnpost),
46 : };
47 :
48 : // Object implementation
49 0 : FXIMPLEMENT(GUICursorDialog, GUIGLObjectPopupMenu, GUICursorDialogMap, ARRAYNUMBER(GUICursorDialogMap))
50 :
51 : // ===========================================================================
52 : // member method definitions
53 : // ===========================================================================
54 :
55 0 : GUICursorDialog::GUICursorDialog(GUIGLObjectPopupMenu::PopupType type, GUISUMOAbstractView* view, const std::vector<GUIGlObject*>& objects) :
56 : GUIGLObjectPopupMenu(view->getMainWindow(), view, type),
57 0 : myType(type),
58 0 : myView(view) {
59 : // continue depending of properties
60 0 : if (type == GUIGLObjectPopupMenu::PopupType::PROPERTIES) {
61 0 : buildDialogElements(view, TL("Overlapped objects"), GUIIcon::MODEINSPECT, MID_CURSORDIALOG_PROPERTIES, objects);
62 0 : } else if (type == GUIGLObjectPopupMenu::PopupType::DELETE_ELEMENT) {
63 0 : buildDialogElements(view, TL("Delete element"), GUIIcon::MODEDELETE, MID_CURSORDIALOG_DELETEELEMENT, objects);
64 0 : } else if (type == GUIGLObjectPopupMenu::PopupType::SELECT_ELEMENT) {
65 0 : buildDialogElements(view, TL("Select element"), GUIIcon::MODESELECT, MID_CURSORDIALOG_SELECTELEMENT, objects);
66 0 : } else if (type == GUIGLObjectPopupMenu::PopupType::FRONT_ELEMENT) {
67 0 : buildDialogElements(view, TL("Mark front element"), GUIIcon::FRONTELEMENT, MID_CURSORDIALOG_SETFRONTELEMENT, objects);
68 : }
69 0 : }
70 :
71 :
72 0 : GUICursorDialog::~GUICursorDialog() {
73 : // delete all menu commands
74 0 : for (const auto& GLObject : myMenuCommandGLObjects) {
75 0 : delete GLObject.first;
76 : }
77 0 : }
78 :
79 :
80 : long
81 0 : GUICursorDialog::onCmdSetFrontElement(FXObject* obj, FXSelector, void*) {
82 : // search element in myGLObjects
83 0 : for (const auto& GLObject : myMenuCommandGLObjects) {
84 0 : if (GLObject.first == obj) {
85 0 : GLObject.second->markAsFrontElement();
86 : }
87 : }
88 : // destroy popup
89 0 : myView->destroyPopup();
90 0 : return 1;
91 : }
92 :
93 :
94 : long
95 0 : GUICursorDialog::onCmdDeleteElement(FXObject* obj, FXSelector, void*) {
96 : // search element in myGLObjects
97 0 : for (const auto& GLObject : myMenuCommandGLObjects) {
98 0 : if (GLObject.first == obj) {
99 0 : GLObject.second->deleteGLObject();
100 : }
101 : }
102 : // destroy popup
103 0 : myView->destroyPopup();
104 0 : return 1;
105 : }
106 :
107 :
108 : long
109 0 : GUICursorDialog::onCmdSelectElement(FXObject* obj, FXSelector, void*) {
110 : // search element in myGLObjects
111 0 : for (const auto& GLObject : myMenuCommandGLObjects) {
112 0 : if (GLObject.first == obj) {
113 0 : GLObject.second->selectGLObject();
114 : }
115 : }
116 : // destroy popup
117 0 : myView->destroyPopup();
118 0 : return 1;
119 : }
120 :
121 :
122 : long
123 0 : GUICursorDialog::onCmdOpenPropertiesPopUp(FXObject* obj, FXSelector, void*) {
124 : // search element in myGLObjects
125 0 : for (const auto& GLObject : myMenuCommandGLObjects) {
126 0 : if (GLObject.first == obj) {
127 0 : myView->replacePopup(GLObject.second->getPopUpMenu(*myView->getMainWindow(), *myView));
128 : return 1;
129 : }
130 : }
131 : return 0;
132 : }
133 :
134 :
135 : long
136 0 : GUICursorDialog::onCmdMoveListUp(FXObject*, FXSelector, void*) {
137 0 : myListIndex -= NUM_VISIBLE_ITEMS;
138 0 : updateList();
139 0 : show();
140 0 : return 0;
141 : }
142 :
143 :
144 : long
145 0 : GUICursorDialog::onCmdMoveListDown(FXObject*, FXSelector, void*) {
146 0 : myListIndex += NUM_VISIBLE_ITEMS;
147 0 : updateList();
148 0 : show();
149 0 : return 0;
150 : }
151 :
152 :
153 : long
154 0 : GUICursorDialog::onCmdProcessFront(FXObject*, FXSelector, void*) {
155 0 : if (myMenuCommandGLObjects.size() > 0) {
156 : // continue depending of properties
157 0 : if (myType == GUIGLObjectPopupMenu::PopupType::DELETE_ELEMENT) {
158 0 : myMenuCommandGLObjects.front().second->deleteGLObject();
159 0 : } else if (myType == GUIGLObjectPopupMenu::PopupType::SELECT_ELEMENT) {
160 0 : myMenuCommandGLObjects.front().second->selectGLObject();
161 0 : } else if (myType == GUIGLObjectPopupMenu::PopupType::FRONT_ELEMENT) {
162 0 : myMenuCommandGLObjects.front().second->markAsFrontElement();
163 : }
164 : }
165 0 : return 0;
166 : }
167 :
168 :
169 : long
170 0 : GUICursorDialog::onCmdUnpost(FXObject* obj, FXSelector, void* ptr) {
171 : // ignore move up, down and header
172 0 : if ((obj == myMoveUpMenuCommand) || (obj == myMoveDownMenuCommand) || (obj == myMenuHeader)) {
173 : return 1;
174 : }
175 0 : if (grabowner) {
176 0 : grabowner->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), ptr);
177 : } else {
178 0 : popdown();
179 0 : if (grabbed()) {
180 0 : ungrab();
181 : }
182 : }
183 : return 1;
184 : }
185 :
186 :
187 : void
188 0 : GUICursorDialog::updateList() {
189 : // first hide all menu commands
190 0 : for (const auto& GLObject : myMenuCommandGLObjects) {
191 0 : GLObject.first->hide();
192 : }
193 : // check if disable menu command up
194 0 : if (myListIndex == 0) {
195 0 : myMoveUpMenuCommand->disable();
196 : } else {
197 0 : myMoveUpMenuCommand->enable();
198 : }
199 : // show menu commands depending of myListIndex
200 0 : if ((myListIndex + NUM_VISIBLE_ITEMS) > (int)myMenuCommandGLObjects.size()) {
201 0 : for (int i = (int)myMenuCommandGLObjects.size() - NUM_VISIBLE_ITEMS; i < (int)myMenuCommandGLObjects.size(); i++) {
202 0 : myMenuCommandGLObjects.at(i).first->show();
203 : }
204 0 : myMoveDownMenuCommand->disable();
205 : } else {
206 0 : for (int i = myListIndex; i < (myListIndex + NUM_VISIBLE_ITEMS); i++) {
207 0 : myMenuCommandGLObjects.at(i).first->show();
208 : }
209 0 : myMoveDownMenuCommand->enable();
210 : }
211 : // recalc popup
212 0 : recalc();
213 0 : }
214 :
215 :
216 : void
217 0 : GUICursorDialog::buildDialogElements(GUISUMOAbstractView* view, const FXString text, GUIIcon icon, FXSelector sel, const std::vector<GUIGlObject*>& objects) {
218 : // create header
219 0 : myMenuHeader = new MFXMenuHeader(this, view->getMainWindow()->getBoldFont(), text, GUIIconSubSys::getIcon(icon), nullptr, 0);
220 0 : new FXMenuSeparator(this);
221 : // check if create move up menu command
222 0 : if (objects.size() > NUM_VISIBLE_ITEMS) {
223 0 : myMoveUpMenuCommand = GUIDesigns::buildFXMenuCommand(this, "Previous", GUIIconSubSys::getIcon(GUIIcon::ARROW_UP), this, MID_CURSORDIALOG_MOVEUP);
224 0 : new FXMenuSeparator(this);
225 : }
226 : // create a menu command for every object
227 0 : for (const auto& glo : objects) {
228 0 : const std::string selStatus = gSelected.isSelected(glo) ? " (selected)" : "";
229 0 : myMenuCommandGLObjects.push_back(std::make_pair(GUIDesigns::buildFXMenuCommand(this, glo->getMicrosimID() + selStatus, glo->getGLIcon(), this, sel), glo));
230 : }
231 : // check if create move down menu command
232 0 : if (objects.size() > NUM_VISIBLE_ITEMS) {
233 0 : new FXMenuSeparator(this);
234 0 : myMoveDownMenuCommand = GUIDesigns::buildFXMenuCommand(this, "Next", GUIIconSubSys::getIcon(GUIIcon::ARROW_DOWN), this, MID_CURSORDIALOG_MOVEDOWN);
235 0 : updateList();
236 : }
237 0 : }
238 :
239 : /****************************************************************************/
|