4 Website: http://www.vultaire.net/software/jben/
5 License: GNU General Public License (GPL) version 2
6 (http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>
24 #include "frame_maingui.h"
27 #include "wx/msgdlg.h"
28 #include "file_utils.h"
30 #include "frame_kanjipad.h"
31 #include "encoding_convert.h"
38 ID_menuFileQuit
=wxID_EXIT
,
39 ID_menuHelpAbout
=wxID_ABOUT
,
41 ID_menuKanjiAddFromFile
=1,
42 ID_menuKanjiAddByGrade
,
43 ID_menuKanjiAddByFreq
,
44 ID_menuKanjiSaveToFile
,
45 ID_menuKanjiClearList
,
49 ID_menuKanjiSortByGrade
,
50 ID_menuKanjiSortByFreq
,
51 ID_menuKanjiSearchKanjiPad
,
59 BEGIN_EVENT_TABLE(FrameMainGUI
, wxFrame
)
60 EVT_CLOSE(FrameMainGUI::OnClose
)
62 EVT_MENU(ID_menuFileQuit
, FrameMainGUI::OnFileQuit
)
64 EVT_MENU(ID_menuKanjiAddFromFile
, FrameMainGUI::OnKanjiAddFromFile
)
65 EVT_MENU(ID_menuKanjiAddByGrade
, FrameMainGUI::OnKanjiAddByGrade
)
66 EVT_MENU(ID_menuKanjiAddByFreq
, FrameMainGUI::OnKanjiAddByFreq
)
67 EVT_MENU(ID_menuKanjiSaveToFile
, FrameMainGUI::OnKanjiSaveToFile
)
68 EVT_MENU(ID_menuKanjiClearList
, FrameMainGUI::OnKanjiClearList
)
70 EVT_MENU(ID_menuKanjiDumpList
, FrameMainGUI::OnKanjiDumpList
)
72 EVT_MENU(ID_menuKanjiSortByGrade
, FrameMainGUI::OnKanjiSortByGrade
)
73 EVT_MENU(ID_menuKanjiSortByFreq
, FrameMainGUI::OnKanjiSortByFreq
)
74 EVT_MENU(ID_menuKanjiSearchKanjiPad
, FrameMainGUI::OnKanjiSearchKanjiPad
)
76 EVT_MENU(ID_menuHelpAbout
, FrameMainGUI::OnHelpAbout
)
77 EVT_MENU(ID_menuHelpLicense
, FrameMainGUI::OnHelpLicense
)
79 EVT_NOTEBOOK_PAGE_CHANGING(ID_tabsMain
, FrameMainGUI::OnTabChanging
)
80 EVT_NOTEBOOK_PAGE_CHANGED (ID_tabsMain
, FrameMainGUI::OnMajorTabChanged
)
81 EVT_NOTEBOOK_PAGE_CHANGING(ID_tabsKanji
, FrameMainGUI::OnTabChanging
)
82 EVT_NOTEBOOK_PAGE_CHANGED (ID_tabsKanji
, FrameMainGUI::OnMinorTabChanged
)
83 EVT_NOTEBOOK_PAGE_CHANGING(ID_tabsWords
, FrameMainGUI::OnTabChanging
)
84 EVT_NOTEBOOK_PAGE_CHANGED (ID_tabsWords
, FrameMainGUI::OnMinorTabChanged
)
85 EVT_NOTEBOOK_PAGE_CHANGING(ID_tabsConfig
, FrameMainGUI::OnTabChanging
)
86 EVT_NOTEBOOK_PAGE_CHANGED (ID_tabsConfig
, FrameMainGUI::OnMinorTabChanged
)
90 FrameMainGUI::FrameMainGUI() : wxFrame
92 _T(PROGRAM_NAME
" v" VERSION_STR
" by " AUTHOR_NAME
),
93 wxDefaultPosition
, wxSize(600,400)) {
94 this->SetIcon(wxICON(iconJben
));
95 wxInitAllImageHandlers(); /* This is needed for PNG support - GIFs seem to
96 load fine without it. */
98 /* Don't create these objects until/unless needed. */
99 dialogAddKanjiByFreq
= NULL
;
100 dialogAddKanjiByGrade
= NULL
;
103 wxMenu
*menu
, *subMenu
;
106 menuBar
= new wxMenuBar
;
109 menu
->Append(ID_menuFileQuit
, _T("E&xit..."));
110 menuBar
->Append(menu
, _T("&File"));
113 kanjiMenu
= new wxMenu
;
114 /* Submenu: Search for Kanji (probably a temporary menu, for now) */
115 subMenu
= new wxMenu
;
116 subMenu
->Append(ID_menuKanjiSearchKanjiPad
, _T("By &Handwriting"));
117 kanjiMenu
->AppendSubMenu(subMenu
, _T("&Find Kanji"));
118 /* Submenu: Add Kanji to List */
119 subMenu
= new wxMenu
;
120 subMenu
->Append(ID_menuKanjiAddFromFile
, _T("&From File..."));
121 subMenu
->Append(ID_menuKanjiAddByGrade
, _T("By Jouyou &Grade Level..."));
122 subMenu
->Append(ID_menuKanjiAddByFreq
,
123 _T("By Newspaper F&requency Ranking..."));
124 kanjiMenu
->AppendSubMenu(subMenu
, _T("&Add Kanji to List"));
125 /* Submenu: Sort Kanji in List*/
126 subMenu
= new wxMenu
;
127 subMenu
->Append(ID_menuKanjiSortByGrade
, _T("By Jouyou &Grade Level"));
128 subMenu
->Append(ID_menuKanjiSortByFreq
,
129 _T("By Newspaper F&requency Ranking"));
130 kanjiMenu
->AppendSubMenu(subMenu
, _T("S&ort Kanji in List"));
131 /* Other Kanji Menu options */
132 kanjiMenu
->Append(ID_menuKanjiSaveToFile
,
133 _T("&Save Kanji List to File..."));
134 if(jben
->kanjiList
->Size()==0)
135 kanjiMenu
->Enable(ID_menuKanjiSaveToFile
, false);
136 kanjiMenu
->AppendSeparator();
137 kanjiMenu
->Append(ID_menuKanjiClearList
,
138 _T("&Clear Kanji List"));
139 if(jben
->kanjiList
->Size()==0)
140 kanjiMenu
->Enable(ID_menuKanjiClearList
, false);
142 kanjiMenu
->Append(ID_menuKanjiDumpList
, _T("&Dump Kanji List to Console"));
144 menuBar
->Append(kanjiMenu
, _T("&Kanji"));
147 menu
->Append(ID_menuHelpAbout
, _T("&About..."));
148 menu
->Append(ID_menuHelpLicense
, _T("&License Information..."));
149 menuBar
->Append(menu
, _T("&Help"));
153 tabsMain
= new wxNotebook(this,
154 ID_tabsMain
,wxDefaultPosition
,
155 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_TOP
);
157 tabsKanji
= new wxNotebook(tabsMain
,
158 ID_tabsKanji
,wxDefaultPosition
,
159 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_TOP
);
160 tabsWords
= new wxNotebook(tabsMain
,
161 ID_tabsWords
,wxDefaultPosition
,
162 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_TOP
);
163 tabsConfig
= new wxNotebook(tabsMain
,
164 ID_tabsConfig
,wxDefaultPosition
,
165 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_TOP
);
167 tabsKanji
= new wxNotebook(tabsMain
,
168 ID_tabsKanji
,wxDefaultPosition
,
169 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_LEFT
);
170 tabsWords
= new wxNotebook(tabsMain
,
171 ID_tabsWords
,wxDefaultPosition
,
172 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_LEFT
);
173 tabsConfig
= new wxNotebook(tabsMain
,
174 ID_tabsConfig
,wxDefaultPosition
,
175 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_LEFT
);
177 tabsMain
->AddPage(tabsKanji
,_T("Kanji"),true);
178 tabsMain
->AddPage(tabsWords
,_T("Words"),false);
179 tabsMain
->AddPage(tabsConfig
,_T("Configuration"),false);
180 tabMajor
= (wxNotebookPage
*) tabsKanji
;
182 panelKanjiDict
= new PanelKanjiDict(tabsKanji
);
183 panelKanjiDrill
= new PanelKanjiDrill(tabsKanji
);
184 panelKanjiListEditor
= new PanelKanjiListEditor(tabsKanji
);
185 tabsKanji
->AddPage(panelKanjiDict
,_T("Dictionary"),true);
186 tabsKanji
->AddPage(panelKanjiDrill
,_T("Practice"),false);
187 tabsKanji
->AddPage(panelKanjiListEditor
,_T("Study List"),false);
188 tabMinor
= (wxNotebookPage
*) panelKanjiDict
;
190 panelWordDict
= new PanelWordDict(tabsWords
);
191 /* ADVANCED IDEA: Use radical database to create a multi-choice test option
192 for vocab and kanji. That is, like on the JLPT for reading/writing
193 Kanji, use kanji which share one or more radicals or readings as
194 alternate options when possible. (Without this, panelVocabTest seems
195 somewhat pointless at this time.) */
196 panelVocabListEditor
= new PanelVocabListEditor(tabsWords
);
197 tabsWords
->AddPage(panelWordDict
,_T("Dictionary"),true);
198 tabsWords
->AddPage(panelVocabListEditor
,_T("Study List"),false);
200 panelConfig
= new PanelConfig(tabsConfig
);
201 tabsConfig
->AddPage(panelConfig
,_T("Main Options"),true);
204 void FrameMainGUI::OnFileQuit(wxCommandEvent
& event
) {
208 void FrameMainGUI::OnKanjiAddFromFile(wxCommandEvent
& event
) {
209 /* NOTE: We may add the flag wxFD_CHANGE_DIR later, if we add in code
210 to save the full path for the jben.cfg file. */
211 wxFileDialog
*fd
= new wxFileDialog(
212 this, _T("Open File"), wxEmptyString
, wxEmptyString
, _T("*"),
213 wxFD_OPEN
| wxFD_FILE_MUST_EXIST
| wxFD_MULTIPLE
);
214 if(fd
->ShowModal()==wxID_OK
) {
215 wxArrayString filenames
;
216 wstring file
, allFiles
;
217 fd
->GetPaths(filenames
);
218 for(unsigned int i
=0;i
<filenames
.Count();i
++) {
220 utfconv_wm(filenames
[i
].c_str()).c_str(),
222 allFiles
.append(file
);
224 int result
= jben
->kanjiList
->AddFromString(allFiles
);
226 wxMessageBox(wxString::Format(
227 _T("Added %d kanji to the list."), result
),
228 _T("Add Kanji From File"), wxOK
| wxICON_INFORMATION
, this);
233 void FrameMainGUI::OnKanjiAddByGrade(wxCommandEvent
& event
) {
234 if(!dialogAddKanjiByGrade
)
235 dialogAddKanjiByGrade
= new DialogAddKanjiByGrade(this);
236 int result
= dialogAddKanjiByGrade
->ShowModal();
237 if(result
==wxID_OK
) {
238 /*printf("Selected grades: %d to %d\n",
239 dialogAddKanjiByGrade->GetLowGrade(),
240 dialogAddKanjiByGrade->GetHighGrade()
242 result
= jben
->kanjiList
->AddByGrade(
243 dialogAddKanjiByGrade
->GetLowGrade(),
244 dialogAddKanjiByGrade
->GetHighGrade());
246 wxMessageBox(wxString::Format(
247 _T("Added %d kanji to the list."), result
),
248 _T("Add Kanji by Jouyou Grade"), wxOK
| wxICON_INFORMATION
, this);
249 } else if(result
==wxID_CANCEL
) {
250 /*printf("Cancel event occurred within dialog!\n");*/
253 else printf("Unknown key (%08X) pressed within dialog!\n", result
);
257 void FrameMainGUI::OnKanjiAddByFreq(wxCommandEvent
& event
) {
258 if(!dialogAddKanjiByFreq
)
259 dialogAddKanjiByFreq
= new DialogAddKanjiByFreq(this);
260 int result
= dialogAddKanjiByFreq
->ShowModal();
261 if(result
==wxID_OK
) {
262 /*printf("Selected frequencies: %d to %d\n",
263 dialogAddKanjiByFreq->GetLowFreq(),
264 dialogAddKanjiByFreq->GetHighFreq()
266 result
= jben
->kanjiList
->AddByFrequency(
267 dialogAddKanjiByFreq
->GetLowFreq(),
268 dialogAddKanjiByFreq
->GetHighFreq());
270 wxMessageBox(wxString::Format(
271 _T("Added %d kanji to the list."), result
),
272 _T("Add Kanji by Frequency"), wxOK
| wxICON_INFORMATION
, this);
273 } else if(result
==wxID_CANCEL
) {
277 else printf("Unknown key (%08X) pressed within dialog!\n", result
);
281 void FrameMainGUI::OnKanjiSaveToFile(wxCommandEvent
& event
) {
282 /* NOTE: We may add the flag wxFD_CHANGE_DIR later, if we add in code
283 to save the full path for the jben.cfg file. */
284 wxFileDialog
*fd
= new wxFileDialog(
285 this, _T("Save Kanji List to File"), wxEmptyString
, wxEmptyString
,
286 _T("*"), wxFD_SAVE
| wxFD_OVERWRITE_PROMPT
);
287 if(fd
->ShowModal()==wxID_OK
) {
288 wxString kanjiList
= jben
->kanjiList
->ToString(20);
289 wxString filename
= fd
->GetPath();
290 /* Open file/write to file/close file */ /* TO DO */
291 wxFFile
f(filename
, _T("w"));
293 f
.Write(kanjiList
, *wxConvCurrent
);
300 void FrameMainGUI::OnKanjiClearList(wxCommandEvent
& event
) {
301 jben
->kanjiList
->Clear();
306 void FrameMainGUI::OnKanjiDumpList(wxCommandEvent
& event
) {
307 printf("Current kanji list: %ls\n", jben
->kanjiList
->ToString().c_str());
311 void FrameMainGUI::OnHelpAbout(wxCommandEvent
& event
) {
313 PROGRAM_NAME
" v" VERSION_STR
315 "\nCopyright " COPYRIGHT_DATE
"\n\n"
317 "Inspired in large by JWPce and JFC by Glenn Rosenthal:\n"
318 "http://www.physics.ucla.edu/~grosenth/\n\n"
320 "Powered by Monash University's EDICT2 and KANJIDIC:\n"
321 "http://www.csse.monash.edu.au/~jwb/edict_doc.html\n"
322 "http://www.csse.monash.edu.au/~jwb/kanjidic.html\n\n"
324 "Built using wxWidgets: http://www.wxwidgets.org/\n\n"
326 "Hand writing recognition is based upon code from im-ja:\n"
327 "http://im-ja.sourceforge.net/\n"
328 "Which uses code based upon KanjiPad by Owen Taylor:\n"
329 "http://fishsoup.net/software/kanjipad/\n\n"
331 "See \"Help->License Information...\" for important license details."),
332 _T("About " PROGRAM_NAME
), wxOK
| wxICON_INFORMATION
, this);
335 void FrameMainGUI::OnHelpLicense(wxCommandEvent
& event
) {
337 "Program distributed under the GNU General Public License (GPL) version 2:\n"
338 "http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt\n\n"
339 "EDICT2 and KANJIDIC distributed under a separate license specified at\n"
340 "http://www.csse.monash.edu.au/~jwb/edrdg/license.htm\n\n"
342 "The SKIP (System of Kanji Indexing by Patterns) system for ordering kanji "
343 "was developed by Jack Halpern (Kanji Dictionary Publishing Society at "
344 "http://www.kanji.org/), and is used with his permission.\n\n"
346 "Copies of the GNU General Public License, Monash University's license for "
347 "the dictionary files and documentation for the dictionary files are "
348 "contained in this program's \"license\" directory."),
349 _T("License Information"), wxOK
| wxICON_INFORMATION
, this);
352 void FrameMainGUI::OnMajorTabChanged(wxNotebookEvent
& event
) {
354 printf("DEBUG: OnMAJORTabChanged called.\n");
356 tabMajor
= (wxNotebookPage
*) tabsMain
->GetPage(event
.GetSelection());
357 tabMinor
= ((wxNotebook
*)tabMajor
)->GetCurrentPage();
359 printf("tabMajor = %p, tabMinor = %p\n", tabMajor
, tabMinor
);
364 void FrameMainGUI::OnMinorTabChanged(wxNotebookEvent
& event
) {
366 printf("DEBUG: OnMinorTabChanged called.\n");
368 wxNotebook
*nb
= (wxNotebook
*) tabsMain
->GetCurrentPage();
370 tabMinor
= (wxNotebookPage
*) nb
->GetPage(event
.GetSelection());
371 } else tabMinor
= NULL
;
373 printf("tabMajor = %p, tabMinor = %p\n", tabMajor
, tabMinor
);
378 /* This is the handler code for our tab changes.
379 It's called by both OnTabChanging functions.
380 Returns true if the tab change should take place, and false if it
382 bool FrameMainGUI::TabChangeHandler(wxNotebookPage
*page
) {
384 if(page
== panelConfig
) {
385 if(panelConfig
->ChangeDetected()) {
386 result
= wxMessageBox(
387 _T("You have made changes to your configuration. Do you want "
389 _T("Unsaved Changes Detected!"),
390 wxYES_NO
| wxCANCEL
| wxICON_QUESTION
, this);
392 panelConfig
->Commit();
393 } else if(result
==wxNO
) {
394 panelConfig
->Revert();
395 } else if(result
==wxCANCEL
) {
400 else if(page
== panelKanjiListEditor
) {
401 if(panelKanjiListEditor
->ChangeDetected()) {
402 result
= wxMessageBox(
403 _T("You have made changes to the kanji list. Do you want to "
405 _T("Unsaved Changes Detected!"),
406 wxYES_NO
| wxCANCEL
| wxICON_QUESTION
, this);
408 panelKanjiListEditor
->Commit();
409 } else if(result
==wxNO
) {
410 panelKanjiListEditor
->Revert();
411 } else if(result
==wxCANCEL
) {
416 else if(page
== panelVocabListEditor
) {
417 if(panelVocabListEditor
->ChangeDetected()) {
418 result
= wxMessageBox(
419 _T("You have made changes to the vocab list. Do you want to "
421 _T("Unsaved Changes Detected!"),
422 wxYES_NO
| wxCANCEL
| wxICON_QUESTION
, this);
424 panelVocabListEditor
->Commit();
425 } else if(result
==wxNO
) {
426 panelVocabListEditor
->Revert();
427 } else if(result
==wxCANCEL
) {
432 else if(page
== panelKanjiDrill
) {
433 if(panelKanjiDrill
->TestInProgress()) {
435 wxMessageBox(_T("A test is in progress. Switching tabs will "
436 "abort the test. Are you sure you want to do "
438 _T("Test in progress!"), wxYES_NO
| wxICON_EXCLAMATION
, this);
440 panelKanjiDrill
->Stop();
449 void FrameMainGUI::OnTabChanging(wxNotebookEvent
& event
) {
450 int index
= event
.GetOldSelection();
451 if(index
==-1) return;
453 if(!TabChangeHandler(tabMinor
)) event
.Veto();
456 void FrameMainGUI::OnKanjiSortByGrade(wxCommandEvent
& ev
) {
457 jben
->kanjiList
->Sort(ST_GRADE
);
461 void FrameMainGUI::OnKanjiSortByFreq(wxCommandEvent
& ev
) {
462 jben
->kanjiList
->Sort(ST_FREQUENCY
);
466 void FrameMainGUI::OnKanjiSearchKanjiPad(wxCommandEvent
& ev
) {
467 /* Multiple instances are allowed - just spin off an instance. */
468 FrameKanjiPad
*kanjiPad
=
469 new FrameKanjiPad(this, -1, _T("J-Ben: KanjiPad"));
473 void FrameMainGUI::Redraw() {
474 bool state
= (jben
->kanjiList
->Size()>0);
475 kanjiMenu
->Enable(ID_menuKanjiSaveToFile
, state
);
476 kanjiMenu
->Enable(ID_menuKanjiClearList
, state
);
479 ((RedrawablePanel
*)tabMinor
)->Redraw();
483 void FrameMainGUI::OnClose(wxCloseEvent
& event
) {
484 if(!event
.CanVeto()) {
486 fprintf(stderr
, "event.CanVeto() returned false!\n");
490 /* Check for active kanji drill */
491 if(tabsMain
->GetCurrentPage()==panelKanjiDrill
&&
492 panelKanjiDrill
->TestInProgress()) {
494 wxMessageBox(_T("A test is in progress. Are you sure you want to "
496 _T("Test in progress!"), wxYES_NO
| wxICON_EXCLAMATION
, this);
498 panelKanjiDrill
->Stop();
505 /* Everything is okay - close the program. */