ManageDBDialog: added Close button
[aoi.git] / src / gui_dialogs.hxx
blobabc8b0711152340c8850075ffd7643129c291f16
1 /*
2 Copyright 2013 Karel Matas
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef _GUI_DIALOGS_HXX
18 #define _GUI_DIALOGS_HXX
20 #include <cmath>
21 #include <curl/curl.h>
22 #include <FL/Fl_Double_Window.H>
23 #include <FL/Fl_Text_Display.H>
24 #include <FL/Fl_Text_Buffer.H>
25 #include <FL/Fl_Menu_Window.H>
26 #include <FL/Fl_Menu_Button.H>
27 #include <FL/Fl_Progress.H>
28 #include <FL/Fl_Choice.H>
29 #include <FL/Fl_Box.H>
30 #include <FL/Fl_Button.H>
31 #include <FL/Fl_Hold_Browser.H>
32 #include <FL/Fl.H>
33 #include <FL/fl_ask.H>
35 #include "logger.hxx"
36 #include "gui_widgets.hxx"
37 #include "datatypes.hxx"
38 #include "config.hxx"
39 #include "romanization.hxx"
42 using aoi_config::Config;
43 using aoi::Kanji;
45 namespace aoi_ui {
47 class DialogFontTest : public Fl_Double_Window
49 private:
50 Fl_Hold_Browser *browser_ = nullptr;
51 Fl_Box *l_fonts_ = nullptr;
52 Fl_Box *l_ascii_ = nullptr;
53 Fl_Box *l_jis208_ = nullptr;
54 Fl_Box *l_jis212_ = nullptr;
55 Fl_Box *l_jis213_ = nullptr;
56 Fl_Box *l_kana_ = nullptr;
57 Fl_Box *b_ascii_ = nullptr;
58 Fl_Box *b_jis208_ = nullptr;
59 Fl_Box *b_jis212_ = nullptr;
60 Fl_Box *b_jis213_ = nullptr;
61 Fl_Box *b_kana_ = nullptr;
62 Fl_Button *bt_ok_ = nullptr;
63 Fl_Button *bt_cancel_ = nullptr;
64 Fl_Input *input_ = nullptr;
65 string s_fonts_;
66 Fl_Font selected_font_ = -1;
68 public:
69 DialogFontTest( int w=600, int h=400 ) : Fl_Double_Window(w,h)
71 browser_ = new Fl_Hold_Browser( 5, 5, 230, 365 );
72 browser_->callback(static_callback, (void*)this);
73 l_fonts_ = new Fl_Box( 5, 370, 250, 30 );
74 l_fonts_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
76 l_ascii_ = new Fl_Box( 240, 5, 110, 40, "ASCII" );
77 l_ascii_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
78 l_ascii_->labelfont(FL_BOLD);
79 b_ascii_ = new Fl_Box( 355, 5, 240, 40, "Hello world" );
80 b_ascii_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
81 b_ascii_->labelsize(36);
83 l_kana_ = new Fl_Box( 240, 50, 110, 40, "Kana" );
84 l_kana_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
85 l_kana_->labelfont(FL_BOLD);
86 b_kana_ = new Fl_Box( 355, 50, 240, 40, "ひらーカタ." );
87 b_kana_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
88 b_kana_->labelsize(36);
90 l_jis208_ = new Fl_Box( 240, 95, 110, 40, "JIS X 208" );
91 l_jis208_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
92 l_jis208_->labelfont(FL_BOLD);
93 b_jis208_ = new Fl_Box( 355, 95, 240, 40, "龠堯槇遙凜熙");
94 b_jis208_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
95 b_jis208_->labelsize(36);
97 l_jis212_ = new Fl_Box( 240, 140, 110, 40, "JIS X 212" );
98 l_jis212_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
99 l_jis212_->labelfont(FL_BOLD);
100 b_jis212_ = new Fl_Box( 355, 140, 240, 40, "龑龒龔龖龗龞");
101 b_jis212_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
102 b_jis212_->labelsize(36);
105 l_jis213_ = new Fl_Box( 240, 185, 110, 40, "JIS X 213" );
106 l_jis213_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
107 l_jis213_->labelfont(FL_BOLD);
108 b_jis213_ = new Fl_Box( 355, 185, 240, 40, "臭艹艹著贈辶");
109 b_jis213_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
110 b_jis213_->labelsize(36);
112 input_ = new Fl_Input( 240, 270, 350, 40, "Custom text" );
113 input_->align( FL_ALIGN_TOP_LEFT );
114 input_->labelfont( FL_HELVETICA|FL_BOLD );
116 bt_ok_ = new Fl_Button( w-70, h-35, 65, 30, "OK");
117 bt_ok_->callback( static_ok, (void*)this );
118 bt_cancel_ = new Fl_Button( w-140, h-35, 65, 30, "Cancel");
119 bt_cancel_->callback( static_cancel, (void*)this );
121 #ifdef WINDOWS
122 Fl_Font n_fonts = Fl::set_fonts("*");
123 #else
124 Fl_Font n_fonts = Fl::set_fonts("-*-*-*-*-*-*-*-*-*-*-*-*-iso10646-1");
125 #endif
127 s_fonts_ = std::to_string(n_fonts) + string(" fonts found");
128 l_fonts_->label(s_fonts_.c_str());
130 for ( int i=0; i<n_fonts; ++i ){
131 const char *name = Fl::get_font_name(i);
132 browser_->add( name, (void*)i );
135 // hide some fonts
136 browser_->hide( FL_SYMBOL+1 ); // protected for Help_View
137 // browser_->hide( FONT_KANJI+1 ); // reserved for program
139 label("Fonts");
140 hide();
143 void cb ( Fl_Font f ){
144 b_ascii_->labelfont(f);
145 b_kana_->labelfont(f);
146 b_jis208_->labelfont(f);
147 b_jis212_->labelfont(f);
148 b_jis213_->labelfont(f);
149 input_->textfont(f);
150 redraw();
153 void cb_ok () {
154 selected_font_ = browser_->value()-1;
155 hide();
158 void cb_cancel () {
159 selected_font_ = -1;
160 hide();
163 int run (){
164 show();
165 while ( visible() ){
166 usleep(1000);
167 Fl::check();
169 return selected_font();
172 inline Fl_Font selected_font() const { return selected_font_; };
173 inline static void static_callback ( Fl_Widget *w, void *p )
174 { ((DialogFontTest*)p)->cb( ((Fl_Hold_Browser*)w)->value()-1 ); };
175 inline static void static_ok ( Fl_Widget *w, void *p )
176 { ((DialogFontTest*)p)->cb_ok(); }
177 inline static void static_cancel ( Fl_Widget *w, void *p )
178 { ((DialogFontTest*)p)->cb_cancel(); };
183 class DialogDownload : public Fl_Double_Window
185 private:
186 Fl_Progress *progress_ = nullptr;
187 Fl_Button *b_abort_ = nullptr;
188 Fl_Button *b_url_ = nullptr;
189 Fl_Button *b_fname_ = nullptr;
190 Fl_Button *b_dload_ = nullptr;
191 Fl_Box *l_url_ = nullptr;
192 Fl_Box *l_fname_ = nullptr;
193 string url_ = "";
194 string fname_ = "";
195 static bool abort_download_;
196 bool downloading_ = false;
198 public:
199 DialogDownload( int w=400, int h=125 );
200 ~DialogDownload();
202 static size_t mycurl_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
204 size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
205 return written;
207 static size_t mycurl_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
208 { return fread(ptr, size, nmemb, stream); }
210 static int mycurl_progress_func(void *progress_widget,
211 double dltotal, double dlnow,
212 double ultotal, double ulnow )
214 float perc = 100.*dlnow/dltotal;
215 char buff[128];
216 sprintf(buff, "%.1f%% of %.1f MB", perc, dltotal/1024/1024);
217 ((Fl_Progress*)progress_widget)->label( buff );
218 ((Fl_Progress*)progress_widget)->value(perc);
219 Fl::check();
220 // non-zero cancels download
221 return abort_download_;
224 void run (){
225 show();
226 while ( visible() ){
227 usleep(1000);
228 Fl::check();
232 void download_url( const char *url, const char *fname );
233 void set_names ( const string &url, const string &fname="" );
234 void abort ();
235 void cb_download ();
236 void cb_url_callback ();
237 void cb_fname_callback ();
239 inline static void scb_url_callback ( Fl_Widget *w, void *p ){
240 ((DialogDownload*)p)->cb_url_callback(); }
241 inline static void scb_fname_callback ( Fl_Widget *w, void *p ){
242 ((DialogDownload*)p)->cb_fname_callback(); }
243 inline static void scb_abort ( Fl_Widget *w, void *p ){
244 ((DialogDownload*)p)->abort(); }
245 inline static void scb_download ( Fl_Widget *w, void *p ){
246 ((DialogDownload*)p)->cb_download(); }
247 inline static void scb_close_window ( Fl_Widget *w, void *f ){
248 // dont close main window on ESC
249 if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape )
250 return;
251 // dont close when download in progress
252 if ( ((DialogDownload*)f)->downloading_ ) {
253 fl_message("You must abort download before closing window." );
254 return;
256 ((DialogDownload*)w)->hide();
261 class EditWordDialog : public Fl_Double_Window
263 private:
265 public:
266 EditWordDialog ( int x, int y, int w, int h, const char *l="Edit word" );
267 ~EditWordDialog(){};
271 class ManageDBDialog : public Fl_Double_Window
273 public:
274 class Item : public Fl_Group
276 private:
277 Fl_Box *l_name_ = nullptr;
278 Fl_Box *l_ver_ = nullptr;
279 Fl_Menu_Button *menu_ = nullptr;
280 Fl_Box *l_desc_ = nullptr;
281 string title_;
282 string version_;
283 string description_;
284 public:
285 Item ( int x, int y, int w, int h, const char *l=0 );
286 ~Item(){};
287 void set ( const string &title, const string &version,
288 const string &description, Fl_Color col,
289 Fl_Callback *f_file, Fl_Callback *f_download, void *cb_data );
290 inline string title () const { return title_; }
291 inline void version ( string s, Fl_Color c )
292 { version_ = s; l_ver_->label(version_.c_str()); l_ver_->labelcolor(c); }
294 private:
295 int last_y_ = 0;
296 Fl_Button *b_close_ = nullptr;
298 public:
299 ManageDBDialog ( int w=300, int h=200, const char *l="Manage Database" );
300 ~ManageDBDialog(){};
302 void add_item ( const string &name, const string &version,
303 const string &description, Fl_Color col=FL_BLACK,
304 Fl_Callback *f_file=nullptr, Fl_Callback *f_download=nullptr,
305 void *cb_data=nullptr );
306 inline Item *item ( const string &name )
308 for ( int i=0; i<children(); i++ ){
309 Item *pi = dynamic_cast<Item*>(child(i));
310 if ( pi && pi->title() == name )
311 return pi;
313 return nullptr;
315 inline static void scb_close ( Fl_Widget *w, void *p )
316 { ((ManageDBDialog*)p)->hide(); };
320 class KanjiPopupWindow : public Fl_Menu_Window
322 private:
323 KanjiInfo *box_;
325 public:
326 KanjiPopupWindow ( int w, int h );
327 ~KanjiPopupWindow (){};
329 inline void font_a ( Fl_Font f, int s ) { box_->font_a( f, s ); }
330 inline void font_b ( Fl_Font f, int s ) { box_->font_b( f, s ); }
331 inline void set ( const Kanji &k ) { box_->set_data(k); }
333 int handle ( int event );
335 inline void popup() {
336 // XXX: after clear_border() take_focus() does not work
337 // clear_border();
338 // position at cursor
339 position(Fl::event_x_root(), Fl::event_y_root());
340 size( box_->w(), box_->h());
341 show();
342 take_focus();
347 class DialogTextDisplay : public Fl_Double_Window
349 private:
350 Fl_Text_Buffer *buffer_ = nullptr;
351 Fl_Text_Display *display_ = nullptr;
352 Fl_Button *b_close_ = nullptr;
353 Fl_Button *b_copy_ = nullptr;
354 public:
355 DialogTextDisplay( int w=300, int h=200 ) : Fl_Double_Window(w,h){
356 printf("DialogTextDisplay\n");
357 b_close_ = new Fl_Button( w-75, h-30, 70, 30, "Close" );
358 b_copy_ = new Fl_Button( 5, h-30, 70, 30, "Copy");
359 display_ = new Fl_Text_Display( 5, 5, w-10, h-35 );
360 buffer_ = new Fl_Text_Buffer();
361 b_close_->callback( scb_close, (void*)this );
362 b_copy_->callback( scb_copy, (void*)this);
363 display_->buffer( buffer_ );
364 set_modal();
365 end();
367 void set_text ( const string &s, Fl_Font f=FL_HELVETICA ){
368 display_->textfont(f);
369 buffer_->text(s.c_str());
371 void cb_close (){
372 hide();
374 inline static void scb_close ( Fl_Widget *w, void *p ){
375 ((DialogTextDisplay*)p)->cb_close(); };
376 inline static void scb_copy ( Fl_Widget *w, void *p ) {
377 const char *d = ((DialogTextDisplay*)p)->buffer_->text();
378 int len = strlen(d);
379 Fl::copy( d, len, 0);
380 Fl::copy( d, len, 1);
385 // XXX
386 class DialogAlert : public Fl_Double_Window
388 private:
389 string message_ = "";
390 string description_ = "";
391 // IMAGE?
392 Fl_Button *b_ok_ = nullptr;
393 Fl_Button *b_desc_ = nullptr; // popup description
394 Fl_Font font_desc_ = FONT_KANJI;
395 Fl_Box *box_ = nullptr;
397 public:
398 DialogAlert( int w=300, int h=200) : Fl_Double_Window(w,h){
399 int bw = 70; // button width
400 int bh = 25; // button height
401 box_ = new Fl_Box( 5, 5, w-10, h-bh-15);
402 b_ok_ = new Fl_Button( w-5-bw, h-5-bh, bw, bh, "OK" );
403 b_ok_->callback( scb_close, (void*)this );
404 b_desc_ = new Fl_Button( 5, h-5-bh, 100, bh, "Description");
405 b_desc_->callback( scb_show_description, (void*)this );
406 b_desc_->deactivate();
407 label("Alert");
408 set_modal();
410 ~DialogAlert(){};
412 void set_text ( const string &msg, const string &desc ){
413 if ( desc.empty() )
414 b_desc_->deactivate();
415 else
416 b_desc_->activate();
417 message_ = msg;
418 box_->label(message_.c_str());
419 description_ = desc;
422 void cb_close (){
423 hide();
426 void cb_show_description (){
427 DialogTextDisplay d;
428 d.position(100,100);
429 d.set_text(description_.c_str(), font_desc_ );
430 d.show();
433 inline static void scb_show_description ( Fl_Widget *w, void *p ){
434 ((DialogAlert*)p)->cb_show_description(); }
436 inline static void scb_close ( Fl_Widget *w, void *p ){
437 ((DialogAlert*)p)->cb_close(); };
441 class DialogProgress : public Fl_Double_Window
443 private:
444 string message_ = "";
445 Fl_Progress *progress_ = nullptr;
447 public:
448 DialogProgress( int w, int h ):Fl_Double_Window(w,h){
449 box( FL_BORDER_BOX );
450 progress_ = new Fl_Progress( 10, 10, w-20, 30 );
451 progress_->minimum(0);
452 progress_->maximum(1);
453 set_modal();
454 clear_border();
455 end();
457 ~DialogProgress(){}
459 void init () { message_ = ""; }
461 void progress ( float percent, const string &message="" ){
462 message_ = message;
463 progress_->label(message_.c_str());
464 progress_->value( percent/100. );
465 Fl::check();
470 class DialogSettings : public Fl_Double_Window
472 private:
473 Fl_Hold_Browser *browser_ = nullptr;
474 Fl_Button *b_ok_ = nullptr;
475 Fl_Button *b_defaults_ = nullptr;
476 std::map<string,Config::Value> data_;
477 std::map<string,Config::Value> defaults_;
479 public:
480 DialogSettings( int w=400, int h=500 );
481 ~DialogSettings(){};
482 int handle ( int event );
483 std::map<string,Config::Value> run ();
484 void set ( const std::map<string,Config::Value> &m, const std::map<string,Config::Value> &defaults={} );
485 inline void restore_defaults () {
486 data_ = defaults_;
487 hide();
489 void cb ( int line );
490 inline static void static_callback ( Fl_Widget *w, void *p )
491 { ((DialogSettings*)p)->cb( ((Fl_Hold_Browser*)w)->value()); };
492 inline static void static_ok ( Fl_Widget *w, void *p )
493 { ((DialogSettings*)p)->hide(); }
494 inline static void scb_restore_defaults ( Fl_Widget *w, void *p )
495 { ((DialogSettings*)p)->restore_defaults(); };
498 } // namespace aoi_ui
499 #endif // _GUI_DIALOGS_HXX