Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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, MFXDialogBox, GNEPythonToolDialogMap, ARRAYNUMBER(GNEPythonToolDialogMap))
57
58// ============================================-===============================
59// member method definitions
60// ===========================================================================
61
63 MFXDialogBox(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 MFXDialogBox::show(PLACEMENT_SCREEN);
132 // refresh APP
133 getApp()->refresh();
134}
135
136
137void
139 // finish
140}
141
142
147
148
149const GNEPythonTool*
153
154
155long
156GNEPythonToolDialog::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
157 // toggle check
159 if (myGNEApp->getViewNet()) {
162 }
163 // enable/disable static tooltip
165 // save in registry
166 getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
167 update();
168
169 return 1;
170}
171
172
173long
174GNEPythonToolDialog::onCmdSave(FXObject*, FXSelector, void*) {
175 // open save dialog
176 const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, true);
177 // check file
178 if (file.size() > 0) {
180 }
181 return 1;
182}
183
184
185long
186GNEPythonToolDialog::onCmdLoad(FXObject*, FXSelector, void*) {
187 // open file dialog
188 const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, false);
189 // check file
190 if ((file.size() > 0) && myPythonTool->loadConfiguration(file)) {
191 // rebuild arguments
192 buildArguments((mySortedCheckButton->getCheck() == TRUE), (myGroupedCheckButton->getCheck() == TRUE));
193 }
194 return 1;
195}
196
197
198long
199GNEPythonToolDialog::onCmdSetVisualization(FXObject*, FXSelector, void*) {
200 // rebuild arguments
201 buildArguments((mySortedCheckButton->getCheck() == TRUE), (myGroupedCheckButton->getCheck() == TRUE));
202 return 1;
203}
204
205
206long
207GNEPythonToolDialog::onCmdRun(FXObject*, FXSelector, void*) {
208 // hide dialog
209 hide();
210 // run tool
211 return myGNEApp->tryHandle(myPythonTool->getMenuCommand(), FXSEL(SEL_COMMAND, MID_GNE_RUNPYTHONTOOL), nullptr);
212}
213
214
215long
216GNEPythonToolDialog::onCmdCancel(FXObject*, FXSelector, void*) {
217 // hide dialog
218 hide();
219 return 1;
220}
221
222
223long
224GNEPythonToolDialog::onCmdReset(FXObject*, FXSelector, void*) {
225 // iterate over all arguments and reset values
226 for (const auto& argument : myArguments) {
227 argument->reset();
228 }
229 return 1;
230}
231
232
233long
234GNEPythonToolDialog::onUpdRequiredAttributes(FXObject* sender, FXSelector, void*) {
235 // iterate over all arguments and check if required attribute is set
236 for (const auto& argument : myArguments) {
237 if (argument->requiredAttributeSet() == false) {
238 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
239 }
240 }
241 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
242}
243
244
246 std::string(category) {
247}
248
249
250void
252 myOptions.push_back(std::make_pair(name, option));
253}
254
255
256const std::vector<std::pair<std::string, Option*> >&
258 return myOptions;
259}
260
261
262void
264 // just sort vector with options
265 std::sort(myOptions.begin(), myOptions.end());
266}
267
268
272
273
274void
275GNEPythonToolDialog::buildArguments(bool sortByName, bool groupedByCategories) {
276 // clear arguments and categories
277 for (const auto& argument : myArguments) {
278 delete argument;
279 }
280 for (const auto& category : myCategories) {
281 delete category;
282 }
283 myArguments.clear();
284 myCategories.clear();
285 // get argument sorted by name and grouped by categories
286 auto categoryOptions = groupedByCategories ? getOptionsByCategories(myPythonTool->getToolsOptions()) : getOptions(myPythonTool->getToolsOptions());
287 // calculate number of arguments
288 int numArguments = 0;
289 for (auto& categoryOption : categoryOptions) {
290 numArguments += (int)categoryOption.getOptions().size() + 1;
291 }
292 const int halfNumArguments = numArguments / 2;
293 // declare counter for number of inserted arguments
294 int numInsertedArguments = 0;
295 // iterate over category options
296 for (auto& categoryOption : categoryOptions) {
297 // get argument frame
298 auto argumentFrame = (numInsertedArguments < halfNumArguments) ? myArgumentFrameLeft : myArgumentFrameRight;
299 // add category
300 if (categoryOption.size() > 0) {
301 myCategories.push_back(new GNEPythonToolDialogElements::Category(argumentFrame, categoryOption));
302 numInsertedArguments++;
303 }
304 // check if sort by name
305 if (sortByName) {
306 categoryOption.sortByName();
307 }
308 // add options
309 for (const auto& option : categoryOption.getOptions()) {
310 // get argument frame (again)
311 argumentFrame = (numInsertedArguments < halfNumArguments) ? myArgumentFrameLeft : myArgumentFrameRight;
312 // continue depending of type
313 if (option.second->isInteger()) {
314 myArguments.push_back(new GNEPythonToolDialogElements::IntArgument(this, argumentFrame, option.first, option.second));
315 } else if (option.second->isFloat()) {
316 myArguments.push_back(new GNEPythonToolDialogElements::FloatArgument(this, argumentFrame, option.first, option.second));
317 } else if (option.second->isBool()) {
318 myArguments.push_back(new GNEPythonToolDialogElements::BoolArgument(this, argumentFrame, option.first, option.second));
319 } else if (option.second->isFileName()) {
320 myArguments.push_back(new GNEPythonToolDialogElements::FileNameArgument(this, argumentFrame, option.first, option.second));
321 } else if (option.second->isNetwork()) {
322 myArguments.push_back(new GNEPythonToolDialogElements::NetworkArgument(this, argumentFrame, option.first, option.second));
323 } else if (option.second->isAdditional()) {
324 myArguments.push_back(new GNEPythonToolDialogElements::AdditionalArgument(this, argumentFrame, option.first, option.second));
325 } else if (option.second->isRoute()) {
326 myArguments.push_back(new GNEPythonToolDialogElements::RouteArgument(this, argumentFrame, option.first, option.second));
327 } else if (option.second->isData()) {
328 myArguments.push_back(new GNEPythonToolDialogElements::DataArgument(this, argumentFrame, option.first, option.second));
329 } else if (option.second->isSumoConfig()) {
330 myArguments.push_back(new GNEPythonToolDialogElements::SumoConfigArgument(this, argumentFrame, option.first, option.second));
331 } else if (option.second->isEdge()) {
332 myArguments.push_back(new GNEPythonToolDialogElements::EdgeArgument(this, argumentFrame, option.first, option.second));
333 } else if (option.second->isEdgeVector()) {
334 myArguments.push_back(new GNEPythonToolDialogElements::EdgeVectorArgument(this, argumentFrame, option.first, option.second));
335 } else {
336 myArguments.push_back(new GNEPythonToolDialogElements::StringArgument(this, argumentFrame, option.first, option.second));
337 }
338 numInsertedArguments++;
339 }
340 }
341 // adjust parameter column (call always after create elements)
343}
344
345
346void
348 int maximumWidth = 0;
349 // iterate over all arguments and find the maximum width
350 for (const auto& argument : myArguments) {
351 const auto label = argument->getParameterLabel();
352 const int columnWidth = label->getFont()->getTextWidth(label->getText().text(), label->getText().length() + MARGIN);
353 if (columnWidth > maximumWidth) {
354 maximumWidth = columnWidth;
355 }
356 }
357 // set maximum width for all parameter labels
358 for (const auto& argument : myArguments) {
359 argument->getParameterLabel()->setWidth(maximumWidth);
360 }
361}
362
363
364std::vector<GNEPythonToolDialog::CategoryOptions>
366 // use a vector with only one empty category to reuse code of buildArguments
367 std::vector<GNEPythonToolDialog::CategoryOptions> result = {GNEPythonToolDialog::CategoryOptions("")};
368 // add all options to result
369 for (const auto& option : optionsCont) {
370 result.front().addOption(option.first, option.second);
371 }
372 return result;
373}
374
375
376std::vector<GNEPythonToolDialog::CategoryOptions>
378 // declare vector with common categories
379 const std::vector<std::string> commonCategories = {"input", "output", "processing", "time"};
380 // fill categories
381 std::vector<std::string> categories = commonCategories;
382 for (const auto& option : optionsCont) {
383 if (std::find(categories.begin(), categories.end(), option.second->getSubTopic()) == categories.end()) {
384 categories.push_back(option.second->getSubTopic());
385 }
386 }
387 // declare vector of category options and fill
388 std::vector<GNEPythonToolDialog::CategoryOptions> result;
389 for (const auto& category : categories) {
390 result.push_back(GNEPythonToolDialog::CategoryOptions(category));
391 }
392 // fill result with options
393 for (const auto& option : optionsCont) {
394 auto category = std::find(result.begin(), result.end(), option.second->getSubTopic());
395 // add option in category
396 category->addOption(option.first, option.second);
397 }
398 // drop empty categories
399 auto it = result.begin();
400 while (it != result.end()) {
401 if (it->getOptions().empty()) {
402 it = result.erase(it);
403 } else {
404 it++;
405 }
406 }
407 return result;
408}
409
410
411int
413 const int column = (int)myArguments.size() / NUMROWSBYCOLUMN;
414 return (column < MAXNUMCOLUMNS) ? column : (MAXNUMCOLUMNS - 1);
415}
416
417
418FXVerticalFrame*
422
423
424FXVerticalFrame*
428
429/****************************************************************************/
#define MAXNUMCOLUMNS
#define NUMROWSBYCOLUMN
#define MARGIN
FXDEFMAP(GNEPythonToolDialog) GNEPythonToolDialogMap[]
@ MID_GNE_SET_ATTRIBUTE
attribute edited
Definition GUIAppEnum.h:991
@ 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:36
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
void runInternalTest(const InternalTestStep::DialogTest *modalArguments)
run internal test
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
dialog arguments (used for certain functions that opens modal dialogs)
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