RunyuWindow.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * This file is part of Runyu.
  3. *
  4. * Runyu 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.
  8. *
  9. * Runyu 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.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with Runyu. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "RunyuWindow.h"
  18. #include "WordListFile.h"
  19. #include <Application.h>
  20. #include <Locale.h>
  21. #include <File.h>
  22. #include <ControlLook.h>
  23. #include <GridView.h>
  24. #include <GroupView.h>
  25. #include <Menu.h>
  26. #include <MenuBar.h>
  27. #include <MenuItem.h>
  28. #include <GroupLayout.h>
  29. #include <TextControl.h>
  30. #include <Button.h>
  31. #include <LocaleRoster.h>
  32. #include <Roster.h>
  33. #include <String.h>
  34. #include <Font.h>
  35. #include <Alert.h>
  36. #include <Entry.h>
  37. #include <Directory.h>
  38. #include <Url.h>
  39. RunyuWindow::RunyuWindow(BRect frame, const char* title)
  40. : BWindow(frame, title, B_TITLED_WINDOW,
  41. B_NOT_ZOOMABLE | B_AVOID_FRONT, B_ALL_WORKSPACES | B_QUIT_ON_WINDOW_CLOSE | B_CLOSE_ON_ESCAPE)
  42. {
  43. // Create window view & layout
  44. BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 0);
  45. SetLayout(layout);
  46. // Add menubar
  47. BMenuBar *menuBar = new BMenuBar("menu");
  48. layout->AddView(menuBar);
  49. // File menu
  50. BMenu* fileMenu = new BMenu("File");
  51. fileMenu->AddItem(new BMenuItem("Update Dictionary",
  52. new BMessage(kMsgUpdateDictionary), 'U'));
  53. fileMenu->AddSeparatorItem();
  54. fileMenu->AddItem(new BMenuItem("Quit",
  55. new BMessage(B_QUIT_REQUESTED), 'Q'));
  56. menuBar->AddItem(fileMenu);
  57. // Help menu
  58. BMenu* helpMenu = new BMenu("Help");
  59. helpMenu->AddItem(new BMenuItem("Learn Na'vi",
  60. new BMessage(kMsgLearnNavi)));
  61. helpMenu->AddItem(new BMenuItem("About Runyu",
  62. new BMessage(kMsgAboutRunyu)));
  63. menuBar->AddItem(helpMenu);
  64. fLayout = new BGroupLayout(B_VERTICAL);
  65. fLayout->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
  66. B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
  67. fLayout->SetSpacing(B_USE_DEFAULT_SPACING);
  68. BView* fview = new BView("view", 0, fLayout);
  69. fview->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
  70. layout->AddView(fview);
  71. // Draw the top box with word input and button.
  72. BGroupView* searchLayout = new BGroupView(B_HORIZONTAL);
  73. searchInput = new BTextControl("search", "Word:", " ", NULL);
  74. BButton* searchButton = new BButton("search",
  75. "Search", new BMessage(kMessageSearch));
  76. searchLayout->GroupLayout()->AddItem(searchInput->CreateLabelLayoutItem());
  77. searchLayout->GroupLayout()->AddItem(searchInput->CreateTextViewLayoutItem());
  78. searchLayout->GroupLayout()->AddView(searchButton);
  79. fLayout->AddView(searchLayout);
  80. results = new BTextView("results");
  81. results->MakeEditable(false);
  82. results->MakeSelectable(true);
  83. results->SetStylable(true);
  84. results->SetInsets(10, 10, 10, 10);
  85. fLayout->AddView(results);
  86. // Focus the searchInput dealio
  87. searchInput->MakeFocus(true);
  88. searchInput->SetText("");
  89. }
  90. RunyuWindow::~RunyuWindow()
  91. {
  92. }
  93. bool
  94. RunyuWindow::QuitRequested()
  95. {
  96. be_app->PostMessage(B_QUIT_REQUESTED);
  97. Hide();
  98. return true;
  99. }
  100. void
  101. RunyuWindow::MessageReceived(BMessage* message)
  102. {
  103. switch (message->what) {
  104. case kMessageSearch:
  105. {
  106. _SearchForWord(searchInput->Text());
  107. break;
  108. }
  109. case kMsgLearnNavi:
  110. {
  111. //BUrl learnnavi("https://learnnavi.org/");
  112. //learnnavi.OpenWithPreferredApplication();
  113. // Is there a nicer way to do this?
  114. entry_ref ref;
  115. if (get_ref_for_path("/bin/open", &ref))
  116. return;
  117. const char* args[] = { "/bin/open", "https://learnnavi.org/", NULL};
  118. be_roster->Launch(&ref, 2, args);
  119. break;
  120. }
  121. case kMsgAboutRunyu:
  122. {
  123. // This should use AboutWindow.h which is part of interface kit
  124. // however I can't figure how to get it compiled with the
  125. // #include <AboutWindow.h>
  126. break;
  127. }
  128. case kMsgUpdateDictionary:
  129. {
  130. be_app->MessageReceived(message);
  131. break;
  132. }
  133. default:
  134. {
  135. BWindow::MessageReceived(message);
  136. break;
  137. }
  138. }
  139. }
  140. void
  141. RunyuWindow::_SearchForWord(const char* word)
  142. {
  143. BString searchTerm(word);
  144. // Get preferred language
  145. BMessage preferredLanguages;
  146. BLocaleRoster::Default()->GetPreferredLanguages(&preferredLanguages);
  147. const char* firstLanguage;
  148. if (preferredLanguages.FindString("language", &firstLanguage) != B_OK) {
  149. firstLanguage = "en"; // Fallback to english
  150. }
  151. // Now open word list.
  152. BDirectory basePath("/boot/home/config/settings/Runyu/");
  153. const BEntry naviPath(&basePath, "nvi.words");
  154. const BEntry naviIpaPath(&basePath, "nvi.ipa");
  155. BString fileName(firstLanguage); fileName += ".words";
  156. const BEntry localPath(&basePath, fileName.String());
  157. // Check that both exist, if not display an error.
  158. if (!(localPath.Exists() && naviPath.Exists())) {
  159. BAlert* notFoundError = new BAlert("Dictionary Not Found",
  160. "The dictionaries have not been found so a search cannot run.",
  161. "OK",
  162. NULL,
  163. NULL,
  164. B_WIDTH_AS_USUAL,
  165. B_STOP_ALERT);
  166. notFoundError->SetShortcut(0, B_ESCAPE);
  167. notFoundError->Go();
  168. delete notFoundError;
  169. return;
  170. }
  171. // Put information that we're searching.
  172. results->SetText("Searching...");
  173. WordListFile naviDict = WordListFile(&naviPath);
  174. WordListFile naviIpa = WordListFile(&naviIpaPath);
  175. WordListFile localDict = WordListFile(&localPath);
  176. // Now search through both dictionaries looking for the word
  177. BString definition;
  178. BString ipa;
  179. bool foundWord = false;
  180. long long lineno;
  181. if ((lineno = naviDict.FindWord(searchTerm)) != -1) {
  182. foundWord = true;
  183. localDict.ReadLine(definition, lineno);
  184. ipa.SetTo("");
  185. _WriteDefinition(definition, ipa, searchTerm);
  186. }
  187. if ((lineno = localDict.FindWord(searchTerm)) != -1) {
  188. foundWord = true;
  189. naviDict.ReadLine(definition, lineno);
  190. naviIpa.ReadLine(ipa, lineno);
  191. _WriteDefinition(definition, ipa, searchTerm);
  192. }
  193. if (!foundWord) {
  194. BString error(word);
  195. error += " can't be found in the dictionary.";
  196. error.Capitalize();
  197. results->SetText(error.String());
  198. }
  199. }
  200. void
  201. RunyuWindow::_WriteDefinition(BString& definition, BString& ipa, BString& meaning)
  202. {
  203. results->SetText("");
  204. definition.Capitalize();
  205. // Write out definition.
  206. BFont font;
  207. font.SetSize(20.0);
  208. text_run run;
  209. run.font = font;
  210. run.offset = 0;
  211. run.color.red = 0;
  212. run.color.green = 0;
  213. run.color.blue = 0;
  214. run.color.alpha = 255;
  215. text_run_array runArray;
  216. runArray.count = 1;
  217. runArray.runs[0] = run;
  218. results->Insert(definition.String(), &runArray);
  219. // Add IPA
  220. results->Insert(" ");
  221. runArray.runs[0].font.SetFace(B_ITALIC_FACE);
  222. runArray.runs[0].color.red = 187;
  223. runArray.runs[0].color.green = 187;
  224. runArray.runs[0].color.blue = 187;
  225. results->Insert("(", &runArray);
  226. results->Insert(ipa, &runArray);
  227. results->Insert(")", &runArray);
  228. // Add the meaning
  229. results->Insert("\n\t");
  230. runArray.runs[0].color.red = 0;
  231. runArray.runs[0].color.blue = 0;
  232. runArray.runs[0].color.green = 0;
  233. runArray.runs[0].font.SetFace(B_BOLD_FACE);
  234. runArray.runs[0].font.SetSize(12.0);
  235. results->Insert("Meaning: ", &runArray);
  236. runArray.runs[0].font.SetFace(B_REGULAR_FACE);
  237. results->Insert(meaning.String(), &runArray);
  238. }