1 // Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include "GmshConfig.h"
7 #if !defined(HAVE_NO_STDINT_H)
8 #include <stdint.h>
9 #elif defined(HAVE_NO_INTPTR_T)
10 typedef unsigned long intptr_t;
11 #endif
12 #include <string.h>
13 #include <FL/Fl.H>
14 #include <FL/Fl_Tabs.H>
15 #include <FL/Fl_Scroll.H>
16 #include <FL/Fl_Color_Chooser.H>
17 #include <FL/fl_ask.H>
18 #include "GmshDefines.h"
19 #include "GmshMessage.h"
20 #include "FlGui.h"
21 #include "inputValue.h"
22 #include "optionWindow.h"
23 #include "gamepadWindow.h"
24 #include "graphicWindow.h"
25 #include "openglWindow.h"
26 #include "paletteWindow.h"
27 #include "manipWindow.h"
28 #include "extraDialogs.h"
29 #include "drawContext.h"
30 #include "Options.h"
31 #include "GModel.h"
32 #include "MElement.h"
33 #include "PView.h"
34 #include "PViewData.h"
35 #include "PViewOptions.h"
36 #include "OS.h"
37 #include "Context.h"
38 #include "StringUtils.h"
39 #include "gmshLocalNetworkClient.h"
40 #if defined(HAVE_TOUCHBAR)
41 #include "touchBar.h"
42 #endif
43 
44 extern StringXColor GeneralOptions_Color[];
45 extern StringXColor GeometryOptions_Color[];
46 extern StringXColor MeshOptions_Color[];
47 extern StringXColor ViewOptions_Color[];
48 
49 static Fl_Menu_Item menu_point_display[] = {{"Color dot", 0, nullptr, nullptr},
50                                             {"3D sphere", 0, nullptr, nullptr},
51                                             {nullptr}};
52 
53 static Fl_Menu_Item menu_point_display_post[] = {
54   {"Color dot", 0, nullptr, nullptr},
55   {"3D sphere", 0, nullptr, nullptr},
56   {"Scaled dot", 0, nullptr, nullptr},
57   {"Scaled sphere", 0, nullptr, nullptr},
58   {nullptr}};
59 
60 static Fl_Menu_Item menu_line_display[] = {
61   {"Color segment", 0, nullptr, nullptr},
62   {"3D cylinder", 0, nullptr, nullptr},
63   {nullptr}};
64 
65 static Fl_Menu_Item menu_line_display_post[] = {
66   {"Color segment", 0, nullptr, nullptr},
67   {"3D cylinder", 0, nullptr, nullptr},
68   {"Tapered cylinder", 0, nullptr, nullptr},
69   {nullptr}};
70 
71 static Fl_Menu_Item menu_surface_display[] = {
72   {"Cross", 0, nullptr, nullptr},
73   {"Wireframe", 0, nullptr, nullptr},
74   {"Solid", 0, nullptr, nullptr},
75   {nullptr}};
76 
77 static Fl_Menu_Item menu_axes_mode[] = {{"None", 0, nullptr, nullptr},
78                                         {"Simple axes", 0, nullptr, nullptr},
79                                         {"Box", 0, nullptr, nullptr},
80                                         {"Full grid", 0, nullptr, nullptr},
81                                         {"Open grid", 0, nullptr, nullptr},
82                                         {"Ruler", 0, nullptr, nullptr},
83                                         {nullptr}};
84 
85 static Fl_Menu_Item menu_position[] = {
86   {"Manual", 0, nullptr, nullptr},
87   {"Automatic", 0, nullptr, nullptr},
88   {"Top left", 0, nullptr, nullptr},
89   {"Top right", 0, nullptr, nullptr},
90   {"Bottom left", 0, nullptr, nullptr},
91   {"Bottom right", 0, nullptr, nullptr},
92   {"Top", 0, nullptr, nullptr},
93   {"Bottom", 0, nullptr, nullptr},
94   {"Left", 0, nullptr, nullptr},
95   {"Right", 0, nullptr, nullptr},
96   {"Full", 0, nullptr, nullptr},
97   {"Top third", 0, nullptr, nullptr},
98   {"In model coordinates", 0, nullptr, nullptr},
99   {nullptr}};
100 
101 Fl_Menu_Item menu_font_names[] = {
102   {"Times-Roman", 0, nullptr, (void *)FL_TIMES},
103   {"Times-Bold", 0, nullptr, (void *)FL_TIMES_BOLD},
104   {"Times-Italic", 0, nullptr, (void *)FL_TIMES_ITALIC},
105   {"Times-BoldItalic", 0, nullptr, (void *)FL_TIMES_BOLD_ITALIC},
106   {"Helvetica", 0, nullptr, (void *)FL_HELVETICA},
107   {"Helvetica-Bold", 0, nullptr, (void *)FL_HELVETICA_BOLD},
108   {"Helvetica-Oblique", 0, nullptr, (void *)FL_HELVETICA_ITALIC},
109   {"Helvetica-BoldOblique", 0, nullptr, (void *)FL_HELVETICA_BOLD_ITALIC},
110   {"Courier", 0, nullptr, (void *)FL_COURIER},
111   {"Courier-Bold", 0, nullptr, (void *)FL_COURIER_BOLD},
112   {"Courier-Oblique", 0, nullptr, (void *)FL_COURIER_ITALIC},
113   {"Courier-BoldOblique", 0, nullptr, (void *)FL_COURIER_BOLD_ITALIC},
114   {"Symbol", 0, nullptr, (void *)FL_SYMBOL},
115   {"ZapfDingbats", 0, nullptr, (void *)FL_ZAPF_DINGBATS},
116   {"Screen", 0, nullptr, (void *)FL_SCREEN},
117   {nullptr}};
118 
color_cb(Fl_Widget * w,void * data)119 static void color_cb(Fl_Widget *w, void *data)
120 {
121   unsigned int (*fct)(int, int, unsigned int);
122   fct = (unsigned int (*)(int, int, unsigned int))data;
123   uchar r = CTX::instance()->unpackRed(fct(0, GMSH_GET, 0));
124   uchar g = CTX::instance()->unpackGreen(fct(0, GMSH_GET, 0));
125   uchar b = CTX::instance()->unpackBlue(fct(0, GMSH_GET, 0));
126   if(fl_color_chooser("Color Chooser", r, g, b))
127     fct(0, GMSH_SET | GMSH_GUI, CTX::instance()->packColor(r, g, b, 255));
128   drawContext::global()->draw();
129 }
130 
view_color_cb(Fl_Widget * w,void * data)131 static void view_color_cb(Fl_Widget *w, void *data)
132 {
133   unsigned int (*fct)(int, int, unsigned int);
134   fct = (unsigned int (*)(int, int, unsigned int))data;
135   uchar r = CTX::instance()->unpackRed(
136     fct(FlGui::instance()->options->view.index, GMSH_GET, 0));
137   uchar g = CTX::instance()->unpackGreen(
138     fct(FlGui::instance()->options->view.index, GMSH_GET, 0));
139   uchar b = CTX::instance()->unpackBlue(
140     fct(FlGui::instance()->options->view.index, GMSH_GET, 0));
141   if(fl_color_chooser("Color Chooser", r, g, b))
142     fct(FlGui::instance()->options->view.index, GMSH_SET | GMSH_GUI,
143         CTX::instance()->packColor(r, g, b, 255));
144   drawContext::global()->draw();
145 }
146 
general_gmpdcf_cb(Fl_Widget * w,void * data)147 void general_gmpdcf_cb(Fl_Widget *w, void *data)
148 {
149   FlGui::instance()->options->gmpdoption = new gamepadWindow;
150   FlGui::instance()->options->gmpdoption->win->show();
151 }
152 
options_cb(Fl_Widget * w,void * data)153 void options_cb(Fl_Widget *w, void *data)
154 {
155   FlGui::instance()->options->win->show();
156 }
157 
options_browser_cb(Fl_Widget * w,void * data)158 static void options_browser_cb(Fl_Widget *w, void *data)
159 {
160   // allows multiple selections with the mouse
161   FlGui::instance()->options->showGroup(
162     FlGui::instance()->options->browser->value(), true, true);
163 }
164 
options_show_file_cb(Fl_Widget * w,void * data)165 static void options_show_file_cb(Fl_Widget *w, void *data)
166 {
167   std::string what((const char *)data);
168   std::string file = CTX::instance()->homeDir;
169   if(what == "session")
170     file += CTX::instance()->sessionFileName;
171   else
172     file += CTX::instance()->optionsFileName;
173   fl_message("File path: %s", file.c_str());
174 }
175 
options_restore_defaults_cb(Fl_Widget * w,void * data)176 void options_restore_defaults_cb(Fl_Widget *w, void *data)
177 {
178   if(fl_choice(
179        "Do you really want to reset all options to their default values?",
180        "Cancel", "Restore", nullptr)) {
181     UnlinkFile(CTX::instance()->homeDir + CTX::instance()->sessionFileName);
182     UnlinkFile(CTX::instance()->homeDir + CTX::instance()->optionsFileName);
183     ReInitOptions(0);
184     InitOptionsGUI(0);
185     FlGui::instance()->rebuildTree(true);
186     drawContext::global()->draw();
187   }
188 }
189 
general_options_cb(Fl_Widget * w,void * data)190 void general_options_cb(Fl_Widget *w, void *data)
191 {
192   FlGui::instance()->options->showGroup(1);
193 }
194 
general_options_color_scheme_cb(Fl_Widget * w,void * data)195 static void general_options_color_scheme_cb(Fl_Widget *w, void *data)
196 {
197   opt_general_color_scheme(
198     0, GMSH_SET, FlGui::instance()->options->general.choice[3]->value());
199   drawContext::global()->draw();
200 }
201 
general_options_rotation_center_select_cb(Fl_Widget * w,void * data)202 void general_options_rotation_center_select_cb(Fl_Widget *w, void *data)
203 {
204   Msg::StatusGl(
205     "Select geometrical entity, mesh element or post-processing view\n"
206     "[Press 'q' to abort]");
207 
208   CTX::instance()->pickElements = 1;
209   CTX::instance()->mesh.changed = ENT_ALL;
210   drawContext::global()->draw();
211   char ib = FlGui::instance()->selectEntity(ENT_ALL);
212   if(ib == 'l') {
213     SPoint3 pc(0., 0., 0.);
214     if(FlGui::instance()->selectedVertices.size())
215       pc.setPosition(FlGui::instance()->selectedVertices[0]->x(),
216                      FlGui::instance()->selectedVertices[0]->y(),
217                      FlGui::instance()->selectedVertices[0]->z());
218     else if(FlGui::instance()->selectedElements.size())
219       pc = FlGui::instance()->selectedElements[0]->barycenter();
220     else if(FlGui::instance()->selectedEdges.size())
221       pc = FlGui::instance()->selectedEdges[0]->bounds().center();
222     else if(FlGui::instance()->selectedFaces.size())
223       pc = FlGui::instance()->selectedFaces[0]->bounds().center();
224     else if(FlGui::instance()->selectedRegions.size())
225       pc = FlGui::instance()->selectedRegions[0]->bounds().center();
226     else if(FlGui::instance()->selectedViews.size() &&
227             FlGui::instance()->selectedViews[0]->getData())
228       pc = FlGui::instance()
229              ->selectedViews[0]
230              ->getData()
231              ->getBoundingBox()
232              .center();
233     opt_general_rotation_center0(0, GMSH_SET | GMSH_GUI, pc.x());
234     opt_general_rotation_center1(0, GMSH_SET | GMSH_GUI, pc.y());
235     opt_general_rotation_center2(0, GMSH_SET | GMSH_GUI, pc.z());
236     drawContext *ctx =
237       FlGui::instance()->getCurrentOpenglWindow()->getDrawContext();
238     ctx->recenterForRotationCenterChange(pc);
239     FlGui::instance()->manip->update();
240   }
241   CTX::instance()->pickElements = 0;
242   CTX::instance()->mesh.changed = ENT_ALL;
243   GModel::current()->setSelection(0);
244   drawContext::global()->draw();
245   Msg::StatusGl("");
246 }
247 
general_options_axes_fit_cb(Fl_Widget * w,void * data)248 void general_options_axes_fit_cb(Fl_Widget *w, void *data)
249 {
250   SBoundingBox3d bbox = GModel::current()->bounds(true);
251   for(std::size_t i = 0; i < PView::list.size(); i++) {
252     if(PView::list[i]->getOptions()->visible &&
253        !PView::list[i]->getData()->getBoundingBox().empty())
254       bbox += PView::list[i]->getData()->getBoundingBox();
255   }
256   if(bbox.empty())
257     bbox = SBoundingBox3d(CTX::instance()->min[0], CTX::instance()->min[1],
258                           CTX::instance()->min[2], CTX::instance()->max[0],
259                           CTX::instance()->max[1], CTX::instance()->max[2]);
260   opt_general_axes_xmin(0, GMSH_SET | GMSH_GUI, bbox.min().x());
261   opt_general_axes_ymin(0, GMSH_SET | GMSH_GUI, bbox.min().y());
262   opt_general_axes_zmin(0, GMSH_SET | GMSH_GUI, bbox.min().z());
263   opt_general_axes_xmax(0, GMSH_SET | GMSH_GUI, bbox.max().x());
264   opt_general_axes_ymax(0, GMSH_SET | GMSH_GUI, bbox.max().y());
265   opt_general_axes_zmax(0, GMSH_SET | GMSH_GUI, bbox.max().z());
266   drawContext::global()->draw();
267 }
268 
general_options_ok_cb(Fl_Widget * w,void * data)269 void general_options_ok_cb(Fl_Widget *w, void *data)
270 {
271   optionWindow *o = FlGui::instance()->options;
272   o->activate((const char *)data);
273 
274   static double lc = 0.;
275   if(lc != CTX::instance()->lc) {
276     lc = CTX::instance()->lc;
277     for(int i = 2; i < 5; i++) {
278       o->general.value[i]->minimum(-5 * CTX::instance()->lc);
279       o->general.value[i]->maximum(5 * CTX::instance()->lc);
280     }
281   }
282   if(data) {
283     const char *name = (const char *)data;
284     if(!strcmp(name, "rotation_center_coord")) {
285       CTX::instance()->drawRotationCenter = 1;
286       SPoint3 p(o->general.value[8]->value(), o->general.value[9]->value(),
287                 o->general.value[10]->value());
288       drawContext *ctx =
289         FlGui::instance()->getCurrentOpenglWindow()->getDrawContext();
290       ctx->recenterForRotationCenterChange(p);
291       FlGui::instance()->manip->update();
292     }
293     else if(!strcmp(name, "rotation_center")) {
294       // pre-fill with cg
295       for(int i = 0; i < 3; i++)
296         o->general.value[8 + i]->value(CTX::instance()->cg[i]);
297       SPoint3 p(CTX::instance()->cg[0], CTX::instance()->cg[1],
298                 CTX::instance()->cg[2]);
299       drawContext *ctx =
300         FlGui::instance()->getCurrentOpenglWindow()->getDrawContext();
301       ctx->recenterForRotationCenterChange(p);
302       FlGui::instance()->manip->update();
303     }
304     else if(!strcmp(name, "light_value")) {
305       double x, y, z;
306       x = o->general.value[2]->value();
307       y = o->general.value[3]->value();
308       z = o->general.value[4]->value();
309       o->general.sphere->setValue(x, y, z);
310     }
311     else if(!strcmp(name, "light_sphere")) {
312       double x, y, z;
313       o->general.sphere->getValue(x, y, z);
314       o->general.value[2]->value(x);
315       o->general.value[3]->value(y);
316       o->general.value[4]->value(z);
317     }
318   }
319 
320   opt_general_axes_auto_position(0, GMSH_SET, o->general.butt[0]->value());
321   opt_general_small_axes(0, GMSH_SET, o->general.butt[1]->value());
322   opt_general_fast_redraw(0, GMSH_SET, o->general.butt[2]->value());
323   opt_general_mouse_hover_meshes(0, GMSH_SET, o->general.butt[11]->value());
324   opt_general_mouse_invert_zoom(0, GMSH_SET, o->general.butt[22]->value());
325   if(opt_general_double_buffer(0, GMSH_GET, 0) != o->general.butt[3]->value())
326     opt_general_double_buffer(0, GMSH_SET, o->general.butt[3]->value());
327   if(opt_general_antialiasing(0, GMSH_GET, 0) != o->general.butt[12]->value())
328     opt_general_antialiasing(0, GMSH_SET, o->general.butt[12]->value());
329   opt_general_trackball(0, GMSH_SET, o->general.butt[5]->value());
330   opt_general_terminal(0, GMSH_SET, o->general.butt[7]->value());
331   double sessionrc = opt_general_session_save(0, GMSH_GET, 0);
332   opt_general_session_save(0, GMSH_SET, o->general.butt[8]->value());
333   if(sessionrc && !opt_general_session_save(0, GMSH_GET, 0))
334     PrintOptions(
335       0, GMSH_SESSIONRC, 1, 1,
336       (CTX::instance()->homeDir + CTX::instance()->sessionFileName).c_str());
337   opt_general_options_save(0, GMSH_SET, o->general.butt[9]->value());
338   opt_general_expert_mode(0, GMSH_SET, o->general.butt[10]->value());
339 #if defined(HAVE_VISUDEV)
340   opt_general_heavy_visualization(0, GMSH_SET, o->general.butt[20]->value());
341 #endif
342 
343   if(opt_general_gui_color_scheme(0, GMSH_GET, 0) !=
344      o->general.butt[21]->value()) {
345     opt_general_gui_color_scheme(0, GMSH_SET, o->general.butt[21]->value());
346     opt_general_color_scheme(0, GMSH_SET | GMSH_GUI,
347                              o->general.butt[21]->value() ? 3. : 1.);
348   }
349 
350   opt_general_tooltips(0, GMSH_SET, o->general.butt[13]->value());
351   opt_general_confirm_overwrite(0, GMSH_SET, o->general.butt[14]->value());
352   opt_general_rotation_center_cg(0, GMSH_SET, o->general.butt[15]->value());
353   opt_general_draw_bounding_box(0, GMSH_SET, o->general.butt[6]->value());
354   opt_general_polygon_offset_always(0, GMSH_SET, o->general.butt[4]->value());
355   opt_general_axes_mikado(0, GMSH_SET, o->general.butt[16]->value());
356 
357   opt_general_shine_exponent(0, GMSH_SET, o->general.value[0]->value());
358   opt_general_shine(0, GMSH_SET, o->general.value[1]->value());
359   opt_general_light00(0, GMSH_SET, o->general.value[2]->value());
360   opt_general_light01(0, GMSH_SET, o->general.value[3]->value());
361   opt_general_light02(0, GMSH_SET, o->general.value[4]->value());
362   opt_general_light03(0, GMSH_SET, o->general.value[13]->value());
363   opt_general_verbosity(0, GMSH_SET, o->general.value[5]->value());
364   opt_general_point_size(0, GMSH_SET, o->general.value[6]->value());
365   opt_general_line_width(0, GMSH_SET, o->general.value[7]->value());
366   opt_general_rotation_center0(0, GMSH_SET, o->general.value[8]->value());
367   opt_general_rotation_center1(0, GMSH_SET, o->general.value[9]->value());
368   opt_general_rotation_center2(0, GMSH_SET, o->general.value[10]->value());
369   opt_general_quadric_subdivisions(0, GMSH_SET, o->general.value[11]->value());
370   opt_general_graphics_fontsize(0, GMSH_SET, o->general.value[12]->value());
371   opt_general_graphics_fontsize_title(0, GMSH_SET,
372                                       o->general.value[28]->value());
373   opt_general_clip_factor(0, GMSH_SET, o->general.value[14]->value());
374   opt_general_polygon_offset_factor(0, GMSH_SET, o->general.value[15]->value());
375   opt_general_polygon_offset_units(0, GMSH_SET, o->general.value[16]->value());
376   opt_general_axes_tics0(0, GMSH_SET, o->general.value[17]->value());
377   opt_general_axes_tics1(0, GMSH_SET, o->general.value[18]->value());
378   opt_general_axes_tics2(0, GMSH_SET, o->general.value[19]->value());
379   opt_general_axes_xmin(0, GMSH_SET, o->general.value[20]->value());
380   opt_general_axes_ymin(0, GMSH_SET, o->general.value[21]->value());
381   opt_general_axes_zmin(0, GMSH_SET, o->general.value[22]->value());
382   opt_general_axes_xmax(0, GMSH_SET, o->general.value[23]->value());
383   opt_general_axes_ymax(0, GMSH_SET, o->general.value[24]->value());
384   opt_general_axes_zmax(0, GMSH_SET, o->general.value[25]->value());
385   opt_general_small_axes_position0(0, GMSH_SET, o->general.value[26]->value());
386   opt_general_small_axes_position1(0, GMSH_SET, o->general.value[27]->value());
387   opt_general_num_threads(0, GMSH_SET, o->general.value[32]->value());
388 
389   opt_general_default_filename(0, GMSH_SET, o->general.input[0]->value());
390   opt_general_editor(0, GMSH_SET, o->general.input[1]->value());
391   opt_general_axes_format0(0, GMSH_SET, o->general.input[3]->value());
392   opt_general_axes_format1(0, GMSH_SET, o->general.input[4]->value());
393   opt_general_axes_format2(0, GMSH_SET, o->general.input[5]->value());
394   opt_general_axes_label0(0, GMSH_SET, o->general.input[6]->value());
395   opt_general_axes_label1(0, GMSH_SET, o->general.input[7]->value());
396   opt_general_axes_label2(0, GMSH_SET, o->general.input[8]->value());
397 
398   opt_general_vector_type(0, GMSH_SET, o->general.choice[0]->value() + 1);
399   opt_general_graphics_font(0, GMSH_SET, o->general.choice[1]->text());
400   opt_general_graphics_font_title(0, GMSH_SET, o->general.choice[6]->text());
401   opt_general_graphics_font_engine(0, GMSH_SET, o->general.choice[7]->text());
402   opt_general_orthographic(0, GMSH_SET, !o->general.choice[2]->value());
403   opt_general_axes(0, GMSH_SET, o->general.choice[4]->value());
404   opt_general_background_gradient(0, GMSH_SET, o->general.choice[5]->value());
405 
406   if((opt_general_gamepad(0, GMSH_GET, 0) != o->general.butt[19]->value()) ||
407      (opt_general_camera_mode(0, GMSH_GET, 0) !=
408       o->general.butt[18]->value())) {
409     if((opt_general_gamepad(0, GMSH_GET, 0) == 1) &&
410        (o->general.butt[18]->value() == 0)) {
411       o->general.butt[19]->value(0);
412     }
413     if((opt_general_camera_mode(0, GMSH_GET, 0) == 0) &&
414        (o->general.butt[19]->value() == 1)) {
415       o->general.butt[18]->value(1);
416     }
417   }
418   opt_general_gamepad(0, GMSH_SET, o->general.butt[19]->value());
419   opt_general_camera_mode(0, GMSH_SET, o->general.butt[18]->value());
420   o->activate((const char *)data);
421 
422   opt_general_eye_sep_ratio(0, GMSH_SET, o->general.value[29]->value());
423   opt_general_focallength_ratio(0, GMSH_SET, o->general.value[30]->value());
424   opt_general_camera_aperture(0, GMSH_SET, o->general.value[31]->value());
425   if(opt_general_stereo_mode(0, GMSH_GET, 0) != o->general.butt[17]->value()) {
426     opt_general_stereo_mode(0, GMSH_SET, o->general.butt[17]->value());
427     for(std::size_t i = 0; i < FlGui::instance()->graph.size(); i++)
428       FlGui::instance()->graph[i]->setStereo((bool)CTX::instance()->stereo);
429   }
430 
431   if(CTX::instance()->fastRedraw)
432     CTX::instance()->post.draw = CTX::instance()->mesh.draw = 0;
433   drawContext::global()->draw();
434   CTX::instance()->post.draw = CTX::instance()->mesh.draw = 1;
435   CTX::instance()->drawRotationCenter = 0;
436 }
437 
general_arrow_param_cb(Fl_Widget * w,void * data)438 static void general_arrow_param_cb(Fl_Widget *w, void *data)
439 {
440   double a = opt_general_arrow_head_radius(0, GMSH_GET, 0);
441   double b = opt_general_arrow_stem_length(0, GMSH_GET, 0);
442   double c = opt_general_arrow_stem_radius(0, GMSH_GET, 0);
443   while(arrowEditor("Arrow Editor", a, b, c)) {
444     opt_general_arrow_head_radius(0, GMSH_SET, a);
445     opt_general_arrow_stem_length(0, GMSH_SET, b);
446     opt_general_arrow_stem_radius(0, GMSH_SET, c);
447     drawContext::global()->draw();
448   }
449 }
450 
geometry_options_cb(Fl_Widget * w,void * data)451 void geometry_options_cb(Fl_Widget *w, void *data)
452 {
453   FlGui::instance()->options->showGroup(2);
454 }
455 
geometry_options_ok_cb(Fl_Widget * w,void * data)456 static void geometry_options_ok_cb(Fl_Widget *w, void *data)
457 {
458   optionWindow *o = FlGui::instance()->options;
459   o->activate((const char *)data);
460 
461   opt_geometry_points(0, GMSH_SET, o->geo.butt[0]->value());
462   opt_geometry_curves(0, GMSH_SET, o->geo.butt[1]->value());
463   opt_geometry_surfaces(0, GMSH_SET, o->geo.butt[2]->value());
464   opt_geometry_volumes(0, GMSH_SET, o->geo.butt[3]->value());
465   opt_geometry_point_labels(0, GMSH_SET, o->geo.butt[4]->value());
466   opt_geometry_curve_labels(0, GMSH_SET, o->geo.butt[5]->value());
467   opt_geometry_surface_labels(0, GMSH_SET, o->geo.butt[6]->value());
468   opt_geometry_volume_labels(0, GMSH_SET, o->geo.butt[7]->value());
469   opt_geometry_auto_coherence(0, GMSH_SET, o->geo.butt[8]->value());
470   opt_geometry_light(0, GMSH_SET, o->geo.butt[9]->value());
471   opt_geometry_highlight_orphans(0, GMSH_SET, o->geo.butt[10]->value());
472 
473   opt_geometry_occ_fix_degenerated(0, GMSH_SET, o->geo.butt[16]->value());
474   opt_geometry_occ_fix_small_edges(0, GMSH_SET, o->geo.butt[11]->value());
475   opt_geometry_occ_fix_small_faces(0, GMSH_SET, o->geo.butt[12]->value());
476   opt_geometry_occ_sew_faces(0, GMSH_SET, o->geo.butt[13]->value());
477   opt_geometry_occ_make_solids(0, GMSH_SET, o->geo.butt[14]->value());
478   opt_geometry_occ_scaling(0, GMSH_SET, o->geo.value[20]->value());
479 
480   opt_geometry_light_two_side(0, GMSH_SET, o->geo.butt[15]->value());
481 
482   opt_geometry_normals(0, GMSH_SET, o->geo.value[0]->value());
483   opt_geometry_tangents(0, GMSH_SET, o->geo.value[1]->value());
484   opt_geometry_tolerance(0, GMSH_SET, o->geo.value[2]->value());
485   opt_geometry_point_size(0, GMSH_SET, o->geo.value[3]->value());
486   opt_geometry_curve_width(0, GMSH_SET, o->geo.value[4]->value());
487   opt_geometry_point_sel_size(0, GMSH_SET, o->geo.value[5]->value());
488   opt_geometry_curve_sel_width(0, GMSH_SET, o->geo.value[6]->value());
489   opt_geometry_transform00(0, GMSH_SET, o->geo.value[7]->value());
490   opt_geometry_transform01(0, GMSH_SET, o->geo.value[8]->value());
491   opt_geometry_transform02(0, GMSH_SET, o->geo.value[9]->value());
492   opt_geometry_transform10(0, GMSH_SET, o->geo.value[11]->value());
493   opt_geometry_transform11(0, GMSH_SET, o->geo.value[12]->value());
494   opt_geometry_transform12(0, GMSH_SET, o->geo.value[13]->value());
495   opt_geometry_transform20(0, GMSH_SET, o->geo.value[15]->value());
496   opt_geometry_transform21(0, GMSH_SET, o->geo.value[16]->value());
497   opt_geometry_transform22(0, GMSH_SET, o->geo.value[17]->value());
498   opt_geometry_offset0(0, GMSH_SET, o->geo.value[10]->value());
499   opt_geometry_offset1(0, GMSH_SET, o->geo.value[14]->value());
500   opt_geometry_offset2(0, GMSH_SET, o->geo.value[18]->value());
501   opt_geometry_num_sub_edges(0, GMSH_SET, o->geo.value[19]->value());
502 
503   opt_geometry_point_type(0, GMSH_SET, o->geo.choice[0]->value());
504   opt_geometry_curve_type(0, GMSH_SET, o->geo.choice[1]->value());
505   opt_geometry_surface_type(0, GMSH_SET, o->geo.choice[2]->value());
506   opt_geometry_transform(0, GMSH_SET, o->geo.choice[3]->value());
507   opt_geometry_label_type(0, GMSH_SET, o->geo.choice[4]->value());
508 
509 #if defined(HAVE_TOUCHBAR)
510   updateTouchBar();
511 #endif
512 
513   if(CTX::instance()->fastRedraw)
514     CTX::instance()->post.draw = CTX::instance()->mesh.draw = 0;
515   drawContext::global()->draw();
516   CTX::instance()->post.draw = CTX::instance()->mesh.draw = 1;
517 }
518 
mesh_options_cb(Fl_Widget * w,void * data)519 void mesh_options_cb(Fl_Widget *w, void *data)
520 {
521   FlGui::instance()->options->showGroup(3);
522 }
523 
mesh_options_ok_cb(Fl_Widget * w,void * data)524 static void mesh_options_ok_cb(Fl_Widget *w, void *data)
525 {
526   optionWindow *o = FlGui::instance()->options;
527   o->activate((const char *)data);
528 
529   opt_mesh_lc_from_curvature(0, GMSH_SET, o->mesh.value[1]->value());
530   opt_mesh_lc_from_points(0, GMSH_SET, o->mesh.butt[5]->value());
531   opt_mesh_lc_from_parametric_points(0, GMSH_SET, o->mesh.butt[26]->value());
532   opt_mesh_lc_extend_from_boundary(0, GMSH_SET, o->mesh.butt[16]->value());
533   opt_mesh_optimize(0, GMSH_SET, o->mesh.butt[2]->value());
534   opt_mesh_optimize_netgen(0, GMSH_SET, o->mesh.butt[24]->value());
535   opt_mesh_order(0, GMSH_SET, o->mesh.value[3]->value());
536   opt_mesh_ho_optimize(0, GMSH_SET, o->mesh.butt[3]->value() ? 2 : 0);
537   opt_mesh_second_order_incomplete(0, GMSH_SET, o->mesh.butt[4]->value());
538   opt_mesh_nodes(0, GMSH_SET, o->mesh.butt[6]->value());
539   opt_mesh_lines(0, GMSH_SET, o->mesh.butt[7]->value());
540   opt_mesh_triangles(0, GMSH_SET, o->mesh.menu->menu()[0].value() ? 1 : 0);
541   opt_mesh_quadrangles(0, GMSH_SET, o->mesh.menu->menu()[1].value() ? 1 : 0);
542   opt_mesh_tetrahedra(0, GMSH_SET, o->mesh.menu->menu()[2].value() ? 1 : 0);
543   opt_mesh_hexahedra(0, GMSH_SET, o->mesh.menu->menu()[3].value() ? 1 : 0);
544   opt_mesh_prisms(0, GMSH_SET, o->mesh.menu->menu()[4].value() ? 1 : 0);
545   opt_mesh_pyramids(0, GMSH_SET, o->mesh.menu->menu()[5].value() ? 1 : 0);
546   opt_mesh_trihedra(0, GMSH_SET, o->mesh.menu->menu()[6].value() ? 1 : 0);
547   opt_mesh_surface_edges(0, GMSH_SET, o->mesh.butt[8]->value());
548   opt_mesh_surface_faces(0, GMSH_SET, o->mesh.butt[9]->value());
549   opt_mesh_volume_edges(0, GMSH_SET, o->mesh.butt[10]->value());
550   opt_mesh_volume_faces(0, GMSH_SET, o->mesh.butt[11]->value());
551   opt_mesh_node_labels(0, GMSH_SET, o->mesh.butt[12]->value());
552   opt_mesh_line_labels(0, GMSH_SET, o->mesh.butt[13]->value());
553   opt_mesh_surface_labels(0, GMSH_SET, o->mesh.butt[14]->value());
554   opt_mesh_volume_labels(0, GMSH_SET, o->mesh.butt[15]->value());
555   opt_mesh_light(0, GMSH_SET, o->mesh.butt[17]->value());
556   opt_mesh_light_two_side(0, GMSH_SET, o->mesh.butt[18]->value());
557   opt_mesh_smooth_normals(0, GMSH_SET, o->mesh.butt[19]->value());
558   opt_mesh_recombine_all(0, GMSH_SET, o->mesh.butt[21]->value());
559 
560   opt_mesh_nb_smoothing(0, GMSH_SET, o->mesh.value[0]->value());
561   opt_mesh_lc_factor(0, GMSH_SET, o->mesh.value[2]->value());
562   opt_mesh_lc_min(0, GMSH_SET, o->mesh.value[25]->value());
563   opt_mesh_lc_max(0, GMSH_SET, o->mesh.value[26]->value());
564   opt_mesh_quality_inf(0, GMSH_SET, o->mesh.value[4]->value());
565   opt_mesh_quality_sup(0, GMSH_SET, o->mesh.value[5]->value());
566   opt_mesh_radius_inf(0, GMSH_SET, o->mesh.value[6]->value());
567   opt_mesh_radius_sup(0, GMSH_SET, o->mesh.value[7]->value());
568   opt_mesh_normals(0, GMSH_SET, o->mesh.value[8]->value());
569   opt_mesh_explode(0, GMSH_SET, o->mesh.value[9]->value());
570   opt_mesh_tangents(0, GMSH_SET, o->mesh.value[13]->value());
571   opt_mesh_num_sub_edges(0, GMSH_SET, o->mesh.value[14]->value());
572   opt_mesh_node_size(0, GMSH_SET, o->mesh.value[10]->value());
573   opt_mesh_line_width(0, GMSH_SET, o->mesh.value[11]->value());
574   opt_mesh_label_sampling(0, GMSH_SET, o->mesh.value[12]->value());
575   opt_mesh_angle_smooth_normals(0, GMSH_SET, o->mesh.value[18]->value());
576 
577   opt_mesh_node_type(0, GMSH_SET, o->mesh.choice[0]->value());
578   opt_mesh_algo2d(0, GMSH_SET,
579                   (o->mesh.choice[2]->value() == 1) ? ALGO_2D_MESHADAPT :
580                   (o->mesh.choice[2]->value() == 2) ? ALGO_2D_DELAUNAY :
581                   (o->mesh.choice[2]->value() == 3) ? ALGO_2D_FRONTAL :
582                   (o->mesh.choice[2]->value() == 4) ? ALGO_2D_BAMG :
583                   (o->mesh.choice[2]->value() == 5) ? ALGO_2D_FRONTAL_QUAD :
584                   (o->mesh.choice[2]->value() == 6) ? ALGO_2D_PACK_PRLGRMS :
585                   (o->mesh.choice[2]->value() == 7) ? ALGO_2D_QUAD_QUASI_STRUCT :
586                   (o->mesh.choice[2]->value() == 8) ? ALGO_2D_INITIAL_ONLY :
587                   ALGO_2D_AUTO);
588   opt_mesh_algo3d(0, GMSH_SET,
589                   (o->mesh.choice[3]->value() == 1) ? ALGO_3D_FRONTAL :
590                   (o->mesh.choice[3]->value() == 2) ? ALGO_3D_HXT :
591                   (o->mesh.choice[3]->value() == 3) ? ALGO_3D_MMG3D :
592                   (o->mesh.choice[3]->value() == 4) ? ALGO_3D_INITIAL_ONLY :
593                                                       ALGO_3D_DELAUNAY);
594   opt_mesh_algo_recombine(0, GMSH_SET, o->mesh.choice[1]->value());
595   opt_mesh_algo_subdivide(0, GMSH_SET, o->mesh.choice[5]->value());
596   opt_mesh_color_carousel(0, GMSH_SET, o->mesh.choice[4]->value());
597   opt_mesh_quality_type(0, GMSH_SET, o->mesh.choice[6]->value());
598   opt_mesh_label_type(0, GMSH_SET, o->mesh.choice[7]->value());
599   opt_mesh_light_lines(0, GMSH_SET, o->mesh.choice[10]->value());
600 
601 #if defined(HAVE_TOUCHBAR)
602   updateTouchBar();
603 #endif
604 
605   if(CTX::instance()->fastRedraw)
606     CTX::instance()->post.draw = CTX::instance()->mesh.draw = 0;
607   drawContext::global()->draw();
608   CTX::instance()->post.draw = CTX::instance()->mesh.draw = 1;
609 }
610 
solver_options_cb(Fl_Widget * w,void * data)611 void solver_options_cb(Fl_Widget *w, void *data)
612 {
613   FlGui::instance()->options->showGroup(4);
614 }
615 
solver_options_ok_cb(Fl_Widget * w,void * data)616 static void solver_options_ok_cb(Fl_Widget *w, void *data)
617 {
618   optionWindow *o = FlGui::instance()->options;
619   o->activate((const char *)data);
620 
621 #if defined(HAVE_ONELAB)
622   int old_listen =
623     (int)opt_solver_listen(0, GMSH_GET, o->solver.butt[0]->value());
624   opt_solver_listen(0, GMSH_SET, o->solver.butt[0]->value());
625   if(!old_listen && o->solver.butt[0]->value()) {
626     auto it = onelab::server::instance()->findClient("Listen");
627     if(it == onelab::server::instance()->lastClient()) {
628       onelab::localNetworkClient *c = new gmshLocalNetworkClient("Listen", "");
629       c->run();
630     }
631     else
632       (*it)->run();
633   }
634 #endif
635 
636   opt_solver_socket_name(0, GMSH_SET, o->solver.input[0]->value());
637   opt_solver_timeout(0, GMSH_SET, o->solver.value[0]->value());
638   opt_solver_python_interpreter(0, GMSH_SET, o->solver.input[1]->value());
639   opt_solver_octave_interpreter(0, GMSH_SET, o->solver.input[2]->value());
640 
641   if(CTX::instance()->fastRedraw)
642     CTX::instance()->post.draw = CTX::instance()->mesh.draw = 0;
643   drawContext::global()->draw();
644   CTX::instance()->post.draw = CTX::instance()->mesh.draw = 1;
645 }
646 
post_options_cb(Fl_Widget * w,void * data)647 void post_options_cb(Fl_Widget *w, void *data)
648 {
649   FlGui::instance()->options->showGroup(5);
650 }
651 
post_options_ok_cb(Fl_Widget * w,void * data)652 static void post_options_ok_cb(Fl_Widget *w, void *data)
653 {
654   optionWindow *o = FlGui::instance()->options;
655   o->activate((const char *)data);
656 
657   opt_post_anim_cycle(0, GMSH_SET, o->post.butt[0]->value());
658   opt_post_combine_remove_orig(0, GMSH_SET, o->post.butt[1]->value());
659   opt_post_horizontal_scales(0, GMSH_SET, o->post.butt[2]->value());
660 
661   opt_post_anim_delay(0, GMSH_SET, o->post.value[0]->value());
662   opt_post_anim_step(0, GMSH_SET, o->post.value[1]->value());
663 
664   opt_post_link(0, GMSH_SET, o->post.choice[0]->value());
665 
666   if(CTX::instance()->fastRedraw)
667     CTX::instance()->post.draw = CTX::instance()->mesh.draw = 0;
668   drawContext::global()->draw();
669   CTX::instance()->post.draw = CTX::instance()->mesh.draw = 1;
670 }
671 
view_options_cb(Fl_Widget * w,void * data)672 void view_options_cb(Fl_Widget *w, void *data)
673 {
674   int num = (intptr_t)data;
675   if(num < 0) { // automatic
676     int current = FlGui::instance()->options->view.index;
677     if(current >= 0 && current < (int)PView::list.size())
678       num = current;
679     else
680       num = 0;
681   }
682   if(num >= 0 && num < (int)PView::list.size())
683     FlGui::instance()->options->showGroup(num + 6);
684 }
685 
view_options_timestep_cb(Fl_Widget * w,void * data)686 static void view_options_timestep_cb(Fl_Widget *w, void *data)
687 {
688   std::string str((const char *)data);
689   for(int i = 0; i < (int)PView::list.size(); i++) {
690     if(i == FlGui::instance()->options->view.index ||
691        FlGui::instance()->options->browser->selected(i + 6)) {
692       if(str == "=")
693         opt_view_timestep(i, GMSH_SET, ((Fl_Value_Input *)w)->value());
694       else if(str == "-")
695         opt_view_timestep(i, GMSH_SET | GMSH_GUI,
696                           opt_view_timestep(i, GMSH_GET, 0) - 1);
697       else if(str == "+")
698         opt_view_timestep(i, GMSH_SET | GMSH_GUI,
699                           opt_view_timestep(i, GMSH_GET, 0) + 1);
700     }
701   }
702   drawContext::global()->draw();
703 }
704 
view_options_ok_cb(Fl_Widget * w,void * data)705 static void view_options_ok_cb(Fl_Widget *w, void *data)
706 {
707   int current = FlGui::instance()->options->view.index;
708 
709   if(current < 0) return;
710 
711   optionWindow *o = FlGui::instance()->options;
712   o->activate((const char *)data);
713 
714   if(data) {
715     std::string str((const char *)data);
716     if(str == "range_min" || str == "range_max") {
717       double vmin = 1e200;
718       double vmax = -1e200;
719       for(int i = 0; i < (int)PView::list.size(); i++) {
720         if(i == current ||
721            FlGui::instance()->options->browser->selected(i + 6)) {
722           // compute min/max taking current visibility status and tensor display
723           // mode into account
724           if(str == "range_min")
725             vmin = std::min(vmin, opt_view_min_visible(i, GMSH_GET, 0));
726           else if(str == "range_max")
727             vmax = std::max(vmax, opt_view_max_visible(i, GMSH_GET, 0));
728         }
729       }
730       if(str == "range_min")
731         o->view.value[31]->value(vmin);
732       else if(str == "range_max")
733         o->view.value[32]->value(vmax);
734     }
735   }
736 
737   int force = (int)opt_post_link(0, GMSH_GET, 0);
738 
739   // get the old values for the current view
740   double scale_type = opt_view_scale_type(current, GMSH_GET, 0);
741   double intervals_type = opt_view_intervals_type(current, GMSH_GET, 0);
742   double point_type = opt_view_point_type(current, GMSH_GET, 0);
743   double line_type = opt_view_line_type(current, GMSH_GET, 0);
744   double vector_type = opt_view_vector_type(current, GMSH_GET, 0);
745   double glyph_location = opt_view_glyph_location(current, GMSH_GET, 0);
746   double tensor_type = opt_view_tensor_type(current, GMSH_GET, 0);
747   double range_type = opt_view_range_type(current, GMSH_GET, 0);
748   double axes = opt_view_axes(current, GMSH_GET, 0);
749   double mikado = opt_view_axes_mikado(current, GMSH_GET, 0);
750   double boundary = opt_view_boundary(current, GMSH_GET, 0);
751   double external_view = opt_view_external_view(current, GMSH_GET, 0);
752   double gen_raise_view = opt_view_gen_raise_view(current, GMSH_GET, 0);
753   double show_time = opt_view_show_time(current, GMSH_GET, 0);
754   double force_num_components =
755     opt_view_force_num_components(current, GMSH_GET, 0);
756   double center_glyphs = opt_view_center_glyphs(current, GMSH_GET, 0);
757 
758   double type = opt_view_type(current, GMSH_GET, 0);
759   double saturate_values = opt_view_saturate_values(current, GMSH_GET, 0);
760   double max_recursion_level =
761     opt_view_max_recursion_level(current, GMSH_GET, 0);
762   double adapt_vis_grid =
763     opt_view_adapt_visualization_grid(current, GMSH_GET, 0);
764   double target_error = opt_view_target_error(current, GMSH_GET, 0);
765   double show_element = opt_view_show_element(current, GMSH_GET, 0);
766   double draw_skin_only = opt_view_draw_skin_only(current, GMSH_GET, 0);
767   double show_scale = opt_view_show_scale(current, GMSH_GET, 0);
768   double auto_position = opt_view_auto_position(current, GMSH_GET, 0);
769   double axes_auto_position = opt_view_axes_auto_position(current, GMSH_GET, 0);
770   double draw_strings = opt_view_draw_strings(current, GMSH_GET, 0);
771   double light = opt_view_light(current, GMSH_GET, 0);
772   double light_two_side = opt_view_light_two_side(current, GMSH_GET, 0);
773   double light_lines = opt_view_light_lines(current, GMSH_GET, 0);
774   double smooth_normals = opt_view_smooth_normals(current, GMSH_GET, 0);
775   double draw_points = opt_view_draw_points(current, GMSH_GET, 0);
776   double draw_lines = opt_view_draw_lines(current, GMSH_GET, 0);
777   double draw_triangles = opt_view_draw_triangles(current, GMSH_GET, 0);
778   double draw_quadrangles = opt_view_draw_quadrangles(current, GMSH_GET, 0);
779   double draw_tetrahedra = opt_view_draw_tetrahedra(current, GMSH_GET, 0);
780   double draw_hexahedra = opt_view_draw_hexahedra(current, GMSH_GET, 0);
781   double draw_prisms = opt_view_draw_prisms(current, GMSH_GET, 0);
782   double draw_pyramids = opt_view_draw_pyramids(current, GMSH_GET, 0);
783   double draw_scalars = opt_view_draw_scalars(current, GMSH_GET, 0);
784   double draw_vectors = opt_view_draw_vectors(current, GMSH_GET, 0);
785   double draw_tensors = opt_view_draw_tensors(current, GMSH_GET, 0);
786   double use_gen_raise = opt_view_use_gen_raise(current, GMSH_GET, 0);
787   double fake_transparency = opt_view_fake_transparency(current, GMSH_GET, 0);
788   double use_stipple = opt_view_use_stipple(current, GMSH_GET, 0);
789 
790   double normals = opt_view_normals(current, GMSH_GET, 0);
791   double tangents = opt_view_tangents(current, GMSH_GET, 0);
792   double custom_min = opt_view_custom_min(current, GMSH_GET, 0);
793   double custom_max = opt_view_custom_max(current, GMSH_GET, 0);
794   double nb_iso = opt_view_nb_iso(current, GMSH_GET, 0);
795   double offset0 = opt_view_offset0(current, GMSH_GET, 0);
796   double offset1 = opt_view_offset1(current, GMSH_GET, 0);
797   double offset2 = opt_view_offset2(current, GMSH_GET, 0);
798   double transform00 = opt_view_transform00(current, GMSH_GET, 0);
799   double transform01 = opt_view_transform01(current, GMSH_GET, 0);
800   double transform02 = opt_view_transform02(current, GMSH_GET, 0);
801   double transform10 = opt_view_transform10(current, GMSH_GET, 0);
802   double transform11 = opt_view_transform11(current, GMSH_GET, 0);
803   double transform12 = opt_view_transform12(current, GMSH_GET, 0);
804   double transform20 = opt_view_transform20(current, GMSH_GET, 0);
805   double transform21 = opt_view_transform21(current, GMSH_GET, 0);
806   double transform22 = opt_view_transform22(current, GMSH_GET, 0);
807   double raise0 = opt_view_raise0(current, GMSH_GET, 0);
808   double raise1 = opt_view_raise1(current, GMSH_GET, 0);
809   double raise2 = opt_view_raise2(current, GMSH_GET, 0);
810   double normal_raise = opt_view_normal_raise(current, GMSH_GET, 0);
811   double timestep = opt_view_timestep(current, GMSH_GET, 0);
812   double arrow_size_min = opt_view_arrow_size_min(current, GMSH_GET, 0);
813   double arrow_size_max = opt_view_arrow_size_max(current, GMSH_GET, 0);
814   double displacement_factor =
815     opt_view_displacement_factor(current, GMSH_GET, 0);
816   double point_size = opt_view_point_size(current, GMSH_GET, 0);
817   double line_width = opt_view_line_width(current, GMSH_GET, 0);
818   double explode = opt_view_explode(current, GMSH_GET, 0);
819   double angle_smooth_normals =
820     opt_view_angle_smooth_normals(current, GMSH_GET, 0);
821   double position0 = opt_view_position0(current, GMSH_GET, 0);
822   double position1 = opt_view_position1(current, GMSH_GET, 0);
823   double size0 = opt_view_size0(current, GMSH_GET, 0);
824   double size1 = opt_view_size1(current, GMSH_GET, 0);
825   double axes_tics0 = opt_view_axes_tics0(current, GMSH_GET, 0);
826   double axes_tics1 = opt_view_axes_tics1(current, GMSH_GET, 0);
827   double axes_tics2 = opt_view_axes_tics2(current, GMSH_GET, 0);
828   double axes_xmin = opt_view_axes_xmin(current, GMSH_GET, 0);
829   double axes_ymin = opt_view_axes_ymin(current, GMSH_GET, 0);
830   double axes_zmin = opt_view_axes_zmin(current, GMSH_GET, 0);
831   double axes_xmax = opt_view_axes_xmax(current, GMSH_GET, 0);
832   double axes_ymax = opt_view_axes_ymax(current, GMSH_GET, 0);
833   double axes_zmax = opt_view_axes_zmax(current, GMSH_GET, 0);
834   double gen_raise_factor = opt_view_gen_raise_factor(current, GMSH_GET, 0);
835   double component_map0 = opt_view_component_map0(current, GMSH_GET, 0);
836   double component_map1 = opt_view_component_map1(current, GMSH_GET, 0);
837   double component_map2 = opt_view_component_map2(current, GMSH_GET, 0);
838   double component_map3 = opt_view_component_map3(current, GMSH_GET, 0);
839   double component_map4 = opt_view_component_map4(current, GMSH_GET, 0);
840   double component_map5 = opt_view_component_map5(current, GMSH_GET, 0);
841   double component_map6 = opt_view_component_map6(current, GMSH_GET, 0);
842   double component_map7 = opt_view_component_map7(current, GMSH_GET, 0);
843   double component_map8 = opt_view_component_map8(current, GMSH_GET, 0);
844   double sampling = opt_view_sampling(current, GMSH_GET, 0);
845 
846   std::string name = opt_view_name(current, GMSH_GET, "");
847   std::string format = opt_view_format(current, GMSH_GET, "");
848   std::string axes_label0 = opt_view_axes_label0(current, GMSH_GET, "");
849   std::string axes_label1 = opt_view_axes_label1(current, GMSH_GET, "");
850   std::string axes_label2 = opt_view_axes_label2(current, GMSH_GET, "");
851   std::string axes_format0 = opt_view_axes_format0(current, GMSH_GET, "");
852   std::string axes_format1 = opt_view_axes_format1(current, GMSH_GET, "");
853   std::string axes_format2 = opt_view_axes_format2(current, GMSH_GET, "");
854   std::string gen_raise0 = opt_view_gen_raise0(current, GMSH_GET, "");
855   std::string gen_raise1 = opt_view_gen_raise1(current, GMSH_GET, "");
856   std::string gen_raise2 = opt_view_gen_raise2(current, GMSH_GET, "");
857 
858   // modify only the views that need to be updated
859   for(int i = 0; i < (int)PView::list.size(); i++) {
860     if(i == current || FlGui::instance()->options->browser->selected(i + 6)) {
861       double val;
862 
863       // view_choice
864 
865       val = o->view.choice[1]->value() + 1;
866       if(force || (val != scale_type)) opt_view_scale_type(i, GMSH_SET, val);
867 
868       val = o->view.choice[0]->value() + 1;
869       if(force || (val != intervals_type))
870         opt_view_intervals_type(i, GMSH_SET, val);
871 
872       val = o->view.choice[5]->value();
873       if(force || (val != point_type)) opt_view_point_type(i, GMSH_SET, val);
874 
875       val = o->view.choice[6]->value();
876       if(force || (val != line_type)) opt_view_line_type(i, GMSH_SET, val);
877 
878       val = o->view.choice[2]->value() + 1;
879       if(force || (val != vector_type)) opt_view_vector_type(i, GMSH_SET, val);
880 
881       val = o->view.choice[3]->value() + 1;
882       if(force || (val != glyph_location))
883         opt_view_glyph_location(i, GMSH_SET, val);
884 
885       val = o->view.choice[4]->value() + 1;
886       if(force || (val != tensor_type)) opt_view_tensor_type(i, GMSH_SET, val);
887 
888       val = o->view.choice[7]->value() + 1;
889       if(force || (val != range_type)) opt_view_range_type(i, GMSH_SET, val);
890 
891       val = o->view.choice[8]->value();
892       if(force || (val != axes)) opt_view_axes(i, GMSH_SET, val);
893 
894       val = o->view.choice[9]->value();
895       if(force || (val != boundary)) opt_view_boundary(i, GMSH_SET, val);
896 
897       val = o->view.choice[10]->value() - 1;
898       if(force || (val != external_view))
899         opt_view_external_view(i, GMSH_SET, val);
900 
901       val = o->view.choice[11]->value() - 1;
902       if(force || (val != gen_raise_view))
903         opt_view_gen_raise_view(i, GMSH_SET, val);
904 
905       val = o->view.choice[12]->value();
906       if(force || (val != show_time)) opt_view_show_time(i, GMSH_SET, val);
907 
908       val = o->view.choice[13]->value() + 1;
909       if(force || (val != type)) opt_view_type(i, GMSH_SET, val);
910 
911       val = (o->view.choice[14]->value() == 1) ? 1 :
912             (o->view.choice[14]->value() == 2) ? 3 :
913             (o->view.choice[14]->value() == 3) ? 9 :
914                                                  0;
915       if(force || (val != force_num_components))
916         opt_view_force_num_components(i, GMSH_SET, val);
917 
918       val = o->view.choice[15]->value();
919       if(force || (val != center_glyphs))
920         opt_view_center_glyphs(i, GMSH_SET, val);
921 
922       val = o->view.choice[16]->value();
923       if(force || (val != auto_position))
924         opt_view_auto_position(i, GMSH_SET, val);
925 
926       // view_butts
927 
928       val = o->view.butt[0]->value();
929       if(force || (val != adapt_vis_grid))
930         opt_view_adapt_visualization_grid(i, GMSH_SET, val);
931 
932       val = o->view.butt[38]->value();
933       if(force || (val != saturate_values))
934         opt_view_saturate_values(i, GMSH_SET, val);
935 
936       val = o->view.butt[10]->value();
937       if(force || (val != show_element))
938         opt_view_show_element(i, GMSH_SET, val);
939 
940       val = o->view.butt[2]->value();
941       if(force || (val != draw_skin_only))
942         opt_view_draw_skin_only(i, GMSH_SET, val);
943 
944       val = o->view.butt[4]->value();
945       if(force || (val != show_scale)) opt_view_show_scale(i, GMSH_SET, val);
946 
947       val = o->view.butt[3]->value();
948       if(force || (val != mikado)) opt_view_axes_mikado(i, GMSH_SET, val);
949 
950       val = o->view.butt[25]->value();
951       if(force || (val != axes_auto_position))
952         opt_view_axes_auto_position(i, GMSH_SET, val);
953 
954       val = o->view.butt[5]->value();
955       if(force || (val != draw_strings))
956         opt_view_draw_strings(i, GMSH_SET, val);
957 
958       val = o->view.butt[11]->value();
959       if(force || (val != light)) opt_view_light(i, GMSH_SET, val);
960 
961       val = o->view.butt[8]->value();
962       if(force || (val != light_lines)) opt_view_light_lines(i, GMSH_SET, val);
963 
964       val = o->view.butt[9]->value();
965       if(force || (val != light_two_side))
966         opt_view_light_two_side(i, GMSH_SET, val);
967 
968       val = o->view.butt[12]->value();
969       if(force || (val != smooth_normals))
970         opt_view_smooth_normals(i, GMSH_SET, val);
971 
972       val = o->view.menu[0]->menu()[0].value() ? 1 : 0;
973       if(force || (val != draw_scalars))
974         opt_view_draw_scalars(i, GMSH_SET, val);
975 
976       val = o->view.menu[0]->menu()[1].value() ? 1 : 0;
977       if(force || (val != draw_vectors))
978         opt_view_draw_vectors(i, GMSH_SET, val);
979 
980       val = o->view.menu[0]->menu()[2].value() ? 1 : 0;
981       if(force || (val != draw_tensors))
982         opt_view_draw_tensors(i, GMSH_SET, val);
983 
984       val = o->view.menu[1]->menu()[0].value() ? 1 : 0;
985       if(force || (val != draw_points)) opt_view_draw_points(i, GMSH_SET, val);
986 
987       val = o->view.menu[1]->menu()[1].value() ? 1 : 0;
988       if(force || (val != draw_lines)) opt_view_draw_lines(i, GMSH_SET, val);
989 
990       val = o->view.menu[1]->menu()[2].value() ? 1 : 0;
991       if(force || (val != draw_triangles))
992         opt_view_draw_triangles(i, GMSH_SET, val);
993 
994       val = o->view.menu[1]->menu()[3].value() ? 1 : 0;
995       if(force || (val != draw_quadrangles))
996         opt_view_draw_quadrangles(i, GMSH_SET, val);
997 
998       val = o->view.menu[1]->menu()[4].value() ? 1 : 0;
999       if(force || (val != draw_tetrahedra))
1000         opt_view_draw_tetrahedra(i, GMSH_SET, val);
1001 
1002       val = o->view.menu[1]->menu()[5].value() ? 1 : 0;
1003       if(force || (val != draw_hexahedra))
1004         opt_view_draw_hexahedra(i, GMSH_SET, val);
1005 
1006       val = o->view.menu[1]->menu()[6].value() ? 1 : 0;
1007       if(force || (val != draw_prisms)) opt_view_draw_prisms(i, GMSH_SET, val);
1008 
1009       val = o->view.menu[1]->menu()[7].value() ? 1 : 0;
1010       if(force || (val != draw_pyramids))
1011         opt_view_draw_pyramids(i, GMSH_SET, val);
1012 
1013       val = o->view.butt[6]->value();
1014       if(force || (val != use_gen_raise))
1015         opt_view_use_gen_raise(i, GMSH_SET, val);
1016 
1017       val = o->view.butt[24]->value();
1018       if(force || (val != fake_transparency))
1019         opt_view_fake_transparency(i, GMSH_SET, val);
1020 
1021       val = o->view.butt[26]->value();
1022       if(force || (val != use_stipple)) opt_view_use_stipple(i, GMSH_SET, val);
1023 
1024       // view_values
1025 
1026       val = o->view.value[0]->value();
1027       if(force || (val != normals)) opt_view_normals(i, GMSH_SET, val);
1028 
1029       val = o->view.value[1]->value();
1030       if(force || (val != tangents)) opt_view_tangents(i, GMSH_SET, val);
1031 
1032       val = o->view.value[31]->value();
1033       if(force || (val != custom_min)) opt_view_custom_min(i, GMSH_SET, val);
1034 
1035       val = o->view.value[32]->value();
1036       if(force || (val != custom_max)) opt_view_custom_max(i, GMSH_SET, val);
1037 
1038       val = o->view.value[33]->value();
1039       if(force || (val != max_recursion_level))
1040         opt_view_max_recursion_level(i, GMSH_SET, val);
1041 
1042       val = o->view.value[34]->value();
1043       if(force || (val != target_error))
1044         opt_view_target_error(i, GMSH_SET, val);
1045 
1046       val = o->view.value[30]->value();
1047       if(force || (val != nb_iso)) opt_view_nb_iso(i, GMSH_SET, val);
1048 
1049       val = o->view.value[40]->value();
1050       if(force || (val != offset0)) opt_view_offset0(i, GMSH_SET, val);
1051 
1052       val = o->view.value[41]->value();
1053       if(force || (val != offset1)) opt_view_offset1(i, GMSH_SET, val);
1054 
1055       val = o->view.value[42]->value();
1056       if(force || (val != offset2)) opt_view_offset2(i, GMSH_SET, val);
1057 
1058       val = o->view.value[51]->value();
1059       if(force || (val != transform00)) opt_view_transform00(i, GMSH_SET, val);
1060 
1061       val = o->view.value[52]->value();
1062       if(force || (val != transform01)) opt_view_transform01(i, GMSH_SET, val);
1063 
1064       val = o->view.value[53]->value();
1065       if(force || (val != transform02)) opt_view_transform02(i, GMSH_SET, val);
1066 
1067       val = o->view.value[54]->value();
1068       if(force || (val != transform10)) opt_view_transform10(i, GMSH_SET, val);
1069 
1070       val = o->view.value[55]->value();
1071       if(force || (val != transform11)) opt_view_transform11(i, GMSH_SET, val);
1072 
1073       val = o->view.value[56]->value();
1074       if(force || (val != transform12)) opt_view_transform12(i, GMSH_SET, val);
1075 
1076       val = o->view.value[57]->value();
1077       if(force || (val != transform20)) opt_view_transform20(i, GMSH_SET, val);
1078 
1079       val = o->view.value[58]->value();
1080       if(force || (val != transform21)) opt_view_transform21(i, GMSH_SET, val);
1081 
1082       val = o->view.value[59]->value();
1083       if(force || (val != transform22)) opt_view_transform22(i, GMSH_SET, val);
1084 
1085       val = o->view.value[43]->value();
1086       if(force || (val != raise0)) opt_view_raise0(i, GMSH_SET, val);
1087 
1088       val = o->view.value[44]->value();
1089       if(force || (val != raise1)) opt_view_raise1(i, GMSH_SET, val);
1090 
1091       val = o->view.value[45]->value();
1092       if(force || (val != raise2)) opt_view_raise2(i, GMSH_SET, val);
1093 
1094       val = o->view.value[46]->value();
1095       if(force || (val != normal_raise))
1096         opt_view_normal_raise(i, GMSH_SET, val);
1097 
1098       val = o->view.value[50]->value();
1099       if(force || (val != timestep)) opt_view_timestep(i, GMSH_SET, val);
1100 
1101       val = o->view.value[64]->value();
1102       if(force || (val != arrow_size_min))
1103         opt_view_arrow_size_min(i, GMSH_SET, val);
1104 
1105       val = o->view.value[60]->value();
1106       if(force || (val != arrow_size_max))
1107         opt_view_arrow_size_max(i, GMSH_SET, val);
1108 
1109       val = o->view.value[63]->value();
1110       if(force || (val != displacement_factor))
1111         opt_view_displacement_factor(i, GMSH_SET, val);
1112 
1113       val = o->view.value[61]->value();
1114       if(force || (val != point_size)) opt_view_point_size(i, GMSH_SET, val);
1115 
1116       val = o->view.value[62]->value();
1117       if(force || (val != line_width)) opt_view_line_width(i, GMSH_SET, val);
1118 
1119       val = o->view.value[12]->value();
1120       if(force || (val != explode)) opt_view_explode(i, GMSH_SET, val);
1121 
1122       val = o->view.value[10]->value();
1123       if(force || (val != angle_smooth_normals))
1124         opt_view_angle_smooth_normals(i, GMSH_SET, val);
1125 
1126       val = o->view.value[20]->value();
1127       if(force || (val != position0)) opt_view_position0(i, GMSH_SET, val);
1128 
1129       val = o->view.value[21]->value();
1130       if(force || (val != position1)) opt_view_position1(i, GMSH_SET, val);
1131 
1132       val = o->view.value[22]->value();
1133       if(force || (val != size0)) opt_view_size0(i, GMSH_SET, val);
1134 
1135       val = o->view.value[23]->value();
1136       if(force || (val != size1)) opt_view_size1(i, GMSH_SET, val);
1137 
1138       val = o->view.value[13]->value();
1139       if(force || (val != axes_xmin)) opt_view_axes_xmin(i, GMSH_SET, val);
1140 
1141       val = o->view.value[14]->value();
1142       if(force || (val != axes_ymin)) opt_view_axes_ymin(i, GMSH_SET, val);
1143 
1144       val = o->view.value[15]->value();
1145       if(force || (val != axes_zmin)) opt_view_axes_zmin(i, GMSH_SET, val);
1146 
1147       val = o->view.value[16]->value();
1148       if(force || (val != axes_xmax)) opt_view_axes_xmax(i, GMSH_SET, val);
1149 
1150       val = o->view.value[17]->value();
1151       if(force || (val != axes_ymax)) opt_view_axes_ymax(i, GMSH_SET, val);
1152 
1153       val = o->view.value[18]->value();
1154       if(force || (val != axes_zmax)) opt_view_axes_zmax(i, GMSH_SET, val);
1155 
1156       val = o->view.value[2]->value();
1157       if(force || (val != gen_raise_factor))
1158         opt_view_gen_raise_factor(i, GMSH_SET, val);
1159 
1160       val = o->view.value[3]->value();
1161       if(force || (val != axes_tics0)) opt_view_axes_tics0(i, GMSH_SET, val);
1162 
1163       val = o->view.value[4]->value();
1164       if(force || (val != axes_tics1)) opt_view_axes_tics1(i, GMSH_SET, val);
1165 
1166       val = o->view.value[5]->value();
1167       if(force || (val != axes_tics2)) opt_view_axes_tics2(i, GMSH_SET, val);
1168 
1169       val = o->view.value[70]->value();
1170       if(force || (val != component_map0))
1171         opt_view_component_map0(i, GMSH_SET, val);
1172 
1173       val = o->view.value[70]->value();
1174       if(force || (val != component_map0))
1175         opt_view_component_map0(i, GMSH_SET, val);
1176 
1177       val = o->view.value[70]->value();
1178       if(force || (val != component_map0))
1179         opt_view_component_map0(i, GMSH_SET, val);
1180 
1181       val = o->view.value[71]->value();
1182       if(force || (val != component_map1))
1183         opt_view_component_map1(i, GMSH_SET, val);
1184 
1185       val = o->view.value[72]->value();
1186       if(force || (val != component_map2))
1187         opt_view_component_map2(i, GMSH_SET, val);
1188 
1189       val = o->view.value[73]->value();
1190       if(force || (val != component_map3))
1191         opt_view_component_map3(i, GMSH_SET, val);
1192 
1193       val = o->view.value[74]->value();
1194       if(force || (val != component_map4))
1195         opt_view_component_map4(i, GMSH_SET, val);
1196 
1197       val = o->view.value[75]->value();
1198       if(force || (val != component_map5))
1199         opt_view_component_map5(i, GMSH_SET, val);
1200 
1201       val = o->view.value[76]->value();
1202       if(force || (val != component_map6))
1203         opt_view_component_map6(i, GMSH_SET, val);
1204 
1205       val = o->view.value[77]->value();
1206       if(force || (val != component_map7))
1207         opt_view_component_map7(i, GMSH_SET, val);
1208 
1209       val = o->view.value[78]->value();
1210       if(force || (val != component_map8))
1211         opt_view_component_map8(i, GMSH_SET, val);
1212 
1213       val = o->view.value[6]->value();
1214       if(force || (val != sampling)) opt_view_sampling(i, GMSH_SET, val);
1215 
1216       // view_inputs
1217 
1218       std::string str;
1219 
1220       str = o->view.input[0]->value();
1221       if(force || (str != name)) opt_view_name(i, GMSH_SET, str);
1222 
1223       str = o->view.input[1]->value();
1224       if(force || (str != format)) opt_view_format(i, GMSH_SET, str);
1225 
1226       str = o->view.input[10]->value();
1227       if(force || (str != axes_label0)) opt_view_axes_label0(i, GMSH_SET, str);
1228 
1229       str = o->view.input[11]->value();
1230       if(force || (str != axes_label1)) opt_view_axes_label1(i, GMSH_SET, str);
1231 
1232       str = o->view.input[12]->value();
1233       if(force || (str != axes_label2)) opt_view_axes_label2(i, GMSH_SET, str);
1234 
1235       str = o->view.input[7]->value();
1236       if(force || (str != axes_format0))
1237         opt_view_axes_format0(i, GMSH_SET, str);
1238 
1239       str = o->view.input[8]->value();
1240       if(force || (str != axes_format1))
1241         opt_view_axes_format1(i, GMSH_SET, str);
1242 
1243       str = o->view.input[9]->value();
1244       if(force || (str != axes_format2))
1245         opt_view_axes_format2(i, GMSH_SET, str);
1246 
1247       str = o->view.input[4]->value();
1248       if(force || (str != gen_raise0)) opt_view_gen_raise0(i, GMSH_SET, str);
1249 
1250       str = o->view.input[5]->value();
1251       if(force || (str != gen_raise1)) opt_view_gen_raise1(i, GMSH_SET, str);
1252 
1253       str = o->view.input[6]->value();
1254       if(force || (str != gen_raise2)) opt_view_gen_raise2(i, GMSH_SET, str);
1255 
1256       // colors (since the color buttons modify the values directly
1257       // through callbacks, we can use the opt_XXX routines directly)
1258       if(force || (i != current)) {
1259         opt_view_color_points(i, GMSH_SET,
1260                               opt_view_color_points(current, GMSH_GET, 0));
1261         opt_view_color_lines(i, GMSH_SET,
1262                              opt_view_color_lines(current, GMSH_GET, 0));
1263         opt_view_color_triangles(
1264           i, GMSH_SET, opt_view_color_triangles(current, GMSH_GET, 0));
1265         opt_view_color_quadrangles(
1266           i, GMSH_SET, opt_view_color_quadrangles(current, GMSH_GET, 0));
1267         opt_view_color_tetrahedra(
1268           i, GMSH_SET, opt_view_color_tetrahedra(current, GMSH_GET, 0));
1269         opt_view_color_hexahedra(
1270           i, GMSH_SET, opt_view_color_hexahedra(current, GMSH_GET, 0));
1271         opt_view_color_prisms(i, GMSH_SET,
1272                               opt_view_color_prisms(current, GMSH_GET, 0));
1273         opt_view_color_pyramids(i, GMSH_SET,
1274                                 opt_view_color_pyramids(current, GMSH_GET, 0));
1275         opt_view_color_trihedra(i, GMSH_SET,
1276                                 opt_view_color_trihedra(current, GMSH_GET, 0));
1277         opt_view_color_tangents(i, GMSH_SET,
1278                                 opt_view_color_tangents(current, GMSH_GET, 0));
1279         opt_view_color_normals(i, GMSH_SET,
1280                                opt_view_color_normals(current, GMSH_GET, 0));
1281         opt_view_color_text2d(i, GMSH_SET,
1282                               opt_view_color_text2d(current, GMSH_GET, 0));
1283         opt_view_color_text3d(i, GMSH_SET,
1284                               opt_view_color_text3d(current, GMSH_GET, 0));
1285         opt_view_color_axes(i, GMSH_SET,
1286                             opt_view_color_axes(current, GMSH_GET, 0));
1287         opt_view_color_background2d(
1288           i, GMSH_SET, opt_view_color_background2d(current, GMSH_GET, 0));
1289       }
1290 
1291       // colorbar window
1292 
1293       if(force || (i != current)) {
1294         ColorTable_Copy(&PView::list[current]->getOptions()->colorTable);
1295         ColorTable_Paste(&PView::list[i]->getOptions()->colorTable);
1296         PView::list[i]->setChanged(true);
1297       }
1298     }
1299   }
1300 
1301 #if defined(HAVE_TOUCHBAR)
1302   updateTouchBar();
1303 #endif
1304 
1305   if(CTX::instance()->fastRedraw)
1306     CTX::instance()->post.draw = CTX::instance()->mesh.draw = 0;
1307   drawContext::global()->draw();
1308   CTX::instance()->post.draw = CTX::instance()->mesh.draw = 1;
1309 }
1310 
view_options_max_recursion_cb(Fl_Widget * w,void * data)1311 static void view_options_max_recursion_cb(Fl_Widget *w, void *data)
1312 {
1313   std::string str((const char *)data);
1314   int val = (int)FlGui::instance()->options->view.value[33]->value();
1315   if(str == "-" && val > 0)
1316     FlGui::instance()->options->view.value[33]->value(val - 1);
1317   else if(str == "+")
1318     FlGui::instance()->options->view.value[33]->value(val + 1);
1319   view_options_ok_cb(nullptr, nullptr);
1320 }
1321 
optionWindow(int deltaFontSize)1322 optionWindow::optionWindow(int deltaFontSize)
1323 {
1324   general.butt.resize(50, nullptr);
1325   general.push.resize(50, nullptr);
1326   general.value.resize(50, nullptr);
1327   general.color.resize(50, nullptr);
1328   general.input.resize(50, nullptr);
1329   general.choice.resize(50, nullptr);
1330   geo.butt.resize(50, nullptr);
1331   geo.value.resize(50, nullptr);
1332   geo.color.resize(50, nullptr);
1333   geo.choice.resize(50, nullptr);
1334   mesh.butt.resize(50, nullptr);
1335   mesh.retbutt.resize(50, nullptr);
1336   mesh.input.resize(50, nullptr);
1337   mesh.value.resize(50, nullptr);
1338   mesh.color.resize(50, nullptr);
1339   mesh.choice.resize(50, nullptr);
1340   solver.butt.resize(50, nullptr);
1341   solver.value.resize(50, nullptr);
1342   solver.input.resize(50, nullptr);
1343   post.butt.resize(50, nullptr);
1344   post.value.resize(50, nullptr);
1345   post.choice.resize(50, nullptr);
1346   view.butt.resize(50, nullptr);
1347   view.value.resize(100, nullptr);
1348   view.input.resize(50, nullptr);
1349   view.push.resize(50, nullptr);
1350   view.choice.resize(50, nullptr);
1351   view.color.resize(50, nullptr);
1352   view.label.resize(50, nullptr);
1353   view.menu.resize(50, nullptr);
1354 
1355   FL_NORMAL_SIZE -= deltaFontSize;
1356 
1357   int width = 37 * FL_NORMAL_SIZE + WB;
1358   int height = 12 * BH + 4 * WB;
1359   int L = 7 * FL_NORMAL_SIZE;
1360 
1361   win = new paletteWindow(width, height,
1362                           CTX::instance()->nonModalWindows ? true : false);
1363   win->box(GMSH_WINDOW_BOX);
1364   win->label("Options - General");
1365 
1366   // Selection browser
1367   browser = new Fl_Multi_Browser(0, 0, L, height);
1368   browser->box(GMSH_SIMPLE_RIGHT_BOX);
1369   browser->has_scrollbar(Fl_Browser_::VERTICAL);
1370   browser->add("General");
1371   browser->add("Geometry");
1372   browser->add("Mesh");
1373   browser->add("Solver");
1374   browser->add("Post-pro");
1375   browser->callback(options_browser_cb);
1376   browser->value(1);
1377 
1378   redraw = new Fl_Return_Button(WB, height - BH - WB, L - WB, BH, "Redraw");
1379   redraw->callback(redraw_cb);
1380 
1381   width -= L;
1382   int BW = width - 4 * WB;
1383 
1384   // General options
1385   general.group = new Fl_Group(L, 0, width, height, "General Options");
1386   {
1387     Fl_Tabs *o = new Fl_Tabs(L + WB, WB, width - 2 * WB, height - 2 * WB);
1388     {
1389       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
1390                                  height - 2 * WB - BH, "General");
1391 
1392       general.butt[21] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW,
1393                                              BH, "Use dark interface");
1394       general.butt[21]->tooltip("General.FltkColorScheme");
1395       general.butt[21]->type(FL_TOGGLE_BUTTON);
1396       general.butt[21]->callback(general_options_ok_cb);
1397 
1398       general.butt[13] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 2 * BH, BW,
1399                                              BH, "Show tooltips");
1400       general.butt[13]->tooltip("General.Tooltips");
1401       general.butt[13]->type(FL_TOGGLE_BUTTON);
1402       general.butt[13]->callback(general_options_ok_cb);
1403 
1404       general.butt[6] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH, BW, BH,
1405                                             "Show bounding boxes");
1406       general.butt[6]->tooltip("General.DrawBoundingBoxes (Alt+b)");
1407       general.butt[6]->type(FL_TOGGLE_BUTTON);
1408       general.butt[6]->callback(general_options_ok_cb);
1409 
1410       general.butt[2] =
1411         new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
1412                             "Draw simplified model during user interaction");
1413       general.butt[2]->tooltip("General.FastRedraw (Alt+f)");
1414       general.butt[2]->type(FL_TOGGLE_BUTTON);
1415       general.butt[2]->callback(general_options_ok_cb, (void *)"fast_redraw");
1416 
1417       general.butt[11] =
1418         new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH,
1419                             "Enable mouse hover over meshes and views");
1420       general.butt[11]->tooltip("General.MouseHoverMeshes");
1421       general.butt[11]->type(FL_TOGGLE_BUTTON);
1422       general.butt[11]->callback(general_options_ok_cb);
1423 
1424       general.butt[3] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH,
1425                                             "Enable double buffering");
1426       general.butt[3]->tooltip("General.DoubleBuffer");
1427       general.butt[3]->type(FL_TOGGLE_BUTTON);
1428       general.butt[3]->callback(general_options_ok_cb);
1429 
1430       general.butt[12] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 7 * BH, BW,
1431                                              BH, "Enable antialiasing");
1432       general.butt[12]->tooltip("General.Antialiasing");
1433       general.butt[12]->type(FL_TOGGLE_BUTTON);
1434       general.butt[12]->callback(general_options_ok_cb);
1435 
1436       general.butt[5] =
1437         new Fl_Check_Button(L + 2 * WB, 2 * WB + 8 * BH, BW, BH,
1438                             "Use trackball rotation instead of Euler angles");
1439       general.butt[5]->tooltip("General.Trackball");
1440       general.butt[5]->type(FL_TOGGLE_BUTTON);
1441       general.butt[5]->callback(general_options_ok_cb);
1442 
1443       general.butt[15] =
1444         new Fl_Check_Button(L + 2 * WB, 2 * WB + 9 * BH, BW, BH,
1445                             "Rotate around pseudo center of mass");
1446       general.butt[15]->tooltip("General.RotationCenterGravity");
1447       general.butt[15]->type(FL_TOGGLE_BUTTON);
1448       general.butt[15]->callback(general_options_ok_cb,
1449                                  (void *)"rotation_center");
1450 
1451       general.push[0] =
1452         new Fl_Button(L + 2 * IW - 2 * WB, 2 * WB + 10 * BH, BB, BH, "Select");
1453       general.push[0]->callback(general_options_rotation_center_select_cb);
1454 
1455       general.value[8] =
1456         new Fl_Value_Input(L + 2 * WB, 2 * WB + 10 * BH, IW / 3, BH);
1457       general.value[8]->tooltip("General.RotationCenterX");
1458       general.value[8]->callback(general_options_ok_cb,
1459                                  (void *)"rotation_center_coord");
1460       general.value[9] =
1461         new Fl_Value_Input(L + 2 * WB + IW / 3, 2 * WB + 10 * BH, IW / 3, BH);
1462       general.value[9]->tooltip("General.RotationCenterY");
1463       general.value[9]->callback(general_options_ok_cb,
1464                                  (void *)"rotation_center_coord");
1465       general.value[10] =
1466         new Fl_Value_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 10 * BH, IW / 3,
1467                            BH, "Rotation center");
1468       general.value[10]->tooltip("General.RotationCenterZ");
1469       general.value[10]->align(FL_ALIGN_RIGHT);
1470       general.value[10]->callback(general_options_ok_cb,
1471                                   (void *)"rotation_center_coord");
1472 
1473       general.butt[22] =
1474         new Fl_Check_Button(L + 2 * WB, 2 * WB + 11 * BH, BW, BH,
1475                             "Invert mouse wheel zoom direction");
1476       general.butt[22]->tooltip("General.MouseInvertZoom");
1477       general.butt[22]->type(FL_TOGGLE_BUTTON);
1478       general.butt[22]->callback(general_options_ok_cb);
1479 
1480       o->end();
1481     }
1482     {
1483       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
1484                                  height - 2 * WB - BH, "Advanced");
1485 
1486       general.butt[7] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW, BH,
1487                                             "Print messages on terminal");
1488       general.butt[7]->tooltip("General.Terminal");
1489       general.butt[7]->type(FL_TOGGLE_BUTTON);
1490       general.butt[7]->callback(general_options_ok_cb);
1491 
1492       general.value[5] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW, BH,
1493                                             "Message verbosity");
1494       general.value[5]->tooltip("General.Verbosity");
1495       general.value[5]->minimum(0);
1496       general.value[5]->maximum(10);
1497       if(CTX::instance()->inputScrolling) general.value[5]->step(1);
1498       general.value[5]->align(FL_ALIGN_RIGHT);
1499       general.value[5]->callback(general_options_ok_cb);
1500 
1501       general.input[1] = new Fl_Input(L + 2 * WB, 2 * WB + 3 * BH, IW, BH,
1502                                       "Text editor command");
1503       general.input[1]->tooltip("General.TextEditor");
1504       general.input[1]->align(FL_ALIGN_RIGHT);
1505       general.input[1]->callback(general_options_ok_cb);
1506 
1507       general.input[0] =
1508         new Fl_Input(L + 2 * WB, 2 * WB + 4 * BH, IW, BH, "Default file name");
1509       general.input[0]->tooltip("General.DefaultFileName");
1510       general.input[0]->align(FL_ALIGN_RIGHT);
1511       general.input[0]->callback(general_options_ok_cb);
1512 
1513       general.butt[14] =
1514         new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH,
1515                             "Ask confirmation before overwriting files");
1516       general.butt[14]->tooltip("General.ConfirmOverwrite");
1517       general.butt[14]->type(FL_TOGGLE_BUTTON);
1518       general.butt[14]->callback(general_options_ok_cb);
1519 
1520       general.butt[8] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH,
1521                                             "Save session information on exit");
1522       general.butt[8]->tooltip("General.SaveSession");
1523       general.butt[8]->type(FL_TOGGLE_BUTTON);
1524       general.butt[8]->callback(general_options_ok_cb);
1525 
1526       Fl_Button *b0 =
1527         new Fl_Button(L + width - 2 * WB - BW / 3, 2 * WB + 6 * BH, BW / 3, BH,
1528                       "Show file path");
1529       b0->callback(options_show_file_cb, (void *)"session");
1530 
1531       general.butt[9] = new Fl_Check_Button(
1532         L + 2 * WB, 2 * WB + 7 * BH, BW / 2 - WB, BH, "Save options on exit");
1533       general.butt[9]->tooltip("General.SaveOptions");
1534       general.butt[9]->type(FL_TOGGLE_BUTTON);
1535       general.butt[9]->callback(general_options_ok_cb);
1536 
1537       Fl_Button *b1 =
1538         new Fl_Button(L + width - 2 * WB - BW / 3, 2 * WB + 7 * BH, BW / 3, BH,
1539                       "Show file path");
1540       b1->callback(options_show_file_cb, (void *)"option");
1541 
1542       general.butt[10] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 8 * BH, BW,
1543                                              BH, "Enable expert mode");
1544       general.butt[10]->tooltip("General.ExpertMode");
1545       general.butt[10]->type(FL_TOGGLE_BUTTON);
1546       general.butt[10]->callback(general_options_ok_cb);
1547 
1548       general.value[32] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 9 * BH, IW,
1549                                              BH, "Number of threads");
1550       general.value[32]->tooltip("General.NumThreads");
1551       general.value[32]->minimum(0);
1552       general.value[32]->maximum(16);
1553       if(CTX::instance()->inputScrolling) general.value[32]->step(1);
1554       general.value[32]->align(FL_ALIGN_RIGHT);
1555       general.value[32]->callback(general_options_ok_cb);
1556 #if !defined(_OPENMP)
1557       general.value[32]->deactivate();
1558 #endif
1559 
1560 #if defined(HAVE_VISUDEV)
1561       general.butt[20] =
1562         new Fl_Check_Button(L + 2 * WB, 2 * WB + 10 * BH, BW / 2 - WB, BH,
1563                             "Enable heavy visualization capabilities");
1564       general.butt[20]->type(FL_TOGGLE_BUTTON);
1565       general.butt[20]->callback(general_options_ok_cb);
1566 #endif
1567 
1568       Fl_Button *b2 = new Fl_Button(L + 2 * WB, 2 * WB + 11 * BH, BW, BH,
1569                                     "Restore all options to default settings");
1570       b2->callback(options_restore_defaults_cb);
1571       if(CTX::instance()->guiColorScheme)
1572         b2->color(FL_DARK_RED);
1573       else
1574         b2->labelcolor(FL_DARK_RED);
1575 
1576       o->end();
1577     }
1578     {
1579       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
1580                                  height - 2 * WB - BH, "Axes");
1581 
1582       general.choice[4] =
1583         new Fl_Choice(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "Axes mode");
1584       general.choice[4]->tooltip("General.Axes (Alt+a)");
1585       general.choice[4]->menu(menu_axes_mode);
1586       general.choice[4]->align(FL_ALIGN_RIGHT);
1587       general.choice[4]->callback(general_options_ok_cb,
1588                                   (void *)"general_axes");
1589 
1590       general.butt[16] = new Fl_Check_Button(
1591         L + width - (int)(0.85 * IW) - 2 * WB, 2 * WB + 1 * BH,
1592         (int)(0.85 * IW), BH, "Mikado style");
1593       general.butt[16]->tooltip("General.AxesMikado");
1594       general.butt[16]->type(FL_TOGGLE_BUTTON);
1595       general.butt[16]->callback(general_options_ok_cb);
1596 
1597       general.value[17] =
1598         new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW / 3, BH);
1599       general.value[17]->tooltip("General.AxesTicsX");
1600       general.value[17]->minimum(0.);
1601       if(CTX::instance()->inputScrolling) general.value[17]->step(1);
1602       general.value[17]->maximum(100);
1603       general.value[17]->callback(general_options_ok_cb);
1604       general.value[18] = new Fl_Value_Input(L + 2 * WB + 1 * IW / 3,
1605                                              2 * WB + 2 * BH, IW / 3, BH);
1606       general.value[18]->tooltip("General.AxesTicsY");
1607       general.value[18]->minimum(0.);
1608       if(CTX::instance()->inputScrolling) general.value[18]->step(1);
1609       general.value[18]->maximum(100);
1610       general.value[18]->callback(general_options_ok_cb);
1611       general.value[19] = new Fl_Value_Input(
1612         L + 2 * WB + 2 * IW / 3, 2 * WB + 2 * BH, IW / 3, BH, "Axes tics");
1613       general.value[19]->tooltip("General.AxesTicsZ");
1614       general.value[19]->minimum(0.);
1615       if(CTX::instance()->inputScrolling) general.value[19]->step(1);
1616       general.value[19]->maximum(100);
1617       general.value[19]->align(FL_ALIGN_RIGHT);
1618       general.value[19]->callback(general_options_ok_cb);
1619 
1620       general.input[3] = new Fl_Input(L + 2 * WB, 2 * WB + 3 * BH, IW / 3, BH);
1621       general.input[3]->tooltip("General.AxesFormatX");
1622       general.input[3]->callback(general_options_ok_cb);
1623       general.input[4] =
1624         new Fl_Input(L + 2 * WB + 1 * IW / 3, 2 * WB + 3 * BH, IW / 3, BH);
1625       general.input[4]->callback(general_options_ok_cb);
1626       general.input[4]->tooltip("General.AxesFormatY");
1627       general.input[5] = new Fl_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 3 * BH,
1628                                       IW / 3, BH, "Axes format");
1629       general.input[5]->tooltip("General.AxesFormatZ");
1630       general.input[5]->align(FL_ALIGN_RIGHT);
1631       general.input[5]->callback(general_options_ok_cb);
1632 
1633       general.input[6] = new Fl_Input(L + 2 * WB, 2 * WB + 4 * BH, IW / 3, BH);
1634       general.input[6]->tooltip("General.AxesLabelX");
1635       general.input[6]->callback(general_options_ok_cb);
1636       general.input[7] =
1637         new Fl_Input(L + 2 * WB + 1 * IW / 3, 2 * WB + 4 * BH, IW / 3, BH);
1638       general.input[7]->tooltip("General.AxesLabelY");
1639       general.input[7]->callback(general_options_ok_cb);
1640       general.input[8] = new Fl_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 4 * BH,
1641                                       IW / 3, BH, "Axes labels");
1642       general.input[8]->tooltip("General.AxesLabelZ");
1643       general.input[8]->align(FL_ALIGN_RIGHT);
1644       general.input[8]->callback(general_options_ok_cb);
1645 
1646       general.butt[0] =
1647         new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH,
1648                             "Set position and size of axes automatically");
1649       general.butt[0]->tooltip("General.AxesAutoPosition");
1650       general.butt[0]->type(FL_TOGGLE_BUTTON);
1651       general.butt[0]->callback(general_options_ok_cb,
1652                                 (void *)"general_axes_auto");
1653 
1654       general.value[20] =
1655         new Fl_Value_Input(L + 2 * WB, 2 * WB + 6 * BH, IW / 3, BH);
1656       general.value[20]->callback(general_options_ok_cb);
1657       general.value[20]->tooltip("General.AxesMinX");
1658       general.value[21] =
1659         new Fl_Value_Input(L + 2 * WB + IW / 3, 2 * WB + 6 * BH, IW / 3, BH);
1660       general.value[21]->tooltip("General.AxesMinY");
1661       general.value[21]->callback(general_options_ok_cb);
1662       general.value[22] = new Fl_Value_Input(
1663         L + 2 * WB + 2 * IW / 3, 2 * WB + 6 * BH, IW / 3, BH, "Axes minimum");
1664       general.value[22]->tooltip("General.AxesMinZ");
1665       general.value[22]->align(FL_ALIGN_RIGHT);
1666       general.value[22]->callback(general_options_ok_cb);
1667 
1668       general.value[23] =
1669         new Fl_Value_Input(L + 2 * WB, 2 * WB + 7 * BH, IW / 3, BH);
1670       general.value[23]->tooltip("General.AxesMaxX");
1671       general.value[23]->callback(general_options_ok_cb);
1672       general.value[24] =
1673         new Fl_Value_Input(L + 2 * WB + IW / 3, 2 * WB + 7 * BH, IW / 3, BH);
1674       general.value[24]->tooltip("General.AxesMaxY");
1675       general.value[24]->callback(general_options_ok_cb);
1676       general.value[25] = new Fl_Value_Input(
1677         L + 2 * WB + 2 * IW / 3, 2 * WB + 7 * BH, IW / 3, BH, "Axes maximum");
1678       general.value[25]->tooltip("General.AxesMaxZ");
1679       general.value[25]->align(FL_ALIGN_RIGHT);
1680       general.value[25]->callback(general_options_ok_cb);
1681 
1682       general.push[1] =
1683         new Fl_Button(L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Fit to visible");
1684       general.push[1]->callback(general_options_axes_fit_cb);
1685 
1686       general.butt[1] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 9 * BH, BW, BH,
1687                                             "Show small axes");
1688       general.butt[1]->tooltip("General.SmallAxes (Alt+Shift+a)");
1689       general.butt[1]->type(FL_TOGGLE_BUTTON);
1690       general.butt[1]->callback(general_options_ok_cb,
1691                                 (void *)"general_small_axes");
1692 
1693       general.value[26] =
1694         new Fl_Value_Input(L + 2 * WB, 2 * WB + 10 * BH, IW / 2, BH);
1695       general.value[26]->tooltip("General.SmallAxesPositionX");
1696       general.value[26]->minimum(-2000);
1697       general.value[26]->maximum(2000);
1698       if(CTX::instance()->inputScrolling) general.value[26]->step(1);
1699       general.value[26]->callback(general_options_ok_cb);
1700       general.value[27] =
1701         new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 10 * BH, IW / 2, BH,
1702                            "Small axes position");
1703       general.value[26]->tooltip("General.SmallAxesPositionY");
1704       general.value[27]->align(FL_ALIGN_RIGHT);
1705       general.value[27]->minimum(-2000);
1706       general.value[27]->maximum(2000);
1707       if(CTX::instance()->inputScrolling) general.value[27]->step(1);
1708       general.value[27]->callback(general_options_ok_cb);
1709 
1710       o->end();
1711     }
1712     {
1713       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
1714                                  height - 2 * WB - BH, "Aspect");
1715       o->hide();
1716 
1717       static Fl_Menu_Item menu_projection[] = {
1718         {"Orthographic", 0, nullptr, nullptr},
1719         {"Perspective", 0, nullptr, nullptr},
1720         {nullptr}};
1721       general.choice[2] =
1722         new Fl_Choice(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "Projection mode");
1723       general.choice[2]->tooltip("General.Orthographic (Alt+o)");
1724       general.choice[2]->menu(menu_projection);
1725       general.choice[2]->align(FL_ALIGN_RIGHT);
1726       general.choice[2]->callback(general_options_ok_cb);
1727 
1728       general.value[14] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW,
1729                                              BH, "Z-clipping distance factor");
1730       general.value[14]->tooltip("General.ClipFactor");
1731       general.value[14]->minimum(0.1);
1732       general.value[14]->maximum(20.);
1733       if(CTX::instance()->inputScrolling) general.value[14]->step(0.1);
1734       general.value[14]->align(FL_ALIGN_RIGHT);
1735       general.value[14]->callback(general_options_ok_cb);
1736 
1737       general.value[15] =
1738         new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW / 2, BH);
1739       general.value[15]->tooltip("General.PolygonOffsetFactor");
1740       general.value[15]->minimum(0.);
1741       general.value[15]->maximum(10.);
1742       if(CTX::instance()->inputScrolling) general.value[15]->step(0.01);
1743       general.value[15]->align(FL_ALIGN_RIGHT);
1744       general.value[15]->callback(general_options_ok_cb);
1745 
1746       general.value[16] =
1747         new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 3 * BH, IW / 2, BH,
1748                            "Polygon offset factor/units");
1749       general.value[16]->tooltip("General.PolygonOffsetUnits");
1750       general.value[16]->minimum(0.);
1751       general.value[16]->maximum(10.);
1752       if(CTX::instance()->inputScrolling) general.value[16]->step(0.01);
1753       general.value[16]->align(FL_ALIGN_RIGHT);
1754       general.value[16]->callback(general_options_ok_cb);
1755 
1756       general.butt[4] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
1757                                             "Always apply polygon offset");
1758       general.butt[4]->tooltip("General.PolygonOffsetAlwaysOn");
1759       general.butt[4]->type(FL_TOGGLE_BUTTON);
1760       general.butt[4]->callback(general_options_ok_cb);
1761 
1762       general.value[11] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW,
1763                                              BH, "Quadric subdivisions");
1764       general.value[11]->tooltip("General.QuadricSubdivisions");
1765       general.value[11]->minimum(3);
1766       general.value[11]->maximum(30);
1767       if(CTX::instance()->inputScrolling) general.value[11]->step(1);
1768       general.value[11]->align(FL_ALIGN_RIGHT);
1769       general.value[11]->callback(general_options_ok_cb);
1770 
1771       general.value[6] =
1772         new Fl_Value_Input(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Point size");
1773       general.value[6]->minimum(0.1);
1774       general.value[6]->maximum(50);
1775       if(CTX::instance()->inputScrolling) general.value[6]->step(0.1);
1776       general.value[6]->align(FL_ALIGN_RIGHT);
1777       general.value[6]->callback(general_options_ok_cb);
1778 
1779       general.value[7] =
1780         new Fl_Value_Input(L + 2 * WB, 2 * WB + 7 * BH, IW, BH, "Line width");
1781       general.value[7]->tooltip("General.PointSize");
1782       general.value[7]->minimum(0.1);
1783       general.value[7]->maximum(50);
1784       if(CTX::instance()->inputScrolling) general.value[7]->step(0.1);
1785       general.value[7]->align(FL_ALIGN_RIGHT);
1786       general.value[7]->callback(general_options_ok_cb);
1787 
1788       static Fl_Menu_Item menu_genvectype[] = {
1789         {"Line", 0, nullptr, nullptr},
1790         {"Arrow", 0, nullptr, nullptr},
1791         {"Pyramid", 0, nullptr, nullptr},
1792         {"3D arrow", 0, nullptr, nullptr},
1793         {nullptr}};
1794       general.choice[0] =
1795         new Fl_Choice(L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Vector display");
1796       general.choice[0]->tooltip("General.VectorType");
1797       general.choice[0]->menu(menu_genvectype);
1798       general.choice[0]->align(FL_ALIGN_RIGHT);
1799       general.choice[0]->callback(general_options_ok_cb);
1800 
1801       Fl_Button *b = new Fl_Button(L + 2 * IW - 2 * WB, 2 * WB + 8 * BH, BB, BH,
1802                                    "Edit arrow");
1803       b->callback(general_arrow_param_cb);
1804 
1805       static Fl_Menu_Item menu_font_engine[] = {
1806         {"Native", 0, nullptr, nullptr},
1807         {"Cairo", 0, nullptr, nullptr
1808 #if !defined(HAVE_CAIRO)
1809          ,
1810          FL_MENU_INACTIVE
1811 #endif
1812         },
1813         {"StringTexture", 0, nullptr, nullptr},
1814         {nullptr}};
1815       general.choice[7] = new Fl_Choice(L + 2 * WB, 2 * WB + 9 * BH, IW, BH,
1816                                         "Font rendering engine");
1817       general.choice[7]->tooltip("General.GraphicsFontEngine");
1818       general.choice[7]->menu(menu_font_engine);
1819       general.choice[7]->align(FL_ALIGN_RIGHT);
1820       general.choice[7]->callback(general_options_ok_cb);
1821 
1822       int w1 = (int)(4. * IW / 5.), w2 = IW - w1;
1823       general.choice[1] = new Fl_Choice(L + 2 * WB, 2 * WB + 10 * BH, w1, BH);
1824       general.choice[1]->tooltip("General.GraphicsFont");
1825       general.choice[1]->menu(menu_font_names);
1826       general.choice[1]->align(FL_ALIGN_RIGHT);
1827       general.choice[1]->callback(general_options_ok_cb);
1828       general.value[12] = new Fl_Value_Input(L + 2 * WB + w1, 2 * WB + 10 * BH,
1829                                              w2, BH, "Default font");
1830       general.value[12]->tooltip("General.GraphicsFontSize");
1831       general.value[12]->minimum(5);
1832       general.value[12]->maximum(40);
1833       if(CTX::instance()->inputScrolling) general.value[12]->step(1);
1834       general.value[12]->align(FL_ALIGN_RIGHT);
1835       general.value[12]->callback(general_options_ok_cb);
1836 
1837       general.choice[6] = new Fl_Choice(L + 2 * WB, 2 * WB + 11 * BH, w1, BH);
1838       general.choice[6]->tooltip("General.GraphicsFontTitle");
1839       general.choice[6]->menu(menu_font_names);
1840       general.choice[6]->align(FL_ALIGN_RIGHT);
1841       general.choice[6]->callback(general_options_ok_cb);
1842       general.value[28] = new Fl_Value_Input(L + 2 * WB + w1, 2 * WB + 11 * BH,
1843                                              w2, BH, "Title font");
1844       general.value[28]->tooltip("General.GraphicsFontSizeTitle");
1845       general.value[28]->minimum(5);
1846       general.value[28]->maximum(40);
1847       if(CTX::instance()->inputScrolling) general.value[28]->step(1);
1848       general.value[28]->align(FL_ALIGN_RIGHT);
1849       general.value[28]->callback(general_options_ok_cb);
1850 
1851       o->end();
1852     }
1853     {
1854       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
1855                                  height - 2 * WB - BH, "Color");
1856       o->hide();
1857 
1858       general.value[2] =
1859         new Fl_Value_Input(L + 2 * WB, 2 * WB + 1 * BH, IW / 3, BH);
1860       general.value[2]->tooltip("General.Light0X");
1861       general.value[2]->minimum(-1.);
1862       general.value[2]->maximum(1.);
1863       if(CTX::instance()->inputScrolling) general.value[2]->step(0.01);
1864       general.value[2]->callback(general_options_ok_cb, (void *)"light_value");
1865 
1866       general.value[3] =
1867         new Fl_Value_Input(L + 2 * WB + IW / 3, 2 * WB + 1 * BH, IW / 3, BH);
1868       general.value[3]->tooltip("General.Light0Y");
1869       general.value[3]->minimum(-1.);
1870       general.value[3]->maximum(1.);
1871       if(CTX::instance()->inputScrolling) general.value[3]->step(0.01);
1872       general.value[3]->callback(general_options_ok_cb, (void *)"light_value");
1873 
1874       general.value[4] = new Fl_Value_Input(
1875         L + 2 * WB + 2 * IW / 3, 2 * WB + 1 * BH, IW / 3, BH, "Light position");
1876       general.value[4]->tooltip("General.Light0Z");
1877       general.value[4]->minimum(-1.);
1878       general.value[4]->maximum(1.);
1879       if(CTX::instance()->inputScrolling) general.value[4]->step(0.01);
1880       general.value[4]->align(FL_ALIGN_RIGHT);
1881       general.value[4]->callback(general_options_ok_cb, (void *)"light_value");
1882 
1883       general.value[13] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW,
1884                                              BH, "Light position divisor");
1885       general.value[13]->tooltip("General.Light0W");
1886       general.value[13]->minimum(0.);
1887       general.value[13]->maximum(1.);
1888       if(CTX::instance()->inputScrolling) general.value[13]->step(0.01);
1889       general.value[13]->align(FL_ALIGN_RIGHT);
1890       general.value[13]->callback(general_options_ok_cb);
1891 
1892       general.sphere = new spherePositionWidget(L + width - 2 * BH - 2 * WB,
1893                                                 2 * WB + 1 * BH, 2 * BH);
1894       general.sphere->callback(general_options_ok_cb, (void *)"light_sphere");
1895 
1896       general.value[1] =
1897         new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW / 2, BH);
1898       general.value[1]->tooltip("General.Shininess");
1899       general.value[1]->minimum(0);
1900       general.value[1]->maximum(10);
1901       if(CTX::instance()->inputScrolling) general.value[1]->step(0.1);
1902       general.value[1]->callback(general_options_ok_cb);
1903       general.value[0] =
1904         new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 3 * BH, IW / 2, BH,
1905                            "Material shininess/exponent");
1906       general.value[0]->tooltip("General.ShininessExponent");
1907       general.value[0]->minimum(0);
1908       general.value[0]->maximum(128);
1909       if(CTX::instance()->inputScrolling) general.value[0]->step(1);
1910       general.value[0]->align(FL_ALIGN_RIGHT);
1911       general.value[0]->callback(general_options_ok_cb);
1912 
1913       static Fl_Menu_Item menu_color_scheme[] = {
1914         {"Light", 0, nullptr, nullptr},
1915         {"Default", 0, nullptr, nullptr},
1916         {"Grayscale", 0, nullptr, nullptr},
1917         {"Dark", 0, nullptr, nullptr},
1918         {nullptr}};
1919 
1920       general.choice[3] = new Fl_Choice(L + 2 * WB, 2 * WB + 4 * BH, IW, BH,
1921                                         "Predefined color scheme");
1922       general.choice[3]->tooltip("General.ColorScheme (Alt+c)");
1923       general.choice[3]->menu(menu_color_scheme);
1924       general.choice[3]->align(FL_ALIGN_RIGHT);
1925       general.choice[3]->callback(general_options_color_scheme_cb);
1926 
1927       static Fl_Menu_Item menu_bg_grad[] = {{"None", 0, nullptr, nullptr},
1928                                             {"Vertical", 0, nullptr, nullptr},
1929                                             {"Horizontal", 0, nullptr, nullptr},
1930                                             {"Radial", 0, nullptr, nullptr},
1931                                             {nullptr}};
1932 
1933       general.choice[5] = new Fl_Choice(L + 2 * WB, 2 * WB + 5 * BH, IW, BH,
1934                                         "Background gradient");
1935       general.choice[5]->tooltip("General.BackgroundGradient");
1936       general.choice[5]->menu(menu_bg_grad);
1937       general.choice[5]->align(FL_ALIGN_RIGHT);
1938       general.choice[5]->callback(general_options_ok_cb);
1939 
1940       Fl_Scroll *s = new Fl_Scroll(L + 2 * WB, 3 * WB + 6 * BH, IW + 20,
1941                                    height - 5 * WB - 6 * BH);
1942       std::size_t i = 0, j = 0;
1943       while(GeneralOptions_Color[j].str) {
1944         if(GeneralOptions_Color[j].level & GMSH_DEPRECATED) {
1945           j++;
1946           continue;
1947         }
1948         general.color[i] = new Fl_Button(L + 2 * WB, 3 * WB + (6 + i) * BH, IW,
1949                                          BH, GeneralOptions_Color[j].str);
1950         general.color[i]->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE |
1951                                 FL_ALIGN_CLIP);
1952         general.color[i]->callback(color_cb,
1953                                    (void *)GeneralOptions_Color[j].function);
1954         i++;
1955         j++;
1956         if(i >= general.color.size()) {
1957           Msg::Error("General color widget vector should be resized");
1958           break;
1959         }
1960       }
1961       s->end();
1962 
1963       o->end();
1964     }
1965     {
1966       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
1967                                  height - 2 * WB - BH, "Camera");
1968       o->hide();
1969 
1970       general.butt[18] = new Fl_Check_Button(
1971         L + 2 * WB, 2 * WB + 1 * BH, BW, BH, "Enable camera (experimental)");
1972       general.butt[18]->tooltip("General.Camera");
1973       general.butt[18]->type(FL_TOGGLE_BUTTON);
1974       general.butt[18]->value(opt_general_camera_mode(0, GMSH_GET, 0));
1975       general.butt[18]->callback(general_options_ok_cb,
1976                                  (void *)"general_camera");
1977 
1978       general.butt[17] =
1979         new Fl_Check_Button(L + 2 * WB, 2 * WB + 2 * BH, BW, BH,
1980                             "Enable stereo rendering (experimental)");
1981       general.butt[17]->tooltip("General.Stereo");
1982       general.butt[17]->type(FL_TOGGLE_BUTTON);
1983       general.butt[17]->value(opt_general_stereo_mode(0, GMSH_GET, 0));
1984       general.butt[17]->callback(general_options_ok_cb);
1985 
1986       general.value[29] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW,
1987                                              BH, "Eye separation ratio (%)");
1988       general.value[29]->tooltip("General.CameraEyeSeparationRatio");
1989       general.value[29]->minimum(0.1);
1990       general.value[29]->maximum(10.);
1991       if(CTX::instance()->inputScrolling) general.value[29]->step(.1);
1992       general.value[29]->value(CTX::instance()->eye_sep_ratio);
1993       general.value[29]->align(FL_ALIGN_RIGHT);
1994       general.value[29]->callback(general_options_ok_cb);
1995 
1996       general.value[30] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 4 * BH, IW,
1997                                              BH, "Focal length ratio (%)");
1998       general.value[30]->tooltip("General.CameraFocalLengthRatio");
1999       general.value[30]->minimum(0.1);
2000       general.value[30]->maximum(10.);
2001       if(CTX::instance()->inputScrolling) general.value[30]->step(.1);
2002       general.value[30]->value(CTX::instance()->focallength_ratio);
2003       general.value[30]->align(FL_ALIGN_RIGHT);
2004       general.value[30]->callback(general_options_ok_cb);
2005 
2006       general.value[31] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW,
2007                                              BH, "Camera Aperture (degrees)");
2008       general.value[31]->tooltip("General.CameraAperture");
2009       general.value[31]->minimum(10.);
2010       general.value[31]->maximum(120.);
2011       if(CTX::instance()->inputScrolling) general.value[31]->step(1);
2012       general.value[31]->value(CTX::instance()->camera_aperture);
2013       general.value[31]->align(FL_ALIGN_RIGHT);
2014       general.value[31]->callback(general_options_ok_cb);
2015 
2016       general.butt[19] = new Fl_Check_Button(
2017         L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Enable gamepad (experimental)");
2018       general.butt[19]->type(FL_TOGGLE_BUTTON);
2019       general.butt[19]->value(opt_general_gamepad(0, GMSH_GET, 0));
2020       general.butt[19]->callback(general_options_ok_cb,
2021                                  (void *)"general_camera");
2022 
2023       general.gamepadconfig =
2024         new Fl_Button(L + 2 * WB, 2 * WB + 8 * BH, BW, BH, "Configure Gamepad");
2025       general.gamepadconfig->callback(general_gmpdcf_cb);
2026 
2027       if(opt_general_camera_mode(0, GMSH_GET, 0) == 0) {
2028         general.value[30]->deactivate();
2029         general.value[31]->deactivate();
2030       }
2031 
2032       if(opt_general_stereo_mode(0, GMSH_GET, 0) == 0)
2033         general.value[29]->deactivate();
2034 
2035       if(CTX::instance()->gamepad && CTX::instance()->gamepad->active) {
2036         general.gamepadconfig->activate();
2037         opt_general_camera_mode(0, GMSH_SET, 1);
2038         general.butt[18]->value(opt_general_camera_mode(0, GMSH_GET, 0));
2039       }
2040       else {
2041         general.gamepadconfig->deactivate();
2042       }
2043       o->end();
2044     }
2045     o->end();
2046   }
2047 
2048   general.group->end();
2049 
2050   // Geometry options
2051   geo.group = new Fl_Group(L, 0, width, height, "Geometry Options");
2052   geo.group->hide();
2053   {
2054     Fl_Tabs *o = new Fl_Tabs(L + WB, WB, width - 2 * WB, height - 2 * WB);
2055     {
2056       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2057                                  height - 2 * WB - BH, "General");
2058       o->hide();
2059 
2060       geo.value[2] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 1 * BH, IW, BH,
2061                                         "Geometry tolerance");
2062       geo.value[2]->tooltip("Geometry.Tolerance");
2063       geo.value[2]->align(FL_ALIGN_RIGHT);
2064       geo.value[2]->callback(geometry_options_ok_cb);
2065 
2066       geo.butt[8] = new Fl_Check_Button(
2067         L + 2 * WB, 2 * WB + 2 * BH, BW, BH,
2068         "Remove duplicate entities in GEO model transforms");
2069       geo.butt[8]->tooltip("Geometry.AutoCoherence");
2070       geo.butt[8]->type(FL_TOGGLE_BUTTON);
2071       geo.butt[8]->callback(geometry_options_ok_cb);
2072 
2073       Fl_Box *b = new Fl_Box(L + 2 * WB, 2 * WB + 3 * BH, BW, 2);
2074       b->box(FL_ENGRAVED_FRAME);
2075       b->labeltype(FL_NO_LABEL);
2076 
2077       Fl_Box *b2 = new Fl_Box(FL_NO_BOX, L + 2 * WB, 2 * WB + 3 * BH + 1, IW,
2078                               BH, "Open CASCADE model healing options:");
2079       b2->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT);
2080 
2081       geo.butt[16] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
2082                                          "Remove degenerated edges and faces");
2083       geo.butt[16]->tooltip("Geometry.OCCFixDegenerated");
2084       geo.butt[16]->type(FL_TOGGLE_BUTTON);
2085       geo.butt[16]->callback(geometry_options_ok_cb);
2086 
2087       geo.butt[11] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH,
2088                                          "Remove small edges");
2089       geo.butt[11]->tooltip("Geometry.OCCFixSmallEdges");
2090       geo.butt[11]->type(FL_TOGGLE_BUTTON);
2091       geo.butt[11]->callback(geometry_options_ok_cb);
2092 
2093       geo.butt[12] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH,
2094                                          "Remove small faces");
2095       geo.butt[12]->tooltip("Geometry.OCCFixSmallFaces");
2096       geo.butt[12]->type(FL_TOGGLE_BUTTON);
2097       geo.butt[12]->callback(geometry_options_ok_cb);
2098 
2099       geo.butt[13] =
2100         new Fl_Check_Button(L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Sew faces");
2101       geo.butt[13]->tooltip("Geometry.OCCFixSewFaces");
2102       geo.butt[13]->type(FL_TOGGLE_BUTTON);
2103       geo.butt[13]->callback(geometry_options_ok_cb);
2104 
2105       geo.butt[14] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 8 * BH, BW, BH,
2106                                          "Fix shells and make solids");
2107       geo.butt[14]->tooltip("Geometry.OCCMakeSolids");
2108       geo.butt[14]->type(FL_TOGGLE_BUTTON);
2109       geo.butt[14]->callback(geometry_options_ok_cb);
2110 
2111       geo.value[20] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 9 * BH, IW, BH,
2112                                          "Global model scaling");
2113       geo.value[20]->tooltip("Geometry.OCCScaling");
2114       geo.value[20]->align(FL_ALIGN_RIGHT);
2115       geo.value[20]->callback(geometry_options_ok_cb);
2116 
2117 #if !defined(HAVE_OCC)
2118       b2->deactivate();
2119       geo.butt[16]->deactivate();
2120       geo.butt[11]->deactivate();
2121       geo.butt[12]->deactivate();
2122       geo.butt[13]->deactivate();
2123       geo.butt[14]->deactivate();
2124       geo.value[20]->deactivate();
2125 #endif
2126       o->end();
2127     }
2128     {
2129       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2130                                  height - 2 * WB - BH, "Visibility");
2131 
2132       geo.butt[0] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH,
2133                                         BW / 2 - WB, BH, "Points");
2134       geo.butt[0]->tooltip("Geometry.Points (Alt+p)");
2135       geo.butt[0]->type(FL_TOGGLE_BUTTON);
2136       geo.butt[0]->callback(geometry_options_ok_cb);
2137 
2138       geo.butt[1] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 2 * BH,
2139                                         BW / 2 - WB, BH, "Curves");
2140       geo.butt[1]->tooltip("Geometry.Curves (Alt+l)");
2141       geo.butt[1]->type(FL_TOGGLE_BUTTON);
2142       geo.butt[1]->callback(geometry_options_ok_cb);
2143 
2144       geo.butt[2] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH,
2145                                         BW / 2 - WB, BH, "Surfaces");
2146       geo.butt[2]->tooltip("Geometry.Surfaces (Alt+s)");
2147       geo.butt[2]->type(FL_TOGGLE_BUTTON);
2148       geo.butt[2]->callback(geometry_options_ok_cb);
2149 
2150       geo.butt[3] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH,
2151                                         BW / 2 - WB, BH, "Volumes");
2152       geo.butt[3]->tooltip("Geometry.Volumes (Alt+v)");
2153       geo.butt[3]->type(FL_TOGGLE_BUTTON);
2154       geo.butt[3]->callback(geometry_options_ok_cb);
2155 
2156       geo.butt[4] = new Fl_Check_Button(L + width / 2, 2 * WB + 1 * BH,
2157                                         BW / 2 - WB, BH, "Point labels");
2158       geo.butt[4]->tooltip("Geometry.PointLabels");
2159       geo.butt[4]->type(FL_TOGGLE_BUTTON);
2160       geo.butt[4]->callback(geometry_options_ok_cb);
2161 
2162       geo.butt[5] = new Fl_Check_Button(L + width / 2, 2 * WB + 2 * BH,
2163                                         BW / 2 - WB, BH, "Curve labels");
2164       geo.butt[5]->tooltip("Geometry.CurveLabels");
2165       geo.butt[5]->type(FL_TOGGLE_BUTTON);
2166       geo.butt[5]->callback(geometry_options_ok_cb);
2167 
2168       geo.butt[6] = new Fl_Check_Button(L + width / 2, 2 * WB + 3 * BH,
2169                                         BW / 2 - WB, BH, "Surface labels");
2170       geo.butt[6]->tooltip("Geometry.SurfaceLabels");
2171       geo.butt[6]->type(FL_TOGGLE_BUTTON);
2172       geo.butt[6]->callback(geometry_options_ok_cb);
2173 
2174       geo.butt[7] = new Fl_Check_Button(L + width / 2, 2 * WB + 4 * BH,
2175                                         BW / 2 - WB, BH, "Volume labels");
2176       geo.butt[7]->tooltip("Geometry.VolumeLabels");
2177       geo.butt[7]->type(FL_TOGGLE_BUTTON);
2178       geo.butt[7]->callback(geometry_options_ok_cb);
2179 
2180       static Fl_Menu_Item menu_label_type[] = {
2181         {"Description", 0, nullptr, nullptr},
2182         {"Elementary tag", 0, nullptr, nullptr},
2183         {"Physical tag(s)", 0, nullptr, nullptr},
2184         {"Elementary name", 0, nullptr, nullptr},
2185         {"Physical name(s)", 0, nullptr, nullptr},
2186         {nullptr}};
2187       geo.choice[4] =
2188         new Fl_Choice(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Label type");
2189       geo.choice[4]->tooltip("Geometry.LabelType");
2190       geo.choice[4]->menu(menu_label_type);
2191       geo.choice[4]->align(FL_ALIGN_RIGHT);
2192       geo.choice[4]->callback(geometry_options_ok_cb);
2193 
2194       geo.value[0] =
2195         new Fl_Value_Input(L + 2 * WB, 2 * WB + 6 * BH, IW / 2, BH);
2196       geo.value[0]->tooltip("Geometry.Normals");
2197       geo.value[0]->minimum(0);
2198       geo.value[0]->maximum(500);
2199       if(CTX::instance()->inputScrolling) geo.value[0]->step(1);
2200       geo.value[0]->align(FL_ALIGN_RIGHT);
2201       geo.value[0]->when(FL_WHEN_RELEASE);
2202       geo.value[0]->callback(geometry_options_ok_cb);
2203 
2204       geo.value[1] = new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 6 * BH,
2205                                         IW / 2, BH, "Normals and tangents");
2206       geo.value[1]->tooltip("Geometry.Tangents");
2207       geo.value[1]->minimum(0);
2208       geo.value[1]->maximum(500);
2209       if(CTX::instance()->inputScrolling) geo.value[1]->step(1);
2210       geo.value[1]->align(FL_ALIGN_RIGHT);
2211       geo.value[1]->when(FL_WHEN_RELEASE);
2212       geo.value[1]->callback(geometry_options_ok_cb);
2213 
2214       o->end();
2215     }
2216     {
2217       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2218                                  height - 2 * WB - BH, "Transfo");
2219       o->hide();
2220 
2221       static Fl_Menu_Item menu_transform[] = {{"None", 0, nullptr, nullptr},
2222                                               {"Scaling", 0, nullptr, nullptr},
2223                                               {nullptr}};
2224       geo.choice[3] = new Fl_Choice(L + 2 * WB, 2 * WB + 1 * BH, IW, BH,
2225                                     "Main window transform");
2226       geo.choice[3]->tooltip("Geometry.Transform");
2227       geo.choice[3]->menu(menu_transform);
2228       geo.choice[3]->align(FL_ALIGN_RIGHT);
2229       geo.choice[3]->callback(geometry_options_ok_cb, (void *)"geo_transform");
2230 
2231       int ss = 2 * IW / 3 / 3 + 4;
2232       geo.value[7] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, ss, BH);
2233       geo.value[7]->tooltip("Geometry.TransformXX");
2234       geo.value[8] =
2235         new Fl_Value_Input(L + 2 * WB + ss, 2 * WB + 2 * BH, ss, BH);
2236       geo.value[8]->tooltip("Geometry.TransformXY");
2237       geo.value[9] =
2238         new Fl_Value_Input(L + 2 * WB + 2 * ss, 2 * WB + 2 * BH, ss, BH, " X");
2239       geo.value[9]->tooltip("Geometry.TransformXZ");
2240       geo.value[10] =
2241         new Fl_Value_Input(L + 2 * WB + IW, 2 * WB + 2 * BH, 7 * IW / 10, BH);
2242       geo.value[10]->tooltip("Geometry.OffsetX");
2243 
2244       geo.value[11] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, ss, BH);
2245       geo.value[11]->tooltip("Geometry.TransformYX");
2246       geo.value[12] =
2247         new Fl_Value_Input(L + 2 * WB + ss, 2 * WB + 3 * BH, ss, BH);
2248       geo.value[12]->tooltip("Geometry.TransformYY");
2249       geo.value[13] = new Fl_Value_Input(L + 2 * WB + 2 * ss, 2 * WB + 3 * BH,
2250                                          ss, BH, " Y +");
2251       geo.value[13]->tooltip("Geometry.TransformYZ");
2252       geo.value[14] =
2253         new Fl_Value_Input(L + 2 * WB + IW, 2 * WB + 3 * BH, 7 * IW / 10, BH);
2254       geo.value[14]->tooltip("Geometry.OffsetY");
2255 
2256       geo.value[15] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 4 * BH, ss, BH);
2257       geo.value[15]->tooltip("Geometry.TransformZX");
2258       geo.value[16] =
2259         new Fl_Value_Input(L + 2 * WB + ss, 2 * WB + 4 * BH, ss, BH);
2260       geo.value[16]->tooltip("Geometry.TransformZY");
2261       geo.value[17] =
2262         new Fl_Value_Input(L + 2 * WB + 2 * ss, 2 * WB + 4 * BH, ss, BH, " Z");
2263       geo.value[17]->tooltip("Geometry.TransformZZ");
2264       geo.value[18] =
2265         new Fl_Value_Input(L + 2 * WB + IW, 2 * WB + 4 * BH, 7 * IW / 10, BH);
2266       geo.value[18]->tooltip("Geometry.OffsetZ");
2267 
2268       for(int i = 7; i <= 18; i++) {
2269         geo.value[i]->minimum(-1.);
2270         geo.value[i]->maximum(1.);
2271         if(CTX::instance()->inputScrolling) geo.value[i]->step(0.1);
2272         geo.value[i]->align(FL_ALIGN_RIGHT);
2273         geo.value[i]->when(FL_WHEN_RELEASE);
2274         geo.value[i]->callback(geometry_options_ok_cb);
2275       }
2276 
2277       o->end();
2278     }
2279     {
2280       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2281                                  height - 2 * WB - BH, "Aspect");
2282       o->hide();
2283 
2284       geo.choice[0] =
2285         new Fl_Choice(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "Point display");
2286       geo.choice[0]->tooltip("Geometry.PointType");
2287       geo.choice[0]->menu(menu_point_display);
2288       geo.choice[0]->align(FL_ALIGN_RIGHT);
2289       geo.choice[0]->callback(geometry_options_ok_cb);
2290 
2291       geo.value[3] =
2292         new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Point size");
2293       geo.value[3]->tooltip("Geometry.PointSize");
2294       geo.value[3]->minimum(0.1);
2295       geo.value[3]->maximum(50);
2296       if(CTX::instance()->inputScrolling) geo.value[3]->step(0.1);
2297       geo.value[3]->align(FL_ALIGN_RIGHT);
2298       geo.value[3]->callback(geometry_options_ok_cb);
2299 
2300       geo.value[5] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW, BH,
2301                                         "Selected point size");
2302       geo.value[5]->tooltip("Geometry.PointSelectSize");
2303       geo.value[5]->minimum(0.1);
2304       geo.value[5]->maximum(50);
2305       if(CTX::instance()->inputScrolling) geo.value[5]->step(0.1);
2306       geo.value[5]->align(FL_ALIGN_RIGHT);
2307       geo.value[5]->callback(geometry_options_ok_cb);
2308 
2309       geo.choice[1] =
2310         new Fl_Choice(L + 2 * WB, 2 * WB + 4 * BH, IW, BH, "Curve display");
2311       geo.choice[1]->tooltip("Geometry.CurveType");
2312       geo.choice[1]->menu(menu_line_display);
2313       geo.choice[1]->align(FL_ALIGN_RIGHT);
2314       geo.choice[1]->callback(geometry_options_ok_cb);
2315 
2316       geo.value[4] =
2317         new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Curve width");
2318       geo.value[4]->tooltip("Geometry.CurveWidth");
2319       geo.value[4]->minimum(0.1);
2320       geo.value[4]->maximum(50);
2321       if(CTX::instance()->inputScrolling) geo.value[4]->step(0.1);
2322       geo.value[4]->align(FL_ALIGN_RIGHT);
2323       geo.value[4]->callback(geometry_options_ok_cb);
2324 
2325       geo.value[6] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 6 * BH, IW, BH,
2326                                         "Selected curve width");
2327       geo.value[6]->tooltip("Geometry.CurveSelectWidth");
2328       geo.value[6]->minimum(0.1);
2329       geo.value[6]->maximum(50);
2330       if(CTX::instance()->inputScrolling) geo.value[6]->step(0.1);
2331       geo.value[6]->align(FL_ALIGN_RIGHT);
2332       geo.value[6]->callback(geometry_options_ok_cb);
2333 
2334       geo.value[19] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 7 * BH, IW, BH,
2335                                          "Curve subdivisions");
2336       geo.value[19]->tooltip("Geometry.NumSubEdges");
2337       geo.value[19]->minimum(1);
2338       geo.value[19]->maximum(50);
2339       if(CTX::instance()->inputScrolling) geo.value[19]->step(1);
2340       geo.value[19]->align(FL_ALIGN_RIGHT);
2341       geo.value[19]->callback(geometry_options_ok_cb);
2342 
2343       geo.choice[2] =
2344         new Fl_Choice(L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Surface display");
2345       geo.choice[2]->tooltip("Geometry.SurfaceType (Alt+d)");
2346       geo.choice[2]->menu(menu_surface_display);
2347       geo.choice[2]->align(FL_ALIGN_RIGHT);
2348       geo.choice[2]->callback(geometry_options_ok_cb);
2349 
2350       o->end();
2351     }
2352     {
2353       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2354                                  height - 2 * WB - BH, "Color");
2355       o->hide();
2356 
2357       geo.butt[9] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW, BH,
2358                                         "Enable lighting");
2359       geo.butt[9]->tooltip("Geometry.Light (Alt+w)");
2360       geo.butt[9]->type(FL_TOGGLE_BUTTON);
2361       geo.butt[9]->callback(geometry_options_ok_cb);
2362 
2363       geo.butt[15] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 2 * BH, BW, BH,
2364                                          "Use two-side lighting");
2365       geo.butt[15]->tooltip("Geometry.LightTwoSide");
2366       geo.butt[15]->type(FL_TOGGLE_BUTTON);
2367       geo.butt[15]->callback(geometry_options_ok_cb);
2368 
2369       geo.butt[10] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH, BW, BH,
2370                                          "Highlight orphan and boundary entities");
2371       geo.butt[10]->tooltip("Geometry.HighlightOrphans");
2372       geo.butt[10]->type(FL_TOGGLE_BUTTON);
2373       geo.butt[10]->callback(geometry_options_ok_cb);
2374 
2375       Fl_Scroll *s = new Fl_Scroll(L + 2 * WB, 2 * WB + 4 * BH, IW + 20,
2376                                    height - 4 * WB - 4 * BH);
2377       std::size_t i = 0, j = 0;
2378       while(GeometryOptions_Color[j].str) {
2379         if(GeometryOptions_Color[j].level & GMSH_DEPRECATED) {
2380           j++;
2381           continue;
2382         }
2383         geo.color[i] = new Fl_Button(L + 2 * WB, 2 * WB + (4 + i) * BH, IW, BH,
2384                                      GeometryOptions_Color[j].str);
2385         geo.color[i]->callback(color_cb,
2386                                (void *)GeometryOptions_Color[j].function);
2387         i++;
2388         j++;
2389         if(i >= geo.color.size()) {
2390           Msg::Error("Geometry color widget vector should be resized");
2391           break;
2392         }
2393       }
2394       s->end();
2395 
2396       o->end();
2397     }
2398     o->end();
2399   }
2400   geo.group->end();
2401 
2402   // Mesh options
2403   mesh.group = new Fl_Group(L, 0, width, height, "Mesh Options");
2404   mesh.group->hide();
2405   {
2406     Fl_Tabs *o = new Fl_Tabs(L + WB, WB, width - 2 * WB, height - 2 * WB);
2407     {
2408       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2409                                  height - 2 * WB - BH, "General");
2410       o->hide();
2411 
2412       static Fl_Menu_Item menu_2d_algo[] = {
2413         {"Automatic", 0, nullptr, nullptr},
2414         {"MeshAdapt", 0, nullptr, nullptr},
2415         {"Delaunay", 0, nullptr, nullptr},
2416         {"Frontal-Delaunay", 0, nullptr, nullptr},
2417         {"BAMG (experimental)", 0, nullptr, nullptr},
2418         {"Frontal-Delaunay for Quads (experimental)", 0, nullptr, nullptr},
2419         {"Packing of parallelograms (experimental)", 0, nullptr, nullptr},
2420         {"Quasi-Structured Quad (experimental)", 0, nullptr, nullptr},
2421         {"Initial Mesh Only (no node insertion)", 0, nullptr, nullptr},
2422         {nullptr}};
2423       static Fl_Menu_Item menu_3d_algo[] = {
2424         {"Delaunay", 0, nullptr, nullptr},
2425         {"Frontal", 0, nullptr, nullptr},
2426         {"HXT (experimental)", 0, nullptr, nullptr},
2427         {"MMG3D (experimental, single volume only)", 0, nullptr, nullptr},
2428         {"Initial Mesh Only (no node insertion)", 0, nullptr, nullptr},
2429         {nullptr}};
2430       static Fl_Menu_Item menu_recombination_algo[] = {
2431         {"Simple", 0, nullptr, nullptr},
2432         {"Blossom", 0, nullptr, nullptr},
2433         {"Simple Full-Quad", 0, nullptr, nullptr},
2434         {"Blossom Full-Quad", 0, nullptr, nullptr},
2435         {"Christos's bipartite labelling", 0, nullptr, nullptr},
2436         {nullptr}};
2437       static Fl_Menu_Item menu_subdivision_algo[] = {
2438         {"None", 0, nullptr, nullptr},
2439         {"All Quads", 0, nullptr, nullptr},
2440         {"All Hexas", 0, nullptr, nullptr},
2441         {nullptr}};
2442 
2443       mesh.choice[2] =
2444         new Fl_Choice(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "2D algorithm");
2445       mesh.choice[2]->tooltip("Mesh.Algorithm");
2446       mesh.choice[2]->menu(menu_2d_algo);
2447       mesh.choice[2]->align(FL_ALIGN_RIGHT);
2448       mesh.choice[2]->callback(mesh_options_ok_cb);
2449 
2450       mesh.choice[3] =
2451         new Fl_Choice(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "3D algorithm");
2452       mesh.choice[3]->tooltip("Mesh.Algorithm3D");
2453       mesh.choice[3]->menu(menu_3d_algo);
2454       mesh.choice[3]->align(FL_ALIGN_RIGHT);
2455       mesh.choice[3]->callback(mesh_options_ok_cb);
2456 
2457       mesh.choice[1] = new Fl_Choice(L + 2 * WB, 2 * WB + 3 * BH, IW, BH,
2458                                      "2D recombination algorithm");
2459       mesh.choice[1]->tooltip("Mesh.RecombinationAlgorithm");
2460       mesh.choice[1]->menu(menu_recombination_algo);
2461       mesh.choice[1]->align(FL_ALIGN_RIGHT);
2462       mesh.choice[1]->callback(mesh_options_ok_cb);
2463 
2464       mesh.butt[21] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
2465                                           "Recombine all triangular meshes");
2466       mesh.butt[21]->tooltip("Mesh.RecombineAll");
2467       mesh.butt[21]->type(FL_TOGGLE_BUTTON);
2468       mesh.butt[21]->callback(mesh_options_ok_cb);
2469 
2470       mesh.choice[5] = new Fl_Choice(L + 2 * WB, 2 * WB + 5 * BH, IW, BH,
2471                                      "Subdivision algorithm");
2472       mesh.choice[5]->tooltip("Mesh.SubdivisionAlgorithm");
2473       mesh.choice[5]->menu(menu_subdivision_algo);
2474       mesh.choice[5]->align(FL_ALIGN_RIGHT);
2475       mesh.choice[5]->callback(mesh_options_ok_cb);
2476 
2477       mesh.value[0] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 6 * BH, IW, BH,
2478                                          "Smoothing steps");
2479       mesh.value[0]->tooltip("Mesh.Smoothing");
2480       mesh.value[0]->minimum(0);
2481       mesh.value[0]->maximum(100);
2482       if(CTX::instance()->inputScrolling) mesh.value[0]->step(1);
2483       mesh.value[0]->align(FL_ALIGN_RIGHT);
2484       mesh.value[0]->callback(mesh_options_ok_cb);
2485 
2486       mesh.value[2] = new inputValueFloat(L + 2 * WB, 2 * WB + 7 * BH, IW, BH,
2487                                           "Element size factor");
2488       mesh.value[2]->tooltip("Mesh.MeshSizeFactor");
2489       mesh.value[2]->minimum(0.001);
2490       mesh.value[2]->maximum(1000);
2491       if(CTX::instance()->inputScrolling) mesh.value[2]->step(0.01);
2492       mesh.value[2]->align(FL_ALIGN_RIGHT);
2493       mesh.value[2]->callback(mesh_options_ok_cb);
2494 
2495       mesh.value[25] =
2496         new Fl_Value_Input(L + 2 * WB, 2 * WB + 8 * BH, IW / 2, BH);
2497       mesh.value[25]->tooltip("Mesh.MeshSizeMin");
2498       mesh.value[25]->align(FL_ALIGN_RIGHT);
2499       mesh.value[25]->callback(mesh_options_ok_cb);
2500 
2501       mesh.value[26] = new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 8 * BH,
2502                                           IW / 2, BH, "Min/Max element size");
2503       mesh.value[26]->tooltip("Mesh.MeshSizeMax");
2504       mesh.value[26]->align(FL_ALIGN_RIGHT);
2505       mesh.value[26]->callback(mesh_options_ok_cb);
2506 
2507       mesh.value[3] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 9 * BH, IW / 3,
2508                                          BH, "Element order");
2509       mesh.value[3]->tooltip("Mesh.ElementOrder");
2510       mesh.value[3]->minimum(1);
2511       mesh.value[3]->maximum(2);
2512       if(CTX::instance()->inputScrolling) mesh.value[3]->step(1);
2513       mesh.value[3]->align(FL_ALIGN_RIGHT);
2514       mesh.value[3]->callback(mesh_options_ok_cb);
2515 
2516       mesh.butt[4] =
2517         new Fl_Check_Button(L + 2 * WB + 1.25 * IW, 2 * WB + 9 * BH, BW, BH,
2518                             "Use incomplete elements");
2519       mesh.butt[4]->tooltip("Mesh.SecondOrderIncomplete");
2520       mesh.butt[4]->type(FL_TOGGLE_BUTTON);
2521       mesh.butt[4]->callback(mesh_options_ok_cb);
2522 
2523       o->end();
2524     }
2525 
2526     {
2527       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2528                                  height - 2 * WB - BH, "Advanced");
2529       o->hide();
2530 
2531       mesh.butt[5] =
2532         new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW, BH,
2533                             "Compute element sizes using point values");
2534       mesh.butt[5]->tooltip("Mesh.MeshSizeFromPoints");
2535       mesh.butt[5]->type(FL_TOGGLE_BUTTON);
2536       mesh.butt[5]->callback(mesh_options_ok_cb);
2537 
2538       mesh.butt[26] = new Fl_Check_Button(
2539         L + 2 * WB, 2 * WB + 2 * BH, BW, BH,
2540         "Compute element sizes using parametric point values");
2541       mesh.butt[26]->tooltip("Mesh.MeshSizeFromParametricPoints");
2542       mesh.butt[26]->type(FL_TOGGLE_BUTTON);
2543       mesh.butt[26]->callback(mesh_options_ok_cb);
2544 
2545       mesh.value[1] =
2546         new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW / 2, BH,
2547                            "Compute element sizes from curvature");
2548       mesh.value[1]->tooltip("Mesh.MeshSizeFromCurvature (number of elements "
2549                              "per 2 * Pi radians)");
2550       mesh.value[1]->minimum(0);
2551       mesh.value[1]->maximum(50);
2552       if(CTX::instance()->inputScrolling) mesh.value[1]->step(1);
2553       mesh.value[1]->align(FL_ALIGN_RIGHT);
2554       mesh.value[1]->callback(mesh_options_ok_cb);
2555 
2556       mesh.butt[16] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
2557                                           "Extend element sizes from boundary");
2558       mesh.butt[16]->tooltip("Mesh.MeshSizeExtendFromBoundary");
2559       mesh.butt[16]->type(FL_TOGGLE_BUTTON);
2560       mesh.butt[16]->callback(mesh_options_ok_cb);
2561 
2562       mesh.butt[2] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH,
2563                                          "Optimize quality of tetrahedra");
2564       mesh.butt[2]->tooltip("Mesh.Optimize");
2565       mesh.butt[2]->type(FL_TOGGLE_BUTTON);
2566       mesh.butt[2]->callback(mesh_options_ok_cb);
2567 
2568       mesh.butt[24] =
2569         new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH,
2570                             "Optimize quality of tetrahedra with Netgen");
2571       mesh.butt[24]->tooltip("Mesh.OptimizeNetgen");
2572       mesh.butt[24]->type(FL_TOGGLE_BUTTON);
2573 #if !defined(HAVE_NETGEN)
2574       mesh.butt[24]->deactivate();
2575 #endif
2576       mesh.butt[24]->callback(mesh_options_ok_cb);
2577 
2578       mesh.butt[3] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 7 * BH, BW, BH,
2579                                          "Optimize high-order meshes");
2580       mesh.butt[3]->tooltip("Mesh.HighOrderOptimize");
2581       mesh.butt[3]->type(FL_TOGGLE_BUTTON);
2582       mesh.butt[3]->callback(mesh_options_ok_cb);
2583 
2584       o->end();
2585     }
2586 
2587     {
2588       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2589                                  height - 2 * WB - BH, "Visibility");
2590 
2591       mesh.butt[6] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH,
2592                                          BW / 2 - WB, BH, "Nodes");
2593       mesh.butt[6]->tooltip("Mesh.Points (Alt+Shift+p)");
2594       mesh.butt[6]->type(FL_TOGGLE_BUTTON);
2595       mesh.butt[6]->callback(mesh_options_ok_cb);
2596 
2597       mesh.butt[7] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 2 * BH,
2598                                          BW / 2 - WB, BH, "1D elements");
2599       mesh.butt[7]->tooltip("Mesh.Lines (Alt+Shift+l)");
2600       mesh.butt[7]->type(FL_TOGGLE_BUTTON);
2601       mesh.butt[7]->callback(mesh_options_ok_cb);
2602 
2603       mesh.butt[8] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH,
2604                                          BW / 2 - WB, BH, "2D element edges");
2605       mesh.butt[8]->tooltip("Mesh.SurfaceEdges (Alt+Shift+s)");
2606       mesh.butt[8]->type(FL_TOGGLE_BUTTON);
2607       mesh.butt[8]->callback(mesh_options_ok_cb);
2608 
2609       mesh.butt[9] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH,
2610                                          BW / 2 - WB, BH, "2D element faces");
2611       mesh.butt[9]->tooltip("Mesh.SurfaceFaces (Alt+Shift+d)");
2612       mesh.butt[9]->type(FL_TOGGLE_BUTTON);
2613       mesh.butt[9]->callback(mesh_options_ok_cb);
2614 
2615       mesh.butt[10] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH,
2616                                           BW / 2 - WB, BH, "3D element edges");
2617       mesh.butt[10]->tooltip("Mesh.VolumeEdges (Alt+Shift+v)");
2618       mesh.butt[10]->type(FL_TOGGLE_BUTTON);
2619       mesh.butt[10]->callback(mesh_options_ok_cb);
2620 
2621       mesh.butt[11] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH,
2622                                           BW / 2 - WB, BH, "3D element faces");
2623       mesh.butt[11]->tooltip("Mesh.VolumeFaces (Alt+Shift+b)");
2624       mesh.butt[11]->type(FL_TOGGLE_BUTTON);
2625       mesh.butt[11]->callback(mesh_options_ok_cb);
2626 
2627       mesh.butt[12] = new Fl_Check_Button(L + width / 2, 2 * WB + 1 * BH,
2628                                           BW / 2 - WB, BH, "Node labels");
2629       mesh.butt[12]->tooltip("Mesh.NodeLabels");
2630       mesh.butt[12]->type(FL_TOGGLE_BUTTON);
2631       mesh.butt[12]->callback(mesh_options_ok_cb);
2632 
2633       mesh.butt[13] = new Fl_Check_Button(L + width / 2, 2 * WB + 2 * BH,
2634                                           BW / 2 - WB, BH, "1D element labels");
2635       mesh.butt[13]->tooltip("Mesh.LineLabels");
2636       mesh.butt[13]->type(FL_TOGGLE_BUTTON);
2637       mesh.butt[13]->callback(mesh_options_ok_cb);
2638 
2639       mesh.butt[14] = new Fl_Check_Button(L + width / 2, 2 * WB + 3 * BH,
2640                                           BW / 2 - WB, BH, "2D element labels");
2641       mesh.butt[14]->tooltip("Mesh.SurfaceLabels");
2642       mesh.butt[14]->type(FL_TOGGLE_BUTTON);
2643       mesh.butt[14]->callback(mesh_options_ok_cb);
2644 
2645       mesh.butt[15] = new Fl_Check_Button(L + width / 2, 2 * WB + 4 * BH,
2646                                           BW / 2 - WB, BH, "3D element labels");
2647       mesh.butt[15]->tooltip("Mesh.VolumeLabels");
2648       mesh.butt[15]->type(FL_TOGGLE_BUTTON);
2649       mesh.butt[15]->callback(mesh_options_ok_cb);
2650 
2651       static Fl_Menu_Item menu_label_type[] = {
2652         {"Node/element tag", 0, nullptr, nullptr},
2653         {"Elementary entity tag", 0, nullptr, nullptr},
2654         {"Physical group tag(s)", 0, nullptr, nullptr},
2655         {"Mesh partition", 0, nullptr, nullptr},
2656         {"Coordinates", 0, nullptr, nullptr},
2657         {nullptr}};
2658       mesh.choice[7] =
2659         new Fl_Choice(L + 2 * WB, 2 * WB + 7 * BH, IW, BH, "Label type");
2660       mesh.choice[7]->tooltip("Mesh.LabelType");
2661       mesh.choice[7]->menu(menu_label_type);
2662       mesh.choice[7]->align(FL_ALIGN_RIGHT);
2663       mesh.choice[7]->callback(mesh_options_ok_cb);
2664 
2665       mesh.value[12] =
2666         new Fl_Value_Input(L + width - (int)(0.85 * IW) - 2 * WB,
2667                            2 * WB + 7 * BH, IW / 3, BH, "Sampling");
2668       mesh.value[12]->tooltip("Mesh.LabelSampling");
2669       mesh.value[12]->minimum(1);
2670       mesh.value[12]->maximum(100);
2671       if(CTX::instance()->inputScrolling) mesh.value[12]->step(1);
2672       mesh.value[12]->align(FL_ALIGN_RIGHT);
2673       mesh.value[12]->when(FL_WHEN_RELEASE);
2674       mesh.value[12]->callback(mesh_options_ok_cb);
2675 
2676       static Fl_Menu_Item menu_mesh_element_types[] = {
2677         {"Triangles", 0, nullptr, nullptr, FL_MENU_TOGGLE},
2678         {"Quadrangles", 0, nullptr, nullptr, FL_MENU_TOGGLE},
2679         {"Tetrahedra", 0, nullptr, nullptr, FL_MENU_TOGGLE},
2680         {"Hexahedra", 0, nullptr, nullptr, FL_MENU_TOGGLE},
2681         {"Prisms", 0, nullptr, nullptr, FL_MENU_TOGGLE},
2682         {"Pyramids", 0, nullptr, nullptr, FL_MENU_TOGGLE},
2683         {"Trihedra", 0, nullptr, nullptr, FL_MENU_TOGGLE},
2684         {nullptr}};
2685 
2686       mesh.menu =
2687         new Fl_Menu_Button(L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Elements");
2688       mesh.menu->tooltip(
2689         "Mesh.Triangles, Mesh.Quadrangles, Mesh.Tetrahedra, "
2690         "Mesh.Hexahedra, Mesh.Prisms, Mesh.Pyramids, Mesh.Trihedra");
2691       mesh.menu->menu(menu_mesh_element_types);
2692       mesh.menu->callback(mesh_options_ok_cb);
2693 
2694       mesh.value[4] =
2695         new Fl_Value_Input(L + 2 * WB, 2 * WB + 9 * BH, IW / 4, BH);
2696       mesh.value[4]->tooltip("Mesh.QualityInf");
2697       mesh.value[4]->minimum(0);
2698       mesh.value[4]->maximum(1);
2699       if(CTX::instance()->inputScrolling) mesh.value[4]->step(0.01);
2700       mesh.value[4]->align(FL_ALIGN_RIGHT);
2701       mesh.value[4]->when(FL_WHEN_RELEASE);
2702       mesh.value[4]->callback(mesh_options_ok_cb);
2703 
2704       mesh.value[5] = new Fl_Value_Input(L + 2 * WB + IW / 4, 2 * WB + 9 * BH,
2705                                          IW / 2 - IW / 4, BH);
2706       mesh.value[5]->tooltip("Mesh.QualitySup");
2707       mesh.value[5]->minimum(0);
2708       mesh.value[5]->maximum(1);
2709       if(CTX::instance()->inputScrolling) mesh.value[5]->step(0.01);
2710       mesh.value[5]->align(FL_ALIGN_RIGHT);
2711       mesh.value[5]->when(FL_WHEN_RELEASE);
2712       mesh.value[5]->callback(mesh_options_ok_cb);
2713 
2714       static Fl_Menu_Item menu_quality_type[] = {{"SICN", 0, nullptr, nullptr},
2715                                                  {"SIGE", 0, nullptr, nullptr},
2716                                                  {"Gamma", 0, nullptr, nullptr},
2717                                                  {"Disto", 0, nullptr, nullptr},
2718                                                  {nullptr}};
2719       mesh.choice[6] = new Fl_Choice(L + 2 * WB + IW / 2, 2 * WB + 9 * BH,
2720                                      IW / 2, BH, "Quality range");
2721       mesh.choice[6]->tooltip("Mesh.QualityType");
2722       mesh.choice[6]->menu(menu_quality_type);
2723       mesh.choice[6]->align(FL_ALIGN_RIGHT);
2724       mesh.choice[6]->callback(mesh_options_ok_cb);
2725 
2726       mesh.value[6] =
2727         new Fl_Value_Input(L + 2 * WB, 2 * WB + 10 * BH, IW / 2, BH);
2728       mesh.value[6]->tooltip("Mesh.RadiusInf");
2729       mesh.value[6]->align(FL_ALIGN_RIGHT);
2730       mesh.value[6]->when(FL_WHEN_RELEASE);
2731       mesh.value[6]->callback(mesh_options_ok_cb);
2732 
2733       mesh.value[7] = new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 10 * BH,
2734                                          IW / 2, BH, "Size range");
2735       mesh.value[7]->tooltip("Mesh.RadiusSup");
2736       mesh.value[7]->align(FL_ALIGN_RIGHT);
2737       mesh.value[7]->when(FL_WHEN_RELEASE);
2738       mesh.value[7]->callback(mesh_options_ok_cb);
2739 
2740       mesh.value[8] =
2741         new Fl_Value_Input(L + 2 * WB, 2 * WB + 11 * BH, IW / 2, BH);
2742       mesh.value[8]->tooltip("Mesh.Normals");
2743       mesh.value[8]->minimum(0);
2744       mesh.value[8]->maximum(500);
2745       if(CTX::instance()->inputScrolling) mesh.value[8]->step(1);
2746       mesh.value[8]->align(FL_ALIGN_RIGHT);
2747       mesh.value[8]->when(FL_WHEN_RELEASE);
2748       mesh.value[8]->callback(mesh_options_ok_cb);
2749 
2750       mesh.value[13] = new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 11 * BH,
2751                                           IW / 2, BH, "Normals and tangents");
2752       mesh.value[13]->tooltip("Mesh.Tangents");
2753       mesh.value[13]->minimum(0);
2754       mesh.value[13]->maximum(200);
2755       if(CTX::instance()->inputScrolling) mesh.value[13]->step(1.0);
2756       mesh.value[13]->align(FL_ALIGN_RIGHT);
2757       mesh.value[13]->when(FL_WHEN_RELEASE);
2758       mesh.value[13]->callback(mesh_options_ok_cb);
2759 
2760       o->end();
2761     }
2762     {
2763       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2764                                  height - 2 * WB - BH, "Aspect");
2765       o->hide();
2766 
2767       mesh.value[9] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 1 * BH, IW, BH,
2768                                          "Element shrinking factor");
2769       mesh.value[9]->tooltip("Mesh.Explode");
2770       mesh.value[9]->minimum(0);
2771       mesh.value[9]->maximum(1);
2772       if(CTX::instance()->inputScrolling) mesh.value[9]->step(0.01);
2773       mesh.value[9]->align(FL_ALIGN_RIGHT);
2774       mesh.value[9]->when(FL_WHEN_RELEASE);
2775       mesh.value[9]->callback(mesh_options_ok_cb);
2776 
2777       mesh.choice[0] =
2778         new Fl_Choice(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Point display");
2779       mesh.choice[0]->tooltip("Mesh.PointType");
2780       mesh.choice[0]->menu(menu_point_display);
2781       mesh.choice[0]->align(FL_ALIGN_RIGHT);
2782       mesh.choice[0]->callback(mesh_options_ok_cb);
2783 
2784       mesh.value[10] =
2785         new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW, BH, "Point size");
2786       mesh.value[10]->tooltip("Mesh.PointSize");
2787       mesh.value[10]->minimum(0.1);
2788       mesh.value[10]->maximum(50);
2789       if(CTX::instance()->inputScrolling) mesh.value[10]->step(0.1);
2790       mesh.value[10]->align(FL_ALIGN_RIGHT);
2791       mesh.value[10]->callback(mesh_options_ok_cb);
2792 
2793       mesh.value[11] =
2794         new Fl_Value_Input(L + 2 * WB, 2 * WB + 4 * BH, IW, BH, "Line width");
2795       mesh.value[11]->tooltip("Mesh.LineWidth");
2796       mesh.value[11]->minimum(0.1);
2797       mesh.value[11]->maximum(50);
2798       if(CTX::instance()->inputScrolling) mesh.value[11]->step(0.1);
2799       mesh.value[11]->align(FL_ALIGN_RIGHT);
2800       mesh.value[11]->callback(mesh_options_ok_cb);
2801 
2802       mesh.value[14] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH,
2803                                           "High-order element subdivisions");
2804       mesh.value[14]->tooltip("Mesh.NumSubEdges");
2805       mesh.value[14]->minimum(1);
2806       mesh.value[14]->maximum(10);
2807       if(CTX::instance()->inputScrolling) mesh.value[14]->step(1);
2808       mesh.value[14]->align(FL_ALIGN_RIGHT);
2809       mesh.value[14]->when(FL_WHEN_RELEASE);
2810       mesh.value[14]->callback(mesh_options_ok_cb);
2811 
2812       o->end();
2813     }
2814     {
2815       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2816                                  height - 2 * WB - BH, "Color");
2817       o->hide();
2818 
2819       mesh.butt[17] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW, BH,
2820                                           "Enable lighting");
2821       mesh.butt[17]->tooltip("Mesh.Light (Alt+w)");
2822       mesh.butt[17]->type(FL_TOGGLE_BUTTON);
2823       mesh.butt[17]->callback(mesh_options_ok_cb, (void *)"mesh_light");
2824 
2825       static Fl_Menu_Item menu_mesh_light_lines[] = {
2826         {"No", 0, nullptr, nullptr},
2827         {"Surface", 0, nullptr, nullptr},
2828         {"Volume and surface", 0, nullptr, nullptr},
2829         {nullptr}};
2830       mesh.choice[10] =
2831         new Fl_Choice(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Edge lighting");
2832       mesh.choice[10]->tooltip("Mesh.LightLines");
2833       mesh.choice[10]->menu(menu_mesh_light_lines);
2834       mesh.choice[10]->align(FL_ALIGN_RIGHT);
2835       mesh.choice[10]->callback(mesh_options_ok_cb);
2836 
2837       mesh.butt[18] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH, BW, BH,
2838                                           "Use two-side lighting");
2839       mesh.butt[18]->tooltip("Mesh.LightTwoSide");
2840       mesh.butt[18]->type(FL_TOGGLE_BUTTON);
2841       mesh.butt[18]->callback(mesh_options_ok_cb);
2842 
2843       mesh.butt[19] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
2844                                           "Smooth normals");
2845       mesh.butt[19]->tooltip("Mesh.SmoothNormals");
2846       mesh.butt[19]->type(FL_TOGGLE_BUTTON);
2847       mesh.butt[19]->callback(mesh_options_ok_cb);
2848 
2849       mesh.value[18] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH,
2850                                           "Smoothing threshold angle");
2851       mesh.value[18]->tooltip("Mesh.AngleSmoothNormals");
2852       mesh.value[18]->minimum(0.);
2853       mesh.value[18]->maximum(180.);
2854       if(CTX::instance()->inputScrolling) mesh.value[18]->step(1.);
2855       mesh.value[18]->align(FL_ALIGN_RIGHT);
2856       mesh.value[18]->when(FL_WHEN_RELEASE);
2857       mesh.value[18]->callback(mesh_options_ok_cb);
2858 
2859       static Fl_Menu_Item menu_mesh_color[] = {
2860         {"By element type", 0, nullptr, nullptr},
2861         {"By elementary entity", 0, nullptr, nullptr},
2862         {"By physical group", 0, nullptr, nullptr},
2863         {"By mesh partition", 0, nullptr, nullptr},
2864         {nullptr}};
2865       mesh.choice[4] =
2866         new Fl_Choice(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Coloring mode");
2867       mesh.choice[4]->tooltip("Mesh.ColorCarousel");
2868       mesh.choice[4]->menu(menu_mesh_color);
2869       mesh.choice[4]->align(FL_ALIGN_RIGHT);
2870       mesh.choice[4]->callback(mesh_options_ok_cb);
2871 
2872       Fl_Scroll *s = new Fl_Scroll(L + 2 * WB, 3 * WB + 7 * BH, IW + 20,
2873                                    height - 5 * WB - 7 * BH);
2874       std::size_t i = 0, j = 0;
2875       while(MeshOptions_Color[j].str) {
2876         if(MeshOptions_Color[j].level & GMSH_DEPRECATED) {
2877           j++;
2878           continue;
2879         }
2880         mesh.color[i] = new Fl_Button(L + 2 * WB, 3 * WB + (7 + i) * BH, IW, BH,
2881                                       MeshOptions_Color[j].str);
2882         mesh.color[i]->callback(color_cb,
2883                                 (void *)MeshOptions_Color[j].function);
2884         i++;
2885         j++;
2886         if(i >= mesh.color.size()) {
2887           Msg::Error("Mesh color widget vector should be resized");
2888           break;
2889         }
2890       }
2891       s->end();
2892 
2893       o->end();
2894     }
2895     o->end();
2896   }
2897   mesh.group->end();
2898 
2899   // Solver options
2900   solver.group = new Fl_Group(L, 0, width, height, "Solver Options");
2901   solver.group->hide();
2902   {
2903     Fl_Tabs *o = new Fl_Tabs(L + WB, WB, width - 2 * WB, height - 2 * WB);
2904     {
2905       {
2906         Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2907                                    height - 2 * WB - BH, "General");
2908 
2909         solver.input[0] =
2910           new Fl_Input(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "Base socket name");
2911         solver.input[0]->tooltip("Solver.SocketName");
2912         solver.input[0]->align(FL_ALIGN_RIGHT);
2913         solver.input[0]->callback(solver_options_ok_cb);
2914 
2915         solver.value[0] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW,
2916                                              BH, "Timeout (in seconds)");
2917         solver.value[0]->tooltip("Solver.Timout");
2918         solver.value[0]->align(FL_ALIGN_RIGHT);
2919         solver.value[0]->callback(solver_options_ok_cb);
2920 
2921         solver.butt[0] =
2922           new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH, BW, BH,
2923                               "Always listen to incoming connection requests");
2924         solver.butt[0]->tooltip("Solver.AlwaysListen");
2925         solver.butt[0]->type(FL_TOGGLE_BUTTON);
2926         solver.butt[0]->callback(solver_options_ok_cb);
2927 
2928         solver.input[1] = new Fl_Input(L + 2 * WB, 2 * WB + 4 * BH, IW, BH,
2929                                        "Python interpreter");
2930         solver.input[1]->tooltip("Solver.PythonInterpreter");
2931         solver.input[1]->align(FL_ALIGN_RIGHT);
2932         solver.input[1]->callback(solver_options_ok_cb);
2933 
2934         solver.input[2] = new Fl_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH,
2935                                        "Octave interpreter");
2936         solver.input[2]->tooltip("Solver.OctaveInterpreter");
2937         solver.input[2]->align(FL_ALIGN_RIGHT);
2938         solver.input[2]->callback(solver_options_ok_cb);
2939 
2940         o->end();
2941       }
2942     }
2943     o->end();
2944   }
2945   solver.group->end();
2946 
2947   // Post-processing options
2948   post.group = new Fl_Group(L, 0, width, height, "Post-processing Options");
2949   post.group->hide();
2950   {
2951     Fl_Tabs *o = new Fl_Tabs(L + WB, WB, width - 2 * WB, height - 2 * WB);
2952     {
2953       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
2954                                  height - 2 * WB - BH, "General");
2955 
2956       static Fl_Menu_Item menu_links[] = {
2957         {"Apply next changes to selected views", 0, nullptr, nullptr},
2958         {"Force same options for selected views", 0, nullptr, nullptr},
2959         {nullptr}};
2960 
2961       post.choice[0] =
2962         new Fl_Choice(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "View links");
2963       post.choice[0]->tooltip("PostProcessing.Link");
2964       post.choice[0]->menu(menu_links);
2965       post.choice[0]->align(FL_ALIGN_RIGHT);
2966       post.choice[0]->callback(post_options_ok_cb);
2967 
2968       post.value[0] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW, BH,
2969                                          "Frame duration (in seconds)");
2970       post.value[0]->tooltip("PostProcessing.AnimationDelay");
2971       post.value[0]->minimum(0);
2972       post.value[0]->maximum(10);
2973       if(CTX::instance()->inputScrolling) post.value[0]->step(0.01);
2974       post.value[0]->align(FL_ALIGN_RIGHT);
2975       post.value[0]->callback(post_options_ok_cb);
2976 
2977       post.value[1] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW, BH,
2978                                          "Animation increment step");
2979       post.value[1]->tooltip("PostProcessing.AnimationStep");
2980       post.value[1]->minimum(1);
2981       post.value[1]->maximum(100);
2982       if(CTX::instance()->inputScrolling) post.value[1]->step(1);
2983       post.value[1]->align(FL_ALIGN_RIGHT);
2984       post.value[1]->callback(post_options_ok_cb);
2985 
2986       post.butt[0] =
2987         new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
2988                             "Cycle through views instead of steps");
2989       post.butt[0]->tooltip("PostProcessing.AnimationCycle");
2990       post.butt[0]->type(FL_TOGGLE_BUTTON);
2991       post.butt[0]->callback(post_options_ok_cb);
2992 
2993       post.butt[1] =
2994         new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH,
2995                             "Remove original views after combination");
2996       post.butt[1]->tooltip("PostProcessing.CombineRemoveOriginal");
2997       post.butt[1]->type(FL_TOGGLE_BUTTON);
2998       post.butt[1]->callback(post_options_ok_cb);
2999 
3000       post.butt[2] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH,
3001                                          "Draw value scales horizontally");
3002       post.butt[2]->tooltip("PostProcessing.HorizontalScales");
3003       post.butt[2]->type(FL_TOGGLE_BUTTON);
3004       post.butt[2]->callback(post_options_ok_cb);
3005 
3006       o->end();
3007     }
3008     o->end();
3009   }
3010   post.group->end();
3011 
3012   // View options
3013   view.index = -1;
3014   view.group = new Fl_Group(L, 0, width, height, "View Options");
3015   view.group->hide();
3016   {
3017     Fl_Tabs *o = new Fl_Tabs(L + WB, WB, width - 2 * WB, height - 2 * WB);
3018     {
3019       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
3020                                  height - 2 * WB - BH, "General");
3021 
3022       static Fl_Menu_Item menu_plot_type[] = {{"3D", 0, nullptr, nullptr},
3023                                               {"2D space", 0, nullptr, nullptr},
3024                                               {"2D time", 0, nullptr, nullptr},
3025                                               {"2D", 0, nullptr, nullptr},
3026                                               {nullptr}};
3027       view.choice[13] =
3028         new Fl_Choice(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "Plot type");
3029       view.choice[13]->tooltip("View.Type");
3030       view.choice[13]->menu(menu_plot_type);
3031       view.choice[13]->align(FL_ALIGN_RIGHT);
3032       view.choice[13]->callback(view_options_ok_cb);
3033 
3034       view.input[0] =
3035         new Fl_Input(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "View name");
3036       view.input[0]->tooltip("View.Name");
3037       view.input[0]->align(FL_ALIGN_RIGHT);
3038       view.input[0]->callback(view_options_ok_cb);
3039 
3040       int sw = (int)(1.5 * FL_NORMAL_SIZE);
3041       view.push[3] = new Fl_Button(L + 2 * WB, 2 * WB + 3 * BH, sw, BH, "-");
3042       view.push[3]->callback(view_options_timestep_cb, (void *)"-");
3043       view.push[4] =
3044         new Fl_Button(L + 2 * WB + IW - sw, 2 * WB + 3 * BH, sw, BH, "+");
3045       view.push[4]->callback(view_options_timestep_cb, (void *)"+");
3046       view.value[50] =
3047         new Fl_Value_Input(L + 2 * WB + sw, 2 * WB + 3 * BH, IW - 2 * sw, BH);
3048       view.value[50]->tooltip("View.TimeStep");
3049       view.value[50]->callback(view_options_timestep_cb, (void *)"=");
3050       view.value[50]->align(FL_ALIGN_RIGHT);
3051       view.value[50]->minimum(0);
3052       view.value[50]->maximum(0);
3053       if(CTX::instance()->inputScrolling) view.value[50]->step(1);
3054       view.label[0] =
3055         new Fl_Box(L + 2 * WB + IW, 2 * WB + 3 * BH, width / 2, BH, "Step");
3056       view.label[0]->box(FL_NO_BOX);
3057       view.label[0]->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
3058 
3059       view.range =
3060         new Fl_Group(L + 2 * WB, 2 * WB + 4 * BH, width - 4 * WB, 8 * BH);
3061 
3062       view.value[30] =
3063         new Fl_Value_Input(L + 2 * WB, 2 * WB + 4 * BH, IW, BH, "Intervals");
3064       view.value[30]->tooltip("View.NbIso");
3065       view.value[30]->align(FL_ALIGN_RIGHT);
3066       view.value[30]->minimum(1);
3067       view.value[30]->maximum(256);
3068       if(CTX::instance()->inputScrolling) view.value[30]->step(1);
3069       view.value[30]->when(FL_WHEN_RELEASE);
3070       view.value[30]->callback(view_options_ok_cb);
3071 
3072       view.input[1] =
3073         new Fl_Input(L + width - (int)(0.85 * IW) - 2 * WB, 2 * WB + 4 * BH,
3074                      (int)(0.5 * 0.85 * IW), BH, "Format");
3075       view.input[1]->tooltip("View.Format");
3076       view.input[1]->align(FL_ALIGN_RIGHT);
3077       view.input[1]->callback(view_options_ok_cb);
3078 
3079       static Fl_Menu_Item menu_iso[] = {
3080         {"Iso-values", 0, nullptr, nullptr},
3081         {"Continuous map", 0, nullptr, nullptr},
3082         {"Filled iso-values", 0, nullptr, nullptr},
3083         {"Numeric values", 0, nullptr, nullptr},
3084         {nullptr}};
3085       view.choice[0] =
3086         new Fl_Choice(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Intervals type");
3087       view.choice[0]->tooltip("View.IntervalsType (Alt+t)");
3088       view.choice[0]->menu(menu_iso);
3089       view.choice[0]->align(FL_ALIGN_RIGHT);
3090       view.choice[0]->callback(view_options_ok_cb);
3091 
3092       static Fl_Menu_Item menu_scale[] = {
3093         {"Linear", 0, nullptr, nullptr},
3094         {"Logarithmic", 0, nullptr, nullptr},
3095         {"Double logarithmic", 0, nullptr, nullptr},
3096         {nullptr}};
3097       view.choice[1] = new Fl_Choice(L + width - (int)(0.85 * IW) - 2 * WB,
3098                                      2 * WB + 5 * BH, (int)(0.85 * IW), BH);
3099       view.choice[1]->tooltip("View.ScaleType");
3100       view.choice[1]->menu(menu_scale);
3101       view.choice[1]->align(FL_ALIGN_RIGHT);
3102       view.choice[1]->callback(view_options_ok_cb);
3103 
3104       static Fl_Menu_Item menu_range[] = {{"Default", 0, nullptr, nullptr},
3105                                           {"Custom", 0, nullptr, nullptr},
3106                                           {"Per step", 0, nullptr, nullptr},
3107                                           {nullptr}};
3108       view.choice[7] =
3109         new Fl_Choice(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Range mode");
3110       view.choice[7]->tooltip("View.RangeType (Alt+r)");
3111       view.choice[7]->menu(menu_range);
3112       view.choice[7]->align(FL_ALIGN_RIGHT);
3113       view.choice[7]->callback(view_options_ok_cb, (void *)"custom_range");
3114 
3115       view.butt[38] =
3116         new Fl_Check_Button(L + width - (int)(0.85 * IW) - 2 * WB,
3117                             2 * WB + 6 * BH, (int)(0.85 * IW), BH, "Saturate");
3118       view.butt[38]->tooltip("View.SaturateValues");
3119       view.butt[38]->type(FL_TOGGLE_BUTTON);
3120       view.butt[38]->callback(view_options_ok_cb);
3121 
3122       int sw2 = (int)(2.5 * FL_NORMAL_SIZE);
3123       view.push[1] = new Fl_Button(L + 2 * WB, 2 * WB + 7 * BH, sw2, BH, "Min");
3124       view.push[1]->callback(view_options_ok_cb, (void *)"range_min");
3125       view.value[31] = new Fl_Value_Input(L + 2 * WB + sw2, 2 * WB + 7 * BH,
3126                                           IW - sw2, BH, "Custom min");
3127       view.value[31]->tooltip("View.CustomMin");
3128       view.value[31]->align(FL_ALIGN_RIGHT);
3129       view.value[31]->when(FL_WHEN_RELEASE);
3130       view.value[31]->callback(view_options_ok_cb);
3131 
3132       view.push[2] = new Fl_Button(L + 2 * WB, 2 * WB + 8 * BH, sw2, BH, "Max");
3133       view.push[2]->callback(view_options_ok_cb, (void *)"range_max");
3134       view.value[32] = new Fl_Value_Input(L + 2 * WB + sw2, 2 * WB + 8 * BH,
3135                                           IW - sw2, BH, "Custom max");
3136       view.value[32]->tooltip("View.CustomMax");
3137       view.value[32]->align(FL_ALIGN_RIGHT);
3138       view.value[32]->when(FL_WHEN_RELEASE);
3139       view.value[32]->callback(view_options_ok_cb);
3140 
3141       view.butt[0] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 9 * BH, BW, BH,
3142                                          "Adapt visualization grid");
3143       view.butt[0]->tooltip("View.AdaptVisualizationGrid");
3144       view.butt[0]->type(FL_TOGGLE_BUTTON);
3145       view.butt[0]->callback(view_options_ok_cb, (void *)"view_adaptive");
3146 
3147       view.push[5] = new Fl_Button(L + 2 * WB, 2 * WB + 10 * BH, sw, BH, "-");
3148       view.push[5]->callback(view_options_max_recursion_cb, (void *)"-");
3149       view.push[6] =
3150         new Fl_Button(L + 2 * WB + IW - sw, 2 * WB + 10 * BH, sw, BH, "+");
3151       view.push[6]->callback(view_options_max_recursion_cb, (void *)"+");
3152       view.value[33] =
3153         new Fl_Value_Input(L + 2 * WB + sw, 2 * WB + 10 * BH, IW - 2 * sw, BH);
3154       view.value[33]->tooltip("View.MaxRecursionLevel");
3155       view.value[33]->align(FL_ALIGN_RIGHT);
3156       view.value[33]->minimum(0);
3157       view.value[33]->maximum(6);
3158       if(CTX::instance()->inputScrolling) view.value[33]->step(1);
3159       view.value[33]->when(FL_WHEN_RELEASE);
3160       view.value[33]->callback(view_options_ok_cb);
3161       view.label[1] = new Fl_Box(L + 2 * WB + IW, 2 * WB + 10 * BH, width / 2,
3162                                  BH, "Maximum recursion level");
3163       view.label[1]->box(FL_NO_BOX);
3164       view.label[1]->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
3165 
3166       view.value[34] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 11 * BH, IW, BH,
3167                                           "Target visualization error");
3168       view.value[34]->tooltip("View.TargetError");
3169       view.value[34]->align(FL_ALIGN_RIGHT);
3170       view.value[34]->minimum(-1.e-4);
3171       view.value[34]->maximum(0.1);
3172       if(CTX::instance()->inputScrolling) view.value[34]->step(1.e-4);
3173       view.value[34]->when(FL_WHEN_RELEASE);
3174       view.value[34]->callback(view_options_ok_cb);
3175 
3176       view.range->end();
3177 
3178       o->end();
3179     }
3180     {
3181       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
3182                                  height - 2 * WB - BH, "Axes");
3183       o->hide();
3184 
3185       view.choice[8] =
3186         new Fl_Choice(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "Axes mode");
3187       view.choice[8]->tooltip("View.Axes (Alt+a)");
3188       view.choice[8]->menu(menu_axes_mode);
3189       view.choice[8]->align(FL_ALIGN_RIGHT);
3190       view.choice[8]->callback(view_options_ok_cb, (void *)"view_axes");
3191 
3192       view.butt[3] = new Fl_Check_Button(L + width - (int)(0.85 * IW) - 2 * WB,
3193                                          2 * WB + 1 * BH, (int)(0.85 * IW), BH,
3194                                          "Mikado style");
3195       view.butt[3]->tooltip("View.AxesMikado");
3196       view.butt[3]->type(FL_TOGGLE_BUTTON);
3197       view.butt[3]->callback(view_options_ok_cb);
3198 
3199       view.value[3] =
3200         new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW / 3, BH);
3201       view.value[3]->tooltip("View.AxesTicsX");
3202       view.value[3]->minimum(0.);
3203       if(CTX::instance()->inputScrolling) view.value[3]->step(1);
3204       view.value[3]->maximum(100);
3205       view.value[3]->callback(view_options_ok_cb);
3206       view.value[4] = new Fl_Value_Input(L + 2 * WB + 1 * IW / 3,
3207                                          2 * WB + 2 * BH, IW / 3, BH);
3208       view.value[4]->tooltip("View.AxesTicsY");
3209       view.value[4]->minimum(0.);
3210       if(CTX::instance()->inputScrolling) view.value[4]->step(1);
3211       view.value[4]->maximum(100);
3212       view.value[4]->callback(view_options_ok_cb);
3213       view.value[5] = new Fl_Value_Input(
3214         L + 2 * WB + 2 * IW / 3, 2 * WB + 2 * BH, IW / 3, BH, "Axes tics");
3215       view.value[5]->tooltip("View.AxesTicsZ");
3216       view.value[5]->minimum(0.);
3217       if(CTX::instance()->inputScrolling) view.value[5]->step(1);
3218       view.value[5]->maximum(100);
3219       view.value[5]->align(FL_ALIGN_RIGHT);
3220       view.value[5]->callback(view_options_ok_cb);
3221 
3222       view.input[7] = new Fl_Input(L + 2 * WB, 2 * WB + 3 * BH, IW / 3, BH);
3223       view.input[7]->tooltip("View.AxesFormatX");
3224       view.input[7]->callback(view_options_ok_cb);
3225       view.input[8] =
3226         new Fl_Input(L + 2 * WB + 1 * IW / 3, 2 * WB + 3 * BH, IW / 3, BH);
3227       view.input[8]->tooltip("View.AxesFormatY");
3228       view.input[8]->callback(view_options_ok_cb);
3229       view.input[9] = new Fl_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 3 * BH,
3230                                    IW / 3, BH, "Axes format");
3231       view.input[9]->tooltip("View.AxesFormatZ");
3232       view.input[9]->align(FL_ALIGN_RIGHT);
3233       view.input[9]->callback(view_options_ok_cb);
3234 
3235       view.input[10] = new Fl_Input(L + 2 * WB, 2 * WB + 4 * BH, IW / 3, BH);
3236       view.input[10]->tooltip("View.AxesLabelX");
3237       view.input[10]->callback(view_options_ok_cb);
3238       view.input[11] =
3239         new Fl_Input(L + 2 * WB + 1 * IW / 3, 2 * WB + 4 * BH, IW / 3, BH);
3240       view.input[11]->tooltip("View.AxesLabelY");
3241       view.input[11]->callback(view_options_ok_cb);
3242       view.input[12] = new Fl_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 4 * BH,
3243                                     IW / 3, BH, "Axes labels");
3244       view.input[12]->tooltip("View.AxesLabelZ");
3245       view.input[12]->align(FL_ALIGN_RIGHT);
3246       view.input[12]->callback(view_options_ok_cb);
3247 
3248       view.butt[25] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH,
3249                                           "Position 3D axes automatically");
3250       view.butt[25]->tooltip("View.AxesAutoPosition");
3251       view.butt[25]->type(FL_TOGGLE_BUTTON);
3252       view.butt[25]->callback(view_options_ok_cb, (void *)"view_axes_auto_3d");
3253 
3254       view.value[13] =
3255         new Fl_Value_Input(L + 2 * WB, 2 * WB + 6 * BH, IW / 3, BH);
3256       view.value[13]->tooltip("View.AxesMinX");
3257       view.value[13]->callback(view_options_ok_cb);
3258       view.value[14] =
3259         new Fl_Value_Input(L + 2 * WB + IW / 3, 2 * WB + 6 * BH, IW / 3, BH);
3260       view.value[14]->tooltip("View.AxesMinY");
3261       view.value[14]->callback(view_options_ok_cb);
3262       view.value[15] =
3263         new Fl_Value_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 6 * BH, IW / 3, BH,
3264                            "3D axes minimum");
3265       view.value[15]->tooltip("View.AxesMinZ");
3266       view.value[15]->align(FL_ALIGN_RIGHT);
3267       view.value[15]->callback(view_options_ok_cb);
3268 
3269       view.value[16] =
3270         new Fl_Value_Input(L + 2 * WB, 2 * WB + 7 * BH, IW / 3, BH);
3271       view.value[16]->tooltip("View.AxesMaxX");
3272       view.value[16]->callback(view_options_ok_cb);
3273       view.value[17] =
3274         new Fl_Value_Input(L + 2 * WB + IW / 3, 2 * WB + 7 * BH, IW / 3, BH);
3275       view.value[17]->tooltip("View.AxesMaxY");
3276       view.value[17]->callback(view_options_ok_cb);
3277       view.value[18] =
3278         new Fl_Value_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 7 * BH, IW / 3, BH,
3279                            "3D axes maximum");
3280       view.value[18]->tooltip("View.AxesMaxZ");
3281       view.value[18]->align(FL_ALIGN_RIGHT);
3282       view.value[18]->callback(view_options_ok_cb);
3283 
3284       view.choice[16] = new Fl_Choice(L + 2 * WB, 2 * WB + 8 * BH, IW, BH,
3285                                       "2D axes/value scale position");
3286       view.choice[16]->tooltip("View.AutoPosition");
3287       view.choice[16]->menu(menu_position);
3288       view.choice[16]->align(FL_ALIGN_RIGHT);
3289       view.choice[16]->callback(view_options_ok_cb,
3290                                 (void *)"view_axes_auto_2d");
3291 
3292       view.value[20] =
3293         new Fl_Value_Input(L + 2 * WB, 2 * WB + 9 * BH, IW / 2, BH);
3294       view.value[20]->minimum(-2000);
3295       view.value[20]->maximum(2000);
3296       if(CTX::instance()->inputScrolling) view.value[20]->step(0.5);
3297       view.value[20]->callback(view_options_ok_cb);
3298       view.value[21] =
3299         new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 9 * BH, IW / 2, BH,
3300                            "2D axes/value scale position");
3301       view.value[21]->align(FL_ALIGN_RIGHT);
3302       view.value[21]->minimum(-2000);
3303       view.value[21]->maximum(2000);
3304       if(CTX::instance()->inputScrolling) view.value[21]->step(0.5);
3305       view.value[21]->callback(view_options_ok_cb);
3306 
3307       view.value[22] =
3308         new Fl_Value_Input(L + 2 * WB, 2 * WB + 10 * BH, IW / 2, BH);
3309       view.value[22]->tooltip("View.PositionX");
3310       view.value[22]->minimum(0);
3311       view.value[22]->maximum(2000);
3312       if(CTX::instance()->inputScrolling) view.value[22]->step(0.5);
3313       view.value[22]->callback(view_options_ok_cb);
3314       view.value[23] =
3315         new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 10 * BH, IW / 2, BH,
3316                            "2D axes/value scale size");
3317       view.value[23]->tooltip("View.PositionY");
3318       view.value[23]->align(FL_ALIGN_RIGHT);
3319       view.value[23]->minimum(0);
3320       view.value[23]->maximum(2000);
3321       if(CTX::instance()->inputScrolling) view.value[23]->step(0.5);
3322       view.value[23]->callback(view_options_ok_cb);
3323 
3324       o->end();
3325     }
3326     {
3327       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
3328                                  height - 2 * WB - BH, "Visibility");
3329       o->hide();
3330 
3331       view.butt[4] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW, BH,
3332                                          "Show value scale");
3333       view.butt[4]->tooltip("View.ShowScale (Alt+i)");
3334       view.butt[4]->type(FL_TOGGLE_BUTTON);
3335       view.butt[4]->callback(view_options_ok_cb);
3336 
3337       static Fl_Menu_Item time_display[] = {
3338         {"None", 0, nullptr, nullptr},
3339         {"Time series", 0, nullptr, nullptr},
3340         {"Harmonic data", 0, nullptr, nullptr},
3341         {"Automatic", 0, nullptr, nullptr},
3342         {"Step data", 0, nullptr, nullptr},
3343         {"Multi-step data", 0, nullptr, nullptr},
3344         {"Real eigenvalues", 0, nullptr, nullptr},
3345         {"Complex eigenvalues", 0, nullptr, nullptr},
3346         {nullptr}};
3347       view.choice[12] =
3348         new Fl_Choice(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Time display");
3349       view.choice[12]->tooltip("View.ShowTime");
3350       view.choice[12]->menu(time_display);
3351       view.choice[12]->align(FL_ALIGN_RIGHT);
3352       view.choice[12]->callback(view_options_ok_cb);
3353 
3354       view.butt[5] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH, BW, BH,
3355                                          "Show annotations");
3356       view.butt[5]->tooltip("View.DrawStrings (Alt+n)");
3357       view.butt[5]->type(FL_TOGGLE_BUTTON);
3358       view.butt[5]->callback(view_options_ok_cb);
3359 
3360       view.butt[10] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
3361                                           "Draw element outlines");
3362       view.butt[10]->tooltip("View.ShowElement (Alt+e)");
3363       view.butt[10]->type(FL_TOGGLE_BUTTON);
3364       view.butt[10]->callback(view_options_ok_cb);
3365 
3366       view.butt[2] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH,
3367                                          "Draw only skin of 3D views");
3368       view.butt[2]->tooltip("View.DrawSkinOnly");
3369       view.butt[2]->type(FL_TOGGLE_BUTTON);
3370       view.butt[2]->callback(view_options_ok_cb);
3371 
3372       static Fl_Menu_Item menu_view_element_types[] = {
3373         {"Points", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3374         {"Lines", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3375         {"Triangles", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3376         {"Quadrangles", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3377         {"Tetrahedra", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3378         {"Hexahedra", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3379         {"Prisms", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3380         {"Pyramids", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3381         {nullptr}};
3382 
3383       view.menu[1] =
3384         new Fl_Menu_Button(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Elements");
3385       view.menu[1]->tooltip(
3386         "View.DrawPoints, View.DrawLines, View.DrawTriangles, "
3387         "View.DrawQuadrangles, View.DrawTetrahedra, View.DrawHexahedra, "
3388         "View.DrawPrisms, View.DrawPyramids");
3389       view.menu[1]->menu(menu_view_element_types);
3390       view.menu[1]->callback(view_options_ok_cb);
3391 
3392       view.value[6] = new Fl_Value_Input(L + 3 * WB + IW, 2 * WB + 6 * BH,
3393                                          IW / 3, BH, "Sampling");
3394       view.value[6]->tooltip("View.Sampling");
3395       view.value[6]->minimum(1);
3396       view.value[6]->maximum(100);
3397       if(CTX::instance()->inputScrolling) view.value[6]->step(1);
3398       view.value[6]->align(FL_ALIGN_RIGHT);
3399       view.value[6]->when(FL_WHEN_RELEASE);
3400       view.value[6]->callback(view_options_ok_cb);
3401 
3402       static Fl_Menu_Item menu_boundary[] = {
3403         {"None", 0, nullptr, nullptr},
3404         {"Dimension - 1", 0, nullptr, nullptr},
3405         {"Dimension - 2", 0, nullptr, nullptr},
3406         {"Dimension - 3", 0, nullptr, nullptr},
3407         {nullptr}};
3408       view.choice[9] = new Fl_Choice(L + 2 * WB, 2 * WB + 7 * BH, IW, BH,
3409                                      "Element boundary mode");
3410       view.choice[9]->tooltip("View.Boundary");
3411       view.choice[9]->menu(menu_boundary);
3412       view.choice[9]->align(FL_ALIGN_RIGHT);
3413       view.choice[9]->callback(view_options_ok_cb);
3414 
3415       view.value[0] =
3416         new Fl_Value_Input(L + 2 * WB, 2 * WB + 8 * BH, IW / 2, BH);
3417       view.value[0]->tooltip("View.Normals");
3418       view.value[0]->minimum(0);
3419       view.value[0]->maximum(500);
3420       if(CTX::instance()->inputScrolling) view.value[0]->step(1);
3421       view.value[0]->align(FL_ALIGN_RIGHT);
3422       view.value[0]->when(FL_WHEN_RELEASE);
3423       view.value[0]->callback(view_options_ok_cb);
3424 
3425       view.value[1] = new Fl_Value_Input(L + 2 * WB + IW / 2, 2 * WB + 8 * BH,
3426                                          IW / 2, BH, "Normals and tangents");
3427       view.value[1]->tooltip("View.Tangents");
3428       view.value[1]->minimum(0);
3429       view.value[1]->maximum(500);
3430       if(CTX::instance()->inputScrolling) view.value[1]->step(1);
3431       view.value[1]->align(FL_ALIGN_RIGHT);
3432       view.value[1]->when(FL_WHEN_RELEASE);
3433       view.value[1]->callback(view_options_ok_cb);
3434 
3435       static Fl_Menu_Item menu_view_field_types[] = {
3436         {"Scalar", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3437         {"Vector", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3438         {"Tensor", 0, nullptr, nullptr, FL_MENU_TOGGLE},
3439         {nullptr}};
3440       view.menu[0] =
3441         new Fl_Menu_Button(L + 2 * WB, 2 * WB + 9 * BH, IW, BH, "Fields");
3442       view.menu[0]->tooltip(
3443         "View.DrawScalars, View.DrawVectors, View.DrawTensors");
3444       view.menu[0]->menu(menu_view_field_types);
3445       view.menu[0]->callback(view_options_ok_cb);
3446 
3447       static Fl_Menu_Item menu_force_field_type[] = {
3448         {"Original Field", 0, nullptr, nullptr},
3449         {"Force Scalar", 0, nullptr, nullptr},
3450         {"Force Vector", 0, nullptr, nullptr},
3451         {"Force Tensor", 0, nullptr, nullptr},
3452         {nullptr}};
3453       view.choice[14] = new Fl_Choice(L + 2 * WB, 2 * WB + 10 * BH, IW, BH);
3454       view.choice[14]->tooltip("View.ForceNumComponents");
3455       view.choice[14]->menu(menu_force_field_type);
3456       view.choice[14]->align(FL_ALIGN_RIGHT);
3457       view.choice[14]->callback(view_options_ok_cb);
3458 
3459       for(int i = 0; i < 9; i++) {
3460         int W = width - 5 * WB - IW;
3461         int w = W / 9;
3462         view.value[70 + i] =
3463           new Fl_Value_Input(L + 3 * WB + IW + i * w, 2 * WB + 10 * BH, w, BH);
3464         view.value[70 + i]->tooltip("View.ComponentMap");
3465         view.value[70 + i]->minimum(-1);
3466         view.value[70 + i]->maximum(9);
3467         if(CTX::instance()->inputScrolling) view.value[70 + i]->step(1);
3468         view.value[70 + i]->callback(view_options_ok_cb);
3469       }
3470 
3471       o->end();
3472     }
3473     {
3474       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
3475                                  height - 2 * WB - BH, "Transfo");
3476       o->hide();
3477 
3478       Fl_Box *b = new Fl_Box(FL_NO_BOX, L + 2 * WB, 2 * WB + 1 * BH, IW, BH,
3479                              "Coordinate transformation:");
3480       b->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT);
3481 
3482       int ss = 2 * IW / 3 / 3 + 4;
3483       view.value[51] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, ss, BH);
3484       view.value[51]->tooltip("View.TransformXX");
3485       view.value[52] =
3486         new Fl_Value_Input(L + 2 * WB + ss, 2 * WB + 2 * BH, ss, BH);
3487       view.value[52]->tooltip("View.TransformXY");
3488       view.value[53] =
3489         new Fl_Value_Input(L + 2 * WB + 2 * ss, 2 * WB + 2 * BH, ss, BH, " X");
3490       view.value[53]->tooltip("View.TransformXZ");
3491       view.value[40] =
3492         new inputValueFloat(L + 2 * WB + IW, 2 * WB + 2 * BH, 7 * IW / 10, BH);
3493       view.value[40]->tooltip("View.OffsetX");
3494 
3495       view.value[54] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, ss, BH);
3496       view.value[54]->tooltip("View.TransformYX");
3497       view.value[55] =
3498         new Fl_Value_Input(L + 2 * WB + ss, 2 * WB + 3 * BH, ss, BH);
3499       view.value[55]->tooltip("View.TransformYY");
3500       view.value[56] = new Fl_Value_Input(L + 2 * WB + 2 * ss, 2 * WB + 3 * BH,
3501                                           ss, BH, " Y +");
3502       view.value[56]->tooltip("View.TransformYZ");
3503       view.value[41] =
3504         new inputValueFloat(L + 2 * WB + IW, 2 * WB + 3 * BH, 7 * IW / 10, BH);
3505       view.value[41]->tooltip("View.OffsetY");
3506 
3507       view.value[57] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 4 * BH, ss, BH);
3508       view.value[57]->tooltip("View.TransformZX");
3509       view.value[58] =
3510         new Fl_Value_Input(L + 2 * WB + ss, 2 * WB + 4 * BH, ss, BH);
3511       view.value[58]->tooltip("View.TransformZY");
3512       view.value[59] =
3513         new Fl_Value_Input(L + 2 * WB + 2 * ss, 2 * WB + 4 * BH, ss, BH, " Z");
3514       view.value[59]->tooltip("View.TransformZZ");
3515       view.value[42] =
3516         new inputValueFloat(L + 2 * WB + IW, 2 * WB + 4 * BH, 7 * IW / 10, BH);
3517       view.value[42]->tooltip("View.OffsetZ");
3518 
3519       Fl_Box *b2 = new Fl_Box(FL_NO_BOX, L + 2 * WB + 2 * IW - 3 * WB,
3520                               2 * WB + 1 * BH, 7 * IW / 10, BH, "Raise:");
3521       b2->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT);
3522 
3523       view.value[43] = new inputValueFloat(L + 2 * WB + 2 * IW - 3 * WB,
3524                                            2 * WB + 2 * BH, 7 * IW / 10, BH);
3525       view.value[43]->tooltip("View.RaizeX");
3526       view.value[44] = new inputValueFloat(L + 2 * WB + 2 * IW - 3 * WB,
3527                                            2 * WB + 3 * BH, 7 * IW / 10, BH);
3528       view.value[44]->tooltip("View.RaizeY");
3529       view.value[45] = new inputValueFloat(L + 2 * WB + 2 * IW - 3 * WB,
3530                                            2 * WB + 4 * BH, 7 * IW / 10, BH);
3531       view.value[45]->tooltip("View.RaizeZ");
3532       view.value[46] = new inputValueFloat(L + 2 * WB, 2 * WB + 5 * BH, 3 * ss,
3533                                            BH, "Normal raise");
3534       view.value[46]->tooltip("View.NormalRaize");
3535 
3536       for(int i = 40; i <= 46; i++) {
3537         view.value[i]->align(FL_ALIGN_RIGHT);
3538         view.value[i]->when(FL_WHEN_RELEASE);
3539         view.value[i]->callback(view_options_ok_cb);
3540       }
3541       for(int i = 51; i <= 59; i++) {
3542         view.value[i]->minimum(-1.);
3543         view.value[i]->maximum(1.);
3544         if(CTX::instance()->inputScrolling) view.value[i]->step(0.1);
3545         view.value[i]->align(FL_ALIGN_RIGHT);
3546         view.value[i]->when(FL_WHEN_RELEASE);
3547         view.value[i]->callback(view_options_ok_cb);
3548       }
3549 
3550       view.butt[6] =
3551         new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH,
3552                             "Use general transformation expressions");
3553       view.butt[6]->tooltip("View.UseGeneralizedRaise");
3554       view.butt[6]->type(FL_TOGGLE_BUTTON);
3555       view.butt[6]->callback(view_options_ok_cb,
3556                              (void *)"view_general_transform");
3557 
3558       view.choice[11] =
3559         new Fl_Choice(L + 2 * WB, 2 * WB + 7 * BH, IW, BH, "Data source");
3560       view.choice[11]->tooltip("View.GeneralizedRaiseView");
3561       view.choice[11]->align(FL_ALIGN_RIGHT);
3562       view.choice[11]->add("Self");
3563       view.choice[11]->callback(view_options_ok_cb);
3564 
3565       view.value[2] =
3566         new inputValueFloat(L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Factor");
3567       view.value[2]->tooltip("View.GeneralizedRaiseFactor");
3568       view.value[2]->align(FL_ALIGN_RIGHT);
3569       view.value[2]->when(FL_WHEN_RELEASE);
3570       view.value[2]->callback(view_options_ok_cb);
3571 
3572       view.input[4] =
3573         new Fl_Input(L + 2 * WB, 2 * WB + 9 * BH, IW, BH, "X expression");
3574       view.input[4]->tooltip("View.GeneralizedRaiseX");
3575       view.input[4]->align(FL_ALIGN_RIGHT);
3576       view.input[4]->callback(view_options_ok_cb);
3577 
3578       view.input[5] =
3579         new Fl_Input(L + 2 * WB, 2 * WB + 10 * BH, IW, BH, "Y expression");
3580       view.input[5]->tooltip("View.GeneralizedRaiseY");
3581       view.input[5]->align(FL_ALIGN_RIGHT);
3582       view.input[5]->callback(view_options_ok_cb);
3583 
3584       view.input[6] =
3585         new Fl_Input(L + 2 * WB, 2 * WB + 11 * BH, IW, BH, "Z expression");
3586       view.input[6]->tooltip("View.GeneralizedRaiseZ");
3587       view.input[6]->align(FL_ALIGN_RIGHT);
3588       view.input[6]->callback(view_options_ok_cb);
3589 
3590       o->end();
3591     }
3592     {
3593       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
3594                                  height - 2 * WB - BH, "Aspect");
3595       o->hide();
3596 
3597       view.value[12] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 1 * BH, IW, BH,
3598                                           "Element shrinking factor");
3599       view.value[12]->tooltip("View.Explode");
3600       view.value[12]->minimum(0.);
3601       if(CTX::instance()->inputScrolling) view.value[12]->step(0.01);
3602       view.value[12]->maximum(1.);
3603       view.value[12]->align(FL_ALIGN_RIGHT);
3604       view.value[12]->when(FL_WHEN_RELEASE);
3605       view.value[12]->callback(view_options_ok_cb);
3606 
3607       view.choice[5] =
3608         new Fl_Choice(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Point display");
3609       view.choice[5]->tooltip("View.PointType");
3610       view.choice[5]->menu(menu_point_display_post);
3611       view.choice[5]->align(FL_ALIGN_RIGHT);
3612       view.choice[5]->callback(view_options_ok_cb);
3613 
3614       view.value[61] =
3615         new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW, BH, "Point size");
3616       view.value[61]->tooltip("View.PointSize");
3617       view.value[61]->minimum(0.1);
3618       view.value[61]->maximum(50);
3619       if(CTX::instance()->inputScrolling) view.value[61]->step(0.1);
3620       view.value[61]->align(FL_ALIGN_RIGHT);
3621       view.value[61]->callback(view_options_ok_cb);
3622 
3623       view.choice[6] =
3624         new Fl_Choice(L + 2 * WB, 2 * WB + 4 * BH, IW, BH, "Line display");
3625       view.choice[6]->tooltip("View.LineType");
3626       view.choice[6]->menu(menu_line_display_post);
3627       view.choice[6]->align(FL_ALIGN_RIGHT);
3628       view.choice[6]->callback(view_options_ok_cb);
3629 
3630       view.butt[26] =
3631         new Fl_Check_Button(L + width - (int)(0.85 * IW) - 2 * WB,
3632                             2 * WB + 4 * BH, (int)(0.85 * IW), BH, "Stipple");
3633       view.butt[26]->tooltip("View.Stipple");
3634       view.butt[26]->type(FL_TOGGLE_BUTTON);
3635       view.butt[26]->callback(view_options_ok_cb);
3636 
3637       view.value[62] =
3638         new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Line width");
3639       view.value[62]->tooltip("View.LineWidth");
3640       view.value[62]->minimum(0.1);
3641       view.value[62]->maximum(50);
3642       if(CTX::instance()->inputScrolling) view.value[62]->step(0.1);
3643       view.value[62]->align(FL_ALIGN_RIGHT);
3644       view.value[62]->callback(view_options_ok_cb);
3645 
3646       {
3647         static Fl_Menu_Item menu_vectype[] = {
3648           {"Line", 0, nullptr, nullptr},
3649           {"Arrow", 0, nullptr, nullptr},
3650           {"Pyramid", 0, nullptr, nullptr},
3651           {"3D arrow", 0, nullptr, nullptr},
3652           {"Displacement", 0, nullptr, nullptr},
3653           {"Comet", 0, nullptr, nullptr},
3654           {nullptr}};
3655         view.choice[2] =
3656           new Fl_Choice(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Vector display");
3657         view.choice[2]->tooltip("View.VectorType");
3658         view.choice[2]->menu(menu_vectype);
3659         view.choice[2]->align(FL_ALIGN_RIGHT);
3660         view.choice[2]->callback(view_options_ok_cb);
3661 
3662         view.value[64] =
3663           new Fl_Value_Input(L + 2 * WB, 2 * WB + 7 * BH, IW / 2, BH);
3664         view.value[64]->tooltip("View.ArrowSizeMin");
3665         view.value[64]->minimum(0);
3666         view.value[64]->maximum(500);
3667         if(CTX::instance()->inputScrolling) view.value[64]->step(1);
3668         view.value[64]->align(FL_ALIGN_RIGHT);
3669         view.value[64]->callback(view_options_ok_cb);
3670         view.value[60] = new Fl_Value_Input(
3671           L + 2 * WB + IW / 2, 2 * WB + 7 * BH, IW / 2, BH, "Arrow size");
3672         view.value[60]->tooltip("View.ArrowSizeMax");
3673         view.value[60]->minimum(0);
3674         view.value[60]->maximum(500);
3675         if(CTX::instance()->inputScrolling) view.value[60]->step(1);
3676         view.value[60]->align(FL_ALIGN_RIGHT);
3677         view.value[60]->callback(view_options_ok_cb);
3678 
3679         view.value[63] = new inputValueFloat(L + 2 * WB, 2 * WB + 8 * BH, IW,
3680                                              BH, "Displacement factor");
3681         view.value[63]->tooltip("View.DisplacementFactor");
3682         view.value[63]->minimum(0.);
3683         view.value[63]->maximum(1.);
3684         if(CTX::instance()->inputScrolling) view.value[63]->step(0.01);
3685         view.value[63]->align(FL_ALIGN_RIGHT);
3686         view.value[63]->when(FL_WHEN_RELEASE);
3687         view.value[63]->callback(view_options_ok_cb);
3688 
3689         view.choice[10] = new Fl_Choice(L + 2 * WB, 2 * WB + 9 * BH, IW, BH,
3690                                         "Data source for vector fields");
3691         view.choice[10]->tooltip("View.ExternalView");
3692         view.choice[10]->align(FL_ALIGN_RIGHT);
3693         view.choice[10]->add("Self");
3694         view.choice[10]->callback(view_options_ok_cb);
3695       }
3696 
3697       static Fl_Menu_Item menu_glyph_loc[] = {
3698         {"Barycenter", 0, nullptr, nullptr},
3699         {"Node", 0, nullptr, nullptr},
3700         {nullptr}};
3701       view.choice[3] =
3702         new Fl_Choice(L + 2 * WB, 2 * WB + 10 * BH, IW, BH, "Glyph location");
3703       view.choice[3]->tooltip("View.GlyphLocation");
3704       view.choice[3]->menu(menu_glyph_loc);
3705       view.choice[3]->align(FL_ALIGN_RIGHT);
3706       view.choice[3]->callback(view_options_ok_cb);
3707 
3708       static Fl_Menu_Item menu_glyph_center[] = {
3709         {"Left-aligned", 0, nullptr, nullptr},
3710         {"Centered", 0, nullptr, nullptr},
3711         {"Right-aligned", 0, nullptr, nullptr},
3712         {nullptr}};
3713       view.choice[15] = new Fl_Choice(L + width - (int)(0.85 * IW) - 2 * WB,
3714                                       2 * WB + 10 * BH, (int)(0.85 * IW), BH);
3715       view.choice[15]->tooltip("View.CenterGlyphs");
3716       view.choice[15]->menu(menu_glyph_center);
3717       view.choice[15]->callback(view_options_ok_cb);
3718 
3719       static Fl_Menu_Item menu_tensor[] = {
3720         {"Von-Mises", 0, nullptr, nullptr},
3721         {"Maximum eigenvalue", 0, nullptr, nullptr},
3722         {"Minimum eigenvalue", 0, nullptr, nullptr},
3723         {"Eigenvectors", 0, nullptr, nullptr},
3724         {"Ellipse", 0, nullptr, nullptr},
3725         {"Ellipsoid", 0, nullptr, nullptr},
3726         {"Frame", 0, nullptr, nullptr},
3727         {nullptr}};
3728       view.choice[4] =
3729         new Fl_Choice(L + 2 * WB, 2 * WB + 11 * BH, IW, BH, "Tensor display");
3730       view.choice[4]->tooltip("View.TensorType");
3731       view.choice[4]->menu(menu_tensor);
3732       view.choice[4]->align(FL_ALIGN_RIGHT);
3733       view.choice[4]->callback(view_options_ok_cb);
3734 
3735       o->end();
3736     }
3737     {
3738       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
3739                                  height - 2 * WB - BH, "Color");
3740       o->hide();
3741 
3742       view.butt[11] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW, BH,
3743                                           "Enable lighting");
3744       view.butt[11]->tooltip("View.Light (Alt+w)");
3745       view.butt[11]->type(FL_TOGGLE_BUTTON);
3746       view.butt[11]->callback(view_options_ok_cb, (void *)"view_light");
3747 
3748       view.butt[8] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 2 * BH, BW, BH,
3749                                          "Enable lighting of lines");
3750       view.butt[8]->tooltip("View.LightLines");
3751       view.butt[8]->type(FL_TOGGLE_BUTTON);
3752       view.butt[8]->callback(view_options_ok_cb);
3753 
3754       view.butt[9] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH, BW, BH,
3755                                          "Use two-side lighting");
3756       view.butt[9]->tooltip("View.LightTwoSide");
3757       view.butt[9]->type(FL_TOGGLE_BUTTON);
3758       view.butt[9]->callback(view_options_ok_cb);
3759 
3760       view.butt[12] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH,
3761                                           "Smooth normals");
3762       view.butt[12]->tooltip("View.SmoothNormals");
3763       view.butt[12]->type(FL_TOGGLE_BUTTON);
3764       view.butt[12]->callback(view_options_ok_cb);
3765 
3766       view.value[10] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH,
3767                                           "Smoothing threshold angle");
3768       view.value[10]->tooltip("View.AngleSmoothNormals");
3769       view.value[10]->minimum(0.);
3770       if(CTX::instance()->inputScrolling) view.value[10]->step(1.);
3771       view.value[10]->maximum(180.);
3772       view.value[10]->align(FL_ALIGN_RIGHT);
3773       view.value[10]->when(FL_WHEN_RELEASE);
3774       view.value[10]->callback(view_options_ok_cb);
3775 
3776       view.butt[24] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH,
3777                                           "Use fake transparency mode");
3778       view.butt[24]->tooltip("View.FakeTransparency");
3779       view.butt[24]->type(FL_TOGGLE_BUTTON);
3780       view.butt[24]->callback(view_options_ok_cb);
3781 
3782       Fl_Scroll *s = new Fl_Scroll(L + 2 * WB, 3 * WB + 7 * BH, IW + 20,
3783                                    height - 5 * WB - 7 * BH);
3784       std::size_t i = 0, j = 0;
3785       while(ViewOptions_Color[j].str) {
3786         if(ViewOptions_Color[j].level & GMSH_DEPRECATED) {
3787           j++;
3788           continue;
3789         }
3790         view.color[i] = new Fl_Button(L + 2 * WB, 3 * WB + (7 + i) * BH, IW, BH,
3791                                       ViewOptions_Color[j].str);
3792         view.color[i]->callback(view_color_cb,
3793                                 (void *)ViewOptions_Color[j].function);
3794         i++;
3795         j++;
3796         if(i >= view.color.size()) {
3797           Msg::Error("View color widget vector should be resized");
3798           break;
3799         }
3800       }
3801       s->end();
3802 
3803       o->end();
3804     }
3805     {
3806       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB,
3807                                  height - 2 * WB - BH, "Map");
3808       // o->label("@-1gmsh_colormap");
3809       o->hide();
3810 
3811       view.colorbar = new colorbarWindow(L + 2 * WB, 2 * WB + BH,
3812                                          width - 4 * WB, height - 4 * WB - BH);
3813       view.colorbar->end();
3814       view.colorbar->callback(view_options_ok_cb);
3815 
3816       o->end();
3817     }
3818     o->end();
3819   }
3820   view.group->end();
3821 
3822   win->position(CTX::instance()->optPosition[0],
3823                 CTX::instance()->optPosition[1]);
3824   win->end();
3825 
3826   FL_NORMAL_SIZE += deltaFontSize;
3827 }
3828 
showGroup(int num,bool showWindow,bool allowMultipleSelections)3829 void optionWindow::showGroup(int num, bool showWindow,
3830                              bool allowMultipleSelections)
3831 {
3832   general.group->hide();
3833   geo.group->hide();
3834   mesh.group->hide();
3835   solver.group->hide();
3836   post.group->hide();
3837   view.group->hide();
3838 
3839   if(num > 5 && allowMultipleSelections) {
3840     for(int i = 1; i <= 5; i++) browser->select(i, 0);
3841   }
3842   else {
3843     browser->deselect();
3844   }
3845   browser->select(num, 1);
3846   switch(num) {
3847   case 0:
3848   case 1:
3849     win->label("Options - General");
3850     general.group->show();
3851     break;
3852   case 2:
3853     win->label("Options - Geometry");
3854     geo.group->show();
3855     break;
3856   case 3:
3857     win->label("Options - Mesh");
3858     mesh.group->show();
3859     break;
3860   case 4:
3861     win->label("Options - Solver");
3862     solver.group->show();
3863     break;
3864   case 5:
3865     win->label("Options - Post-pro");
3866     post.group->show();
3867     break;
3868   default: {
3869     updateViewGroup(num - 6);
3870     static char str[128];
3871     sprintf(str, "Options - View [%d]", num - 6);
3872     win->label(str);
3873     view.group->show();
3874   } break;
3875   }
3876   if(showWindow) win->show();
3877 }
3878 
resetBrowser()3879 void optionWindow::resetBrowser()
3880 {
3881   int select = browser->value();
3882   browser->clear();
3883   browser->add("General");
3884   browser->add("Geometry");
3885   browser->add("Mesh");
3886   browser->add("Solver");
3887   browser->add("Post-pro");
3888   for(std::size_t i = 0; i < PView::list.size(); i++) {
3889     char str[128];
3890     sprintf(str, "View [%lu]", i);
3891     browser->add(str);
3892   }
3893   int num = (select <= browser->size()) ? select : browser->size();
3894   showGroup(num, false);
3895 }
3896 
resetExternalViewList()3897 void optionWindow::resetExternalViewList()
3898 {
3899   char str[32];
3900   view.choice[10]->clear();
3901   view.choice[11]->clear();
3902   view.choice[10]->add("Self");
3903   view.choice[11]->add("Self");
3904   for(std::size_t i = 0; i < PView::list.size(); i++) {
3905     sprintf(str, "View [%lu]", i);
3906     view.choice[10]->add(str, 0, nullptr);
3907     view.choice[11]->add(str, 0, nullptr);
3908   }
3909   if(view.index >= 0 && view.index < (int)PView::list.size()) {
3910     opt_view_external_view(view.index, GMSH_GUI, 0);
3911     opt_view_gen_raise_view(view.index, GMSH_GUI, 0);
3912   }
3913 }
3914 
updateViewGroup(int index)3915 void optionWindow::updateViewGroup(int index)
3916 {
3917   if(index < 0 || index >= (int)PView::list.size()) return;
3918 
3919   view.index = index;
3920 
3921   PView *v = PView::list[index];
3922   PViewData *data = v->getData();
3923   PViewOptions *opt = v->getOptions();
3924 
3925   double maxval = std::max(fabs(data->getMin()), fabs(data->getMax()));
3926   if(!maxval) maxval = 1.;
3927   double val1 = 10. * CTX::instance()->lc;
3928   double val2 = 2. * CTX::instance()->lc / maxval;
3929 
3930   opt_view_name(index, GMSH_GUI, "");
3931   opt_view_format(index, GMSH_GUI, "");
3932   opt_view_type(index, GMSH_GUI, 0);
3933   opt_view_show_scale(index, GMSH_GUI, 0);
3934   opt_view_draw_strings(index, GMSH_GUI, 0);
3935 
3936   opt_view_adapt_visualization_grid(index, GMSH_GUI, 0);
3937   opt_view_max_recursion_level(index, GMSH_GUI, 0);
3938   opt_view_target_error(index, GMSH_GUI, 0);
3939 
3940   if(data->getNumPoints() || data->getNumLines()) {
3941     ((Fl_Menu_Item *)view.choice[13]->menu())[1].activate();
3942     ((Fl_Menu_Item *)view.choice[13]->menu())[2].activate();
3943   }
3944   else {
3945     ((Fl_Menu_Item *)view.choice[13]->menu())[1].deactivate();
3946     ((Fl_Menu_Item *)view.choice[13]->menu())[2].deactivate();
3947   }
3948 
3949   opt_view_auto_position(index, GMSH_GUI, 0);
3950   opt_view_position0(index, GMSH_GUI, 0);
3951   opt_view_position1(index, GMSH_GUI, 0);
3952   opt_view_size0(index, GMSH_GUI, 0);
3953   opt_view_size1(index, GMSH_GUI, 0);
3954 
3955   opt_view_axes(index, GMSH_GUI, 0);
3956   opt_view_axes_mikado(index, GMSH_GUI, 0);
3957   opt_view_axes_format0(index, GMSH_GUI, "");
3958   opt_view_axes_format1(index, GMSH_GUI, "");
3959   opt_view_axes_format2(index, GMSH_GUI, "");
3960   opt_view_axes_tics0(index, GMSH_GUI, 0);
3961   opt_view_axes_tics1(index, GMSH_GUI, 0);
3962   opt_view_axes_tics2(index, GMSH_GUI, 0);
3963   opt_view_axes_label0(index, GMSH_GUI, "");
3964   opt_view_axes_label1(index, GMSH_GUI, "");
3965   opt_view_axes_label2(index, GMSH_GUI, "");
3966   opt_view_axes_auto_position(index, GMSH_GUI, 0);
3967   opt_view_axes_xmin(index, GMSH_GUI, 0);
3968   opt_view_axes_xmax(index, GMSH_GUI, 0);
3969   opt_view_axes_ymin(index, GMSH_GUI, 0);
3970   opt_view_axes_ymax(index, GMSH_GUI, 0);
3971   opt_view_axes_zmin(index, GMSH_GUI, 0);
3972   opt_view_axes_zmax(index, GMSH_GUI, 0);
3973   for(int i = 13; i <= 18; i++) {
3974     if(CTX::instance()->inputScrolling)
3975       view.value[i]->step(CTX::instance()->lc / 200., 1);
3976     view.value[i]->minimum(-CTX::instance()->lc);
3977     view.value[i]->maximum(CTX::instance()->lc);
3978   }
3979 
3980   if(data->getNumElements()) {
3981     view.range->activate();
3982     ((Fl_Menu_Item *)view.choice[13]->menu())[0].activate();
3983   }
3984   else {
3985     view.range->deactivate();
3986     ((Fl_Menu_Item *)view.choice[13]->menu())[0].deactivate();
3987   }
3988   opt_view_show_element(index, GMSH_GUI, 0);
3989   opt_view_draw_skin_only(index, GMSH_GUI, 0);
3990   opt_view_light(index, GMSH_GUI, 0);
3991   opt_view_light_two_side(index, GMSH_GUI, 0);
3992   opt_view_light_lines(index, GMSH_GUI, 0);
3993   opt_view_smooth_normals(index, GMSH_GUI, 0);
3994   opt_view_angle_smooth_normals(index, GMSH_GUI, 0);
3995   opt_view_boundary(index, GMSH_GUI, 0);
3996   opt_view_explode(index, GMSH_GUI, 0);
3997   opt_view_draw_points(index, GMSH_GUI, 0);
3998   opt_view_draw_lines(index, GMSH_GUI, 0);
3999   opt_view_draw_triangles(index, GMSH_GUI, 0);
4000   opt_view_draw_quadrangles(index, GMSH_GUI, 0);
4001   opt_view_draw_tetrahedra(index, GMSH_GUI, 0);
4002   opt_view_draw_hexahedra(index, GMSH_GUI, 0);
4003   opt_view_draw_prisms(index, GMSH_GUI, 0);
4004   opt_view_draw_pyramids(index, GMSH_GUI, 0);
4005   opt_view_draw_trihedra(index, GMSH_GUI, 0);
4006   opt_view_draw_scalars(index, GMSH_GUI, 0);
4007   opt_view_draw_vectors(index, GMSH_GUI, 0);
4008   opt_view_draw_tensors(index, GMSH_GUI, 0);
4009   opt_view_normals(index, GMSH_GUI, 0);
4010   opt_view_tangents(index, GMSH_GUI, 0);
4011   opt_view_sampling(index, GMSH_GUI, 0);
4012 
4013   opt_view_nb_iso(index, GMSH_GUI, 0);
4014   opt_view_intervals_type(index, GMSH_GUI, 0);
4015   opt_view_range_type(index, GMSH_GUI, 0);
4016   opt_view_custom_min(index, GMSH_GUI, 0);
4017   opt_view_custom_max(index, GMSH_GUI, 0);
4018   opt_view_scale_type(index, GMSH_GUI, 0);
4019   opt_view_saturate_values(index, GMSH_GUI, 0);
4020 
4021   opt_view_offset0(index, GMSH_GUI, 0);
4022   opt_view_offset1(index, GMSH_GUI, 0);
4023   opt_view_offset2(index, GMSH_GUI, 0);
4024   for(int i = 40; i <= 42; i++) {
4025     if(CTX::instance()->inputScrolling) view.value[i]->step(val1 / 200., 1);
4026     view.value[i]->minimum(-val1);
4027     view.value[i]->maximum(val1);
4028   }
4029   opt_view_transform00(index, GMSH_GUI, 0);
4030   opt_view_transform01(index, GMSH_GUI, 0);
4031   opt_view_transform02(index, GMSH_GUI, 0);
4032   opt_view_transform10(index, GMSH_GUI, 0);
4033   opt_view_transform11(index, GMSH_GUI, 0);
4034   opt_view_transform12(index, GMSH_GUI, 0);
4035   opt_view_transform20(index, GMSH_GUI, 0);
4036   opt_view_transform21(index, GMSH_GUI, 0);
4037   opt_view_transform22(index, GMSH_GUI, 0);
4038   opt_view_raise0(index, GMSH_GUI, 0);
4039   opt_view_raise1(index, GMSH_GUI, 0);
4040   opt_view_raise2(index, GMSH_GUI, 0);
4041   opt_view_normal_raise(index, GMSH_GUI, 0);
4042   for(int i = 43; i <= 46; i++) {
4043     if(CTX::instance()->inputScrolling) view.value[i]->step(val2 / 200., 1);
4044     view.value[i]->minimum(-val2);
4045     view.value[i]->maximum(val2);
4046   }
4047   opt_view_use_gen_raise(index, GMSH_GUI, 0);
4048   opt_view_gen_raise_view(index, GMSH_GUI, 0);
4049   opt_view_gen_raise_factor(index, GMSH_GUI, 0);
4050   opt_view_gen_raise0(index, GMSH_GUI, "");
4051   opt_view_gen_raise1(index, GMSH_GUI, "");
4052   opt_view_gen_raise2(index, GMSH_GUI, "");
4053   if(CTX::instance()->inputScrolling) view.value[2]->step(val2 / 200., 1);
4054   view.value[2]->minimum(-val2);
4055   view.value[2]->maximum(val2);
4056 
4057   if(data->getNumTimeSteps() == 1) {
4058     view.value[50]->deactivate();
4059     view.push[3]->deactivate();
4060     view.push[4]->deactivate();
4061     view.label[0]->deactivate();
4062   }
4063   else {
4064     view.value[50]->activate();
4065     view.push[3]->activate();
4066     view.push[4]->activate();
4067     view.label[0]->activate();
4068   }
4069   view.value[50]->maximum(data->getNumTimeSteps() - 1);
4070   opt_view_timestep(index, GMSH_GUI, 0);
4071   opt_view_show_time(index, GMSH_GUI, 0);
4072   opt_view_force_num_components(index, GMSH_GUI, 0);
4073   opt_view_component_map0(index, GMSH_GUI, 0);
4074   opt_view_component_map1(index, GMSH_GUI, 0);
4075   opt_view_component_map2(index, GMSH_GUI, 0);
4076   opt_view_component_map3(index, GMSH_GUI, 0);
4077   opt_view_component_map4(index, GMSH_GUI, 0);
4078   opt_view_component_map5(index, GMSH_GUI, 0);
4079   opt_view_component_map6(index, GMSH_GUI, 0);
4080   opt_view_component_map7(index, GMSH_GUI, 0);
4081   opt_view_component_map8(index, GMSH_GUI, 0);
4082 
4083   opt_view_point_size(index, GMSH_GUI, 0);
4084   opt_view_point_type(index, GMSH_GUI, 0);
4085   opt_view_line_width(index, GMSH_GUI, 0);
4086   opt_view_line_type(index, GMSH_GUI, 0);
4087   opt_view_vector_type(index, GMSH_GUI, 0);
4088   opt_view_arrow_size_min(index, GMSH_GUI, 0);
4089   opt_view_arrow_size_max(index, GMSH_GUI, 0);
4090 
4091   opt_view_displacement_factor(index, GMSH_GUI, 0);
4092   double val3 = 2. * CTX::instance()->lc / maxval;
4093   if(CTX::instance()->inputScrolling) view.value[63]->step(val3 / 100., 1);
4094   view.value[63]->maximum(val3);
4095 
4096   opt_view_external_view(index, GMSH_GUI, 0);
4097   opt_view_glyph_location(index, GMSH_GUI, 0);
4098   opt_view_center_glyphs(index, GMSH_GUI, 0);
4099   opt_view_tensor_type(index, GMSH_GUI, 0);
4100 
4101   opt_view_fake_transparency(index, GMSH_GUI, 0);
4102   opt_view_use_stipple(index, GMSH_GUI, 0);
4103   opt_view_color_points(index, GMSH_GUI, 0);
4104   opt_view_color_lines(index, GMSH_GUI, 0);
4105   opt_view_color_triangles(index, GMSH_GUI, 0);
4106   opt_view_color_quadrangles(index, GMSH_GUI, 0);
4107   opt_view_color_tetrahedra(index, GMSH_GUI, 0);
4108   opt_view_color_hexahedra(index, GMSH_GUI, 0);
4109   opt_view_color_prisms(index, GMSH_GUI, 0);
4110   opt_view_color_pyramids(index, GMSH_GUI, 0);
4111   opt_view_color_trihedra(index, GMSH_GUI, 0);
4112   opt_view_color_tangents(index, GMSH_GUI, 0);
4113   opt_view_color_normals(index, GMSH_GUI, 0);
4114   opt_view_color_text2d(index, GMSH_GUI, 0);
4115   opt_view_color_text3d(index, GMSH_GUI, 0);
4116   opt_view_color_axes(index, GMSH_GUI, 0);
4117   opt_view_color_background2d(index, GMSH_GUI, 0);
4118 
4119   view.colorbar->update(data->getName().c_str(), data->getMin(), data->getMax(),
4120                         &opt->colorTable, &v->getChanged());
4121 }
4122 
activate(const char * what)4123 void optionWindow::activate(const char *what)
4124 {
4125   if(!what) return;
4126 
4127   // activate/deactivate parts of the option window depending on the
4128   // user's choices (or the option settings)
4129   if(!strcmp(what, "fast_redraw")) {
4130     if(general.butt[2]->value()) {
4131       browser->resize(browser->x(), browser->y(), browser->w(),
4132                       win->h() - 2 * WB - BH);
4133       redraw->show();
4134       win->redraw();
4135     }
4136     else {
4137       browser->resize(browser->x(), browser->y(), browser->w(), win->h());
4138       redraw->hide();
4139       win->redraw();
4140     }
4141   }
4142   else if(!strcmp(what, "rotation_center")) {
4143     if(general.butt[15]->value()) {
4144       general.push[0]->deactivate();
4145       general.value[8]->deactivate();
4146       general.value[9]->deactivate();
4147       general.value[10]->deactivate();
4148     }
4149     else {
4150       general.push[0]->activate();
4151       general.value[8]->activate();
4152       general.value[9]->activate();
4153       general.value[10]->activate();
4154     }
4155   }
4156   else if(!strcmp(what, "general_axes")) {
4157     if(general.choice[4]->value()) {
4158       general.value[17]->activate();
4159       general.value[18]->activate();
4160       general.value[19]->activate();
4161       general.input[3]->activate();
4162       general.input[4]->activate();
4163       general.input[5]->activate();
4164       general.input[6]->activate();
4165       general.input[7]->activate();
4166       general.input[8]->activate();
4167     }
4168     else {
4169       general.value[17]->deactivate();
4170       general.value[18]->deactivate();
4171       general.value[19]->deactivate();
4172       general.input[3]->deactivate();
4173       general.input[4]->deactivate();
4174       general.input[5]->deactivate();
4175       general.input[6]->deactivate();
4176       general.input[7]->deactivate();
4177       general.input[8]->deactivate();
4178     }
4179   }
4180   else if(!strcmp(what, "general_axes_auto")) {
4181     if(general.butt[0]->value()) {
4182       general.value[20]->deactivate();
4183       general.value[21]->deactivate();
4184       general.value[22]->deactivate();
4185       general.value[23]->deactivate();
4186       general.value[24]->deactivate();
4187       general.value[25]->deactivate();
4188       general.push[1]->deactivate();
4189     }
4190     else {
4191       general.value[20]->activate();
4192       general.value[21]->activate();
4193       general.value[22]->activate();
4194       general.value[23]->activate();
4195       general.value[24]->activate();
4196       general.value[25]->activate();
4197       general.push[1]->activate();
4198     }
4199   }
4200   else if(!strcmp(what, "general_small_axes")) {
4201     if(general.butt[1]->value()) {
4202       general.value[26]->activate();
4203       general.value[27]->activate();
4204     }
4205     else {
4206       general.value[26]->deactivate();
4207       general.value[27]->deactivate();
4208     }
4209   }
4210   else if(!strcmp(what, "general_camera")) {
4211     if(general.butt[19]->value()) {
4212       if(CTX::instance()->gamepad && CTX::instance()->gamepad->active)
4213         general.gamepadconfig->activate();
4214     }
4215     else {
4216       general.gamepadconfig->deactivate();
4217     }
4218     if(general.butt[17]->value() == 0) { general.value[29]->deactivate(); }
4219     else {
4220       general.value[29]->activate();
4221     }
4222     if(general.butt[18]->value() == 0) {
4223       general.value[30]->deactivate();
4224       general.value[31]->deactivate();
4225     }
4226     else {
4227       general.value[30]->activate();
4228       general.value[31]->activate();
4229     }
4230   }
4231   else if(!strcmp(what, "geo_transform")) {
4232     if(geo.choice[3]->value() == 1) {
4233       for(int i = 7; i <= 18; i++) geo.value[i]->activate();
4234     }
4235     else {
4236       for(int i = 7; i <= 18; i++) geo.value[i]->deactivate();
4237     }
4238   }
4239   else if(!strcmp(what, "custom_range")) {
4240     if(view.choice[7]->value() == 1) {
4241       view.value[31]->activate();
4242       view.value[32]->activate();
4243       view.push[1]->activate();
4244       view.push[2]->activate();
4245       view.butt[38]->activate();
4246     }
4247     else {
4248       view.value[31]->deactivate();
4249       view.value[32]->deactivate();
4250       view.push[1]->deactivate();
4251       view.push[2]->deactivate();
4252       view.butt[38]->deactivate();
4253     }
4254   }
4255   else if(!strcmp(what, "view_adaptive")) {
4256     if(view.butt[0]->value()) {
4257       view.push[5]->activate();
4258       view.push[6]->activate();
4259       view.value[33]->activate();
4260       view.value[34]->activate();
4261       view.label[1]->activate();
4262     }
4263     else {
4264       view.push[5]->deactivate();
4265       view.push[6]->deactivate();
4266       view.value[33]->deactivate();
4267       view.value[34]->deactivate();
4268       view.label[1]->deactivate();
4269     }
4270   }
4271   else if(!strcmp(what, "view_general_transform")) {
4272     if(view.butt[6]->value()) {
4273       view.choice[11]->activate();
4274       view.value[2]->activate();
4275       view.input[4]->activate();
4276       view.input[5]->activate();
4277       view.input[6]->activate();
4278     }
4279     else {
4280       view.choice[11]->deactivate();
4281       view.value[2]->deactivate();
4282       view.input[4]->deactivate();
4283       view.input[5]->deactivate();
4284       view.input[6]->deactivate();
4285     }
4286   }
4287   else if(!strcmp(what, "mesh_light")) {
4288     if(mesh.butt[17]->value()) {
4289       mesh.butt[18]->activate();
4290       mesh.butt[19]->activate();
4291       mesh.choice[10]->activate();
4292       mesh.value[18]->activate();
4293     }
4294     else {
4295       mesh.butt[18]->deactivate();
4296       mesh.butt[19]->deactivate();
4297       mesh.choice[10]->deactivate();
4298       mesh.value[18]->deactivate();
4299     }
4300   }
4301   else if(!strcmp(what, "view_light")) {
4302     if(view.butt[11]->value()) {
4303       view.butt[8]->activate();
4304       view.butt[9]->activate();
4305       view.butt[12]->activate();
4306       view.value[10]->activate();
4307     }
4308     else {
4309       view.butt[8]->deactivate();
4310       view.butt[9]->deactivate();
4311       view.butt[12]->deactivate();
4312       view.value[10]->deactivate();
4313     }
4314   }
4315   else if(!strcmp(what, "view_axes")) {
4316     if(view.choice[8]->value()) {
4317       view.value[3]->activate();
4318       view.value[4]->activate();
4319       view.value[5]->activate();
4320       view.input[7]->activate();
4321       view.input[8]->activate();
4322       view.input[9]->activate();
4323       view.input[10]->activate();
4324       view.input[11]->activate();
4325       view.input[12]->activate();
4326     }
4327     else {
4328       view.value[3]->deactivate();
4329       view.value[4]->deactivate();
4330       view.value[5]->deactivate();
4331       view.input[7]->deactivate();
4332       view.input[8]->deactivate();
4333       view.input[9]->deactivate();
4334       view.input[10]->deactivate();
4335       view.input[11]->deactivate();
4336       view.input[12]->deactivate();
4337     }
4338   }
4339   else if(!strcmp(what, "view_axes_auto_3d")) {
4340     if(view.butt[25]->value()) {
4341       view.value[13]->deactivate();
4342       view.value[14]->deactivate();
4343       view.value[15]->deactivate();
4344       view.value[16]->deactivate();
4345       view.value[17]->deactivate();
4346       view.value[18]->deactivate();
4347     }
4348     else {
4349       view.value[13]->activate();
4350       view.value[14]->activate();
4351       view.value[15]->activate();
4352       view.value[16]->activate();
4353       view.value[17]->activate();
4354       view.value[18]->activate();
4355     }
4356   }
4357   else if(!strcmp(what, "view_axes_auto_2d")) {
4358     if(view.choice[16]->value() == 0 || view.choice[16]->value() == 12) {
4359       view.value[20]->activate();
4360       view.value[21]->activate();
4361       view.value[22]->activate();
4362       view.value[23]->activate();
4363     }
4364     else {
4365       view.value[20]->deactivate();
4366       view.value[21]->deactivate();
4367       view.value[22]->deactivate();
4368       view.value[23]->deactivate();
4369     }
4370   }
4371 }
4372