Eclipse SUMO - Simulation of Urban MObility
GNEMatchGenericDataAttribute.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 /****************************************************************************/
18 // The Widget for modifying selections of network-elements
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <netedit/GNENet.h>
23 #include <netedit/GNEViewNet.h>
27 
29 #include "GNEElementSet.h"
30 
31 // ===========================================================================
32 // FOX callback mapping
33 // ===========================================================================
34 
35 FXDEFMAP(GNEMatchGenericDataAttribute) GNEMatchGenericDataAttributeMap[] = {
42  FXMAPFUNC(SEL_COMMAND, MID_HELP, GNEMatchGenericDataAttribute::onCmdHelp)
43 };
44 
45 // Object implementation
46 FXIMPLEMENT(GNEMatchGenericDataAttribute, FXGroupBoxModule, GNEMatchGenericDataAttributeMap, ARRAYNUMBER(GNEMatchGenericDataAttributeMap))
47 
48 // ===========================================================================
49 // method definitions
50 // ===========================================================================
51 
52 GNEMatchGenericDataAttribute::GNEMatchGenericDataAttribute(GNEElementSet* elementSet, SumoXMLTag defaultTag, SumoXMLAttr defaultAttr, const std::string& defaultValue) :
53  FXGroupBoxModule(elementSet->getSelectorFrameParent()->getContentFrame(), "Match GenericData Attribute"),
54  myElementSet(elementSet),
55  myIntervalSelector(nullptr),
56  myBegin(nullptr),
57  myEnd(nullptr),
58  myMatchGenericDataTagComboBox(nullptr),
59  myMatchGenericDataAttrComboBox(nullptr),
60  myCurrentTag(defaultTag),
61  myCurrentAttribute(toString(defaultAttr)),
62  myMatchGenericDataString(nullptr) {
63  // Create MFXIconComboBox for interval
64  new FXLabel(getCollapsableFrame(), "Interval [begin, end]", nullptr, GUIDesignLabelThick);
65  myIntervalSelector = new MFXIconComboBox(getCollapsableFrame(), GUIDesignComboBoxNCol, this, MID_GNE_SELECTORFRAME_SETINTERVAL, GUIDesignComboBoxStaticExtended);
66  // Create textfield for begin and end
67  FXHorizontalFrame* myHorizontalFrameBeginEnd = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);
68  myBegin = new FXTextField(myHorizontalFrameBeginEnd, GUIDesignTextFieldNCol, this, MID_GNE_SELECTORFRAME_SETBEGIN, GUIDesignTextField);
69  myEnd = new FXTextField(myHorizontalFrameBeginEnd, GUIDesignTextFieldNCol, this, MID_GNE_SELECTORFRAME_SETEND, GUIDesignTextField);
70  // Create MFXIconComboBox for generic datas
71  myMatchGenericDataTagComboBox = new MFXIconComboBox(getCollapsableFrame(), GUIDesignComboBoxNCol, this, MID_GNE_SELECTORFRAME_SELECTTAG, GUIDesignComboBox);
72  // Create listBox for Attributes
73  myMatchGenericDataAttrComboBox = new FXComboBox(getCollapsableFrame(), GUIDesignComboBoxNCol, this, MID_GNE_SELECTORFRAME_SELECTATTRIBUTE, GUIDesignComboBox);
74  // Create TextField for MatchGenericData string
75  myMatchGenericDataString = new FXTextField(getCollapsableFrame(), GUIDesignTextFieldNCol, this, MID_GNE_SELECTORFRAME_PROCESSSTRING, GUIDesignTextField);
76  // Create help button
77  new FXButton(getCollapsableFrame(), "Help", nullptr, this, MID_HELP, GUIDesignButtonRectangular);
78  // Fill list of sub-items (first element will be "edge")
79  enableMatchGenericDataAttribute();
80  // Set speed of edge as default attribute
81  myMatchGenericDataAttrComboBox->setText("speed");
82  myCurrentAttribute = SUMO_ATTR_SPEED;
83  // Set default value for MatchGenericData string
84  myMatchGenericDataString->setText(defaultValue.c_str());
85 }
86 
87 
89 
90 
91 void
93  // first drop intervals
94  myIntervals.clear();
95  // iterate over all data sets
96  for (const auto& dataSet : myElementSet->getSelectorFrameParent()->getViewNet()->getNet()->getAttributeCarriers()->getDataSets()) {
97  for (const auto& dataInterval : dataSet->getDataIntervalChildren()) {
98  myIntervals[std::make_pair(dataInterval.second->getAttributeDouble(SUMO_ATTR_BEGIN), dataInterval.second->getAttributeDouble(SUMO_ATTR_END))] = -1;
99  }
100  }
101  // disable modul if there isn't intervals
102  if (myIntervals.size() == 0) {
104  } else {
105  // enable comboboxes and text field
107  myBegin->enable();
108  myEnd->enable();
111  myMatchGenericDataString->enable();
112  // clear combo box interval selector
114  // fill combo Box
115  for (auto& interval : myIntervals) {
116  interval.second = myIntervalSelector->appendIconItem((" [" + toString(interval.first.first) + "," + toString(interval.first.second) + "]").c_str(), GUIIconSubSys::getIcon(GUIIcon::DATAINTERVAL));
117  }
118  // set number of visible items
119  if (myIntervalSelector->getNumItems() < 10) {
121  } else {
123  }
124  // Clear items of myMatchGenericDataTagComboBox
126  // update begin and end
127  myBegin->setText(toString(myIntervals.begin()->first.first).c_str());
128  myBegin->setTextColor(FXRGB(0, 0, 0));
129  myEnd->setText(toString(myIntervals.begin()->first.second).c_str());
130  myEnd->setTextColor(FXRGB(0, 0, 0));
131  // get generic datas
132  const auto genericDataTags = GNEAttributeCarrier::getTagPropertiesByType(GNETagProperties::TagType::GENERICDATA);
133  // fill combo box (only with drawable elements)
134  for (const auto& genericDataTag : genericDataTags) {
135  if (genericDataTag.isDrawable()) {
136  myMatchGenericDataTagComboBox->appendIconItem(genericDataTag.getFieldString().c_str(), GUIIconSubSys::getIcon(genericDataTag.getGUIIcon()));
137  }
138  }
139  // set first item as current item
142  // call select tag
143  onCmdSelectTag(nullptr, 0, nullptr);
144  }
145 }
146 
147 
148 void
150  // disable comboboxes and text field
152  myBegin->disable();
153  myEnd->disable();
156  myMatchGenericDataString->disable();
157  // change colors to black (even if there are invalid values)
159  myMatchGenericDataAttrComboBox->setTextColor(FXRGB(0, 0, 0));
160  myMatchGenericDataString->setTextColor(FXRGB(0, 0, 0));
161 }
162 
163 
164 void
166  // just show Module
167  show();
168 }
169 
170 
171 void
173  // just hide modul
174  hide();
175 }
176 
177 
178 long
179 GNEMatchGenericDataAttribute::onCmdSetInterval(FXObject*, FXSelector, void*) {
180  // iterate over interval and update begin and end
181  for (auto& interval : myIntervals) {
182  if (interval.second == myIntervalSelector->getCurrentItem()) {
183  // update begin
184  myBegin->setTextColor(FXRGB(0, 0, 0));
185  myBegin->setText(toString(interval.first.first).c_str());
186  // update end
187  myEnd->setTextColor(FXRGB(0, 0, 0));
188  myEnd->setText(toString(interval.first.second).c_str());
189  }
190  }
191  // call onCmdSelectTag
192  onCmdSelectTag(0, 0, 0);
193  return 1;
194 }
195 
196 
197 long
198 GNEMatchGenericDataAttribute::onCmdSetBegin(FXObject*, FXSelector, void*) {
199  // check if can be parsed to double
200  if (GNEAttributeCarrier::canParse<double>(myBegin->getText().text()) &&
201  GNEAttributeCarrier::canParse<double>(myEnd->getText().text())) {
202  // set valid color text and kill focus
203  myBegin->setTextColor(FXRGB(0, 0, 0));
204  myBegin->killFocus();
205  // enable elements
208  myMatchGenericDataString->enable();
209  // call onCmdSelectTag
210  onCmdSelectTag(0, 0, 0);
211  } else {
212  // set invalid color text
213  myBegin->setTextColor(FXRGB(255, 0, 0));
214  // disable elements
217  myMatchGenericDataString->disable();
218  }
219  return 1;
220 }
221 
222 
223 long
224 GNEMatchGenericDataAttribute::onCmdSetEnd(FXObject*, FXSelector, void*) {
225  // check if can be parsed to double
226  if (GNEAttributeCarrier::canParse<double>(myBegin->getText().text()) &&
227  GNEAttributeCarrier::canParse<double>(myEnd->getText().text())) {
228  // set valid color text and kill focus
229  myEnd->setTextColor(FXRGB(0, 0, 0));
230  myEnd->killFocus();
231  // enable elements
234  myMatchGenericDataString->enable();
235  // call onCmdSelectTag
236  onCmdSelectTag(0, 0, 0);
237  } else {
238  // set invalid color text
239  myEnd->setTextColor(FXRGB(255, 0, 0));
240  // disable elements
243  myMatchGenericDataString->disable();
244  }
245  return 1;
246 }
247 
248 
249 long
250 GNEMatchGenericDataAttribute::onCmdSelectTag(FXObject*, FXSelector, void*) {
251  // First check what type of elementes is being selected
253  // get generic data tags
254  const auto listOfTags = GNEAttributeCarrier::getTagPropertiesByType(GNETagProperties::TagType::GENERICDATA);
255  // fill myMatchGenericDataTagComboBox
256  for (const auto& genericDataTag : listOfTags) {
257  if (genericDataTag.isDrawable() && (genericDataTag.getFieldString() == myMatchGenericDataTagComboBox->getText().text())) {
258  myCurrentTag = genericDataTag.getTag();
259  }
260  }
261  // check that typed-by-user value is correct
263  // obtain begin and end
264  const double begin = GNEAttributeCarrier::parse<double>(myBegin->getText().text());
265  const double end = GNEAttributeCarrier::parse<double>(myEnd->getText().text());
266  // obtain all Generic Data attributes for current generic tag
268  // set color and enable items
271  myMatchGenericDataString->enable();
272  myMatchGenericDataAttrComboBox->clearItems();
273  // add data set parent
275  // fill attribute combo box
276  for (const auto& attribute : attributes) {
277  myMatchGenericDataAttrComboBox->appendItem(attribute.c_str());
278  }
279  myMatchGenericDataAttrComboBox->setNumVisible(myMatchGenericDataAttrComboBox->getNumItems());
280  onCmdSelectAttribute(nullptr, 0, nullptr);
281  } else {
282  // change color to red and disable items
283  myMatchGenericDataTagComboBox->setTextColor(FXRGB(255, 0, 0));
285  myMatchGenericDataString->disable();
286  }
287  update();
288  return 1;
289 }
290 
291 
292 long
294  // obtain all Generic Data attributes for current generic tag
296  toString(myCurrentTag), GNEAttributeCarrier::parse<double>(myBegin->getText().text()),
297  GNEAttributeCarrier::parse<double>(myEnd->getText().text()));
298  // add extra data set parent attribute
299  attributes.insert(toString(GNE_ATTR_DATASET));
300  // clear current attribute
301  myCurrentAttribute.clear();
302  // set current selected attribute
303  for (const auto& attribute : attributes) {
304  if (attribute == myMatchGenericDataAttrComboBox->getText().text()) {
305  myCurrentAttribute = attribute;
306  }
307  }
308  // check if selected attribute is valid
309  if (myCurrentAttribute.empty()) {
310  myMatchGenericDataAttrComboBox->setTextColor(FXRGB(255, 0, 0));
311  myMatchGenericDataString->disable();
312  } else {
313  myMatchGenericDataAttrComboBox->setTextColor(FXRGB(0, 0, 0));
314  myMatchGenericDataString->enable();
315  }
316  return 1;
317 }
318 
319 
320 long
322  // obtain expression and tag value
323  std::string expression = myMatchGenericDataString->getText().text();
324  bool valid = true;
325  // get all Generic datas
327  GNEAttributeCarrier::parse<double>(myBegin->getText().text()),
328  GNEAttributeCarrier::parse<double>(myEnd->getText().text()));
329  if (expression == "") {
330  // the empty expression matches all objects
333  // The expression must have the form
334  // <val matches if attr < val
335  // >val matches if attr > val
336  // =val matches if attr = val
337  // val matches if attr = val
338  char compOp = expression[0];
339  if ((compOp == '<') || (compOp == '>') || (compOp == '=')) {
340  expression = expression.substr(1);
341  } else {
342  compOp = '=';
343  }
344  // check if value can be parsed to double
345  if (GNEAttributeCarrier::canParse<double>(expression.c_str())) {
346  myElementSet->getSelectorFrameParent()->handleIDs(myElementSet->getSelectorFrameParent()->getGenericMatches(genericDatas, myCurrentAttribute, compOp, GNEAttributeCarrier::parse<double>(expression.c_str()), expression));
347  } else {
348  valid = false;
349  }
350  } else {
351  // The expression must have the form
352  // =str: matches if <str> is an exact match
353  // !str: matches if <str> is not a substring
354  // ^str: matches if <str> is not an exact match
355  // str: matches if <str> is a substring (sends compOp '@')
356  // Alternatively, if the expression is empty it matches all objects
357  char compOp = expression[0];
358  if ((compOp == '=') || (compOp == '!') || (compOp == '^')) {
359  expression = expression.substr(1);
360  } else {
361  compOp = '@';
362  }
364  }
365  // change color depending of flag "valid"
366  if (valid) {
367  myMatchGenericDataString->setTextColor(FXRGB(0, 0, 0));
368  myMatchGenericDataString->killFocus();
369  } else {
370  myMatchGenericDataString->setTextColor(FXRGB(255, 0, 0));
371  }
372  return 1;
373 }
374 
375 
376 long
377 GNEMatchGenericDataAttribute::onCmdHelp(FXObject*, FXSelector, void*) {
378  // Create dialog box
379  FXDialogBox* additionalNeteditAttributesHelpDialog = new FXDialogBox(getCollapsableFrame(), "Netedit Parameters Help", GUIDesignDialogBox);
380  additionalNeteditAttributesHelpDialog->setIcon(GUIIconSubSys::getIcon(GUIIcon::MODEADDITIONAL));
381  // set help text
382  std::ostringstream help;
383  help
384  << "- The 'MatchGenericData Attribute' controls allow to specify a set of objects which are then applied to the current selection\n"
385  << " according to the current 'Modification Mode'.\n"
386  << " 1. Select an object type from the first input box\n"
387  << " 2. Select an attribute from the second input box\n"
388  << " 3. Enter a 'match expression' in the third input box and press <return>\n"
389  << "\n"
390  << "- The empty expression matches all objects\n"
391  << "- For numerical attributes the match expression must consist of a comparison operator ('<', '>', '=') and a number.\n"
392  << "- An object matches if the comparison between its attribute and the given number by the given operator evaluates to 'true'\n"
393  << "\n"
394  << "- For string attributes the match expression must consist of a comparison operator ('', '=', '!', '^') and a string.\n"
395  << " '' (no operator) matches if string is a substring of that object'ts attribute.\n"
396  << " '=' matches if string is an exact match.\n"
397  << " '!' matches if string is not a substring.\n"
398  << " '^' matches if string is not an exact match.\n"
399  << "\n"
400  << "- Examples:\n"
401  << " junction; id; 'foo' -> match all junctions that have 'foo' in their id\n"
402  << " junction; type; '=priority' -> match all junctions of type 'priority', but not of type 'priority_stop'\n"
403  << " edge; speed; '>10' -> match all edges with a speed above 10\n";
404  // Create label with the help text
405  new FXLabel(additionalNeteditAttributesHelpDialog, help.str().c_str(), nullptr, GUIDesignLabelFrameInformation);
406  // Create horizontal separator
407  new FXHorizontalSeparator(additionalNeteditAttributesHelpDialog, GUIDesignHorizontalSeparator);
408  // Create frame for OK Button
409  FXHorizontalFrame* myHorizontalFrameOKButton = new FXHorizontalFrame(additionalNeteditAttributesHelpDialog, GUIDesignAuxiliarHorizontalFrame);
410  // Create Button Close (And two more horizontal frames to center it)
411  new FXHorizontalFrame(myHorizontalFrameOKButton, GUIDesignAuxiliarHorizontalFrame);
412  new FXButton(myHorizontalFrameOKButton, "OK\t\tclose", GUIIconSubSys::getIcon(GUIIcon::ACCEPT), additionalNeteditAttributesHelpDialog, FXDialogBox::ID_ACCEPT, GUIDesignButtonOK);
413  new FXHorizontalFrame(myHorizontalFrameOKButton, GUIDesignAuxiliarHorizontalFrame);
414  // Write Warning in console if we're in testing mode
415  WRITE_DEBUG("Opening help dialog of selector frame");
416  // create Dialog
417  additionalNeteditAttributesHelpDialog->create();
418  // show in the given position
419  additionalNeteditAttributesHelpDialog->show(PLACEMENT_CURSOR);
420  // refresh APP
421  getApp()->refresh();
422  // open as modal dialog (will block all windows until stop() or stopModal() is called)
423  getApp()->runModalFor(additionalNeteditAttributesHelpDialog);
424  // Write Warning in console if we're in testing mode
425  WRITE_DEBUG("Close help dialog of selector frame");
426  return 1;
427 }
428 
429 /****************************************************************************/
FXDEFMAP(GNEMatchGenericDataAttribute) GNEMatchGenericDataAttributeMap[]
@ MID_GNE_SELECTORFRAME_SETINTERVAL
change interval
Definition: GUIAppEnum.h:893
@ MID_GNE_SELECTORFRAME_SELECTATTRIBUTE
select attribute in selector frame
Definition: GUIAppEnum.h:887
@ MID_GNE_SELECTORFRAME_SETEND
end text field
Definition: GUIAppEnum.h:897
@ MID_GNE_SELECTORFRAME_SELECTTAG
select tag in selector frame
Definition: GUIAppEnum.h:885
@ MID_HELP
help button
Definition: GUIAppEnum.h:600
@ MID_GNE_SELECTORFRAME_SETBEGIN
edit begin text field
Definition: GUIAppEnum.h:895
@ MID_GNE_SELECTORFRAME_PROCESSSTRING
process string
Definition: GUIAppEnum.h:889
#define GUIDesignComboBox
Definition: GUIDesigns.h:267
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:285
#define GUIDesignTextField
Definition: GUIDesigns.h:42
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:343
#define GUIDesignDialogBox
Definition: GUIDesigns.h:527
#define GUIDesignButtonRectangular
little button rectangula used in frames (For example, in "help" buttons)
Definition: GUIDesigns.h:74
#define GUIDesignComboBoxStaticExtended
Combo box static (not editable) extended over the all frame.
Definition: GUIDesigns.h:273
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:60
#define GUIDesignButtonOK
Definition: GUIDesigns.h:124
#define GUIDesignHorizontalSeparator
Definition: GUIDesigns.h:395
#define GUIDesignLabelThick
label extended over frame with thick and with text justify to left
Definition: GUIDesigns.h:202
#define GUIDesignLabelFrameInformation
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition: GUIDesigns.h:244
@ MODEADDITIONAL
@ DATAINTERVAL
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:290
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_NOTHING
invalid tag
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ GNE_ATTR_DATASET
data set of a generic data
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
FXGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toogled)
static const std::vector< GNETagProperties > getTagPropertiesByType(const int tagPropertyCategory)
get tagProperties associated to the given GNETagProperties::TagType (NETWORKELEMENT,...
GNESelectorFrame * getSelectorFrameParent() const
get Selector Frame Parent
GNEViewNet * getViewNet() const
get view net
Definition: GNEFrame.cpp:133
long onCmdHelp(FXObject *, FXSelector, void *)
Called when the user clicks the help button.
long onCmdSetBegin(FXObject *, FXSelector, void *)
Called when the user change begin text field.
void disableMatchGenericDataAttribute()
disable match attributes
SumoXMLTag myCurrentTag
current SumoXMLTag tag
void enableMatchGenericDataAttribute()
enable match attributes
void hideMatchGenericDataAttribute()
hide match attributes
long onCmdSetInterval(FXObject *, FXSelector, void *)
Called when the user selects an interval.
FXComboBox * myMatchGenericDataAttrComboBox
attributes of the match box
std::string myCurrentAttribute
current string Attribute
GNEElementSet * myElementSet
FOX need this.
FXTextField * myEnd
TextField for end.
FXTextField * myMatchGenericDataString
string of the match
MFXIconComboBox * myIntervalSelector
tag of the match box
long onCmdSelectTag(FXObject *, FXSelector, void *)
Called when the user selects a tag in the match box.
void showMatchGenericDataAttribute()
show match attributes
long onCmdSelectAttribute(FXObject *, FXSelector, void *)
Called when the user selects an attribute in the match box.
long onCmdProcessString(FXObject *, FXSelector, void *)
Called when the user enters a new selection expression.
FXTextField * myBegin
TextField for begin.
MFXIconComboBox * myMatchGenericDataTagComboBox
tag of the match box
long onCmdSetEnd(FXObject *, FXSelector, void *)
Called when the user change end text field.
std::map< std::pair< double, double >, int > myIntervals
std::vector< GNEGenericData * > retrieveGenericDatas(const SumoXMLTag genericDataTag, const double begin, const double end)
retrieve generic datas within the given interval
std::set< std::string > retrieveGenericDataParameters(const std::string &genericDataTag, const double begin, const double end) const
return a set of parameters for the given data Interval
const std::set< GNEDataSet * > & getDataSets() const
get demand elements
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:125
std::vector< GNEAttributeCarrier * > getGenericMatches(const std::vector< GNEGenericData * > &genericDatas, const std::string &attr, const char compOp, const double val, const std::string &expr)
return GenericDatas of the given type with matching attrs
void handleIDs(const std::vector< GNEAttributeCarrier * > &ACs, const ModificationMode::Operation setop=ModificationMode::Operation::DEFAULT)
apply list of ids to the current selection according to Operation,
GNENet * getNet() const
get the net object
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
ComboBox with icon.
FXString getText() const
Get the text.
FXint getCurrentItem() const
Get the current item's index.
virtual void enable()
Enable combo box.
void setCurrentItem(FXint index, FXbool notify=FALSE)
Set the current item (index is zero-based)
void setTextColor(FXColor clr)
Change text color.
void clearItems()
Remove all items from the list.
FXint getNumItems() const
Return the number of items in the list.
void setNumVisible(FXint nvis)
Set the number of visible items in the drop down list.
FXint appendIconItem(const FXString &text, FXIcon *icon=nullptr, FXColor bgColor=FXRGB(255, 255, 255), void *ptr=nullptr)
append icon
virtual void disable()
Disable combo box.