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 //! Shows MainWindow and returns Fl::run()
255 int run ( int argc
, char **argv
);
257 //! Reset checkboxes for filtering pos in dictionary (noun,verb, adj, exp)
258 void reset_filters ();
261 * Shows and sets modal dialog with progress.
263 inline void progress ( float percent
, const string
&message
){
264 center_window( dlg_progress_
);
265 dlg_progress_
->progress( percent
, message
);
267 //! Hides modal progress dialog.
268 inline void progress_hide (){
269 dlg_progress_
->init();
270 dlg_progress_
->hide();
274 inline void alert ( const char *msg
) { fl_alert("%s",msg
); };
275 inline void alert ( const string
&s
) { alert(s
.c_str()); };
277 //! Shows download dialog for given url.
278 inline string
download_dialog ( const string
&url
){
279 string fname
= utils::guess_fname_from_url(url
);
280 dlg_download_
->set_names ( url
, fname
);
281 center_window( dlg_download_
);
282 dlg_download_
->run();
286 //! Shows no. of found dictionary results in DicView header.
287 inline void set_dic_results ( const string
&s
)
288 { main_window_
->dic_view_
->headers( {"","",s
} ); };
289 //! Shows no. of found kanji results in label.
290 inline void set_kanji_results ( const string
&s
) {
291 buffer_
["kanji_results"] = s
;
292 // XXX: ugly hack, but l_knj_results is invisibile if
293 // label(buffer_["kanji_results"].c_str()) of any other
294 // widget is not called ...
295 main_window_
->knj_view_
->label( buffer_
["kanji_results"].c_str() );
296 main_window_
->knj_view_
->label("");
297 main_window_
->l_knj_results
->label( buffer_
["kanji_results"].c_str() );
300 //! Shows <i>Manage database</i> dialog.
301 inline ManageDBDialog
*dlg_manage_db (){
302 center_window( dlg_manage_db_
, main_window_
);
303 return dlg_manage_db_
;
307 * Copy userdata to clipboard and selection buffer (middle button on Linux).
309 static void scb_copy ( Fl_Widget
*w
, void *userdata
) {
310 const char *d
= (const char*)userdata
;
312 Fl::copy( d
, len
, 0);
313 Fl::copy( d
, len
, 1);
317 //! Change cursor to WAIT (hourglass).
318 inline void cursor_wait () { change_cursor(FL_CURSOR_WAIT
); };
319 //! Change cursor to default (arrow).
320 inline void cursor_default () { change_cursor(); }
322 inline bool sort_components_by_strokes () const {
323 return main_window_
->cb_knj_components
->value();
326 //! Shows <i>Font</i> dialog.
328 center_window( dlg_fonts_
);
329 return dlg_fonts_
->run();
332 //! Shows <i>Romanization test</i> dialog.
333 void show_romanization_test ()
335 DialogRomanizationTest
*d
= new DialogRomanizationTest();
339 //! Shows dialog <i>Settings</i>.
340 void show_settings ();
343 * Popus menu (context) menu in DicView.
344 * \param did JMdict id of the word.
345 * \param things List of kanji in the word.
346 * \param notes If false then item <i>Notes</i> will be grayed out.
347 * \param examples If false then item <i>Examples</i> will be grayed out.
349 void dicview_menu ( int did
, const vector
<string
> &things
, bool notes
=false, bool examples
=false );
352 void edit_word ( const aoi::DicWord
&w
);
354 //! Popups KanjiPopupWindow in KanjiView.
355 void popup_kanji ( const Kanji
&k
);
357 // interface for App (controller)
358 inline void help_file ( const string
&s
) { help_file_
= s
; };
359 inline void fontname_kanji ( const string
&s
)
360 { fontname_kanji_
=s
; init_fonts(); };
361 inline void font_base_size ( int s
)
362 { font_base_size_
=s
; init_fonts(); };
363 inline string
skip () const { return main_window_
->e_skip
->value(); };
364 inline int sort_mode () const { return main_window_
->knj_orderby_
->value(); };
365 inline const char *strokes () const { return main_window_
->e_strokes
->value(); };
366 inline const char *jlpt () const { return main_window_
->e_jlpt
->value(); };
367 inline const char *grade () const { return main_window_
->e_grade
->value(); };
368 inline vector
<string
> components_include () const
369 { return main_window_
->compo_view_
->selected1(); };
370 inline vector
<string
> components_exclude () const
371 { return main_window_
->compo_view_
->selected2(); };
372 inline void highlight_components ( const string
&comps
)
373 { main_window_
->compo_view_
->set_highlight(comps
); }
376 Fl_Native_File_Chooser fnfc
;
377 fnfc
.title("Pick a file");
378 fnfc
.type(Fl_Native_File_Chooser::BROWSE_FILE
);
379 switch ( fnfc
.show() ) {
381 throw std::runtime_error( fnfc
.errmsg() );
386 return fnfc
.filename();
389 vector
<string
> listview_filters ();
391 inline int dicview_selected_rowid () const
392 { return main_window_
->dic_view_
->selected_row_id(); };
394 inline void set_components ( const vector
<ComponentView::Cell
> &v
)
395 { main_window_
->compo_view_
->set_data(v
); };
397 inline void set_listview ( const vector
<string
> &d
, const vector
<int> &r
={} )
398 { main_window_
->dic_view_
->set_data(d
,r
); };
399 inline void register_tag_dicview ( const string
&tag
, const TextStyle
&style
)
400 { main_window_
->dic_view_
->register_tag(tag
,style
); };
402 inline void set_kanjiview ( const vector
<KanjiView::Cell
> &d
)
403 { main_window_
->knj_view_
->set_data(d
); };
405 inline const char *get_dic_input () const
406 { return main_window_
->dic_input_
->value(); };
409 void cb_toggle_group ();
410 void cb_knj_clear ();
411 void cb_show_help (){
412 dlg_help_
->load(help_file_
.c_str());
415 void cb_jis208_toggle ();
417 // static callbacks - wrappers for real callbacks
418 inline static void scb_knj_clear ( Fl_Widget
*w
, void *f
)
419 {((GUI
*)f
)->cb_knj_clear(); }
420 inline static void scb_toggle_group(Fl_Widget
*w
, void *f
)
421 {((GUI
*)f
)->cb_toggle_group();};
422 inline static void scb_show_help(Fl_Widget
*w
, void *f
)
423 {((GUI
*)f
)->cb_show_help();};
424 inline static void scb_jis208_toggle(Fl_Widget
*w
, void *f
)
425 {((GUI
*)f
)->cb_jis208_toggle();};
426 inline static void scb_test_romanization ( Fl_Widget
*w
, void *p
)
427 {((GUI
*)p
)->show_romanization_test(); }
428 inline static void scb_test_fonts ( Fl_Widget
*w
, void *p
)
429 {((GUI
*)p
)->select_font(); }
430 inline static void scb_show_settings ( Fl_Widget
*w
, void *p
)
431 {((GUI
*)p
)->show_settings(); }