1 /*
2 * Copyright 2011 kubtek <kubtek@mail.com>
3 *
4 * This file is part of StarDict.
5 *
6 * StarDict is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * StarDict is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with StarDict. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <cstring>
25 #include <string>
26 #include <glib/gi18n.h>
27
28 #ifdef _WIN32
29 # include <gdk/gdkwin32.h>
30 #endif
31
32 #include "stardict.h"
33 #include "desktop.h"
34 #include "conf.h"
35 #include "lib/utils.h"
36 #include "iskeyspressed.h"
37
38 #include "floatwin.h"
39
FloatWin()40 FloatWin::FloatWin()
41 {
42 hide_window_timer = 0;
43 lookup_running_timer = 0;
44 now_window_width = 0;
45 now_window_height = 0;
46 button_box_once_shown = false;
47 ismoving = false;
48 menu = NULL;
49 content_state = ContentState_Empty;
50 have_real_content = false;
51 window_positioned = false;
52 IgnoreScanModifierKey = false;
53 }
54
Create()55 void FloatWin::Create()
56 {
57 FloatWindow = gtk_window_new(GTK_WINDOW_POPUP);
58 gtk_widget_set_events(FloatWindow, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK);
59 g_signal_connect (G_OBJECT (FloatWindow), "button_press_event", G_CALLBACK (vButtonPressCallback), this);
60 g_signal_connect (G_OBJECT (FloatWindow), "button_release_event", G_CALLBACK (vButtonReleaseCallback), this);
61 g_signal_connect (G_OBJECT (FloatWindow), "motion_notify_event", G_CALLBACK (vMotionNotifyCallback), this);
62 g_signal_connect (G_OBJECT (FloatWindow), "enter_notify_event", G_CALLBACK (vEnterNotifyCallback), this);
63 g_signal_connect (G_OBJECT (FloatWindow), "leave_notify_event", G_CALLBACK (vLeaveNotifyCallback), this);
64
65 GtkWidget *frame = gtk_frame_new(NULL);
66 gtk_frame_set_shadow_type(GTK_FRAME(frame),GTK_SHADOW_ETCHED_OUT);
67 gtk_container_add(GTK_CONTAINER(FloatWindow),frame);
68 GtkWidget *vbox;
69 #if GTK_MAJOR_VERSION >= 3
70 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
71 #else
72 vbox = gtk_vbox_new(false,0);
73 #endif
74 gtk_container_set_border_width (GTK_CONTAINER (vbox), FLOATWIN_BORDER_WIDTH);
75 gtk_container_add(GTK_CONTAINER(frame),vbox);
76
77 create_button_hbox();
78 gtk_box_pack_start(GTK_BOX(vbox),button_hbox,false,false,0);
79 view.reset(new ArticleView(GTK_BOX(vbox), (BookNameStyle)conf->get_int_at("dictionary/bookname_style"), true));
80
81 gtk_widget_show_all(frame);
82 gtk_widget_hide(button_hbox); //show all will show hbox's children,now hide hbox only.
83
84 set_bg();
85 set_transparent(conf->get_int_at("floating_window/transparent"));
86 restore_locked_position();
87
88 conf->notify_add("/apps/stardict/preferences/floating_window/lock",
89 sigc::mem_fun(this, &FloatWin::on_lock_changed));
90 conf->notify_add("/apps/stardict/preferences/dictionary/scan_selection",
91 sigc::mem_fun(this, &FloatWin::on_dict_scan_select_changed));
92 conf->notify_add("/apps/stardict/preferences/floating_window/lock_x",
93 sigc::mem_fun(this, &FloatWin::on_lock_x_changed));
94 conf->notify_add("/apps/stardict/preferences/floating_window/lock_y",
95 sigc::mem_fun(this, &FloatWin::on_lock_y_changed));
96 conf->notify_add("/apps/stardict/preferences/floating_window/transparent",
97 sigc::mem_fun(this, &FloatWin::on_transparent_changed));
98
99 conf->notify_add("/apps/stardict/preferences/floating_window/use_custom_bg",
100 sigc::mem_fun(this, &FloatWin::on_use_custom_bg_changed));
101 gtk_widget_realize(FloatWindow);
102 }
103
End()104 void FloatWin::End()
105 {
106 if (conf->get_bool_at("floating_window/lock")) {
107 gint x, y;
108 gtk_window_get_position(GTK_WINDOW(FloatWindow), &x, &y);
109 conf->set_int_at("floating_window/lock_x", x);
110 conf->set_int_at("floating_window/lock_y", y);
111 }
112
113 destroy_hide_window_timer();
114 if (menu)
115 gtk_widget_destroy(menu);
116 menu = NULL;
117 if (FloatWindow)
118 gtk_widget_destroy(FloatWindow);
119 FloatWindow = NULL;
120 content_state = ContentState_Empty;
121 have_real_content = false;
122 }
123
StartLookup(const char * sWord,bool IgnoreScanModifierKey)124 void FloatWin::StartLookup(const char* sWord, bool IgnoreScanModifierKey)
125 {
126 QueryingWord = sWord;
127 content_state = ContentState_Waiting;
128 /* Set the text telling that lookup is running, but do not show the window.
129 The window will be shown when a response arrives or when LOOKUP_RUNNING_TIMEOUT
130 elapses. */
131 const std::string markup = get_looking_up_markup(QueryingWord.c_str());
132 view->set_pango_text(markup.c_str());
133 set_busy_cursor();
134 have_real_content = false;
135 window_positioned = false;
136 this->IgnoreScanModifierKey = IgnoreScanModifierKey;
137 start_lookup_running_timer();
138 }
139
EndLookup(void)140 void FloatWin::EndLookup(void)
141 {
142 content_state = have_real_content ? ContentState_Found : ContentState_NotFound;
143 if(!have_real_content) {
144 const std::string markup = get_not_found_markup(QueryingWord.c_str(), _("<Not Found!>"));
145 view->set_pango_text(markup.c_str());
146 if (conf->get_bool_at("floating_window/show_if_not_found")) {
147 Popup(!window_positioned);
148 window_positioned = true;
149 }
150 }
151 set_normal_cursor();
152 destroy_lookup_running_timer();
153 }
154
AppendTextLocalDict(gchar *** Word,gchar **** WordData,const gchar * sOriginWord)155 void FloatWin::AppendTextLocalDict(gchar ***Word, gchar ****WordData, const gchar *sOriginWord)
156 {
157 view->begin_update();
158 if(!have_real_content)
159 view->clear();
160 const std::string mark = get_head_word_markup(sOriginWord);
161 view->append_pango_text(mark.c_str());
162 int j,k;
163 for (size_t i=0; i<gpAppFrame->scan_dictmask.size(); i++) {
164 if (Word[i]) {
165 view->AppendNewline();
166 view->SetDictIndex(gpAppFrame->scan_dictmask[i]);
167 if (gpAppFrame->scan_dictmask[i].type == InstantDictType_LOCAL)
168 view->AppendHeader(gpAppFrame->oLibs.dict_name(gpAppFrame->scan_dictmask[i].index).c_str());
169 else if (gpAppFrame->scan_dictmask[i].type == InstantDictType_VIRTUAL)
170 view->AppendHeader(gpAppFrame->oStarDictPlugins->VirtualDictPlugins.dict_name(gpAppFrame->scan_dictmask[i].index));
171 else if (gpAppFrame->scan_dictmask[i].type == InstantDictType_NET)
172 view->AppendHeader(gpAppFrame->oStarDictPlugins->NetDictPlugins.dict_name(gpAppFrame->scan_dictmask[i].index));
173 j=0;
174 do {
175 if (j==0) {
176 if (strcmp(Word[i][j], sOriginWord))
177 view->AppendWord(Word[i][j]);
178 } else {
179 view->AppendNewline();
180 view->AppendWord(Word[i][j]);
181 }
182 view->AppendData(WordData[i][j][0], Word[i][j],
183 sOriginWord);
184 k=1;
185 while (WordData[i][j][k]) {
186 view->AppendNewline();
187 view->AppendDataSeparate();
188 view->AppendData(WordData[i][j][k],
189 Word[i][j], sOriginWord);
190 k++;
191 }
192 j++;
193 } while (Word[i][j]);
194 }
195 }
196 view->end_update();
197 have_real_content = true;
198 destroy_lookup_running_timer();
199
200 gboolean pronounced = false;
201 readwordtype = gpAppFrame->oReadWord.canRead(sOriginWord);
202 if (readwordtype != READWORD_CANNOT) {
203 if (PronounceWord == sOriginWord) {
204 pronounced = true;
205 } else {
206 PronounceWord = sOriginWord;
207 }
208 } else {
209 for (size_t i=0;i< gpAppFrame->scan_dictmask.size(); i++) {
210 if (Word[i] && strcmp(Word[i][0], sOriginWord)) {
211 readwordtype = gpAppFrame->oReadWord.canRead(Word[i][0]);
212 if (readwordtype != READWORD_CANNOT) {
213 if (PronounceWord == Word[i][0])
214 pronounced = true;
215 else
216 PronounceWord = Word[i][0];
217 }
218 break;
219 }
220 }
221 }
222 gtk_widget_set_sensitive(PronounceWordButton, readwordtype != READWORD_CANNOT);
223
224 Popup(!window_positioned);
225 window_positioned = true;
226 if ((readwordtype != READWORD_CANNOT) && (!pronounced) && conf->get_bool_at("floating_window/pronounce_when_popup"))
227 gpAppFrame->oReadWord.read(PronounceWord.c_str(), readwordtype);
228 }
229
AppendTextNetDict(NetDictResponse * resp)230 void FloatWin::AppendTextNetDict(NetDictResponse *resp)
231 {
232 if(!resp->data)
233 return;
234
235 view->begin_update();
236 if(!have_real_content)
237 view->clear();
238 if (!have_real_content) {
239 std::string mark = get_head_word_markup(resp->word);
240 view->append_pango_text(mark.c_str());
241 }
242 InstantDictIndex dict_index;
243 dict_index.type = InstantDictType_UNKNOWN;
244 view->SetDictIndex(dict_index);
245 view->AppendNewline();
246 view->AppendHeader(resp->bookname);
247 view->AppendWord(resp->word);
248 view->AppendData(resp->data, resp->word, resp->word);
249 view->end_update();
250 have_real_content = true;
251 destroy_lookup_running_timer();
252
253 gboolean pronounced = false;
254 readwordtype = gpAppFrame->oReadWord.canRead(resp->word);
255 if (readwordtype != READWORD_CANNOT) {
256 if (PronounceWord == resp->word)
257 pronounced = true;
258 else
259 PronounceWord = resp->word;
260 }
261 gtk_widget_set_sensitive(PronounceWordButton, readwordtype != READWORD_CANNOT);
262
263 Popup(!window_positioned);
264 window_positioned = true;
265 if ((readwordtype != READWORD_CANNOT) && (!pronounced) && conf->get_bool_at("floating_window/pronounce_when_popup"))
266 gpAppFrame->oReadWord.read(PronounceWord.c_str(), readwordtype);
267 }
268
AppendTextStarDictNet(const struct STARDICT::LookupResponse::DictResponse * dict_response)269 void FloatWin::AppendTextStarDictNet(const struct STARDICT::LookupResponse::DictResponse *dict_response)
270 {
271 if(dict_response->dict_result_list.empty())
272 return;
273
274 view->begin_update();
275 if(!have_real_content)
276 view->clear();
277 if (!have_real_content) {
278 std::string mark = get_head_word_markup(dict_response->oword);
279 view->append_pango_text(mark.c_str());
280 }
281 InstantDictIndex dict_index;
282 dict_index.type = InstantDictType_UNKNOWN;
283 view->SetDictIndex(dict_index);
284 for (std::list<struct STARDICT::LookupResponse::DictResponse::DictResult *>::const_iterator i = dict_response->dict_result_list.begin(); i != dict_response->dict_result_list.end(); ++i) {
285 view->AppendNewline();
286 view->AppendHeader((*i)->bookname);
287 for (std::list<struct STARDICT::LookupResponse::DictResponse::DictResult::WordResult *>::iterator j = (*i)->word_result_list.begin(); j != (*i)->word_result_list.end(); ++j) {
288 if (j == (*i)->word_result_list.begin()) {
289 if (strcmp((*j)->word, dict_response->oword)) {
290 view->AppendWord((*j)->word);
291 }
292 } else {
293 view->AppendNewline();
294 view->AppendWord((*j)->word);
295 }
296 std::list<char *>::iterator k = (*j)->datalist.begin();
297 view->AppendData(*k, (*j)->word, dict_response->oword);
298 for (++k; k != (*j)->datalist.end(); ++k) {
299 view->AppendNewline();
300 view->AppendDataSeparate();
301 view->AppendData(*k, (*j)->word, dict_response->oword);
302 }
303 }
304 }
305 view->end_update();
306 have_real_content = true;
307 destroy_lookup_running_timer();
308
309 gboolean pronounced = false;
310 readwordtype = gpAppFrame->oReadWord.canRead(dict_response->oword);
311 if (readwordtype != READWORD_CANNOT) {
312 if (PronounceWord == dict_response->oword)
313 pronounced = true;
314 else
315 PronounceWord = dict_response->oword;
316 } else {
317 for (std::list<struct STARDICT::LookupResponse::DictResponse::DictResult *>::const_iterator i = dict_response->dict_result_list.begin(); i != dict_response->dict_result_list.end(); ++i) {
318 std::list<struct STARDICT::LookupResponse::DictResponse::DictResult::WordResult *>::iterator j = (*i)->word_result_list.begin();
319 if (j != (*i)->word_result_list.end() && strcmp((*j)->word, dict_response->oword)) {
320 readwordtype = gpAppFrame->oReadWord.canRead((*j)->word);
321 if (readwordtype != READWORD_CANNOT) {
322 if (PronounceWord == (*j)->word)
323 pronounced = true;
324 else
325 PronounceWord = (*j)->word;
326 }
327 break;
328 }
329 }
330 }
331 gtk_widget_set_sensitive(PronounceWordButton, readwordtype != READWORD_CANNOT);
332
333 Popup(!window_positioned);
334 window_positioned = true;
335 if ((readwordtype != READWORD_CANNOT) && (!pronounced) && conf->get_bool_at("floating_window/pronounce_when_popup"))
336 gpAppFrame->oReadWord.read(PronounceWord.c_str(), readwordtype);
337 }
338
AppendTextFuzzy(gchar **** ppppWord,gchar ***** pppppWordData,const gchar ** ppOriginWord,gint count,const gchar * sOriginWord)339 void FloatWin::AppendTextFuzzy(gchar ****ppppWord, gchar *****pppppWordData, const gchar ** ppOriginWord, gint count, const gchar *sOriginWord)
340 {
341 view->begin_update();
342 if(!have_real_content)
343 view->clear();
344
345 std::string mark;
346 gchar *m_str;
347 mark = _("Fuzzy query");
348 mark += " ";
349 mark += get_head_word_markup(sOriginWord);
350 mark += " ";
351 mark += _("has succeeded.\n");
352 if (count ==1)
353 mark+= _("Found 1 word:\n");
354 else {
355 m_str=g_strdup_printf(_("Found %d words:\n"),count);
356 mark += m_str;
357 g_free(m_str);
358 }
359
360 int j;
361 for (j=0; j<count-1; j++) {
362 mark += "<span size=\"x-large\">";
363 m_str = g_markup_escape_text(ppOriginWord[j], -1);
364 mark += m_str;
365 g_free(m_str);
366 mark += "</span> ";
367 }
368 mark += "<span size=\"x-large\">";
369 m_str = g_markup_escape_text(ppOriginWord[count-1],-1);
370 mark += m_str;
371 g_free(m_str);
372 mark += "</span>";
373 view->append_pango_text(mark.c_str());
374
375 int m,n;
376 for (j=0; j<count; j++) {
377 if (!ppppWord[j])
378 continue;
379 mark = "\n\n";
380 mark += get_head_word_markup(ppOriginWord[j]);
381 view->append_pango_text(mark.c_str());
382 for (size_t i=0; i<gpAppFrame->scan_dictmask.size(); i++) {
383 if (ppppWord[j][i]) {
384 view->AppendNewline();
385 view->SetDictIndex(gpAppFrame->scan_dictmask[i]);
386 if (gpAppFrame->scan_dictmask[i].type == InstantDictType_LOCAL)
387 view->AppendHeader(gpAppFrame->oLibs.dict_name(gpAppFrame->scan_dictmask[i].index).c_str());
388 else if (gpAppFrame->scan_dictmask[i].type == InstantDictType_VIRTUAL)
389 view->AppendHeader(gpAppFrame->oStarDictPlugins->VirtualDictPlugins.dict_name(gpAppFrame->scan_dictmask[i].index));
390 else if (gpAppFrame->scan_dictmask[i].type == InstantDictType_NET)
391 view->AppendHeader(gpAppFrame->oStarDictPlugins->NetDictPlugins.dict_name(gpAppFrame->scan_dictmask[i].index));
392 m=0;
393 do {
394 if (m==0) {
395 if (strcmp(ppppWord[j][i][m], ppOriginWord[j]))
396 view->AppendWord(ppppWord[j][i][m]);
397 } else {
398 view->AppendNewline();
399 view->AppendWord(ppppWord[j][i][m]);
400 }
401 view->AppendData(pppppWordData[j][i][m][0], ppppWord[j][i][m],
402 sOriginWord);
403 n=1;
404 while (pppppWordData[j][i][m][n]) {
405 view->AppendNewline();
406 view->AppendDataSeparate();
407 view->AppendData(pppppWordData[j][i][m][n],
408 ppppWord[j][i][m], sOriginWord);
409 n++;
410 }
411 m++;
412 } while (ppppWord[j][i][m]);
413 }
414 }
415 }
416 view->end_update();
417 have_real_content = true;
418 destroy_lookup_running_timer();
419
420 readwordtype = gpAppFrame->oReadWord.canRead(sOriginWord);
421 if (readwordtype != READWORD_CANNOT)
422 PronounceWord = sOriginWord;
423 gtk_widget_set_sensitive(PronounceWordButton, readwordtype != READWORD_CANNOT);
424
425
426 Popup(!window_positioned);
427 window_positioned = true;
428 /*bool pronounce_when_popup=
429 conf->get_bool_at("floating_window/pronounce_when_popup");
430
431 if (canRead && pronounce_when_popup)
432 gpAppFrame->oReadWord.read(PronounceWord.c_str());*/
433 }
434
ShowPangoTips(const char * sWord,const char * text)435 void FloatWin::ShowPangoTips(const char *sWord, const char *text)
436 {
437 QueryingWord = sWord;
438 view->set_pango_text(text);
439 have_real_content = true;
440 IgnoreScanModifierKey = false;
441 destroy_lookup_running_timer();
442
443 //gboolean pronounced = false;
444 readwordtype = gpAppFrame->oReadWord.canRead(sWord);
445 if (readwordtype != READWORD_CANNOT) {
446 if (PronounceWord == sWord) {
447 //pronounced = true;
448 } else {
449 PronounceWord = sWord;
450 }
451 }
452 gtk_widget_set_sensitive(PronounceWordButton, readwordtype != READWORD_CANNOT);
453
454 Popup(true);
455 window_positioned = true;
456 }
457
Show()458 void FloatWin::Show()
459 {
460 gtk_widget_show(FloatWindow);
461 #ifdef _WIN32
462 gtk_window_present(GTK_WINDOW(FloatWindow));
463 #endif
464 start_hide_window_timer();
465 }
466
Hide()467 void FloatWin::Hide()
468 {
469 destroy_hide_window_timer();
470 button_box_once_shown = false;
471 window_positioned = false;
472 PronounceWord.clear();
473 gtk_widget_hide(FloatWindow);
474 }
475
on_query_click(GtkWidget * widget,FloatWin * oFloatWin)476 void FloatWin::on_query_click(GtkWidget *widget, FloatWin *oFloatWin)
477 {
478 play_sound_on_event("buttonactive");
479
480 if (!conf->get_bool_at("floating_window/lock"))
481 oFloatWin->Hide();
482 gpAppFrame->Query(oFloatWin->QueryingWord.c_str());
483 gpAppFrame->oDockLet->maximize_from_tray();
484 }
485
on_save_click(GtkWidget * widget,FloatWin * oFloatWin)486 void FloatWin::on_save_click(GtkWidget *widget, FloatWin *oFloatWin)
487 {
488 const std::string& filePath = conf->get_string_at("dictionary/export_file");
489 #ifdef _WIN32
490 FILE *fp = fopen(abs_path_to_data_dir(filePath).c_str(), "a+");
491 #else
492 FILE *fp = fopen(filePath.c_str(), "a+");
493 #endif
494 if(fp) {
495 if (conf->get_bool_at("dictionary/only_export_word")) {
496 fputs(oFloatWin->QueryingWord.c_str(),fp);
497 fputs("\n",fp);
498 } else {
499 fputs(oFloatWin->view->get_text().c_str(),fp);
500 fputs("\n\n",fp);
501 }
502 fclose(fp);
503 }
504 play_sound_on_event("buttonactive");
505 }
506
on_play_click(GtkWidget * widget,FloatWin * oFloatWin)507 void FloatWin::on_play_click(GtkWidget *widget, FloatWin *oFloatWin)
508 {
509 gpAppFrame->oReadWord.read(oFloatWin->PronounceWord.c_str(), oFloatWin->readwordtype);
510 }
511
on_stop_click(GtkWidget * widget,FloatWin * oFloatWin)512 void FloatWin::on_stop_click(GtkWidget *widget, FloatWin *oFloatWin)
513 {
514 play_sound_on_event("buttonactive");
515 conf->set_bool_at("dictionary/scan_selection", false);
516 }
517
518 #ifndef CONFIG_GPE
on_help_click(GtkWidget * widget,FloatWin * oFloatWin)519 void FloatWin::on_help_click(GtkWidget *widget, FloatWin *oFloatWin)
520 {
521 play_sound_on_event("buttonactive");
522
523 if (!conf->get_bool_at("floating_window/lock"))
524 oFloatWin->Hide();
525 show_help("stardict-scan-selection");
526 }
527
on_quit_click(GtkWidget * widget,FloatWin * oFloatWin)528 void FloatWin::on_quit_click(GtkWidget *widget, FloatWin *oFloatWin)
529 {
530 play_sound_on_event("buttonactive");
531 gpAppFrame->Quit();
532 }
533 #endif
vLockCallback(GtkWidget * widget,FloatWin * oFloatWin)534 void FloatWin::vLockCallback(GtkWidget *widget, FloatWin *oFloatWin)
535 {
536 play_sound_on_event("buttonactive");
537 conf->set_bool_at("floating_window/lock",
538 !conf->get_bool_at("floating_window/lock"));
539 }
540
vHideWindowTimeOutCallback(gpointer data)541 gint FloatWin::vHideWindowTimeOutCallback(gpointer data)
542 {
543 FloatWin *oFloatWin = static_cast<FloatWin *>(data);
544 bool lock=
545 conf->get_bool_at("floating_window/lock");
546 if(lock || oFloatWin->ismoving || !gtk_widget_get_visible(GTK_WIDGET(oFloatWin->FloatWindow)))
547 return true;
548
549 bool only_scan_while_modifier_key=
550 conf->get_bool_at("dictionary/only_scan_while_modifier_key");
551 bool hide_floatwin_when_modifier_key_released=
552 conf->get_bool_at("dictionary/hide_floatwin_when_modifier_key_released");
553 if (only_scan_while_modifier_key
554 && hide_floatwin_when_modifier_key_released
555 && !oFloatWin->IgnoreScanModifierKey) {
556 GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(oFloatWin->FloatWindow));
557 GdkDisplay *display = gdk_screen_get_display(screen);
558 gint iCurrentX,iCurrentY;
559 #if GTK_MAJOR_VERSION >= 3
560 GdkDeviceManager *device_manager = gdk_display_get_device_manager (display);
561 GdkDevice *pointer = gdk_device_manager_get_client_pointer (device_manager);
562 gdk_device_get_position(pointer, NULL, &iCurrentX, &iCurrentY);
563 #else
564 gdk_display_get_pointer(display, NULL, &iCurrentX, &iCurrentY, NULL);
565 #endif
566 if (iCurrentX == oFloatWin->popup_pointer_x && iCurrentY==oFloatWin->popup_pointer_y) {
567 bool released = !gpAppFrame->unlock_keys->is_pressed();
568
569 if (released) {
570 oFloatWin->Hide();
571 gpAppFrame->oSelection.LastClipWord.clear(); //so press modifier key again will pop up the floatwin.
572 return true;
573 }
574 }
575 }
576
577 if (oFloatWin->get_distance_pointer_to_window() > DISAPPEAR_DISTANCE){
578 oFloatWin->Hide();
579 }
580
581 return true;
582 }
583
vLookupRunningTimeOutCallback(gpointer data)584 gint FloatWin::vLookupRunningTimeOutCallback(gpointer data)
585 {
586 FloatWin *oFloatWin = static_cast<FloatWin *>(data);
587 if(!oFloatWin->have_real_content) {
588 if (conf->get_bool_at("floating_window/show_if_not_found")) {
589 oFloatWin->Popup(!oFloatWin->window_positioned);
590 oFloatWin->window_positioned = true;
591 }
592 }
593 oFloatWin->lookup_running_timer = 0;
594 return FALSE;
595 }
596
vEnterNotifyCallback(GtkWidget * widget,GdkEventCrossing * event,FloatWin * oFloatWin)597 gboolean FloatWin::vEnterNotifyCallback (GtkWidget *widget, GdkEventCrossing *event, FloatWin *oFloatWin)
598 {
599 #ifdef _WIN32
600 if ((event->detail==GDK_NOTIFY_ANCESTOR) || (event->detail==GDK_NOTIFY_NONLINEAR) || (event->detail==GDK_NOTIFY_NONLINEAR_VIRTUAL)) {
601 #else
602 if ((event->detail==GDK_NOTIFY_NONLINEAR) || (event->detail==GDK_NOTIFY_NONLINEAR_VIRTUAL)) {
603 #endif
604 if (!gtk_widget_get_visible(GTK_WIDGET(oFloatWin->button_hbox))) {
605 gtk_widget_show(oFloatWin->button_hbox);
606
607 if (!oFloatWin->button_box_once_shown) {
608 oFloatWin->button_box_once_shown = true;
609 oFloatWin->button_box_show_first_time();
610 }
611 }
612 }
613 return true;
614 }
615
616 gboolean FloatWin::vLeaveNotifyCallback (GtkWidget *widget, GdkEventCrossing *event, FloatWin *oFloatWin)
617 {
618 #ifdef _WIN32
619 if (((event->detail==GDK_NOTIFY_ANCESTOR) || (event->detail==GDK_NOTIFY_NONLINEAR) || (event->detail==GDK_NOTIFY_NONLINEAR_VIRTUAL))&&(!oFloatWin->ismoving)) {
620 #else
621 if (((event->detail==GDK_NOTIFY_NONLINEAR) || (event->detail==GDK_NOTIFY_NONLINEAR_VIRTUAL))&&(!oFloatWin->ismoving)) {
622 #endif
623 gtk_widget_hide(oFloatWin->button_hbox);
624 }
625 return true;
626 }
627
628 gboolean FloatWin::vButtonPressCallback (GtkWidget * widget, GdkEventButton * event , FloatWin *oFloatWin)
629 {
630 if (event->type == GDK_BUTTON_PRESS) {
631 if (event->button == 1) {
632 gtk_window_get_position(GTK_WINDOW(widget),&(oFloatWin->press_window_x),&(oFloatWin->press_window_y));
633 oFloatWin->press_x_root = (gint)(event->x_root);
634 oFloatWin->press_y_root = (gint)(event->y_root);
635 oFloatWin->ismoving = true;
636 }
637 else if (event->button == 3) {
638 oFloatWin->show_popup_menu(event);
639 }
640 } else if (event->type == GDK_2BUTTON_PRESS) {
641 if (oFloatWin->content_state == ContentState_NotFound) {
642 std::string QueryingWord(oFloatWin->QueryingWord);
643 gpAppFrame->LookupWithFuzzyToFloatWin(QueryingWord.c_str());
644 } else
645 oFloatWin->Hide();
646 }
647
648 return true;
649 }
650
651 gboolean FloatWin::vButtonReleaseCallback (GtkWidget * widget, GdkEventButton * event , FloatWin *oFloatWin)
652 {
653 if (event->button == 1) {
654 oFloatWin->ismoving = false;
655 }
656
657 return true;
658 }
659
660 gboolean FloatWin::vMotionNotifyCallback (GtkWidget * widget, GdkEventMotion * event , FloatWin *oFloatWin)
661 {
662 if (event->state & GDK_BUTTON1_MASK) {
663 gint x,y;
664 x = oFloatWin->press_window_x + (gint)(event->x_root) - oFloatWin->press_x_root;
665 y = oFloatWin->press_window_y + (gint)(event->y_root) - oFloatWin->press_y_root;
666 if (x<0)
667 x = 0;
668 if (y<0)
669 y = 0;
670 gtk_window_move(GTK_WINDOW(oFloatWin->FloatWindow), x, y);
671 }
672
673 return true;
674 }
675
676 void FloatWin::on_menu_copy_activate(GtkWidget * widget, FloatWin *oFloatWin)
677 {
678 GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
679 gtk_clipboard_set_text(clipboard, oFloatWin->view->get_text().c_str(), -1);
680 }
681
682 void FloatWin::on_menu_save_activate(GtkWidget * widget, FloatWin *oFloatWin)
683 {
684 oFloatWin->on_save_click(widget, oFloatWin);
685 }
686
687 void FloatWin::on_menu_query_activate(GtkWidget * widget, FloatWin *oFloatWin)
688 {
689 oFloatWin->on_query_click(widget, oFloatWin);
690 }
691
692 void FloatWin::on_menu_play_activate(GtkWidget * widget, FloatWin *oFloatWin)
693 {
694 oFloatWin->on_play_click(widget, oFloatWin);
695 }
696
697 void FloatWin::on_menu_fuzzyquery_activate(GtkWidget * widget, FloatWin *oFloatWin)
698 {
699 /* do not use oFloatWin->QueryingWord directly,
700 LookupWithFuzzyToFloatWin overwrite oFloatWin->QueryingWord */
701 const std::string tQueryingWord(oFloatWin->QueryingWord);
702 gpAppFrame->LookupWithFuzzyToFloatWin(tQueryingWord.c_str());
703 }
704
705 void FloatWin::on_lock_changed(const baseconfval* )
706 {
707 gtk_image_set_from_stock(GTK_IMAGE(LockImage),
708 get_lock_image_stock_id(), GTK_ICON_SIZE_MENU);
709 }
710
711 void FloatWin::on_dict_scan_select_changed(const baseconfval* scanval)
712 {
713 bool scan = static_cast<const confval<bool> *>(scanval)->val_;
714
715 gtk_widget_set_sensitive(StopButton, scan);
716 }
717
718 void FloatWin::on_lock_x_changed(const baseconfval* lock_x_val)
719 {
720 int lock_x=static_cast<const confval<int> *>(lock_x_val)->val_;
721 if (conf->get_bool_at("floating_window/lock")) {
722 gint old_x, old_y;
723 gtk_window_get_position(GTK_WINDOW(FloatWindow), &old_x, &old_y);
724 if (lock_x!=old_x) {
725 gtk_window_move(GTK_WINDOW(FloatWindow), lock_x, old_y);
726 }
727 }
728 }
729
730 void FloatWin::on_lock_y_changed(const baseconfval* lock_y_val)
731 {
732 int lock_y=static_cast<const confval<int> *>(lock_y_val)->val_;
733
734 if (conf->get_bool_at("floating_window/lock")) {
735 gint old_x,old_y;
736 gtk_window_get_position(GTK_WINDOW(FloatWindow), &old_x, &old_y);
737 if (lock_y!=old_y) {
738 gtk_window_move(GTK_WINDOW(FloatWindow), old_x, lock_y);
739 }
740 }
741 }
742
743 void FloatWin::on_transparent_changed(const baseconfval* val)
744 {
745 int transparent = static_cast<const confval<int> *>(val)->val_;
746 set_transparent(transparent);
747 }
748
749 void FloatWin::on_use_custom_bg_changed(const baseconfval* )
750 {
751 set_bg();
752 }
753
754 gint FloatWin::get_vscrollbar_width(void)
755 {
756 static gint vscrollbar_width = 0;
757 if (!vscrollbar_width) {
758 if (view->vscroll_bar()) {
759 GtkRequisition vscrollbar_requisition;
760 #if GTK_MAJOR_VERSION >= 3
761 gtk_widget_get_preferred_size(view->vscroll_bar(), NULL, &vscrollbar_requisition);
762 #else
763 gtk_widget_size_request(view->vscroll_bar(), &vscrollbar_requisition);
764 #endif
765 vscrollbar_width = vscrollbar_requisition.width;
766 vscrollbar_width += view->scroll_space();
767 }
768 }
769 return vscrollbar_width;
770 }
771
772 gint FloatWin::get_window_border_width(void)
773 {
774 return 2*(FLOATWIN_BORDER_WIDTH+2); // 2 is the frame 's width. Or get it by gtk function? i am lazy,hoho
775 }
776
777 void FloatWin::float_window_size(gint& window_width, gint& window_height)
778 {
779 GtkRequisition requisition;
780 #if GTK_MAJOR_VERSION >= 3
781 gtk_widget_get_preferred_size(view->widget(), NULL, &requisition);
782 #else
783 gtk_widget_size_request(view->widget(), &requisition);
784 #endif
785 int max_window_width=conf->get_int_at("floating_window/max_window_width");
786 if (requisition.width > max_window_width) {
787 // it is not really max window width setting.
788 gtk_widget_set_size_request(view->widget(), max_window_width, -1);
789 gtk_label_set_line_wrap(GTK_LABEL(view->widget()), true);
790 #if GTK_MAJOR_VERSION >= 3
791 gtk_widget_get_preferred_size(view->widget(), NULL, &requisition); //update requisition
792 #else
793 gtk_widget_size_request(view->widget(), &requisition); //update requisition
794 #endif
795 }
796 window_width = get_window_border_width() + requisition.width;
797 int max_window_height=
798 conf->get_int_at("floating_window/max_window_height");
799 if (requisition.height > max_window_height) {
800 const gint vscrollbar_width = get_vscrollbar_width();
801 view->set_size(requisition.width + vscrollbar_width, max_window_height);
802 window_height = get_window_border_width() + max_window_height;
803 window_width += vscrollbar_width;
804 } else {
805 view->set_size(requisition.width, requisition.height);
806 window_height = get_window_border_width() + requisition.height;
807 }
808
809 gboolean button_hbox_visible = gtk_widget_get_visible(GTK_WIDGET(button_hbox));
810 if (button_hbox_visible) {
811 GtkAllocation allocation;
812 gtk_widget_get_allocation(button_hbox, &allocation);
813 window_height += allocation.height;
814 if (window_width < allocation.width + get_window_border_width())
815 window_width = allocation.width + get_window_border_width();
816 }
817 }
818
819 void FloatWin::float_window_position(gboolean usePointerPosition,
820 gint window_width, gint window_height, gint& x, gint& y)
821 {
822 GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(FloatWindow));
823 if (usePointerPosition) {
824 GdkDisplay *display = gdk_screen_get_display(screen);
825 #if GTK_MAJOR_VERSION >= 3
826 GdkDeviceManager *device_manager = gdk_display_get_device_manager (display);
827 GdkDevice *pointer = gdk_device_manager_get_client_pointer (device_manager);
828 gdk_device_get_position (pointer, NULL, &x, &y);
829 #else
830 gdk_display_get_pointer(display, NULL, &x, &y, NULL);
831 #endif
832 x += FLOATWIN_OFFSET_X;
833 y += FLOATWIN_OFFSET_Y;
834 } else {
835 gtk_window_get_position(GTK_WINDOW(FloatWindow),&x,&y);
836 }
837 gint screen_width = gdk_screen_get_width(screen);
838 gint screen_height = gdk_screen_get_height(screen);
839 if (x + window_width > screen_width)
840 x = screen_width - window_width;
841 if (y + window_height > screen_height)
842 y = screen_height - window_height;
843 }
844
845 void FloatWin::remember_pointer_position(void)
846 {
847 /* TODO: the user of this object should tell why the floating windows has to be shown. */
848 bool pressed = gpAppFrame->unlock_keys->is_pressed();
849
850 if (pressed) {
851 GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(FloatWindow));
852 GdkDisplay *display = gdk_screen_get_display(screen);
853 #if GTK_MAJOR_VERSION >= 3
854 GdkDeviceManager *device_manager = gdk_display_get_device_manager (display);
855 GdkDevice *pointer = gdk_device_manager_get_client_pointer (device_manager);
856 gdk_device_get_position(pointer, NULL, &popup_pointer_x, &popup_pointer_y);
857 #else
858 gdk_display_get_pointer(display, NULL, &popup_pointer_x, &popup_pointer_y, NULL);
859 #endif
860 } else {
861 // popup by middle click on the notification area icon,
862 // so never hiden the floating window even mouse didn't moved as in FloatWin::vHideWindowTimeOutCallback().
863 popup_pointer_x = -1;
864 popup_pointer_y = -1;
865 }
866 }
867
868 void FloatWin::Popup(gboolean updatePosition)
869 {
870 ismoving = true;
871 gint window_width, window_height;
872 float_window_size(window_width, window_height);
873
874 if (conf->get_bool_at("floating_window/lock")) {
875 gtk_window_resize(GTK_WINDOW(FloatWindow),window_width,window_height);
876 // need to make window's resize relate to other corner?
877 } else {
878 gint iCurrentX,iCurrentY;
879 gboolean newPosition = (!gtk_widget_get_visible(GTK_WIDGET(FloatWindow))) || updatePosition;
880 float_window_position(newPosition, window_width, window_height, iCurrentX, iCurrentY);
881 if (newPosition) {
882 button_box_once_shown = false;
883 remember_pointer_position();
884 }
885 // don't use gdk_window_resize,it make the window can't be smaller latter!
886 // note: must do resize before move should be better,as the vHideWindowTimeOutCallback() may hide it.
887 gtk_window_resize(GTK_WINDOW(FloatWindow),window_width,window_height);
888 gtk_window_move(GTK_WINDOW(FloatWindow),iCurrentX,iCurrentY);
889 }
890 now_window_width = window_width;
891 now_window_height = window_height;
892
893 Show();
894 ismoving = false;
895 }
896
897
898 void FloatWin::create_button_hbox(void)
899 {
900 #if GTK_MAJOR_VERSION >= 3
901 button_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
902 #else
903 button_hbox = gtk_hbox_new(false,0);
904 #endif
905
906 GtkWidget *button;
907 button= gtk_button_new();
908 gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_stock(GTK_STOCK_FIND,GTK_ICON_SIZE_MENU));
909 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
910 g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_query_click), this);
911 g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
912 gtk_box_pack_start(GTK_BOX(button_hbox),button,false,false,0);
913 gtk_widget_set_tooltip_text(button,_("Query in the main window"));
914
915 button= gtk_button_new();
916 gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_stock(GTK_STOCK_SAVE,GTK_ICON_SIZE_MENU));
917 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
918 g_signal_connect(G_OBJECT(button),"clicked",
919 G_CALLBACK(on_save_click), this);
920 g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
921 gtk_box_pack_start(GTK_BOX(button_hbox),button,false,false,0);
922 gtk_widget_set_tooltip_text(button,_("Save to file"));
923
924 PronounceWordButton= gtk_button_new();
925 gtk_container_add(GTK_CONTAINER(PronounceWordButton),gtk_image_new_from_stock(GTK_STOCK_EXECUTE,GTK_ICON_SIZE_MENU));
926 gtk_button_set_relief (GTK_BUTTON (PronounceWordButton), GTK_RELIEF_NONE);
927 g_signal_connect(G_OBJECT(PronounceWordButton),"clicked", G_CALLBACK(on_play_click), this);
928 g_signal_connect(G_OBJECT(PronounceWordButton),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
929 gtk_box_pack_start(GTK_BOX(button_hbox),PronounceWordButton,false,false,0);
930 gtk_widget_set_tooltip_text(PronounceWordButton,_("Pronounce the word"));
931
932 gtk_widget_set_sensitive(PronounceWordButton, false);
933
934 StopButton= gtk_button_new();
935 gtk_container_add(GTK_CONTAINER(StopButton),gtk_image_new_from_stock(GTK_STOCK_STOP,GTK_ICON_SIZE_MENU));
936 gtk_button_set_relief (GTK_BUTTON (StopButton), GTK_RELIEF_NONE);
937 g_signal_connect(G_OBJECT(StopButton),"clicked", G_CALLBACK(on_stop_click), this);
938 g_signal_connect(G_OBJECT(StopButton),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
939 gtk_box_pack_start(GTK_BOX(button_hbox),StopButton,false,false,0);
940 gtk_widget_set_tooltip_text(StopButton, _("Stop selection-scanning"));
941
942 gtk_widget_set_sensitive(gpAppFrame->oFloatWin.StopButton,
943 conf->get_bool_at("dictionary/scan_selection"));
944
945 #ifndef CONFIG_GPE
946 button= gtk_button_new();
947 gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_stock(GTK_STOCK_HELP,GTK_ICON_SIZE_MENU));
948 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
949 g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_help_click), this);
950 g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
951 gtk_box_pack_start(GTK_BOX(button_hbox),button,false,false,0);
952 gtk_widget_set_tooltip_text(button,_("Help"));
953
954 button= gtk_button_new();
955 gtk_container_add(GTK_CONTAINER(button),gtk_image_new_from_stock(GTK_STOCK_QUIT,GTK_ICON_SIZE_MENU));
956 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
957 g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_quit_click), this);
958 g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
959 gtk_box_pack_start(GTK_BOX(button_hbox),button,false,false,0);
960 gtk_widget_set_tooltip_text(button,_("Quit"));
961 #endif
962
963 button = gtk_button_new();
964
965 LockImage= gtk_image_new_from_stock(get_lock_image_stock_id(),GTK_ICON_SIZE_MENU);
966 gtk_container_add(GTK_CONTAINER(button),LockImage);
967 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
968 g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(vLockCallback),this);
969 g_signal_connect(G_OBJECT(button),"enter_notify_event", G_CALLBACK(stardict_on_enter_notify), NULL);
970 gtk_box_pack_end(GTK_BOX(button_hbox),button,false,false,0);
971 gtk_widget_set_tooltip_text(button,_("Lock floating window"));
972 }
973
974 int FloatWin::get_distance_pointer_to_window(void)
975 {
976 GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(FloatWindow));
977 GdkDisplay *display = gdk_screen_get_display(screen);
978 gint iCurrentX,iCurrentY;
979 #if GTK_MAJOR_VERSION >= 3
980 GdkDeviceManager *device_manager = gdk_display_get_device_manager (display);
981 GdkDevice *pointer = gdk_device_manager_get_client_pointer (device_manager);
982 gdk_device_get_position(pointer, NULL, &iCurrentX, &iCurrentY);
983 #else
984 gdk_display_get_pointer(display, NULL, &iCurrentX, &iCurrentY, NULL);
985 #endif
986 gint window_x,window_y,window_width,window_height;
987 gtk_window_get_position(GTK_WINDOW(FloatWindow),&window_x,&window_y);
988 //notice: gtk_window_get_size() is not really uptodate,don't use it! see "gtk reference".
989 //gtk_window_get_size(GTK_WINDOW(FloatWindow),&window_width,&window_height);
990 window_width = now_window_width;
991 window_height = now_window_height;
992
993 int distance;
994 if (iCurrentX < window_x) {
995 distance = (iCurrentX-window_x)*(iCurrentX-window_x);
996 if (iCurrentY < window_y)
997 distance += (iCurrentY-window_y)*(iCurrentY-window_y);
998 else if (iCurrentY > window_y+window_height)
999 distance += (iCurrentY-window_y-window_height)*(iCurrentY-window_y-window_height);
1000 } else if (iCurrentX > window_x+window_width) {
1001 distance = (iCurrentX-window_x-window_width)*(iCurrentX-window_x-window_width);
1002 if (iCurrentY < window_y)
1003 distance += (iCurrentY-window_y)*(iCurrentY-window_y);
1004 else if ( iCurrentY > window_y+window_height )
1005 distance += (iCurrentY-window_y-window_height)*(iCurrentY-window_y-window_height);
1006 } else {
1007 if (iCurrentY < window_y)
1008 distance = (window_y - iCurrentY)*(window_y - iCurrentY);
1009 else if (iCurrentY > window_y+window_height)
1010 distance = (iCurrentY-window_y-window_height)*(iCurrentY-window_y-window_height);
1011 else
1012 distance = 0; //in the floating window.
1013 }
1014 return distance;
1015 }
1016
1017 void FloatWin::button_box_show_first_time(void)
1018 {
1019 gint iCurrentX,iCurrentY;
1020 gtk_window_get_position(GTK_WINDOW(FloatWindow),&iCurrentX,&iCurrentY);
1021 GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(FloatWindow));
1022 gint screen_width = gdk_screen_get_width(screen);
1023 gint screen_height = gdk_screen_get_height(screen);
1024 GtkRequisition requisition;
1025 #if GTK_MAJOR_VERSION >= 3
1026 gtk_widget_get_preferred_size(button_hbox, NULL, &requisition);
1027 #else
1028 gtk_widget_size_request(button_hbox,&requisition);
1029 #endif
1030 now_window_height += requisition.height;
1031 requisition.width += get_window_border_width();
1032 if (requisition.width > now_window_width)
1033 now_window_width = requisition.width;
1034 bool changed=false;
1035 if (iCurrentX < 0) {
1036 iCurrentX = 0;
1037 changed = true;
1038 } else if (iCurrentX + now_window_width > screen_width) {
1039 iCurrentX = screen_width - now_window_width;
1040 changed = true;
1041 }
1042 if (iCurrentY < 0) {
1043 iCurrentY = 0;
1044 changed = true;
1045 } else if (iCurrentY + now_window_height > screen_height) {
1046 iCurrentY = screen_height - now_window_height;
1047 changed = true;
1048 }
1049 if (changed) {
1050 gtk_window_move(GTK_WINDOW(FloatWindow),iCurrentX,iCurrentY);
1051 }
1052 }
1053
1054 void FloatWin::show_popup_menu(GdkEventButton * event)
1055 {
1056 if (menu)
1057 gtk_widget_destroy(menu);
1058 menu = gtk_menu_new();
1059
1060 GtkWidget *menuitem;
1061 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Copy"));
1062 GtkWidget *image;
1063 image = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU);
1064 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
1065 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
1066 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_menu_copy_activate), this);
1067 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1068 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Save"));
1069 image = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU);
1070 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
1071 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
1072 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_menu_save_activate), this);
1073 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1074 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Query"));
1075 image = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
1076 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
1077 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
1078 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_menu_query_activate), this);
1079 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1080
1081 if (gtk_widget_get_sensitive(GTK_WIDGET(PronounceWordButton))) {
1082 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Play"));
1083 image = gtk_image_new_from_stock(GTK_STOCK_EXECUTE, GTK_ICON_SIZE_MENU);
1084 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
1085 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
1086 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_menu_play_activate), this);
1087 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1088 }
1089
1090 menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Fuzzy query"));
1091 image = gtk_image_new_from_stock(GTK_STOCK_FIND_AND_REPLACE, GTK_ICON_SIZE_MENU);
1092 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
1093 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
1094 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_menu_fuzzyquery_activate), this);
1095 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1096
1097 gtk_widget_show_all(menu);
1098 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time);
1099 play_sound_on_event("menushow");
1100 }
1101
1102 void FloatWin::set_transparent(int transparent)
1103 {
1104 g_assert(0 <= transparent && transparent <= 100);
1105 gtk_window_set_opacity(GTK_WINDOW(FloatWindow), (100-transparent)/100.0);
1106 }
1107
1108 void FloatWin::set_bg(void)
1109 {
1110 #if GTK_MAJOR_VERSION >= 3
1111 GdkRGBA color;
1112 const GdkRGBA *pcolor = NULL;
1113 if (conf->get_bool_at("floating_window/use_custom_bg")) {
1114 color.red = conf->get_double_at("floating_window/bg_red");
1115 color.green = conf->get_double_at("floating_window/bg_green");
1116 color.blue = conf->get_double_at("floating_window/bg_blue");
1117 color.alpha = 1;
1118 pcolor = &color;
1119 }
1120 gtk_widget_override_background_color(FloatWindow, GTK_STATE_FLAG_NORMAL, pcolor);
1121 view->modify_bg(GTK_STATE_FLAG_NORMAL, pcolor);
1122 #else
1123 GdkColor color;
1124 const GdkColor *pcolor = NULL;
1125 if (conf->get_bool_at("floating_window/use_custom_bg")) {
1126 color.red = conf->get_int_at("floating_window/bg_red");
1127 color.green = conf->get_int_at("floating_window/bg_green");
1128 color.blue = conf->get_int_at("floating_window/bg_blue");
1129 pcolor = &color;
1130 }
1131 gtk_widget_modify_bg(FloatWindow, GTK_STATE_NORMAL, pcolor);
1132 view->modify_bg(GTK_STATE_NORMAL, pcolor);
1133 #endif
1134 }
1135
1136 void FloatWin::set_bookname_style(BookNameStyle style)
1137 {
1138 if (view.get()) {
1139 view->set_bookname_style(style);
1140 }
1141 }
1142
1143 const gchar* FloatWin::get_lock_image_stock_id(void)
1144 {
1145 if (conf->get_bool_at("floating_window/lock"))
1146 return GTK_STOCK_GOTO_LAST;
1147 else
1148 return GTK_STOCK_GO_FORWARD;
1149 }
1150
1151 /* Restore locked position of the window. When may this be usefull?
1152 The floating window is hiden initially. */
1153 void FloatWin::restore_locked_position(void)
1154 {
1155 GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(FloatWindow));
1156 gint screen_width = gdk_screen_get_width(screen);
1157 gint screen_height = gdk_screen_get_height(screen);
1158 int max_window_width=
1159 conf->get_int_at("floating_window/max_window_width");
1160 int max_window_height=
1161 conf->get_int_at("floating_window/max_window_height");
1162 if (max_window_width < MIN_MAX_FLOATWIN_WIDTH ||
1163 max_window_width > screen_width)
1164 conf->set_int_at("floating_window/max_window_width",
1165 DEFAULT_MAX_FLOATWIN_WIDTH);
1166 if (max_window_height < MIN_MAX_FLOATWIN_HEIGHT ||
1167 max_window_height > screen_height)
1168 conf->set_int_at("floating_window/max_window_height", DEFAULT_MAX_FLOATWIN_HEIGHT);
1169
1170 max_window_width=
1171 conf->get_int_at("floating_window/max_window_width");
1172 max_window_height=
1173 conf->get_int_at("floating_window/max_window_height");
1174
1175 int lock_x=
1176 conf->get_int_at("floating_window/lock_x");
1177 int lock_y=
1178 conf->get_int_at("floating_window/lock_y");
1179 if (lock_x<0)
1180 lock_x=0;
1181 else if (lock_x > (screen_width - max_window_width))
1182 lock_x = screen_width - max_window_width;
1183 if (lock_y<0)
1184 lock_y=0;
1185 else if (lock_y > (screen_height - max_window_height))
1186 lock_y = screen_height - max_window_height;
1187 gtk_window_move(GTK_WINDOW(FloatWindow),lock_x,lock_y);
1188 }
1189
1190 std::string FloatWin::get_not_found_markup(const gchar* sWord, const gchar* sReason)
1191 {
1192 glib::CharStr str(g_markup_printf_escaped(
1193 "<b><big>%s</big></b>\n<span foreground=\"blue\">%s</span>", sWord, sReason));
1194 return get_impl(str);
1195 }
1196
1197 std::string FloatWin::get_looking_up_markup(const gchar* sWord)
1198 {
1199 glib::CharStr str(g_markup_printf_escaped(
1200 "<b><big>%s</big></b>\n<span foreground=\"blue\">%s</span>", sWord, _("Looking up...")));
1201 return get_impl(str);
1202 }
1203
1204 std::string FloatWin::get_head_word_markup(const gchar* sWord)
1205 {
1206 std::string markup = "<b><span size=\"x-large\">";
1207 glib::CharStr str(g_markup_escape_text(sWord, -1));
1208 markup += get_impl(str);
1209 markup += "</span></b>";
1210 return markup;
1211 }
1212
1213 void FloatWin::set_busy_cursor(void)
1214 {
1215 gdk_window_set_cursor(gtk_widget_get_window(FloatWindow), get_impl(gpAppFrame->oAppSkin.watch_cursor));
1216 }
1217
1218 void FloatWin::set_normal_cursor(void)
1219 {
1220 gdk_window_set_cursor(gtk_widget_get_window(FloatWindow), get_impl(gpAppFrame->oAppSkin.normal_cursor));
1221 }
1222
1223 void FloatWin::start_hide_window_timer(void)
1224 {
1225 if (!hide_window_timer)
1226 hide_window_timer = g_timeout_add(FLOAT_TIMEOUT, vHideWindowTimeOutCallback, this);
1227 }
1228
1229 void FloatWin::destroy_hide_window_timer(void)
1230 {
1231 if (hide_window_timer) {
1232 g_source_remove(hide_window_timer);
1233 hide_window_timer = 0;
1234 }
1235 }
1236
1237 void FloatWin::start_lookup_running_timer(void)
1238 {
1239 if (!lookup_running_timer)
1240 lookup_running_timer = g_timeout_add(LOOKUP_RUNNING_TIMEOUT, vLookupRunningTimeOutCallback, this);
1241 }
1242
1243 void FloatWin::destroy_lookup_running_timer(void)
1244 {
1245 if (lookup_running_timer) {
1246 g_source_remove(lookup_running_timer);
1247 lookup_running_timer = 0;
1248 }
1249 }
1250