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/>.
26 #include <FL/Fl_Double_Window.H>
27 #include <FL/Fl_Group.H>
28 #include <FL/Fl_Tile.H>
29 #include <FL/Fl_Menu_Button.H>
30 #include <FL/Fl_Button.H>
31 #include <FL/fl_ask.H>
32 #include <FL/Fl_Choice.H>
33 #include <FL/Fl_Native_File_Chooser.H>
34 #include <FL/Fl_Check_Button.H>
35 #include <FL/Fl_Help_Dialog.H>
36 #include <FL/Fl_Widget.H>
39 #include "gui_settings.hxx"
40 #include "gui_widgets.hxx"
41 #include "gui_dialogs.hxx"
42 #include "gui_dicview.hxx"
43 #include "gui_kanjiview.hxx"
46 * Contains class GUI, which manages the main window and all the dialogs.
47 * \todo Separate all the functions working as interface for the App.
66 * Closes all windows and quits FLTK. Used as callback in menu and MainWindow.
68 static void quit_fltk ( Fl_Widget
*w
, void *p
)
71 Fl_Window *mainwindow = (Fl_Window*)p;
72 // hide all other windows
73 Fl_Window *win = Fl::next_window( mainwindow );
76 win = Fl::next_window( mainwindow );
78 // hide main window and thus exit program
81 while(Fl::first_window())
82 Fl::first_window()->hide();
87 * Centers the window w on the first visible window or on its parent if the
88 * parent is not nullptr.
89 * If the w is smaller than parent then positions w on top left corner od parent.
90 * Works only on the hidden w.
91 * \param ontop if true then w is brought to the front
92 * \todo does not work after start
93 * \todo check whether ontop works (in creating dictionary)
95 static void center_window ( Fl_Window
*w
, Fl_Window
*parent
=nullptr, bool ontop
=true)
100 parent
= Fl::first_window();
104 int nx
= (parent
->w() - w
->w())/2;
105 int ny
= (parent
->h() - w
->h())/2;
106 if ( nx
< 10 ) nx
=10;
107 if ( ny
< 10 ) ny
=10;
108 w
->position( parent
->x_root()+nx
, parent
->y_root()+ny
);
109 // should ensure, that w will be on top ...
118 * Dialog for the testing of romanization (both hiragana and katakana).
119 * Shows the input and output field.
121 class DialogRomanizationTest
: public Fl_Double_Window
124 Fl_Input
*input_
= nullptr;
125 Fl_Input
*output_
= nullptr;
126 Fl_Choice
*choice_
= nullptr;
127 Fl_Button
*b_close_
= nullptr;
130 DialogRomanizationTest( int w
=300, int h
=180 );
131 ~DialogRomanizationTest(){};
133 inline static void scb_input( Fl_Widget
*w
, void *p
)
134 { ((DialogRomanizationTest
*)p
)->cb_input(); }
135 inline static void scb_close ( Fl_Widget
*w
, void *p
)
136 { ((DialogRomanizationTest
*)p
)->hide(); }
140 /*! Container for all MainWindow related widgets.
141 * Handles global shortcuts
142 * ALL THE CONFIGURATIONS OF ITS WIDGETS SHOULD BE DONE IN GUI::GUI()
144 class MainWindow
: public Fl_Double_Window
147 GUI
*parent_
= nullptr;
149 Fl_Menu_Button
*b_menu_
= nullptr;
150 Fl_Button
*b_toggle_view_
= nullptr; // switch between dictionary and kanjiview
152 Fl_Group
*grp_dictionary_
= nullptr;
153 Fl_Group
*grp_kanjidic_
= nullptr;
156 DicView
*dic_view_
= nullptr;
157 Entry
*dic_input_
= nullptr;
158 Fl_Check_Button
*cb_verb_
= nullptr;
159 Fl_Check_Button
*cb_adj_
= nullptr;
160 Fl_Check_Button
*cb_noun_
= nullptr;
161 Fl_Check_Button
*cb_expr_
= nullptr;
164 Label
*l_knj_results
= nullptr;
165 Entry
*e_skip
= nullptr;
166 Entry
*e_strokes
= nullptr;
167 Entry
*e_jlpt
= nullptr;
168 Entry
*e_grade
= nullptr;
169 KanjiView
*knj_view_
= nullptr;
170 Fl_Choice
*knj_orderby_
= nullptr;
171 ComponentView
*compo_view_
= nullptr;
172 Fl_Button
*b_knj_clear_
= nullptr;
173 Fl_Button
*b_knj_search_
= nullptr;
174 Fl_Check_Button
*cb_knj_jis208
= nullptr;
175 // toggle sort components by strokes / by freq
176 Fl_Check_Button
*cb_knj_components
= nullptr;
179 MainWindow ( GUI
*parent
, int w
, int h
);
182 int handle ( int event
);
187 * Encapsulates the MainWindow and all dialogs.
188 * Provides interface for class App.
196 int font_base_size_
= 12;
197 string fontname_kanji_
= "";
198 string help_file_
= "";
200 MainWindow
*main_window_
= nullptr;
202 DialogFontTest
*dlg_fonts_
= nullptr;
203 DialogDownload
*dlg_download_
= nullptr;
204 DialogProgress
*dlg_progress_
= nullptr;
205 KanjiPopupWindow
*popup_
= nullptr;
206 Fl_Help_Dialog
*dlg_help_
= nullptr;
207 DialogEditWord
*dlg_edit_word_
= nullptr;
208 ManageDBDialog
*dlg_manage_db_
= nullptr;
210 //! Prevents closing MainWindow when ESC pressed.
211 inline static void scb_main_window_ ( Fl_Widget
*w
, void *f
)
213 if ( Fl::event() == FL_SHORTCUT
){
214 switch ( Fl::event_key() ){
215 case FL_Escape
: // dont close main window on ESC
220 quit_fltk( w
, (void*)w
);
224 void change_cursor ( Fl_Cursor c
= FL_CURSOR_DEFAULT
);
229 GUI ( aoi::App
*parent
);
233 * Sets FONT_KANJI a FL_SYMBOL (needed in Fl_Help_Dialog).
234 * Initialize fonts in all relevant widgets and dialogs.
239 * Sets FL_BACKGROUND_COLOR, FL_BACKGROUND2_COLOR, FL_FOREGROUND_COLOR
240 * and FL_SELECTION_COLOR
245 * Displays simple window with the text <i>s</i> and 2 buttons
246 * (default: <b>Yes</b> and </b>No</b>). String <i>s</i> may contain
248 * \return pressed button number (0 for the first, 1 for the second)
250 inline int choice ( const string
&s
, const string
&btn1
="Yes",
251 const string
&btn2
="No" ){
252 return fl_choice( s
.c_str(), btn1
.c_str(), btn2
.c_str(), 0);
256 //! Shows MainWindow and returns Fl::run()
257 int run ( int argc
, char **argv
);
259 //! Reset checkboxes for filtering pos in dictionary (noun,verb, adj, exp)
260 void reset_filters ();
263 * Shows and sets modal dialog with progress.
265 inline void progress ( float percent
, const string
&message
){
266 if ( ! dlg_progress_
->visible() )
267 dlg_progress_
->show();
268 center_window( dlg_progress_
);
269 dlg_progress_
->progress( percent
, message
);
271 //! Hides modal progress dialog.
272 inline void progress_hide (){
273 dlg_progress_
->init();
274 dlg_progress_
->hide();
279 * Shows simple textview with HTML 2.0 support.
281 inline void show_html ( const string
&s
){
282 DialogHtmlView
*d
= new DialogHtmlView(600,400);
287 inline void alert ( const char *msg
) { fl_alert("%s",msg
); };
288 inline void alert ( const string
&s
) { alert(s
.c_str()); };
291 * Shows download dialog for given url.
292 * \return name(path) of the downloaded file
294 inline string
download_dialog ( const string
&url
){
295 string fname
= utils::guess_fname_from_url(url
);
296 dlg_download_
->set_names ( url
, fname
);
297 center_window( dlg_download_
);
298 dlg_download_
->run();
302 //! Shows no. of found dictionary results in DicView header.
303 inline void set_dic_results ( const string
&s
)
304 { main_window_
->dic_view_
->headers( {"","",s
} ); };
306 // XXX: does not work
307 //! Shows no. of found kanji results in label.
308 inline void set_kanji_results ( const string
&s
) {
309 main_window_
->l_knj_results
->show();
310 main_window_
->l_knj_results
->set(s
);
313 //! Shows <i>Manage database</i> dialog.
314 inline ManageDBDialog
*dlg_manage_db (){
315 center_window( dlg_manage_db_
, main_window_
);
316 return dlg_manage_db_
;
320 * Copy userdata to clipboard and selection buffer (middle button on Linux).
322 static void scb_copy ( Fl_Widget
*w
, void *userdata
) {
323 const char *d
= (const char*)userdata
;
325 Fl::copy( d
, len
, 0);
326 Fl::copy( d
, len
, 1);
330 //! Change the cursor to WAIT (hourglass).
331 inline void cursor_wait () { change_cursor(FL_CURSOR_WAIT
); };
332 //! Change the cursor to default (arrow).
333 inline void cursor_default () { change_cursor(); }
335 //! Returns the status of checkbox above the list of the components
336 inline bool sort_components_by_strokes () const {
337 return main_window_
->cb_knj_components
->value();
340 //! Shows <i>Font</i> dialog.
342 center_window( dlg_fonts_
);
343 return dlg_fonts_
->run();
346 //! Shows <i>Romanization test</i> dialog.
347 void show_romanization_test ()
349 DialogRomanizationTest
*d
= new DialogRomanizationTest();
353 //! Shows dialog <i>Settings</i>.
354 void show_settings ();
357 * Popups the (context) menu in DicView.
358 * \param did JMdict id of the word.
359 * \param things List of kanji in the word.
360 * \param notes If false then item <i>Notes</i> will be grayed out.
361 * \param examples If false then item <i>Examples</i> will be grayed out.
363 void dicview_menu ( int did
, const vector
<string
> &things
,
364 bool notes
=false, bool examples
=false );
366 /*! Shows the <i>Edit word</i> dialog.
368 void edit_word ( const aoi::DicWord
&w
);
370 //! Popups KanjiPopupWindow in KanjiView.
371 void popup_kanji ( const Kanji
&k
);
373 * Tells App to find kanji <i>k</a> in the database
374 * and call popup_kanji( const Kanji &k ).
376 void popup_kanji ( const string
&k
);
378 //! Sets the file serving as index for the help.
379 inline void help_file ( const string
&s
) { help_file_
= s
; };
380 /*! Sets the name of the font that will be used for non ASCII characters.
381 * \note the font should be able to display JIS X 208/212/213
383 inline void fontname_kanji ( const string
&s
)
384 { fontname_kanji_
=s
; init_fonts(); };
385 //! The base size of the fonts. All other sized are derived from this value.
386 inline void font_base_size ( int s
)
387 { font_base_size_
=s
; init_fonts(); };
388 //! Returns the content of the input field "SKIP"
389 inline string
skip () const { return main_window_
->e_skip
->value(); };
390 //! Return the selected sort mode (in kanjiview)
391 inline int sort_mode () const { return main_window_
->knj_orderby_
->value(); };
392 //! Returns the content of the input field "Strokes" (#)
393 inline const char *strokes () const { return main_window_
->e_strokes
->value(); };
394 //! Returns the content of the input field "JLPT"
395 inline const char *jlpt () const { return main_window_
->e_jlpt
->value(); };
396 //! Returns the content of the input field "Grade" (Grd.)
397 inline const char *grade () const { return main_window_
->e_grade
->value(); };
398 //! Returns all the components selected by the leftclick.
399 inline vector
<string
> components_include () const
400 { return main_window_
->compo_view_
->selected1(); };
401 //! Returns all the components selected by the rightclick.
402 inline vector
<string
> components_exclude () const
403 { return main_window_
->compo_view_
->selected2(); };
404 //! Highlights all the components that are the part of the currently selected kanji.
405 inline void highlight_components ( const string
&comps
)
406 { main_window_
->compo_view_
->set_highlight(comps
); }
408 /*! Displays the fileselection dialog. On the Windows it should be the native
409 * dialog, on the Linux the FLTK's.
410 * \returns path or ""
413 Fl_Native_File_Chooser fnfc
;
414 fnfc
.title("Pick a file");
415 fnfc
.type(Fl_Native_File_Chooser::BROWSE_FILE
);
416 switch ( fnfc
.show() ) {
418 throw std::runtime_error( fnfc
.errmsg() );
423 return fnfc
.filename();
426 //! Returns selected fitlers for listview as string ( "noun", "verb", "adj", "expr")
427 vector
<string
> listview_filters ();
429 inline int dicview_selected_rowid () const
430 { return main_window_
->dic_view_
->selected_row_id(); };
432 inline void set_components ( const vector
<ComponentView::Cell
> &v
)
433 { main_window_
->compo_view_
->set_data(v
); };
435 inline void set_listview ( const vector
<string
> &d
, const vector
<int> &r
={} )
436 { main_window_
->dic_view_
->set_data(d
,r
); };
437 inline void register_tag_dicview ( const string
&tag
, const TextStyle
&style
)
438 { main_window_
->dic_view_
->register_tag(tag
,style
); };
440 inline void set_kanjiview ( const vector
<KanjiView::Cell
> &d
)
441 { main_window_
->knj_view_
->set_data(d
); };
443 inline const char *get_dic_input () const
444 { return main_window_
->dic_input_
->value(); };
446 void cb_toggle_group ();
447 void cb_knj_clear ();
448 void cb_show_help (){
449 dlg_help_
->load(help_file_
.c_str());
452 void cb_jis208_toggle ();
454 inline static void scb_menu_show_kanji ( Fl_Widget
*w
, void *p
){
455 char name
[64]; // the last picked menu item
456 if ( ((Fl_Menu_
*)w
)->item_pathname(name
, sizeof(name
)-1) == 0 )
457 // menu item is in the form: "Kanji/Show"
458 ((GUI
*)p
)->popup_kanji( strtok( name
, "/" ) );
460 inline static void scb_knj_clear ( Fl_Widget
*w
, void *f
)
461 {((GUI
*)f
)->cb_knj_clear(); }
462 inline static void scb_toggle_group(Fl_Widget
*w
, void *f
)
463 {((GUI
*)f
)->cb_toggle_group();}
464 inline static void scb_show_help(Fl_Widget
*w
, void *f
)
465 {((GUI
*)f
)->cb_show_help();}
466 inline static void scb_jis208_toggle(Fl_Widget
*w
, void *f
)
467 {((GUI
*)f
)->cb_jis208_toggle();}
468 inline static void scb_test_romanization ( Fl_Widget
*w
, void *p
)
469 {((GUI
*)p
)->show_romanization_test(); }
470 inline static void scb_test_fonts ( Fl_Widget
*w
, void *p
)
471 {((GUI
*)p
)->select_font(); }
472 inline static void scb_show_settings ( Fl_Widget
*w
, void *p
)
473 {((GUI
*)p
)->show_settings(); }