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