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
;
107 menuBar
= new wxMenuBar
;
110 menu
->Append(ID_menuFileQuit
, _T("E&xit..."));
111 menuBar
->Append(menu
, _T("&File"));
114 kanjiMenu
= new wxMenu
;
115 /* Submenu: Search for Kanji (probably a temporary menu, for now) */
116 subMenu
= new wxMenu
;
117 subMenu
->Append(ID_menuKanjiSearchKanjiPad
, _T("By &Handwriting"));
118 kanjiMenu
->AppendSubMenu(subMenu
, _T("&Find Kanji"));
119 /* Submenu: Add Kanji to List */
120 subMenu
= new wxMenu
;
121 subMenu
->Append(ID_menuKanjiAddFromFile
, _T("&From File..."));
122 subMenu
->Append(ID_menuKanjiAddByGrade
, _T("By Jouyou &Grade Level..."));
123 subMenu
->Append(ID_menuKanjiAddByFreq
,
124 _T("By Newspaper F&requency Ranking..."));
125 kanjiMenu
->AppendSubMenu(subMenu
, _T("&Add Kanji to List"));
126 /* Submenu: Sort Kanji in List*/
127 subMenu
= new wxMenu
;
128 subMenu
->Append(ID_menuKanjiSortByGrade
, _T("By Jouyou &Grade Level"));
129 subMenu
->Append(ID_menuKanjiSortByFreq
,
130 _T("By Newspaper F&requency Ranking"));
131 kanjiMenu
->AppendSubMenu(subMenu
, _T("S&ort Kanji in List"));
132 /* Other Kanji Menu options */
133 kanjiMenu
->Append(ID_menuKanjiSaveToFile
,
134 _T("&Save Kanji List to File..."));
135 if(jben
->kanjiList
->Size()==0)
136 kanjiMenu
->Enable(ID_menuKanjiSaveToFile
, false);
137 kanjiMenu
->AppendSeparator();
138 kanjiMenu
->Append(ID_menuKanjiClearList
,
139 _T("&Clear Kanji List"));
140 if(jben
->kanjiList
->Size()==0)
141 kanjiMenu
->Enable(ID_menuKanjiClearList
, false);
143 kanjiMenu
->Append(ID_menuKanjiDumpList
, _T("&Dump Kanji List to Console"));
145 menuBar
->Append(kanjiMenu
, _T("&Kanji"));
148 menu
->Append(ID_menuHelpAbout
, _T("&About..."));
149 menu
->Append(ID_menuHelpLicense
, _T("&License Information..."));
150 menuBar
->Append(menu
, _T("&Help"));
154 tabsMain
= new wxNotebook(this,
155 ID_tabsMain
,wxDefaultPosition
,
156 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_TOP
);
158 tabsKanji
= new wxNotebook(tabsMain
,
159 ID_tabsKanji
,wxDefaultPosition
,
160 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_TOP
);
161 tabsWords
= new wxNotebook(tabsMain
,
162 ID_tabsWords
,wxDefaultPosition
,
163 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_TOP
);
164 tabsConfig
= new wxNotebook(tabsMain
,
165 ID_tabsConfig
,wxDefaultPosition
,
166 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_TOP
);
168 tabsKanji
= new wxNotebook(tabsMain
,
169 ID_tabsKanji
,wxDefaultPosition
,
170 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_LEFT
);
171 tabsWords
= new wxNotebook(tabsMain
,
172 ID_tabsWords
,wxDefaultPosition
,
173 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_LEFT
);
174 tabsConfig
= new wxNotebook(tabsMain
,
175 ID_tabsConfig
,wxDefaultPosition
,
176 wxDefaultSize
,wxCLIP_CHILDREN
| wxNB_LEFT
);
179 panelKanjiDict
= new PanelKanjiDict(tabsKanji
);
180 panelKanjiDrill
= new PanelKanjiDrill(tabsKanji
);
181 panelKanjiListEditor
= new PanelKanjiListEditor(tabsKanji
);
182 tabsKanji
->AddPage(panelKanjiDict
,_T("Dictionary"),true);
183 tabsKanji
->AddPage(panelKanjiDrill
,_T("Practice"),false);
184 tabsKanji
->AddPage(panelKanjiListEditor
,_T("Study List"),false);
186 panelWordDict
= new PanelWordDict(tabsWords
);
187 /* ADVANCED IDEA: Use radical database to create a multi-choice test option
188 for vocab and kanji. That is, like on the JLPT for reading/writing
189 Kanji, use kanji which share one or more radicals or readings as
190 alternate options when possible. (Without this, panelVocabTest seems
191 somewhat pointless at this time.) */
192 panelVocabListEditor
= new PanelVocabListEditor(tabsWords
);
193 tabsWords
->AddPage(panelWordDict
,_T("Dictionary"),true);
194 tabsWords
->AddPage(panelVocabListEditor
,_T("Study List"),false);
196 panelConfig
= new PanelConfig(tabsConfig
);
197 tabsConfig
->AddPage(panelConfig
,_T("Main Options"),true);
199 tabsMain
->AddPage(tabsWords
,_T("Words"),true);
200 tabsMain
->AddPage(tabsKanji
,_T("Kanji"),false);
201 tabsMain
->AddPage(tabsConfig
,_T("Configuration"),false);
203 tabMajor
= (wxNotebookPage
*) tabsWords
;
204 tabMinor
= (wxNotebookPage
*) panelWordDict
;
207 void FrameMainGUI::OnFileQuit(wxCommandEvent
& event
) {
211 void FrameMainGUI::OnKanjiAddFromFile(wxCommandEvent
& event
) {
212 /* NOTE: We may add the flag wxFD_CHANGE_DIR later, if we add in code
213 to save the full path for the jben.cfg file. */
214 wxFileDialog
*fd
= new wxFileDialog(
215 this, _T("Open File"), wxEmptyString
, wxEmptyString
, _T("*"),
216 wxFD_OPEN
| wxFD_FILE_MUST_EXIST
| wxFD_MULTIPLE
);
217 if(fd
->ShowModal()==wxID_OK
) {
218 wxArrayString filenames
;
219 wstring file
, allFiles
;
220 fd
->GetPaths(filenames
);
221 for(unsigned int i
=0;i
<filenames
.Count();i
++) {
223 utfconv_wm(filenames
[i
].c_str()).c_str(),
225 allFiles
.append(file
);
227 int result
= jben
->kanjiList
->AddFromString(allFiles
);
229 wxMessageBox(wxString::Format(
230 _T("Added %d kanji to the list."), result
),
231 _T("Add Kanji From File"), wxOK
| wxICON_INFORMATION
, this);
236 void FrameMainGUI::OnKanjiAddByGrade(wxCommandEvent
& event
) {
237 if(!dialogAddKanjiByGrade
)
238 dialogAddKanjiByGrade
= new DialogAddKanjiByGrade(this);
239 int result
= dialogAddKanjiByGrade
->ShowModal();
240 if(result
==wxID_OK
) {
241 result
= jben
->kanjiList
->AddByGrade(
242 dialogAddKanjiByGrade
->GetLowGrade(),
243 dialogAddKanjiByGrade
->GetHighGrade());
245 wxMessageBox(wxString::Format(
246 _T("Added %d kanji to the list."), result
),
247 _T("Add Kanji by Jouyou Grade"), wxOK
| wxICON_INFORMATION
, this);
248 } else if(result
==wxID_CANCEL
) {
252 else printf("Unknown key (%08X) pressed within dialog!\n", result
);
256 void FrameMainGUI::OnKanjiAddByFreq(wxCommandEvent
& event
) {
257 if(!dialogAddKanjiByFreq
)
258 dialogAddKanjiByFreq
= new DialogAddKanjiByFreq(this);
259 int result
= dialogAddKanjiByFreq
->ShowModal();
260 if(result
==wxID_OK
) {
261 result
= jben
->kanjiList
->AddByFrequency(
262 dialogAddKanjiByFreq
->GetLowFreq(),
263 dialogAddKanjiByFreq
->GetHighFreq());
265 wxMessageBox(wxString::Format(
266 _T("Added %d kanji to the list."), result
),
267 _T("Add Kanji by Frequency"), wxOK
| wxICON_INFORMATION
, this);
268 } else if(result
==wxID_CANCEL
) {
272 else printf("Unknown key (%08X) pressed within dialog!\n", result
);
276 void FrameMainGUI::OnKanjiSaveToFile(wxCommandEvent
& event
) {
277 /* NOTE: We may add the flag wxFD_CHANGE_DIR later, if we add in code
278 to save the full path for the jben.cfg file. */
279 wxFileDialog
*fd
= new wxFileDialog(
280 this, _T("Save Kanji List to File"), wxEmptyString
, wxEmptyString
,
281 _T("*"), wxFD_SAVE
| wxFD_OVERWRITE_PROMPT
);
282 if(fd
->ShowModal()==wxID_OK
) {
283 wxString kanjiList
= jben
->kanjiList
->ToString(20);
284 wxString filename
= fd
->GetPath();
285 /* Open file/write to file/close file */ /* TO DO */
286 wxFFile
f(filename
, _T("w"));
288 f
.Write(kanjiList
, *wxConvCurrent
);
295 void FrameMainGUI::OnKanjiClearList(wxCommandEvent
& event
) {
296 jben
->kanjiList
->Clear();
301 void FrameMainGUI::OnKanjiDumpList(wxCommandEvent
& event
) {
302 printf("Current kanji list: %ls\n", jben
->kanjiList
->ToString().c_str());
306 void FrameMainGUI::OnHelpAbout(wxCommandEvent
& event
) {
308 PROGRAM_NAME
" v" VERSION_STR
310 "\nCopyright " COPYRIGHT_DATE
"\n\n"
312 "Inspired in large by JWPce and JFC by Glenn Rosenthal:\n"
313 "http://www.physics.ucla.edu/~grosenth/\n\n"
315 "Powered by Monash University's EDICT2 and KANJIDIC:\n"
316 "http://www.csse.monash.edu.au/~jwb/edict_doc.html\n"
317 "http://www.csse.monash.edu.au/~jwb/kanjidic.html\n\n"
319 "Built using wxWidgets: http://www.wxwidgets.org/\n\n"
321 "Hand writing recognition is based upon code from im-ja:\n"
322 "http://im-ja.sourceforge.net/\n"
323 "Which uses code based upon KanjiPad by Owen Taylor:\n"
324 "http://fishsoup.net/software/kanjipad/\n\n"
326 "See \"Help->License Information...\" for important license details."),
327 _T("About " PROGRAM_NAME
), wxOK
| wxICON_INFORMATION
, this);
330 void FrameMainGUI::OnHelpLicense(wxCommandEvent
& event
) {
331 wxString licenseMessage
= _T(
332 "Program distributed under the GNU General Public License (GPL) version 2:\n"
333 "http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt\n\n"
334 "EDICT2 and KANJIDIC distributed under a separate license specified at\n"
335 "http://www.csse.monash.edu.au/~jwb/edrdg/license.htm\n\n"
337 "The SKIP (System of Kanji Indexing by Patterns) system for ordering kanji "
338 "was developed by Jack Halpern (Kanji Dictionary Publishing Society at "
339 "http://www.kanji.org/), and is used with his permission.\n\n"
341 "Copies of the GNU General Public License, Monash University's license for "
342 "the dictionary files and documentation for the dictionary files are "
343 "contained in this program's \"license\" directory.");
345 licenseMessage
.append(
346 _T(" (On this system, it should be located in\n"));
347 licenseMessage
.append(utfconv_mw(LICENSEDIR
));
348 licenseMessage
.append(_T(".)"));
350 wxMessageBox(licenseMessage
, _T("License Information"),
351 wxOK
| wxICON_INFORMATION
, this);
354 void FrameMainGUI::OnMajorTabChanged(wxNotebookEvent
& event
) {
356 printf("DEBUG: OnMAJORTabChanged called.\n");
358 tabMajor
= (wxNotebookPage
*) tabsMain
->GetPage(event
.GetSelection());
359 tabMinor
= ((wxNotebook
*)tabMajor
)->GetCurrentPage();
361 printf("tabMajor = %p, tabMinor = %p\n", tabMajor
, tabMinor
);
366 void FrameMainGUI::OnMinorTabChanged(wxNotebookEvent
& event
) {
368 printf("DEBUG: OnMinorTabChanged called.\n");
370 wxNotebook
*nb
= (wxNotebook
*) tabsMain
->GetCurrentPage();
372 tabMinor
= (wxNotebookPage
*) nb
->GetPage(event
.GetSelection());
373 } else tabMinor
= NULL
;
375 printf("tabMajor = %p, tabMinor = %p\n", tabMajor
, tabMinor
);
380 /* This is the handler code for our tab changes.
381 It's called by both OnTabChanging functions.
382 Returns true if the tab change should take place, and false if it
384 bool FrameMainGUI::TabChangeHandler(wxNotebookPage
*page
) {
386 if(page
== panelConfig
) {
387 if(panelConfig
->ChangeDetected()) {
388 result
= wxMessageBox(
389 _T("You have made changes to your configuration. Do you want "
391 _T("Unsaved Changes Detected!"),
392 wxYES_NO
| wxCANCEL
| wxICON_QUESTION
, this);
394 panelConfig
->Commit();
395 } else if(result
==wxNO
) {
396 panelConfig
->Revert();
397 } else if(result
==wxCANCEL
) {
402 else if(page
== panelKanjiListEditor
) {
403 if(panelKanjiListEditor
->ChangeDetected()) {
404 result
= wxMessageBox(
405 _T("You have made changes to the kanji list. Do you want to "
407 _T("Unsaved Changes Detected!"),
408 wxYES_NO
| wxCANCEL
| wxICON_QUESTION
, this);
410 panelKanjiListEditor
->Commit();
411 } else if(result
==wxNO
) {
412 panelKanjiListEditor
->Revert();
413 } else if(result
==wxCANCEL
) {
418 else if(page
== panelVocabListEditor
) {
419 if(panelVocabListEditor
->ChangeDetected()) {
420 result
= wxMessageBox(
421 _T("You have made changes to the vocab list. Do you want to "
423 _T("Unsaved Changes Detected!"),
424 wxYES_NO
| wxCANCEL
| wxICON_QUESTION
, this);
426 panelVocabListEditor
->Commit();
427 } else if(result
==wxNO
) {
428 panelVocabListEditor
->Revert();
429 } else if(result
==wxCANCEL
) {
434 else if(page
== panelKanjiDrill
) {
435 if(panelKanjiDrill
->TestInProgress()) {
437 wxMessageBox(_T("A test is in progress. Switching tabs will "
438 "abort the test. Are you sure you want to do "
440 _T("Test in progress!"), wxYES_NO
| wxICON_EXCLAMATION
, this);
442 panelKanjiDrill
->Stop();
451 void FrameMainGUI::OnTabChanging(wxNotebookEvent
& event
) {
452 int index
= event
.GetOldSelection();
453 if(index
==-1) return;
455 if(!TabChangeHandler(tabMinor
)) event
.Veto();
458 void FrameMainGUI::OnKanjiSortByGrade(wxCommandEvent
& ev
) {
459 jben
->kanjiList
->Sort(ST_GRADE
);
463 void FrameMainGUI::OnKanjiSortByFreq(wxCommandEvent
& ev
) {
464 jben
->kanjiList
->Sort(ST_FREQUENCY
);
468 void FrameMainGUI::OnKanjiSearchKanjiPad(wxCommandEvent
& ev
) {
469 /* Multiple instances are allowed - just spin off an instance. */
470 FrameKanjiPad
*kanjiPad
=
471 new FrameKanjiPad(this, -1, _T("J-Ben: KanjiPad"));
475 void FrameMainGUI::Redraw() {
476 bool state
= (jben
->kanjiList
->Size()>0);
477 kanjiMenu
->Enable(ID_menuKanjiSaveToFile
, state
);
478 kanjiMenu
->Enable(ID_menuKanjiClearList
, state
);
481 ((RedrawablePanel
*)tabMinor
)->Redraw();
485 void FrameMainGUI::OnClose(wxCloseEvent
& event
) {
486 if(!event
.CanVeto()) {
488 fprintf(stderr
, "event.CanVeto() returned false!\n");
492 /* Check for active kanji drill */
493 if(tabsMain
->GetCurrentPage()==panelKanjiDrill
&&
494 panelKanjiDrill
->TestInProgress()) {
496 wxMessageBox(_T("A test is in progress. Are you sure you want to "
498 _T("Test in progress!"), wxYES_NO
| wxICON_EXCLAMATION
, this);
500 panelKanjiDrill
->Stop();
507 /* Everything is okay - close the program. */