Eclipse SUMO - Simulation of Urban MObility
GNEMatchAttribute.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
25
26#include "GNEMatchAttribute.h"
27
28// ===========================================================================
29// FOX callback mapping
30// ===========================================================================
31
32FXDEFMAP(GNEMatchAttribute) GNEMatchAttributeMap[] = {
36 FXMAPFUNC(SEL_COMMAND, MID_HELP, GNEMatchAttribute::onCmdHelp)
37};
38
39// Object implementation
40FXIMPLEMENT(GNEMatchAttribute, MFXGroupBoxModule, GNEMatchAttributeMap, ARRAYNUMBER(GNEMatchAttributeMap))
41
42// ===========================================================================
43// method definitions
44// ===========================================================================
45
46GNEMatchAttribute::GNEMatchAttribute(GNEElementSet* elementSet, SumoXMLTag defaultTag, SumoXMLAttr defaultAttr, const std::string& defaultValue) :
47 MFXGroupBoxModule(elementSet->getSelectorFrameParent(), "Match Attribute"),
48 myElementSet(elementSet),
49 myCurrentTag(defaultTag),
50 myCurrentAttribute(defaultAttr) {
51 // Create MFXIconComboBox for tags
52 myMatchTagComboBox = new MFXIconComboBox(getCollapsableFrame(), GUIDesignComboBoxNCol, true, this, MID_GNE_SELECTORFRAME_SELECTTAG, GUIDesignComboBox);
53 // Create FXComboBox for Attributes
54 myMatchAttrComboBox = new FXComboBox(getCollapsableFrame(), GUIDesignComboBoxNCol, this, MID_GNE_SELECTORFRAME_SELECTATTRIBUTE, GUIDesignComboBox);
55 // Create TextField for Match string
56 myMatchString = new FXTextField(getCollapsableFrame(), GUIDesignTextFieldNCol, this, MID_GNE_SELECTORFRAME_PROCESSSTRING, GUIDesignTextField);
57 // create button
58 myMatchStringButton = new FXButton(getCollapsableFrame(), TL("Apply selection"), nullptr, this, MID_GNE_SELECTORFRAME_PROCESSSTRING, GUIDesignButton);
59 // Create help button
60 new FXButton(getCollapsableFrame(), TL("Help"), nullptr, this, MID_HELP, GUIDesignButtonRectangular);
61 // Set default value for Match string
62 myMatchString->setText(defaultValue.c_str());
63}
64
65
67
68
69void
71 // enable comboBox, text field and button
73 myMatchAttrComboBox->enable();
74 myMatchString->enable();
75 myMatchStringButton->enable();
76}
77
78
79void
81 // disable comboboxes and text field
83 myMatchAttrComboBox->disable();
84 myMatchString->disable();
85 myMatchStringButton->disable();
86 // change colors to black (even if there are invalid values)
87 myMatchTagComboBox->setTextColor(FXRGB(0, 0, 0));
88 myMatchAttrComboBox->setTextColor(FXRGB(0, 0, 0));
89 myMatchString->setTextColor(FXRGB(0, 0, 0));
90}
91
92
93void
95 // declare flag for proj
96 const bool proj = (GeoConvHelper::getFinal().getProjString() != "!");
97 // get tags for the given element set
98 std::vector<GNETagProperties> tagPropertiesStrings;
99 if (type == (GNEElementSet::Type::NETWORK)) {
100 tagPropertiesStrings = GNEAttributeCarrier::getTagPropertiesByType(GNETagProperties::TagType::NETWORKELEMENT);
101 } else if (type == GNEElementSet::Type::ADDITIONAL) {
102 tagPropertiesStrings = GNEAttributeCarrier::getTagPropertiesByType(GNETagProperties::TagType::ADDITIONALELEMENT);
103 } else if (type == GNEElementSet::Type::SHAPE) {
104 tagPropertiesStrings = GNEAttributeCarrier::getTagPropertiesByType(GNETagProperties::TagType::SHAPE);
105 } else if (type == GNEElementSet::Type::TAZ) {
106 tagPropertiesStrings = GNEAttributeCarrier::getTagPropertiesByType(GNETagProperties::TagType::TAZELEMENT);
107 } else if (type == GNEElementSet::Type::DEMAND) {
108 tagPropertiesStrings = GNEAttributeCarrier::getTagPropertiesByType(GNETagProperties::TagType::DEMANDELEMENT | GNETagProperties::TagType::STOP);
109 } else if (type == GNEElementSet::Type::DATA) {
110 tagPropertiesStrings = GNEAttributeCarrier::getTagPropertiesByType(GNETagProperties::TagType::GENERICDATA);
111 } else {
112 throw ProcessError(TL("Unknown set"));
113 }
114 // now filter to allow only drawables and proj
115 myTagPropertiesString.clear();
116 for (const auto& tagProperty : tagPropertiesStrings) {
117 if (tagProperty.isDrawable() && (!tagProperty.requireProj() || proj)) {
118 myTagPropertiesString.push_back(tagProperty);
119 }
120 }
121 // update tag
122 updateTag();
123 // update attribute
125 // show groupbox
126 show();
127}
128
129
130void
132 // hide groupbox
133 hide();
134}
135
136
137long
138GNEMatchAttribute::onCmdSelMBTag(FXObject*, FXSelector, void*) {
139 // reset current tag
141 // set invalid color
142 myMatchTagComboBox->setTextColor(FXRGB(255, 0, 0));
143 // iterate over tags
144 for (const auto& tagString : myTagPropertiesString) {
145 if (tagString.getFieldString() == myMatchTagComboBox->getText().text()) {
146 // set valid tag
147 myCurrentTag = tagString.getTag();
148 // set valid color
149 myMatchTagComboBox->setTextColor(FXRGB(0, 0, 0));
150 }
151 }
152 // update attribute
154 return 1;
155}
156
157
158long
159GNEMatchAttribute::onCmdSelMBAttribute(FXObject*, FXSelector, void*) {
160 // first obtain a copy of item attributes vinculated with current tag
161 auto tagPropertiesCopy = GNEAttributeCarrier::getTagProperty(myCurrentTag);
162 // obtain tag property (only for improve code legibility)
164 // add an extra AttributeValues to allow select ACs using as criterium "parameters"
165 GNEAttributeProperties extraAttrProperty;
167 GNEAttributeProperties::AttrProperty::STRING,
168 "Parameters");
169 tagPropertiesCopy.addAttribute(extraAttrProperty);
170 // add extra attribute if item can close shape
171 if (tagValue.canCloseShape()) {
172 // add an extra AttributeValues to allow select ACs using as criterium "close shape"
174 GNEAttributeProperties::AttrProperty::BOOL | GNEAttributeProperties::AttrProperty::DEFAULTVALUE,
175 "Close shape",
176 "true");
177 tagPropertiesCopy.addAttribute(extraAttrProperty);
178 }
179 // add extra attribute if item can have parent
180 if (tagValue.isChild()) {
181 // add an extra AttributeValues to allow select ACs using as criterium "parent"
182 extraAttrProperty = GNEAttributeProperties(GNE_ATTR_PARENT,
183 GNEAttributeProperties::AttrProperty::STRING,
184 "Parent element");
185 tagPropertiesCopy.addAttribute(extraAttrProperty);
186 }
187 // set current selected attribute
189 for (const auto& attribute : tagPropertiesCopy) {
190 if (attribute.getAttrStr() == myMatchAttrComboBox->getText().text()) {
191 myCurrentAttribute = attribute.getAttr();
192 }
193 }
194 // check if selected attribute is valid
196 myMatchAttrComboBox->setTextColor(FXRGB(0, 0, 0));
197 myMatchString->enable();
198 myMatchStringButton->enable();
199 } else {
200 myMatchAttrComboBox->setTextColor(FXRGB(255, 0, 0));
201 myMatchString->disable();
202 myMatchStringButton->disable();
203 }
204 return 1;
205}
206
207
208long
209GNEMatchAttribute::onCmdSelMBString(FXObject*, FXSelector, void*) {
210 // obtain expresion
211 std::string expr(myMatchString->getText().text());
213 bool valid = true;
214 if (expr == "") {
215 // the empty expression matches all objects
217 } else if (tagValue.hasAttribute(myCurrentAttribute) && tagValue.getAttributeProperties(myCurrentAttribute).isNumerical()) {
218 // The expression must have the form
219 // <val matches if attr < val
220 // >val matches if attr > val
221 // =val matches if attr = val
222 // val matches if attr = val
223 char compOp = expr[0];
224 if (compOp == '<' || compOp == '>' || compOp == '=') {
225 expr = expr.substr(1);
226 } else {
227 compOp = '=';
228 }
229 // check if value can be parsed to double
230 if (GNEAttributeCarrier::canParse<double>(expr.c_str())) {
231 myElementSet->getSelectorFrameParent()->handleIDs(myElementSet->getSelectorFrameParent()->getMatches(myCurrentTag, myCurrentAttribute, compOp, GNEAttributeCarrier::parse<double>(expr.c_str()), expr));
232 } else {
233 valid = false;
234 }
235 } else {
236 // The expression must have the form
237 // =str: matches if <str> is an exact match
238 // !str: matches if <str> is not a substring
239 // ^str: matches if <str> is not an exact match
240 // str: matches if <str> is a substring (sends compOp '@')
241 // Alternatively, if the expression is empty it matches all objects
242 char compOp = expr[0];
243 if (compOp == '=' || compOp == '!' || compOp == '^') {
244 expr = expr.substr(1);
245 } else {
246 compOp = '@';
247 }
249 }
250 if (valid) {
251 myMatchString->setTextColor(FXRGB(0, 0, 0));
252 myMatchString->killFocus();
253 myMatchStringButton->enable();
254 } else {
255 myMatchString->setTextColor(FXRGB(255, 0, 0));
256 myMatchStringButton->disable();
257 }
258 return 1;
259}
260
261
262long
263GNEMatchAttribute::onCmdHelp(FXObject*, FXSelector, void*) {
264 // Create dialog box
265 FXDialogBox* additionalNeteditAttributesHelpDialog = new FXDialogBox(getCollapsableFrame(), "Netedit Parameters Help", GUIDesignDialogBox);
266 additionalNeteditAttributesHelpDialog->setIcon(GUIIconSubSys::getIcon(GUIIcon::MODEADDITIONAL));
267 // set help text
268 std::ostringstream help;
269 help
270 << TL("- The 'Match Attribute' controls allow to specify a set of objects which are then applied to the current selection\n")
271 << TL(" according to the current 'Modification Mode'.\n")
272 << TL(" 1. Select an object type from the first input box\n")
273 << TL(" 2. Select an attribute from the second input box\n")
274 << TL(" 3. Enter a 'match expression' in the third input box and press <return>\n")
275 << "\n"
276 << TL("- The empty expression matches all objects\n")
277 << TL("- For numerical attributes the match expression must consist of a comparison operator ('<', '>', '=') and a number.\n")
278 << TL("- An object matches if the comparison between its attribute and the given number by the given operator evaluates to 'true'\n")
279 << "\n"
280 << TL("- For string attributes the match expression must consist of a comparison operator ('', '=', '!', '^') and a string.\n")
281 << TL(" '' (no operator) matches if string is a substring of that object'ts attribute.\n")
282 << TL(" '=' matches if string is an exact match.\n")
283 << TL(" '!' matches if string is not a substring.\n")
284 << TL(" '^' matches if string is not an exact match.\n")
285 << "\n"
286 << TL("- Examples:\n")
287 << TL(" junction; id; 'foo' -> match all junctions that have 'foo' in their id\n")
288 << TL(" junction; type; '=priority' -> match all junctions of type 'priority', but not of type 'priority_stop'\n")
289 << TL(" edge; speed; '>10' -> match all edges with a speed above 10\n");
290 // Create label with the help text
291 new FXLabel(additionalNeteditAttributesHelpDialog, help.str().c_str(), nullptr, GUIDesignLabelFrameInformation);
292 // Create horizontal separator
293 new FXHorizontalSeparator(additionalNeteditAttributesHelpDialog, GUIDesignHorizontalSeparator);
294 // Create frame for OK Button
295 FXHorizontalFrame* myHorizontalFrameOKButton = new FXHorizontalFrame(additionalNeteditAttributesHelpDialog, GUIDesignAuxiliarHorizontalFrame);
296 // Create Button Close (And two more horizontal frames to center it)
297 new FXHorizontalFrame(myHorizontalFrameOKButton, GUIDesignAuxiliarHorizontalFrame);
298 new FXButton(myHorizontalFrameOKButton, TL("OK\t\tclose"), GUIIconSubSys::getIcon(GUIIcon::ACCEPT), additionalNeteditAttributesHelpDialog, FXDialogBox::ID_ACCEPT, GUIDesignButtonOK);
299 new FXHorizontalFrame(myHorizontalFrameOKButton, GUIDesignAuxiliarHorizontalFrame);
300 // Write Warning in console if we're in testing mode
301 WRITE_DEBUG("Opening help dialog of selector frame");
302 // create Dialog
303 additionalNeteditAttributesHelpDialog->create();
304 // show in the given position
305 additionalNeteditAttributesHelpDialog->show(PLACEMENT_CURSOR);
306 // refresh APP
307 getApp()->refresh();
308 // open as modal dialog (will block all windows until stop() or stopModal() is called)
309 getApp()->runModalFor(additionalNeteditAttributesHelpDialog);
310 // Write Warning in console if we're in testing mode
311 WRITE_DEBUG("Close help dialog of selector frame");
312 return 1;
313}
314
315
316void
318 // declare tag index
319 int tagIndex = -1;
320 // fill combo box tags
322 myMatchTagComboBox->setTextColor(FXRGB(0, 0, 0));
323 // itreate over myTagPropertiesString
324 for (int i = 0; i < (int)myTagPropertiesString.size(); i++) {
325 // add tag in combo Box
326 myMatchTagComboBox->appendIconItem(myTagPropertiesString.at(i).getFieldString().c_str(), GUIIconSubSys::getIcon(myTagPropertiesString.at(i).getGUIIcon()));
327 // check tag index
328 if (myTagPropertiesString.at(i).getTag() == myCurrentTag) {
329 tagIndex = i;
330 }
331 }
332 // set num visible items
334 // check tagIndex
335 if (tagIndex == -1) {
337 myCurrentTag = myTagPropertiesString.front().getTag();
338 } else {
340 }
341}
342
343
344void
346 // first check if tag is valid
348 // now continue with attributes
349 const auto& tagProperty = GNEAttributeCarrier::getTagProperty(myCurrentTag);
350 // set color and enable items
351 myMatchAttrComboBox->enable();
352 myMatchAttrComboBox->setTextColor(FXRGB(0, 0, 0));
353 myMatchAttrComboBox->clearItems();
354 // declare attr index
355 int attrIndex = -1;
356 // fill attribute combo box
357 for (int i = 0; i < (int)tagProperty.getNumberOfAttributes(); i++) {
358 myMatchAttrComboBox->appendItem(tagProperty.at(i).getAttrStr().c_str());
359 // check attr index
360 if (tagProperty.at(i).getAttr() == myCurrentAttribute) {
361 attrIndex = i;
362 }
363 }
364 // Check if are allowed "Parameter"
365 if (tagProperty.hasParameters()) {
368 attrIndex = (myMatchAttrComboBox->getNumItems() - 1);
369 }
370 }
371 // check if item can close shape
372 if (tagProperty.canCloseShape()) {
375 attrIndex = (myMatchAttrComboBox->getNumItems() - 1);
376 }
377 }
378 // check if item can have parent
379 if (tagProperty.isChild()) {
380 myMatchAttrComboBox->appendItem(toString(GNE_ATTR_PARENT).c_str());
382 attrIndex = (myMatchAttrComboBox->getNumItems() - 1);
383 }
384 }
385 // set num visible items
386 myMatchAttrComboBox->setNumVisible(myMatchAttrComboBox->getNumItems());
387 // check attrIndex
388 if (attrIndex == -1) {
389 myMatchAttrComboBox->setCurrentItem(0);
390 myCurrentAttribute = tagProperty.begin()->getAttr();
391 } else {
392 myMatchAttrComboBox->setCurrentItem(attrIndex);
393 }
394 // enable mach string
395 myMatchString->enable();
396 myMatchStringButton->enable();
397 } else {
398 // disable myMatchAttrComboBox
399 myMatchAttrComboBox->disable();
400 // disable mach string
401 myMatchString->disable();
402 myMatchStringButton->disable();
403 }
404}
405
406/****************************************************************************/
FXDEFMAP(GNEMatchAttribute) GNEMatchAttributeMap[]
@ MID_GNE_SELECTORFRAME_SELECTATTRIBUTE
select attribute in selector frame
Definition: GUIAppEnum.h:966
@ MID_GNE_SELECTORFRAME_SELECTTAG
select tag in selector frame
Definition: GUIAppEnum.h:964
@ MID_HELP
help button
Definition: GUIAppEnum.h:641
@ MID_GNE_SELECTORFRAME_PROCESSSTRING
process string
Definition: GUIAppEnum.h:968
#define GUIDesignButton
Definition: GUIDesigns.h:77
#define GUIDesignComboBox
Definition: GUIDesigns.h:306
#define GUIDesignComboBoxNCol
number of column of every combo box
Definition: GUIDesigns.h:321
#define GUIDesignTextField
Definition: GUIDesigns.h:48
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:397
#define GUIDesignDialogBox
Definition: GUIDesigns.h:584
#define GUIDesignButtonRectangular
little button rectangula used in frames (For example, in "help" buttons)
Definition: GUIDesigns.h:83
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:69
#define GUIDesignButtonOK
Definition: GUIDesigns.h:142
#define GUIDesignHorizontalSeparator
Definition: GUIDesigns.h:452
#define GUIDesignLabelFrameInformation
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition: GUIDesigns.h:271
@ MODEADDITIONAL
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:276
#define TL(string)
Definition: MsgHandler.h:282
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_NOTHING
invalid tag
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ GNE_ATTR_PARENT
parent of an additional element
@ GNE_ATTR_PARAMETERS
parameters "key1=value1|key2=value2|...|keyN=valueN"
@ GNE_ATTR_CLOSE_SHAPE
Close shape of a polygon (Used by GNEPolys)
@ SUMO_ATTR_NOTHING
invalid attribute
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static const std::vector< GNETagProperties > getTagPropertiesByType(const int tagPropertyCategory)
get tagProperties associated to the given GNETagProperties::TagType (NETWORKELEMENT,...
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
Type
FOX-declaration.
Definition: GNEElementSet.h:42
GNESelectorFrame * getSelectorFrameParent() const
get Selector Frame Parent
void showMatchAttribute(const GNEElementSet::Type type)
show match attributes
~GNEMatchAttribute()
destructor
FXButton * myMatchStringButton
match string button
SumoXMLAttr myCurrentAttribute
current SumoXMLTag Attribute
FXComboBox * myMatchAttrComboBox
attributes of the match box
MFXIconComboBox * myMatchTagComboBox
tag of the match box
GNEElementSet * myElementSet
pointer to element set Parent
void updateTag()
FOX need this.
std::vector< GNETagProperties > myTagPropertiesString
vector with tagProperties
void updateAttribute()
update attribute
FXTextField * myMatchString
string of the match
void hideMatchAttribute()
hide match attributes
long onCmdSelMBTag(FXObject *, FXSelector, void *)
Called when the user selectes a tag in the match box.
long onCmdHelp(FXObject *, FXSelector, void *)
Called when the user clicks the help button.
long onCmdSelMBString(FXObject *, FXSelector, void *)
Called when the user enters a new selection expression.
long onCmdSelMBAttribute(FXObject *, FXSelector, void *)
Called when the user selectes a tag in the match box.
void enableMatchAttribute()
enable match attributes
void disableMatchAttribute()
disable match attributes
SumoXMLTag myCurrentTag
current SumoXMLTag tag
std::vector< GNEAttributeCarrier * > getMatches(const SumoXMLTag ACTag, const SumoXMLAttr ACAttr, const char compOp, const double val, const std::string &expr)
return ACs 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,
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
const std::string & getProjString() const
Returns the original projection definition.
MFXGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
ComboBox with icon.
FXString getText() const
Get the text.
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.
Definition: json.hpp:4471