diff --git a/Common/Context.h b/Common/Context.h index 66efa9498caf4533f4afa83a9785d2cf0752098c..dd512fd8e4e260f0dc4557628b769752412b5a80 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -223,7 +223,7 @@ class CTX { std::string socketName; std::string name[5], executable[5], remoteLogin[5]; int autoSaveDatabase, autoArchiveOutputFiles, autoMesh, autoMergeFile; - int autoHideNewViews, autoShowLastStep; + int autoHideNewViews, autoShowLastStep, autoCheck; }solver; // print options struct{ diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index 71c5af3ed63072ca334f7bd0b10c5c205be8c4a2..268f1e0fef6f176e4c4fb55e2ea6cdea85e4489c 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -1108,6 +1108,8 @@ StringXNumber SolverOptions_Number[] = { "Always listen to incoming connection requests?" }, { F|O, "AutoArchiveOutputFiles" , opt_solver_auto_archive_output_files , 0. , "Automatically archive output files after each computation" }, + { F|O, "AutoCheck" , opt_solver_auto_check , 1. , + "Automatically check model every time a parameter is changed" }, { F|O, "AutoSaveDatabase" , opt_solver_auto_save_database , 1. , "Automatically save database after each computation" }, { F|O, "AutoMesh" , opt_solver_auto_mesh , 1. , diff --git a/Common/Options.cpp b/Common/Options.cpp index 895d8c5c227a15c1fafb4dacb05b84d4836acf9f..2e0c89481d62ff03df0dba3d977baa01b38308dd 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -5739,6 +5739,13 @@ double opt_solver_auto_archive_output_files(OPT_ARGS_NUM) return CTX::instance()->solver.autoArchiveOutputFiles; } +double opt_solver_auto_check(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX::instance()->solver.autoCheck = (int)val; + return CTX::instance()->solver.autoCheck; +} + double opt_solver_auto_mesh(OPT_ARGS_NUM) { if(action & GMSH_SET) diff --git a/Common/Options.h b/Common/Options.h index 07372c2c6ef7632335137079d49b4f225d2eadf9..7ae91f9465bb672eea62fb54e9a3872206642ba5 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -470,6 +470,7 @@ double opt_solver_timeout(OPT_ARGS_NUM); double opt_solver_plugins(OPT_ARGS_NUM); double opt_solver_auto_save_database(OPT_ARGS_NUM); double opt_solver_auto_archive_output_files(OPT_ARGS_NUM); +double opt_solver_auto_check(OPT_ARGS_NUM); double opt_solver_auto_mesh(OPT_ARGS_NUM); double opt_solver_auto_merge_file(OPT_ARGS_NUM); double opt_solver_auto_hide_new_views(OPT_ARGS_NUM); diff --git a/Common/onelab.h b/Common/onelab.h index ee5460052ce38d383dde2aafdd4ecce3af9571e6..98d24da4609543a6faa92c4954123e0ca521f4e9 100644 --- a/Common/onelab.h +++ b/Common/onelab.h @@ -383,9 +383,10 @@ namespace onelab{ // The string class. A string has a mutable "kind": we do not derive // specialized classes, because the kind should be changeable at runtime // (e.g. from a client-dependent mathematical expression to a table of - // values). Kinds currently recognized by Gmsh are: "file". Possible kinds - // could be "complex", "matrix m n", "hostname", client-dependent mathematical - // expression, onelab mathematical expression (through mathex?), ... + // values). Kinds currently recognized by Gmsh are: "file", "macro". Possible + // kinds could be "complex", "matrix m n", "hostname", client-dependent + // mathematical expression, onelab mathematical expression (through mathex?), + // ... class string : public parameter{ private: std::string _value, _kind; diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp index ff1b71cdfe9c4751b719f7f6ac35770b9c8123bc..62863ca0d8a492c3fe2cf5504e5a36fbe9131377 100644 --- a/Fltk/onelabWindow.cpp +++ b/Fltk/onelabWindow.cpp @@ -600,7 +600,6 @@ void onelab_cb(Fl_Widget *w, void *data) if(action != "initialize") FlGui::instance()->onelab->show(); } - void onelab_option_cb(Fl_Widget *w, void *data) { if(!data) return; @@ -610,6 +609,10 @@ void onelab_option_cb(Fl_Widget *w, void *data) CTX::instance()->solver.autoSaveDatabase = val; else if(what == "archive") CTX::instance()->solver.autoArchiveOutputFiles = val; + else if(what == "check"){ + CTX::instance()->solver.autoCheck = val; + FlGui::instance()->onelab->setButtonVisibility(); + } else if(what == "mesh") CTX::instance()->solver.autoMesh = val; else if(what == "merge") @@ -737,6 +740,8 @@ onelabWindow::onelabWindow(int deltaFontSize) FL_MENU_TOGGLE); _gear->add("Archive output files automatically", 0, onelab_option_cb, (void*)"archive", FL_MENU_TOGGLE); + _gear->add("Check model after each change", 0, onelab_option_cb, (void*)"check", + FL_MENU_TOGGLE); _gear->add("Remesh automatically", 0, onelab_option_cb, (void*)"mesh", FL_MENU_TOGGLE); _gear->add("Merge results automatically", 0, onelab_option_cb, (void*)"merge", @@ -758,6 +763,8 @@ onelabWindow::onelabWindow(int deltaFontSize) (CTX::instance()->solverPosition[0], CTX::instance()->solverPosition[1]); _win->end(); + setButtonVisibility(); + FL_NORMAL_SIZE += _deltaFontSize; } @@ -778,6 +785,15 @@ static bool getFlColor(const std::string &str, Fl_Color &c) return false; } +template<class T> +static void autoCheck(const T &pold, const T &pnew, bool force=false) +{ + if(!CTX::instance()->solver.autoCheck && pnew.getAttribute("AutoCheck") != "1") + return; + if(force || pold.getValue() != pnew.getValue()) + onelab_cb(0, (void*)"check"); +} + template<class T> void onelabWindow::_addParameter(T &p) { @@ -802,8 +818,10 @@ static void onelab_number_check_button_cb(Fl_Widget *w, void *data) onelab::server::instance()->get(numbers, name); if(numbers.size()){ Fl_Check_Button *o = (Fl_Check_Button*)w; + onelab::number old = numbers[0]; numbers[0].setValue(o->value()); onelab::server::instance()->set(numbers[0]); + autoCheck(old, numbers[0]); } } @@ -816,8 +834,10 @@ static void onelab_number_choice_cb(Fl_Widget *w, void *data) if(numbers.size()){ Fl_Choice *o = (Fl_Choice*)w; std::vector<double> choices = numbers[0].getChoices(); + onelab::number old = numbers[0]; if(o->value() < (int)choices.size()) numbers[0].setValue(choices[o->value()]); onelab::server::instance()->set(numbers[0]); + autoCheck(old, numbers[0]); } } @@ -829,6 +849,7 @@ static void onelab_number_input_range_cb(Fl_Widget *w, void *data) onelab::server::instance()->get(numbers, name); if(numbers.size()){ inputRange *o = (inputRange*)w; + onelab::number old = numbers[0]; if(o->doCallbackOnValues()){ numbers[0].setValue(o->value()); numbers[0].setMin(o->minimum()); @@ -841,6 +862,7 @@ static void onelab_number_input_range_cb(Fl_Widget *w, void *data) numbers[0].setAttribute("Graph", o->graph()); onelab::server::instance()->set(numbers[0]); updateGraphs(); + autoCheck(old, numbers[0]); } } @@ -913,6 +935,18 @@ Fl_Widget *onelabWindow::_addParameterWidget(onelab::number &p, Fl_Tree_Item *n, return but; } +static void onelab_string_button_cb(Fl_Widget *w, void *data) +{ + if(!data) return; + std::string name = FlGui::instance()->onelab->getPath((Fl_Tree_Item*)data); + std::vector<onelab::string> strings; + onelab::server::instance()->get(strings, name); + if(strings.size()){ + MergeFile(strings[0].getValue()); + autoCheck(strings[0], strings[0], true); + } +} + static void onelab_string_input_choice_cb(Fl_Widget *w, void *data) { if(!data) return; @@ -921,8 +955,10 @@ static void onelab_string_input_choice_cb(Fl_Widget *w, void *data) onelab::server::instance()->get(strings, name); if(strings.size()){ Fl_Input_Choice *o = (Fl_Input_Choice*)w; + onelab::string old = strings[0]; strings[0].setValue(o->value()); onelab::server::instance()->set(strings[0]); + autoCheck(old, strings[0]); } } @@ -954,6 +990,15 @@ static void onelab_input_choice_file_merge_cb(Fl_Widget *w, void *data) Fl_Widget *onelabWindow::_addParameterWidget(onelab::string &p, Fl_Tree_Item *n, bool highlight, Fl_Color c) { + // macro button + if(p.getKind() == "macro"){ + Fl_Button *but = new Fl_Button(1, 1, _itemWidth, 1); + but->align(FL_ALIGN_INSIDE | FL_ALIGN_CLIP); + but->callback(onelab_string_button_cb, (void*)n); + if(highlight) but->color(c); + return but; + } + // non-editable value if(p.getReadOnly()){ Fl_Output *but = new Fl_Output(1, 1, _itemWidth, 1); @@ -1003,8 +1048,10 @@ static void onelab_region_input_cb(Fl_Widget *w, void *data) onelab::server::instance()->get(regions, name); if(regions.size()){ inputRegion *o = (inputRegion*)w; + onelab::region old = regions[0]; regions[0].setValue(o->value()); onelab::server::instance()->set(regions[0]); + autoCheck(old, regions[0]); } } @@ -1132,6 +1179,23 @@ void onelabWindow::checkForErrors(const std::string &client) } } +void onelabWindow::setButtonVisibility() +{ + if(_butt[0]->visible() && CTX::instance()->solver.autoCheck){ + _butt[0]->hide(); + _gear->position(_gear->x() + _butt[0]->w() + WB, _gear->y()); + _win->init_sizes(); + _win->redraw(); + } + + if(!_butt[0]->visible() && !CTX::instance()->solver.autoCheck){ + _butt[0]->show(); + _gear->position(_gear->x() - _butt[0]->w() - WB, _gear->y()); + _win->init_sizes(); + _win->redraw(); + } +} + void onelabWindow::setButtonMode(const std::string &butt0, const std::string &butt1) { if(butt0 == "check"){ @@ -1186,13 +1250,14 @@ void onelabWindow::rebuildSolverList() // update OneLab window title and gear menu _title = "OneLab"; Fl_Menu_Item* menu = (Fl_Menu_Item*)_gear->menu(); - int values[6] = {CTX::instance()->solver.autoSaveDatabase, + int values[7] = {CTX::instance()->solver.autoSaveDatabase, CTX::instance()->solver.autoArchiveOutputFiles, + CTX::instance()->solver.autoCheck, CTX::instance()->solver.autoMesh, CTX::instance()->solver.autoMergeFile, CTX::instance()->solver.autoHideNewViews, CTX::instance()->solver.autoShowLastStep}; - for(int i = 0; i < 6; i++){ + for(int i = 0; i < 7; i++){ int idx = _gearOptionsStart - 1 + i; if(values[i]) menu[idx].set(); diff --git a/Fltk/onelabWindow.h b/Fltk/onelabWindow.h index 58fcb7f04c4675214df9c48ef5610e5dcf21cbaf..57ecc25e9a985d219087b5aa7f22be3a9d307b60 100644 --- a/Fltk/onelabWindow.h +++ b/Fltk/onelabWindow.h @@ -48,6 +48,7 @@ class onelabWindow{ int h(){ return _win->h(); } void rebuildSolverList(); void rebuildTree(); + void setButtonVisibility(); void setButtonMode(const std::string &butt0, const std::string &butt1); bool isBusy(); void show(){ _win->show(); } diff --git a/demos/indheat.geo b/demos/indheat.geo index d1163445cec1b8415c06b46031727f6d293d151d..399a36c067f8f540f875d27df86db2ade1961495 100644 --- a/demos/indheat.geo +++ b/demos/indheat.geo @@ -10,10 +10,14 @@ DefineConstant ht = {0.4, Label "Tube height"}, rt1 = {0.075, Label "Tube internal radius"}, rt2 = {0.092, Label "Tube external radius"}, - lb = {1, Label "Infinite box width"} + lb = {1, Label "Infinite box width"}, left = {1, Choices{0,1}, Label "Terminals on the left?"} + // macro = {"aa.pos", Label "Run my macro!", Kind "macro", Path "Actions"}, + // showLines = {1, Choices {0,1}, Label "Show lines?"} ]; +//Geometry.Lines = showLines; + // inductor p = newp; Point(p)={0, -r, -hc/2, lc}; @@ -32,8 +36,8 @@ s = news; Plane Surface(s) = {ll}; tmp[] = {s}; vol_coil[] = {}; -For j In {1:4*turns+(left?2:0)} - tmp[] = Extrude { {0,0,hc/turns/4}, {0,0,1} , {0,0,0} , Pi/2} +For j In {1:4*Floor(turns)+(left?2:0)} + tmp[] = Extrude { {0,0,hc/Floor(turns)/4}, {0,0,1} , {0,0,0} , Pi/2} { Surface {tmp[0]}; /*Layers {nn / 4};*/ }; vol_coil[] += tmp[1]; EndFor @@ -143,5 +147,5 @@ Physical Surface(IN) = in; Physical Surface(OUT) = out; Physical Surface(INF) = {s:s+5}; -Homology(2) {{COIL,TUBE},{SKIN_COIL, SKIN_TUBE}}; -Cohomology(1) {{AIR},{}}; +//Homology(2) {{COIL,TUBE},{SKIN_COIL, SKIN_TUBE}}; +//Cohomology(1) {{AIR},{}};