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 DialogAlert
*dlg_alert_
= nullptr;
214 DialogProgress
*dlg_progress_
= nullptr;
215 KanjiPopupWindow
*popup_
= nullptr;
216 Fl_Help_Dialog
*dlg_help_
= nullptr;
217 EditWordDialog
*dlg_edit_word_
= nullptr;
218 ManageDBDialog
*dlg_manage_db_
= nullptr;
220 //! Prevents closing MainWindow when ESC pressed.
221 inline static void scb_main_window_ ( Fl_Widget
*w
, void *f
)
223 if ( Fl::event() == FL_SHORTCUT
){
224 switch ( Fl::event_key() ){
225 case FL_Escape
: // dont close main window on ESC
230 quit_fltk( w
, (void*)w
);
234 void change_cursor ( Fl_Cursor c
= FL_CURSOR_DEFAULT
);
239 GUI ( aoi::App
*parent
);
243 * Sets FONT_KANJI a FL_SYMBOL (needed in Fl_Help_Dialog).
244 * Initialize fonts in all relevant widgets and dialogs.
249 * Sets FL_BACKGROUND_COLOR, FL_BACKGROUND2_COLOR, FL_FOREGROUND_COLOR
250 * and FL_SELECTION_COLOR
255 //! Shows MainWindow and returns Fl::run()
256 int run ( int argc
, char **argv
);
258 //! Reset checkboxes for filtering pos in dictionary (noun,verb, adj, exp)
259 void reset_filters ();
262 * Shows and sets modal dialog with progress.
264 inline void progress ( float percent
, const string
&message
){
265 center_window( dlg_progress_
);
266 dlg_progress_
->progress( percent
, message
);
268 //! Hides modal progress dialog.
269 inline void progress_hide (){
270 dlg_progress_
->init();
271 dlg_progress_
->hide();
275 inline void alert ( const char *msg
) { fl_alert("%s",msg
); };
276 inline void alert ( const string
&s
) { alert(s
.c_str()); };
278 inline void alert2 ( const string
&msg
, const string
&desc
="" ){
279 dlg_progress_
->position(
280 main_window_
->x_root()+main_window_
->w()/2,
281 main_window_
->y_root()+main_window_
->h()/3 );
282 dlg_alert_
->set_text( msg
, desc
);
286 //! Shows download dialog for given url.
287 inline string
download_dialog ( const string
&url
){
288 string fname
= utils::guess_fname_from_url(url
);
289 dlg_download_
->set_names ( url
, fname
);
290 center_window( dlg_download_
);
291 dlg_download_
->run();
295 //! Shows no. of found dictionary results in DicView header.
296 inline void set_dic_results ( const string
&s
)
297 { main_window_
->dic_view_
->headers( {"","",s
} ); };
298 //! Shows no. of found kanji results in label.
299 inline void set_kanji_results ( const string
&s
) {
300 buffer_
["kanji_results"] = s
;
301 // XXX: ugly hack, but l_knj_results is invisibile if
302 // label(buffer_["kanji_results"].c_str()) of any other
303 // widget is not called ...
304 main_window_
->knj_view_
->label( buffer_
["kanji_results"].c_str() );
305 main_window_
->knj_view_
->label("");
306 main_window_
->l_knj_results
->label( buffer_
["kanji_results"].c_str() );
309 //! Shows <i>Manage database</i> dialog.
310 inline ManageDBDialog
*dlg_manage_db (){
311 center_window( dlg_manage_db_
, main_window_
);
312 return dlg_manage_db_
;
316 * Copy userdata to clipboard and selection buffer (middle button on Linux).
318 static void scb_copy ( Fl_Widget
*w
, void *userdata
) {
319 const char *d
= (const char*)userdata
;
321 Fl::copy( d
, len
, 0);
322 Fl::copy( d
, len
, 1);
326 //! Change cursor to WAIT (hourglass).
327 inline void cursor_wait () { change_cursor(FL_CURSOR_WAIT
); };
328 //! Change cursor to default (arrow).
329 inline void cursor_default () { change_cursor(); }
331 inline bool sort_components_by_strokes () const {
332 return main_window_
->cb_knj_components
->value();
335 //! Shows <i>Font</i> dialog.
337 center_window( dlg_fonts_
);
338 return dlg_fonts_
->run();
341 //! Shows <i>Romanization test</i> dialog.
342 void show_romanization_test ()
344 DialogRomanizationTest
*d
= new DialogRomanizationTest();
348 //! Shows dialog <i>Settings</i>.
349 void show_settings ();
352 * Popus menu (context) menu in DicView.
353 * \param did JMdict id of the word.
354 * \param things List of kanji in the word.
355 * \param notes If false then item <i>Notes</i> will be grayed out.
356 * \param examples If false then item <i>Examples</i> will be grayed out.
358 void dicview_menu ( int did
, const vector
<string
> &things
, bool notes
=false, bool examples
=false );
363 //! Popups KanjiPopupWindow in KanjiView.
364 void popup_kanji ( const Kanji
&k
);
366 // interface for App (controller)
367 inline void help_file ( const string
&s
) { help_file_
= s
; };
368 inline void fontname_kanji ( const string
&s
)
369 { fontname_kanji_
=s
; init_fonts(); };
370 inline void font_base_size ( int s
)
371 { font_base_size_
=s
; init_fonts(); };
372 inline string
skip () const { return main_window_
->e_skip
->value(); };
373 inline int sort_mode () const { return main_window_
->knj_orderby_
->value(); };
374 inline const char *strokes () const { return main_window_
->e_strokes
->value(); };
375 inline const char *jlpt () const { return main_window_
->e_jlpt
->value(); };
376 inline const char *grade () const { return main_window_
->e_grade
->value(); };
377 inline vector
<string
> components_include () const
378 { return main_window_
->compo_view_
->selected1(); };
379 inline vector
<string
> components_exclude () const
380 { return main_window_
->compo_view_
->selected2(); };
381 inline void highlight_components ( const string
&comps
)
382 { main_window_
->compo_view_
->set_highlight(comps
); }
385 Fl_Native_File_Chooser fnfc
;
386 fnfc
.title("Pick a file");
387 fnfc
.type(Fl_Native_File_Chooser::BROWSE_FILE
);
388 switch ( fnfc
.show() ) {
390 throw std::runtime_error( fnfc
.errmsg() );
395 return fnfc
.filename();
398 vector
<string
> listview_filters ();
400 inline void set_components ( const vector
<ComponentView::Cell
> &v
)
401 { main_window_
->compo_view_
->set_data(v
); };
403 inline void set_listview ( const vector
<string
> &d
, const vector
<int> &r
={} )
404 { main_window_
->dic_view_
->set_data(d
,r
); };
405 inline void register_tag_dicview ( const string
&tag
, const TextStyle
&style
)
406 { main_window_
->dic_view_
->register_tag(tag
,style
); };
408 inline void set_kanjiview ( const vector
<KanjiView::Cell
> &d
)
409 { main_window_
->knj_view_
->set_data(d
); };
411 inline const char *get_dic_input () const
412 { return main_window_
->dic_input_
->value(); };
415 void cb_toggle_group ();
416 void cb_knj_clear ();
417 void cb_show_help (){
418 dlg_help_
->load(help_file_
.c_str());
421 void cb_jis208_toggle ();
423 // static callbacks - wrappers for real callbacks
424 inline static void scb_knj_clear ( Fl_Widget
*w
, void *f
)
425 {((GUI
*)f
)->cb_knj_clear(); }
426 inline static void scb_toggle_group(Fl_Widget
*w
, void *f
)
427 {((GUI
*)f
)->cb_toggle_group();};
428 inline static void scb_show_help(Fl_Widget
*w
, void *f
)
429 {((GUI
*)f
)->cb_show_help();};
430 inline static void scb_jis208_toggle(Fl_Widget
*w
, void *f
)
431 {((GUI
*)f
)->cb_jis208_toggle();};
432 inline static void scb_test_romanization ( Fl_Widget
*w
, void *p
)
433 {((GUI
*)p
)->show_romanization_test(); }
434 inline static void scb_test_fonts ( Fl_Widget
*w
, void *p
)
435 {((GUI
*)p
)->select_font(); }
436 inline static void scb_show_settings ( Fl_Widget
*w
, void *p
)
437 {((GUI
*)p
)->show_settings(); }