Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/foxtools/MFXComboBoxIcon.cpp
193674 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2006-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 MFXComboBoxIcon.cpp
15
/// @author Jakob Erdmann
16
/// @author Pablo Alvarez Lopez
17
/// @date 2018-12-19
18
///
19
//
20
/****************************************************************************/
21
22
#include <utils/common/MsgHandler.h>
23
#include <utils/gui/div/GUIDesigns.h>
24
#include <utils/gui/images/GUIIconSubSys.h>
25
#include <utils/gui/windows/GUIAppEnum.h>
26
27
#include "MFXComboBoxIcon.h"
28
#include "MFXListIcon.h"
29
#include "MFXListIconItem.h"
30
#include "MFXTextFieldSearch.h"
31
32
// ===========================================================================
33
// FOX callback mapping
34
// ===========================================================================
35
36
FXDEFMAP(MFXComboBoxIcon) MFXComboBoxIconMap[] = {
37
FXMAPFUNC(SEL_FOCUS_UP, 0, MFXComboBoxIcon::onFocusUp),
38
FXMAPFUNC(SEL_FOCUS_DOWN, 0, MFXComboBoxIcon::onFocusDown),
39
FXMAPFUNC(SEL_FOCUS_SELF, 0, MFXComboBoxIcon::onFocusSelf),
40
FXMAPFUNC(SEL_UPDATE, MFXComboBoxIcon::ID_TEXT, MFXComboBoxIcon::onUpdFmText),
41
FXMAPFUNC(SEL_CLICKED, MFXComboBoxIcon::ID_LIST, MFXComboBoxIcon::onListClicked),
42
FXMAPFUNC(SEL_COMMAND, MFXComboBoxIcon::ID_LIST, MFXComboBoxIcon::onListClicked),
43
FXMAPFUNC(SEL_LEFTBUTTONPRESS, MFXComboBoxIcon::ID_TEXT, MFXComboBoxIcon::onTextButton),
44
FXMAPFUNC(SEL_MOUSEWHEEL, MFXComboBoxIcon::ID_TEXT, MFXComboBoxIcon::onMouseWheel),
45
FXMAPFUNC(SEL_CHANGED, MFXComboBoxIcon::ID_TEXT, MFXComboBoxIcon::onTextChanged),
46
FXMAPFUNC(SEL_COMMAND, MFXComboBoxIcon::ID_TEXT, MFXComboBoxIcon::onTextCommand),
47
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETVALUE, MFXComboBoxIcon::onFwdToText),
48
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETINTVALUE, MFXComboBoxIcon::onFwdToText),
49
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETREALVALUE, MFXComboBoxIcon::onFwdToText),
50
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_SETSTRINGVALUE, MFXComboBoxIcon::onFwdToText),
51
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETINTVALUE, MFXComboBoxIcon::onFwdToText),
52
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETREALVALUE, MFXComboBoxIcon::onFwdToText),
53
FXMAPFUNC(SEL_COMMAND, FXWindow::ID_GETSTRINGVALUE, MFXComboBoxIcon::onFwdToText),
54
FXMAPFUNC(SEL_COMMAND, MID_MTEXTFIELDSEARCH_UPDATED, MFXComboBoxIcon::onCmdFilter),
55
};
56
57
// Object implementation
58
FXIMPLEMENT(MFXComboBoxIcon, FXPacker, MFXComboBoxIconMap, ARRAYNUMBER(MFXComboBoxIconMap))
59
60
// ===========================================================================
61
// member method definitions
62
// ===========================================================================
63
64
MFXComboBoxIcon::MFXComboBoxIcon(FXComposite* p, MFXStaticToolTip* staticToolTip, const bool canSearch, const int visibleItems,
65
FXObject* tgt, FXSelector sel, FXuint opts, FXint x, FXint y, FXint w, FXint h, FXint pl, FXint pr, FXint pt, FXint pb):
66
FXPacker(p, opts, x, y, w, h, 0, 0, 0, 0, 0, 0) {
67
flags |= FLAG_ENABLED;
68
target = tgt;
69
message = sel;
70
// create text field
71
myTextFieldIcon = new MFXTextFieldIcon(this, staticToolTip, GUIIcon::EMPTY, this, MFXComboBoxIcon::ID_TEXT, 0, 0, 0, 0, 0, pl, pr, pt, pb);
72
if (options & COMBOBOX_STATIC) {
73
myTextFieldIcon->setEditable(FALSE);
74
}
75
// create pane for list
76
myPane = new FXPopup(this, FRAME_LINE);
77
// check if create search button
78
if (canSearch) {
79
myTextFieldSearch = new MFXTextFieldSearch(myPane, staticToolTip, this, ID_SEARCH, FRAME_THICK | LAYOUT_FIX_WIDTH | LAYOUT_FIX_HEIGHT, 0, 0, 0, 0, 2, 2, 2, 2);
80
// create label for empty icon
81
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);
82
myNoItemsLabel->setTextColor(GUIDesignTextColorRed);
83
myNoItemsLabel->hide();
84
}
85
// create list icon
86
myList = new MFXListIcon(myPane, this, MFXComboBoxIcon::ID_LIST, LIST_BROWSESELECT | LIST_AUTOSELECT | LAYOUT_FILL_X | LAYOUT_FILL_Y | SCROLLERS_TRACK | HSCROLLER_NEVER);
87
if (options & COMBOBOX_STATIC) {
88
myList->setScrollStyle(SCROLLERS_TRACK | HSCROLLING_OFF);
89
}
90
myList->setNumVisible(visibleItems);
91
// create button
92
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);
93
myButton->setXOffset(border);
94
myButton->setYOffset(border);
95
flags &= ~(FXuint)FLAG_UPDATE; // Never GUI update
96
97
}
98
99
100
MFXComboBoxIcon::~MFXComboBoxIcon() {
101
delete myPane;
102
myPane = (FXPopup*) - 1L;
103
myTextFieldIcon = (MFXTextFieldIcon*) - 1L;
104
myButton = (FXMenuButton*) - 1L;
105
if (myTextFieldSearch) {
106
myTextFieldSearch = (MFXTextFieldSearch*) - 1L;
107
myNoItemsLabel = (FXLabel*) - 1L;
108
}
109
myList = (MFXListIcon*) - 1L;
110
}
111
112
113
void
114
MFXComboBoxIcon::create() {
115
FXPacker::create();
116
myPane->create();
117
}
118
119
120
void
121
MFXComboBoxIcon::detach() {
122
FXPacker::detach();
123
myPane->detach();
124
}
125
126
127
void
128
MFXComboBoxIcon::destroy() {
129
myPane->destroy();
130
FXPacker::destroy();
131
}
132
133
134
void
135
MFXComboBoxIcon::enable() {
136
if (!isEnabled()) {
137
FXPacker::enable();
138
myTextFieldIcon->enable();
139
myButton->enable();
140
}
141
}
142
143
144
void
145
MFXComboBoxIcon::disable() {
146
if (isEnabled()) {
147
FXPacker::disable();
148
myTextFieldIcon->disable();
149
myButton->disable();
150
}
151
}
152
153
154
FXint
155
MFXComboBoxIcon::getDefaultWidth() {
156
FXint ww = myTextFieldIcon->getDefaultWidth() + myButton->getDefaultWidth() + (border << 1);
157
FXint pw = myPane->getDefaultWidth();
158
return FXMAX(ww, pw);
159
}
160
161
162
FXint
163
MFXComboBoxIcon::getDefaultHeight() {
164
FXint th, bh;
165
th = myTextFieldIcon->getDefaultHeight();
166
bh = myButton->getDefaultHeight();
167
return FXMAX(th, bh) + (border << 1);
168
}
169
170
171
void
172
MFXComboBoxIcon::layout() {
173
const FXint itemHeight = height - (border << 1);
174
const FXint buttonWidth = myButton->getDefaultWidth();
175
const FXint textWidth = width - buttonWidth - (border << 1);
176
myTextFieldIcon->position(border, border, textWidth, itemHeight);
177
myButton->position(border + textWidth, border, buttonWidth, itemHeight);
178
if (myTextFieldSearch) {
179
myTextFieldSearch->resize(width, height);
180
myNoItemsLabel->resize(width, height);
181
}
182
myPane->resize(width, myPane->getDefaultHeight());
183
flags &= ~(FXuint)FLAG_DIRTY;
184
}
185
186
187
FXString
188
MFXComboBoxIcon::getText() const {
189
return myTextFieldIcon->getText();
190
}
191
192
193
FXint
194
MFXComboBoxIcon::getNumItems() const {
195
return myList->getNumItems();
196
}
197
198
199
void
200
MFXComboBoxIcon::setNumVisible(FXint nvis) {
201
myList->setNumVisible(nvis);
202
}
203
204
205
void
206
MFXComboBoxIcon::setText(const FXString& text, FXbool notify) {
207
myTextFieldIcon->setText(text, notify);
208
}
209
210
211
FXbool
212
MFXComboBoxIcon::isItemCurrent(FXint index) const {
213
return myList->isItemCurrent(index);
214
}
215
216
217
long
218
MFXComboBoxIcon::setCurrentItem(const FXint index, FXbool notify) {
219
if (index >= 0 && index <= myList->getNumItems()) {
220
// get item
221
MFXListIconItem* item = myList->getItem(index);
222
// set it as current item and make it visible
223
myList->setCurrentItem(item);
224
myList->makeItemVisible(index);
225
// update both text fields
226
myTextFieldIcon->setText(item->getText());
227
myTextFieldIcon->setIcon(item->getIcon());
228
myTextFieldIcon->setBackColor(item->getBackGroundColor());
229
// check if notify
230
if (notify && target) {
231
return target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)item);
232
}
233
} else {
234
fxerror("%s::setItem: index out of range.\n", getClassName());
235
}
236
return 0;
237
}
238
239
240
long
241
MFXComboBoxIcon::setCurrentItem(const FXString& text, FXbool notify) {
242
// check if item exist
243
for (int i = 0; i < myList->getNumItems(); i++) {
244
const auto itemText = myList->tolowerString(myList->getItem(i)->getText());
245
if (myList->tolowerString(text) == itemText) {
246
// use "set curent item" function
247
return setCurrentItem(i, notify);
248
}
249
}
250
return 0;
251
}
252
253
254
FXint
255
MFXComboBoxIcon::getCurrentItem() const {
256
return myList->getCurrentItemIndex();
257
}
258
259
260
FXint
261
MFXComboBoxIcon::updateIconItem(FXint index, const FXString& text, FXIcon* icon, FXColor bgColor, void* ptr) {
262
if (index < 0 || myList->getNumItems() <= index) {
263
fxerror("%s::setItem: index out of range.\n", getClassName());
264
}
265
myList->editItem(index, text, NULL, ptr);
266
if (isItemCurrent(index)) {
267
myTextFieldIcon->setText(text);
268
myTextFieldIcon->setBackColor(bgColor);
269
myTextFieldIcon->setIcon(icon);
270
}
271
recalc();
272
return index;
273
}
274
275
276
FXint
277
MFXComboBoxIcon::insertIconItem(FXint index, const FXString& text, FXIcon* icon, FXColor bgColor, void* ptr) {
278
index = myList->insertItem(index, new MFXListIconItem(text, icon, bgColor, ptr));
279
if (isItemCurrent(index)) {
280
myTextFieldIcon->setText(text);
281
myTextFieldIcon->setBackColor(bgColor);
282
myTextFieldIcon->setIcon(icon);
283
}
284
recalc();
285
return index;
286
}
287
288
289
FXint
290
MFXComboBoxIcon::appendIconItem(const FXString& text, FXIcon* icon, FXColor bgColor, void* ptr) {
291
FXint index = myList->appendItem(new MFXListIconItem(text, icon, bgColor, ptr));
292
if (isItemCurrent(getNumItems() - 1)) {
293
myTextFieldIcon->setText(text);
294
myTextFieldIcon->setBackColor(bgColor);
295
myTextFieldIcon->setIcon(icon);
296
}
297
recalc();
298
return index;
299
}
300
301
302
void
303
MFXComboBoxIcon::removeItem(FXint index) {
304
const auto isCurrent = myList->isItemCurrent(index);
305
if (isCurrent == TRUE) {
306
if ((index > 0) && (index < (int)myList->getNumItems())) {
307
setCurrentItem(index - 1);
308
} else if (myList->getNumItems() > 0) {
309
setCurrentItem(0);
310
}
311
}
312
myList->removeItem(index);
313
recalc();
314
}
315
316
317
void
318
MFXComboBoxIcon::clearItems() {
319
myTextFieldIcon->setText("");
320
myList->clearItems();
321
recalc();
322
}
323
324
325
FXint
326
MFXComboBoxIcon::findItem(const FXString& text) const {
327
return myList->findItem(text);
328
}
329
330
331
std::string
332
MFXComboBoxIcon::getItemText(FXint index) const {
333
return myList->getItem(index)->getText().text();
334
}
335
336
337
void
338
MFXComboBoxIcon::setBackColor(FXColor clr) {
339
myTextFieldIcon->setBackColor(clr);
340
myList->setBackColor(clr);
341
}
342
343
344
void
345
MFXComboBoxIcon::setTextColor(FXColor clr) {
346
myTextFieldIcon->setTextColor(clr);
347
myList->setTextColor(clr);
348
}
349
350
351
FXColor
352
MFXComboBoxIcon::getTextColor() const {
353
return myTextFieldIcon->getTextColor();
354
}
355
356
357
void
358
MFXComboBoxIcon::setTipText(const FXString& txt) {
359
myTextFieldIcon->setTipText(txt);
360
}
361
362
363
const FXString&
364
MFXComboBoxIcon::getTipText() const {
365
return myTextFieldIcon->getTipText();
366
}
367
368
369
long
370
MFXComboBoxIcon::onUpdFmText(FXObject*, FXSelector, void*) {
371
return (target && !myPane->shown()) ? target->tryHandle(this, FXSEL(SEL_UPDATE, message), NULL) : 0;
372
}
373
374
375
long
376
MFXComboBoxIcon::onCmdFilter(FXObject*, FXSelector, void* ptr) {
377
myList->setFilter(myTextFieldSearch->getText(), myNoItemsLabel);
378
myPane->resize(width, myPane->getDefaultHeight());
379
myPane->recalc();
380
myPane->onPaint(0, 0, ptr);
381
return 1;
382
}
383
384
385
long
386
MFXComboBoxIcon::onFwdToText(FXObject* sender, FXSelector sel, void* ptr) {
387
return myTextFieldIcon->handle(sender, sel, ptr);
388
}
389
390
391
long
392
MFXComboBoxIcon::onListClicked(FXObject*, FXSelector sel, void* ptr) {
393
// hide pane
394
myButton->handle(this, FXSEL(SEL_COMMAND, ID_UNPOST), NULL);
395
if (FXSELTYPE(sel) == SEL_COMMAND) {
396
// cast MFXListIconItem
397
const MFXListIconItem* item = (MFXListIconItem*)ptr;
398
// set icon and background color
399
myTextFieldIcon->setText(item->getText());
400
myTextFieldIcon->setIcon(item->getIcon());
401
myTextFieldIcon->setBackColor(item->getBackGroundColor());
402
// Select if editable
403
if (!(options & COMBOBOX_STATIC)) {
404
myTextFieldIcon->selectAll();
405
}
406
if (target) {
407
target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)getText().text());
408
}
409
}
410
return 1;
411
}
412
413
414
long
415
MFXComboBoxIcon::onTextButton(FXObject*, FXSelector, void*) {
416
if (options & COMBOBOX_STATIC) {
417
// Post the myList
418
myButton->handle(this, FXSEL(SEL_COMMAND, ID_POST), NULL);
419
return 1;
420
}
421
return 0;
422
}
423
424
425
long
426
MFXComboBoxIcon::onTextChanged(FXObject*, FXSelector, void* ptr) {
427
return target ? target->tryHandle(this, FXSEL(SEL_CHANGED, message), ptr) : 0;
428
}
429
430
431
long
432
MFXComboBoxIcon::onTextCommand(FXObject*, FXSelector, void* ptr) {
433
// reset background colors
434
myTextFieldIcon->setBackColor(GUIDesignBackgroundColorWhite);
435
// check if item exist
436
for (int i = 0; i < myList->getNumItems(); i++) {
437
const auto itemText = myList->tolowerString(myList->getItem(i)->getText());
438
if (myList->tolowerString(myTextFieldIcon->getText()) == itemText) {
439
// use "set curent item" function
440
return setCurrentItem(i, TRUE);
441
}
442
}
443
// no item found, then reset icon label
444
myTextFieldIcon->setIcon(GUIIconSubSys::getIcon(GUIIcon::CANCEL));
445
return target ? target->tryHandle(this, FXSEL(SEL_COMMAND, message), ptr) : 0;
446
}
447
448
449
long
450
MFXComboBoxIcon::onFocusSelf(FXObject* sender, FXSelector, void* ptr) {
451
return myTextFieldIcon->handle(sender, FXSEL(SEL_FOCUS_SELF, 0), ptr);
452
}
453
454
455
long
456
MFXComboBoxIcon::onFocusUp(FXObject*, FXSelector, void*) {
457
if (isEnabled()) {
458
FXint index = getCurrentItem();
459
if (index < 0) {
460
index = getNumItems() - 1;
461
} else if (0 < index) {
462
index--;
463
}
464
if (0 <= index && index < getNumItems()) {
465
setCurrentItem(index, TRUE);
466
}
467
return 1;
468
}
469
return 0;
470
}
471
472
473
long
474
MFXComboBoxIcon::onFocusDown(FXObject*, FXSelector, void*) {
475
if (isEnabled()) {
476
FXint index = getCurrentItem();
477
if (index < 0) {
478
index = 0;
479
} else if (index < getNumItems() - 1) {
480
index++;
481
}
482
if (0 <= index && index < getNumItems()) {
483
setCurrentItem(index, TRUE);
484
}
485
return 1;
486
}
487
return 0;
488
}
489
490
491
long MFXComboBoxIcon::onMouseWheel(FXObject*, FXSelector, void* ptr) {
492
FXEvent* event = (FXEvent*)ptr;
493
if (isEnabled()) {
494
FXint index = getCurrentItem();
495
if (event->code < 0) {
496
if (index < 0) {
497
index = 0;
498
} else if (index < getNumItems() - 1) {
499
index++;
500
}
501
} else if (event->code > 0) {
502
if (index < 0) {
503
index = getNumItems() - 1;
504
} else if (0 < index) {
505
index--;
506
}
507
}
508
if (0 <= index && index < getNumItems()) {
509
setCurrentItem(index, TRUE);
510
}
511
return 1;
512
}
513
return 0;
514
}
515
516
517
MFXComboBoxIcon::MFXComboBoxIcon() {}
518
519