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 <stdlib.h>
7 #include <FL/Fl_Tabs.H>
8 #include <FL/Fl_Return_Button.H>
9 #include "FlGui.h"
10 #include "drawContext.h"
11 #include "contextWindow.h"
12 #include "paletteWindow.h"
13 #include "graphicWindow.h"
14 #include "openglWindow.h"
15 #include "Parser.h"
16 #include "GModel.h"
17 #ifdef Convex // can be defined by Xlib
18 #undef Convex
19 #endif
20 #include "GModelIO_OCC.h"
21 #include "scriptStringInterface.h"
22 #include "OpenFile.h"
23 #include "Context.h"
24 #include "Options.h"
25 #include "MallocUtils.h"
26 #include "StringUtils.h"
27 #include "Geo.h"
28 #include "VertexArray.h"
29 #include "mathEvaluator.h"
30 
getval(const char * str,double & val)31 static bool getval(const char *str, double &val)
32 {
33   std::vector<std::string> var;
34   std::vector<double> valVar;
35 
36   // we should probably use the actual .geo parser instead...
37   for(auto it = gmsh_yysymbols.begin(); it != gmsh_yysymbols.end(); it++) {
38     if(it->second.value.size() == 1) {
39       var.push_back(it->first);
40       valVar.push_back(it->second.value[0]);
41     }
42   }
43 
44   std::vector<std::string> expr(1);
45   expr[0] = str;
46   std::vector<double> res(1);
47   mathEvaluator f(expr, var);
48   if(expr.empty()) return false;
49   if(!f.eval(valVar, res)) return false;
50   val = res[0];
51   return true;
52 }
53 
draw_stl(std::vector<SPoint3> & vertices,std::vector<SVector3> & normals,std::vector<int> & triangles)54 static void draw_stl(std::vector<SPoint3> &vertices,
55                      std::vector<SVector3> &normals,
56                      std::vector<int> &triangles)
57 {
58   GLint mode[2];
59   glGetIntegerv(GL_POLYGON_MODE, mode);
60   if(CTX::instance()->geom.surfaceType == 1)
61     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
62   else
63     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
64   glEnable(GL_LIGHTING);
65   glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
66   glColor4ubv((GLubyte *)&CTX::instance()->color.geom.highlight[0]);
67 
68   VertexArray va(3, triangles.size());
69   for(std::size_t i = 0; i < triangles.size(); i += 3) {
70     SPoint3 p1 = vertices[triangles[i]];
71     SPoint3 p2 = vertices[triangles[i + 1]];
72     SPoint3 p3 = vertices[triangles[i + 2]];
73     SVector3 n1 = normals[triangles[i]];
74     SVector3 n2 = normals[triangles[i + 1]];
75     SVector3 n3 = normals[triangles[i + 2]];
76     double x[3] = {p1.x(), p2.x(), p3.x()};
77     double y[3] = {p1.y(), p2.y(), p3.y()};
78     double z[3] = {p1.z(), p2.z(), p3.z()};
79     SVector3 nn[3] = {n1, n2, n3};
80     va.add(x, y, z, nn);
81   }
82   va.finalize();
83 
84   glVertexPointer(3, GL_FLOAT, 0, va.getVertexArray());
85   glEnableClientState(GL_VERTEX_ARRAY);
86   glNormalPointer(NORMAL_GLTYPE, 0, va.getNormalArray());
87   glEnableClientState(GL_NORMAL_ARRAY);
88   glDisableClientState(GL_COLOR_ARRAY);
89   glDrawArrays(GL_TRIANGLES, 0, va.getNumVertices());
90   glDisableClientState(GL_VERTEX_ARRAY);
91   glDisableClientState(GL_NORMAL_ARRAY);
92 
93   glDisable(GL_LIGHTING);
94   glPolygonMode(GL_FRONT_AND_BACK, mode[1]);
95 }
96 
elementary_add_parameter_cb(Fl_Widget * w,void * data)97 static void elementary_add_parameter_cb(Fl_Widget *w, void *data)
98 {
99   scriptAddParameter(FlGui::instance()->elementaryContext->input[0]->value(),
100                      FlGui::instance()->elementaryContext->input[1]->value(),
101                      FlGui::instance()->elementaryContext->input[2]->value(),
102                      FlGui::instance()->elementaryContext->input[3]->value(),
103                      GModel::current()->getFileName());
104   FlGui::instance()->resetVisibility();
105   FlGui::instance()->rebuildTree(true);
106 }
107 
elementary_draw_point_cb(Fl_Widget * w,void * data)108 static void elementary_draw_point_cb(Fl_Widget *w, void *data)
109 {
110   if(data) return; // we are here from do_callback()
111   double x, y, z;
112   if(!getval(FlGui::instance()->elementaryContext->input[4]->value(), x))
113     return;
114   if(!getval(FlGui::instance()->elementaryContext->input[5]->value(), y))
115     return;
116   if(!getval(FlGui::instance()->elementaryContext->input[6]->value(), z))
117     return;
118   FlGui::instance()->getCurrentOpenglWindow()->setPoint(x, y, z);
119   drawContext::global()->draw();
120 }
121 
elementary_add_point_cb(Fl_Widget * w,void * data)122 static void elementary_add_point_cb(Fl_Widget *w, void *data)
123 {
124   scriptAddPoint(GModel::current()->getFileName(),
125                  FlGui::instance()->elementaryContext->input[4]->value(),
126                  FlGui::instance()->elementaryContext->input[5]->value(),
127                  FlGui::instance()->elementaryContext->input[6]->value(),
128                  FlGui::instance()->elementaryContext->input[7]->value());
129   FlGui::instance()->resetVisibility();
130   GModel::current()->setSelection(0);
131   SetBoundingBox();
132   drawContext::global()->draw();
133 }
134 
draw_circle(void * context)135 static void draw_circle(void *context)
136 {
137   if(!GModel::current()->getOCCInternals())
138     GModel::current()->createOCCInternals();
139   double xc, yc, zc, r, angle1, angle2;
140   if(!getval(FlGui::instance()->elementaryContext->input[8]->value(), xc))
141     return;
142   if(!getval(FlGui::instance()->elementaryContext->input[9]->value(), yc))
143     return;
144   if(!getval(FlGui::instance()->elementaryContext->input[10]->value(), zc))
145     return;
146   if(!getval(FlGui::instance()->elementaryContext->input[11]->value(), r))
147     return;
148   if(!getval(FlGui::instance()->elementaryContext->input[12]->value(), angle1))
149     return;
150   if(!getval(FlGui::instance()->elementaryContext->input[13]->value(), angle2))
151     return;
152 
153   if(angle2 <= angle1) return;
154   glColor4ubv((GLubyte *)&CTX::instance()->color.geom.highlight[0]);
155   glBegin(GL_LINE_STRIP);
156   const int N = 30;
157   for(int i = 0; i < N; i++) {
158     double t = angle1 + (double)i / (double)(N - 1) * (angle2 - angle1);
159     double x = xc + r * cos(t);
160     double y = yc + r * sin(t);
161     double z = zc;
162     glVertex3d(x, y, z);
163   }
164   glEnd();
165 }
166 
elementary_draw_circle_cb(Fl_Widget * w,void * data)167 static void elementary_draw_circle_cb(Fl_Widget *w, void *data)
168 {
169   drawContext::setDrawGeomTransientFunction(draw_circle);
170   if(!data) drawContext::global()->draw();
171 }
172 
elementary_add_circle_cb(Fl_Widget * w,void * data)173 static void elementary_add_circle_cb(Fl_Widget *w, void *data)
174 {
175   scriptAddCircle(GModel::current()->getFileName(),
176                   FlGui::instance()->elementaryContext->input[8]->value(),
177                   FlGui::instance()->elementaryContext->input[9]->value(),
178                   FlGui::instance()->elementaryContext->input[10]->value(),
179                   FlGui::instance()->elementaryContext->input[11]->value(),
180                   FlGui::instance()->elementaryContext->input[12]->value(),
181                   FlGui::instance()->elementaryContext->input[13]->value());
182   FlGui::instance()->resetVisibility();
183   GModel::current()->setSelection(0);
184   SetBoundingBox();
185   drawContext::global()->draw();
186 }
187 
draw_ellipse(void * context)188 static void draw_ellipse(void *context)
189 {
190   if(!GModel::current()->getOCCInternals())
191     GModel::current()->createOCCInternals();
192   double xc, yc, zc, rx, ry, angle1, angle2;
193   if(!getval(FlGui::instance()->elementaryContext->input[14]->value(), xc))
194     return;
195   if(!getval(FlGui::instance()->elementaryContext->input[15]->value(), yc))
196     return;
197   if(!getval(FlGui::instance()->elementaryContext->input[16]->value(), zc))
198     return;
199   if(!getval(FlGui::instance()->elementaryContext->input[17]->value(), rx))
200     return;
201   if(!getval(FlGui::instance()->elementaryContext->input[18]->value(), ry))
202     return;
203   if(!getval(FlGui::instance()->elementaryContext->input[19]->value(), angle1))
204     return;
205   if(!getval(FlGui::instance()->elementaryContext->input[20]->value(), angle2))
206     return;
207   if(angle2 <= angle1) return;
208   glColor4ubv((GLubyte *)&CTX::instance()->color.geom.highlight[0]);
209   glBegin(GL_LINE_STRIP);
210   const int N = 30;
211   for(int i = 0; i < N; i++) {
212     double t = angle1 + (double)i / (double)(N - 1) * (angle2 - angle1);
213     double x = xc + rx * cos(t);
214     double y = yc + ry * sin(t);
215     double z = zc;
216     glVertex3d(x, y, z);
217   }
218   glEnd();
219 }
220 
elementary_draw_ellipse_cb(Fl_Widget * w,void * data)221 static void elementary_draw_ellipse_cb(Fl_Widget *w, void *data)
222 {
223   drawContext::setDrawGeomTransientFunction(draw_ellipse);
224   if(!data) drawContext::global()->draw();
225 }
226 
elementary_add_ellipse_cb(Fl_Widget * w,void * data)227 static void elementary_add_ellipse_cb(Fl_Widget *w, void *data)
228 {
229   scriptAddEllipse(GModel::current()->getFileName(),
230                    FlGui::instance()->elementaryContext->input[14]->value(),
231                    FlGui::instance()->elementaryContext->input[15]->value(),
232                    FlGui::instance()->elementaryContext->input[16]->value(),
233                    FlGui::instance()->elementaryContext->input[17]->value(),
234                    FlGui::instance()->elementaryContext->input[18]->value(),
235                    FlGui::instance()->elementaryContext->input[19]->value(),
236                    FlGui::instance()->elementaryContext->input[20]->value());
237   FlGui::instance()->resetVisibility();
238   GModel::current()->setSelection(0);
239   SetBoundingBox();
240   drawContext::global()->draw();
241 }
242 
draw_disk(void * context)243 static void draw_disk(void *context)
244 {
245   if(!GModel::current()->getOCCInternals())
246     GModel::current()->createOCCInternals();
247   double xc, yc, zc, rx, ry;
248   if(!getval(FlGui::instance()->elementaryContext->input[21]->value(), xc))
249     return;
250   if(!getval(FlGui::instance()->elementaryContext->input[22]->value(), yc))
251     return;
252   if(!getval(FlGui::instance()->elementaryContext->input[23]->value(), zc))
253     return;
254   if(!getval(FlGui::instance()->elementaryContext->input[24]->value(), rx))
255     return;
256   if(!getval(FlGui::instance()->elementaryContext->input[25]->value(), ry))
257     return;
258   std::vector<SPoint3> vertices;
259   std::vector<SVector3> normals;
260   std::vector<int> triangles;
261   if(!GModel::current()->getOCCInternals()->makeDiskSTL(
262        xc, yc, zc, rx, ry, vertices, normals, triangles))
263     return;
264   draw_stl(vertices, normals, triangles);
265 }
266 
elementary_draw_disk_cb(Fl_Widget * w,void * data)267 static void elementary_draw_disk_cb(Fl_Widget *w, void *data)
268 {
269   drawContext::setDrawGeomTransientFunction(draw_disk);
270   if(!data) drawContext::global()->draw();
271 }
272 
elementary_add_disk_cb(Fl_Widget * w,void * data)273 static void elementary_add_disk_cb(Fl_Widget *w, void *data)
274 {
275   scriptAddDisk(GModel::current()->getFileName(),
276                 FlGui::instance()->elementaryContext->input[21]->value(),
277                 FlGui::instance()->elementaryContext->input[22]->value(),
278                 FlGui::instance()->elementaryContext->input[23]->value(),
279                 FlGui::instance()->elementaryContext->input[24]->value(),
280                 FlGui::instance()->elementaryContext->input[25]->value());
281   FlGui::instance()->resetVisibility();
282   GModel::current()->setSelection(0);
283   SetBoundingBox();
284   drawContext::global()->draw();
285 }
286 
draw_rectangle(void * context)287 static void draw_rectangle(void *context)
288 {
289   if(!GModel::current()->getOCCInternals())
290     GModel::current()->createOCCInternals();
291   double x, y, z, dx, dy, r;
292   if(!getval(FlGui::instance()->elementaryContext->input[26]->value(), x))
293     return;
294   if(!getval(FlGui::instance()->elementaryContext->input[27]->value(), y))
295     return;
296   if(!getval(FlGui::instance()->elementaryContext->input[28]->value(), z))
297     return;
298   if(!getval(FlGui::instance()->elementaryContext->input[29]->value(), dx))
299     return;
300   if(!getval(FlGui::instance()->elementaryContext->input[30]->value(), dy))
301     return;
302   if(!getval(FlGui::instance()->elementaryContext->input[31]->value(), r))
303     return;
304   std::vector<SPoint3> vertices;
305   std::vector<SVector3> normals;
306   std::vector<int> triangles;
307   if(!GModel::current()->getOCCInternals()->makeRectangleSTL(
308        x, y, z, dx, dy, r, vertices, normals, triangles))
309     return;
310   draw_stl(vertices, normals, triangles);
311 }
312 
elementary_draw_rectangle_cb(Fl_Widget * w,void * data)313 static void elementary_draw_rectangle_cb(Fl_Widget *w, void *data)
314 {
315   drawContext::setDrawGeomTransientFunction(draw_rectangle);
316   if(!data) drawContext::global()->draw();
317 }
318 
elementary_add_rectangle_cb(Fl_Widget * w,void * data)319 static void elementary_add_rectangle_cb(Fl_Widget *w, void *data)
320 {
321   scriptAddRectangle(GModel::current()->getFileName(),
322                      FlGui::instance()->elementaryContext->input[26]->value(),
323                      FlGui::instance()->elementaryContext->input[27]->value(),
324                      FlGui::instance()->elementaryContext->input[28]->value(),
325                      FlGui::instance()->elementaryContext->input[29]->value(),
326                      FlGui::instance()->elementaryContext->input[30]->value(),
327                      FlGui::instance()->elementaryContext->input[31]->value());
328   FlGui::instance()->resetVisibility();
329   GModel::current()->setSelection(0);
330   SetBoundingBox();
331   drawContext::global()->draw();
332 }
333 
draw_sphere(void * context)334 static void draw_sphere(void *context)
335 {
336   if(!GModel::current()->getOCCInternals())
337     GModel::current()->createOCCInternals();
338   double xc, yc, zc, r, angle1, angle2, angle3;
339   if(!getval(FlGui::instance()->elementaryContext->input[32]->value(), xc))
340     return;
341   if(!getval(FlGui::instance()->elementaryContext->input[33]->value(), yc))
342     return;
343   if(!getval(FlGui::instance()->elementaryContext->input[34]->value(), zc))
344     return;
345   if(!getval(FlGui::instance()->elementaryContext->input[35]->value(), r))
346     return;
347   if(!getval(FlGui::instance()->elementaryContext->input[36]->value(), angle1))
348     return;
349   if(!getval(FlGui::instance()->elementaryContext->input[37]->value(), angle2))
350     return;
351   if(!getval(FlGui::instance()->elementaryContext->input[38]->value(), angle3))
352     return;
353   std::vector<SPoint3> vertices;
354   std::vector<SVector3> normals;
355   std::vector<int> triangles;
356   if(!GModel::current()->getOCCInternals()->makeSphereSTL(
357        xc, yc, zc, r, angle1, angle2, angle3, vertices, normals, triangles))
358     return;
359   draw_stl(vertices, normals, triangles);
360 }
361 
elementary_draw_sphere_cb(Fl_Widget * w,void * data)362 static void elementary_draw_sphere_cb(Fl_Widget *w, void *data)
363 {
364   drawContext::setDrawGeomTransientFunction(draw_sphere);
365   if(!data) drawContext::global()->draw();
366 }
367 
elementary_add_sphere_cb(Fl_Widget * w,void * data)368 static void elementary_add_sphere_cb(Fl_Widget *w, void *data)
369 {
370   scriptAddSphere(GModel::current()->getFileName(),
371                   FlGui::instance()->elementaryContext->input[32]->value(),
372                   FlGui::instance()->elementaryContext->input[33]->value(),
373                   FlGui::instance()->elementaryContext->input[34]->value(),
374                   FlGui::instance()->elementaryContext->input[35]->value(),
375                   FlGui::instance()->elementaryContext->input[36]->value(),
376                   FlGui::instance()->elementaryContext->input[37]->value(),
377                   FlGui::instance()->elementaryContext->input[38]->value());
378   FlGui::instance()->resetVisibility();
379   GModel::current()->setSelection(0);
380   drawContext::setDrawGeomTransientFunction(nullptr);
381   SetBoundingBox();
382   drawContext::global()->draw();
383 }
384 
draw_cylinder(void * context)385 static void draw_cylinder(void *context)
386 {
387   if(!GModel::current()->getOCCInternals())
388     GModel::current()->createOCCInternals();
389   double xc, yc, zc, dx, dy, dz, r, angle;
390   if(!getval(FlGui::instance()->elementaryContext->input[39]->value(), xc))
391     return;
392   if(!getval(FlGui::instance()->elementaryContext->input[40]->value(), yc))
393     return;
394   if(!getval(FlGui::instance()->elementaryContext->input[41]->value(), zc))
395     return;
396   if(!getval(FlGui::instance()->elementaryContext->input[42]->value(), dx))
397     return;
398   if(!getval(FlGui::instance()->elementaryContext->input[43]->value(), dy))
399     return;
400   if(!getval(FlGui::instance()->elementaryContext->input[44]->value(), dz))
401     return;
402   if(!getval(FlGui::instance()->elementaryContext->input[45]->value(), r))
403     return;
404   if(!getval(FlGui::instance()->elementaryContext->input[46]->value(), angle))
405     return;
406   std::vector<SPoint3> vertices;
407   std::vector<SVector3> normals;
408   std::vector<int> triangles;
409   if(!GModel::current()->getOCCInternals()->makeCylinderSTL(
410        xc, yc, zc, dx, dy, dz, r, angle, vertices, normals, triangles))
411     return;
412   draw_stl(vertices, normals, triangles);
413 }
414 
elementary_draw_cylinder_cb(Fl_Widget * w,void * data)415 static void elementary_draw_cylinder_cb(Fl_Widget *w, void *data)
416 {
417   drawContext::setDrawGeomTransientFunction(draw_cylinder);
418   if(!data) drawContext::global()->draw();
419 }
420 
elementary_add_cylinder_cb(Fl_Widget * w,void * data)421 static void elementary_add_cylinder_cb(Fl_Widget *w, void *data)
422 {
423   scriptAddCylinder(GModel::current()->getFileName(),
424                     FlGui::instance()->elementaryContext->input[39]->value(),
425                     FlGui::instance()->elementaryContext->input[40]->value(),
426                     FlGui::instance()->elementaryContext->input[41]->value(),
427                     FlGui::instance()->elementaryContext->input[42]->value(),
428                     FlGui::instance()->elementaryContext->input[43]->value(),
429                     FlGui::instance()->elementaryContext->input[44]->value(),
430                     FlGui::instance()->elementaryContext->input[45]->value(),
431                     FlGui::instance()->elementaryContext->input[46]->value());
432   FlGui::instance()->resetVisibility();
433   GModel::current()->setSelection(0);
434   SetBoundingBox();
435   drawContext::global()->draw();
436 }
437 
draw_box(void * context)438 static void draw_box(void *context)
439 {
440   if(!GModel::current()->getOCCInternals())
441     GModel::current()->createOCCInternals();
442   double x, y, z, dx, dy, dz;
443   if(!getval(FlGui::instance()->elementaryContext->input[47]->value(), x))
444     return;
445   if(!getval(FlGui::instance()->elementaryContext->input[48]->value(), y))
446     return;
447   if(!getval(FlGui::instance()->elementaryContext->input[49]->value(), z))
448     return;
449   if(!getval(FlGui::instance()->elementaryContext->input[50]->value(), dx))
450     return;
451   if(!getval(FlGui::instance()->elementaryContext->input[51]->value(), dy))
452     return;
453   if(!getval(FlGui::instance()->elementaryContext->input[52]->value(), dz))
454     return;
455   std::vector<SPoint3> vertices;
456   std::vector<SVector3> normals;
457   std::vector<int> triangles;
458   if(!GModel::current()->getOCCInternals()->makeBoxSTL(
459        x, y, z, dx, dy, dz, vertices, normals, triangles))
460     return;
461   draw_stl(vertices, normals, triangles);
462 }
463 
elementary_draw_box_cb(Fl_Widget * w,void * data)464 static void elementary_draw_box_cb(Fl_Widget *w, void *data)
465 {
466   drawContext::setDrawGeomTransientFunction(draw_box);
467   if(!data) drawContext::global()->draw();
468 }
469 
elementary_add_box_cb(Fl_Widget * w,void * data)470 static void elementary_add_box_cb(Fl_Widget *w, void *data)
471 {
472   scriptAddBox(GModel::current()->getFileName(),
473                FlGui::instance()->elementaryContext->input[47]->value(),
474                FlGui::instance()->elementaryContext->input[48]->value(),
475                FlGui::instance()->elementaryContext->input[49]->value(),
476                FlGui::instance()->elementaryContext->input[50]->value(),
477                FlGui::instance()->elementaryContext->input[51]->value(),
478                FlGui::instance()->elementaryContext->input[52]->value());
479   FlGui::instance()->resetVisibility();
480   GModel::current()->setSelection(0);
481   SetBoundingBox();
482   drawContext::global()->draw();
483 }
484 
draw_torus(void * context)485 static void draw_torus(void *context)
486 {
487   if(!GModel::current()->getOCCInternals())
488     GModel::current()->createOCCInternals();
489   double xc, yc, zc, r1, r2, angle;
490   if(!getval(FlGui::instance()->elementaryContext->input[53]->value(), xc))
491     return;
492   if(!getval(FlGui::instance()->elementaryContext->input[54]->value(), yc))
493     return;
494   if(!getval(FlGui::instance()->elementaryContext->input[55]->value(), zc))
495     return;
496   if(!getval(FlGui::instance()->elementaryContext->input[56]->value(), r1))
497     return;
498   if(!getval(FlGui::instance()->elementaryContext->input[57]->value(), r2))
499     return;
500   if(!getval(FlGui::instance()->elementaryContext->input[58]->value(), angle))
501     return;
502   std::vector<SPoint3> vertices;
503   std::vector<SVector3> normals;
504   std::vector<int> triangles;
505   if(!GModel::current()->getOCCInternals()->makeTorusSTL(
506        xc, yc, zc, r1, r2, angle, vertices, normals, triangles))
507     return;
508   draw_stl(vertices, normals, triangles);
509 }
510 
elementary_draw_torus_cb(Fl_Widget * w,void * data)511 static void elementary_draw_torus_cb(Fl_Widget *w, void *data)
512 {
513   drawContext::setDrawGeomTransientFunction(draw_torus);
514   if(!data) drawContext::global()->draw();
515 }
516 
elementary_add_torus_cb(Fl_Widget * w,void * data)517 static void elementary_add_torus_cb(Fl_Widget *w, void *data)
518 {
519   scriptAddTorus(GModel::current()->getFileName(),
520                  FlGui::instance()->elementaryContext->input[53]->value(),
521                  FlGui::instance()->elementaryContext->input[54]->value(),
522                  FlGui::instance()->elementaryContext->input[55]->value(),
523                  FlGui::instance()->elementaryContext->input[56]->value(),
524                  FlGui::instance()->elementaryContext->input[57]->value(),
525                  FlGui::instance()->elementaryContext->input[58]->value());
526   FlGui::instance()->resetVisibility();
527   GModel::current()->setSelection(0);
528   SetBoundingBox();
529   drawContext::global()->draw();
530 }
531 
draw_cone(void * context)532 static void draw_cone(void *context)
533 {
534   if(!GModel::current()->getOCCInternals())
535     GModel::current()->createOCCInternals();
536   double xc, yc, zc, dx, dy, dz, r1, r2, angle;
537   if(!getval(FlGui::instance()->elementaryContext->input[59]->value(), xc))
538     return;
539   if(!getval(FlGui::instance()->elementaryContext->input[60]->value(), yc))
540     return;
541   if(!getval(FlGui::instance()->elementaryContext->input[61]->value(), zc))
542     return;
543   if(!getval(FlGui::instance()->elementaryContext->input[62]->value(), dx))
544     return;
545   if(!getval(FlGui::instance()->elementaryContext->input[63]->value(), dy))
546     return;
547   if(!getval(FlGui::instance()->elementaryContext->input[64]->value(), dz))
548     return;
549   if(!getval(FlGui::instance()->elementaryContext->input[65]->value(), r1))
550     return;
551   if(!getval(FlGui::instance()->elementaryContext->input[66]->value(), r2))
552     return;
553   if(!getval(FlGui::instance()->elementaryContext->input[67]->value(), angle))
554     return;
555   std::vector<SPoint3> vertices;
556   std::vector<SVector3> normals;
557   std::vector<int> triangles;
558   if(!GModel::current()->getOCCInternals()->makeConeSTL(
559        xc, yc, zc, dx, dy, dz, r1, r2, angle, vertices, normals, triangles))
560     return;
561   draw_stl(vertices, normals, triangles);
562 }
563 
elementary_draw_cone_cb(Fl_Widget * w,void * data)564 static void elementary_draw_cone_cb(Fl_Widget *w, void *data)
565 {
566   drawContext::setDrawGeomTransientFunction(draw_cone);
567   if(!data) drawContext::global()->draw();
568 }
569 
elementary_add_cone_cb(Fl_Widget * w,void * data)570 static void elementary_add_cone_cb(Fl_Widget *w, void *data)
571 {
572   scriptAddCone(GModel::current()->getFileName(),
573                 FlGui::instance()->elementaryContext->input[59]->value(),
574                 FlGui::instance()->elementaryContext->input[60]->value(),
575                 FlGui::instance()->elementaryContext->input[61]->value(),
576                 FlGui::instance()->elementaryContext->input[62]->value(),
577                 FlGui::instance()->elementaryContext->input[63]->value(),
578                 FlGui::instance()->elementaryContext->input[64]->value(),
579                 FlGui::instance()->elementaryContext->input[65]->value(),
580                 FlGui::instance()->elementaryContext->input[66]->value(),
581                 FlGui::instance()->elementaryContext->input[67]->value());
582   FlGui::instance()->resetVisibility();
583   GModel::current()->setSelection(0);
584   SetBoundingBox();
585   drawContext::global()->draw();
586 }
587 
draw_wedge(void * context)588 static void draw_wedge(void *context)
589 {
590   if(!GModel::current()->getOCCInternals())
591     GModel::current()->createOCCInternals();
592   double x, y, z, dx, dy, dz, ltx;
593   if(!getval(FlGui::instance()->elementaryContext->input[68]->value(), x))
594     return;
595   if(!getval(FlGui::instance()->elementaryContext->input[69]->value(), y))
596     return;
597   if(!getval(FlGui::instance()->elementaryContext->input[70]->value(), z))
598     return;
599   if(!getval(FlGui::instance()->elementaryContext->input[71]->value(), dx))
600     return;
601   if(!getval(FlGui::instance()->elementaryContext->input[72]->value(), dy))
602     return;
603   if(!getval(FlGui::instance()->elementaryContext->input[73]->value(), dz))
604     return;
605   if(!getval(FlGui::instance()->elementaryContext->input[74]->value(), ltx))
606     return;
607   std::vector<SPoint3> vertices;
608   std::vector<SVector3> normals;
609   std::vector<int> triangles;
610   if(!GModel::current()->getOCCInternals()->makeWedgeSTL(
611        x, y, z, dx, dy, dz, ltx, vertices, normals, triangles))
612     return;
613   draw_stl(vertices, normals, triangles);
614 }
615 
elementary_draw_wedge_cb(Fl_Widget * w,void * data)616 static void elementary_draw_wedge_cb(Fl_Widget *w, void *data)
617 {
618   drawContext::setDrawGeomTransientFunction(draw_wedge);
619   if(!data) drawContext::global()->draw();
620 }
621 
elementary_add_wedge_cb(Fl_Widget * w,void * data)622 static void elementary_add_wedge_cb(Fl_Widget *w, void *data)
623 {
624   scriptAddWedge(GModel::current()->getFileName(),
625                  FlGui::instance()->elementaryContext->input[68]->value(),
626                  FlGui::instance()->elementaryContext->input[69]->value(),
627                  FlGui::instance()->elementaryContext->input[70]->value(),
628                  FlGui::instance()->elementaryContext->input[71]->value(),
629                  FlGui::instance()->elementaryContext->input[72]->value(),
630                  FlGui::instance()->elementaryContext->input[73]->value(),
631                  FlGui::instance()->elementaryContext->input[74]->value());
632   FlGui::instance()->resetVisibility();
633   GModel::current()->setSelection(0);
634   SetBoundingBox();
635   drawContext::global()->draw();
636 }
637 
elementary_switch_tabs_cb(Fl_Widget * w,void * data)638 static void elementary_switch_tabs_cb(Fl_Widget *w, void *data)
639 {
640   if(FlGui::instance()->elementaryContext->tab1->visible()) {
641     FlGui::instance()->elementaryContext->tab1->hide();
642     FlGui::instance()->elementaryContext->tab2->show();
643   }
644   else {
645     FlGui::instance()->elementaryContext->tab2->hide();
646     FlGui::instance()->elementaryContext->tab1->show();
647   }
648 }
649 
elementary_snap_cb(Fl_Widget * w,void * data)650 static void elementary_snap_cb(Fl_Widget *w, void *data)
651 {
652   CTX::instance()->geom.snap[0] =
653     FlGui::instance()->elementaryContext->value[0]->value();
654   CTX::instance()->geom.snap[1] =
655     FlGui::instance()->elementaryContext->value[1]->value();
656   CTX::instance()->geom.snap[2] =
657     FlGui::instance()->elementaryContext->value[2]->value();
658 }
659 
elementaryContextWindow(int deltaFontSize)660 elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
661 {
662   FL_NORMAL_SIZE -= deltaFontSize;
663 
664   int width = 34 * FL_NORMAL_SIZE;
665   int height = 5 * WB + 10 * BH;
666 
667   win = new paletteWindow(width, height,
668                           CTX::instance()->nonModalWindows ? true : false,
669                           "Elementary Entity Context");
670   win->box(GMSH_WINDOW_BOX);
671   {
672     tab1 = new Fl_Tabs(WB, WB, width - 2 * WB, height - 3 * WB - BH);
673     // 0: Parameter
674     {
675       group[0] = new Fl_Group(WB, WB + BH, width - 2 * WB,
676                               height - 3 * WB - 2 * BH, "Parameter");
677       input[0] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Name");
678       input[0]->value("lc");
679       input[1] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Value");
680       input[1]->value("0.1");
681       input[2] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Label");
682       input[2]->value("");
683       input[3] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Path");
684       input[3]->value("Parameters");
685       for(int i = 0; i < 4; i++) { input[i]->align(FL_ALIGN_RIGHT); }
686       {
687         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
688                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
689         o->callback(elementary_add_parameter_cb);
690       }
691       group[0]->end();
692     }
693     // 1: Point
694     {
695       group[1] = new Fl_Group(WB, WB + BH, width - 2 * WB,
696                               height - 3 * WB - 2 * BH, "Point");
697       input[4] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X");
698       input[4]->value("0");
699       input[5] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y");
700       input[5]->value("0");
701       input[6] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Z");
702       input[6]->value("0");
703       input[7] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH,
704                               "Prescribed mesh size at point");
705       input[7]->value("1.0");
706       for(int i = 4; i < 8; i++) {
707         input[i]->align(FL_ALIGN_RIGHT);
708         input[i]->callback(elementary_draw_point_cb);
709       }
710       {
711         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
712                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
713         o->callback(elementary_add_point_cb);
714       }
715       group[1]->end();
716     }
717     // 2: Circle
718     {
719       group[2] = new Fl_Group(WB, WB + BH, width - 2 * WB,
720                               height - 3 * WB - 2 * BH, "Circle");
721       input[8] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
722       input[8]->value("0");
723       input[9] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
724       input[9]->value("0");
725       input[10] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Center Z");
726       input[10]->value("0");
727       input[11] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Radius");
728       input[11]->value("0.5");
729       input[12] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Angle 1");
730       input[12]->value("0");
731       input[13] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Angle 2");
732       input[13]->value("2*Pi");
733       for(int i = 8; i < 14; i++) {
734         input[i]->align(FL_ALIGN_RIGHT);
735         input[i]->callback(elementary_draw_circle_cb);
736       }
737       {
738         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
739                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
740         o->callback(elementary_add_circle_cb);
741       }
742       group[2]->end();
743     }
744     // 3: Ellipse
745     {
746       group[3] = new Fl_Group(WB, WB + BH, width - 2 * WB,
747                               height - 3 * WB - 2 * BH, "Ellipse");
748       input[14] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
749       input[14]->value("0");
750       input[15] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
751       input[15]->value("0");
752       input[16] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Center Z");
753       input[16]->value("0");
754       input[17] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Radius X");
755       input[17]->value("0.5");
756       input[18] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Radius Y");
757       input[18]->value("0.25");
758       input[19] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Angle 1");
759       input[19]->value("0");
760       input[20] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Angle 2");
761       input[20]->value("2*Pi");
762       for(int i = 14; i < 21; i++) {
763         input[i]->align(FL_ALIGN_RIGHT);
764         input[i]->callback(elementary_draw_ellipse_cb);
765       }
766       {
767         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
768                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
769         o->callback(elementary_add_ellipse_cb);
770       }
771       group[3]->end();
772     }
773     // 4: Disk
774     {
775       group[4] = new Fl_Group(WB, WB + BH, width - 2 * WB,
776                               height - 3 * WB - 2 * BH, "Disk");
777       input[21] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
778       input[21]->value("0");
779       input[22] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
780       input[22]->value("0");
781       input[23] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Center Z");
782       input[23]->value("0");
783       input[24] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Radius X");
784       input[24]->value("0.5");
785       input[25] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Radius Y");
786       input[25]->value("0.25");
787       for(int i = 21; i < 26; i++) {
788         input[i]->align(FL_ALIGN_RIGHT);
789         input[i]->callback(elementary_draw_disk_cb);
790       }
791       {
792         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
793                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
794         o->callback(elementary_add_disk_cb);
795       }
796       group[4]->end();
797     }
798     // 5: Rectangle
799     {
800       group[5] = new Fl_Group(WB, WB + BH, width - 2 * WB,
801                               height - 3 * WB - 2 * BH, "Rectangle");
802       input[26] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X");
803       input[26]->value("0");
804       input[27] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y");
805       input[27]->value("0");
806       input[28] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Z");
807       input[28]->value("0");
808       input[29] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "DX");
809       input[29]->value("1");
810       input[30] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "DY");
811       input[30]->value("0.5");
812       input[31] =
813         new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Rounded radius");
814       input[31]->value("0");
815       for(int i = 26; i < 32; i++) {
816         input[i]->align(FL_ALIGN_RIGHT);
817         input[i]->callback(elementary_draw_rectangle_cb);
818       }
819       {
820         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
821                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
822         o->callback(elementary_add_rectangle_cb);
823       }
824       group[5]->end();
825     }
826     tab1->end();
827   }
828   {
829     tab2 = new Fl_Tabs(WB, WB, width - 2 * WB, height - 3 * WB - BH);
830     // 6: Sphere
831     {
832       group[6] = new Fl_Group(WB, WB + BH, width - 2 * WB,
833                               height - 3 * WB - 2 * BH, "Sphere");
834       input[32] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
835       input[32]->value("0");
836       input[33] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
837       input[33]->value("0");
838       input[34] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Center Z");
839       input[34]->value("0");
840       input[35] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Radius");
841       input[35]->value("0.5");
842       input[36] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Angle 1");
843       input[36]->value("-Pi/2");
844       input[37] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Angle 2");
845       input[37]->value("Pi/2");
846       input[38] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Angle 3");
847       input[38]->value("2*Pi");
848       for(int i = 32; i < 39; i++) {
849         input[i]->align(FL_ALIGN_RIGHT);
850         input[i]->callback(elementary_draw_sphere_cb);
851       }
852       {
853         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
854                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
855         o->callback(elementary_add_sphere_cb);
856       }
857       group[6]->end();
858     }
859     // 7: Cylinder
860     {
861       group[7] = new Fl_Group(WB, WB + BH, width - 2 * WB,
862                               height - 3 * WB - 2 * BH, "Cylinder");
863       input[39] =
864         new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center base X");
865       input[39]->value("0");
866       input[40] =
867         new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center base Y");
868       input[40]->value("0");
869       input[41] =
870         new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Center base Z");
871       input[41]->value("0");
872       input[42] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Axis DX");
873       input[42]->value("1");
874       input[43] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Axis DY");
875       input[43]->value("0");
876       input[44] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Axis DZ");
877       input[44]->value("0");
878       input[45] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Radius");
879       input[45]->value("0.5");
880       input[46] = new Fl_Input(2 * WB, 2 * WB + 8 * BH, IW, BH, "Angle");
881       input[46]->value("2*Pi");
882       for(int i = 39; i < 47; i++) {
883         input[i]->align(FL_ALIGN_RIGHT);
884         input[i]->callback(elementary_draw_cylinder_cb);
885       }
886       {
887         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
888                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
889         o->callback(elementary_add_cylinder_cb);
890       }
891       group[7]->end();
892     }
893     // 8: Box
894     {
895       group[8] = new Fl_Group(WB, WB + BH, width - 2 * WB,
896                               height - 3 * WB - 2 * BH, "Box");
897       input[47] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X");
898       input[47]->value("0");
899       input[48] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y");
900       input[48]->value("0");
901       input[49] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Z");
902       input[49]->value("0");
903       input[50] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "DX");
904       input[50]->value("1");
905       input[51] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "DY");
906       input[51]->value("1");
907       input[52] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "DZ");
908       input[52]->value("1");
909       for(int i = 47; i < 53; i++) {
910         input[i]->align(FL_ALIGN_RIGHT);
911         input[i]->callback(elementary_draw_box_cb);
912       }
913       {
914         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
915                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
916         o->callback(elementary_add_box_cb);
917       }
918       group[8]->end();
919     }
920     // 9: Torus
921     {
922       group[9] = new Fl_Group(WB, WB + BH, width - 2 * WB,
923                               height - 3 * WB - 2 * BH, "Torus");
924       input[53] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
925       input[53]->value("0");
926       input[54] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
927       input[54]->value("0");
928       input[55] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Center Z");
929       input[55]->value("0");
930       input[56] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Radius 1");
931       input[56]->value("0.5");
932       input[57] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Radius 2");
933       input[57]->value("0.2");
934       input[58] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Angle");
935       input[58]->value("2*Pi");
936       for(int i = 53; i < 59; i++) {
937         input[i]->align(FL_ALIGN_RIGHT);
938         input[i]->callback(elementary_draw_torus_cb);
939       }
940       {
941         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
942                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
943         o->callback(elementary_add_torus_cb);
944       }
945       group[9]->end();
946     }
947     // 10: Cone
948     {
949       group[10] = new Fl_Group(WB, WB + BH, width - 2 * WB,
950                                height - 3 * WB - 2 * BH, "Cone");
951       input[59] =
952         new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center base X");
953       input[59]->value("0");
954       input[60] =
955         new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center base Y");
956       input[60]->value("0");
957       input[61] =
958         new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Center base Z");
959       input[61]->value("0");
960       input[62] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Axis DX");
961       input[62]->value("1");
962       input[63] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Axis DY");
963       input[63]->value("0");
964       input[64] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Axis DZ");
965       input[64]->value("0");
966       input[65] = new Fl_Input(2 * WB + (width - 2 * WB) / 2, 2 * WB + 4 * BH,
967                                IW, BH, "Radius 1");
968       input[65]->value("0.5");
969       input[66] = new Fl_Input(2 * WB + (width - 2 * WB) / 2, 2 * WB + 5 * BH,
970                                IW, BH, "Radius 2");
971       input[66]->value("0.1");
972       input[67] = new Fl_Input(2 * WB + (width - 2 * WB) / 2, 2 * WB + 6 * BH,
973                                IW, BH, "Angle");
974       input[67]->value("2*Pi");
975       for(int i = 59; i < 68; i++) {
976         input[i]->align(FL_ALIGN_RIGHT);
977         input[i]->callback(elementary_draw_cone_cb);
978       }
979       {
980         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
981                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
982         o->callback(elementary_add_cone_cb);
983       }
984       group[10]->end();
985     }
986     // 11: Wedge
987     {
988       group[11] = new Fl_Group(WB, WB + BH, width - 2 * WB,
989                                height - 3 * WB - 2 * BH, "Wedge");
990       input[68] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X");
991       input[68]->value("0");
992       input[69] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y");
993       input[69]->value("0");
994       input[70] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Z");
995       input[70]->value("0");
996       input[71] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "DX");
997       input[71]->value("0.5");
998       input[72] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "DY");
999       input[72]->value("0.5");
1000       input[73] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "DZ");
1001       input[73]->value("0.5");
1002       input[74] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Top DX");
1003       input[74]->value("0");
1004       for(int i = 68; i < 75; i++) {
1005         input[i]->align(FL_ALIGN_RIGHT);
1006         input[i]->callback(elementary_draw_wedge_cb);
1007       }
1008       {
1009         Fl_Button *o = new Fl_Button(width - BB - 2 * WB,
1010                                      height - 3 * WB - 2 * BH, BB, BH, "Add");
1011         o->callback(elementary_add_wedge_cb);
1012       }
1013       group[11]->end();
1014     }
1015     tab2->end();
1016   }
1017 
1018   {
1019     Fl_Button *o = new Fl_Button(width - 4 * WB, WB, 3 * WB, 3 * WB, "...");
1020     o->callback(elementary_switch_tabs_cb);
1021   }
1022   {
1023     value[0] = new Fl_Value_Input(WB, height - WB - BH, IW / 3, BH, "X");
1024     value[1] =
1025       new Fl_Value_Input(WB + IW / 2, height - WB - BH, IW / 3, BH, "Y");
1026     value[2] =
1027       new Fl_Value_Input(WB + IW, height - WB - BH, IW / 3, BH, "Z snap");
1028     for(int i = 0; i < 3; i++) {
1029       value[i]->align(FL_ALIGN_RIGHT);
1030       value[i]->callback(elementary_snap_cb);
1031     }
1032     butt[0] =
1033       new Fl_Check_Button(width - 6 * BH, height - WB - BH, 1.2 * BH, BH, "X");
1034     butt[0]->tooltip("Toggle (x) or exclusive unselect (Shift+x)");
1035     butt[1] = new Fl_Check_Button(width - 6 * BH + 1.2 * BH, height - WB - BH,
1036                                   1.2 * BH, BH, "Y");
1037     butt[1]->tooltip("Toggle (y) or exclusive unselect (Shift+y)");
1038     butt[2] = new Fl_Check_Button(width - 6 * BH + 2.4 * BH, height - WB - BH,
1039                                   (6 - 2 * 1.2) * BH - WB, BH, "Z freeze");
1040     butt[2]->tooltip("Toggle (z) or exclusive unselect (Shift+z)");
1041   }
1042 
1043   tab1->show();
1044   tab2->hide();
1045 
1046   win->position(CTX::instance()->ctxPosition[0],
1047                 CTX::instance()->ctxPosition[1]);
1048   win->end();
1049 
1050   FL_NORMAL_SIZE += deltaFontSize;
1051 }
1052 
frozenPointCoord(int coord)1053 bool elementaryContextWindow::frozenPointCoord(int coord)
1054 {
1055   if(coord < 0 || coord > 2) return false;
1056   return butt[coord]->value() ? true : false;
1057 }
1058 
updatePoint(double pt[3],int which)1059 void elementaryContextWindow::updatePoint(double pt[3], int which)
1060 {
1061   for(int i = 0; i < 3; i++) {
1062     if(!frozenPointCoord(i)) {
1063       char str[32];
1064       sprintf(str, "%g", pt[i]);
1065       if(which == 1) {
1066         int start[11] = {4, 8, 14, 21, 26, 32, 39, 47, 53, 59, 68};
1067         for(int k = 0; k < 11; k++) {
1068           input[start[k] + i]->value(str);
1069           if(input[start[k] + i]->parent()->active()) {
1070             input[start[k] + i]->do_callback(nullptr, (void *)"no_redraw");
1071           }
1072         }
1073       }
1074     }
1075   }
1076 }
1077 
show(int pane)1078 void elementaryContextWindow::show(int pane)
1079 {
1080   FlGui::instance()->lastContextWindow = 0;
1081 
1082   if(pane < 0 || pane > 11) return;
1083 
1084   for(int i = 0; i < 12; i++) {
1085     group[i]->hide();
1086     group[i]->deactivate();
1087   }
1088 
1089   if(pane < 6) {
1090     tab1->show();
1091     tab2->hide();
1092   }
1093   else {
1094     tab1->hide();
1095     tab2->show();
1096   }
1097 
1098   group[pane]->show();
1099   group[pane]->activate();
1100   win->show();
1101 }
1102 
physical_add_cb(Fl_Widget * w,void * data)1103 static void physical_add_cb(Fl_Widget *w, void *data)
1104 {
1105   std::string what = data ? (const char *)data : "";
1106 
1107   physicalContextWindow *pc = FlGui::instance()->physicalContext;
1108   std::string name = pc->input[0]->value();
1109   int tag = pc->value[0]->value();
1110   std::string existingName = "";
1111   int existingTag = 0;
1112   if(what != "Tag") {
1113     auto it = pc->physicalNames.find(name);
1114     if(it != pc->physicalNames.end()) {
1115       existingName = name;
1116       existingTag = it->second;
1117     }
1118   }
1119   if(what != "Name") {
1120     auto it = pc->physicalTags.find(tag);
1121     if(it != pc->physicalTags.end()) {
1122       existingTag = tag;
1123       existingName = it->second;
1124     }
1125   }
1126 
1127   if(existingName.size() || existingTag) {
1128     // change color to warn that the group exists
1129     Fl_Color c = (!CTX::instance()->guiColorScheme ? FL_DARK_BLUE : FL_BLUE);
1130     pc->input[0]->textcolor(c);
1131     pc->value[0]->textcolor(c);
1132     if(what != "Name" && !strlen(pc->input[0]->value()))
1133       pc->input[0]->value(existingName.c_str());
1134     if(what != "Tag") pc->value[0]->value(existingTag);
1135     pc->append = true;
1136   }
1137   else {
1138     pc->input[0]->textcolor(FL_FOREGROUND_COLOR);
1139     pc->value[0]->textcolor(FL_FOREGROUND_COLOR);
1140     if(what != "Tag") pc->value[0]->value(NEWPHYSICAL());
1141     pc->append = false;
1142   }
1143 
1144   if(pc->butt[0]->active()) {
1145     if(pc->butt[0]->value())
1146       pc->value[0]->deactivate();
1147     else
1148       pc->value[0]->activate();
1149   }
1150 
1151   pc->input[0]->redraw();
1152   pc->value[0]->redraw();
1153 
1154   pc->selectedName = pc->input[0]->value();
1155   pc->selectedTag = pc->value[0]->value();
1156 }
1157 
physical_remove_cb(Fl_Widget * w,void * data)1158 static void physical_remove_cb(Fl_Widget *w, void *data)
1159 {
1160   physicalContextWindow *pc = FlGui::instance()->physicalContext;
1161   int tag = 0;
1162   std::string name = "";
1163   if(pc->choice[0]->text()) {
1164     std::vector<std::string> tmp = SplitString(pc->choice[0]->text(), ':');
1165     tag = (tmp.size() > 0) ? atoi(tmp[0].c_str()) : 0;
1166     name = (tmp.size() > 1) ? tmp[1] : "";
1167   }
1168 
1169   pc->selectedName = name;
1170   pc->selectedTag = tag;
1171 }
1172 
physicalContextWindow(int deltaFontSize)1173 physicalContextWindow::physicalContextWindow(int deltaFontSize)
1174   : selectedTag(0), type(""), mode("Add"), selectedName(""), append(false)
1175 {
1176   FL_NORMAL_SIZE -= deltaFontSize;
1177 
1178   int width = 30 * FL_NORMAL_SIZE;
1179   int height = 5 * WB + 4 * BH;
1180 
1181   win = new paletteWindow(width, height,
1182                           CTX::instance()->nonModalWindows ? true : false,
1183                           "Physical Group Context");
1184   win->box(GMSH_WINDOW_BOX);
1185 
1186   {
1187     tab = new Fl_Tabs(WB, WB, width - 2 * WB, 4 * BH + 3 * WB);
1188     // 0: Add
1189     {
1190       group[0] =
1191         new Fl_Group(WB, WB + BH, width - 2 * WB, 3 * BH + 3 * WB, "Add");
1192 
1193       box[0] = new Fl_Box(2 * WB, 2 * WB + 1 * BH, width, BH);
1194       box[0]->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
1195 
1196       input[0] = new Fl_Input_Choice(2 * WB, 2 * WB + 2 * BH,
1197                                      (int)(0.6 * width), BH, "Name");
1198       input[0]->value("");
1199       input[0]->align(FL_ALIGN_RIGHT);
1200       input[0]->callback(physical_add_cb, (void *)"Name");
1201       input[0]->when(FL_WHEN_CHANGED);
1202 
1203       value[0] = new Fl_Value_Input(2 * WB, 2 * WB + 3 * BH, (int)(0.6 * width),
1204                                     BH, "Tag");
1205       value[0]->value(0);
1206       value[0]->deactivate();
1207       value[0]->align(FL_ALIGN_RIGHT);
1208       value[0]->callback(physical_add_cb, (void *)"Tag");
1209       value[0]->when(FL_WHEN_CHANGED);
1210 
1211       butt[0] = new Fl_Check_Button(width - width / 4, 2 * WB + 3 * BH,
1212                                     width / 4 - 2 * WB, BH, "Automatic");
1213       butt[0]->value(1);
1214       butt[0]->callback(physical_add_cb);
1215 
1216       group[0]->end();
1217     }
1218     // 1: Remove
1219     {
1220       group[1] =
1221         new Fl_Group(WB, WB + BH, width - 2 * WB, 3 * BH + 3 * WB, "Remove");
1222 
1223       box[1] = new Fl_Box(2 * WB, 2 * WB + 1 * BH, width, BH);
1224       box[1]->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
1225 
1226       choice[0] =
1227         new Fl_Choice(2 * WB, 2 * WB + 2 * BH, (int)(0.6 * width), BH);
1228       choice[0]->align(FL_ALIGN_RIGHT);
1229       choice[0]->callback(physical_remove_cb);
1230 
1231       group[1]->end();
1232     }
1233     tab->end();
1234   }
1235 
1236   win->position(CTX::instance()->ctxPosition[0],
1237                 CTX::instance()->ctxPosition[1]);
1238   win->end();
1239 
1240   FL_NORMAL_SIZE += deltaFontSize;
1241 }
1242 
show(const std::string & what,bool remove)1243 void physicalContextWindow::show(const std::string &what, bool remove)
1244 {
1245   FlGui::instance()->lastContextWindow = 3;
1246 
1247   // update window title and labels
1248   type = what;
1249   int dim;
1250   if(type == "Volume")
1251     dim = 3;
1252   else if(type == "Surface")
1253     dim = 2;
1254   else if(type == "Curve")
1255     dim = 1;
1256   else if(type == "Point")
1257     dim = 0;
1258   else {
1259     Msg::Error("Unknown physical context '%s'", type.c_str());
1260     return;
1261   }
1262   win->copy_label(std::string("Physical " + type + " Context").c_str());
1263   std::string s(" and select " + type + "(s) to ");
1264   std::transform(s.begin(), s.end(), s.begin(), ::tolower);
1265   box[0]->copy_label(
1266     std::string("Create or choose group," + s + "add").c_str());
1267   box[1]->copy_label(std::string("Choose group" + s + "remove").c_str());
1268 
1269   // get all physical group tags and names (this is relatively expensive - so we
1270   // shouldn't do it in the callbacks)
1271   std::map<int, std::vector<GEntity *> > groups;
1272   GModel::current()->getPhysicalGroups(dim, groups);
1273   physicalTags.clear();
1274   physicalNames.clear();
1275   for(auto &p : groups) {
1276     std::string name = GModel::current()->getPhysicalName(dim, p.first);
1277     physicalTags[p.first] = name;
1278     if(name.size()) physicalNames[name] = p.first;
1279   }
1280 
1281   // create menus with existing physicals
1282   std::vector<Fl_Menu_Item> menuAdd, menuRemove;
1283   static std::vector<char *> toFree;
1284   for(std::size_t i = 0; i < toFree.size(); i++) free(toFree[i]);
1285   toFree.clear();
1286   {
1287     for(auto &p : physicalNames) {
1288       char *str = strdup(p.first.c_str());
1289       Fl_Menu_Item item = {str, 0, nullptr, nullptr, 0};
1290       toFree.push_back(str);
1291       menuAdd.push_back(item);
1292     }
1293     Fl_Menu_Item item = {nullptr};
1294     menuAdd.push_back(item);
1295     input[0]->menubutton()->copy(&menuAdd[0]);
1296   }
1297   {
1298     for(auto &p : physicalTags) {
1299       std::string label = std::to_string(p.first);
1300       if(p.second.size()) label += ": " + p.second;
1301       char *str = strdup(label.c_str());
1302       Fl_Menu_Item item = {str, 0, nullptr, nullptr, 0};
1303       toFree.push_back(str);
1304       menuRemove.push_back(item);
1305     }
1306     Fl_Menu_Item item = {nullptr};
1307     menuRemove.push_back(item);
1308     choice[0]->copy(&menuRemove[0]);
1309   }
1310 
1311   // activate the relevant tabs and widgets
1312   for(int i = 0; i < 2; i++) {
1313     group[i]->hide();
1314     group[i]->deactivate();
1315   }
1316   if(remove) {
1317     mode = "Remove";
1318     group[1]->show();
1319     group[1]->activate();
1320     physical_remove_cb(nullptr, nullptr);
1321   }
1322   else {
1323     mode = "Add";
1324     group[0]->show();
1325     group[0]->activate();
1326     if(butt[0]->value())
1327       value[0]->deactivate();
1328     else
1329       value[0]->activate();
1330     physical_add_cb(nullptr, (void *)"Name");
1331   }
1332 
1333   if(!win->shown()) win->show();
1334 }
1335 
1336 static Fl_Menu_Item menu_selection_mode[] = {
1337   {"All entities", 0, nullptr, nullptr}, {"Points", 0, nullptr, nullptr},
1338   {"Curves", 0, nullptr, nullptr},       {"Surfaces", 0, nullptr, nullptr},
1339   {"Volumes", 0, nullptr, nullptr},      {nullptr}};
1340 
selection_mode_cb(Fl_Widget * w,void * data)1341 static void selection_mode_cb(Fl_Widget *w, void *data)
1342 {
1343   Fl_Choice *c = (Fl_Choice *)w;
1344   int mode = ENT_ALL;
1345   switch(c->value()) {
1346   case 1:
1347     mode = ENT_POINT;
1348     opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
1349     break;
1350   case 2:
1351     mode = ENT_CURVE;
1352     opt_geometry_curves(0, GMSH_SET | GMSH_GUI, 1);
1353     break;
1354   case 3:
1355     mode = ENT_SURFACE;
1356     opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
1357     break;
1358   case 4:
1359     mode = ENT_VOLUME;
1360     opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1);
1361     break;
1362   }
1363   for(std::size_t i = 0; i < FlGui::instance()->graph.size(); i++)
1364     for(std::size_t j = 0; j < FlGui::instance()->graph[i]->gl.size(); j++)
1365       FlGui::instance()->graph[i]->gl[j]->changeSelection = mode;
1366   drawContext::global()->draw();
1367 }
1368 
transformContextWindow(int deltaFontSize)1369 transformContextWindow::transformContextWindow(int deltaFontSize)
1370 {
1371   FL_NORMAL_SIZE -= deltaFontSize;
1372 
1373   int width = 34 * FL_NORMAL_SIZE;
1374   int height = 5 * WB + 10 * BH;
1375 
1376   win = new paletteWindow(width, height,
1377                           CTX::instance()->nonModalWindows ? true : false,
1378                           "Elementary Operation Context");
1379   win->box(GMSH_WINDOW_BOX);
1380   {
1381     Fl_Tabs *o = new Fl_Tabs(WB, WB, width - 2 * WB, height - 3 * WB - BH);
1382     // 0: Translate
1383     {
1384       group[0] = new Fl_Group(WB, WB + BH, width - 2 * WB,
1385                               height - 3 * WB - 2 * BH, "Translate");
1386       input[0] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "DX");
1387       input[0]->value("0");
1388       input[1] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "DY");
1389       input[1]->value("0");
1390       input[2] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "DZ");
1391       input[2]->value("1");
1392       for(int i = 0; i < 3; i++) { input[i]->align(FL_ALIGN_RIGHT); }
1393       butt[0] = new Fl_Check_Button(2 * WB, 2 * WB + 4 * BH, width - 4 * WB, BH,
1394                                     "Apply translation on copy");
1395       butt[0]->value(0);
1396       butt[7] = new Fl_Check_Button(2 * WB, 2 * WB + 5 * BH, width - 4 * WB, BH,
1397                                     "Extrude mesh");
1398       butt[7]->value(0);
1399       input[21] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Mesh layers");
1400       input[21]->value("5");
1401       input[21]->align(FL_ALIGN_RIGHT);
1402       butt[8] = new Fl_Check_Button(width / 2 + 2 * WB, 2 * WB + 6 * BH,
1403                                     width / 2 - 4 * WB, BH, "Recombine");
1404       butt[8]->value(1);
1405       group[0]->end();
1406     }
1407     // 1: Rotate
1408     {
1409       group[1] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1410                               "Rotate");
1411       input[3] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Axis point X");
1412       input[3]->value("0");
1413       input[4] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Axis point Y");
1414       input[4]->value("0");
1415       input[5] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Axis point Z");
1416       input[5]->value("0");
1417       input[6] =
1418         new Fl_Input(width / 2 + 2 * WB, 2 * WB + 1 * BH, IW, BH, "Axis DX");
1419       input[6]->value("0");
1420       input[7] =
1421         new Fl_Input(width / 2 + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Axis DY");
1422       input[7]->value("1");
1423       input[8] =
1424         new Fl_Input(width / 2 + 2 * WB, 2 * WB + 3 * BH, IW, BH, "Axis DZ");
1425       input[8]->value("0");
1426       input[9] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Angle");
1427       input[9]->value("Pi/4");
1428       for(int i = 3; i < 10; i++) { input[i]->align(FL_ALIGN_RIGHT); }
1429       butt[1] = new Fl_Check_Button(2 * WB, 2 * WB + 5 * BH, width - 4 * WB, BH,
1430                                     "Apply rotation on copy");
1431       butt[1]->value(0);
1432       butt[9] = new Fl_Check_Button(2 * WB, 2 * WB + 6 * BH, width - 4 * WB, BH,
1433                                     "Extrude mesh");
1434       butt[9]->value(0);
1435       input[22] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Mesh layers");
1436       input[22]->value("5");
1437       input[22]->align(FL_ALIGN_RIGHT);
1438       butt[10] = new Fl_Check_Button(width / 2 + 2 * WB, 2 * WB + 7 * BH,
1439                                      width / 2 - 4 * WB, BH, "Recombine");
1440       butt[10]->value(1);
1441       group[1]->end();
1442     }
1443     // 2: Scale
1444     {
1445       group[2] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1446                               "Scale");
1447       input[10] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
1448       input[10]->value("0");
1449       input[11] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
1450       input[11]->value("0");
1451       input[12] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Center Z");
1452       input[12]->value("0");
1453       input[13] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Scale X");
1454       input[13]->value("0.5");
1455       input[14] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Scale Y");
1456       input[14]->value("0.5");
1457       input[15] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Scale Z");
1458       input[15]->value("0.5");
1459       for(int i = 10; i < 16; i++) { input[i]->align(FL_ALIGN_RIGHT); }
1460       butt[2] = new Fl_Check_Button(2 * WB, 2 * WB + 7 * BH, width - 4 * WB, BH,
1461                                     "Apply scaling on copy");
1462       butt[2]->value(0);
1463       group[2]->end();
1464     }
1465     // 3: Symmetry
1466     {
1467       group[3] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1468                               "Symmetry");
1469       input[16] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Plane A");
1470       input[16]->value("1");
1471       input[17] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Plane B");
1472       input[17]->value("0");
1473       input[18] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Plane C");
1474       input[18]->value("0");
1475       input[19] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Plane D");
1476       input[19]->value("1");
1477       for(int i = 16; i < 20; i++) { input[i]->align(FL_ALIGN_RIGHT); }
1478       butt[3] = new Fl_Check_Button(2 * WB, 2 * WB + 5 * BH, width - 4 * WB, BH,
1479                                     "Apply symmetry on copy");
1480       butt[3]->value(0);
1481       group[3]->end();
1482     }
1483     // 4: Boolean
1484     {
1485       group[4] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1486                               "Boolean");
1487       butt[4] = new Fl_Check_Button(2 * WB, 2 * WB + 1 * BH, width - 4 * WB, BH,
1488                                     "Delete object");
1489       butt[4]->value(1);
1490       butt[5] = new Fl_Check_Button(2 * WB, 2 * WB + 2 * BH, width - 4 * WB, BH,
1491                                     "Delete tool");
1492       butt[5]->value(1);
1493       group[4]->end();
1494     }
1495     // 5: Fillet
1496     {
1497       group[5] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1498                               "Fillet");
1499       input[20] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Radius");
1500       input[20]->value("0.1");
1501       input[20]->align(FL_ALIGN_RIGHT);
1502       group[5]->end();
1503     }
1504     // 6: Delete
1505     {
1506       group[6] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1507                               "Delete");
1508       butt[6] = new Fl_Check_Button(2 * WB, 2 * WB + 1 * BH, width - 4 * WB, BH,
1509                                     "Recursive");
1510       butt[6]->value(1);
1511       group[6]->end();
1512     }
1513     o->end();
1514   }
1515 
1516   choice = new Fl_Choice(WB, height - WB - BH, IW, BH, "Selection mode");
1517   choice->menu(menu_selection_mode);
1518   choice->align(FL_ALIGN_RIGHT);
1519   choice->callback(selection_mode_cb);
1520 
1521   win->position(CTX::instance()->ctxPosition[0],
1522                 CTX::instance()->ctxPosition[1]);
1523   win->end();
1524 
1525   FL_NORMAL_SIZE += deltaFontSize;
1526 }
1527 
show(int pane,bool extrude,bool selection)1528 void transformContextWindow::show(int pane, bool extrude, bool selection)
1529 {
1530   FlGui::instance()->lastContextWindow = 1;
1531 
1532   for(int i = 0; i < 7; i++) {
1533     group[i]->hide();
1534     group[i]->deactivate();
1535   }
1536   for(int i = 0; i < 4; i++) {
1537     if(extrude)
1538       butt[i]->deactivate();
1539     else
1540       butt[i]->activate();
1541   }
1542   for(int i = 7; i < 11; i++) {
1543     if(!extrude)
1544       butt[i]->deactivate();
1545     else
1546       butt[i]->activate();
1547   }
1548   for(int i = 21; i < 23; i++) {
1549     if(!extrude)
1550       input[i]->deactivate();
1551     else
1552       input[i]->activate();
1553   }
1554   if(selection)
1555     choice->activate();
1556   else
1557     choice->deactivate();
1558   if(pane < 0 || pane > 6) { group[0]->show(); }
1559   else {
1560     group[pane]->show();
1561     group[pane]->activate();
1562   }
1563   win->show();
1564 }
1565 
meshContextWindow(int deltaFontSize)1566 meshContextWindow::meshContextWindow(int deltaFontSize)
1567 {
1568   FL_NORMAL_SIZE -= deltaFontSize;
1569 
1570   static Fl_Menu menu_transfinite_dir[] = {{"Left", 0, nullptr, nullptr},
1571                                            {"Right", 0, nullptr, nullptr},
1572                                            {"Alternated", 0, nullptr, nullptr},
1573                                            {nullptr}};
1574 
1575   int width = 29 * FL_NORMAL_SIZE;
1576   int height = 4 * WB + 4 * BH;
1577 
1578   win = new paletteWindow(width, height, CTX::instance()->nonModalWindows,
1579                           "Mesh Context");
1580   win->box(GMSH_WINDOW_BOX);
1581   {
1582     Fl_Tabs *o = new Fl_Tabs(WB, WB, width - 2 * WB, height - 2 * WB);
1583     // 0: Element size at points
1584     {
1585       group[0] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1586                               "Element size");
1587       input[0] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Value");
1588       input[0]->value("0.1");
1589       input[0]->align(FL_ALIGN_RIGHT);
1590       group[0]->end();
1591     }
1592     // 1: Transfinite line
1593     {
1594       group[1] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1595                               "Transfinite curve");
1596       input[1] =
1597         new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Number of points");
1598       input[1]->value("10");
1599       input[2] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Parameter");
1600       input[2]->value("1");
1601       for(int i = 1; i < 3; i++) { input[i]->align(FL_ALIGN_RIGHT); }
1602       static Fl_Menu_Item menu_trsf_mesh[] = {
1603         {"Progression", 0, nullptr, nullptr},
1604         {"Bump", 0, nullptr, nullptr},
1605         {"Beta", 0, nullptr, nullptr},
1606         {nullptr}};
1607       choice[0] = new Fl_Choice(2 * WB, 2 * WB + 2 * BH, IW, BH, "Type");
1608       choice[0]->menu(menu_trsf_mesh);
1609       choice[0]->align(FL_ALIGN_RIGHT);
1610       group[1]->end();
1611     }
1612 
1613     // 2: Transfinite surface
1614     {
1615       group[2] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH,
1616                               "Transfinite Surface");
1617 
1618       choice[1] = new Fl_Choice(2 * WB, 2 * WB + 1 * BH, IW, BH,
1619                                 "Transfinite Arrangement");
1620       choice[1]->menu(menu_transfinite_dir);
1621       choice[1]->align(FL_ALIGN_RIGHT);
1622 
1623       group[2]->end();
1624     }
1625     o->end();
1626   }
1627 
1628   win->position(CTX::instance()->ctxPosition[0],
1629                 CTX::instance()->ctxPosition[1]);
1630   win->end();
1631 
1632   FL_NORMAL_SIZE += deltaFontSize;
1633 }
1634 
show(int pane)1635 void meshContextWindow::show(int pane)
1636 {
1637   FlGui::instance()->lastContextWindow = 2;
1638 
1639   for(int i = 0; i < 3; i++) {
1640     group[i]->hide();
1641     group[i]->deactivate();
1642   }
1643   group[pane]->show();
1644   group[pane]->activate();
1645   win->show();
1646 }
1647