Eclipse SUMO - Simulation of Urban MObility
MFXComboBoxIcon.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2006-2024 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 /****************************************************************************/
19 //
20 /****************************************************************************/
21 
22 // =========================================================================
23 // included modules
24 // =========================================================================
25 
29 
30 #include "MFXComboBoxIcon.h"
31 
32 // =========================================================================
33 // defines
34 // =========================================================================
35 
36 #define ICON_SPACING 4 // Spacing between icon and label (2 + 2)
37 #define ICON_SIZE 16
38 
39 // ===========================================================================
40 // FOX callback mapping
41 // ===========================================================================
42 
43 FXDEFMAP(MFXComboBoxIcon) MFXComboBoxIconMap[] = {
44  FXMAPFUNC(SEL_FOCUS_UP, 0, MFXComboBoxIcon::onFocusUp),
45  FXMAPFUNC(SEL_FOCUS_DOWN, 0, MFXComboBoxIcon::onFocusDown),
46  FXMAPFUNC(SEL_FOCUS_SELF, 0, MFXComboBoxIcon::onFocusSelf),
50  FXMAPFUNC(SEL_LEFTBUTTONPRESS, MFXComboBoxIcon::ID_TEXT, MFXComboBoxIcon::onTextButton),
51  FXMAPFUNC(SEL_MOUSEWHEEL, MFXComboBoxIcon::ID_TEXT, MFXComboBoxIcon::onMouseWheel),
54  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETVALUE, MFXComboBoxIcon::onFwdToText),
55  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETINTVALUE, MFXComboBoxIcon::onFwdToText),
56  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETREALVALUE, MFXComboBoxIcon::onFwdToText),
57  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETSTRINGVALUE, MFXComboBoxIcon::onFwdToText),
58  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETINTVALUE, MFXComboBoxIcon::onFwdToText),
59  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETREALVALUE, MFXComboBoxIcon::onFwdToText),
60  FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETSTRINGVALUE, MFXComboBoxIcon::onFwdToText),
62 };
63 
64 // Object implementation
65 FXIMPLEMENT(MFXComboBoxIcon, FXPacker, MFXComboBoxIconMap, ARRAYNUMBER(MFXComboBoxIconMap))
66 
67 // ===========================================================================
68 // member method definitions
69 // ===========================================================================
70 
71 MFXComboBoxIcon::MFXComboBoxIcon(FXComposite* p, FXint cols, const bool canSearch, const int visibleItems,
72  FXObject* tgt, FXSelector sel, FXuint opts, FXint x, FXint y, FXint w, FXint h, FXint pl, FXint pr, FXint pt, FXint pb):
73  FXPacker(p, opts, x, y, w, h, 0, 0, 0, 0, 0, 0) {
74  flags |= FLAG_ENABLED;
75  target = tgt;
76  message = sel;
77  // create text field
78  myTextFieldIcon = new MFXTextFieldIcon(this, cols, nullptr, this, MFXComboBoxIcon::ID_TEXT, 0, 0, 0, 0, 0, pl, pr, pt, pb);
79  if (options & COMBOBOX_STATIC) {
80  myTextFieldIcon->setEditable(FALSE);
81  }
82  // create pane for list
83  myPane = new FXPopup(this, FRAME_LINE);
84  // check if create search button
85  if (canSearch) {
86  myTextFieldSearch = new MFXTextFieldSearch(myPane, 1, this, ID_SEARCH, FRAME_THICK | LAYOUT_FIX_WIDTH | LAYOUT_FIX_HEIGHT, 0, 0, 0, 0, 2, 2, 2, 2);
87  // create label for empty icon
88  myNoItemsLabel = new FXLabel(myPane, TL("No matches found"), nullptr, FRAME_THICK | LAYOUT_FIX_WIDTH | LAYOUT_FIX_HEIGHT, 0, 0, 0, 0, 2, 2, 2, 2);
89  myNoItemsLabel->setTextColor(FXRGB(255, 0, 0));
90  myNoItemsLabel->hide();
91  }
92  // create list icon
93  myList = new MFXListIcon(myPane, this, MFXComboBoxIcon::ID_LIST, LIST_BROWSESELECT | LIST_AUTOSELECT | LAYOUT_FILL_X | LAYOUT_FILL_Y | SCROLLERS_TRACK | HSCROLLER_NEVER);
94  if (options & COMBOBOX_STATIC) {
95  myList->setScrollStyle(SCROLLERS_TRACK | HSCROLLING_OFF);
96  }
97  myList->setNumVisible(visibleItems);
98  // create button
99  myButton = new FXMenuButton(this, FXString::null, NULL, myPane, FRAME_RAISED | FRAME_THICK | MENUBUTTON_DOWN | MENUBUTTON_ATTACH_RIGHT, 0, 0, 0, 0, 0, 0, 0, 0);
100  myButton->setXOffset(border);
101  myButton->setYOffset(border);
102  flags &= ~(FXuint)FLAG_UPDATE; // Never GUI update
103 
104 }
105 
106 
108  delete myPane;
109  myPane = (FXPopup*) - 1L;
111  myButton = (FXMenuButton*) - 1L;
112  if (myTextFieldSearch) {
114  myNoItemsLabel = (FXLabel*) - 1L;
115  }
116  myList = (MFXListIcon*) - 1L;
117 }
118 
119 
120 void
122  FXPacker::create();
123  myPane->create();
124 }
125 
126 
127 void
129  FXPacker::detach();
130  myPane->detach();
131 }
132 
133 
134 void
136  myPane->destroy();
137  FXPacker::destroy();
138 }
139 
140 
141 void
143  if (!isEnabled()) {
144  FXPacker::enable();
146  myButton->enable();
147  }
148 }
149 
150 
151 void
153  if (isEnabled()) {
154  FXPacker::disable();
156  myButton->disable();
157  }
158 }
159 
160 
161 FXint
163  FXint ww = myTextFieldIcon->getDefaultWidth() + myButton->getDefaultWidth() + (border << 1);
164  FXint pw = myPane->getDefaultWidth();
165  return FXMAX(ww, pw);
166 }
167 
168 
169 FXint
171  FXint th, bh;
173  bh = myButton->getDefaultHeight();
174  return FXMAX(th, bh) + (border << 1);
175 }
176 
177 
178 void
180  const FXint itemHeight = height - (border << 1);
181  const FXint buttonWidth = myButton->getDefaultWidth();
182  const FXint textWidth = width - buttonWidth - (border << 1);
183  myTextFieldIcon->position(border, border, textWidth, itemHeight);
184  myButton->position(border + textWidth, border, buttonWidth, itemHeight);
185  if (myTextFieldSearch) {
186  myTextFieldSearch->resize(width, height);
187  myNoItemsLabel->resize(width, height);
188  }
189  myPane->resize(width, myPane->getDefaultHeight());
190  flags &= ~(FXuint)FLAG_DIRTY;
191 }
192 
193 
194 FXString
196  return myTextFieldIcon->getText();
197 }
198 
199 
200 FXint
202  return myList->getNumItems();
203 }
204 
205 
206 void
208  myList->setNumVisible(nvis);
209 }
210 
211 
212 void
213 MFXComboBoxIcon::setText(const FXString& text) {
214  myTextFieldIcon->setText(text);
215 }
216 
217 
218 FXbool
219 MFXComboBoxIcon::isItemCurrent(FXint index) const {
220  return myList->isItemCurrent(index);
221 }
222 
223 
224 long
225 MFXComboBoxIcon::setCurrentItem(const FXint index, FXbool notify) {
226  if (index >= 0 && index <= myList->getNumItems()) {
227  // get item
228  MFXListIconItem* item = myList->getItem(index);
229  // set it as current item and make it visible
230  myList->setCurrentItem(item);
231  myList->makeItemVisible(index);
232  // update both text fields
233  myTextFieldIcon->setText(item->getText());
234  myTextFieldIcon->setIcon(item->getIcon());
235  myTextFieldIcon->setBackColor(item->getBackGroundColor());
236  // check if notify
237  if (notify && target) {
238  return target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)item);
239  }
240  } else {
241  fxerror("%s::setItem: index out of range.\n", getClassName());
242  }
243  return 0;
244 }
245 
246 
247 long
248 MFXComboBoxIcon::setCurrentItem(const FXString& text, FXbool notify) {
249  // check if item exist
250  for (int i = 0; i < myList->getNumItems(); i++) {
251  const auto itemText = myList->tolowerString(myList->getItem(i)->getText());
252  if (myList->tolowerString(text) == itemText) {
253  // use "set curent item" function
254  return setCurrentItem(i, notify);
255  }
256  }
257  return 0;
258 }
259 
260 
261 FXint
263  return myList->getCurrentItemIndex();
264 }
265 
266 
267 FXint
268 MFXComboBoxIcon::updateIconItem(FXint index, const FXString& text, FXIcon* icon, FXColor bgColor, void* ptr) {
269  if (index < 0 || myList->getNumItems() <= index) {
270  fxerror("%s::setItem: index out of range.\n", getClassName());
271  }
272  myList->editItem(index, text, NULL, ptr);
273  if (isItemCurrent(index)) {
274  myTextFieldIcon->setText(text);
275  myTextFieldIcon->setBackColor(bgColor);
276  myTextFieldIcon->setIcon(icon);
277  }
278  recalc();
279  return index;
280 }
281 
282 
283 FXint
284 MFXComboBoxIcon::insertIconItem(FXint index, const FXString& text, FXIcon* icon, FXColor bgColor, void* ptr) {
285  index = myList->insertItem(index, new MFXListIconItem(text, icon, bgColor, ptr));
286  if (isItemCurrent(index)) {
287  myTextFieldIcon->setText(text);
288  myTextFieldIcon->setBackColor(bgColor);
289  myTextFieldIcon->setIcon(icon);
290  }
291  recalc();
292  return index;
293 }
294 
295 
296 FXint
297 MFXComboBoxIcon::appendIconItem(const FXString& text, FXIcon* icon, FXColor bgColor, void* ptr) {
298  FXint index = myList->appendItem(new MFXListIconItem(text, icon, bgColor, ptr));
299  if (isItemCurrent(getNumItems() - 1)) {
300  myTextFieldIcon->setText(text);
301  myTextFieldIcon->setBackColor(bgColor);
302  myTextFieldIcon->setIcon(icon);
303  }
304  recalc();
305  return index;
306 }
307 
308 
309 void
311  const auto isCurrent = myList->isItemCurrent(index);
312  if (isCurrent == TRUE) {
313  if ((index > 0) && (index < (int)myList->getNumItems())) {
314  setCurrentItem(index - 1);
315  } else if (myList->getNumItems() > 0) {
316  setCurrentItem(0);
317  }
318  }
319  myList->removeItem(index);
320  recalc();
321 }
322 
323 
324 void
327  myList->clearItems();
328  recalc();
329 }
330 
331 
332 FXint
333 MFXComboBoxIcon::findItem(const FXString& text) const {
334  return myList->findItem(text);
335 }
336 
337 
338 std::string
339 MFXComboBoxIcon::getItemText(FXint index) const {
340  return myList->getItem(index)->getText().text();
341 }
342 
343 
344 void
346  myTextFieldIcon->setBackColor(clr);
347  myList->setBackColor(clr);
348 }
349 
350 
351 void
354  myList->setTextColor(clr);
355 }
356 
357 
358 FXColor
360  return myTextFieldIcon->getTextColor();
361 }
362 
363 
364 void
365 MFXComboBoxIcon::setTipText(const FXString& txt) {
367 }
368 
369 
370 const FXString&
372  return myTextFieldIcon->getTipText();
373 }
374 
375 
376 long
377 MFXComboBoxIcon::onUpdFmText(FXObject*, FXSelector, void*) {
378  return (target && !myPane->shown()) ? target->tryHandle(this, FXSEL(SEL_UPDATE, message), NULL) : 0;
379 }
380 
381 
382 long
383 MFXComboBoxIcon::onCmdFilter(FXObject*, FXSelector, void* ptr) {
385  myPane->resize(width, myPane->getDefaultHeight());
386  myPane->recalc();
387  myPane->onPaint(0, 0, ptr);
388  return 1;
389 }
390 
391 
392 long
393 MFXComboBoxIcon::onFwdToText(FXObject* sender, FXSelector sel, void* ptr) {
394  return myTextFieldIcon->handle(sender, sel, ptr);
395 }
396 
397 
398 long
399 MFXComboBoxIcon::onListClicked(FXObject*, FXSelector sel, void* ptr) {
400  // hide pane
401  myButton->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
402  if (FXSELTYPE(sel) == SEL_COMMAND) {
403  // cast MFXListIconItem
404  const MFXListIconItem* item = (MFXListIconItem*)ptr;
405  // set icon and background color
406  myTextFieldIcon->setText(item->getText());
407  myTextFieldIcon->setIcon(item->getIcon());
408  myTextFieldIcon->setBackColor(item->getBackGroundColor());
409  // Select if editable
410  if (!(options & COMBOBOX_STATIC)) {
412  }
413  if (target) {
414  target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)getText().text());
415  }
416  }
417  return 1;
418 }
419 
420 
421 long
422 MFXComboBoxIcon::onTextButton(FXObject*, FXSelector, void*) {
423  if (options & COMBOBOX_STATIC) {
424  // Post the myList
425  myButton->handle(this, FXSEL(SEL_COMMAND, ID_POST), NULL);
426  return 1;
427  }
428  return 0;
429 }
430 
431 
432 long
433 MFXComboBoxIcon::onTextChanged(FXObject*, FXSelector, void* ptr) {
434  return target ? target->tryHandle(this, FXSEL(SEL_CHANGED, message), ptr) : 0;
435 }
436 
437 
438 long
439 MFXComboBoxIcon::onTextCommand(FXObject*, FXSelector, void* ptr) {
440  // reset background colors
441  myTextFieldIcon->setBackColor(FXRGB(255, 255, 255));
442  // check if item exist
443  for (int i = 0; i < myList->getNumItems(); i++) {
444  const auto itemText = myList->tolowerString(myList->getItem(i)->getText());
445  if (myList->tolowerString(myTextFieldIcon->getText()) == itemText) {
446  // use "set curent item" function
447  return setCurrentItem(i, TRUE);
448  }
449  }
450  // no item found, then reset icon label
452  return target ? target->tryHandle(this, FXSEL(SEL_COMMAND, message), ptr) : 0;
453 }
454 
455 
456 long
457 MFXComboBoxIcon::onFocusSelf(FXObject* sender, FXSelector, void* ptr) {
458  return myTextFieldIcon->handle(sender, FXSEL(SEL_FOCUS_SELF, 0), ptr);
459 }
460 
461 
462 long
463 MFXComboBoxIcon::onFocusUp(FXObject*, FXSelector, void*) {
464  if (isEnabled()) {
465  FXint index = getCurrentItem();
466  if (index < 0) {
467  index = getNumItems() - 1;
468  } else if (0 < index) {
469  index--;
470  }
471  if (0 <= index && index < getNumItems()) {
472  setCurrentItem(index, TRUE);
473  }
474  return 1;
475  }
476  return 0;
477 }
478 
479 
480 long
481 MFXComboBoxIcon::onFocusDown(FXObject*, FXSelector, void*) {
482  if (isEnabled()) {
483  FXint index = getCurrentItem();
484  if (index < 0) {
485  index = 0;
486  } else if (index < getNumItems() - 1) {
487  index++;
488  }
489  if (0 <= index && index < getNumItems()) {
490  setCurrentItem(index, TRUE);
491  }
492  return 1;
493  }
494  return 0;
495 }
496 
497 
498 long MFXComboBoxIcon::onMouseWheel(FXObject*, FXSelector, void* ptr) {
499  FXEvent* event = (FXEvent*)ptr;
500  if (isEnabled()) {
501  FXint index = getCurrentItem();
502  if (event->code < 0) {
503  if (index < 0) {
504  index = 0;
505  } else if (index < getNumItems() - 1) {
506  index++;
507  }
508  } else if (event->code > 0) {
509  if (index < 0) {
510  index = getNumItems() - 1;
511  } else if (0 < index) {
512  index--;
513  }
514  }
515  if (0 <= index && index < getNumItems()) {
516  setCurrentItem(index, TRUE);
517  }
518  return 1;
519  }
520  return 0;
521 }
522 
523 
@ MID_MTEXTFIELDSEARCH_UPDATED
callback for MFXTextFieldSearch
Definition: GUIAppEnum.h:1586
FXDEFMAP(MFXComboBoxIcon) MFXComboBoxIconMap[]
#define TL(string)
Definition: MsgHandler.h:315
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
ComboBox with icon.
FXbool isItemCurrent(FXint index) const
Return true if current item.
FXint insertIconItem(FXint index, const FXString &text, FXIcon *icon=nullptr, FXColor bgColor=FXRGB(255, 255, 255), void *ptr=nullptr)
insert icon item in the given position
long setCurrentItem(const FXint index, FXbool notify=FALSE)
Set the current item (index is zero-based)
void layout()
Perform layout.
FXint getCurrentItem() const
Get the current item's index.
void destroy()
Destroy server-side resources.
FXint findItem(const FXString &text) const
find item
long onTextChanged(FXObject *, FXSelector, void *)
void removeItem(FXint index)
Remove this item from the list.
long onFwdToText(FXObject *, FXSelector, void *)
FXint getNumItems() const
Return the number of items in the list.
FXLabel * myNoItemsLabel
no items label
const FXString & getTipText() const
Get the tool tip message for this combobox.
long onMouseWheel(FXObject *, FXSelector, void *)
FXint getDefaultWidth()
Return default width.
MFXTextFieldSearch * myTextFieldSearch
text field search
void setBackColor(FXColor clr)
Set window background color.
long onListClicked(FXObject *, FXSelector, void *)
FXMenuButton * myButton
myButton
MFXListIcon * myList
list with all items
FXString getText() const
Get the text.
long onCmdFilter(FXObject *, FXSelector, void *)
void setTextColor(FXColor clr)
Change text color.
FXPopup * myPane
popup in which place search label and list
void setNumVisible(FXint nvis)
Set the number of visible items in the drop down list.
~MFXComboBoxIcon()
Destructor.
void clearItems()
Remove all items from the list.
FXint updateIconItem(FXint index, const FXString &text, FXIcon *icon=nullptr, FXColor bgColor=FXRGB(255, 255, 255), void *ptr=nullptr)
Replace the item at index.
FXint getDefaultHeight()
Return default height.
long onTextButton(FXObject *, FXSelector, void *)
void setText(const FXString &text)
Set the text in the textField.
void setTipText(const FXString &txt)
Set the tool tip message for this combobox.
std::string getItemText(FXint index) const
Get text for specified item.
void disable()
Disable combo box.
MFXComboBoxIcon()
FOX need this.
FXColor getTextColor() const
Return text color.
long onUpdFmText(FXObject *, FXSelector, void *)
FXint appendIconItem(const FXString &text, FXIcon *icon=nullptr, FXColor bgColor=FXRGB(255, 255, 255), void *ptr=nullptr)
append icon item in the last position
void enable()
Enable combo box.
MFXTextFieldIcon * myTextFieldIcon
textField icon
long onTextCommand(FXObject *, FXSelector, void *)
void detach()
Detach server-side resources.
void create()
Create server-side resources.
long onFocusDown(FXObject *, FXSelector, void *)
long onFocusSelf(FXObject *, FXSelector, void *)
long onFocusUp(FXObject *, FXSelector, void *)
Commands.
A list item which allows for custom coloring.
Definition: MFXListIcon.h:30
void setNumVisible(FXint nvis)
Change the number of visible items.
void makeItemVisible(MFXListIconItem *item)
Scroll to bring item into view.
FXint editItem(FXint index, const FXString &text, FXIcon *icon=NULL, void *ptr=NULL, FXbool notify=FALSE)
Replace items text, icon, and user-data pointer.
int findItem(const FXString &text) const
Search items by name (In all items)
FXString tolowerString(const FXString &str) const
tolower string
FXint getNumItems() const
Return the number of items in the list.
Definition: MFXListIcon.h:80
FXint appendItem(MFXListIconItem *item, FXbool notify=FALSE)
Append a [possibly subclassed] item to the list.
FXbool isItemCurrent(FXint index) const
Return TRUE if item is current.
FXint getCurrentItemIndex() const
Return current item, if any.
void setFilter(const FXString &value, FXLabel *label)
filter items in list
MFXListIconItem * getItem(FXint index) const
Return the item at the given index.
void setTextColor(FXColor clr)
Change normal text color.
void clearItems(FXbool notify=FALSE)
Remove all items from list.
void removeItem(FXint index, FXbool notify=FALSE)
Remove node from list.
void setCurrentItem(MFXListIconItem *item, FXbool notify=FALSE)
Change current item.
FXint insertItem(FXint index, MFXListIconItem *item, FXbool notify=FALSE)
Insert a new [possibly subclassed] item at the give index.
const FXString & getText() const
Return item's text label.
FXIcon * getIcon() const
Return item's icon.
const FXColor & getBackGroundColor() const
get background color
virtual void disable()
Disable text field.
virtual void enable()
Enable text field.
virtual FXint getDefaultWidth()
Return default width.
FXColor getTextColor() const
Return text color.
FXString getText() const
Get the text for this label.
virtual FXint getDefaultHeight()
Return default height.
FXbool selectAll()
Select all text.
void setTextColor(FXColor clr)
Change text color.
const FXString & getTipText() const
Get the tool tip message for this text field.
void setIcon(FXIcon *ic)
Change the icon.
void setTipText(const FXString &text)
Set the tool tip message for this text field.
void setText(const FXString &text, FXbool notify=FALSE)
Change the text and move cursor to end.
FXTextFieldIcon (based on FXTextFieldIcon)