8 #include <wx/spinctrl.h>
9 #include <wx/stattext.h>
10 #include <wx/textdlg.h>
15 for (
Size colIdx = 0; colIdx < cols.
size(); ++colIdx) {
16 const std::string baseName = cols[colIdx].node->instanceName();
22 const std::size_t n = name.find(
" / ");
23 if (n == std::string::npos) {
24 throw InvalidSetup(
"Invalid name of cloned node: " + name);
26 const std::string clonedName = name.substr(n + 3);
27 if (baseName == clonedName) {
33 this->modifyNode(*modifiedNode, runIdx, colIdx);
50 ss >> v[
X] >> v[
Y] >> v[
Z];
60 path =
Path(ss.str());
69 "' is invalid for this parameter. Possible values are:\n" +
85 void BatchManager::modifyNode(
JobNode& node,
const Size runIdx,
const Size paramIdx) {
86 const std::string newValue =
getCell(paramIdx, runIdx);
91 settings.
set(cols[paramIdx].key, variant);
96 const Size rowCnt =
root->get<
int>(
"runCount");
97 const Size colCnt =
root->get<
int>(
"paramCount");
98 this->
resize(rowCnt, colCnt);
101 for (
Size i = 0; i < colCnt; ++i) {
102 const Optional<std::string> paramDesc = paramNode->tryGet<std::string>(
"param-" + std::to_string(i));
106 const std::size_t sep = paramDesc->find(
"->");
107 if (sep == std::string::npos) {
110 cols[i].key = paramDesc->substr(sep + 2);
111 const std::string name = paramDesc->substr(0, sep);
112 auto iter = std::find_if(nodes.begin(), nodes.end(), [&name](
const SharedPtr<JobNode>& node) {
113 return node->instanceName() == name;
115 if (iter != nodes.end()) {
116 cols[i].node = *iter;
121 for (
Size i = 0; i < rowCnt; ++i) {
122 rows[i] = runNode->
get<std::string>(
"run-" + std::to_string(i));
126 for (
Size j = 0; j < rowCnt; ++j) {
127 for (
Size i = 0; i < colCnt; ++i) {
129 cellNode->
get<std::string>(
"cell-" + std::to_string(i) +
"-" + std::to_string(j));
137 root->set(
"paramCount", cols.
size());
140 for (
Size i = 0; i < cols.
size(); ++i) {
142 paramNode->set(
"param-" + std::to_string(i), cols[i].node->instanceName() +
"->" + cols[i].key);
147 for (
Size i = 0; i < rows.
size(); ++i) {
148 runNode->set(
"run-" + std::to_string(i),
getRunName(i));
152 for (
Size j = 0; j < rows.
size(); ++j) {
153 for (
Size i = 0; i < cols.
size(); ++i) {
154 cellNode->set(
"cell-" + std::to_string(i) +
"-" + std::to_string(j), cells[
Pixel(i, j)]);
161 wxArrayString& items;
191 : wxDialog(parent, wxID_ANY,
"Select parameter")
193 wxBoxSizer* sizer =
new wxBoxSizer(wxVERTICAL);
195 wxBoxSizer* nodeSizer =
new wxBoxSizer(wxHORIZONTAL);
196 nodeSizer->Add(
new wxStaticText(
this, wxID_ANY,
"Node:", wxDefaultPosition, wxSize(120, -1)));
197 nodeBox =
new ComboBox(
this,
"", wxSize(200, -1));
203 nodeBox->SetSelection(0);
204 nodeSizer->Add(nodeBox);
205 sizer->Add(nodeSizer);
207 wxBoxSizer* paramSizer =
new wxBoxSizer(wxHORIZONTAL);
208 paramSizer->Add(
new wxStaticText(
this, wxID_ANY,
"Parameter:", wxDefaultPosition, wxSize(120, -1)));
209 paramBox =
new ComboBox(
this,
"", wxSize(200, -1));
210 paramSizer->Add(paramBox);
211 sizer->Add(paramSizer);
213 nodeBox->Bind(wxEVT_COMBOBOX, [
this, nodes](wxCommandEvent&
UNUSED(evt)) {
214 const int idx = nodeBox->GetSelection();
219 paramBox->Set(items);
220 paramBox->SetSelection(0);
223 wxBoxSizer* buttonSizer =
new wxBoxSizer(wxHORIZONTAL);
224 wxButton* okButton =
new wxButton(
this, wxID_ANY,
"OK");
225 okButton->Bind(wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) { this->EndModal(wxID_OK); });
226 buttonSizer->Add(okButton);
227 wxButton* cancelButton =
new wxButton(
this, wxID_ANY,
"Cancel");
229 wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) { this->EndModal(wxID_CANCEL); });
230 buttonSizer->Add(cancelButton);
231 sizer->Add(buttonSizer);
233 this->SetSizer(sizer);
237 return nodes[nodeBox->GetSelection()];
241 return cached.keys[paramBox->GetSelection()];
245 return nodeBox->GetValue() +
" - " + paramBox->GetValue();
250 : wxDialog(parent, wxID_ANY,
"Batch run", wxDefaultPosition, wxSize(800, 530))
251 , manager(mgr.clone())
252 , nodes(
std::move(nodes)) {
254 wxBoxSizer* sizer =
new wxBoxSizer(wxVERTICAL);
256 wxBoxSizer* controlsSizer =
new wxBoxSizer(wxHORIZONTAL);
257 controlsSizer->Add(
new wxStaticText(
this, wxID_ANY,
"Run count:"));
258 wxSpinCtrl* runSpinner =
new wxSpinCtrl(
this, wxID_ANY);
260 controlsSizer->Add(runSpinner);
261 controlsSizer->Add(
new wxStaticText(
this, wxID_ANY,
"Parameter count:"));
262 wxSpinCtrl* paramSpinner =
new wxSpinCtrl(
this, wxID_ANY);
264 controlsSizer->Add(paramSpinner);
266 sizer->Add(controlsSizer);
267 sizer->AddSpacer(10);
269 grid =
new wxGrid(
this, wxID_ANY, wxDefaultPosition, wxSize(800, 450));
270 grid->SetDefaultColSize(200);
271 grid->SetTabBehaviour(wxGrid::Tab_Wrap);
273 grid->EnableEditing(
true);
277 wxBoxSizer* buttonSizer =
new wxBoxSizer(wxHORIZONTAL);
278 wxButton* okButton =
new wxButton(
this, wxID_ANY,
"OK");
279 okButton->Bind(wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) { this->EndModal(wxID_OK); });
280 buttonSizer->Add(okButton);
281 wxButton* closeButton =
new wxButton(
this, wxID_ANY,
"Cancel");
282 closeButton->Bind(wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) { this->EndModal(wxID_CANCEL); });
283 buttonSizer->Add(closeButton);
284 sizer->Add(buttonSizer);
286 grid->Bind(wxEVT_GRID_LABEL_LEFT_DCLICK, [
this](wxGridEvent& evt) {
287 const bool isRow = evt.GetCol() == -1;
289 wxTextEntryDialog* dialog =
new wxTextEntryDialog(
this,
"Enter name of the run");
290 dialog->SetValue(grid->GetRowLabelValue(evt.GetRow()));
291 if (dialog->ShowModal() == wxID_OK) {
292 const wxString value = dialog->GetValue();
293 grid->SetRowLabelValue(evt.GetRow(), value);
294 manager.
setRunName(evt.GetRow(), std::string(value));
299 if (dialog->ShowModal() == wxID_OK) {
300 grid->SetColLabelValue(evt.GetCol(), dialog->
getLabel());
305 grid->Bind(wxEVT_GRID_LABEL_RIGHT_CLICK, [
this](wxGridEvent& evt) {
306 if (evt.GetRow() == -1) {
311 menu.Append(0,
"Duplicate");
312 menu.Append(1,
"Delete");
314 const Size rowIdx = evt.GetRow();
315 menu.Bind(wxEVT_COMMAND_MENU_SELECTED, [
this, rowIdx](wxCommandEvent& evt) {
316 switch (evt.GetId()) {
318 manager.duplicateRun(rowIdx);
319 grid->InsertRows(rowIdx, 1);
322 manager.deleteRun(rowIdx);
323 grid->DeleteRows(rowIdx, 1);
331 this->PopupMenu(&menu);
334 grid->Bind(wxEVT_GRID_CELL_CHANGED, [
this](wxGridEvent& evt) {
335 const std::string value(grid->GetCellValue(evt.GetRow(), evt.GetCol()));
336 manager.
setCell(evt.GetCol(), evt.GetRow(), value);
339 runSpinner->Bind(wxEVT_SPINCTRL, [
this](wxSpinEvent& evt) {
340 const int newRunCount =
max(evt.GetValue(), 1);
341 const int oldRunCount = grid->GetNumberRows();
342 if (newRunCount > oldRunCount) {
343 grid->InsertRows(oldRunCount, newRunCount - oldRunCount);
345 grid->DeleteRows(newRunCount, oldRunCount - newRunCount);
347 manager.
resize(newRunCount, grid->GetNumberCols());
349 paramSpinner->Bind(wxEVT_SPINCTRL, [
this](wxSpinEvent& evt) {
350 const int newParamCount =
max(evt.GetValue(), 1);
351 const int oldParamCount = grid->GetNumberCols();
352 if (newParamCount > oldParamCount) {
353 grid->InsertCols(oldParamCount, newParamCount - oldParamCount);
355 grid->DeleteCols(newParamCount, oldParamCount - newParamCount);
357 manager.
resize(grid->GetNumberRows(), newParamCount);
361 this->SetSizer(sizer);
367 void BatchDialog::update() {
370 SPH_ASSERT(grid->GetNumberCols() ==
int(paramCnt));
371 SPH_ASSERT(grid->GetNumberRows() ==
int(runCnt));
372 for (
Size j = 0; j < runCnt; ++j) {
373 grid->SetRowLabelValue(j, manager.
getRunName(j));
375 for (
Size i = 0; i < paramCnt; ++i) {
381 for (
Size j = 0; j < runCnt; ++j) {
382 for (
Size i = 0; i < paramCnt; ++i) {
383 grid->SetCellValue(j, i, manager.
getCell(i, j));
#define SPH_ASSERT(x,...)
Interface for the configuration files storing job data.
uint32_t Size
Integral type used to index arrays (by default).
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
constexpr INLINE T max(const T &f1, const T &f2)
INLINE Float root(const Float f)
#define NAMESPACE_SPH_END
decltype(auto) INLINE forValue(Variant< TArgs... > &variant, TFunctor &&functor)
AddParamProc(wxArrayString &items, Array< std::string > &keys)
virtual void onCategory(const std::string &UNUSED(name)) const override
virtual void onEntry(const std::string &key, IVirtualEntry &entry) const override
Called for every entry in the current category.
Object providing safe access to continuous memory of data.
INLINE void push(U &&u)
Adds new element to the end of the array, resizing the array if necessary.
void clear()
Removes all elements from the array, but does NOT release the memory.
INLINE TCounter size() const noexcept
BatchDialog(wxWindow *parent, const BatchManager &manager, Array< SharedPtr< JobNode >> &&nodes)
std::string getParamKey(const Size colIdx) const
void save(Config &config)
void setCell(const Size colIdx, const Size rowIdx, const std::string &value)
Size getParamCount() const
void load(Config &config, ArrayView< const SharedPtr< JobNode >> nodes)
std::string getRunName(const Size rowIdx) const
void resize(const Size rowCnt, const Size colCnt)
void modifyHierarchy(const Size runIdx, JobNode &node)
Modifies the settings of the given node hierarchy.
std::string getCell(const Size colIdx, const Size rowIdx) const
void setRunName(const Size rowIdx, const std::string &name)
SharedPtr< JobNode > getParamNode(const Size colIdx) const
void setParam(const Size colIdx, const SharedPtr< JobNode > &node, const std::string &key)
void operator()(Path &path)
void operator()(Interval &i)
void operator()(ExtraEntry &extra)
void operator()(EnumWrapper &ew)
void operator()(Vector &v)
BatchValueVisitor(const std::string &newValue)
void operator()(T &value)
Default overload.
Provides functionality for reading and writing configuration files.
SharedPtr< ConfigNode > addNode(const std::string &name)
Adds a new node to the config.
SharedPtr< ConfigNode > getNode(const std::string &name)
Returns a node with given name.
static Optional< TEnum > fromString(const std::string &value)
static std::string getDesc()
Represents a virtual entry in the settings.
virtual std::string getName() const =0
Returns a descriptive name of the entry.
Object representing a 1D interval of real numbers.
Thrown when components of the run are mutually incompatible.
Building block of a simulation hierarchy.
std::string instanceName() const
Returns the instance name of the job.
void enumerate(Function< void(const SharedPtr< JobNode > &job)> func)
Enumerates all nodes in the hierarchy.
VirtualSettings getSettings() const
Returns settings object allowing to access and modify the state of the job.
INLINE Type & value()
Returns the reference to the stored value.
ParamSelectDialog(wxWindow *parent, ArrayView< const SharedPtr< JobNode >> nodes)
SharedPtr< JobNode > getNode() const
Array< std::string > keys
wxString getLabel() const
std::string getKey() const
Object representing a path on a filesystem.
INLINE RawPtr< T > get() const
Variant, an implementation of type-safe union, similar to std::variant or boost::variant.
Interface allowing to enumerate all entries in the settings.
Holds a map of virtual entries, associated with a unique name.
void enumerate(const IEntryProc &proc)
Enumerates all entries stored in the settings.
IVirtualEntry::Value get(const std::string &key) const
Returns a value of an entry.
void set(const std::string &key, const IVirtualEntry::Value &value)
Modifies an existing entry in the settings.
Overload of std::swap for Sph::Array.