Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GUIDialog_ChooserAbstract.cpp
Go to the documentation of this file.
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/****************************************************************************/
20// Class for the window that allows to choose a street, junction or vehicle
21/****************************************************************************/
22#include <config.h>
23
24#include <string>
25#include <vector>
26#include <fxkeys.h>
37
39
40
41// ===========================================================================
42// FOX callback mapping
43// ===========================================================================
61
62FXIMPLEMENT(GUIDialog_ChooserAbstract, FXMainWindow, GUIDialog_ChooserAbstractMap, ARRAYNUMBER(GUIDialog_ChooserAbstractMap))
63
64
65// ===========================================================================
66// method definitions
67// ===========================================================================
68#ifdef _MSC_VER
69#pragma warning(push)
70#pragma warning(disable: 4355) // mask warning about "this" in initializers
71#endif
73 FXIcon* icon, const FXString& title, const std::vector<GUIGlID>& ids, GUIGlObjectStorage& /*glStorage*/) :
74 FXMainWindow(windowsParent->getApp(), title, icon, nullptr, GUIDesignChooserDialog),
75 GUIPersistentWindowPos(this, "LOCATOR", true, 20, 40, 300, 350),
76 myWindowsParent(windowsParent),
77 myMessageId(messageId),
78 myLocateByName(false),
79 myHaveFilteredSubstring(false) {
80 FXHorizontalFrame* hbox = new FXHorizontalFrame(this, GUIDesignAuxiliarFrame);
81 // build the list
82 FXVerticalFrame* layoutLeft = new FXVerticalFrame(hbox, GUIDesignChooserLayoutLeft);
83 myTextEntry = new FXTextField(layoutLeft, 0, this, MID_CHOOSER_TEXT, TEXTFIELD_ENTER_ONLY | GUIDesignChooserTextField);
84 FXVerticalFrame* layoutList = new FXVerticalFrame(layoutLeft, GUIDesignChooserLayoutList);
85 myList = new FXList(layoutList, this, MID_CHOOSER_LIST, GUIDesignChooserListSingle);
86 // build the buttons
87 FXVerticalFrame* layoutRight = new FXVerticalFrame(hbox, GUIDesignChooserLayoutRight);
90 // only enable Track Button if we're locating vehicles
91 if (title.text() != std::string(TL("Vehicle Chooser"))) {
92 myTrackButton->disable();
93 myTrackButton->hide();
94 }
95 new FXHorizontalSeparator(layoutRight, GUIDesignHorizontalSeparator);
97 GUIDesigns::buildFXButton(layoutRight, TL("By &Name"), TL("Locate item by name"), "", nullptr, this, MID_CHOOSEN_NAME, GUIDesignChooserButtons);
98 GUIDesigns::buildFXButton(layoutRight, TL("&Select/deselect"), "", TL("Select/deselect current object"), GUIIconSubSys::getIcon(GUIIcon::FLAG), this, MID_CHOOSEN_INVERT, GUIDesignChooserButtons);
99 GUIDesigns::buildFXButton(layoutRight, TL("&Filter substring"), "", "", nullptr, this, MID_CHOOSER_FILTER_SUBSTR, GUIDesignChooserButtons);
100 GUIDesigns::buildFXButton(layoutRight, TL("Select &all"), "", TL("Select all items in list"), GUIIconSubSys::getIcon(GUIIcon::FLAG), this, MID_CHOOSEN_SELECT, GUIDesignChooserButtons);
101 GUIDesigns::buildFXButton(layoutRight, TL("&Deselect all"), "", TL("Deselect all items in list"), GUIIconSubSys::getIcon(GUIIcon::FLAG), this, MID_CHOOSEN_CLEAR, GUIDesignChooserButtons);
102 GUIDesigns::buildFXButton(layoutRight, TL("&Update"), "", TL("Reload all ids"), GUIIconSubSys::getIcon(GUIIcon::RELOAD), this, MID_UPDATE, GUIDesignChooserButtons);
103 new FXHorizontalSeparator(layoutRight, GUIDesignHorizontalSeparator);
105 myCountLabel = new FXLabel(layoutRight, "placeholder", nullptr, LAYOUT_BOTTOM | LAYOUT_FILL_X | JUSTIFY_LEFT);
106 myCaseSensitive = new FXCheckButton(layoutRight, TL("case-sensitive search"));
107 myCaseSensitive->setCheck(getApp()->reg().readIntEntry("LOCATOR", "caseSensitive", 0) == 1);
108 myInstantCenter = new FXCheckButton(layoutRight, TL("auto-center"));
109 myInstantCenter->setCheck(getApp()->reg().readIntEntry("LOCATOR", "autoCenter", 0) == 1);
110 refreshList(ids);
111 // add child in windowsParent
114 // create and show dialog
115 create();
116 show();
117}
118#ifdef _MSC_VER
119#pragma warning(pop)
120#endif
121
122
124 // remove child from windowsParent
126 getApp()->reg().writeIntEntry("LOCATOR", "autoCenter", myInstantCenter->getCheck());
127 getApp()->reg().writeIntEntry("LOCATOR", "caseSensitive", myCaseSensitive->getCheck());
128}
129
130
133 return static_cast<GUIGlObject*>(mySelected);
134}
135
136
137void
139 FXMainWindow::show();
140 myTextEntry->setFocus();
141}
142
143
144long
145GUIDialog_ChooserAbstract::onCmdCenter(FXObject*, FXSelector, void*) {
146 int selected = myList->getCurrentItem();
147 if (selected >= 0) {
149 myWindowsParent->setView(*static_cast<GUIGlID*>(myList->getItemData(selected)));
150 }
151 return 1;
152}
153
154
155long
156GUIDialog_ChooserAbstract::onCmdTrack(FXObject*, FXSelector, void*) {
157 int selected = myList->getCurrentItem();
158 if (selected >= 0) {
159 myWindowsParent->setView(*static_cast<GUIGlID*>(myList->getItemData(selected)));
160 GUIGlID id = *static_cast<GUIGlID*>(myList->getItemData(selected));
162 if (o->getType() == GLO_VEHICLE) {
164 }
166 }
167 return 1;
168}
169
170
171long
172GUIDialog_ChooserAbstract::onCmdClose(FXObject*, FXSelector, void*) {
173 close(true);
174 return 1;
175}
176
177long
178GUIDialog_ChooserAbstract::onChgList(FXObject*, FXSelector, void*) {
179 // mouse-click toggles item selection but changked current item with
180 // keyboard does not affect select
181 // Enabling the line blow toggles the behavior (which must be fixed via onChgListSel)
182 myList->selectItem(myList->getCurrentItem());
183 if (myInstantCenter->getCheck()) {
184 onCmdCenter(nullptr, 0, nullptr);
185 }
186 return 1;
187}
188
189long
190GUIDialog_ChooserAbstract::onChgListSel(FXObject*, FXSelector, void*) {
191 myList->selectItem(myList->getCurrentItem());
192 return 1;
193}
194
195long
196GUIDialog_ChooserAbstract::onChgText(FXObject*, FXSelector, void*) {
197 const bool caseSensitive = myCaseSensitive->getCheck() == TRUE;
198 int id = -1;
200 // findItem does not support substring search
201 const int numItems = myList->getNumItems();
202 FXString t = myTextEntry->getText();
203 if (!caseSensitive) {
204 t = t.lower();
205 }
206 for (int i = 0; i < numItems; i++) {
207 FXString t2 = myList->getItemText(i);
208 if (!caseSensitive) {
209 t2 = t2.lower();
210 }
211 if (t2.find(t) >= 0) {
212 id = i;
213 break;
214 }
215 }
216 } else {
217 const int caseOpt = caseSensitive ? 0 : SEARCH_IGNORECASE;
218 id = myList->findItem(myTextEntry->getText(), -1, SEARCH_PREFIX | caseOpt);
219 }
220 if (id < 0) {
221 if (myList->getNumItems() > 0) {
222 myList->deselectItem(myList->getCurrentItem());
223 }
224 myCenterButton->disable();
225 myTrackButton->disable();
226 return 1;
227 }
228 myList->deselectItem(myList->getCurrentItem());
229 myList->makeItemVisible(id);
230 myList->selectItem(id);
231 myList->setCurrentItem(id, true);
232 myCenterButton->enable();
233 myTrackButton->enable();
234 return 1;
235}
236
237
238long
239GUIDialog_ChooserAbstract::onCmdText(FXObject*, FXSelector, void*) {
240 int current = myList->getCurrentItem();
241 if (current >= 0 && myList->isItemSelected(current)) {
242 myWindowsParent->setView(*static_cast<GUIGlID*>(myList->getItemData(current)));
243 }
244 return 1;
245}
246
247
248
249long
250GUIDialog_ChooserAbstract::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
251 FXEvent* event = (FXEvent*)ptr;
252 if (event->code == KEY_Return) {
253 onCmdText(nullptr, 0, nullptr);
254 if ((event->state & CONTROLMASK) != 0) {
255 close(true);
256 }
257 return 1;
258 } else if (event->code == KEY_Left || (event->code == KEY_Up && myList->getCurrentItem() == 0)) {
259 myTextEntry->setFocus();
260 return 1;
261 } else if (event->code == KEY_Escape) {
262 close(true);
263 return 1;
264 }
265 return FXMainWindow::onKeyPress(o, sel, ptr);
266}
267
268
269long
270GUIDialog_ChooserAbstract::onCmdFilter(FXObject*, FXSelector, void*) {
272 std::vector<GUIGlID> selectedGlIDs;
273 const int numItems = myList->getNumItems();
274 for (int i = 0; i < numItems; i++) {
275 const GUIGlID glID = *static_cast<GUIGlID*>(myList->getItemData(i));
276 if (myList->getItemIcon(i) == flag) {
277 selectedGlIDs.push_back(glID);
278 }
279 }
280 refreshList(selectedGlIDs);
281 return 1;
282}
283
284
285long
286GUIDialog_ChooserAbstract::onCmdFilterSubstr(FXObject*, FXSelector, void*) {
287 const bool caseSensitive = myCaseSensitive->getCheck() == TRUE;
288 std::vector<GUIGlID> selectedGlIDs;
289 const int numItems = myList->getNumItems();
290 FXString t = myTextEntry->getText();
291 if (!caseSensitive) {
292 t = t.lower();
293 }
294 for (int i = 0; i < numItems; i++) {
295 FXString t2 = myList->getItemText(i);
296 if (!caseSensitive) {
297 t2 = t2.lower();
298 }
299 if (t2.find(t) >= 0) {
300 const GUIGlID glID = *static_cast<GUIGlID*>(myList->getItemData(i));
301 selectedGlIDs.push_back(glID);
302 }
303 }
304 refreshList(selectedGlIDs);
305 // filter ACs in netedit
306 filterACs(selectedGlIDs);
308 onChgText(nullptr, 0, nullptr);
309 return 1;
310}
311
312
313std::string
315 if (myLocateByName) {
316 return o->getOptionalName();
317 } else {
318 return o->getMicrosimID();
319 }
320}
321
322void
323GUIDialog_ChooserAbstract::refreshList(const std::vector<GUIGlID>& ids) {
324 myList->clearItems();
325 for (auto i : ids) {
327 if (o == nullptr) {
328 continue;
329 }
330 const std::string& name = getObjectName(o);
331 const bool selected = myWindowsParent->isSelected(o);
332 FXIcon* const ico = selected ? GUIIconSubSys::getIcon(GUIIcon::FLAG) : nullptr;
333 myIDs.insert(o->getGlID());
334 myList->appendItem(name.c_str(), ico, (void*) & (*myIDs.find(o->getGlID())));
336 }
337 myList->update();
338 myCountLabel->setText(TLF("% objects", toString(ids.size())).c_str());
339}
340
341
342long
345 int i = myList->getCurrentItem();
346 if (i >= 0) {
348 if (myList->getItemIcon(i) == flag) {
349 myList->setItemIcon(i, nullptr);
350 } else {
351 myList->setItemIcon(i, flag);
352 }
353 }
354 myList->update();
355 myWindowsParent->getView()->update();
356 return 1;
357}
358
359
360long
363 const int numItems = myList->getNumItems();
364 for (int i = 0; i < numItems; i++) {
365 select(i);
366 myList->setItemIcon(i, flag);
367 }
368 myList->update();
369 myWindowsParent->getView()->update();
370 return 1;
371}
372
373
374long
376 const int numItems = myList->getNumItems();
377 for (int i = 0; i < numItems; i++) {
378 deselect(i);
379 myList->setItemIcon(i, nullptr);
380 }
381 myList->update();
382 myWindowsParent->getView()->update();
383 return 1;
384}
385
386
387long
388GUIDialog_ChooserAbstract::onCmdLocateByName(FXObject*, FXSelector, void*) {
389 std::vector<std::pair<std::string, GUIGlID> > namesAndIDs;
390 myLocateByName = true;
391 const int numItems = myList->getNumItems();
392 for (int i = 0; i < numItems; i++) {
393 GUIGlID glID = *static_cast<GUIGlID*>(myList->getItemData(i));
395 if (o != 0) {
396 const std::string& name = getObjectName(o);
397 if (name != "") {
398 namesAndIDs.push_back(std::make_pair(name, glID));
399 }
400 }
402 }
403 std::sort(namesAndIDs.begin(), namesAndIDs.end());
404 std::vector<GUIGlID> selectedGlIDs;
405 for (const auto& item : namesAndIDs) {
406 selectedGlIDs.push_back(item.second);
407 }
408 refreshList(selectedGlIDs);
409 myTextEntry->setFocus();
410 return 1;
411}
412
413long
414GUIDialog_ChooserAbstract::onCmdUpdate(FXObject*, FXSelector, void*) {
416 return 1;
417}
418
419void
421 GUIGlID* glID = static_cast<GUIGlID*>(myList->getItemData(listIndex));
423}
424
425void
427 GUIGlID* glID = static_cast<GUIGlID*>(myList->getItemData(listIndex));
428 gSelected.select(*glID);
429}
430
431void
433 GUIGlID* glID = static_cast<GUIGlID*>(myList->getItemData(listIndex));
434 gSelected.deselect(*glID);
435}
436
437
438void
439GUIDialog_ChooserAbstract::filterACs(const std::vector<GUIGlID>& /*GLIDs*/) {
440 // overrided in GNEACChooserDialog
441}
442
443/****************************************************************************/
@ MID_CHOOSER_TRACK
Track object.
Definition GUIAppEnum.h:583
@ MID_CANCEL
Cancel-button pressed.
Definition GUIAppEnum.h:310
@ MID_CHOOSER_TEXT
Text entry.
Definition GUIAppEnum.h:585
@ MID_UPDATE
Update-button pressed.
Definition GUIAppEnum.h:312
@ MID_CHOOSEN_INVERT
Deselect selected items.
Definition GUIAppEnum.h:617
@ MID_CHOOSEN_SELECT
select all items
Definition GUIAppEnum.h:613
@ MID_CHOOSER_LIST
Object list.
Definition GUIAppEnum.h:587
@ MID_CHOOSEN_NAME
Deselect selected items.
Definition GUIAppEnum.h:619
@ MID_CHOOSER_FILTER_SUBSTR
Filter list by substring.
Definition GUIAppEnum.h:591
@ MID_CHOOSEN_CLEAR
Clear set.
Definition GUIAppEnum.h:607
@ MID_CHOOSER_FILTER
Filter selected.
Definition GUIAppEnum.h:589
@ MID_CHOOSER_CENTER
Center object.
Definition GUIAppEnum.h:581
#define GUIDesignChooserTextField
design for Chooser TextField
Definition GUIDesigns.h:667
#define GUIDesignChooserListSingle
design for Chooser List
Definition GUIDesigns.h:670
#define GUIDesignChooserButtons
design for Chooser buttons
Definition GUIDesigns.h:664
#define GUIDesignChooserLayoutLeft
design for Chooser Layout left
Definition GUIDesigns.h:679
#define GUIDesignChooserLayoutRight
design for Chooser Layout right
Definition GUIDesigns.h:682
#define GUIDesignHorizontalSeparator
Definition GUIDesigns.h:494
#define GUIDesignChooserLayoutList
design for Chooser Layout list
Definition GUIDesigns.h:685
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition GUIDesigns.h:409
#define GUIDesignChooserDialog
Definition GUIDesigns.h:661
FXDEFMAP(GUIDialog_ChooserAbstract) GUIDialog_ChooserAbstractMap[]
unsigned int GUIGlID
Definition GUIGlObject.h:44
@ GLO_VEHICLE
a vehicle
GUISelectedStorage gSelected
A global holder of selected objects.
@ RECENTERVIEW
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
static FXButton * buildFXButton(FXComposite *p, const std::string &text, const std::string &tip, const std::string &help, FXIcon *ic, FXObject *tgt, FXSelector sel, FXuint opts=BUTTON_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0, FXint pl=DEFAULT_PAD, FXint pr=DEFAULT_PAD, FXint pt=DEFAULT_PAD, FXint pb=DEFAULT_PAD)
build button
bool myLocateByName
whether to locate by object name instead of id
FXButton * myCenterButton
The button that triggers centering on the select object.
long onCmdText(FXObject *, FXSelector, void *)
Callback: Selects to current item if enter is pressed.
long onCmdClose(FXObject *, FXSelector, void *)
Callback: The dialog shall be closed.
void refreshList(const std::vector< GUIGlID > &ids)
update the list with the given ids
long onCmdCenter(FXObject *, FXSelector, void *)
Callback: The selected item shall be centered within the calling view.
FXCheckButton * myCaseSensitive
Whether search is case sensitive.
int myMessageId
the object type being chosen
virtual ~GUIDialog_ChooserAbstract()
Destructor.
long onCmdFilter(FXObject *, FXSelector, void *)
Callback: Hides unselected items if pressed.
long onCmdFilterSubstr(FXObject *, FXSelector, void *)
Callback: Hides unmatched items if pressed.
long onKeyPress(FXObject *o, FXSelector sel, void *data)
keyboard functions
virtual void deselect(int listIndex)
unset selection (handled differently in netedit)
virtual void select(int listIndex)
set selection (handled differently in netedit)
void show()
sets the focus after the window is created to work-around bug in libfox
long onCmdTrack(FXObject *, FXSelector, void *)
Callback: The selected vehicle shall be tracked within the calling view.
long onCmdLocateByName(FXObject *, FXSelector, void *)
Callback: Toggle locator by name.
bool myHaveFilteredSubstring
whether the list was filter by substring
FXLabel * myCountLabel
label for declaring list size
long onChgText(FXObject *, FXSelector, void *)
Callback: Something has been typed into the field.
GUIGlChildWindow * myWindowsParent
window parent
long onCmdUpdate(FXObject *, FXSelector, void *)
Callback: Update list.
std::set< GUIGlID > myIDs
myList contains (void) pointers to elements of myIDs instead of the more volatile pointers to GUIGlOb...
long onChgListSel(FXObject *, FXSelector, void *)
Callback: Current list item selection has changed.
GUIGlObject * mySelected
The chosen id.
long onCmdClearListSelection(FXObject *, FXSelector, void *)
long onCmdAddListSelection(FXObject *, FXSelector, void *)
virtual void toggleSelection(int listIndex)
fox need this
FXButton * myTrackButton
The button that triggers tracking on the select vehicle.
virtual std::string getObjectName(GUIGlObject *o) const
retrieve name for the given object
GUIDialog_ChooserAbstract(GUIGlChildWindow *windowsParent, int messageId, FXIcon *icon, const FXString &title, const std::vector< GUIGlID > &ids, GUIGlObjectStorage &glStorage)
Constructor.
virtual void filterACs(const std::vector< GUIGlID > &GLIDs)
filter ACs (needed in netedit)
FXTextField * myTextEntry
The text field.
long onCmdToggleSelection(FXObject *, FXSelector, void *)
Callback: Toggle selection status of current object / list.
FXCheckButton * myInstantCenter
Whether each change in the list should re-center the view.
long onChgList(FXObject *, FXSelector, void *)
Callback: Current list item has changed.
GUIGlObject * getObject() const
Returns the chosen (selected) object.
FXList * myList
The list that holds the ids.
void setView(GUIGlID id)
Centers the view onto the given artifact.
virtual bool isSelected(GUIGlObject *o) const
true if the object is selected (may include extra logic besides calling gSelected)
GUISUMOAbstractView * getView() const
return GUISUMOAbstractView
GUIMainWindow * getGUIMainWindowParent()
Returns the GUIMainWindow parent.
virtual std::vector< GUIGlID > getObjectIDs(int messageId) const
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
virtual const std::string getOptionalName() const
Returns the name of the object (default "")
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
GUIGlID getGlID() const
Returns the numerical id of the object.
A storage for of displayed objects via their numerical id.
void unblockObject(GUIGlID id)
Marks an object as unblocked.
GUIGlObject * getObjectBlocking(GUIGlID id) const
Returns the object from the container locking it.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
void removeChild(FXMainWindow *child)
removes the given child window from the list (FXMainWindow)
void addChild(FXMainWindow *child)
Adds a further child window to the list (FXMainWindow)
Persists window position in the registry.
virtual void stopTrack()
stop track
virtual void startTrack(int)
star track
void toggleSelection(GUIGlID id)
Toggles selection of an object.
void select(GUIGlID id, bool update=true)
Adds the object with the given id.
void deselect(GUIGlID id)
Deselects the object with the given id.