Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
GNEPythonToolDialog.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// Dialog for tools
19/****************************************************************************/
20
22#include <netedit/GNEViewNet.h>
27
28#include "GNEPythonToolDialog.h"
29
30// ===========================================================================
31// Defines
32// ===========================================================================
33
34#define MARGIN 4
35#define MAXNUMCOLUMNS 4
36#define NUMROWSBYCOLUMN 20
37
38// ===========================================================================
39// FOX callback mapping
40// ===========================================================================
41
54
55// Object implementation
56FXIMPLEMENT(GNEPythonToolDialog, FXDialogBox, GNEPythonToolDialogMap, ARRAYNUMBER(GNEPythonToolDialogMap))
57
58// ============================================-===============================
59// member method definitions
60// ===========================================================================
61
63 FXDialogBox(GNEApp->getApp(), "Tool", GUIDesignAuxiliarDialogBoxResizable),
64 myGNEApp(GNEApp) {
65 // set icon
67 // create main content frame
68 auto verticalContentFrame = new FXVerticalFrame(this, GUIDesignContentsFrame);
69 // create options
70 auto horizontalOptionsFrame = new FXHorizontalFrame(verticalContentFrame, GUIDesignHorizontalFrameNoPadding);
71 // build options
72 myShowToolTipsMenu = new MFXCheckableButton(false, horizontalOptionsFrame,
73 GNEApp->getStaticTooltipMenu(), (std::string("\t") + TL("Toggle Menu Tooltips") + std::string("\t") + TL("Toggles whether tooltips in the menu shall be shown.")).c_str(),
75 auto saveFile = new MFXButtonTooltip(horizontalOptionsFrame, GNEApp->getStaticTooltipMenu(), TL("Save toolcfg"),
77 saveFile->setTipText(TL("Save file with tool configuration"));
78 auto loadFile = new MFXButtonTooltip(horizontalOptionsFrame, GNEApp->getStaticTooltipMenu(), TL("Load toolcfg"),
80 loadFile->setTipText(TL("Load file with tool configuration"));
81 mySortedCheckButton = new FXCheckButton(horizontalOptionsFrame, TL("Sorted by name"), this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
82 myGroupedCheckButton = new FXCheckButton(horizontalOptionsFrame, TL("Grouped by categories"), this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
83 // add separators
84 new FXSeparator(verticalContentFrame);
85 // Create scroll frame for content rows
86 auto contentScrollWindow = new FXScrollWindow(verticalContentFrame, GUIDesignScrollWindow);
87 auto horizontalRowFrames = new FXHorizontalFrame(contentScrollWindow, LAYOUT_FILL_X | LAYOUT_FILL_Y | PACK_UNIFORM_WIDTH);
88 myArgumentFrameLeft = new FXVerticalFrame(horizontalRowFrames, GUIDesignAuxiliarFrame);
89 myArgumentFrameRight = new FXVerticalFrame(horizontalRowFrames, GUIDesignAuxiliarFrame);
90 // add separator
91 new FXSeparator(verticalContentFrame);
92 // create buttons centered
93 auto horizontalButtonsFrame = new FXHorizontalFrame(verticalContentFrame, GUIDesignHorizontalFrame);
94 auto blueLabel = new FXLabel(horizontalButtonsFrame, TL("Blue options are mandatory"), nullptr, GUIDesignLabelFixed(200));
95 blueLabel->setTextColor(FXRGB(0, 0, 255));
96 new FXHorizontalFrame(horizontalButtonsFrame, GUIDesignAuxiliarHorizontalFrame);
97 GUIDesigns::buildFXButton(horizontalButtonsFrame, TL("Run"), "", TL("run python tool"),
99 GUIDesigns::buildFXButton(horizontalButtonsFrame, TL("Close"), "", TL("close tool dialog"),
101 GUIDesigns::buildFXButton(horizontalButtonsFrame, TL("Reset"), "", TL("reset to default values"),
103 new FXLabel(horizontalButtonsFrame, "", nullptr, GUIDesignLabelFixed(200));
104 new FXHorizontalFrame(horizontalButtonsFrame, GUIDesignAuxiliarHorizontalFrame);
105}
106
107
109
110
111void
113 // set tool
114 myPythonTool = tool;
115 // set title
116 setTitle(myPythonTool->getToolName().c_str());
117 // reset checkboxes
118 mySortedCheckButton->setCheck(FALSE);
119 myGroupedCheckButton->setCheck(TRUE);
120 // set myShowToolTipsMenu
121 myShowToolTipsMenu->setChecked(getApp()->reg().readIntEntry("gui", "menuToolTips", 0) != 1);
122 // set current values in options (like current folders and similar)
124 // build arguments
125 buildArguments(false, true);
126 // get maximum height
127 const int maximumHeight = myArgumentFrameLeft->numChildren() * GUIDesignHeight + 120;
128 // resize
129 resize(1024, maximumHeight <= 768 ? maximumHeight : 768);
130 // show dialog
131 FXDialogBox::show(PLACEMENT_SCREEN);
132 // refresh APP
133 getApp()->refresh();
134}
135
136
141
142
143const GNEPythonTool*
147
148
149long
150GNEPythonToolDialog::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
151 // toggle check
153 if (myGNEApp->getViewNet()) {
156 }
157 // enable/disable static tooltip
159 // save in registry
160 getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
161 update();
162
163 return 1;
164}
165
166
167long
168GNEPythonToolDialog::onCmdSave(FXObject*, FXSelector, void*) {
169 // open save dialog
170 const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, true);
171 // check file
172 if (file.size() > 0) {
174 }
175 return 1;
176}
177
178
179long
180GNEPythonToolDialog::onCmdLoad(FXObject*, FXSelector, void*) {
181 // open file dialog
182 const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, false);
183 // check file
184 if ((file.size() > 0) && myPythonTool->loadConfiguration(file)) {
185 // rebuild arguments
186 buildArguments((mySortedCheckButton->getCheck() == TRUE), (myGroupedCheckButton->getCheck() == TRUE));
187 }
188 return 1;
189}
190
191
192long
193GNEPythonToolDialog::onCmdSetVisualization(FXObject*, FXSelector, void*) {
194 // rebuild arguments
195 buildArguments((mySortedCheckButton->getCheck() == TRUE), (myGroupedCheckButton->getCheck() == TRUE));
196 return 1;
197}
198
199
200long
201GNEPythonToolDialog::onCmdRun(FXObject*, FXSelector, void*) {
202 // hide dialog
203 hide();
204 // run tool
205 return myGNEApp->tryHandle(myPythonTool->getMenuCommand(), FXSEL(SEL_COMMAND, MID_GNE_RUNPYTHONTOOL), nullptr);
206}
207
208
209long
210GNEPythonToolDialog::onCmdCancel(FXObject*, FXSelector, void*) {
211 // hide dialog
212 hide();
213 return 1;
214}
215
216
217long
218GNEPythonToolDialog::onCmdReset(FXObject*, FXSelector, void*) {
219 // iterate over all arguments and reset values
220 for (const auto& argument : myArguments) {
221 argument->reset();
222 }
223 return 1;
224}
225
226
227long
228GNEPythonToolDialog::onUpdRequiredAttributes(FXObject* sender, FXSelector, void*) {
229 // iterate over all arguments and check if required attribute is set
230 for (const auto& argument : myArguments) {
231 if (argument->requiredAttributeSet() == false) {
232 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
233 }
234 }
235 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
236}
237
238
240 std::string(category) {
241}
242
243
244void
246 myOptions.push_back(std::make_pair(name, option));
247}
248
249
250const std::vector<std::pair<std::string, Option*> >&
252 return myOptions;
253}
254
255
256void
258 // just sort vector with options
259 std::sort(myOptions.begin(), myOptions.end());
260}
261
262
266
267
268void
269GNEPythonToolDialog::buildArguments(bool sortByName, bool groupedByCategories) {
270 // clear arguments and categories
271 for (const auto& argument : myArguments) {
272 delete argument;
273 }
274 for (const auto& category : myCategories) {
275 delete category;
276 }
277 myArguments.clear();
278 myCategories.clear();
279 // get argument sorted by name and grouped by categories
280 auto categoryOptions = groupedByCategories ? getOptionsByCategories(myPythonTool->getToolsOptions()) : getOptions(myPythonTool->getToolsOptions());
281 // calculate number of arguments
282 int numArguments = 0;
283 for (auto& categoryOption : categoryOptions) {
284 numArguments += (int)categoryOption.getOptions().size() + 1;
285 }
286 const int halfNumArguments = numArguments / 2;
287 // declare counter for number of inserted arguments
288 int numInsertedArguments = 0;
289 // iterate over category options
290 for (auto& categoryOption : categoryOptions) {
291 // get argument frame
292 auto argumentFrame = (numInsertedArguments < halfNumArguments) ? myArgumentFrameLeft : myArgumentFrameRight;
293 // add category
294 if (categoryOption.size() > 0) {
295 myCategories.push_back(new GNEPythonToolDialogElements::Category(argumentFrame, categoryOption));
296 numInsertedArguments++;
297 }
298 // check if sort by name
299 if (sortByName) {
300 categoryOption.sortByName();
301 }
302 // add options
303 for (const auto& option : categoryOption.getOptions()) {
304 // get argument frame (again)
305 argumentFrame = (numInsertedArguments < halfNumArguments) ? myArgumentFrameLeft : myArgumentFrameRight;
306 // continue depending of type
307 if (option.second->isInteger()) {
308 myArguments.push_back(new GNEPythonToolDialogElements::IntArgument(this, argumentFrame, option.first, option.second));
309 } else if (option.second->isFloat()) {
310 myArguments.push_back(new GNEPythonToolDialogElements::FloatArgument(this, argumentFrame, option.first, option.second));
311 } else if (option.second->isBool()) {
312 myArguments.push_back(new GNEPythonToolDialogElements::BoolArgument(this, argumentFrame, option.first, option.second));
313 } else if (option.second->isFileName()) {
314 myArguments.push_back(new GNEPythonToolDialogElements::FileNameArgument(this, argumentFrame, option.first, option.second));
315 } else if (option.second->isNetwork()) {
316 myArguments.push_back(new GNEPythonToolDialogElements::NetworkArgument(this, argumentFrame, option.first, option.second));
317 } else if (option.second->isAdditional()) {
318 myArguments.push_back(new GNEPythonToolDialogElements::AdditionalArgument(this, argumentFrame, option.first, option.second));
319 } else if (option.second->isRoute()) {
320 myArguments.push_back(new GNEPythonToolDialogElements::RouteArgument(this, argumentFrame, option.first, option.second));
321 } else if (option.second->isData()) {
322 myArguments.push_back(new GNEPythonToolDialogElements::DataArgument(this, argumentFrame, option.first, option.second));
323 } else if (option.second->isSumoConfig()) {
324 myArguments.push_back(new GNEPythonToolDialogElements::SumoConfigArgument(this, argumentFrame, option.first, option.second));
325 } else if (option.second->isEdge()) {
326 myArguments.push_back(new GNEPythonToolDialogElements::EdgeArgument(this, argumentFrame, option.first, option.second));
327 } else if (option.second->isEdgeVector()) {
328 myArguments.push_back(new GNEPythonToolDialogElements::EdgeVectorArgument(this, argumentFrame, option.first, option.second));
329 } else {
330 myArguments.push_back(new GNEPythonToolDialogElements::StringArgument(this, argumentFrame, option.first, option.second));
331 }
332 numInsertedArguments++;
333 }
334 }
335 // adjust parameter column (call always after create elements)
337}
338
339
340void
342 int maximumWidth = 0;
343 // iterate over all arguments and find the maximum width
344 for (const auto& argument : myArguments) {
345 const auto label = argument->getParameterLabel();
346 const int columnWidth = label->getFont()->getTextWidth(label->getText().text(), label->getText().length() + MARGIN);
347 if (columnWidth > maximumWidth) {
348 maximumWidth = columnWidth;
349 }
350 }
351 // set maximum width for all parameter labels
352 for (const auto& argument : myArguments) {
353 argument->getParameterLabel()->setWidth(maximumWidth);
354 }
355}
356
357
358std::vector<GNEPythonToolDialog::CategoryOptions>
360 // use a vector with only one empty category to reuse code of buildArguments
361 std::vector<GNEPythonToolDialog::CategoryOptions> result = {GNEPythonToolDialog::CategoryOptions("")};
362 // add all options to result
363 for (const auto& option : optionsCont) {
364 result.front().addOption(option.first, option.second);
365 }
366 return result;
367}
368
369
370std::vector<GNEPythonToolDialog::CategoryOptions>
372 // declare vector with common categories
373 const std::vector<std::string> commonCategories = {"input", "output", "processing", "time"};
374 // fill categories
375 std::vector<std::string> categories = commonCategories;
376 for (const auto& option : optionsCont) {
377 if (std::find(categories.begin(), categories.end(), option.second->getSubTopic()) == categories.end()) {
378 categories.push_back(option.second->getSubTopic());
379 }
380 }
381 // declare vector of category options and fill
382 std::vector<GNEPythonToolDialog::CategoryOptions> result;
383 for (const auto& category : categories) {
384 result.push_back(GNEPythonToolDialog::CategoryOptions(category));
385 }
386 // fill result with options
387 for (const auto& option : optionsCont) {
388 auto category = std::find(result.begin(), result.end(), option.second->getSubTopic());
389 // add option in category
390 category->addOption(option.first, option.second);
391 }
392 // drop empty categories
393 auto it = result.begin();
394 while (it != result.end()) {
395 if (it->getOptions().empty()) {
396 it = result.erase(it);
397 } else {
398 it++;
399 }
400 }
401 return result;
402}
403
404
405int
407 const int column = (int)myArguments.size() / NUMROWSBYCOLUMN;
408 return (column < MAXNUMCOLUMNS) ? column : (MAXNUMCOLUMNS - 1);
409}
410
411
412FXVerticalFrame*
416
417
418FXVerticalFrame*
422
423/****************************************************************************/
#define MAXNUMCOLUMNS
#define NUMROWSBYCOLUMN
#define MARGIN
FXDEFMAP(GNEPythonToolDialog) GNEPythonToolDialogMap[]
@ MID_GNE_SET_ATTRIBUTE
attribute edited
Definition GUIAppEnum.h:939
@ MID_GNE_BUTTON_RUN
run button
@ MID_CHOOSEN_SAVE
Save set.
Definition GUIAppEnum.h:603
@ MID_GNE_BUTTON_CANCEL
cancel button
@ MID_GNE_BUTTON_RESET
reset button
@ MID_GNE_RUNPYTHONTOOL
run python
Definition GUIAppEnum.h:757
@ MID_SHOWTOOLTIPS_MENU
Show tool tips in menus - button.
Definition GUIAppEnum.h:387
@ MID_CHOOSEN_LOAD
Load set.
Definition GUIAppEnum.h:601
#define GUIDesignScrollWindow
design for scroll windows extended over Y and y
Definition GUIDesigns.h:375
#define GUIDesignLabelFixed(width)
label, icon before text, text centered and custom width
Definition GUIDesigns.h:246
#define GUIDesignButtonAccept
Accept Button.
Definition GUIDesigns.h:156
#define GUIDesignButtonCancel
Cancel Button.
Definition GUIDesigns.h:162
#define GUIDesignContentsFrame
design for the main content frame of every frame/dialog with padding and spacing
Definition GUIDesigns.h:387
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:399
#define GUIDesignButtonConfiguration
Configuration Button.
Definition GUIDesigns.h:159
#define GUIDesignMFXCheckableButtonSquare
Definition GUIDesigns.h:137
#define GUIDesignAuxiliarDialogBoxResizable
design for standard dialog box (for example, about dialog)
Definition GUIDesigns.h:611
#define GUIDesignCheckButton
checkButton placed in left position
Definition GUIDesigns.h:192
#define GUIDesignButtonReset
Reset Button.
Definition GUIDesigns.h:165
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition GUIDesigns.h:390
#define GUIDesignHorizontalFrameNoPadding
Horizontal frame extended over frame parent without padding and spacing.
Definition GUIDesigns.h:331
#define GUIDesignHorizontalFrame
Horizontal frame extended over frame parent with padding and spacing.
Definition GUIDesigns.h:328
@ SHOWTOOLTIPS_MENU
@ OPEN
open icons
@ SAVE
save icons
#define TL(string)
Definition MsgHandler.h:305
int GUIDesignHeight
the default size for GUI elements
Definition StdDefs.cpp:35
The main window of Netedit.
GNEViewNet * getViewNet()
get pointer to viewNet
internal class used for sorting options by categories
void addOption(const std::string &name, Option *option)
add option
const std::vector< std::pair< std::string, Option * > > & getOptions() const
get options
Dialog for python tool dialog.
std::vector< CategoryOptions > getOptionsByCategories(OptionsCont &optionsCont) const
get options sorted by category
FXVerticalFrame * myArgumentFrameRight
argument frame right
long onCmdCancel(FXObject *, FXSelector, void *)
event after press cancel button
GNEPythonTool * myPythonTool
python tool
void adjustParameterColumn()
adjust parameter column
int getNumRowColums() const
get number of row colums
GNEPythonToolDialog()
FOX needs this.
long onCmdLoad(FXObject *, FXSelector, void *)
load options
std::vector< GNEPythonToolDialogElements::Argument * > myArguments
list of arguments sorted by categories
GNEApplicationWindow * myGNEApp
pointer to GNEApplicationWindow
std::vector< GNEPythonToolDialogElements::Category * > myCategories
list of categories
long onCmdShowToolTipsMenu(FXObject *, FXSelector, void *)
enable/disable show toolTip
GNEApplicationWindow * getGNEApplicationWindow() const
get pointer to GNEApplicationWindow
long onCmdRun(FXObject *, FXSelector, void *)
event after press run button
MFXCheckableButton * myShowToolTipsMenu
menu for tooltips menu
std::vector< GNEPythonToolDialog::CategoryOptions > getOptions(OptionsCont &optionsCont) const
get options
FXVerticalFrame * getArgumentFrameLeft() const
get argument frame left
long onUpdRequiredAttributes(FXObject *sender, FXSelector, void *)
event for check if required attributes was set
FXCheckButton * mySortedCheckButton
check button to enable/diasble sorting
long onCmdSetVisualization(FXObject *, FXSelector, void *)
set visualization (sorting and grouping)
FXVerticalFrame * getArgumentFrameRight() const
get argument frame right
long onCmdReset(FXObject *, FXSelector, void *)
event after press reset button
FXVerticalFrame * myArgumentFrameLeft
argument frame left
const GNEPythonTool * getPythonTool() const
get python tool
long onCmdSave(FXObject *, FXSelector, void *)
save options
void buildArguments(bool sortByName, bool groupedByCategories)
build arguments
FXCheckButton * myGroupedCheckButton
check button to enable/diasble grouping
void openDialog(GNEPythonTool *tool)
open dialog
void saveConfiguration(const std::string &file) const
save configuration
bool loadConfiguration(const std::string &file)
load configuration
virtual void setCurrentValues()
set current values (used for set values like current folder and similar)
const std::string & getToolName() const
get tool name
FXMenuCommand * getMenuCommand() const
get menu command
OptionsCont & getToolsOptions()
get tools options
GNEViewParent * getViewParent() const
get the net object
static FXButton * buildFXButton(FXComposite *p, const std::string &text, const std::string &tip, const std::string &help, FXIcon *ic, FXObject *tgt, FXSelector sel, FXuint opts=BUTTON_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0, FXint pl=DEFAULT_PAD, FXint pr=DEFAULT_PAD, FXint pt=DEFAULT_PAD, FXint pb=DEFAULT_PAD)
build button
MFXCheckableButton * getShowToolTipsMenu() const
get menu for tooltips menu
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
MFXStaticToolTip * getStaticTooltipMenu() const
get static toolTip for menus
bool amChecked() const
check if this MFXCheckableButton is checked
void setChecked(bool val, const bool inform=false)
check or uncheck this MFXCheckableButton
void enableStaticToolTip(const bool value)
enable/disable static tooltip
A class representing a single program option.
Definition Option.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
Definition json.hpp:4471
static std::string openOptionFileDialog(FXWindow *window, bool save)
open option dialog