55 #ifdef CHECK_MEMORY_LEAKS 57 #endif // CHECK_MEMORY_LEAKS 75 FXIMPLEMENT(
GNESelector, FXScrollWindow, GNESelectorMap, ARRAYNUMBER(GNESelectorMap))
86 FXScrollWindow(parent, LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, WIDTH, 0),
87 myHeaderFont(
new FXFont(getApp(), "Arial", 14, FXFont::Bold)),
88 myUpdateTarget(updateTarget),
89 mySetOperation(SET_ADD),
90 mySetOperationTarget(mySetOperation),
94 myContentFrame =
new FXVerticalFrame(
this, LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, WIDTH, 0);
95 myStats =
new FXLabel(myContentFrame, getStats().c_str(), 0, JUSTIFY_LEFT);
96 myStats->setFont(myHeaderFont);
99 FXGroupBox* selBox =
new FXGroupBox(myContentFrame,
"Modification Mode",
100 GROUPBOX_NORMAL | FRAME_GROOVE | LAYOUT_FILL_X, 2, 0, 0, 0, 4, 2, 2, 2);
101 new FXRadioButton(selBox,
"add\t\tSelected objects are added to the previous selection",
102 &mySetOperationTarget, FXDataTarget::ID_OPTION + SET_ADD);
103 new FXRadioButton(selBox,
"remove\t\tSelected objects are removed from the previous selection",
104 &mySetOperationTarget, FXDataTarget::ID_OPTION + SET_SUB);
105 new FXRadioButton(selBox,
"keep\t\tRestrict previous selection by the current selection",
106 &mySetOperationTarget, FXDataTarget::ID_OPTION + SET_RESTRICT);
107 new FXRadioButton(selBox,
"replace\t\tReplace previous selection by the current selection",
108 &mySetOperationTarget, FXDataTarget::ID_OPTION + SET_REPLACE);
111 FXGroupBox* matchBox =
new FXGroupBox(myContentFrame,
"Match Attribute",
112 GROUPBOX_NORMAL | FRAME_GROOVE | LAYOUT_FILL_X, 2, 0, 0, 0, 4, 2, 2, 2);
115 for (std::vector<SumoXMLTag>::const_iterator it = tags.begin(); it != tags.end(); it++) {
116 myMatchTagBox->appendItem(
toString(*it).c_str());
118 myMatchTagBox->setCurrentItem(1);
119 myMatchTagBox->setNumVisible(myMatchTagBox->getNumItems());
120 myMatchAttrBox =
new FXListBox(matchBox);
121 onCmdSelMBTag(0, 0, 0);
122 myMatchAttrBox->setCurrentItem(3);
123 myMatchString =
new FXTextField(matchBox, 12,
this,
MID_GNE_SELMB_STRING, TEXTFIELD_NORMAL, 0, 0, 0, 0, 4, 2, 0, 2);
124 myMatchString->setText(
">10.0");
125 new FXButton(matchBox,
"Help", 0,
this,
MID_HELP);
127 FXGroupBox* selSizeBox =
new FXGroupBox(myContentFrame,
"Visual Scaling",
128 GROUPBOX_NORMAL | FRAME_GROOVE | LAYOUT_FILL_X, 2, 0, 0, 0, 4, 2, 2, 2);
131 LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK | LAYOUT_FILL_Y);
132 mySelectionScaling->setNumberFormat(1);
133 mySelectionScaling->setIncrements(0.1, .5, 1);
134 mySelectionScaling->setRange(1, 100);
135 mySelectionScaling->setValue(1);
136 mySelectionScaling->setHelpText(
"Enlarge selected objects");
142 ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
143 0, 0, 0, 0, 4, 4, 3, 3);
146 ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
147 0, 0, 0, 0, 4, 4, 3, 3);
149 new FXButton(myContentFrame,
"Save\t\tSave ids of currently selected objects to a file.", 0,
this,
MID_CHOOSEN_SAVE,
150 ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
151 0, 0, 0, 0, 4, 4, 3, 3);
154 new FXButton(myContentFrame,
"Load\t\tLoad ids from a file according to the current modfication mode.", 0,
this,
MID_CHOOSEN_LOAD,
155 ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
156 0, 0, 0, 0, 4, 4, 3, 3);
160 new FXLabel(myContentFrame,
"Hold <SHIFT> for\nrectangle selection.\nPress <DEL> to\ndelete selected items.", 0, JUSTIFY_LEFT);
173 FXFileDialog opendialog(
this,
"Open List of Selected Items");
175 opendialog.setSelectMode(SELECTFILE_EXISTING);
176 opendialog.setPatternList(
"Selection files (*.txt)\nAll files (*)");
180 if (opendialog.execute()) {
182 std::string file = opendialog.getFilename().text();
186 handleIDs(std::vector<GUIGlID>(ids.begin(), ids.end()),
false);
188 FXMessageBox::error(
this, MBOX_OK,
"Errors while loading Selection",
"%s", errors.c_str());
206 FXMessageBox::error(
this, MBOX_OK,
"Storing Selection failed",
"%s", e.what());
223 for (std::set<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) {
227 for (std::set<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) {
241 for (std::vector<SumoXMLAttr>::const_iterator it = attrs.begin(); it != attrs.end(); it++) {
268 char compOp = expr[0];
269 if (compOp ==
'<' || compOp ==
'>' || compOp ==
'=') {
270 expr = expr.substr(1);
275 std::istringstream buf(expr);
277 if (!buf.fail() && (size_t)buf.tellg() == expr.size()) {
289 char compOp = expr[0];
290 if (compOp ==
'=' || compOp ==
'!' || compOp ==
'^') {
291 expr = expr.substr(1);
310 FXDialogBox* helpDialog =
new FXDialogBox(
this,
"Match Attribute Help", DECOR_CLOSE | DECOR_TITLE);
311 std::ostringstream help;
313 <<
"The 'Match Attribute' controls allow to specify a set of objects which are then applied to the current selection " 314 <<
"according to the current 'Modification Mode'.\n" 315 <<
"1. Select an object type from the first input box\n" 316 <<
"2. Select an attribute from the second input box\n" 317 <<
"3. Enter a 'match expression' in the third input box and press <return>\n" 319 <<
"The empty expression matches all objects\n" 320 <<
"For numerical attributes the match expression must consist of a comparison operator ('<', '>', '=') and a number.\n" 321 <<
"An object matches if the comparison between its attribute and the given number by the given operator evaluates to 'true'\n" 323 <<
"For string attributes the match expression must consist of a comparison operator ('', '=', '!', '^') and a string.\n" 324 <<
" '' (no operator) matches if string is a substring of that object'ts attribute.\n" 325 <<
" '=' matches if string is an exact match.\n" 326 <<
" '!' matches if string is not a substring.\n" 327 <<
" '^' matches if string is not an exact match.\n" 330 <<
"junction; id; 'foo' -> match all junctions that have 'foo' in their id\n" 331 <<
"junction; type; '=priority' -> match all junctions of type 'priority', but not of type 'priority_stop'\n" 332 <<
"edge; speed; '>10' -> match all edges with a speed above 10\n";
333 new FXLabel(helpDialog, help.str().c_str(), 0, JUSTIFY_LEFT);
335 new FXButton(helpDialog,
"OK\t\tSave modifications", 0, helpDialog, FXDialogBox::ID_ACCEPT,
336 ICON_BEFORE_TEXT | LAYOUT_FILL_X | FRAME_THICK | FRAME_RAISED,
337 0, 0, 0, 0, 4, 4, 3, 3);
338 helpDialog->create();
356 FXScrollWindow::show();
363 FXScrollWindow::hide();
369 return "Selection:\n" +
386 std::set<GUIGlID> previousSelection;
397 std::set<GUIGlID> idsSet(ids.begin(), ids.end());
398 std::set<GUIGlID> selected;
399 std::set<GUIGlID> deselected;
401 for (std::vector<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) {
406 const GNEEdge& edge = (
static_cast<GNELane*
>(object))->getParentEdge();
414 for (std::set<GUIGlID>::const_iterator it = idsSet.begin(); it != idsSet.end(); it++) {
425 type =
object->getType();
427 if (type ==
GLO_LANE && selectEdges) {
430 id = (
static_cast<GNELane*
>(object))->getParentEdge().getGlID();
433 switch (setOperation) {
439 deselected.insert(
id);
442 if (previousSelection.count(
id)) {
461 std::vector<GUIGlID> result;
464 for (std::set<GUIGlID>::const_iterator it = allIDs.begin(); it != allIDs.end(); it++) {
468 throw ProcessError(
"Unkown object passed to GNESelector::getMatches (id=" +
toString(
id) +
").");
471 if (ac && ac->
getTag() == tag) {
473 result.push_back(
id);
474 }
else if (numerical) {
481 result.push_back(
id);
486 result.push_back(
id);
491 result.push_back(
id);
503 if (acVal.find(expr) != std::string::npos) {
504 result.push_back(
id);
508 if (acVal.find(expr) == std::string::npos) {
509 result.push_back(
id);
514 result.push_back(
id);
519 result.push_back(
id);
SumoXMLTag
Numbers representing SUMO-XML - element names.
static bool isNumerical(SumoXMLAttr attr)
whether an attribute is numerical
void toggleSelection(GUIGlID id)
Toggles selection of an object.
std::set< GUIGlID > getGlIDs(GUIGlObjectType type=GLO_MAX)
long onCmdLoad(FXObject *, FXSelector, void *)
Called when the user presses the Load-button.
void setSelectionScaling(SUMOReal selectionScale)
void remove2Update()
Removes the dialog to be updated.
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
void p_begin(const std::string &description)
FXString gCurrentFolder
The folder used as last.
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
FXListBox * myMatchAttrBox
FXuint mySetOperation
how to modify selection
virtual std::string getAttribute(SumoXMLAttr key) const =0
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extension, FXIcon *icon, FXString ¤tFolder)
Returns the file name to write.
GUIGlID getGlID() const
Returns the numerical id of the object.
GNEViewNet * myUpdateTarget
FXFont * myHeaderFont
Font for the widget.
std::set< GUIGlID > loadIDs(const std::string &filename, std::string &msgOut, GUIGlObjectType type=GLO_MAX, int maxErrors=16)
Loads a selection list (optionally with restricted type) and returns the ids of all active objects...
const std::string ALL_VCLASS_NAMES_MATCH_STRING
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
selector match box messages
const std::set< GUIGlID > & getSelected() const
Returns the list of ids of all selected objects.
static const std::vector< SumoXMLTag > & allowedTags()
get all editable attributes for tag.
FXdouble getValue() const
Return current value.
long onCmdSelMBString(FXObject *, FXSelector, void *)
Called when the user enters a new selection expression validates expression and modifies current sele...
long onCmdSelMBTag(FXObject *, FXSelector, void *)
Called when the user selectes a tag in the match box updates the attr listbox Repaints itself...
FXLabel * myStats
the label for selection statistics
long onCmdInvert(FXObject *, FXSelector, void *)
Called when the user presses the Invert-button invert the selection Repaints itself.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
long onCmdClear(FXObject *, FXSelector, void *)
Called when the user presses the Clear-button.
StringBijection< SUMOVehicleClass > SumoVehicleClassStrings(sumoVehicleClassStringInitializer, SVC_CUSTOM2, false)
FXDEFMAP(GNESelector) GNESelectorMap[]
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
long onCmdScaleSelection(FXObject *, FXSelector, void *)
Called when the user changes visual scaling.
A road/street connecting two junctions (netedit-version)
void add2Update(UpdateTarget *updateTarget)
Adds a dialog to be updated.
static const std::vector< SumoXMLAttr > & allowedAttributes(SumoXMLTag tag)
get all editable attributes for tag.
~GNESelector()
Destructor.
long onCmdSave(FXObject *, FXSelector, void *)
Called when the user presses the Save-button.
std::string getStats() const
FXListBox * myMatchTagBox
state variables for the match box
GNEJunction * getDest() const
returns the destination-junction
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=OUTPUT_ACCURACY)
SumoXMLTag getTag() const
FXRealSpinDial * mySelectionScaling
void unblockObject(GUIGlID id)
Marks an object as unblocked.
void handleIDs(std::vector< GUIGlID > ids, bool selectEdges, SetOperation setop=SET_DEFAULT)
GUIGlObject * getObjectBlocking(GUIGlID id)
Returns the object from the container locking it.
GUISelectedStorage gSelected
A global holder of selected objects.
static FXIcon * getIcon(GUIIcon which)
GNEJunction * getSource() const
returns the source-junction
std::vector< GUIGlID > getMatches(SumoXMLTag tag, SumoXMLAttr attr, char compOp, SUMOReal val, const std::string &expr)
return objects of the given type with matching attrs
long onCmdHelp(FXObject *, FXSelector, void *)
Called when the user clicks the help button pop up help window.
void save(GUIGlObjectType type, const std::string &filename)
Saves a selection list.
FXTextField * myMatchString