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_Box.H>
29 #include <FL/Fl_Tile.H>
30 #include <FL/Fl_Menu_Button.H>
31 #include <FL/Fl_Button.H>
32 #include <FL/fl_ask.H>
33 #include <FL/Fl_Choice.H>
34 #include <FL/Fl_Native_File_Chooser.H>
35 #include <FL/Fl_Check_Button.H>
36 #include <FL/Fl_Help_Dialog.H>
37 #include <FL/Fl_Widget.H>
40 #include "gui_settings.hxx"
41 #include "gui_widgets.hxx"
42 #include "gui_dialogs.hxx"
43 #include "gui_dicview.hxx"
44 #include "gui_kanjiview.hxx"
65 * Closes all windows and quits FLTK. Used as callback in menu and MainWindow.
67 static void quit_fltk ( Fl_Widget
*w
, void *p
)
69 Fl_Window
*mainwindow
= (Fl_Window
*)p
;
70 // hide all other windows
71 Fl_Window
*win
= Fl::next_window( mainwindow
);
74 win
= Fl::next_window( mainwindow
);
76 // hide main window and thus exit program
81 static Fl_Window *last_window ()
83 Fl_Window *w = Fl::first_window();
87 w = Fl::next_window(w);
94 * Centers window w on first visible window or on parent if parent is not nullptr.
95 * If the w is smaller than parent then positions w on top left corner od parent.
96 * Works only on hidden w.
97 * \param ontop if true then w is brought to the front
98 * \todo does not work after start
99 * \todo check whether ontop works (in creating dictionary)
101 static void center_window ( Fl_Window
*w
, Fl_Window
*parent
=nullptr, bool ontop
=true)
106 parent
= Fl::first_window();
110 int nx
= (parent
->w() - w
->w())/2;
111 int ny
= (parent
->h() - w
->h())/2;
112 if ( nx
< 10 ) nx
=10;
113 if ( ny
< 10 ) ny
=10;
114 w
->position( parent
->x_root()+nx
, parent
->y_root()+ny
);
115 // should ensure, that w will be on top ...
125 * Dialog for the testing of romanization (both hiragana and katakana).
126 * Shows input and output field.
128 class DialogRomanizationTest
: public Fl_Double_Window
131 Fl_Input
*input_
= nullptr;
132 Fl_Box
*output_
= nullptr;
133 Fl_Choice
*choice_
= nullptr;
134 Fl_Button
*b_close_
= nullptr;
137 DialogRomanizationTest( int w
=300, int h
=180 );
138 ~DialogRomanizationTest(){};
140 inline static void scb_input( Fl_Widget
*w
, void *p
)
141 { ((DialogRomanizationTest
*)p
)->cb_input(); }
142 inline static void scb_close ( Fl_Widget
*w
, void *p
)
143 { ((DialogRomanizationTest
*)p
)->hide(); }
147 /*! Works as container for all MainWindow related widgets
148 * and handles global shortcuts
149 * ALL CONFIGURATIONS OF ITS WIDGETS SHOULD BE DONE IN GUI::GUI()
151 class MainWindow
: public Fl_Double_Window
154 GUI
*parent_
= nullptr;
156 Fl_Menu_Button
*b_menu_
= nullptr;
157 Fl_Button
*b_toggle_view_
= nullptr; // switch between dictionary and kanjiview
159 Fl_Group
*grp_dictionary_
= nullptr;
160 Fl_Group
*grp_kanjidic_
= nullptr;
163 DicView
*dic_view_
= nullptr;
164 Entry
*dic_input_
= nullptr;
165 Fl_Check_Button
*cb_verb_
= nullptr;
166 Fl_Check_Button
*cb_adj_
= nullptr;
167 Fl_Check_Button
*cb_noun_
= nullptr;
168 Fl_Check_Button
*cb_expr_
= nullptr;
171 Fl_Box
*l_knj_results
= nullptr;
172 Entry
*e_skip
= nullptr;
173 Entry
*e_strokes
= nullptr;
174 Entry
*e_jlpt
= nullptr;
175 Entry
*e_grade
= nullptr;
176 KanjiView
*knj_view_
= nullptr;
177 Fl_Choice
*knj_orderby_
= nullptr;
178 ComponentView
*compo_view_
= nullptr;
179 Fl_Button
*b_knj_clear_
= nullptr;
180 Fl_Button
*b_knj_search_
= nullptr;
181 Fl_Check_Button
*cb_knj_jis208
= nullptr;
182 // toggle sort components by strokes / by freq
183 Fl_Check_Button
*cb_knj_components
= nullptr;
186 MainWindow ( GUI
*parent
, int w
, int h
);
189 int handle ( int event
);
194 * Encapsulates MainWindow and all dialogs.
195 * Provides interface for class App.
203 int font_base_size_
= 12;
204 string fontname_kanji_
= "";
205 string help_file_
= "";
207 std::map
<string
,string
> buffer_
;
209 MainWindow
*main_window_
= nullptr;
211 DialogFontTest
*dlg_fonts_
= nullptr;
212 DialogDownload
*dlg_download_
= nullptr;
213 DialogProgress
*dlg_progress_
= nullptr;
214 KanjiPopupWindow
*popup_
= nullptr;
215 Fl_Help_Dialog
*dlg_help_
= nullptr;
216 DialogEditWord
*dlg_edit_word_
= nullptr;
217 ManageDBDialog
*dlg_manage_db_
= nullptr;
219 //! Prevents closing MainWindow when ESC pressed.
220 inline static void scb_main_window_ ( Fl_Widget
*w
, void *f
)
222 if ( Fl::event() == FL_SHORTCUT
){
223 switch ( Fl::event_key() ){
224 case FL_Escape
: // dont close main window on ESC
229 quit_fltk( w
, (void*)w
);
233 void change_cursor ( Fl_Cursor c
= FL_CURSOR_DEFAULT
);
238 GUI ( aoi::App
*parent
);
242 * Sets FONT_KANJI a FL_SYMBOL (needed in Fl_Help_Dialog).
243 * Initialize fonts in all relevant widgets and dialogs.
248 * Sets FL_BACKGROUND_COLOR, FL_BACKGROUND2_COLOR, FL_FOREGROUND_COLOR
249 * and FL_SELECTION_COLOR
254 * Displays simple window with the text <i>s</i> and 2 buttons
255 * (default: <b>Yes</b> and </b>No</b>). String <i>s</i> may contain
257 * \return pressed button number (0 for the first, 1 for the second)
259 inline int choice ( const string
&s
, const string
&btn1
="Yes",
260 const string
&btn2
="No" ){
261 return fl_choice( s
.c_str(), btn1
.c_str(), btn2
.c_str(), 0);
265 //! Shows MainWindow and returns Fl::run()
266 int run ( int argc
, char **argv
);
268 //! Reset checkboxes for filtering pos in dictionary (noun,verb, adj, exp)
269 void reset_filters ();
272 * Shows and sets modal dialog with progress.
274 inline void progress ( float percent
, const string
&message
){
275 if ( ! dlg_progress_
->visible() )
276 dlg_progress_
->show();
277 center_window( dlg_progress_
);
278 dlg_progress_
->progress( percent
, message
);
280 //! Hides modal progress dialog.
281 inline void progress_hide (){
282 dlg_progress_
->init();
283 dlg_progress_
->hide();
288 * Shows simple textview with HTML 2.0 support.
290 inline void show_html ( const string
&s
){
291 DialogHtmlView
*d
= new DialogHtmlView(600,400);
296 inline void alert ( const char *msg
) { fl_alert("%s",msg
); };
297 inline void alert ( const string
&s
) { alert(s
.c_str()); };
300 * Shows download dialog for given url.
301 * \return name(path) of the downloaded file
303 inline string
download_dialog ( const string
&url
){
304 string fname
= utils::guess_fname_from_url(url
);
305 dlg_download_
->set_names ( url
, fname
);
306 center_window( dlg_download_
);
307 dlg_download_
->run();
311 //! Shows no. of found dictionary results in DicView header.
312 inline void set_dic_results ( const string
&s
)
313 { main_window_
->dic_view_
->headers( {"","",s
} ); };
314 //! Shows no. of found kanji results in label.
315 inline void set_kanji_results ( const string
&s
) {
316 buffer_
["kanji_results"] = s
;
317 // XXX: ugly hack, but l_knj_results is invisibile if
318 // label(buffer_["kanji_results"].c_str()) of any other
319 // widget is not called ...
320 main_window_
->knj_view_
->label( buffer_
["kanji_results"].c_str() );
321 main_window_
->knj_view_
->label("");
322 main_window_
->l_knj_results
->label( buffer_
["kanji_results"].c_str() );
325 //! Shows <i>Manage database</i> dialog.
326 inline ManageDBDialog
*dlg_manage_db (){
327 center_window( dlg_manage_db_
, main_window_
);
328 return dlg_manage_db_
;
332 * Copy userdata to clipboard and selection buffer (middle button on Linux).
334 static void scb_copy ( Fl_Widget
*w
, void *userdata
) {
335 const char *d
= (const char*)userdata
;
337 Fl::copy( d
, len
, 0);
338 Fl::copy( d
, len
, 1);
342 //! Change cursor to WAIT (hourglass).
343 inline void cursor_wait () { change_cursor(FL_CURSOR_WAIT
); };
344 //! Change cursor to default (arrow).
345 inline void cursor_default () { change_cursor(); }
347 inline bool sort_components_by_strokes () const {
348 return main_window_
->cb_knj_components
->value();
351 //! Shows <i>Font</i> dialog.
353 center_window( dlg_fonts_
);
354 return dlg_fonts_
->run();
357 //! Shows <i>Romanization test</i> dialog.
358 void show_romanization_test ()
360 DialogRomanizationTest
*d
= new DialogRomanizationTest();
364 //! Shows dialog <i>Settings</i>.
365 void show_settings ();
368 * Popus menu (context) menu in DicView.
369 * \param did JMdict id of the word.
370 * \param things List of kanji in the word.
371 * \param notes If false then item <i>Notes</i> will be grayed out.
372 * \param examples If false then item <i>Examples</i> will be grayed out.
374 void dicview_menu ( int did
, const vector
<string
> &things
, bool notes
=false, bool examples
=false );
377 void edit_word ( const aoi::DicWord
&w
);
379 //! Popups KanjiPopupWindow in KanjiView.
380 void popup_kanji ( const Kanji
&k
);
382 // interface for App (controller)
383 inline void help_file ( const string
&s
) { help_file_
= s
; };
384 inline void fontname_kanji ( const string
&s
)
385 { fontname_kanji_
=s
; init_fonts(); };
386 inline void font_base_size ( int s
)
387 { font_base_size_
=s
; init_fonts(); };
388 inline string
skip () const { return main_window_
->e_skip
->value(); };
389 inline int sort_mode () const { return main_window_
->knj_orderby_
->value(); };
390 inline const char *strokes () const { return main_window_
->e_strokes
->value(); };
391 inline const char *jlpt () const { return main_window_
->e_jlpt
->value(); };
392 inline const char *grade () const { return main_window_
->e_grade
->value(); };
393 inline vector
<string
> components_include () const
394 { return main_window_
->compo_view_
->selected1(); };
395 inline vector
<string
> components_exclude () const
396 { return main_window_
->compo_view_
->selected2(); };
397 inline void highlight_components ( const string
&comps
)
398 { main_window_
->compo_view_
->set_highlight(comps
); }
401 Fl_Native_File_Chooser fnfc
;
402 fnfc
.title("Pick a file");
403 fnfc
.type(Fl_Native_File_Chooser::BROWSE_FILE
);
404 switch ( fnfc
.show() ) {
406 throw std::runtime_error( fnfc
.errmsg() );
411 return fnfc
.filename();
414 vector
<string
> listview_filters ();
416 inline int dicview_selected_rowid () const
417 { return main_window_
->dic_view_
->selected_row_id(); };
419 inline void set_components ( const vector
<ComponentView::Cell
> &v
)
420 { main_window_
->compo_view_
->set_data(v
); };
422 inline void set_listview ( const vector
<string
> &d
, const vector
<int> &r
={} )
423 { main_window_
->dic_view_
->set_data(d
,r
); };
424 inline void register_tag_dicview ( const string
&tag
, const TextStyle
&style
)
425 { main_window_
->dic_view_
->register_tag(tag
,style
); };
427 inline void set_kanjiview ( const vector
<KanjiView::Cell
> &d
)
428 { main_window_
->knj_view_
->set_data(d
); };
430 inline const char *get_dic_input () const
431 { return main_window_
->dic_input_
->value(); };
434 void cb_toggle_group ();
435 void cb_knj_clear ();
436 void cb_show_help (){
437 dlg_help_
->load(help_file_
.c_str());
440 void cb_jis208_toggle ();
442 // static callbacks - wrappers for real callbacks
443 inline static void scb_knj_clear ( Fl_Widget
*w
, void *f
)
444 {((GUI
*)f
)->cb_knj_clear(); }
445 inline static void scb_toggle_group(Fl_Widget
*w
, void *f
)
446 {((GUI
*)f
)->cb_toggle_group();};
447 inline static void scb_show_help(Fl_Widget
*w
, void *f
)
448 {((GUI
*)f
)->cb_show_help();};
449 inline static void scb_jis208_toggle(Fl_Widget
*w
, void *f
)
450 {((GUI
*)f
)->cb_jis208_toggle();};
451 inline static void scb_test_romanization ( Fl_Widget
*w
, void *p
)
452 {((GUI
*)p
)->show_romanization_test(); }
453 inline static void scb_test_fonts ( Fl_Widget
*w
, void *p
)
454 {((GUI
*)p
)->select_font(); }
455 inline static void scb_show_settings ( Fl_Widget
*w
, void *p
)
456 {((GUI
*)p
)->show_settings(); }