Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNEElementTable.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2025 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// Table used in GNEElementList
19/****************************************************************************/
20
23#include <netedit/GNENet.h>
28
29#include "GNEElementTable.h"
30
31// ===========================================================================
32// FOX callback mapping
33// ===========================================================================
34
41
42// Object implementation
43FXIMPLEMENT(GNEElementTable::Row, FXHorizontalFrame, RowMap, ARRAYNUMBER(RowMap))
44
45// ===========================================================================
46// method definitions
47// ===========================================================================
48
49// ---------------------------------------------------------------------------
50// GNEElementTable::ColumnHeader - methods
51// ---------------------------------------------------------------------------
52
54 FXHorizontalFrame(elementTable, GUIDesignAuxiliarHorizontalFrame) {
55 // create horizontal label with uniform width
56 auto horizontalFrameLabels = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrameUniform);
57 // create empty label
58 new FXLabel(horizontalFrameLabels, "", nullptr, GUIDesignLabelFixed(GUIDesignHeight));
59 // create a label for every attribute
60 for (const auto& attrProperty : tagProperties->getAttributeProperties()) {
61 // check if this attribute can be edited in dialog
62 if (attrProperty->isDialogEditor()) {
63 // create label
64 myLabels.push_back(std::make_pair(attrProperty->getAttr(), new FXLabel(horizontalFrameLabels, attrProperty->getAttrStr().c_str(),
65 nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL))));
66 // check if this attribute is sortable
67 if (attrProperty->isNumerical()) {
68 mySortableAttrs.push_back(attrProperty->getAttr());
69 }
70 }
71 }
72 // calculate buttons label width
73 int buttonLabelWidth = 15 + GUIDesignHeight;
74 if (elementTable->myOptions & GNEElementList::Options::DIALOG_ELEMENT) {
75 buttonLabelWidth += GUIDesignHeight;
76 }
77 if (elementTable->myOptions & GNEElementList::Options::DIALOG_VCLASS) {
78 buttonLabelWidth += GUIDesignHeight;
79 }
80 // create empty label (icons and vertical scroller)
81 new FXLabel(horizontalFrameLabels, "", nullptr, GUIDesignLabelFixed(buttonLabelWidth));
82}
83
84
86
87
88void
90 // enable all labels
91 for (const auto& label : myLabels) {
92 label.second->enable();
93 }
94}
95
96
97void
99 // disable all labels
100 for (const auto& label : myLabels) {
101 label.second->disable();
102 }
103}
104
105
106size_t
108 return myLabels.size();
109}
110
111
112const std::vector<SumoXMLAttr>&
114 return mySortableAttrs;
115}
116
117
118int
120 for (int i = 0; i < (int)myLabels.size(); i++) {
121 if (myLabels.at(i).first == attr) {
122 return i;
123 }
124 }
125 return -1;
126}
127
128// ---------------------------------------------------------------------------
129// GNEElementTable::Row - methods
130// ---------------------------------------------------------------------------
131
132GNEElementTable::Row::Row(GNEElementTable* elementTable, const size_t rowIndex,
134 FXHorizontalFrame(elementTable->myRowsFrame, GUIDesignAuxiliarHorizontalFrame),
135 myElementTable(elementTable),
136 myRowIndex(rowIndex),
137 myAC(AC) {
138 // create and disable index label
139 myIndexLabel = new FXLabel(this, std::to_string(rowIndex + 1).c_str(), nullptr, GUIDesignLabelIconThick);
140 // create horizontal frame for text fields packed uniformly
141 FXHorizontalFrame* textFieldsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrameUniform);
142 // create text fields
143 const auto toolTip = AC->getNet()->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();
144 for (const auto& attrProperty : AC->getTagProperty()->getAttributeProperties()) {
145 // check if this attribute can be edited in dialog
146 if (attrProperty->isDialogEditor()) {
147 // create text field targeting the GNEElementTable
148 auto textField = new MFXTextFieldIcon(textFieldsFrame, toolTip, GUIIcon::EMPTY,
150 // set value from attribute carrier
151 textField->setText(AC->getAttribute(attrProperty->getAttr()).c_str());
152 // add in AttributeTextFields vector
153 myAttributeTextFields.push_back(std::make_pair(attrProperty->getAttr(), textField));
154 }
155 }
156 // create remove button targeting the GNEDialog
157 myRemoveButton = new FXButton(this, "", GUIIconSubSys::getIcon(GUIIcon::REMOVE), this,
159 // check if create vClass dialog button
161 // create open dialog button targeting the GNEDialog
162 myOpenVClassButton = new FXButton(this, "", GUIIconSubSys::getIcon(GUIIcon::VEHICLE), this,
164 }
165 // chekc if create element dialog button
167 // create open dialog button targeting the GNEDialog
168 myOpenDialogButton = new FXButton(this, "", GUIIconSubSys::getIcon(GUIIcon::MODEINSPECT), this,
170 }
171 // create row if table was previously created
172 if (elementTable->id() != 0) {
173 create();
174 elementTable->myRowsFrame->recalc();
175 }
176}
177
178
180
181
182void
184 // enable index label
185 myIndexLabel->enable();
186 // enable all text fields
187 for (const auto& attributeTextField : myAttributeTextFields) {
188 attributeTextField.second->enable();
189 }
190 // enable remove button
191 myRemoveButton->enable();
192 // enable open dialog button if it exists
193 if (myOpenDialogButton) {
194 myOpenDialogButton->enable();
195 }
196}
197
198
199void
201 // disable index label
202 myIndexLabel->disable();
203 // disable all text fields
204 for (const auto& attributeTextField : myAttributeTextFields) {
205 attributeTextField.second->disable();
206 }
207 // disable remove button
208 myRemoveButton->disable();
209 // disable open dialog button if it exists
210 if (myOpenDialogButton) {
211 myOpenDialogButton->disable();
212 }
213}
214
215
216void
218 // set new attribute carrier
219 myAC = AC;
220 // update text fields
221 for (const auto& attributeTextField : myAttributeTextFields) {
222 // get value from attribute carrier
223 const std::string value = myAC->getAttribute(attributeTextField.first);
224 // set text in text field
225 attributeTextField.second->setText(value.c_str());
226 // set valid color
227 attributeTextField.second->setTextColor(GUIDesignTextColorBlack);
228 }
229}
230
231
232std::string
233GNEElementTable::Row::getValue(const size_t column) const {
234 // check index
235 if (column < myAttributeTextFields.size()) {
236 // return text from text field
237 return myAttributeTextFields.at(column).second->getText().text();
238 } else {
239 throw ProcessError("Column ndex out of bounds in GNEElementTable::Row::getValue");
240 }
241}
242
243
244bool
246 // iterate over all text fields
247 for (const auto& attributeTextField : myAttributeTextFields) {
248 // check if text fields colors are valid
249 if ((attributeTextField.second->getTextColor() == GUIDesignTextColorRed) ||
250 (attributeTextField.second->getBackColor() == GUIDesignBackgroundColorRed)) {
251 return false;
252 }
253 }
254 return true;
255}
256
257
258long
259GNEElementTable::Row::onCmdEditRow(FXObject* sender, FXSelector, void*) {
260 // iterate over all text fields
261 for (const auto& attributeTextField : myAttributeTextFields) {
262 // check if sender is the text field
263 if (attributeTextField.second == sender) {
264 // get value
265 const std::string value = attributeTextField.second->getText().text();
266 // check if the value is valid
267 if (!myAC->isValid(attributeTextField.first, value)) {
268 // set red color
269 attributeTextField.second->setTextColor(GUIDesignTextColorRed);
270 // set background red
271 if (value.empty()) {
272 attributeTextField.second->setBackColor(GUIDesignBackgroundColorRed);
273 }
274 } else {
275 // set value in GNEAttributeCarrier using undo-redo
276 myAC->setAttribute(attributeTextField.first, value, myAC->getNet()->getViewNet()->getUndoList());
277 // restore black color and kill focus
278 attributeTextField.second->setTextColor(GUIDesignTextColorBlack);
279 attributeTextField.second->setBackColor(GUIDesignBackgroundColorWhite);
280 attributeTextField.second->killFocus();
281 }
282 // stop after found text field
283 return 1;
284 }
285 }
286 return 0;
287}
288
289
290long
291GNEElementTable::Row::onCmdRemoveRow(FXObject*, FXSelector, void*) {
292 return myElementTable->myElementList->removeElement(myRowIndex);
293}
294
295
296long
297GNEElementTable::Row::onCmdOpenElementDialog(FXObject*, FXSelector, void*) {
298 return myElementTable->myElementList->openElementDialog(myRowIndex);
299}
300
301
302long
303GNEElementTable::Row::onCmdOpenVClassDialog(FXObject*, FXSelector, void*) {
304 // get column with 'allow' attribute
305 const int allowColumnIndex = myElementTable->myColumnHeader->getAttributeIndex(SUMO_ATTR_ALLOW);
306 if (allowColumnIndex >= 0) {
307 // declare allowVClassesDialog
308 const auto allowVClassesDialog = new GNEVClassesDialog(myAC->getNet()->getViewNet()->getViewParent()->getGNEAppWindows(),
309 SUMO_ATTR_ALLOW, myAC->getAttribute(SUMO_ATTR_ALLOW));
310 // continue depending of result
311 if (allowVClassesDialog->getResult() == GNEDialog::Result::ACCEPT) {
312 myAttributeTextFields.at(allowColumnIndex).second->setText(allowVClassesDialog->getModifiedVClasses().c_str(), TRUE);
313 }
314 }
315 return 1;
316}
317
318// ---------------------------------------------------------------------------
319// GNEElementTable - methods
320// ---------------------------------------------------------------------------
321
323 FXVerticalFrame(elementList, LAYOUT_FIX_WIDTH | ((options & GNEElementList::Options::FIXED_HEIGHT) ? LAYOUT_FIX_HEIGHT : LAYOUT_FILL_Y),
324 0, 0, 400, 300, 0, 0, 0, 0, 0, 0),
325 myElementList(elementList),
326 myOptions(options) {
327 // create column header
328 myColumnHeader = new ColumnHeader(this, tagProperties);
329 // create scroll windows for rows
330 myScrollWindow = new FXScrollWindow(this, GUIDesignScrollWindowFixedWidth(400));
331 // create vertical frame for rows and set back
332 myRowsFrame = new FXVerticalFrame(myScrollWindow, GUIDesignAuxiliarFrame);
334}
335
336
339
340
345
346
347void
349 // enable all rows
350 for (const auto& row : myRows) {
351 row->enableRow();
352 }
353 // enable horizontal frame
354 enable();
355}
356
357
358void
360 // disable all rows
361 for (const auto& row : myRows) {
362 row->disableRow();
363 }
364 // disable horizontal frame
365 disable();
366}
367
368
369bool
371 // check if we have any row invalid
372 for (const auto& row : myRows) {
373 if (!row->isValid()) {
374 return false;
375 }
376 }
377 return true;
378}
379
380
381void
382GNEElementTable::resizeTable(const size_t numRows) {
383 // simply remove the rows if numRows is less than the current size
384 while (myRows.size() > numRows) {
385 delete myRows.back();
386 myRows.pop_back();
387 }
388}
389
390
391void
393 // continue depending of the index
394 if (index < myRows.size()) {
395 // simply update the row
396 myRows.at(index)->updateRow(AC);
397 } else if (index == myRows.size()) {
398 // create new row and add it to the list
399 myRows.push_back(new Row(this, index, AC));
400 } else {
401 throw ProcessError("Index out of bounds in GNEElementTable::updateRow");
402 }
403}
404
405
406std::string
407GNEElementTable::getValue(const size_t rowIndex, const size_t columnIndex) const {
408 if (rowIndex < myRows.size()) {
409 return myRows.at(rowIndex)->getValue(columnIndex);
410 } else {
411 throw ProcessError("Row index out of bounds in GNEElementTable::getValue");
412 }
413}
414
415/****************************************************************************/
FXDEFMAP(GNEElementTable::Row) RowMap[]
@ MID_GNE_ELEMENTTABLE_EDIT
@ MID_GNE_ELEMENTTABLE_DIALOG_VCLASS
open dialog vClass
@ MID_GNE_ELEMENTTABLE_DIALOG_ELEMENT
open dialog element
@ MID_GNE_ELEMENTTABLE_REMOVE
remove row
#define GUIDesignTextColorRed
red color (for invalid text)
Definition GUIDesigns.h:44
#define GUIDesignLabelFixed(width)
label, icon before text, text centered and custom width
Definition GUIDesigns.h:248
#define GUIDesignButtonIcon
button only with icon
Definition GUIDesigns.h:109
#define GUIDesignTextField
Definition GUIDesigns.h:74
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:430
#define GUIDesignAuxiliarHorizontalFrameUniform
design for auxiliar (Without borders) horizontal frame used to pack another frames uniform
Definition GUIDesigns.h:436
#define GUIDesignBackgroundColorRed
red background color (for invalid text)
Definition GUIDesigns.h:50
#define GUIDesignLabelThick(justify)
label extended over frame with thick and with text justify to left
Definition GUIDesigns.h:251
#define GUIDesignTextColorBlack
black color (for correct text)
Definition GUIDesigns.h:38
#define GUIDesignBackgroundColorWhite
white background color (for valid text)
Definition GUIDesigns.h:47
#define GUIDesignScrollWindowFixedWidth(customWidth)
design for scroll windows extended over Y and fix width
Definition GUIDesigns.h:397
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition GUIDesigns.h:409
#define GUIDesignLabelIconThick
label squared over frame with thick and with text justify to center
Definition GUIDesigns.h:257
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_ALLOW
int GUIDesignHeight
the default height for GUI elements
Definition StdDefs.cpp:37
const GNETagProperties * getTagProperty() const
get tagProperty associated with this Attribute Carrier
GNENet * getNet() const
get pointer to net
virtual std::string getAttribute(SumoXMLAttr key) const =0
Options
FOX-declaration.
int getAttributeIndex(SumoXMLAttr attr) const
get column with the given
const std::vector< SumoXMLAttr > & getSortableAttributes()
get sortable attributes
void disableRowHeader()
disable row header
void enableRowHeader()
enable row header
size_t getNumColumns() const
get num columns
long onCmdEditRow(FXObject *sender, FXSelector, void *)
called when user edits a row
FXButton * myRemoveButton
remove button
long onCmdOpenVClassDialog(FXObject *sender, FXSelector, void *)
called when user press open vClass dialog button
std::vector< std::pair< SumoXMLAttr, MFXTextFieldIcon * > > myAttributeTextFields
list with textfields and their associated attribute
long onCmdOpenElementDialog(FXObject *sender, FXSelector, void *)
called when user press open element dialog button
void enableRow()
enable row
FXButton * myOpenDialogButton
open dialog button
Row(GNEElementTable *elementTable, const size_t rowIndex, GNEAttributeCarrier *AC)
fox declaration
void updateRow(GNEAttributeCarrier *AC)
update row
bool isValid() const
check if current value is valid
FXButton * myOpenVClassButton
open vClass button
FXLabel * myIndexLabel
index label
std::string getValue(const size_t column) const
get value of the given column index
long onCmdRemoveRow(FXObject *sender, FXSelector, void *)
called when user press remove button
void disableRow()
disable row
ColumnHeader * myColumnHeader
column header
GNEElementList * myElementList
pointer to the parent element list
std::string getValue(const size_t rowIndex, const size_t columnIndex) const
get value
GNEElementList::Options myOptions
GNEElementList options.
FXScrollWindow * myScrollWindow
scrollWindow for rows
bool isValid() const
check if the current values of the table are valid
void updateRow(const size_t index, GNEAttributeCarrier *AC)
update row
void disableTable()
Disable table.
std::vector< Row * > myRows
rows
~GNEElementTable()
destructor
FXVerticalFrame * myRowsFrame
vertical frame for rows
void resizeTable(const size_t numRows)
resize table
GNEElementTable(GNEElementList *elementList, const GNETagProperties *tagProperties, GNEElementList::Options options)
constructor
ColumnHeader * getColumnHeader() const
get column header
void enableTable()
Enable table.
GNEViewNet * getViewNet() const
get view net
Definition GNENet.cpp:2193
const std::vector< const GNEAttributeProperties * > & getAttributeProperties() const
get all attribute properties
GNEViewParent * getViewParent() const
get the net object
GNEApplicationWindow * getGNEAppWindows() const
get GNE Application Windows
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
MFXStaticToolTip * getStaticTooltipMenu() const
get static toolTip for menus