Merge branch 'devel'
[aoi.git] / src / gui_dialogs.hxx
blob9bb507d43a30d243ff9ded40f67a1eedb3d73475
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 /*! \file gui_dialogs.hxx
21 * Custom dialogs.
24 #include <cmath>
25 #include <curl/curl.h>
26 #include <FL/Fl_Double_Window.H>
27 #include <FL/Fl_Text_Display.H>
28 #include <FL/Fl_Text_Buffer.H>
29 #include <FL/Fl_Menu_Window.H>
30 #include <FL/Fl_Menu_Button.H>
31 #include <FL/Fl_Progress.H>
32 #include <FL/Fl_Choice.H>
33 #include <FL/Fl_Box.H>
34 #include <FL/Fl_Button.H>
35 #include <FL/Fl_Hold_Browser.H>
36 #include <FL/Fl.H>
37 #include <FL/fl_ask.H>
38 #include <FL/Fl_Help_View.H>
40 #include "logger.hxx"
41 #include "gui_widgets.hxx"
42 #include "datatypes.hxx"
43 #include "config.hxx"
44 #include "romanization.hxx"
47 using aoi_config::Config;
48 using aoi::Kanji;
50 namespace aoi_ui {
52 /*!
53 * Dialog for testing and setting fonts. Shows list of all available fonts,
54 * labels with testing chracters ( ASCII, KANA, JISX208/212/213 ) and input
55 * field for custom text.
57 class DialogFontTest : public Fl_Double_Window
59 private:
60 Fl_Hold_Browser *browser_ = nullptr;
61 Fl_Box *l_fonts_ = nullptr;
62 Fl_Box *l_ascii_ = nullptr;
63 Fl_Box *l_jis208_ = nullptr;
64 Fl_Box *l_jis212_ = nullptr;
65 Fl_Box *l_jis213_ = nullptr;
66 Fl_Box *l_kana_ = nullptr;
67 Fl_Box *b_ascii_ = nullptr;
68 Fl_Box *b_jis208_ = nullptr;
69 Fl_Box *b_jis212_ = nullptr;
70 Fl_Box *b_jis213_ = nullptr;
71 Fl_Box *b_kana_ = nullptr;
72 Fl_Button *bt_ok_ = nullptr;
73 Fl_Button *bt_cancel_ = nullptr;
74 Fl_Input *input_ = nullptr;
75 string s_fonts_;
76 Fl_Font selected_font_ = -1;
78 public:
79 DialogFontTest( int w=600, int h=400 ) : Fl_Double_Window(w,h)
81 browser_ = new Fl_Hold_Browser( 5, 5, 230, 365 );
82 browser_->callback(static_callback, (void*)this);
83 l_fonts_ = new Fl_Box( 5, 370, 250, 30 );
84 l_fonts_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
86 l_ascii_ = new Fl_Box( 240, 5, 110, 40, "ASCII" );
87 l_ascii_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
88 l_ascii_->labelfont(FL_BOLD);
89 b_ascii_ = new Fl_Box( 355, 5, 240, 40, "Hello world" );
90 b_ascii_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
91 b_ascii_->labelsize(36);
93 l_kana_ = new Fl_Box( 240, 50, 110, 40, "Kana" );
94 l_kana_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
95 l_kana_->labelfont(FL_BOLD);
96 b_kana_ = new Fl_Box( 355, 50, 240, 40, "ひらーカタ." );
97 b_kana_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
98 b_kana_->labelsize(36);
100 l_jis208_ = new Fl_Box( 240, 95, 110, 40, "JIS X 208" );
101 l_jis208_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
102 l_jis208_->labelfont(FL_BOLD);
103 b_jis208_ = new Fl_Box( 355, 95, 240, 40, "龠堯槇遙凜熙");
104 b_jis208_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
105 b_jis208_->labelsize(36);
107 l_jis212_ = new Fl_Box( 240, 140, 110, 40, "JIS X 212" );
108 l_jis212_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
109 l_jis212_->labelfont(FL_BOLD);
110 b_jis212_ = new Fl_Box( 355, 140, 240, 40, "龑龒龔龖龗龞");
111 b_jis212_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
112 b_jis212_->labelsize(36);
115 l_jis213_ = new Fl_Box( 240, 185, 110, 40, "JIS X 213" );
116 l_jis213_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
117 l_jis213_->labelfont(FL_BOLD);
118 b_jis213_ = new Fl_Box( 355, 185, 240, 40, "臭艹艹著贈辶");
119 b_jis213_->align( FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
120 b_jis213_->labelsize(36);
122 input_ = new Fl_Input( 240, 270, 350, 40, "Custom text" );
123 input_->align( FL_ALIGN_TOP_LEFT );
124 input_->labelfont( FL_HELVETICA|FL_BOLD );
126 bt_ok_ = new Fl_Button( w-70, h-35, 65, 30, "OK");
127 bt_ok_->callback( static_ok, (void*)this );
128 bt_cancel_ = new Fl_Button( w-140, h-35, 65, 30, "Cancel");
129 bt_cancel_->callback( static_cancel, (void*)this );
131 #ifdef WINDOWS
132 Fl_Font n_fonts = Fl::set_fonts("*");
133 #else
134 Fl_Font n_fonts = Fl::set_fonts("-*-*-*-*-*-*-*-*-*-*-*-*-iso10646-1");
135 #endif
137 s_fonts_ = std::to_string(n_fonts) + string(" fonts found");
138 l_fonts_->label(s_fonts_.c_str());
140 for ( int i=0; i<n_fonts; ++i ){
141 const char *name = Fl::get_font_name(i);
142 browser_->add( name, (void*)i );
145 // hide some fonts
146 browser_->hide( FL_SYMBOL+1 ); // protected for Help_View
147 // browser_->hide( FONT_KANJI+1 ); // reserved for program
149 label("Fonts");
150 hide();
153 //! Callback called when selecting font
154 void cb ( Fl_Font f ){
155 b_ascii_->labelfont(f);
156 b_kana_->labelfont(f);
157 b_jis208_->labelfont(f);
158 b_jis212_->labelfont(f);
159 b_jis213_->labelfont(f);
160 input_->textfont(f);
161 redraw();
164 //! Callback called on 'OK' button
165 void cb_ok () {
166 selected_font_ = browser_->value()-1;
167 hide();
170 //! Callback called on 'Cancel' button
171 void cb_cancel () {
172 selected_font_ = -1;
173 hide();
176 /*!
177 * Runs dialog and waits for interrupt ( OK button, Cancel button,
178 ESC, Close window )
179 * \return selected font on OK button, -1 otherwise.
181 int run (){
182 show();
183 while ( visible() ){
184 usleep(1000);
185 Fl::check();
187 return selected_font();
190 //! Returns selected font
191 inline Fl_Font selected_font() const { return selected_font_; };
192 //! Calls cb()
193 inline static void static_callback ( Fl_Widget *w, void *p )
194 { ((DialogFontTest*)p)->cb( ((Fl_Hold_Browser*)w)->value()-1 ); };
195 //! Calls cb_ok()
196 inline static void static_ok ( Fl_Widget *w, void *p )
197 { ((DialogFontTest*)p)->cb_ok(); }
198 //! Calls cb_cancel()
199 inline static void static_cancel ( Fl_Widget *w, void *p )
200 { ((DialogFontTest*)p)->cb_cancel(); };
206 * Download dialog that shows the progress of download and allows the change
207 * ot the url and output filename.
209 class DialogDownload : public Fl_Double_Window
211 private:
212 Fl_Progress *progress_ = nullptr;
213 Fl_Button *b_abort_ = nullptr;
214 Fl_Button *b_url_ = nullptr;
215 Fl_Button *b_fname_ = nullptr;
216 Fl_Button *b_dload_ = nullptr;
217 Fl_Box *l_url_ = nullptr;
218 Fl_Box *l_fname_ = nullptr;
219 string url_ = "";
220 string fname_ = "";
221 static bool abort_download_; //!< See mycurl_progress_func()
222 bool downloading_ = false; //!< See abort() and scb_close_window()
224 public:
225 DialogDownload( int w=400, int h=125 );
226 ~DialogDownload();
228 //! Needed by curl
229 static size_t mycurl_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
230 { return fwrite(ptr, size, nmemb, (FILE *)stream); }
231 //! Needed by curl
232 static size_t mycurl_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
233 { return fread(ptr, size, nmemb, stream); }
235 /*!
236 * Needed by curl. Sets progress and calls Fl::check().
237 * Aborts download if abort_download_=true.
239 static int mycurl_progress_func(void *progress_widget,
240 double dltotal, double dlnow,
241 double ultotal, double ulnow )
243 float perc = 100.*dlnow/dltotal;
244 char buff[128];
245 sprintf(buff, "%.1f%% of %.1f MB", perc, dltotal/1024/1024);
246 ((Fl_Progress*)progress_widget)->label( buff );
247 ((Fl_Progress*)progress_widget)->value(perc);
248 Fl::check();
249 // non-zero cancels download
250 return abort_download_;
253 //! Runs dialog and waits for interrupt.
254 void run (){
255 show();
256 while ( visible() ){
257 usleep(1000);
258 Fl::check();
263 * Starts a CURL download.
264 * \param url URL to be downloaded
265 * \param fname name od the output file
267 void download_url( const char *url, const char *fname="downloaded.file" );
268 //! Sets URL and output file name. Tries to guess fname from url if fname is empty.
269 void set_names ( const string &url, const string &fname="" );
270 //! Aborts download. Asks for confirmation if downloading_=true.
271 void abort ();
272 //! Starts download.
273 void cb_download ();
274 //! Allows change of the URL.
275 void cb_url_callback ();
276 //! Allos change of the output filename.
277 void cb_fname_callback ();
279 //! See cb_url_callback()
280 inline static void scb_url_callback ( Fl_Widget *w, void *p ){
281 ((DialogDownload*)p)->cb_url_callback(); }
282 //! See cb_fname_callback()
283 inline static void scb_fname_callback ( Fl_Widget *w, void *p ){
284 ((DialogDownload*)p)->cb_fname_callback(); }
285 //! See abort()
286 inline static void scb_abort ( Fl_Widget *w, void *p ){
287 ((DialogDownload*)p)->abort(); }
288 //! See cb_download()
289 inline static void scb_download ( Fl_Widget *w, void *p ){
290 ((DialogDownload*)p)->cb_download(); }
292 * Prevents closing dialog with ESC and when downloading_=true.
294 inline static void scb_close_window ( Fl_Widget *w, void *f ){
295 // dont close main window on ESC
296 if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape )
297 return;
298 // dont close when download in progress
299 if ( ((DialogDownload*)f)->downloading_ ) {
300 fl_message("You must abort download before closing window." );
301 return;
303 ((DialogDownload*)w)->hide();
309 * Shows all known informations about word.
310 * \todo change to edit word dialog
312 class DialogEditWord : public Fl_Double_Window
314 private:
315 Fl_Button *b_cancel_ = nullptr;
316 Fl_Help_View *view_ = nullptr;
317 Label *l_did_ = nullptr;
319 public:
320 DialogEditWord ( int w=400, int h=500, const char *l="Edit word" );
321 ~DialogEditWord(){}
323 inline void set ( const aoi::DicWord &w ){
324 l_did_->set( std::to_string(w.did()) );
325 view_->value( w.html().c_str() );
328 inline static void scb_cancel ( Fl_Widget *w, void *p )
329 { ((DialogEditWord*)p)->hide(); }
334 * Shows Help_View with Cancel button. Stores text.
336 class DialogHtmlView : public Fl_Double_Window
338 private:
339 Fl_Button *b_cancel_ = nullptr;
340 Fl_Help_View *view_ = nullptr;
341 string str_;
343 public:
344 DialogHtmlView ( int w=400, int h=500, const char *l=0 )
345 : Fl_Double_Window(w,h,l)
347 view_ = new Fl_Help_View(5, 5, w-10, h-80);
348 b_cancel_ = new Fl_Button( w-65, h-35, 60, 30, "Close");
349 end();
350 b_cancel_->callback( scb_cancel, (void*)this );
351 view_->textsize(16);
352 set_modal();
354 ~DialogHtmlView(){};
355 inline void set ( const string &s ){
356 str_ = s;
357 view_->value( str_.c_str() );
359 inline static void scb_cancel ( Fl_Widget *w, void *p )
360 { ((DialogHtmlView*)p)->hide(); }
365 * Dialog with database information. Allows dowloading of the new database
366 * and checking user.db against main.db
367 * \note Callback for b_dload_ is set and called by the widgets caller/creator
368 * (currently aoi::App::cb_manage_db() )
370 class ManageDBDialog : public Fl_Double_Window
372 private:
373 Fl_Button *b_close_ = nullptr;
374 Fl_Button *b_dload_ = nullptr;
375 Fl_Button *b_check_main_ = nullptr;
376 Fl_Button *b_check_user_ = nullptr;
377 Label *lver_main_ = nullptr;
378 Label *l_main_created_ = nullptr;
379 Label *lver_jmdict_ = nullptr;
380 Label *lver_kanjidic_ = nullptr;
381 Label *lver_kradfile_ = nullptr;
382 Label *lver_tatoeba_ = nullptr;
383 Label *l_checked_against_= nullptr;
385 public:
386 ManageDBDialog ( int w=400, int h=300, const char *l="Manage Database" );
387 ~ManageDBDialog(){}
389 // setters
390 //! Sets the version of the main database.
391 inline void main_version ( const string &s )
392 { lver_main_->set(s); }
393 //! Sets the main database creation date.
394 inline void main_created ( const string &s )
395 { l_main_created_->set(s); }
396 //! Sets the version of the jmdict used in database.
397 inline void main_ver_jmdict ( const string &s )
398 { lver_jmdict_->set(s); }
399 //! Sets the version of the kanjidic used in database.
400 inline void main_ver_kanjidic ( const string &s )
401 { lver_kanjidic_->set(s); }
402 //! Sets the version of the kradfile used in database.
403 inline void main_ver_kradfile ( const string &s )
404 { lver_kradfile_->set(s); }
405 //! Sets the version of the tatoeba data used in database.
406 inline void main_ver_tatoeba ( const string &s )
407 { lver_tatoeba_->set(s); }
408 //! Sets the main db. version paired with current user database.
409 inline void user_checked_against ( const string &s )
410 { l_checked_against_->set(s); }
412 //! Sets callback for Button download
413 inline void cb_download( Fl_Callback c=nullptr, void *data=nullptr )
414 { if (c && b_dload_) b_dload_->callback(c, data); }
416 // static callbacks
418 * Check the user.db against main.db.
419 * \todo nothing yet
421 inline static void scb_check_user ( Fl_Widget *w, void *p )
422 { fl_alert("Nothing yet."); }
424 * Check main.db integrity and whether any newer version exists.
425 * \todo nothing yet
427 inline static void scb_check_main ( Fl_Widget *w, void *p )
428 { fl_alert("Nothing yet."); }
429 //! Close dialog.
430 inline static void scb_close ( Fl_Widget *w, void *p )
431 { ((ManageDBDialog*)p)->hide(); }
436 * Popup window that shows informations about kanji.
437 * The window is closed with the close button in the titlebar or with ESC.
438 * \see KanjiInfo
440 class KanjiPopupWindow : public Fl_Menu_Window
442 private:
443 KanjiInfo *box_;
445 public:
446 KanjiPopupWindow ( int w, int h );
447 ~KanjiPopupWindow (){};
449 //! See KanjiInfo::font_b()
450 inline void font_a ( Fl_Font f, int s ) { box_->font_a( f, s ); }
451 //! See KanjiInfo::font_a()
452 inline void font_b ( Fl_Font f, int s ) { box_->font_b( f, s ); }
453 //! See KanjiInfo::set_data()
454 inline void set ( const Kanji &k ) { box_->set_data(k); }
456 int handle ( int event );
458 //! Popups the window positioned at the cursor.
459 inline void popup() {
460 // XXX: after clear_border() take_focus() does not work
461 // clear_border();
462 // position at cursor
463 position(Fl::event_x_root(), Fl::event_y_root());
464 size( box_->w(), box_->h());
465 show();
466 take_focus();
472 * Global progress meter.
474 class DialogProgress : public Fl_Double_Window
476 private:
477 string message_ = "";
478 Fl_Progress *progress_ = nullptr;
480 public:
481 DialogProgress( int w, int h ):Fl_Double_Window(w,h){
482 box( FL_BORDER_BOX );
483 progress_ = new Fl_Progress( 10, 10, w-20, 30 );
484 progress_->minimum(0);
485 progress_->maximum(1);
486 set_modal();
487 clear_border();
488 end();
490 ~DialogProgress(){}
492 //! Sets value to 0% and string to "".
493 void init () { message_ = ""; }
495 //! Sets progress in <i>percent</i> and <i>message</i> to be shown.
496 void progress ( float percent, const string &message="" ){
497 message_ = message;
498 progress_->label(message_.c_str());
499 progress_->value( percent/100. );
500 Fl::check();
506 * Shows Fl_Browser with config data. Selection (leftclick, enter or space)
507 * on the even row will show description of the config value,
508 * selection on the odd row will allow change of the value.
509 * \todo odd ? even ?
511 class DialogSettings : public Fl_Double_Window
513 private:
514 Fl_Hold_Browser *browser_ = nullptr;
515 Fl_Button *b_ok_ = nullptr;
516 Fl_Button *b_defaults_ = nullptr;
517 std::map<string,Config::Value> data_;
518 std::map<string,Config::Value> defaults_;
520 public:
521 DialogSettings( int w=400, int h=500 );
522 ~DialogSettings(){};
524 int handle ( int event );
527 * Runs the dialog and waits for an interrupt (OK button, Cancel button,
528 * Close window, ESC).
529 * \return data_ (always)
531 std::map<string,Config::Value> run ();
534 * Sets config data to be shown.
535 * Sets data_ to m and defaults_ to defaults (or to m if defaults is empty )
537 void set ( const std::map<string,Config::Value> &m,
538 const std::map<string,Config::Value> &defaults={} );
540 //! Replaces data_ with defaults_
541 inline void restore_defaults () {
542 data_ = defaults_;
543 hide();
546 //! Callback called after selection (click, space, enter) of an item in browser.
547 void cb ( int line );
548 //! See cb()
549 inline static void static_callback ( Fl_Widget *w, void *p )
550 { ((DialogSettings*)p)->cb( ((Fl_Hold_Browser*)w)->value()); };
551 //! Hides dialog
552 inline static void static_ok ( Fl_Widget *w, void *p )
553 { ((DialogSettings*)p)->hide(); }
554 //! See restore_defaults()
555 inline static void scb_restore_defaults ( Fl_Widget *w, void *p )
556 { ((DialogSettings*)p)->restore_defaults(); };
559 } // namespace aoi_ui
560 #endif // _GUI_DIALOGS_HXX