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-2024 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#define MARGIN 4
31#define MAXNUMCOLUMNS 4
32#define NUMROWSBYCOLUMN 20
33
34// ===========================================================================
35// FOX callback mapping
36// ===========================================================================
37
50
51// Object implementation
52FXIMPLEMENT(GNEPythonToolDialog, FXDialogBox, GNEPythonToolDialogMap, ARRAYNUMBER(GNEPythonToolDialogMap))
53
54// ============================================-===============================
55// member method definitions
56// ===========================================================================
57
59 FXDialogBox(GNEApp->getApp(), "Tool", GUIDesignAuxiliarDialogBoxResizable),
60 myGNEApp(GNEApp) {
61 // set icon
63 // create main content frame
64 auto verticalContentFrame = new FXVerticalFrame(this, GUIDesignContentsFrame);
65 // create options
66 auto horizontalOptionsFrame = new FXHorizontalFrame(verticalContentFrame, GUIDesignHorizontalFrameNoPadding);
67 // build options
68 myShowToolTipsMenu = new MFXCheckableButton(false, horizontalOptionsFrame,
69 GNEApp->getStaticTooltipMenu(), (std::string("\t") + TL("Toggle Menu Tooltips") + std::string("\t") + TL("Toggles whether tooltips in the menu shall be shown.")).c_str(),
71 auto saveFile = new MFXButtonTooltip(horizontalOptionsFrame, GNEApp->getStaticTooltipMenu(), TL("Save toolcfg"),
73 saveFile->setTipText(TL("Save file with tool configuration"));
74 auto loadFile = new MFXButtonTooltip(horizontalOptionsFrame, GNEApp->getStaticTooltipMenu(), TL("Load toolcfg"),
76 loadFile->setTipText(TL("Load file with tool configuration"));
77 mySortedCheckButton = new FXCheckButton(horizontalOptionsFrame, TL("Sorted by name"), this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
78 myGroupedCheckButton = new FXCheckButton(horizontalOptionsFrame, TL("Grouped by categories"), this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
79 // add separators
80 new FXSeparator(verticalContentFrame);
81 // Create scroll frame for content rows
82 auto contentScrollWindow = new FXScrollWindow(verticalContentFrame, GUIDesignScrollWindow);
83 auto horizontalRowFrames = new FXHorizontalFrame(contentScrollWindow, LAYOUT_FILL_X | LAYOUT_FILL_Y | PACK_UNIFORM_WIDTH);
84 myArgumentFrameLeft = new FXVerticalFrame(horizontalRowFrames, GUIDesignAuxiliarFrame);
85 myArgumentFrameRight = new FXVerticalFrame(horizontalRowFrames, GUIDesignAuxiliarFrame);
86 // add separator
87 new FXSeparator(verticalContentFrame);
88 // create buttons centered
89 auto horizontalButtonsFrame = new FXHorizontalFrame(verticalContentFrame, GUIDesignHorizontalFrame);
90 auto blueLabel = new FXLabel(horizontalButtonsFrame, TL("Blue options are mandatory"), nullptr, GUIDesignLabelFixed(200));
91 blueLabel->setTextColor(FXRGB(0, 0, 255));
92 new FXHorizontalFrame(horizontalButtonsFrame, GUIDesignAuxiliarHorizontalFrame);
93 GUIDesigns::buildFXButton(horizontalButtonsFrame, TL("Run"), "", TL("run python tool"),
95 GUIDesigns::buildFXButton(horizontalButtonsFrame, TL("Close"), "", TL("close tool dialog"),
97 GUIDesigns::buildFXButton(horizontalButtonsFrame, TL("Reset"), "", TL("reset to default values"),
99 new FXLabel(horizontalButtonsFrame, "", nullptr, GUIDesignLabelFixed(200));
100 new FXHorizontalFrame(horizontalButtonsFrame, GUIDesignAuxiliarHorizontalFrame);
101}
102
103
105
106
107void
109 // set tool
110 myPythonTool = tool;
111 // set title
112 setTitle(myPythonTool->getToolName().c_str());
113 // reset checkboxes
114 mySortedCheckButton->setCheck(FALSE);
115 myGroupedCheckButton->setCheck(TRUE);
116 // set myShowToolTipsMenu
117 myShowToolTipsMenu->setChecked(getApp()->reg().readIntEntry("gui", "menuToolTips", 0) != 1);
118 // set current values in options (like current folders and similar)
120 // build arguments
121 buildArguments(false, true);
122 // get maximum height
123 const int maximumHeight = myArgumentFrameLeft->numChildren() * GUIDesignHeight + 120;
124 // resize
125 resize(1024, maximumHeight <= 768 ? maximumHeight : 768);
126 // show dialog
127 FXDialogBox::show(PLACEMENT_SCREEN);
128 // refresh APP
129 getApp()->refresh();
130}
131
132
137
138
139const GNEPythonTool*
143
144
145long
146GNEPythonToolDialog::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
147 // toggle check
149 if (myGNEApp->getViewNet()) {
152 }
153 // enable/disable static tooltip
155 // save in registry
156 getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
157 update();
158
159 return 1;
160}
161
162
163long
164GNEPythonToolDialog::onCmdSave(FXObject*, FXSelector, void*) {
165 // open save dialog
166 const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, true);
167 // check file
168 if (file.size() > 0) {
170 }
171 return 1;
172}
173
174
175long
176GNEPythonToolDialog::onCmdLoad(FXObject*, FXSelector, void*) {
177 // open file dialog
178 const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, false);
179 // check file
180 if ((file.size() > 0) && myPythonTool->loadConfiguration(file)) {
181 // rebuild arguments
182 buildArguments((mySortedCheckButton->getCheck() == TRUE), (myGroupedCheckButton->getCheck() == TRUE));
183 }
184 return 1;
185}
186
187
188long
189GNEPythonToolDialog::onCmdSetVisualization(FXObject*, FXSelector, void*) {
190 // rebuild arguments
191 buildArguments((mySortedCheckButton->getCheck() == TRUE), (myGroupedCheckButton->getCheck() == TRUE));
192 return 1;
193}
194
195
196long
197GNEPythonToolDialog::onCmdRun(FXObject*, FXSelector, void*) {
198 // hide dialog
199 hide();
200 // run tool
201 return myGNEApp->tryHandle(myPythonTool->getMenuCommand(), FXSEL(SEL_COMMAND, MID_GNE_RUNPYTHONTOOL), nullptr);
202}
203
204
205long
206GNEPythonToolDialog::onCmdCancel(FXObject*, FXSelector, void*) {
207 // hide dialog
208 hide();
209 return 1;
210}
211
212
213long
214GNEPythonToolDialog::onCmdReset(FXObject*, FXSelector, void*) {
215 // iterate over all arguments and reset values
216 for (const auto& argument : myArguments) {
217 argument->reset();
218 }
219 return 1;
220}
221
222
223long
224GNEPythonToolDialog::onUpdRequiredAttributes(FXObject* sender, FXSelector, void*) {
225 // iterate over all arguments and check if required attribute is set
226 for (const auto& argument : myArguments) {
227 if (argument->requiredAttributeSet() == false) {
228 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
229 }
230 }
231 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
232}
233
234
236 std::string(category) {
237}
238
239
240void
242 myOptions.push_back(std::make_pair(name, option));
243}
244
245
246const std::vector<std::pair<std::string, Option*> >&
248 return myOptions;
249}
250
251
252void
254 // just sort vector with options
255 std::sort(myOptions.begin(), myOptions.end());
256}
257
258
262
263
264void
265GNEPythonToolDialog::buildArguments(bool sortByName, bool groupedByCategories) {
266 // clear arguments and categories
267 for (const auto& argument : myArguments) {
268 delete argument;
269 }
270 for (const auto& category : myCategories) {
271 delete category;
272 }
273 myArguments.clear();
274 myCategories.clear();
275 // get argument sorted by name and grouped by categories
276 auto categoryOptions = groupedByCategories ? getOptionsByCategories(myPythonTool->getToolsOptions()) : getOptions(myPythonTool->getToolsOptions());
277 // calculate number of arguments
278 int numArguments = 0;
279 for (auto& categoryOption : categoryOptions) {
280 numArguments += (int)categoryOption.getOptions().size() + 1;
281 }
282 const int halfNumArguments = numArguments / 2;
283 // declare counter for number of inserted arguments
284 int numInsertedArguments = 0;
285 // iterate over category options
286 for (auto& categoryOption : categoryOptions) {
287 // get argument frame
288 auto argumentFrame = (numInsertedArguments < halfNumArguments) ? myArgumentFrameLeft : myArgumentFrameRight;
289 // add category
290 if (categoryOption.size() > 0) {
291 myCategories.push_back(new GNEPythonToolDialogElements::Category(argumentFrame, categoryOption));
292 numInsertedArguments++;
293 }
294 // check if sort by name
295 if (sortByName) {
296 categoryOption.sortByName();
297 }
298 // add options
299 for (const auto& option : categoryOption.getOptions()) {
300 // get argument frame (again)
301 argumentFrame = (numInsertedArguments < halfNumArguments) ? myArgumentFrameLeft : myArgumentFrameRight;
302 // continue depending of type
303 if (option.second->isInteger()) {
304 myArguments.push_back(new GNEPythonToolDialogElements::IntArgument(this, argumentFrame, option.first, option.second));
305 } else if (option.second->isFloat()) {
306 myArguments.push_back(new GNEPythonToolDialogElements::FloatArgument(this, argumentFrame, option.first, option.second));
307 } else if (option.second->isBool()) {
308 myArguments.push_back(new GNEPythonToolDialogElements::BoolArgument(this, argumentFrame, option.first, option.second));
309 } else if (option.second->isFileName()) {
310 myArguments.push_back(new GNEPythonToolDialogElements::FileNameArgument(this, argumentFrame, option.first, option.second));
311 } else if (option.second->isNetwork()) {
312 myArguments.push_back(new GNEPythonToolDialogElements::NetworkArgument(this, argumentFrame, option.first, option.second));
313 } else if (option.second->isAdditional()) {
314 myArguments.push_back(new GNEPythonToolDialogElements::AdditionalArgument(this, argumentFrame, option.first, option.second));
315 } else if (option.second->isRoute()) {
316 myArguments.push_back(new GNEPythonToolDialogElements::RouteArgument(this, argumentFrame, option.first, option.second));
317 } else if (option.second->isData()) {
318 myArguments.push_back(new GNEPythonToolDialogElements::DataArgument(this, argumentFrame, option.first, option.second));
319 } else if (option.second->isSumoConfig()) {
320 myArguments.push_back(new GNEPythonToolDialogElements::SumoConfigArgument(this, argumentFrame, option.first, option.second));
321 } else if (option.second->isEdge()) {
322 myArguments.push_back(new GNEPythonToolDialogElements::EdgeArgument(this, argumentFrame, option.first, option.second));
323 } else if (option.second->isEdgeVector()) {
324 myArguments.push_back(new GNEPythonToolDialogElements::EdgeVectorArgument(this, argumentFrame, option.first, option.second));
325 } else {
326 myArguments.push_back(new GNEPythonToolDialogElements::StringArgument(this, argumentFrame, option.first, option.second));
327 }
328 numInsertedArguments++;
329 }
330 }
331 // adjust parameter column (call always after create elements)
333}
334
335
336void
338 int maximumWidth = 0;
339 // iterate over all arguments and find the maximum width
340 for (const auto& argument : myArguments) {
341 const auto label = argument->getParameterLabel();
342 const int columnWidth = label->getFont()->getTextWidth(label->getText().text(), label->getText().length() + MARGIN);
343 if (columnWidth > maximumWidth) {
344 maximumWidth = columnWidth;
345 }
346 }
347 // set maximum width for all parameter labels
348 for (const auto& argument : myArguments) {
349 argument->getParameterLabel()->setWidth(maximumWidth);
350 }
351}
352
353
354std::vector<GNEPythonToolDialog::CategoryOptions>
356 // use a vector with only one empty category to reuse code of buildArguments
357 std::vector<GNEPythonToolDialog::CategoryOptions> result = {GNEPythonToolDialog::CategoryOptions("")};
358 // add all options to result
359 for (const auto& option : optionsCont) {
360 result.front().addOption(option.first, option.second);
361 }
362 return result;
363}
364
365
366std::vector<GNEPythonToolDialog::CategoryOptions>
368 // declare vector with common categories
369 const std::vector<std::string> commonCategories = {"input", "output", "processing", "time"};
370 // fill categories
371 std::vector<std::string> categories = commonCategories;
372 for (const auto& option : optionsCont) {
373 if (std::find(categories.begin(), categories.end(), option.second->getSubTopic()) == categories.end()) {
374 categories.push_back(option.second->getSubTopic());
375 }
376 }
377 // declare vector of category options and fill
378 std::vector<GNEPythonToolDialog::CategoryOptions> result;
379 for (const auto& category : categories) {
380 result.push_back(GNEPythonToolDialog::CategoryOptions(category));
381 }
382 // fill result with options
383 for (const auto& option : optionsCont) {
384 auto category = std::find(result.begin(), result.end(), option.second->getSubTopic());
385 // add option in category
386 category->addOption(option.first, option.second);
387 }
388 // drop empty categories
389 auto it = result.begin();
390 while (it != result.end()) {
391 if (it->getOptions().empty()) {
392 it = result.erase(it);
393 } else {
394 it++;
395 }
396 }
397 return result;
398}
399
400
401int
403 const int column = (int)myArguments.size() / NUMROWSBYCOLUMN;
404 return (column < MAXNUMCOLUMNS) ? column : (MAXNUMCOLUMNS - 1);
405}
406
407
408FXVerticalFrame*
412
413
414FXVerticalFrame*
418
419/****************************************************************************/
#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:381
#define GUIDesignLabelFixed(width)
label, icon before text, text centered and custom width
Definition GUIDesigns.h:252
#define GUIDesignButtonAccept
Accept Button.
Definition GUIDesigns.h:162
#define GUIDesignButtonCancel
Cancel Button.
Definition GUIDesigns.h:168
#define GUIDesignContentsFrame
design for the main content frame of every frame/dialog with padding and spacing
Definition GUIDesigns.h:393
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:405
#define GUIDesignButtonConfiguration
Configuration Button.
Definition GUIDesigns.h:165
#define GUIDesignMFXCheckableButtonSquare
Definition GUIDesigns.h:143
#define GUIDesignAuxiliarDialogBoxResizable
design for standard dialog box (for example, about dialog)
Definition GUIDesigns.h:614
#define GUIDesignCheckButton
checkButton placed in left position
Definition GUIDesigns.h:198
#define GUIDesignButtonReset
Reset Button.
Definition GUIDesigns.h:171
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition GUIDesigns.h:396
#define GUIDesignHorizontalFrameNoPadding
Horizontal frame extended over frame parent without padding and spacing.
Definition GUIDesigns.h:337
#define GUIDesignHorizontalFrame
Horizontal frame extended over frame parent with padding and spacing.
Definition GUIDesigns.h:334
@ SHOWTOOLTIPS_MENU
@ OPEN
open icons
@ SAVE
save icons
#define TL(string)
Definition MsgHandler.h:315
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:72
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