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"
64 * Closes all windows and quits FLTK. Used as callback in menu and MainWindow.
66 static void quit_fltk ( Fl_Widget
*w
, void *p
)
68 Fl_Window
*mainwindow
= (Fl_Window
*)p
;
69 // hide all other windows
70 Fl_Window
*win
= Fl::next_window( mainwindow
);
73 win
= Fl::next_window( mainwindow
);
75 // hide main window and thus exit program
80 static Fl_Window *last_window ()
82 Fl_Window *w = Fl::first_window();
86 w = Fl::next_window(w);
93 * Centers window w on first visible window or on parent if parent is not nullptr.
94 * If the w is smaller than parent then positions w on top left corner od parent.
95 * Works only on hidden w.
96 * \param ontop if true then w is brought to the front
97 * \todo does not work after start
98 * \todo check whether ontop works (in creating dictionary)
100 static void center_window ( Fl_Window
*w
, Fl_Window
*parent
=nullptr, bool ontop
=true)
105 parent
= Fl::first_window();
109 int nx
= (parent
->w() - w
->w())/2;
110 int ny
= (parent
->h() - w
->h())/2;
111 if ( nx
< 10 ) nx
=10;
112 if ( ny
< 10 ) ny
=10;
113 w
->position( parent
->x_root()+nx
, parent
->y_root()+ny
);
114 // should ensure, that w will be on top ...
124 * Dialog for the testing of romanization (both hiragana and katakana).
125 * Shows input and output field.
127 class DialogRomanizationTest
: public Fl_Double_Window
130 Fl_Input
*input_
= nullptr;
131 Fl_Input
*output_
= nullptr;
132 Fl_Choice
*choice_
= nullptr;
133 Fl_Button
*b_close_
= nullptr;
136 DialogRomanizationTest( int w
=300, int h
=180 );
137 ~DialogRomanizationTest(){};
139 inline static void scb_input( Fl_Widget
*w
, void *p
)
140 { ((DialogRomanizationTest
*)p
)->cb_input(); }
141 inline static void scb_close ( Fl_Widget
*w
, void *p
)
142 { ((DialogRomanizationTest
*)p
)->hide(); }
146 /*! Works as container for all MainWindow related widgets
147 * and handles global shortcuts
148 * ALL CONFIGURATIONS OF ITS WIDGETS SHOULD BE DONE IN GUI::GUI()
150 class MainWindow
: public Fl_Double_Window
153 GUI
*parent_
= nullptr;
155 Fl_Menu_Button
*b_menu_
= nullptr;
156 Fl_Button
*b_toggle_view_
= nullptr; // switch between dictionary and kanjiview
158 Fl_Group
*grp_dictionary_
= nullptr;
159 Fl_Group
*grp_kanjidic_
= nullptr;
162 DicView
*dic_view_
= nullptr;
163 Entry
*dic_input_
= nullptr;
164 Fl_Check_Button
*cb_verb_
= nullptr;
165 Fl_Check_Button
*cb_adj_
= nullptr;
166 Fl_Check_Button
*cb_noun_
= nullptr;
167 Fl_Check_Button
*cb_expr_
= nullptr;
170 Label
*l_knj_results
= nullptr;
171 Entry
*e_skip
= nullptr;
172 Entry
*e_strokes
= nullptr;
173 Entry
*e_jlpt
= nullptr;
174 Entry
*e_grade
= nullptr;
175 KanjiView
*knj_view_
= nullptr;
176 Fl_Choice
*knj_orderby_
= nullptr;
177 ComponentView
*compo_view_
= nullptr;
178 Fl_Button
*b_knj_clear_
= nullptr;
179 Fl_Button
*b_knj_search_
= nullptr;
180 Fl_Check_Button
*cb_knj_jis208
= nullptr;
181 // toggle sort components by strokes / by freq
182 Fl_Check_Button
*cb_knj_components
= nullptr;
185 MainWindow ( GUI
*parent
, int w
, int h
);
188 int handle ( int event
);
193 * Encapsulates MainWindow and all dialogs.
194 * Provides interface for class App.
202 int font_base_size_
= 12;
203 string fontname_kanji_
= "";
204 string help_file_
= "";
206 MainWindow
*main_window_
= nullptr;
208 DialogFontTest
*dlg_fonts_
= nullptr;
209 DialogDownload
*dlg_download_
= nullptr;
210 DialogProgress
*dlg_progress_
= nullptr;
211 KanjiPopupWindow
*popup_
= nullptr;
212 Fl_Help_Dialog
*dlg_help_
= nullptr;
213 DialogEditWord
*dlg_edit_word_
= nullptr;
214 ManageDBDialog
*dlg_manage_db_
= nullptr;
216 //! Prevents closing MainWindow when ESC pressed.
217 inline static void scb_main_window_ ( Fl_Widget
*w
, void *f
)
219 if ( Fl::event() == FL_SHORTCUT
){
220 switch ( Fl::event_key() ){
221 case FL_Escape
: // dont close main window on ESC
226 quit_fltk( w
, (void*)w
);
230 void change_cursor ( Fl_Cursor c
= FL_CURSOR_DEFAULT
);
235 GUI ( aoi::App
*parent
);
239 * Sets FONT_KANJI a FL_SYMBOL (needed in Fl_Help_Dialog).
240 * Initialize fonts in all relevant widgets and dialogs.
245 * Sets FL_BACKGROUND_COLOR, FL_BACKGROUND2_COLOR, FL_FOREGROUND_COLOR
246 * and FL_SELECTION_COLOR
251 * Displays simple window with the text <i>s</i> and 2 buttons
252 * (default: <b>Yes</b> and </b>No</b>). String <i>s</i> may contain
254 * \return pressed button number (0 for the first, 1 for the second)
256 inline int choice ( const string
&s
, const string
&btn1
="Yes",
257 const string
&btn2
="No" ){
258 return fl_choice( s
.c_str(), btn1
.c_str(), btn2
.c_str(), 0);
262 //! Shows MainWindow and returns Fl::run()
263 int run ( int argc
, char **argv
);
265 //! Reset checkboxes for filtering pos in dictionary (noun,verb, adj, exp)
266 void reset_filters ();
269 * Shows and sets modal dialog with progress.
271 inline void progress ( float percent
, const string
&message
){
272 if ( ! dlg_progress_
->visible() )
273 dlg_progress_
->show();
274 center_window( dlg_progress_
);
275 dlg_progress_
->progress( percent
, message
);
277 //! Hides modal progress dialog.
278 inline void progress_hide (){
279 dlg_progress_
->init();
280 dlg_progress_
->hide();
285 * Shows simple textview with HTML 2.0 support.
287 inline void show_html ( const string
&s
){
288 DialogHtmlView
*d
= new DialogHtmlView(600,400);
293 inline void alert ( const char *msg
) { fl_alert("%s",msg
); };
294 inline void alert ( const string
&s
) { alert(s
.c_str()); };
297 * Shows download dialog for given url.
298 * \return name(path) of the downloaded file
300 inline string
download_dialog ( const string
&url
){
301 string fname
= utils::guess_fname_from_url(url
);
302 dlg_download_
->set_names ( url
, fname
);
303 center_window( dlg_download_
);
304 dlg_download_
->run();
308 //! Shows no. of found dictionary results in DicView header.
309 inline void set_dic_results ( const string
&s
)
310 { main_window_
->dic_view_
->headers( {"","",s
} ); };
312 // XXX: does not work
313 //! Shows no. of found kanji results in label.
314 inline void set_kanji_results ( const string
&s
) {
315 main_window_
->l_knj_results
->show();
316 main_window_
->l_knj_results
->set(s
);
319 //! Shows <i>Manage database</i> dialog.
320 inline ManageDBDialog
*dlg_manage_db (){
321 center_window( dlg_manage_db_
, main_window_
);
322 return dlg_manage_db_
;
326 * Copy userdata to clipboard and selection buffer (middle button on Linux).
328 static void scb_copy ( Fl_Widget
*w
, void *userdata
) {
329 const char *d
= (const char*)userdata
;
331 Fl::copy( d
, len
, 0);
332 Fl::copy( d
, len
, 1);
336 //! Change cursor to WAIT (hourglass).
337 inline void cursor_wait () { change_cursor(FL_CURSOR_WAIT
); };
338 //! Change cursor to default (arrow).
339 inline void cursor_default () { change_cursor(); }
341 inline bool sort_components_by_strokes () const {
342 return main_window_
->cb_knj_components
->value();
345 //! Shows <i>Font</i> dialog.
347 center_window( dlg_fonts_
);
348 return dlg_fonts_
->run();
351 //! Shows <i>Romanization test</i> dialog.
352 void show_romanization_test ()
354 DialogRomanizationTest
*d
= new DialogRomanizationTest();
358 //! Shows dialog <i>Settings</i>.
359 void show_settings ();
362 * Popus menu (context) menu in DicView.
363 * \param did JMdict id of the word.
364 * \param things List of kanji in the word.
365 * \param notes If false then item <i>Notes</i> will be grayed out.
366 * \param examples If false then item <i>Examples</i> will be grayed out.
368 void dicview_menu ( int did
, const vector
<string
> &things
, bool notes
=false, bool examples
=false );
371 void edit_word ( const aoi::DicWord
&w
);
373 //! Popups KanjiPopupWindow in KanjiView.
374 void popup_kanji ( const Kanji
&k
);
376 // interface for App (controller)
377 inline void help_file ( const string
&s
) { help_file_
= s
; };
378 inline void fontname_kanji ( const string
&s
)
379 { fontname_kanji_
=s
; init_fonts(); };
380 inline void font_base_size ( int s
)
381 { font_base_size_
=s
; init_fonts(); };
382 inline string
skip () const { return main_window_
->e_skip
->value(); };
383 inline int sort_mode () const { return main_window_
->knj_orderby_
->value(); };
384 inline const char *strokes () const { return main_window_
->e_strokes
->value(); };
385 inline const char *jlpt () const { return main_window_
->e_jlpt
->value(); };
386 inline const char *grade () const { return main_window_
->e_grade
->value(); };
387 inline vector
<string
> components_include () const
388 { return main_window_
->compo_view_
->selected1(); };
389 inline vector
<string
> components_exclude () const
390 { return main_window_
->compo_view_
->selected2(); };
391 inline void highlight_components ( const string
&comps
)
392 { main_window_
->compo_view_
->set_highlight(comps
); }
395 Fl_Native_File_Chooser fnfc
;
396 fnfc
.title("Pick a file");
397 fnfc
.type(Fl_Native_File_Chooser::BROWSE_FILE
);
398 switch ( fnfc
.show() ) {
400 throw std::runtime_error( fnfc
.errmsg() );
405 return fnfc
.filename();
408 vector
<string
> listview_filters ();
410 inline int dicview_selected_rowid () const
411 { return main_window_
->dic_view_
->selected_row_id(); };
413 inline void set_components ( const vector
<ComponentView::Cell
> &v
)
414 { main_window_
->compo_view_
->set_data(v
); };
416 inline void set_listview ( const vector
<string
> &d
, const vector
<int> &r
={} )
417 { main_window_
->dic_view_
->set_data(d
,r
); };
418 inline void register_tag_dicview ( const string
&tag
, const TextStyle
&style
)
419 { main_window_
->dic_view_
->register_tag(tag
,style
); };
421 inline void set_kanjiview ( const vector
<KanjiView::Cell
> &d
)
422 { main_window_
->knj_view_
->set_data(d
); };
424 inline const char *get_dic_input () const
425 { return main_window_
->dic_input_
->value(); };
427 void cb_toggle_group ();
428 void cb_knj_clear ();
429 void cb_show_help (){
430 dlg_help_
->load(help_file_
.c_str());
433 void cb_jis208_toggle ();
435 //! See popup_kanji()
436 inline static void scb_knj_clear ( Fl_Widget
*w
, void *f
)
437 {((GUI
*)f
)->cb_knj_clear(); }
438 inline static void scb_toggle_group(Fl_Widget
*w
, void *f
)
439 {((GUI
*)f
)->cb_toggle_group();};
440 inline static void scb_show_help(Fl_Widget
*w
, void *f
)
441 {((GUI
*)f
)->cb_show_help();};
442 inline static void scb_jis208_toggle(Fl_Widget
*w
, void *f
)
443 {((GUI
*)f
)->cb_jis208_toggle();};
444 inline static void scb_test_romanization ( Fl_Widget
*w
, void *p
)
445 {((GUI
*)p
)->show_romanization_test(); }
446 inline static void scb_test_fonts ( Fl_Widget
*w
, void *p
)
447 {((GUI
*)p
)->select_font(); }
448 inline static void scb_show_settings ( Fl_Widget
*w
, void *p
)
449 {((GUI
*)p
)->show_settings(); }