1 // Gmsh - Copyright (C) 1997-2012 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file for license information. Please report all
4 // bugs and problems to <gmsh@geuz.org>.
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 <sstream>
13 #include <string.h>
14 #include <FL/Fl.H>
15 #include <FL/Fl_Tooltip.H>
16 #include <FL/Fl_Shared_Image.H>
17 #include <FL/Fl_File_Icon.H>
18 #include <FL/x.H>
19 #include <FL/gl.h>
20 #include "FlGui.h"
21 #include "graphicWindow.h"
22 #include "menuWindow.h"
23 #include "optionWindow.h"
24 #include "fieldWindow.h"
25 #include "pluginWindow.h"
26 #include "statisticsWindow.h"
27 #include "visibilityWindow.h"
28 #include "clippingWindow.h"
29 #include "manipWindow.h"
30 #include "contextWindow.h"
31 #include "onelabWindow.h"
32 #include "aboutWindow.h"
33 #include "colorbarWindow.h"
34 #include "fileDialogs.h"
35 #include "GmshDefines.h"
36 #include "GmshMessage.h"
37 #include "GModel.h"
38 #include "MElement.h"
39 #include "PView.h"
40 #include "Field.h"
41 #include "Plugin.h"
42 #include "PluginManager.h"
43 #include "OpenFile.h"
44 #include "Win32Icon.h"
45 #include "Options.h"
46 #include "CommandLine.h"
47 #include "Context.h"
48 #include "StringUtils.h"
49 #include "Generator.h"
50 #include "gl2ps.h"
51
52 // check (now!) if there are any pending events, and process them
check()53 void FlGui::check(){ Fl::check(); }
54
55 // wait (possibly indefinitely) for any events, then process them
wait()56 void FlGui::wait(){ Fl::wait(); }
57
58 // wait (at most time seconds) for any events, then process them
wait(double time)59 void FlGui::wait(double time){ Fl::wait(time); }
60
61 class drawContextFltk : public drawContextGlobal{
62 public:
draw()63 void draw()
64 {
65 if(!FlGui::available()) return;
66 for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++){
67 for(unsigned int j = 0; j < FlGui::instance()->graph[i]->gl.size(); j++){
68 FlGui::instance()->graph[i]->gl[j]->make_current();
69 FlGui::instance()->graph[i]->gl[j]->redraw();
70 // to initialize the camera distance from model
71 drawContext * ctx = FlGui::instance()->graph[i]->gl[j]->getDrawContext();
72 ctx->camera.update();
73 }
74 }
75 FlGui::instance()->check();
76 }
drawCurrentOpenglWindow(bool make_current)77 void drawCurrentOpenglWindow(bool make_current)
78 {
79 if(!FlGui::available()) return;
80 openglWindow *gl = FlGui::instance()->getCurrentOpenglWindow();
81 if(make_current) gl->make_current();
82 gl->redraw();
83 glFlush();
84 FlGui::instance()->check();
85 }
getFontIndex(const char * fontname)86 int getFontIndex(const char *fontname)
87 {
88 if(fontname){
89 for(int i = 0; i < NUM_FONTS; i++)
90 if(!strcmp(menu_font_names[i].label(), fontname))
91 return i;
92 }
93 Msg::Error("Unknown font \"%s\" (using \"Helvetica\" instead)", fontname);
94 Msg::Info("Available fonts:");
95 for(int i = 0; i < NUM_FONTS; i++)
96 Msg::Info(" \"%s\"", menu_font_names[i].label());
97 return 4;
98 }
getFontEnum(int index)99 int getFontEnum(int index)
100 {
101 if(index >= 0 && index < NUM_FONTS)
102 return (intptr_t)menu_font_names[index].user_data();
103 return FL_HELVETICA;
104 }
getFontName(int index)105 const char *getFontName(int index)
106 {
107 if(index >= 0 && index < NUM_FONTS)
108 return menu_font_names[index].label();
109 return "Helvetica";
110 }
getFontAlign(const char * alignstr)111 int getFontAlign(const char *alignstr)
112 {
113 if(alignstr){
114 if(!strcmp(alignstr, "BottomLeft") || !strcmp(alignstr, "Left") ||
115 !strcmp(alignstr, "left"))
116 return 0;
117 else if(!strcmp(alignstr, "BottomCenter") || !strcmp(alignstr, "Center") ||
118 !strcmp(alignstr, "center"))
119 return 1;
120 else if(!strcmp(alignstr, "BottomRight") || !strcmp(alignstr, "Right") ||
121 !strcmp(alignstr, "right"))
122 return 2;
123 else if(!strcmp(alignstr, "TopLeft"))
124 return 3;
125 else if(!strcmp(alignstr, "TopCenter"))
126 return 4;
127 else if(!strcmp(alignstr, "TopRight"))
128 return 5;
129 else if(!strcmp(alignstr, "CenterLeft"))
130 return 6;
131 else if(!strcmp(alignstr, "CenterCenter"))
132 return 7;
133 else if(!strcmp(alignstr, "CenterRight"))
134 return 8;
135 }
136 Msg::Error("Unknown font alignment \"%s\" (using \"Left\" instead)", alignstr);
137 Msg::Info("Available font alignments:");
138 Msg::Info(" \"Left\" (or \"BottomLeft\")");
139 Msg::Info(" \"Center\" (or \"BottomCenter\")");
140 Msg::Info(" \"Right\" (or \"BottomRight\")");
141 Msg::Info(" \"TopLeft\"");
142 Msg::Info(" \"TopCenter\"");
143 Msg::Info(" \"TopRight\"");
144 Msg::Info(" \"CenterLeft\"");
145 Msg::Info(" \"CenterCenter\"");
146 Msg::Info(" \"CenterRight\"");
147 return 0;
148 }
getFontSize()149 int getFontSize()
150 {
151 if(CTX::instance()->fontSize > 0){
152 return CTX::instance()->fontSize;
153 }
154 else{
155 int w = Fl::w();
156 if(w <= 1024) return 11;
157 else if(w <= 1280) return 12;
158 else if(w <= 1680) return 13;
159 else if(w <= 1920) return 14;
160 else return 15;
161 }
162 }
setFont(int fontid,int fontsize)163 void setFont(int fontid, int fontsize)
164 {
165 gl_font(fontid, fontsize);
166 }
getStringWidth(const char * str)167 double getStringWidth(const char *str)
168 {
169 return gl_width(str);
170 }
getStringHeight()171 int getStringHeight()
172 {
173 return gl_height();
174 }
getStringDescent()175 int getStringDescent()
176 {
177 return gl_descent();
178 }
drawString(const char * str)179 void drawString(const char *str)
180 {
181 gl_draw(str);
182 }
resetFontTextures()183 void resetFontTextures()
184 {
185 #if defined(__APPLE__) && (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3)
186 gl_texture_pile_height(1); // force font texture recomputation
187 #endif
188 }
189 };
190
globalShortcut(int event)191 static int globalShortcut(int event)
192 {
193 if(!FlGui::available()) return 0;
194 return FlGui::instance()->testGlobalShortcuts(event);
195 }
196
FlGui(int argc,char ** argv)197 FlGui::FlGui(int argc, char **argv) : _openedThroughMacFinder(false)
198 {
199 // set X display
200 if(CTX::instance()->display.size())
201 Fl::display(CTX::instance()->display.c_str());
202
203 #if 0 // dark scheme... not bad, but needs work
204 Fl::background(60, 60, 60);
205 Fl::background2(120, 120, 120);
206 Fl::foreground(200, 200, 200);
207 #endif
208
209 // add global shortcuts
210 Fl::add_handler(globalShortcut);
211
212 // set global fltk-dependent drawing functions
213 drawContext::setGlobal(new drawContextFltk);
214
215 // set default font size
216 FL_NORMAL_SIZE = drawContext::global()->getFontSize();
217
218 // handle themes and tooltip font size
219 if(CTX::instance()->guiTheme.size())
220 Fl::scheme(CTX::instance()->guiTheme.c_str());
221 Fl_Tooltip::size(FL_NORMAL_SIZE);
222
223 // register image formats not in core fltk library (jpeg/png)
224 fl_register_images();
225
226 // load default system icons (for file browser)
227 Fl_File_Icon::load_system_icons();
228
229 // add callback to respond to Mac Finder
230 #if defined(__APPLE__)
231 fl_open_callback(OpenProjectMacFinder);
232 #if (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3)
233 fl_mac_set_about(help_about_cb, 0);
234 #endif
235 #endif
236
237 // all the windows are contructed (even if some are not displayed)
238 // since the shortcuts should be valid even for hidden windows, and
239 // we don't want to test for widget existence every time
240 menu = new menuWindow();
241 graph.push_back(new graphicWindow(true, CTX::instance()->numTiles));
242
243 #if defined(WIN32)
244 graph[0]->win->icon
245 ((const char*)LoadImage(fl_display, MAKEINTRESOURCE(IDI_ICON),
246 IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR));
247 #elif defined(__APPLE__)
248 // nothing to do here
249 #else
250 fl_open_display();
251 static char gmsh32x32[] = {
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, 0x03, 0x00,
253 0x00, 0x40, 0x03, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, 0x20, 0x07, 0x00,
254 0x00, 0x10, 0x0f, 0x00, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x08, 0x1f, 0x00,
255 0x00, 0x08, 0x1f, 0x00, 0x00, 0x04, 0x3f, 0x00, 0x00, 0x04, 0x3f, 0x00,
256 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x01, 0xff, 0x00,
257 0x00, 0x01, 0xff, 0x00, 0x80, 0x00, 0xff, 0x01, 0x80, 0x00, 0xff, 0x01,
258 0x40, 0x00, 0xff, 0x03, 0x40, 0x00, 0xff, 0x03, 0x20, 0x00, 0xff, 0x07,
259 0x20, 0x00, 0xff, 0x07, 0x10, 0x00, 0xff, 0x0f, 0x10, 0x00, 0xff, 0x0f,
260 0x08, 0x00, 0xff, 0x1f, 0x08, 0x00, 0xff, 0x1f, 0x04, 0x40, 0xfd, 0x3f,
261 0x04, 0xa8, 0xea, 0x3f, 0x02, 0x55, 0x55, 0x7f, 0xa2, 0xaa, 0xaa, 0x7a,
262 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
263 graph[0]->win->icon
264 ((const char*)XCreateBitmapFromData(fl_display, DefaultRootWindow(fl_display),
265 gmsh32x32, 32, 32));
266 menu->win->icon
267 ((const char*)XCreateBitmapFromData(fl_display, DefaultRootWindow(fl_display),
268 gmsh32x32, 32, 32));
269 #endif
270
271 // open graphic window first for correct non-modal behaviour on
272 // Win32
273 graph[0]->win->show(1, argv);
274 menu->win->show();
275
276 // graphic window should have the initial focus (so we can
277 // e.g. directly loop through time steps with the keyboard)
278 //graph[0]->gl[0]->take_focus();
279 Fl::focus(graph[0]->gl[0]);
280
281 // create additional graphic windows
282 for(int i = 1; i < CTX::instance()->numWindows; i++){
283 graphicWindow *g = new graphicWindow(false, CTX::instance()->numTiles);
284 g->win->resize(graph.back()->win->x() + 10, graph.back()->win->y() + 10,
285 graph.back()->win->w(), graph.back()->win->h());
286 g->win->show();
287 graph.push_back(g);
288 }
289
290 options = new optionWindow(CTX::instance()->deltaFontSize);
291 fields = new fieldWindow(CTX::instance()->deltaFontSize);
292 plugins = new pluginWindow(CTX::instance()->deltaFontSize);
293 stats = new statisticsWindow(CTX::instance()->deltaFontSize);
294 visibility = new visibilityWindow(CTX::instance()->deltaFontSize);
295 clipping = new clippingWindow(CTX::instance()->deltaFontSize);
296 manip = new manipWindow(CTX::instance()->deltaFontSize);
297 geoContext = new geometryContextWindow(CTX::instance()->deltaFontSize);
298 meshContext = new meshContextWindow(CTX::instance()->deltaFontSize);
299 about = new aboutWindow();
300 #if defined(HAVE_ONELAB) && (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3)
301 onelab = new onelabWindow(CTX::instance()->deltaFontSize);
302 #endif
303
304 // init solver plugin stuff
305 callForSolverPlugin(-1);
306
307 // draw
308 for(unsigned int i = 0; i < graph.size(); i++)
309 for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
310 graph[i]->gl[j]->redraw();
311
312 menu->setContext(menu_geometry, 0);
313 }
314
315 FlGui *FlGui::_instance = 0;
316
instance(int argc,char ** argv)317 FlGui *FlGui::instance(int argc, char **argv)
318 {
319 if(!_instance){
320 _instance = new FlGui(argc, argv);
321 // set all options in the new GUI
322 InitOptionsGUI(0);
323 // say welcome!
324 Msg::StatusBar(1, false, "Geometry");
325 Msg::StatusBar(2, false, "Gmsh %s", GetGmshVersion());
326 // log the following for bug reports
327 Msg::Info("-------------------------------------------------------");
328 Msg::Info("Gmsh version : %s", GetGmshVersion());
329 Msg::Info("Build OS : %s", GetGmshBuildOS());
330 Msg::Info("Build options :%s", GetGmshBuildOptions());
331 Msg::Info("Build date : %s", GetGmshBuildDate());
332 Msg::Info("Build host : %s", GetGmshBuildHost());
333 Msg::Info("Packager : %s", GetGmshPackager());
334 Msg::Info("Home directory : %s", CTX::instance()->homeDir.c_str());
335 Msg::Info("Launch date : %s", Msg::GetLaunchDate().c_str());
336 Msg::Info("Command line : %s", Msg::GetCommandLineArgs().c_str());
337 Msg::Info("-------------------------------------------------------");
338 }
339 return _instance;
340 }
341
run()342 int FlGui::run()
343 {
344 // bounding box computation necessary if we run the gui without
345 // merging any files (e.g. if we build the geometry with python and
346 // create the gui from the python script)
347 SetBoundingBox();
348
349 // draw the scene
350 drawContext::global()->draw();
351
352 return Fl::run();
353 }
354
testGlobalShortcuts(int event)355 int FlGui::testGlobalShortcuts(int event)
356 {
357 // we only handle shortcuts here
358 if(event != FL_SHORTCUT) return 0;
359
360 int status = 0;
361
362 if(Fl::test_shortcut('0')) {
363 // FIXME: here we should also reset all onelab variables that depend on Gmsh
364 geometry_reload_cb(0, 0);
365 mod_geometry_cb(0, 0);
366 status = 1;
367 }
368 else if(Fl::test_shortcut('1') || Fl::test_shortcut(FL_F + 1)) {
369 mesh_1d_cb(0, 0);
370 mod_mesh_cb(0, 0);
371 status = 1;
372 }
373 else if(Fl::test_shortcut('2') || Fl::test_shortcut(FL_F + 2)) {
374 mesh_2d_cb(0, 0);
375 mod_mesh_cb(0, 0);
376 status = 1;
377 }
378 else if(Fl::test_shortcut('3') || Fl::test_shortcut(FL_F + 3)) {
379 mesh_3d_cb(0, 0);
380 mod_mesh_cb(0, 0);
381 status = 1;
382 }
383 // FIXME TEST
384 else if(Fl::test_shortcut('4') || Fl::test_shortcut(FL_F + 4)) {
385 RecombineMesh(GModel::current());
386 status = 2;
387 }
388 else if(Fl::test_shortcut(FL_CTRL + 'q') || Fl::test_shortcut(FL_META + 'q')){
389 // only necessary when using the system menu bar, but hey, it
390 // cannot hurt...
391 file_quit_cb(0, 0);
392 status = 1;
393 }
394 else if(Fl::test_shortcut('g')) {
395 mod_geometry_cb(0, 0);
396 Fl::focus(menu->scroll);
397 status = 1;
398 }
399 else if(Fl::test_shortcut('m')) {
400 mod_mesh_cb(0, 0);
401 Fl::focus(menu->scroll);
402 status = 1;
403 }
404 else if(Fl::test_shortcut('s')) {
405 mod_solver_cb(0, 0);
406 Fl::focus(menu->scroll);
407 status = 1;
408 }
409 else if(Fl::test_shortcut('p')) {
410 mod_post_cb(0, 0);
411 Fl::focus(menu->scroll);
412 status = 1;
413 }
414 else if(Fl::test_shortcut('<')) {
415 mod_back_cb(0, 0);
416 status = 1;
417 }
418 else if(Fl::test_shortcut('>')) {
419 mod_forward_cb(0, 0);
420 status = 1;
421 }
422 else if(Fl::test_shortcut('w')) {
423 file_watch_cb(0, 0);
424 status = 1;
425 }
426 else if(Fl::test_shortcut('e')) {
427 for(unsigned int i = 0; i < graph.size(); i++)
428 for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
429 graph[i]->gl[j]->endSelection = 1;
430 status = 0; // trick: do as if we didn't use it
431 }
432 else if(Fl::test_shortcut('u')) {
433 for(unsigned int i = 0; i < graph.size(); i++)
434 for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
435 graph[i]->gl[j]->undoSelection = 1;
436 status = 0; // trick: do as if we didn't use it
437 }
438 else if(Fl::test_shortcut('i')) {
439 for(unsigned int i = 0; i < graph.size(); i++)
440 for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
441 graph[i]->gl[j]->invertSelection = 1;
442 status = 0; // trick: do as if we didn't use it
443 }
444 else if(Fl::test_shortcut('q')) {
445 for(unsigned int i = 0; i < graph.size(); i++)
446 for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
447 graph[i]->gl[j]->quitSelection = 1;
448 status = 0; // trick: do as if we didn't use it
449 }
450 else if(Fl::test_shortcut('-')) {
451 for(unsigned int i = 0; i < graph.size(); i++)
452 for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
453 graph[i]->gl[j]->invertSelection = 1;
454 status = 0; // trick: do as if we didn't use it
455 }
456 else if(Fl::test_shortcut(FL_Escape) ||
457 Fl::test_shortcut(FL_META + FL_Escape) ||
458 Fl::test_shortcut(FL_SHIFT + FL_Escape) ||
459 Fl::test_shortcut(FL_CTRL + FL_Escape) ||
460 Fl::test_shortcut(FL_ALT + FL_Escape)) {
461 bool lasso = false;
462 for(unsigned int i = 0; i < graph.size(); i++)
463 for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
464 if(graph[i]->gl[j]->lassoMode) lasso = true;
465 if(lasso){
466 for(unsigned int i = 0; i < graph.size(); i++)
467 for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
468 graph[i]->gl[j]->lassoMode = false;
469 status = 2;
470 }
471 else{
472 status_options_cb(0, (void *)"S");
473 status = 1;
474 }
475 }
476 else if(Fl::test_shortcut(FL_SHIFT + 'a')) {
477 window_cb(0, (void*)"front");
478 status = 1;
479 }
480 else if(Fl::test_shortcut(FL_SHIFT + 'o')) {
481 general_options_cb(0, 0);
482 status = 1;
483 }
484 else if(Fl::test_shortcut(FL_SHIFT + 'g')) {
485 geometry_options_cb(0, 0);
486 status = 1;
487 }
488 else if(Fl::test_shortcut(FL_SHIFT + 'm')) {
489 mesh_options_cb(0, 0);
490 status = 1;
491 }
492 else if(Fl::test_shortcut(FL_SHIFT + 's')) {
493 solver_options_cb(0, 0);
494 status = 1;
495 }
496 else if(Fl::test_shortcut(FL_SHIFT + 'p')) {
497 post_options_cb(0, 0);
498 status = 1;
499 }
500 else if(Fl::test_shortcut(FL_SHIFT + 'w')) {
501 if(PView::list.size()){
502 if(options->view.index >= 0 && options->view.index < (int)PView::list.size())
503 options->showGroup(options->view.index + 6);
504 else
505 options->showGroup(6);
506 }
507 status = 1;
508 }
509 else if(Fl::test_shortcut(FL_SHIFT + 'u')) {
510 if(PView::list.size()){
511 if(options->view.index >= 0 && options->view.index < (int)PView::list.size())
512 plugins->show(options->view.index);
513 else
514 plugins->show(0);
515 }
516 status = 1;
517 }
518 else if(Fl::test_shortcut(FL_ALT + 'f')) {
519 opt_general_fast_redraw
520 (0, GMSH_SET | GMSH_GUI, !opt_general_fast_redraw(0, GMSH_GET, 0));
521 status = 2;
522 }
523 else if(Fl::test_shortcut(FL_ALT + 'b')) {
524 opt_general_draw_bounding_box
525 (0, GMSH_SET | GMSH_GUI, !opt_general_draw_bounding_box(0, GMSH_GET, 0));
526 status = 2;
527 }
528 else if(Fl::test_shortcut(FL_ALT + 'i')) {
529 for(unsigned int i = 0; i < PView::list.size(); i++)
530 if(opt_view_visible(i, GMSH_GET, 0))
531 opt_view_show_scale
532 (i, GMSH_SET | GMSH_GUI, !opt_view_show_scale(i, GMSH_GET, 0));
533 status = 2;
534 }
535 else if(Fl::test_shortcut(FL_ALT + 'c')) {
536 opt_general_color_scheme
537 (0, GMSH_SET | GMSH_GUI, opt_general_color_scheme(0, GMSH_GET, 0) + 1);
538 status = 2;
539 }
540 else if(Fl::test_shortcut(FL_ALT + 'w')) {
541 opt_geometry_light
542 (0, GMSH_SET | GMSH_GUI, !opt_geometry_light(0, GMSH_GET, 0));
543 opt_mesh_light
544 (0, GMSH_SET | GMSH_GUI, !opt_mesh_light(0, GMSH_GET, 0));
545 for(unsigned int i = 0; i < PView::list.size(); i++)
546 if(opt_view_visible(i, GMSH_GET, 0))
547 opt_view_light
548 (i, GMSH_SET | GMSH_GUI, !opt_view_light(i, GMSH_GET, 0));
549 status = 2;
550 }
551 else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'w')) {
552 opt_mesh_reverse_all_normals
553 (0, GMSH_SET | GMSH_GUI, !opt_mesh_reverse_all_normals(0, GMSH_GET, 0));
554 status = 2;
555 }
556 else if(Fl::test_shortcut(FL_ALT + 'x') ||
557 Fl::test_shortcut(FL_ALT + FL_SHIFT + 'x')) {
558 status_xyz1p_cb(0, (void *)"x");
559 status = 1;
560 }
561 else if(Fl::test_shortcut(FL_ALT + 'y') ||
562 Fl::test_shortcut(FL_ALT + FL_SHIFT + 'y')) {
563 status_xyz1p_cb(0, (void *)"y");
564 status = 1;
565 }
566 else if(Fl::test_shortcut(FL_ALT + 'z') ||
567 Fl::test_shortcut(FL_ALT + FL_SHIFT + 'z')) {
568 status_xyz1p_cb(0, (void *)"z");
569 status = 1;
570 }
571 else if(Fl::test_shortcut(FL_ALT + 'o') ||
572 Fl::test_shortcut(FL_ALT + FL_SHIFT + 'o')) {
573 status_options_cb(0, (void *)"p");
574 status = 1;
575 }
576 else if(Fl::test_shortcut(FL_ALT + 'a')) {
577 opt_general_axes
578 (0, GMSH_SET | GMSH_GUI, opt_general_axes(0, GMSH_GET, 0) + 1);
579 for(unsigned int i = 0; i < PView::list.size(); i++)
580 if(opt_view_visible(i, GMSH_GET, 0))
581 opt_view_axes(i, GMSH_SET | GMSH_GUI, opt_view_axes(i, GMSH_GET, 0) + 1);
582 status = 2;
583 }
584 else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'a')) {
585 opt_general_small_axes
586 (0, GMSH_SET | GMSH_GUI, !opt_general_small_axes(0, GMSH_GET, 0));
587 status = 2;
588 }
589 else if(Fl::test_shortcut(FL_ALT + 'p')) {
590 opt_geometry_points
591 (0, GMSH_SET | GMSH_GUI, !opt_geometry_points(0, GMSH_GET, 0));
592 status = 2;
593 }
594 else if(Fl::test_shortcut(FL_ALT + 'l')) {
595 opt_geometry_lines
596 (0, GMSH_SET | GMSH_GUI, !opt_geometry_lines(0, GMSH_GET, 0));
597 status = 2;
598 }
599 else if(Fl::test_shortcut(FL_ALT + 's')) {
600 opt_geometry_surfaces
601 (0, GMSH_SET | GMSH_GUI, !opt_geometry_surfaces(0, GMSH_GET, 0));
602 status = 2;
603 }
604 else if(Fl::test_shortcut(FL_ALT + 'v')) {
605 opt_geometry_volumes
606 (0, GMSH_SET | GMSH_GUI, !opt_geometry_volumes(0, GMSH_GET, 0));
607 status = 2;
608 }
609 else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'p')) {
610 opt_mesh_points(0, GMSH_SET | GMSH_GUI, !opt_mesh_points(0, GMSH_GET, 0));
611 status = 2;
612 }
613 else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'l')) {
614 opt_mesh_lines
615 (0, GMSH_SET | GMSH_GUI, !opt_mesh_lines(0, GMSH_GET, 0));
616 status = 2;
617 }
618 else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 's')) {
619 opt_mesh_surfaces_edges
620 (0, GMSH_SET | GMSH_GUI, !opt_mesh_surfaces_edges(0, GMSH_GET, 0));
621 status = 2;
622 }
623 else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'v')) {
624 opt_mesh_volumes_edges
625 (0, GMSH_SET | GMSH_GUI, !opt_mesh_volumes_edges(0, GMSH_GET, 0));
626 status = 2;
627 }
628 else if(Fl::test_shortcut(FL_ALT + 'd')){
629 opt_geometry_surface_type
630 (0, GMSH_SET | GMSH_GUI, opt_geometry_surface_type(0, GMSH_GET, 0) + 1);
631 status = 2;
632 }
633 else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'd')) {
634 opt_mesh_surfaces_faces
635 (0, GMSH_SET | GMSH_GUI, !opt_mesh_surfaces_faces(0, GMSH_GET, 0));
636 status = 2;
637 }
638 else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'b')) {
639 opt_mesh_volumes_faces
640 (0, GMSH_SET | GMSH_GUI, !opt_mesh_volumes_faces(0, GMSH_GET, 0));
641 status = 2;
642 }
643 else if(Fl::test_shortcut(FL_ALT + 'm')) {
644 status_options_cb(0, (void *)"M");
645 status = 2;
646 }
647 else if(Fl::test_shortcut(FL_ALT + 't')) {
648 for(unsigned int i = 0; i < PView::list.size(); i++)
649 if(opt_view_visible(i, GMSH_GET, 0))
650 opt_view_intervals_type
651 (i, GMSH_SET | GMSH_GUI, opt_view_intervals_type(i, GMSH_GET, 0) + 1);
652 status = 2;
653 }
654 else if(Fl::test_shortcut(FL_ALT + 'r')) {
655 for(unsigned int i = 0; i < PView::list.size(); i++)
656 if(opt_view_visible(i, GMSH_GET, 0))
657 opt_view_range_type
658 (i, GMSH_SET | GMSH_GUI, opt_view_range_type(i, GMSH_GET, 0) + 1);
659 status = 2;
660 }
661 else if(Fl::test_shortcut(FL_ALT + 'n')) {
662 for(unsigned int i = 0; i < PView::list.size(); i++)
663 if(opt_view_visible(i, GMSH_GET, 0))
664 opt_view_draw_strings
665 (i, GMSH_SET | GMSH_GUI, !opt_view_draw_strings(i, GMSH_GET, 0));
666 status = 2;
667 }
668 else if(Fl::test_shortcut(FL_ALT + 'e') ||
669 Fl::test_shortcut(FL_ALT + FL_SHIFT + 'e')) {
670 for(unsigned int i = 0; i < PView::list.size(); i++)
671 if(opt_view_visible(i, GMSH_GET, 0))
672 opt_view_show_element
673 (i, GMSH_SET | GMSH_GUI, !opt_view_show_element(i, GMSH_GET, 0));
674 status = 2;
675 }
676 else if(Fl::test_shortcut(FL_ALT + 'h')) {
677 static int show = 0;
678 for(unsigned int i = 0; i < PView::list.size(); i++)
679 opt_view_visible(i, GMSH_SET | GMSH_GUI, show);
680 show = !show;
681 status = 2;
682 }
683 else if(testArrowShortcuts()) {
684 status = 1;
685 }
686
687 if(status == 2){
688 drawContext::global()->draw();
689 return 1;
690 }
691 else if(status == 1)
692 return 1;
693 else
694 return 0;
695 }
696
testArrowShortcuts()697 int FlGui::testArrowShortcuts()
698 {
699 if(Fl::test_shortcut(FL_Left)) {
700 status_play_manual(1, -CTX::instance()->post.animStep);
701 return 1;
702 }
703 else if(Fl::test_shortcut(FL_Right)) {
704 status_play_manual(1, CTX::instance()->post.animStep);
705 return 1;
706 }
707 else if(Fl::test_shortcut(FL_Up)) {
708 status_play_manual(0, -CTX::instance()->post.animStep);
709 return 1;
710 }
711 else if(Fl::test_shortcut(FL_Down)) {
712 status_play_manual(0, CTX::instance()->post.animStep);
713 return 1;
714 }
715 return 0;
716 }
717
setGraphicTitle(std::string title)718 void FlGui::setGraphicTitle(std::string title)
719 {
720 for(unsigned int i = 0; i < graph.size(); i++){
721 if(!i){
722 graph[i]->setTitle(title);
723 }
724 else{
725 std::ostringstream sstream;
726 sstream << title << " [" << i << "]";
727 graph[i]->setTitle(sstream.str());
728 }
729 }
730 }
731
updateViews(bool numberOfViewsHasChanged)732 void FlGui::updateViews(bool numberOfViewsHasChanged)
733 {
734 for(unsigned int i = 0; i < graph.size(); i++)
735 graph[i]->checkAnimButtons();
736 if(numberOfViewsHasChanged){
737 if(menu->module->value() == 3)
738 menu->setContext(menu_post, 0);
739 options->resetBrowser();
740 options->resetExternalViewList();
741 fields->loadFieldViewList();
742 plugins->resetViewBrowser();
743 clipping->resetBrowser();
744 }
745 }
746
updateFields()747 void FlGui::updateFields()
748 {
749 fields->editField(GModel::current()->getFields()->get(fields->selected_id));
750 }
751
resetVisibility()752 void FlGui::resetVisibility()
753 {
754 if(visibility->win->shown())
755 visibility_cb(NULL, NULL);
756 }
757
getCurrentOpenglWindow()758 openglWindow *FlGui::getCurrentOpenglWindow()
759 {
760 if(openglWindow::getLastHandled())
761 return openglWindow::getLastHandled();
762 else
763 return graph[0]->gl[0];
764 }
765
splitCurrentOpenglWindow(char how)766 void FlGui::splitCurrentOpenglWindow(char how)
767 {
768 openglWindow *g = getCurrentOpenglWindow();
769 for(unsigned int i = 0; i < graph.size(); i++){
770 if(graph[i]->tile->find(g) != graph[i]->tile->children()){
771 graph[i]->split(g, how);
772 break;
773 }
774 }
775 }
776
selectEntity(int type)777 char FlGui::selectEntity(int type)
778 {
779 return getCurrentOpenglWindow()->selectEntity
780 (type, selectedVertices, selectedEdges, selectedFaces, selectedRegions,
781 selectedElements);
782 }
783
setStatus(const char * msg,int num)784 void FlGui::setStatus(const char *msg, int num)
785 {
786 if(num == 0 || num == 1){
787 static char buff[2][1024];
788 strncpy(buff[num], msg, sizeof(buff[num]) - 1);
789 buff[num][sizeof(buff[num]) - 1] = '\0';
790 for(unsigned int i = 0; i < graph.size(); i++){
791 graph[i]->label[num]->label(buff[num]);
792 graph[i]->label[num]->redraw();
793 }
794 }
795 else if(num == 2){
796 openglWindow *gl = getCurrentOpenglWindow();
797 int n = strlen(msg);
798 int i = 0;
799 while(i < n) if(msg[i++] == '\n') break;
800 gl->screenMessage[0] = std::string(msg);
801 if(i)
802 gl->screenMessage[0].resize(i - 1);
803 if(i < n)
804 gl->screenMessage[1] = std::string(&msg[i]);
805 else
806 gl->screenMessage[1].clear();
807 drawContext::global()->draw();
808 }
809 }
810
storeCurrentWindowsInfo()811 void FlGui::storeCurrentWindowsInfo()
812 {
813 CTX::instance()->menuPosition[0] = menu->win->x();
814 CTX::instance()->menuPosition[1] = menu->win->y();
815 CTX::instance()->glPosition[0] = graph[0]->win->x();
816 CTX::instance()->glPosition[1] = graph[0]->win->y();
817 CTX::instance()->glSize[0] = graph[0]->win->w();
818 CTX::instance()->glSize[1] = (graph[0]->win->h() - graph[0]->bottom->h());
819 CTX::instance()->msgSize = graph[0]->getMessageHeight();
820 CTX::instance()->optPosition[0] = options->win->x();
821 CTX::instance()->optPosition[1] = options->win->y();
822 CTX::instance()->pluginPosition[0] = plugins->win->x();
823 CTX::instance()->pluginPosition[1] = plugins->win->y();
824 CTX::instance()->pluginSize[0] = plugins->win->w();
825 CTX::instance()->pluginSize[1] = plugins->win->h();
826 CTX::instance()->fieldPosition[0] = fields->win->x();
827 CTX::instance()->fieldPosition[1] = fields->win->y();
828 CTX::instance()->fieldSize[0] = fields->win->w();
829 CTX::instance()->fieldSize[1] = fields->win->h();
830 CTX::instance()->statPosition[0] = stats->win->x();
831 CTX::instance()->statPosition[1] = stats->win->y();
832 CTX::instance()->visPosition[0] = visibility->win->x();
833 CTX::instance()->visPosition[1] = visibility->win->y();
834 CTX::instance()->clipPosition[0] = clipping->win->x();
835 CTX::instance()->clipPosition[1] = clipping->win->y();
836 CTX::instance()->manipPosition[0] = manip->win->x();
837 CTX::instance()->manipPosition[1] = manip->win->y();
838 CTX::instance()->ctxPosition[0] = geoContext->win->x();
839 CTX::instance()->ctxPosition[1] = meshContext->win->y();
840 #if defined(HAVE_ONELAB) && (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3)
841 CTX::instance()->solverPosition[0] = onelab->x();
842 CTX::instance()->solverPosition[1] = onelab->y();
843 CTX::instance()->solverSize[0] = onelab->w();
844 CTX::instance()->solverSize[1] = onelab->h();
845 #endif
846 fileChooserGetPosition(&CTX::instance()->fileChooserPosition[0],
847 &CTX::instance()->fileChooserPosition[1]);
848 }
849
callForSolverPlugin(int dim)850 void FlGui::callForSolverPlugin(int dim)
851 {
852 GMSH_SolverPlugin *sp = PluginManager::instance()->findSolverPlugin();
853 if(sp) sp->popupPropertiesForPhysicalEntity(dim);
854 }
855
856 // Callbacks
857
redraw_cb(Fl_Widget * w,void * data)858 void redraw_cb(Fl_Widget *w, void *data)
859 {
860 drawContext::global()->draw();
861 }
862
window_cb(Fl_Widget * w,void * data)863 void window_cb(Fl_Widget *w, void *data)
864 {
865 static int oldx = 0, oldy = 0, oldw = 0, oldh = 0, zoom = 1;
866 std::string str((const char*)data);
867
868 if(str == "minimize"){
869 for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++)
870 if(FlGui::instance()->graph[i]->win->shown())
871 FlGui::instance()->graph[i]->win->iconize();
872 if(FlGui::instance()->options->win->shown())
873 FlGui::instance()->options->win->iconize();
874 if(FlGui::instance()->plugins->win->shown())
875 FlGui::instance()->plugins->win->iconize();
876 if(FlGui::instance()->fields->win->shown())
877 FlGui::instance()->fields->win->iconize();
878 if(FlGui::instance()->visibility->win->shown())
879 FlGui::instance()->visibility->win->iconize();
880 if(FlGui::instance()->clipping->win->shown())
881 FlGui::instance()->clipping->win->iconize();
882 if(FlGui::instance()->manip->win->shown())
883 FlGui::instance()->manip->win->iconize();
884 if(FlGui::instance()->stats->win->shown())
885 FlGui::instance()->stats->win->iconize();
886 if(FlGui::instance()->menu->win->shown())
887 FlGui::instance()->menu->win->iconize();
888 }
889 else if(str == "zoom"){
890 if(zoom){
891 oldx = FlGui::instance()->graph[0]->win->x();
892 oldy = FlGui::instance()->graph[0]->win->y();
893 oldw = FlGui::instance()->graph[0]->win->w();
894 oldh = FlGui::instance()->graph[0]->win->h();
895 //#define FS
896 #ifndef FS
897 FlGui::instance()->graph[0]->win->resize(Fl::x(), Fl::y(), Fl::w(), Fl::h());
898 FlGui::instance()->graph[0]->hideMessages();
899 FlGui::check();
900 #else
901 FlGui::instance()->graph[0]->win->fullscreen();
902 #endif
903 zoom = 0;
904 }
905 else{
906 #ifndef FS
907 FlGui::instance()->graph[0]->win->resize(oldx, oldy, oldw, oldh);
908 #else
909 FlGui::instance()->graph[0]->win->fullscreen_off();
910 #endif
911 zoom = 1;
912 }
913 FlGui::instance()->menu->win->show();
914 }
915 else if(str == "front"){
916 // the order is important!
917 for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++)
918 FlGui::instance()->graph[i]->win->show();
919 if(FlGui::instance()->options->win->shown())
920 FlGui::instance()->options->win->show();
921 if(FlGui::instance()->plugins->win->shown())
922 FlGui::instance()->plugins->win->show();
923 if(FlGui::instance()->fields->win->shown())
924 FlGui::instance()->fields->win->show();
925 if(FlGui::instance()->geoContext->win->shown())
926 FlGui::instance()->geoContext->win->show();
927 if(FlGui::instance()->meshContext->win->shown())
928 FlGui::instance()->meshContext->win->show();
929 #if defined(HAVE_ONELAB) && (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3)
930 if(FlGui::instance()->onelab->shown())
931 FlGui::instance()->onelab->show();
932 #endif
933 if(FlGui::instance()->visibility->win->shown())
934 FlGui::instance()->visibility->win->show();
935 if(FlGui::instance()->clipping->win->shown())
936 FlGui::instance()->clipping->win->show();
937 if(FlGui::instance()->manip->win->shown())
938 FlGui::instance()->manip->win->show();
939 if(FlGui::instance()->stats->win->shown())
940 FlGui::instance()->stats->win->show();
941 FlGui::instance()->menu->win->show();
942 }
943 }
944
addMessage(const char * msg)945 void FlGui::addMessage(const char *msg)
946 {
947 for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++)
948 FlGui::instance()->graph[i]->addMessage(msg);
949 }
950
showMessages()951 void FlGui::showMessages()
952 {
953 for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++)
954 FlGui::instance()->graph[i]->showMessages();
955 }
956
saveMessages(const char * fileName)957 void FlGui::saveMessages(const char *fileName)
958 {
959 FlGui::instance()->graph[0]->saveMessages(fileName);
960 }
961