Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNEDistributionFrame.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// The Widget for edit distribution elements
19/****************************************************************************/
20
27#include <netedit/GNENet.h>
29#include <netedit/GNEUndoList.h>
33
35
36#define TEMPORAL_FILENAME std::string()
37
38// ===========================================================================
39// FOX callback mapping
40// ===========================================================================
41
47
52
53
57
62
63// Object implementation
64FXIMPLEMENT(GNEDistributionFrame::DistributionEditor, GNEGroupBoxModule, DistributionEditorMap, ARRAYNUMBER(DistributionEditorMap))
65FXIMPLEMENT(GNEDistributionFrame::DistributionSelector, GNEGroupBoxModule, DistributionSelectorMap, ARRAYNUMBER(DistributionSelectorMap))
66FXIMPLEMENT(GNEDistributionFrame::DistributionRow, FXHorizontalFrame, DistributionRowMap, ARRAYNUMBER(DistributionRowMap))
67FXIMPLEMENT(GNEDistributionFrame::DistributionValuesEditor, GNEGroupBoxModule, DistributionValuesEditorMap, ARRAYNUMBER(DistributionValuesEditorMap))
68
69
70// ===========================================================================
71// method definitions
72// ===========================================================================
73
74// ---------------------------------------------------------------------------
75// GNEDistributionFrame::DistributionEditor - methods
76// ---------------------------------------------------------------------------
77
79 GNEGroupBoxModule(frameParent, TL("Distribution Editor")),
80 myFrameParent(frameParent),
81 myDistributionTag(distributionTag) {
82 // get staticTooltip menu
83 auto staticTooltipMenu = myFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();
84 // Create new distribution
85 myCreateDistributionButton = new MFXButtonTooltip(getCollapsableFrame(), staticTooltipMenu, TL("New"),
87 myCreateDistributionButton->setTipText(TLF("Create new %", toString(myDistributionTag)).c_str()),
88 // Delete distribution
89 myDeleteDistributionButton = new MFXButtonTooltip(getCollapsableFrame(), staticTooltipMenu, TL("Delete"),
91 myDeleteDistributionButton->setTipText(TLF("Delete current edited %", toString(myDistributionTag)).c_str()),
92 // show editor
93 show();
94}
95
96
98
99
102 return myDistributionTag;
103}
104
105
106long
108 auto undoList = myFrameParent->getViewNet()->getUndoList();
109 // obtain a new valid ID
110 const auto distributionID = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->generateDemandElementID(myDistributionTag);
111 // get bucket
112 auto bucket = myFrameParent->getViewNet()->getNet()->getACTemplates()->getTemplateAC(myDistributionTag)->getFileBucket();
113 // create new distribution
114 GNEDemandElement* distribution = nullptr;
115 if (myDistributionTag == SUMO_TAG_VTYPE_DISTRIBUTION) {
116 distribution = new GNEVTypeDistribution(distributionID, myFrameParent->getViewNet()->getNet(), bucket, -1);
117 } else if (myDistributionTag == SUMO_TAG_ROUTE_DISTRIBUTION) {
118 distribution = new GNERouteDistribution(distributionID, myFrameParent->getViewNet()->getNet(), bucket);
119 } else {
120 throw ProcessError("Invalid distribution");
121 }
122 // add it using undoList (to allow undo-redo)
123 undoList->begin(distribution->getTagProperty()->getGUIIcon(), "create distribution");
124 undoList->add(new GNEChange_DemandElement(distribution, true), true);
125 undoList->end();
126 // refresh selector using created distribution
127 myDistributionSelector->setDistribution(distribution);
128 return 1;
129}
130
131
132long
134 auto undoList = myFrameParent->getViewNet()->getUndoList();
135 auto currentDistribution = myDistributionSelector->getCurrentDistribution();
136 if (currentDistribution) {
137 // begin undo list operation
138 undoList->begin(currentDistribution->getTagProperty()->getGUIIcon(), "delete " + currentDistribution->getTagProperty()->getTagStr() + " distribution");
139 // remove distribution
140 myFrameParent->getViewNet()->getNet()->deleteDemandElement(myDistributionSelector->getCurrentDistribution(), undoList);
141 // end undo list operation
142 undoList->end();
143 // refresh selector
144 myDistributionSelector->refreshDistributionSelector();
145 }
146 return 1;
147}
148
149
150long
152 // check if we have a selected distribution
153 if (myDistributionSelector->getCurrentDistribution()) {
154 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
155 } else {
156 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
157 }
158}
159
160// ---------------------------------------------------------------------------
161// GNETypeFrame::DistributionSelector - methods
162// ---------------------------------------------------------------------------
163
165 GNEGroupBoxModule(frameParent, TL("Distribution selector")),
166 myFrameParent(frameParent) {
167 // Create MFXComboBoxIcon
170 // DistributionSelector is always shown
171 show();
172}
173
174
176
177
178void
180 myCurrentDistribution = distribution;
181 refreshDistributionSelector();
182}
183
184
187 return myCurrentDistribution;
188
189}
190
191
192void
194 // fill distributions
195 fillDistributionComboBox();
196 // set current item
197 for (int i = 0; i < (int)myDistributionsComboBox->getNumItems(); i++) {
198 if (myDistributionsComboBox->getItemText(i) == myCurrentDistribution->getID()) {
199 myDistributionsComboBox->setCurrentItem(i);
200 }
201 }
202}
203
204
205void
207 // fill distributions
208 const auto distributions = fillDistributionComboBox();
209 // update current distribution (used if myCurrentDistribution was deleted during undo-redo)
210 myCurrentDistribution = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->retrieveDemandElement(myCurrentDistribution, false);
211 // update comboBox
212 if (myCurrentDistribution) {
213 for (int i = 0; i < (int)myDistributionsComboBox->getNumItems(); i++) {
214 if (myDistributionsComboBox->getItemText(i) == myCurrentDistribution->getID()) {
215 myDistributionsComboBox->setCurrentItem(i);
216 }
217 }
218 } else if (distributions.size() > 0) {
219 // set first distribution
220 myCurrentDistribution = distributions.begin()->second;
221 }
222 // continue depending of myCurrentDistribution
223 if (myCurrentDistribution) {
224 // show modules
225 myAttributesEditor->showAttributesEditor(myCurrentDistribution, true);
226 myDistributionValuesEditor->showDistributionValuesEditor();
227 } else {
228 // hide modules
229 myAttributesEditor->hideAttributesEditor();
230 myDistributionValuesEditor->hideDistributionValuesEditor();
231 }
232}
233
234
235long
237 const auto viewNet = myFrameParent->getViewNet();
238 const auto& distributions = viewNet->getNet()->getAttributeCarriers()->getDemandElements().at(myDistributionEditor->getDistributionTag());
239 // Check if value of myTypeMatchBox correspond of an allowed additional tags
240 for (const auto& distribution : distributions) {
241 if (distribution.second->getID() == myDistributionsComboBox->getText().text()) {
242 // set pointer
243 myCurrentDistribution = distribution.second;
244 // set color of myTypeMatchBox to black (valid)
245 myDistributionsComboBox->setTextColor(GUIDesignTextColorBlack);
246 // show modules
247 myAttributesEditor->showAttributesEditor(distribution.second, true);
248 myDistributionValuesEditor->showDistributionValuesEditor();
249 // update viewNet
250 viewNet->updateViewNet();
251 return 1;
252 }
253 }
254 // not found, then reset myCurrentDistribution
255 myCurrentDistribution = nullptr;
256 // hide modules
257 myAttributesEditor->hideAttributesEditor();
258 myDistributionValuesEditor->hideDistributionValuesEditor();
259 // set color of myTypeMatchBox to red (invalid)
260 myDistributionsComboBox->setTextColor(GUIDesignTextColorRed);
261 // update viewNet
262 viewNet->updateViewNet();
263 return 1;
264}
265
266
267long
269 const auto& demandElements = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getDemandElements();
270 if (demandElements.at(myDistributionEditor->getDistributionTag()).size() > 0) {
271 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
272 } else {
273 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
274 }
275}
276
277
278std::map<std::string, GNEDemandElement*>
280 // get ACs
281 const auto& ACs = myFrameParent->getViewNet()->getNet()->getAttributeCarriers();
282 // clear items
283 myDistributionsComboBox->clearItems();
284 // fill with distributions sorted by ID
285 std::map<std::string, GNEDemandElement*> distributions;
286 for (const auto& distribution : ACs->getDemandElements().at(myDistributionEditor->getDistributionTag())) {
287 distributions[distribution.second->getID()] = distribution.second;
288 }
289 for (const auto& distribution : distributions) {
290 myDistributionsComboBox->appendIconItem(distribution.first.c_str(), distribution.second->getACIcon());
291 }
292 // return distributions sorted by ID
293 return distributions;
294}
295
296// ---------------------------------------------------------------------------
297// GNEDistributionFrame::DistributionRow - methods
298// ---------------------------------------------------------------------------
299
301 FXHorizontalFrame(attributeEditorParent->getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame),
302 myDistributionValuesEditorParent(attributeEditorParent),
303 myDistributionReference(distributionReference) {
304 // get staticTooltip menu
305 auto staticTooltipMenu = attributeEditorParent->getFrameParent()->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();
306 // create label
308 // Create and disable MFXTextFieldIcon for string attributes
311 // Create MFXTextFieldIcon for string attributes
313 GUIDesignTextFieldRestricted(TEXTFIELD_REAL));
314 // create delete buton
317 myDeleteRowButton->setTipText(TL("Delete distribution value"));
318 // only create if parent was created
319 if (getParent()->id() && attributeEditorParent->myDistributionSelector->getCurrentDistribution()) {
320 // create DistributionRow
321 FXHorizontalFrame::create();
322 // set values
325 // set color depending if attribute is computed
328 } else {
330 }
331 // Show DistributionRow
332 show();
333 }
334}
335
336
337void
339 // only destroy if parent was created
340 if (getParent()->id()) {
341 FXHorizontalFrame::destroy();
342 }
343}
344
345
348 return myDistributionReference;
349}
350
351
354 return myDeleteRowButton;
355}
356
357
358long
360 // set default value if value is empty
361 if (myProbabilityTextField->getText().empty()) {
362 myProbabilityTextField->setText(myDistributionReference->getTagProperty()->getAttributeProperties(SUMO_ATTR_PROB)->getDefaultStringValue().c_str());
363 }
364 // if is valid, update value in AC
365 if (myDistributionReference->isValid(SUMO_ATTR_PROB, myProbabilityTextField->getText().text())) {
366 myDistributionReference->setAttribute(SUMO_ATTR_PROB, myProbabilityTextField->getText().text(), myDistributionReference->getNet()->getUndoList());
367 myDistributionValuesEditorParent->updateSumLabel();
368 // update probablity text field (needed for show the default value)
369 myProbabilityTextField->setText(myDistributionReference->getAttribute(SUMO_ATTR_PROB).c_str(), FALSE);
370 // set color depending if attribute is computed
371 if (myDistributionReference->isAttributeComputed(SUMO_ATTR_PROB)) {
372 myProbabilityTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLUE));
373 } else {
374 myProbabilityTextField->setTextColor(MFXUtils::getFXColor(RGBColor::BLACK));
375 }
376 myProbabilityTextField->killFocus();
377 } else {
378 myProbabilityTextField->setTextColor(MFXUtils::getFXColor(RGBColor::RED));
379 }
380 return 1;
381}
382
383// ---------------------------------------------------------------------------
384// GNEDistributionFrame::DistributionValuesEditor - methods
385// ---------------------------------------------------------------------------
386
388 DistributionSelector* distributionSelector, GNEAttributesEditor* attributesEditor) :
389 GNEGroupBoxModule(frameParent, TL("Distribution values")),
390 myFrameParent(frameParent),
391 myDistributionEditor(distributionEditor),
392 myDistributionSelector(distributionSelector),
393 myAttributesEditor(attributesEditor) {
394 // set relations
399 // get staticTooltip menu
400 auto staticTooltipMenu = frameParent->getViewNet()->getViewParent()->getGNEAppWindows()->getStaticTooltipMenu();
401 // Create bot frame elements
404 myAddButton->setTipText(TL("Add new distribution value"));
405 new FXHorizontalFrame(myBotFrame, GUIDesignAuxiliarHorizontalFrame);
407 mySumLabel = new FXLabel(myBotFrame, "", nullptr, GUIDesignLabelThickedFixed(50));
409}
410
411
412void
414 // remake rows
415 refreshRows();
416 // show DistributionValuesEditor
417 show();
418}
419
420
421void
423 // hide also DistributionValuesEditor
424 hide();
425}
426
427
428void
430 // first remove all rows
431 for (auto& row : myDistributionRows) {
432 // destroy and delete all rows
433 if (row != nullptr) {
434 row->destroy();
435 delete row;
436 row = nullptr;
437 }
438 }
439 myDistributionRows.clear();
440 // continue if we have a distribution to edit
441 if (myDistributionSelector->getCurrentDistribution()) {
442 // Iterate over distribution key-values
443 for (const auto& distributionRef : myDistributionSelector->getCurrentDistribution()->getChildDemandElements()) {
444 if (distributionRef->getTagProperty()->isDistributionReference()) {
445 if (distributionRef->getTagProperty()->isDistributionReference() && (distributionRef->getParentDemandElements().front() == myDistributionSelector->getCurrentDistribution())) {
446 // create distribution row
447 auto distributionRow = new DistributionRow(this, distributionRef);
448 // add into distribution rows
449 myDistributionRows.push_back(distributionRow);
450 }
451 } else {
452 // update geometry of vehicle
453 distributionRef->updateGeometry();
454 }
455 }
456 }
457 // check if enable or disable add button
458 if (myDistributionRows.size() > 0) {
459 myAddButton->enable();
460 } else {
461 myAddButton->disable();
462 }
463 // update sum label
464 updateSumLabel();
465 // reparent bot frame button (to place it at bottom)
466 myBotFrame->reparent(getCollapsableFrame());
467}
468
469
474
475
476long
478 // open distribution dialog
479 GNEDistributionRefDialog distributionDialog(myDistributionSelector->getCurrentDistribution());
480 // only refresh if we added a new row
481 if (distributionDialog.getResult() == GNEDialog::Result::ACCEPT) {
482 refreshRows();
483 }
484 return 1;
485}
486
487
488long
490 for (const auto& row : myDistributionRows) {
491 if (row->getDeleteRowButton() == obj) {
492 myFrameParent->getViewNet()->getNet()->deleteDemandElement(row->getDistributionReference(), myFrameParent->getViewNet()->getUndoList());
493 return 1;
494 }
495 }
496 return 1;
497}
498
499
500void
502 // update probability
503 double sumProbability = 0;
504 if (myDistributionSelector->getCurrentDistribution()) {
505 for (const auto& distributionRef : myDistributionSelector->getCurrentDistribution()->getChildDemandElements()) {
506 if (distributionRef->getTagProperty()->isDistributionReference()) {
507 sumProbability += distributionRef->getAttributeDouble(SUMO_ATTR_PROB);
508 }
509 }
510 // vType distributions
511 if (myDistributionSelector->getCurrentDistribution()->getTagProperty()->getTag() == SUMO_TAG_VTYPE_DISTRIBUTION) {
512 const auto& vTypes = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getDemandElements().at(SUMO_TAG_VTYPE);
513 if (vTypes.size() == myDistributionRows.size()) {
514 myAddButton->disable();
515 } else {
516 myAddButton->enable();
517 }
518 }
519 // route distribution
520 if (myDistributionSelector->getCurrentDistribution()->getTagProperty()->getTag() == SUMO_TAG_ROUTE_DISTRIBUTION) {
521 const auto& routes = myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getDemandElements().at(SUMO_TAG_ROUTE);
522 if (routes.size() == myDistributionRows.size()) {
523 myAddButton->disable();
524 } else {
525 myAddButton->enable();
526 }
527 }
528 } else {
529 myAddButton->disable();
530 }
531 mySumLabel->setText(toString(sumProbability).c_str());
532}
533
534/****************************************************************************/
FXDEFMAP(GNEDistributionFrame::DistributionEditor) DistributionEditorMap[]
@ MID_GNE_DELETE
delete element
@ MID_GNE_SET_ATTRIBUTE
attribute edited
@ MID_GNE_BUTTON_REMOVE
remove button
@ MID_GNE_BUTTON_ADD
add button
@ MID_GNE_CREATE
create element
@ MID_GNE_SET_TYPE
used to select a type of element in a combo box
#define GUIDesignTextFieldFixed(width)
text field with fixed width
Definition GUIDesigns.h:80
#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 GUIDesignButton
Definition GUIDesigns.h:100
#define GUIDesignComboBox
Definition GUIDesigns.h:295
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:430
#define GUIDesignComboBoxVisibleItems
Definition GUIDesigns.h:64
#define GUIDesignTextColorBlack
black color (for correct text)
Definition GUIDesigns.h:38
#define GUIDesignTextFieldRestricted(type)
text field extended over Frame with thick frame (int)
Definition GUIDesigns.h:77
#define GUIDesignLabelThickedFixed(width)
label thicked, icon before text, text centered and custom width
Definition GUIDesigns.h:254
#define GUIDesignLabelIconThick
label squared over frame with thick and with text justify to center
Definition GUIDesigns.h:257
GUIIcon
An enumeration of icons used by the gui applications.
Definition GUIIcons.h:33
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_VTYPE
description of a vehicle/person/container type
@ SUMO_TAG_ROUTE_DISTRIBUTION
distribution of a route
@ SUMO_TAG_ROUTE
description of a route
@ SUMO_TAG_VTYPE_DISTRIBUTION
distribution of a vehicle type
@ SUMO_ATTR_REFID
@ SUMO_ATTR_PROB
int GUIDesignHeight
the default height for GUI elements
Definition StdDefs.cpp:40
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
FXIcon * getACIcon() const
get FXIcon associated to this AC
virtual bool isAttributeComputed(SumoXMLAttr key) const
const GNETagProperties * getTagProperty() const
get tagProperty associated with this Attribute Carrier
virtual std::string getAttribute(SumoXMLAttr key) const =0
Result getResult() const
get result to indicate if this dialog was closed accepting or rejecting changes
long onCmdDeleteDistribution(FXObject *, FXSelector, void *)
Called when "Delete distribution" button is clicked.
SumoXMLTag getDistributionTag() const
get distribution tag
long onUpdDeleteDistribution(FXObject *sender, FXSelector, void *)
Called when "Delete distribution" button is updated.
long onCmdCreateDistribution(FXObject *, FXSelector, void *)
Called when "create distribution" button is clicked.
DistributionSelector * myDistributionSelector
distribution selector
void destroy()
destroy DistributionRow (but don't delete)
GNEDemandElement * getDistributionReference() const
get pointer to distributionReference
MFXTextFieldIcon * myProbabilityTextField
textField to modify the probability attribute
GNEDemandElement * myDistributionReference
pointer to distributionReference
long onCmdSetProbability(FXObject *, FXSelector, void *)
try to set new probability
DistributionRow(DistributionValuesEditor *attributeEditorParent, GNEDemandElement *distributionReference)
FOX-declaration.
MFXButtonTooltip * getDeleteRowButton() const
get delete row button
MFXTextFieldIcon * myIDTextField
comboBox with ID
DistributionValuesEditor * myDistributionValuesEditorParent
FOX need this.
MFXButtonTooltip * myDeleteRowButton
delete row button
GNEDemandElement * getCurrentDistribution() const
current distribution
DistributionValuesEditor * myDistributionValuesEditor
distribution values editor
std::map< std::string, GNEDemandElement * > fillDistributionComboBox()
FOX need this.
long onCmdSelectDistribution(FXObject *, FXSelector, void *)
Called when the user select distribution in ComboBox.
void refreshDistributionIDs()
refresh distribution IDs (only call when user change ID in internal attributes)
MFXComboBoxIcon * myDistributionsComboBox
comboBox with the list of distributions
DistributionEditor * myDistributionEditor
pointer to distribution editor
GNEAttributesEditor * myAttributesEditor
attributes editor
long onCmdUpdateDistribution(FXObject *sender, FXSelector, void *)
update distribution comboBox
void setDistribution(GNEDemandElement *distribution)
refresh modul
DistributionSelector(GNEFrame *frameParent)
constructor
GNEAttributesEditor * myAttributesEditor
attributes editor
DistributionValuesEditor(GNEFrame *frameParent, DistributionEditor *distributionEditor, DistributionSelector *distributionSelector, GNEAttributesEditor *attributesEditor)
constructor
GNEFrame * getFrameParent() const
pointer to GNEFrame parent
DistributionEditor * myDistributionEditor
distribution editor
long onCmdRemoveRow(FXObject *obj, FXSelector, void *)
Called when user press the add button.
long onCmdAddRow(FXObject *, FXSelector, void *)
Called when user press the add button.
DistributionSelector * myDistributionSelector
distribution selector
void showDistributionValuesEditor()
show attributes of multiple ACs
GNEViewNet * getViewNet() const
get view net
Definition GNEFrame.cpp:145
GNEGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
GUIIcon getGUIIcon() const
get GUI icon associated to this tag property
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
virtual void disable()
Disable text field.
void setTextColor(FXColor clr)
Change text color.
void setText(const FXString &text, FXbool notify=FALSE)
Change the text and move cursor to end.
static FXColor getFXColor(const RGBColor &col)
converts FXColor to RGBColor
Definition MFXUtils.cpp:145
static const RGBColor BLUE
Definition RGBColor.h:190
static const RGBColor BLACK
Definition RGBColor.h:196
static const RGBColor RED
named colors
Definition RGBColor.h:188