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>
28
29#include "GNEPythonToolDialog.h"
30
31// ===========================================================================
32// Defines
33// ===========================================================================
34
35#define MARGIN 4
36#define MAXNUMCOLUMNS 4
37#define NUMROWSBYCOLUMN 20
38
39// ===========================================================================
40// FOX callback mapping
41// ===========================================================================
42
53
54// Object implementation
55FXIMPLEMENT(GNEPythonToolDialog, GNEDialog, GNEPythonToolDialogMap, ARRAYNUMBER(GNEPythonToolDialogMap))
56
57// ============================================-===============================
58// member method definitions
59// ===========================================================================
60
62 GNEDialog(applicationWindow, TL("Tool"), GUIIcon::TOOL_PYTHON, GNEDialog::Buttons::RUN_CANCEL_RESET,
63 OpenType::MODAL, ResizeMode::RESIZABLE) {
64 // create options
65 auto horizontalOptionsFrame = new FXHorizontalFrame(myContentFrame, GUIDesignHorizontalFrameNoPadding);
66 // build options
67 myShowToolTipsMenu = new MFXCheckableButton(false, horizontalOptionsFrame,
68 applicationWindow->getStaticTooltipMenu(), (std::string("\t") + TL("Toggle Menu Tooltips") + std::string("\t") + TL("Toggles whether tooltips in the menu shall be shown.")).c_str(),
70 auto saveFile = new MFXButtonTooltip(horizontalOptionsFrame, applicationWindow->getStaticTooltipMenu(), TL("Save toolcfg"),
72 saveFile->setTipText(TL("Save file with tool configuration"));
73 auto loadFile = new MFXButtonTooltip(horizontalOptionsFrame, applicationWindow->getStaticTooltipMenu(), TL("Load toolcfg"),
75 loadFile->setTipText(TL("Load file with tool configuration"));
76 mySortedCheckButton = new FXCheckButton(horizontalOptionsFrame, TL("Sorted by name"), this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
77 myGroupedCheckButton = new FXCheckButton(horizontalOptionsFrame, TL("Grouped by categories"), this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
78 // add separators
79 new FXSeparator(myContentFrame);
80 // Create scroll frame for content rows
81 auto contentScrollWindow = new FXScrollWindow(myContentFrame, GUIDesignScrollWindow);
82 auto horizontalRowFrames = new FXHorizontalFrame(contentScrollWindow, LAYOUT_FILL_X | LAYOUT_FILL_Y | PACK_UNIFORM_WIDTH);
83 myArgumentFrameLeft = new FXVerticalFrame(horizontalRowFrames, GUIDesignAuxiliarFrame);
84 myArgumentFrameRight = new FXVerticalFrame(horizontalRowFrames, GUIDesignAuxiliarFrame);
85 // set tool
86 myPythonTool = tool;
87 // set title
88 setTitle(myPythonTool->getToolName().c_str());
89 // reset checkboxes
90 mySortedCheckButton->setCheck(FALSE);
91 myGroupedCheckButton->setCheck(TRUE);
92 // set myShowToolTipsMenu
93 myShowToolTipsMenu->setChecked(getApp()->reg().readIntEntry("gui", "menuToolTips", 0) != 1);
94 // set current values in options (like current folders and similar)
95 myPythonTool->setCurrentValues();
96 // build arguments
97 buildArguments(false, true);
98 // get maximum height
99 const int maximumHeight = myArgumentFrameLeft->numChildren() * GUIDesignHeight + 120;
100 // resize
101 resize(1024, maximumHeight <= 768 ? maximumHeight : 768);
102 // open dialog
103 openDialog();
104}
105
106
108
109
110void
112 // nothing to do
113}
114
115
116const GNEPythonTool*
120
121
122long
123GNEPythonToolDialog::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
124 // toggle check
129 }
130 // enable/disable static tooltip
132 // save in registry
133 getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
134 update();
135
136 return 1;
137}
138
139
140long
141GNEPythonToolDialog::onCmdSave(FXObject*, FXSelector, void*) {
142 // open save dialog
143 const auto optionsFileDialog = GNEFileDialog(myApplicationWindow, TL("options file"),
147 // check file
148 if (optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) {
149 myPythonTool->saveConfiguration(optionsFileDialog.getFilename());
150 }
151 return 1;
152}
153
154
155long
156GNEPythonToolDialog::onCmdLoad(FXObject*, FXSelector, void*) {
157 // open file dialog
158 const auto optionsFileDialog = GNEFileDialog(myApplicationWindow, TL("options file"),
162 // check file
163 if ((optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) && myPythonTool->loadConfiguration(optionsFileDialog.getFilename())) {
164 // rebuild arguments
165 buildArguments((mySortedCheckButton->getCheck() == TRUE), (myGroupedCheckButton->getCheck() == TRUE));
166 }
167 return 1;
168}
169
170
171long
172GNEPythonToolDialog::onCmdSetVisualization(FXObject*, FXSelector, void*) {
173 // rebuild arguments
174 buildArguments((mySortedCheckButton->getCheck() == TRUE), (myGroupedCheckButton->getCheck() == TRUE));
175 return 1;
176}
177
178
179long
180GNEPythonToolDialog::onCmdRun(FXObject*, FXSelector, void*) {
181 // hide dialog
182 hide();
183 // run tool
184 return myApplicationWindow->tryHandle(myPythonTool->getMenuCommand(), FXSEL(SEL_COMMAND, MID_GNE_RUNPYTHONTOOL), nullptr);
185}
186
187
188long
189GNEPythonToolDialog::onCmdReset(FXObject*, FXSelector, void*) {
190 // iterate over all arguments and reset values
191 for (const auto& argument : myArguments) {
192 argument->reset();
193 }
194 return 1;
195}
196
197
198long
199GNEPythonToolDialog::onUpdRequiredAttributes(FXObject* sender, FXSelector, void*) {
200 // iterate over all arguments and check if required attribute is set
201 for (const auto& argument : myArguments) {
202 if (argument->requiredAttributeSet() == false) {
203 return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
204 }
205 }
206 return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
207}
208
209
211 std::string(category) {
212}
213
214
215void
217 myOptions.push_back(std::make_pair(name, option));
218}
219
220
221const std::vector<std::pair<std::string, Option*> >&
223 return myOptions;
224}
225
226
227void
229 // just sort vector with options
230 std::sort(myOptions.begin(), myOptions.end());
231}
232
233
234void
235GNEPythonToolDialog::buildArguments(bool sortByName, bool groupedByCategories) {
236 // clear arguments and categories
237 for (const auto& argument : myArguments) {
238 delete argument;
239 }
240 for (const auto& category : myCategories) {
241 delete category;
242 }
243 myArguments.clear();
244 myCategories.clear();
245 // get argument sorted by name and grouped by categories
246 auto categoryOptions = groupedByCategories ? getOptionsByCategories(myPythonTool->getToolsOptions()) : getOptions(myPythonTool->getToolsOptions());
247 // calculate number of arguments
248 int numArguments = 0;
249 for (auto& categoryOption : categoryOptions) {
250 numArguments += (int)categoryOption.getOptions().size() + 1;
251 }
252 const int halfNumArguments = numArguments / 2;
253 // declare counter for number of inserted arguments
254 int numInsertedArguments = 0;
255 // iterate over category options
256 for (auto& categoryOption : categoryOptions) {
257 // get argument frame
258 auto argumentFrame = (numInsertedArguments < halfNumArguments) ? myArgumentFrameLeft : myArgumentFrameRight;
259 // add category
260 if (categoryOption.size() > 0) {
261 myCategories.push_back(new GNEPythonToolDialogElements::Category(argumentFrame, categoryOption));
262 numInsertedArguments++;
263 }
264 // check if sort by name
265 if (sortByName) {
266 categoryOption.sortByName();
267 }
268 // add options
269 for (const auto& option : categoryOption.getOptions()) {
270 // get argument frame (again)
271 argumentFrame = (numInsertedArguments < halfNumArguments) ? myArgumentFrameLeft : myArgumentFrameRight;
272 // continue depending of type
273 if (option.second->isInteger()) {
274 myArguments.push_back(new GNEPythonToolDialogElements::IntArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
275 } else if (option.second->isFloat()) {
276 myArguments.push_back(new GNEPythonToolDialogElements::FloatArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
277 } else if (option.second->isBool()) {
278 myArguments.push_back(new GNEPythonToolDialogElements::BoolArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
279 } else if (option.second->isFileName()) {
280 myArguments.push_back(new GNEPythonToolDialogElements::FileNameArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
281 } else if (option.second->isNetwork()) {
282 myArguments.push_back(new GNEPythonToolDialogElements::NetworkArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
283 } else if (option.second->isAdditional()) {
284 myArguments.push_back(new GNEPythonToolDialogElements::AdditionalArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
285 } else if (option.second->isRoute()) {
286 myArguments.push_back(new GNEPythonToolDialogElements::RouteArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
287 } else if (option.second->isData()) {
288 myArguments.push_back(new GNEPythonToolDialogElements::DataArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
289 } else if (option.second->isSumoConfig()) {
290 myArguments.push_back(new GNEPythonToolDialogElements::SumoConfigArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
291 } else if (option.second->isEdge()) {
292 myArguments.push_back(new GNEPythonToolDialogElements::EdgeArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
293 } else if (option.second->isEdgeVector()) {
294 myArguments.push_back(new GNEPythonToolDialogElements::EdgeVectorArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
295 } else {
296 myArguments.push_back(new GNEPythonToolDialogElements::StringArgument(this, myPythonTool, getApplicationWindow(), argumentFrame, option.first, option.second));
297 }
298 numInsertedArguments++;
299 }
300 }
301 // adjust parameter column (call always after create elements)
303}
304
305
306void
308 int maximumWidth = 0;
309 // iterate over all arguments and find the maximum width
310 for (const auto& argument : myArguments) {
311 const auto label = argument->getParameterLabel();
312 const int columnWidth = label->getFont()->getTextWidth(label->getText().text(), label->getText().length() + MARGIN);
313 if (columnWidth > maximumWidth) {
314 maximumWidth = columnWidth;
315 }
316 }
317 // set maximum width for all parameter labels
318 for (const auto& argument : myArguments) {
319 argument->getParameterLabel()->setWidth(maximumWidth);
320 }
321}
322
323
324std::vector<GNEPythonToolDialog::CategoryOptions>
326 // use a vector with only one empty category to reuse code of buildArguments
327 std::vector<GNEPythonToolDialog::CategoryOptions> result = {GNEPythonToolDialog::CategoryOptions("")};
328 // add all options to result
329 for (const auto& option : optionsCont) {
330 result.front().addOption(option.first, option.second);
331 }
332 return result;
333}
334
335
336std::vector<GNEPythonToolDialog::CategoryOptions>
338 // declare vector with common categories
339 const std::vector<std::string> commonCategories = {"input", "output", "processing", "time"};
340 // fill categories
341 std::vector<std::string> categories = commonCategories;
342 for (const auto& option : optionsCont) {
343 if (std::find(categories.begin(), categories.end(), option.second->getSubTopic()) == categories.end()) {
344 categories.push_back(option.second->getSubTopic());
345 }
346 }
347 // declare vector of category options and fill
348 std::vector<GNEPythonToolDialog::CategoryOptions> result;
349 for (const auto& category : categories) {
350 result.push_back(GNEPythonToolDialog::CategoryOptions(category));
351 }
352 // fill result with options
353 for (const auto& option : optionsCont) {
354 auto category = std::find(result.begin(), result.end(), option.second->getSubTopic());
355 // add option in category
356 category->addOption(option.first, option.second);
357 }
358 // drop empty categories
359 auto it = result.begin();
360 while (it != result.end()) {
361 if (it->getOptions().empty()) {
362 it = result.erase(it);
363 } else {
364 it++;
365 }
366 }
367 return result;
368}
369
370
371int
373 const int column = (int)myArguments.size() / NUMROWSBYCOLUMN;
374 return (column < MAXNUMCOLUMNS) ? column : (MAXNUMCOLUMNS - 1);
375}
376
377
378FXVerticalFrame*
382
383
384FXVerticalFrame*
388
389/****************************************************************************/
#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_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:394
#define GUIDesignButtonConfiguration
Configuration Button.
Definition GUIDesigns.h:177
#define GUIDesignMFXCheckableButtonSquare
Definition GUIDesigns.h:158
#define GUIDesignCheckButton
checkButton placed in left position
Definition GUIDesigns.h:194
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition GUIDesigns.h:409
#define GUIDesignHorizontalFrameNoPadding
Horizontal frame extended over frame parent without padding and spacing.
Definition GUIDesigns.h:350
GUIIcon
An enumeration of icons used by the gui applications.
Definition GUIIcons.h:33
@ SHOWTOOLTIPS_MENU
@ OPEN
open icons
@ SAVE
save icons
#define TL(string)
Definition MsgHandler.h:305
int GUIDesignHeight
the default height for GUI elements
Definition StdDefs.cpp:37
The main window of Netedit.
GNEViewNet * getViewNet()
get pointer to viewNet
GNEApplicationWindow * getApplicationWindow() const
get pointer to the application window
Definition GNEDialog.cpp:93
GNEApplicationWindow * myApplicationWindow
FOX needs this.
Definition GNEDialog.h:132
OpenType
Open dialog type.
Definition GNEDialog.h:55
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
std::vector< CategoryOptions > getOptionsByCategories(OptionsCont &optionsCont) const
get options sorted by category
FXVerticalFrame * myArgumentFrameRight
argument frame right
GNEPythonTool * myPythonTool
python tool
void adjustParameterColumn()
adjust parameter column
int getNumRowColums() const
get number of row colums
long onCmdLoad(FXObject *, FXSelector, void *)
load options
std::vector< GNEPythonToolDialogElements::Argument * > myArguments
list of arguments sorted by categories
std::vector< GNEPythonToolDialogElements::Category * > myCategories
list of categories
long onCmdShowToolTipsMenu(FXObject *, FXSelector, void *)
enable/disable show toolTip
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 runInternalTest(const InternalTestStep::DialogArgument *dialogArgument)
run internal test
void buildArguments(bool sortByName, bool groupedByCategories)
build arguments
FXCheckButton * myGroupedCheckButton
check button to enable/diasble grouping
void saveConfiguration(const std::string &file) const
save configuration
bool loadConfiguration(const std::string &file)
load configuration
FXMenuCommand * getMenuCommand() const
get menu command
OptionsCont & getToolsOptions()
get tools options
GNEViewParent * getViewParent() const
get the net object
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 modal dialogs that can not be edited using tab
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
static StringBijection< XMLFileExtension > XMLFileExtensions
XML file Extensions.
Definition json.hpp:4471