Eclipse SUMO - Simulation of Urban MObility
GUIDialog_ChooserAbstract.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2022 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>
36
38
39
40// ===========================================================================
41// FOX callback mapping
42// ===========================================================================
43FXDEFMAP(GUIDialog_ChooserAbstract) GUIDialog_ChooserAbstractMap[] = {
59};
60
61FXIMPLEMENT(GUIDialog_ChooserAbstract, FXMainWindow, GUIDialog_ChooserAbstractMap, ARRAYNUMBER(GUIDialog_ChooserAbstractMap))
62
63
64// ===========================================================================
65// method definitions
66// ===========================================================================
68 FXIcon* icon, const FXString& title, const std::vector<GUIGlID>& ids, GUIGlObjectStorage& /*glStorage*/) :
69 FXMainWindow(windowsParent->getApp(), title, icon, nullptr, GUIDesignChooserDialog),
70 myWindowsParent(windowsParent),
71 myMessageId(messageId),
72 myLocateByName(false),
73 myHaveFilteredSubstring(false) {
74 FXHorizontalFrame* hbox = new FXHorizontalFrame(this, GUIDesignAuxiliarFrame);
75 // build the list
76 FXVerticalFrame* layoutLeft = new FXVerticalFrame(hbox, GUIDesignChooserLayoutLeft);
77 myTextEntry = new FXTextField(layoutLeft, 0, this, MID_CHOOSER_TEXT, TEXTFIELD_ENTER_ONLY | GUIDesignChooserTextField);
78 FXVerticalFrame* layoutList = new FXVerticalFrame(layoutLeft, GUIDesignChooserLayoutList);
79 myList = new FXList(layoutList, this, MID_CHOOSER_LIST, GUIDesignChooserListSingle);
80 // build the buttons
81 FXVerticalFrame* layoutRight = new FXVerticalFrame(hbox, GUIDesignChooserLayoutRight);
82 myCenterButton = new FXButton(layoutRight, TL("Center\t\t"), GUIIconSubSys::getIcon(GUIIcon::RECENTERVIEW), this, MID_CHOOSER_CENTER, GUIDesignChooserButtons);
83 myTrackButton = new FXButton(layoutRight, TL("Track\t\t"), GUIIconSubSys::getIcon(GUIIcon::RECENTERVIEW), this, MID_CHOOSER_TRACK, GUIDesignChooserButtons);
84 // only enable Track Button if we're locating vehicles
85 if (title.text() != std::string("Vehicle Chooser")) {
86 myTrackButton->disable();
87 myTrackButton->hide();
88 }
89 new FXHorizontalSeparator(layoutRight, GUIDesignHorizontalSeparator);
90 new FXButton(layoutRight, TL("&Hide Unselected\t\t"), GUIIconSubSys::getIcon(GUIIcon::FLAG), this, MID_CHOOSER_FILTER, GUIDesignChooserButtons);
91 new FXButton(layoutRight, TL("By &Name\tLocate item by name\t"), nullptr, this, MID_CHOOSEN_NAME, GUIDesignChooserButtons);
92 new FXButton(layoutRight, TL("&Select/deselect\t\tSelect/deselect current object"), GUIIconSubSys::getIcon(GUIIcon::FLAG), this, MID_CHOOSEN_INVERT, GUIDesignChooserButtons);
93 new FXButton(layoutRight, TL("&Filter substring\t\t"), nullptr, this, MID_CHOOSER_FILTER_SUBSTR, GUIDesignChooserButtons);
94 new FXButton(layoutRight, TL("Select &all\t\tSelect all items in list"), GUIIconSubSys::getIcon(GUIIcon::FLAG), this, MID_CHOOSEN_SELECT, GUIDesignChooserButtons);
95 new FXButton(layoutRight, TL("&Deselect all\t\tDeselect all items in list"), GUIIconSubSys::getIcon(GUIIcon::FLAG), this, MID_CHOOSEN_CLEAR, GUIDesignChooserButtons);
96 new FXButton(layoutRight, TL("&Update\t\tReload all ids"), GUIIconSubSys::getIcon(GUIIcon::RELOAD), this, MID_UPDATE, GUIDesignChooserButtons);
97 new FXHorizontalSeparator(layoutRight, GUIDesignHorizontalSeparator);
98 new FXButton(layoutRight, TL("&Close\t\t"), GUIIconSubSys::getIcon(GUIIcon::NO), this, MID_CANCEL, GUIDesignChooserButtons);
99 myCountLabel = new FXLabel(layoutRight, "placeholder", nullptr, LAYOUT_BOTTOM | LAYOUT_FILL_X | JUSTIFY_LEFT);
100 myCaseSensitive = new FXCheckButton(layoutRight, TL("case-sensitive search"));
101 myCaseSensitive->setCheck(getApp()->reg().readIntEntry("LOCATOR", "caseSensitive", 0) == 1);
102 myInstantCenter = new FXCheckButton(layoutRight, TL("auto-center"));
103 myInstantCenter->setCheck(getApp()->reg().readIntEntry("LOCATOR", "autoCenter", 0) == 1);
104 refreshList(ids);
105 // add child in windowsParent
106 myWindowsParent->getParent()->addChild(this);
107 // create and show dialog
108 create();
109 show();
110
111 getApp()->reg().writeIntEntry("TL_TRACKER", "x", getX());
112}
113
114
116 // remove child from windowsParent
118 getApp()->reg().writeIntEntry("LOCATOR", "autoCenter", myInstantCenter->getCheck());
119 getApp()->reg().writeIntEntry("LOCATOR", "caseSensitive", myCaseSensitive->getCheck());
120}
121
122
125 return static_cast<GUIGlObject*>(mySelected);
126}
127
128
129void
131 FXMainWindow::show();
132 myTextEntry->setFocus();
133}
134
135
136long
137GUIDialog_ChooserAbstract::onCmdCenter(FXObject*, FXSelector, void*) {
138 int selected = myList->getCurrentItem();
139 if (selected >= 0) {
141 myWindowsParent->setView(*static_cast<GUIGlID*>(myList->getItemData(selected)));
142 }
143 return 1;
144}
145
146
147long
148GUIDialog_ChooserAbstract::onCmdTrack(FXObject*, FXSelector, void*) {
149 int selected = myList->getCurrentItem();
150 if (selected >= 0) {
151 myWindowsParent->setView(*static_cast<GUIGlID*>(myList->getItemData(selected)));
152 GUIGlID id = *static_cast<GUIGlID*>(myList->getItemData(selected));
154 if (o->getType() == GLO_VEHICLE) {
156 }
158 }
159 return 1;
160}
161
162
163long
164GUIDialog_ChooserAbstract::onCmdClose(FXObject*, FXSelector, void*) {
165 close(true);
166 return 1;
167}
168
169long
170GUIDialog_ChooserAbstract::onChgList(FXObject*, FXSelector, void*) {
171 // mouse-click toggles item selection but changked current item with
172 // keyboard does not affect select
173 // Enabling the line blow toggles the behavior (which must be fixed via onChgListSel)
174 myList->selectItem(myList->getCurrentItem());
175 if (myInstantCenter->getCheck()) {
176 onCmdCenter(nullptr, 0, nullptr);
177 }
178 return 1;
179}
180
181long
182GUIDialog_ChooserAbstract::onChgListSel(FXObject*, FXSelector, void*) {
183 myList->selectItem(myList->getCurrentItem());
184 return 1;
185}
186
187long
188GUIDialog_ChooserAbstract::onChgText(FXObject*, FXSelector, void*) {
189 const bool caseSensitive = myCaseSensitive->getCheck() == TRUE;
190 int id = -1;
192 // findItem does not support substring search
193 const int numItems = myList->getNumItems();
194 FXString t = myTextEntry->getText();
195 if (!caseSensitive) {
196 t = t.lower();
197 }
198 for (int i = 0; i < numItems; i++) {
199 FXString t2 = myList->getItemText(i);
200 if (!caseSensitive) {
201 t2 = t2.lower();
202 }
203 if (t2.find(t) >= 0) {
204 id = i;
205 break;
206 }
207 }
208 } else {
209 const int caseOpt = caseSensitive ? 0 : SEARCH_IGNORECASE;
210 id = myList->findItem(myTextEntry->getText(), -1, SEARCH_PREFIX | caseOpt);
211 }
212 if (id < 0) {
213 if (myList->getNumItems() > 0) {
214 myList->deselectItem(myList->getCurrentItem());
215 }
216 myCenterButton->disable();
217 myTrackButton->disable();
218 return 1;
219 }
220 myList->deselectItem(myList->getCurrentItem());
221 myList->makeItemVisible(id);
222 myList->selectItem(id);
223 myList->setCurrentItem(id, true);
224 myCenterButton->enable();
225 myTrackButton->enable();
226 return 1;
227}
228
229
230long
231GUIDialog_ChooserAbstract::onCmdText(FXObject*, FXSelector, void*) {
232 int current = myList->getCurrentItem();
233 if (current >= 0 && myList->isItemSelected(current)) {
234 myWindowsParent->setView(*static_cast<GUIGlID*>(myList->getItemData(current)));
235 }
236 return 1;
237}
238
239
240
241long
242GUIDialog_ChooserAbstract::onListKeyPress(FXObject*, FXSelector, void* ptr) {
243 FXEvent* event = (FXEvent*)ptr;
244 if (event->code == KEY_Return) {
245 onCmdText(nullptr, 0, nullptr);
246 if ((event->state & CONTROLMASK) != 0) {
247 close(true);
248 }
249 return 1;
250 } else if (event->code == KEY_Left || (event->code == KEY_Up && myList->getCurrentItem() == 0)) {
251 myTextEntry->setFocus();
252 return 1;
253 }
254 // let other elements handle the keypress
255 return 0;
256}
257
258
259long
260GUIDialog_ChooserAbstract::onCmdFilter(FXObject*, FXSelector, void*) {
262 std::vector<GUIGlID> selectedGlIDs;
263 const int numItems = myList->getNumItems();
264 for (int i = 0; i < numItems; i++) {
265 const GUIGlID glID = *static_cast<GUIGlID*>(myList->getItemData(i));
266 if (myList->getItemIcon(i) == flag) {
267 selectedGlIDs.push_back(glID);
268 }
269 }
270 refreshList(selectedGlIDs);
271 return 1;
272}
273
274
275long
276GUIDialog_ChooserAbstract::onCmdFilterSubstr(FXObject*, FXSelector, void*) {
277 const bool caseSensitive = myCaseSensitive->getCheck() == TRUE;
278 std::vector<GUIGlID> selectedGlIDs;
279 const int numItems = myList->getNumItems();
280 FXString t = myTextEntry->getText();
281 if (!caseSensitive) {
282 t = t.lower();
283 }
284 for (int i = 0; i < numItems; i++) {
285 FXString t2 = myList->getItemText(i);
286 if (!caseSensitive) {
287 t2 = t2.lower();
288 }
289 if (t2.find(t) >= 0) {
290 const GUIGlID glID = *static_cast<GUIGlID*>(myList->getItemData(i));
291 selectedGlIDs.push_back(glID);
292 }
293 }
294 refreshList(selectedGlIDs);
295 // filter ACs in NETEDIT
296 filterACs(selectedGlIDs);
298 onChgText(nullptr, 0, nullptr);
299 return 1;
300}
301
302
303std::string
305 if (myLocateByName) {
306 return o->getOptionalName();
307 } else {
308 return o->getMicrosimID();
309 }
310}
311
312void
313GUIDialog_ChooserAbstract::refreshList(const std::vector<GUIGlID>& ids) {
314 myList->clearItems();
315 for (auto i : ids) {
317 if (o == nullptr) {
318 continue;
319 }
320 const std::string& name = getObjectName(o);
321 const bool selected = myWindowsParent->isSelected(o);
322 FXIcon* const ico = selected ? GUIIconSubSys::getIcon(GUIIcon::FLAG) : nullptr;
323 myIDs.insert(o->getGlID());
324 myList->appendItem(name.c_str(), ico, (void*) & (*myIDs.find(o->getGlID())));
326 }
327 myList->update();
328 myCountLabel->setText((toString(ids.size()) + " objects").c_str());
329}
330
331
332long
335 int i = myList->getCurrentItem();
336 if (i >= 0) {
338 if (myList->getItemIcon(i) == flag) {
339 myList->setItemIcon(i, nullptr);
340 } else {
341 myList->setItemIcon(i, flag);
342 }
343 }
344 myList->update();
345 myWindowsParent->getView()->update();
346 return 1;
347}
348
349
350long
353 const int numItems = myList->getNumItems();
354 for (int i = 0; i < numItems; i++) {
355 select(i);
356 myList->setItemIcon(i, flag);
357 }
358 myList->update();
359 myWindowsParent->getView()->update();
360 return 1;
361}
362
363
364long
366 const int numItems = myList->getNumItems();
367 for (int i = 0; i < numItems; i++) {
368 deselect(i);
369 myList->setItemIcon(i, nullptr);
370 }
371 myList->update();
372 myWindowsParent->getView()->update();
373 return 1;
374}
375
376
377long
378GUIDialog_ChooserAbstract::onCmdLocateByName(FXObject*, FXSelector, void*) {
379 std::vector<std::pair<std::string, GUIGlID> > namesAndIDs;
380 myLocateByName = true;
381 const int numItems = myList->getNumItems();
382 for (int i = 0; i < numItems; i++) {
383 GUIGlID glID = *static_cast<GUIGlID*>(myList->getItemData(i));
385 if (o != 0) {
386 const std::string& name = getObjectName(o);
387 if (name != "") {
388 namesAndIDs.push_back(std::make_pair(name, glID));
389 }
390 }
392 }
393 std::sort(namesAndIDs.begin(), namesAndIDs.end());
394 std::vector<GUIGlID> selectedGlIDs;
395 for (const auto& item : namesAndIDs) {
396 selectedGlIDs.push_back(item.second);
397 }
398 refreshList(selectedGlIDs);
399 myTextEntry->setFocus();
400 return 1;
401}
402
403long
404GUIDialog_ChooserAbstract::onCmdUpdate(FXObject*, FXSelector, void*) {
406 return 1;
407}
408
409void
411 GUIGlID* glID = static_cast<GUIGlID*>(myList->getItemData(listIndex));
413}
414
415void
417 GUIGlID* glID = static_cast<GUIGlID*>(myList->getItemData(listIndex));
418 gSelected.select(*glID);
419}
420
421void
423 GUIGlID* glID = static_cast<GUIGlID*>(myList->getItemData(listIndex));
424 gSelected.deselect(*glID);
425}
426
427
428void
429GUIDialog_ChooserAbstract::filterACs(const std::vector<GUIGlID>& /*GLIDs*/) {
430 // overrided in GNEDialogACChooser
431}
432
433/****************************************************************************/
@ MID_CHOOSER_TRACK
Track object.
Definition: GUIAppEnum.h:572
@ MID_CANCEL
Cancel-button pressed.
Definition: GUIAppEnum.h:261
@ MID_CHOOSER_TEXT
Text entry.
Definition: GUIAppEnum.h:574
@ MID_UPDATE
Update-button pressed.
Definition: GUIAppEnum.h:263
@ MID_CHOOSEN_INVERT
Deselect selected items.
Definition: GUIAppEnum.h:606
@ MID_CHOOSEN_SELECT
select all items
Definition: GUIAppEnum.h:602
@ MID_CHOOSER_LIST
Object list.
Definition: GUIAppEnum.h:576
@ MID_CHOOSEN_NAME
Deselect selected items.
Definition: GUIAppEnum.h:608
@ MID_CHOOSER_FILTER_SUBSTR
Filter list by substring.
Definition: GUIAppEnum.h:580
@ MID_CHOOSEN_CLEAR
Clear set.
Definition: GUIAppEnum.h:596
@ MID_CHOOSER_FILTER
Filter selected.
Definition: GUIAppEnum.h:578
@ MID_CHOOSER_CENTER
Center object.
Definition: GUIAppEnum.h:570
#define GUIDesignChooserTextField
design for Chooser TextField
Definition: GUIDesigns.h:633
#define GUIDesignChooserListSingle
design for Chooser List
Definition: GUIDesigns.h:636
#define GUIDesignChooserButtons
design for Chooser buttons
Definition: GUIDesigns.h:630
#define GUIDesignChooserLayoutLeft
design for Chooser Layout left
Definition: GUIDesigns.h:645
#define GUIDesignChooserLayoutRight
design for Chooser Layout right
Definition: GUIDesigns.h:648
#define GUIDesignHorizontalSeparator
Definition: GUIDesigns.h:452
#define GUIDesignChooserLayoutList
design for Chooser Layout list
Definition: GUIDesigns.h:651
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frames used to pack another frames extended in all directions
Definition: GUIDesigns.h:394
#define GUIDesignChooserDialog
Definition: GUIDesigns.h:627
FXDEFMAP(GUIDialog_ChooserAbstract) GUIDialog_ChooserAbstractMap[]
unsigned int GUIGlID
Definition: GUIGlObject.h:43
@ GLO_VEHICLE
a vehicle
GUISelectedStorage gSelected
A global holder of selected objects.
@ RECENTERVIEW
#define TL(string)
Definition: MsgHandler.h:282
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
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.
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 onListKeyPress(FXObject *, FXSelector, void *)
Callback: Selects to current item if enter is pressed.
long onChgText(FXObject *, FXSelector, void *)
Callback: Something has been typed into the 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
@bbrief retrieve name for the given object
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
virtual std::vector< GUIGlID > getObjectIDs(int messageId) const
GUIMainWindow * getParent()
Returns the main window.
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
Definition: GUIGlObject.h:141
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.
Definition: GUIGlObject.h:154
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GUIGlObject.h:102
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)
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.
const unsigned char flag[]
Definition: flag.cpp:24
Definition: json.hpp:4471