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 // Contributor(s):
7 //   Stephen Guzik
8 //
9 
10 #include <stdio.h>
11 #include <string.h>
12 #include <FL/Fl_Value_Slider.H>
13 #include <FL/Fl_Menu_Window.H>
14 #include <FL/Fl_Select_Browser.H>
15 #include <FL/Fl_Toggle_Button.H>
16 #include <FL/Fl_Round_Button.H>
17 #include <FL/Fl_Return_Button.H>
18 #include <FL/Fl_Check_Button.H>
19 #include <FL/Fl_Hold_Browser.H>
20 #include <FL/Fl_Input_Choice.H>
21 #include <FL/Fl_Box.H>
22 #include <FL/Fl_Input.H>
23 #include <FL/Fl_Double_Window.H>
24 #include <FL/fl_ask.H>
25 #include <FL/Fl_Preferences.H>
26 #include "FlGui.h"
27 #include "paletteWindow.h"
28 #include "GmshDefines.h"
29 #include "OpenFile.h"
30 #include "CreateFile.h"
31 #include "Options.h"
32 #include "drawContext.h"
33 #include "GModel.h"
34 #include "Context.h"
35 #include "PView.h"
36 
37 // Arrow editor
38 
arrowEditor(const char * title,double & a,double & b,double & c)39 int arrowEditor(const char *title, double &a, double &b, double &c)
40 {
41   struct _editor {
42     Fl_Window *window;
43     Fl_Value_Slider *sa, *sb, *sc;
44     Fl_Button *apply, *cancel;
45   };
46   static _editor *editor = nullptr;
47 
48   if(!editor) {
49     editor = new _editor;
50     editor->window =
51       new paletteWindow(2 * BB + 3 * WB, 4 * BH + 3 * WB,
52                         CTX::instance()->nonModalWindows ? true : false);
53     editor->sa = new Fl_Value_Slider(WB, WB, BB, BH, "Head radius");
54     editor->sa->tooltip("General.ArrowHeadRadius");
55     editor->sa->type(FL_HOR_SLIDER);
56     editor->sa->align(FL_ALIGN_RIGHT);
57     editor->sb = new Fl_Value_Slider(WB, WB + BH, BB, BH, "Stem length");
58     editor->sb->tooltip("General.ArrowStemLength");
59     editor->sb->type(FL_HOR_SLIDER);
60     editor->sb->align(FL_ALIGN_RIGHT);
61     editor->sc = new Fl_Value_Slider(WB, WB + 2 * BH, BB, BH, "Stem radius");
62     editor->sc->tooltip("General.ArrowStemRadius");
63     editor->sc->type(FL_HOR_SLIDER);
64     editor->sc->align(FL_ALIGN_RIGHT);
65     editor->apply = new Fl_Return_Button(WB, 2 * WB + 3 * BH, BB, BH, "Apply");
66     editor->cancel =
67       new Fl_Button(2 * WB + BB, 2 * WB + 3 * BH, BB, BH, "Cancel");
68     editor->window->end();
69     editor->window->hotspot(editor->window);
70   }
71 
72   editor->window->label(title);
73   editor->sa->value(a);
74   editor->sb->value(b);
75   editor->sc->value(c);
76   editor->window->show();
77 
78   while(editor->window->shown()) {
79     Fl::wait();
80     for(;;) {
81       Fl_Widget *o = Fl::readqueue();
82       if(!o) break;
83       if(o == editor->apply) {
84         a = editor->sa->value();
85         b = editor->sb->value();
86         c = editor->sc->value();
87         return 1;
88       }
89       if(o == editor->window || o == editor->cancel) {
90         editor->window->hide();
91         return 0;
92       }
93     }
94   }
95   return 0;
96 }
97 
98 // Connection and pattern choosers
99 
100 class historyBrowser : public Fl_Hold_Browser {
handle(int event)101   int handle(int event)
102   {
103     switch(event) {
104     case FL_SHORTCUT:
105     case FL_KEYBOARD:
106       if(Fl::test_shortcut(FL_Delete) || Fl::test_shortcut(FL_BackSpace)) {
107         int i = value();
108         if(i) {
109           remove(i);
110           if(i <= size())
111             select(i);
112           else if(i > 1)
113             select(i - 1);
114         }
115         return 1;
116       }
117       break;
118     }
119     return Fl_Hold_Browser::handle(event);
120   };
121 
122 public:
historyBrowser(int x,int y,int w,int h,const char * l=nullptr)123   historyBrowser(int x, int y, int w, int h, const char *l = nullptr)
124     : Fl_Hold_Browser(x, y, w, h, l)
125   {
126   }
127 };
128 
129 class historyChooser {
130 private:
131   std::string _prefix, _label, _commandLabel, _defaultCommand, _okLabel;
132 
133 public:
134   Fl_Double_Window *window;
135   Fl_Input *input;
136   historyBrowser *browser;
137   Fl_Return_Button *ok;
138   Fl_Button *cancel;
139 
140 public:
historyChooser(const std::string & prefix,const std::string & label,const std::string & commandLabel,const std::string & defaultCommand,const std::string & okLabel)141   historyChooser(const std::string &prefix, const std::string &label,
142                  const std::string &commandLabel,
143                  const std::string &defaultCommand, const std::string &okLabel)
144     : _prefix(prefix), _label(label), _commandLabel(commandLabel),
145       _defaultCommand(defaultCommand), _okLabel(okLabel)
146   {
147     int h = 4 * WB + 10 * BH, w = 3 * BB + 2 * WB;
148     window = new Fl_Double_Window(w, h);
149     window->set_modal();
150     window->label(_label.c_str());
151     Fl_Box *b1 = new Fl_Box(WB, WB, w, BH, _commandLabel.c_str());
152     b1->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT);
153     input = new Fl_Input(WB, WB + BH, w - 2 * WB, BH);
154     Fl_Box *b2 = new Fl_Box(WB, 2 * WB + 2 * BH, w, BH, "History:");
155     b2->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT);
156     browser =
157       new historyBrowser(WB, 2 * WB + 3 * BH, w - 2 * WB, h - 4 * BH - 4 * WB);
158     cancel = new Fl_Button(w - WB - BB, h - WB - BH, BB, BH, "Cancel");
159     ok = new Fl_Return_Button(w - 2 * WB - 2 * BB, h - WB - BH, BB, BH,
160                               _okLabel.c_str());
161     Fl_Box *b3 = new Fl_Box(WB, h - WB - BB, WB, WB);
162     b3->hide();
163     window->resizable(b3);
164   }
save(Fl_Preferences & prefs)165   void save(Fl_Preferences &prefs)
166   {
167     for(int i = 0; i < 100; i++) {
168       char name[256];
169       sprintf(name, "%s%02d", _prefix.c_str(), i);
170       if(i < browser->size())
171         prefs.set(name, browser->text(i + 1));
172       else if(prefs.entryExists(name))
173         prefs.deleteEntry(name);
174     }
175     prefs.set((_prefix + "PositionX").c_str(), window->x());
176     prefs.set((_prefix + "PositionY").c_str(), window->y());
177     prefs.set((_prefix + "Width").c_str(), window->w());
178     prefs.set((_prefix + "Height").c_str(), window->h());
179   }
run()180   std::string run()
181   {
182     Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "gmsh");
183     int x = 100, y = 100, h = 4 * WB + 10 * BH, w = 3 * BB + 2 * WB;
184     prefs.get((_prefix + "PositionX").c_str(), x, x);
185     prefs.get((_prefix + "PositionY").c_str(), y, y);
186     prefs.get((_prefix + "Width").c_str(), w, w);
187     prefs.get((_prefix + "Height").c_str(), h, h);
188     window->resize(x, y, w, h);
189     int old = browser->value();
190     browser->clear();
191     for(int i = 0; i < 100; i++) {
192       char name[256], value[1024];
193       sprintf(name, "%s%02d", _prefix.c_str(), i);
194       if(prefs.entryExists(name)) {
195         prefs.get(name, value, "", sizeof(value));
196         browser->add(value);
197       }
198     }
199     int n = browser->size();
200     if(n) {
201       if(old > 0 && old <= n)
202         input->value(browser->text(old));
203       else
204         input->value(browser->text(1));
205     }
206     else
207       input->value(_defaultCommand.c_str());
208     window->show();
209     while(window->shown()) {
210       Fl::wait();
211       for(;;) {
212         Fl_Widget *o = Fl::readqueue();
213         if(!o) break;
214         if(o == ok) {
215           if(strlen(input->value())) {
216             // insert choosen value at the top of the history
217             for(int i = 0; i < browser->size(); i++) {
218               if(!strcmp(input->value(), browser->text(i + 1))) {
219                 browser->remove(i + 1);
220                 break;
221               }
222             }
223             browser->insert(1, input->value());
224           }
225           save(prefs);
226           window->hide();
227           return input->value();
228         }
229         if(o == window || o == cancel) {
230           save(prefs);
231           window->hide();
232           return "";
233         }
234       }
235     }
236     return "";
237   }
238 };
239 
240 static historyChooser *_connectionChooser = nullptr;
connection_select_cb(Fl_Widget * w,void * data)241 static void connection_select_cb(Fl_Widget *w, void *data)
242 {
243   int i = _connectionChooser->browser->value();
244   if(i) _connectionChooser->input->value(_connectionChooser->browser->text(i));
245 }
246 
connectionChooser()247 std::string connectionChooser()
248 {
249   if(!_connectionChooser) {
250     _connectionChooser =
251       new historyChooser("connection", "Remote Start",
252                          "Command:", "./gmsh ../tutorial/view3.pos", "Run");
253     _connectionChooser->browser->callback(connection_select_cb);
254   }
255   return _connectionChooser->run();
256 }
257 
258 static historyChooser *_patternChooser = nullptr;
pattern_select_cb(Fl_Widget * w,void * data)259 static void pattern_select_cb(Fl_Widget *w, void *data)
260 {
261   int i = _patternChooser->browser->value();
262   if(i) _patternChooser->input->value(_patternChooser->browser->text(i));
263 }
264 
patternChooser()265 std::string patternChooser()
266 {
267   if(!_patternChooser) {
268     _patternChooser = new historyChooser("pattern", "Watch Pattern",
269                                          "Pattern:", "output/*.msh", "Watch");
270     _patternChooser->browser->callback(pattern_select_cb);
271   }
272   return _patternChooser->run();
273 }
274 
275 class cgnsImportDialog {
276 private:
277   std::string _prefix, _label, _commandLabel, _defaultCommand, _okLabel;
278 
279 public:
280   Fl_Double_Window *window;
281   Fl_Return_Button *ok;
282   Fl_Input_Choice *input_choice;
283 
284 public:
cgnsImportDialog()285   cgnsImportDialog()
286   {
287     _prefix = "cgns";
288     int h = 3 * WB + 2 * BH, w = 3 * BB + 2 * WB;
289     window = new Fl_Double_Window(w, h);
290     window->set_modal();
291     window->label("CGNS import");
292 
293     input_choice =
294       new Fl_Input_Choice(WB + 2 * BB, WB, 1 * BB, BH, "Import mesh as order");
295 
296     ok = new Fl_Return_Button(w - WB - BB, h - WB - BH, BB, BH, "Import");
297   }
298 
save(Fl_Preferences & prefs)299   void save(Fl_Preferences &prefs)
300   {
301     prefs.set((_prefix + "PositionX").c_str(), window->x());
302     prefs.set((_prefix + "PositionY").c_str(), window->y());
303     prefs.set((_prefix + "Width").c_str(), window->w());
304     prefs.set((_prefix + "Height").c_str(), window->h());
305   }
run()306   int run()
307   {
308     Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "gmsh");
309     int x = 100, y = 100, h = 3 * WB + 2 * BH, w = 3 * BB + 2 * WB;
310     prefs.get((_prefix + "PositionX").c_str(), x, x);
311     prefs.get((_prefix + "PositionY").c_str(), y, y);
312     prefs.get((_prefix + "Width").c_str(), w, w);
313     prefs.get((_prefix + "Height").c_str(), h, h);
314     window->resize(x, y, w, h);
315 
316     int order_max = CTX::instance()->mesh.cgnsImportOrder;
317     int order = 1;
318     input_choice->clear();
319     char text[128];
320     while(order < 5 && order <= order_max && order_max < 10 && order_max > 0) {
321       sprintf(text, "%d", order);
322       input_choice->add(text);
323       order *= 2;
324     }
325     input_choice->value(0);
326 
327     window->show();
328     while(window->shown()) {
329       Fl::wait();
330       for(;;) {
331         Fl_Widget *o = Fl::readqueue();
332         if(!o) break;
333         if(o == ok) {
334           const char *str = input_choice->value();
335           int order = 1;
336           if(strcmp("2", str) == 0)
337             order = 2;
338           else if(strcmp("4", str) == 0)
339             order = 4;
340           // else if (strcmp("8", str) == 0)
341           //  order = 8;
342           save(prefs);
343           window->hide();
344           return order;
345         }
346         if(o == window) {
347           save(prefs);
348           window->hide();
349           return 1;
350         }
351       }
352     }
353     return 1;
354   }
355 };
356 
357 static cgnsImportDialog *_cgnsImport = nullptr;
358 /*static void pattern_select_cb(Fl_Widget* w, void *data)
359 {
360   _cgnsImport->input_choice->value("1");
361 }
362 */
cgnsImport()363 int cgnsImport()
364 {
365   if(!_cgnsImport) { _cgnsImport = new cgnsImportDialog(); }
366   return _cgnsImport->run();
367 }
368