1 /*
2 * Xiphos Bible Study Tool
3 * navbar_book.c - navigation bar for genbook modules
4 *
5 * Copyright (C) 2000-2020 Xiphos Developer Team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <gtk/gtk.h>
27
28 #include "gui/navbar_book.h"
29 #include "gui/utilities.h"
30
31 #include "main/navbar_book.h"
32 #include "main/settings.h"
33 #include "main/sword.h"
34 #include "main/url.hh"
35
36 NAVBAR_BOOK navbar_book;
37
38 /******************************************************************************
39 * Name
40 * menu_deactivate_callback
41 *
42 * Synopsis
43 * #include "gui/navbar_book.h"
44 *
45 * void menu_deactivate_callback (GtkWidget *widget, gpointer user_data)
46 *
47 * Description
48 * return toogle button to normal
49 *
50 * Return value
51 * void
52 */
53
menu_deactivate_callback(GtkWidget * widget,gpointer user_data)54 static void menu_deactivate_callback(GtkWidget *widget,
55 gpointer user_data)
56 {
57 GtkWidget *menu_button;
58
59 menu_button = GTK_WIDGET(user_data);
60
61 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(menu_button),
62 FALSE);
63 }
64
65 /******************************************************************************
66 * Name
67 * menu_position_under
68 *
69 * Synopsis
70 * #include "gui/navbar_book.h"
71 *
72 * void menu_position_under(GtkMenu * menu, int * x, int * y,
73 * gboolean * push_in, gpointer user_data)
74 *
75 * Description
76 * position drop down menu under toogle button
77 *
78 *
79 * Return value
80 * void
81 */
82
menu_position_under(GtkMenu * menu,int * x,int * y,gboolean * push_in,gpointer user_data)83 static void menu_position_under(GtkMenu *menu, int *x, int *y,
84 gboolean *push_in, gpointer user_data)
85 {
86 GtkWidget *widget;
87 GtkAllocation allocation;
88 g_return_if_fail(GTK_IS_BUTTON(user_data));
89 #if GTK_CHECK_VERSION(2, 20, 0)
90 g_return_if_fail(gtk_widget_get_window(user_data));
91 #else
92 g_return_if_fail(GTK_WIDGET_NO_WINDOW(user_data));
93 #endif
94
95 widget = GTK_WIDGET(user_data);
96
97 gdk_window_get_origin(gtk_widget_get_window(widget), x, y);
98 gtk_widget_get_allocation(widget, &allocation);
99 *x += allocation.x;
100 *y += allocation.y + allocation.height;
101
102 *push_in = FALSE;
103 }
104
lookup_entry_press_callback(GtkWidget * widget,GdkEventKey * event,gpointer user_data)105 static gboolean lookup_entry_press_callback(GtkWidget *widget,
106 GdkEventKey *event,
107 gpointer user_data)
108 {
109 if (!settings.havebook)
110 return FALSE;
111 /* this does not work on my system - hope I'm not messing things up
112 for others - 104 is the enter key on the number pad
113 switch (event->hardware_keycode) {
114 case 98:
115 gtk_button_clicked(GTK_BUTTON(navbar_book.button_up));
116 return TRUE;
117 break;
118 case 104:
119 gtk_button_clicked(GTK_BUTTON(navbar_book.button_down));
120 return TRUE;
121 break;
122 case 100:
123 gtk_button_clicked(GTK_BUTTON(navbar_book.button_left));
124 return TRUE;
125 break;
126 case 102:
127 gtk_button_clicked(GTK_BUTTON(navbar_book.button_right));
128 return TRUE;
129 break;
130 }
131 */
132 XI_message(("lookup_entry_press_callback\nkeycode: %d",
133 event->hardware_keycode));
134 return FALSE;
135 }
136
137 /******************************************************************************
138 * Name
139 * select_button_press_callback
140 *
141 * Synopsis
142 * #include "gui/navbar_book.h"
143 *
144 * gboolean select_button_press_callback (GtkWidget *widget,
145 * GdkEventButton *event,
146 * gpointer user_data)
147 *
148 * Description
149 * make the tooglebutton act like a gtk optionmenu by dropping a popup
150 * under the button
151 *
152 * Return value
153 * gboolean
154 */
155
select_button_press_callback(GtkWidget * widget,GdkEventButton * event,gpointer user_data)156 static gboolean select_button_press_callback(GtkWidget *widget,
157 GdkEventButton *event,
158 gpointer user_data)
159 {
160 GtkWidget *menu;
161
162 if (!settings.havebook)
163 return FALSE;
164 menu = main_book_drop_down_new();
165 g_signal_connect(menu, "deactivate",
166 G_CALLBACK(menu_deactivate_callback), widget);
167 if ((event->type == GDK_BUTTON_PRESS) && event->button == 1) {
168 gtk_widget_grab_focus(widget);
169 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
170 TRUE);
171 #if GTK_CHECK_VERSION(3, 22, 0)
172 gtk_menu_popup_at_widget(GTK_MENU(menu), widget, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
173 #else
174 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
175 menu_position_under, widget, event->button,
176 event->time);
177 #endif
178 return TRUE;
179 }
180 return FALSE;
181 }
182
183 /******************************************************************************
184 * Name
185 * on_button_parent_clicked
186 *
187 * Synopsis
188 * #include "gui/navbar_book.h"
189 *
190 * void on_button_parent_clicked(GtkButton * button, gpointer user_data)
191 *
192 * Description
193 * call main_navbar_book_parent() in main/navbar_book.cc
194 *
195 * Return value
196 * void
197 */
198
on_button_parent_clicked(GtkButton * button,gpointer user_data)199 static void on_button_parent_clicked(GtkButton *button, gpointer user_data)
200 {
201 if (!settings.havebook)
202 return;
203 main_navbar_book_parent();
204 }
205
206 /******************************************************************************
207 * Name
208 * on_button_child_clicked
209 *
210 * Synopsis
211 * #include "gui/navbar_book.h"
212 *
213 * void on_button_child_clicked(GtkButton * button, gpointer user_data)
214 *
215 * Description
216 * call main_navbar_book_first_child() in main/navbar_book.cc
217 *
218 * Return value
219 * void
220 */
221
on_button_child_clicked(GtkButton * button,gpointer user_data)222 static void on_button_child_clicked(GtkButton *button, gpointer user_data)
223 {
224 if (!settings.havebook)
225 return;
226 main_navbar_book_first_child();
227 }
228
229 /******************************************************************************
230 * Name
231 * on_button_prev_clicked
232 *
233 * Synopsis
234 * #include "gui/navbar_book.h"
235 *
236 * void on_button_prev_clicked(GtkButton * button, gpointer user_data)
237 *
238 * Description
239 * call main_navbar_book_prev() in main/navbar_book.cc
240 *
241 * Return value
242 * void
243 */
244
on_button_prev_clicked(GtkButton * button,gpointer user_data)245 static void on_button_prev_clicked(GtkButton *button, gpointer user_data)
246 {
247 if (!settings.havebook)
248 return;
249 main_navbar_book_prev();
250 }
251
252 /******************************************************************************
253 * Name
254 * on_button_next_clicked
255 *
256 * Synopsis
257 * #include "gui/navbar_book.h"
258 *
259 * void on_button_next_clicked(GtkButton * button, gpointer user_data)
260 *
261 * Description
262 * call main_navbar_book_next(); in main/navbar_book.cc
263 *
264 * Return value
265 * void
266 */
267
on_button_next_clicked(GtkButton * button,gpointer user_data)268 static void on_button_next_clicked(GtkButton *button, gpointer user_data)
269 {
270 if (!settings.havebook)
271 return;
272 main_navbar_book_next();
273 }
274
275 /******************************************************************************
276 * Name
277 * on_entry_activate
278 *
279 * Synopsis
280 * #include "gui/navbar_book.h"
281 *
282 * void on_entry_activate (GtkEntry *entry, gpointer user_data)
283 *
284 * Description
285 * get entry text and call main_navbar_book_entry_activate();
286 * in main/navbar_book.cc
287 *
288 * Return value
289 * void
290 */
291
on_entry_activate(GtkEntry * entry,gpointer user_data)292 void on_entry_activate(GtkEntry *entry, gpointer user_data)
293 {
294 const gchar *entry_buf = NULL;
295
296 entry_buf = gtk_entry_get_text(entry);
297 main_navbar_book_entry_activate(entry_buf);
298 }
299
300 /******************************************************************************
301 * Name
302 * gui_navbar_book_new
303 *
304 * Synopsis
305 * #include "gui/navbar_book.h"
306 *
307 * GtkWidget *gui_navbar_book_new(void)
308 *
309 * Description
310 * create a new gen book navigation toolbar and return it
311 *
312 * Return value
313 * GtkWidget *
314 */
315
gui_navbar_book_new(void)316 GtkWidget *gui_navbar_book_new(void)
317 {
318 GtkWidget *vbox1;
319 GtkWidget *hbox1;
320 GtkWidget *image1;
321 GtkWidget *arrow1;
322 GtkWidget *image2;
323
324 UI_VBOX(vbox1, FALSE, 0);
325 gtk_widget_show(vbox1);
326
327 UI_HBOX(hbox1, FALSE, 0);
328 gtk_widget_show(hbox1);
329 gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, TRUE, 0);
330
331 navbar_book.lookup_entry = gtk_entry_new();
332 gtk_widget_show(navbar_book.lookup_entry);
333 gtk_box_pack_start(GTK_BOX(hbox1), navbar_book.lookup_entry, TRUE,
334 TRUE, 0);
335 gtk_editable_set_editable(GTK_EDITABLE(navbar_book.lookup_entry),
336 TRUE);
337 gtk_entry_set_invisible_char(GTK_ENTRY(navbar_book.lookup_entry),
338 9679);
339
340 navbar_book.button_list = gtk_toggle_button_new();
341 gtk_widget_show(navbar_book.button_list);
342 gtk_box_pack_start(GTK_BOX(hbox1), navbar_book.button_list, FALSE,
343 FALSE, 0);
344
345 #if GTK_CHECK_VERSION(3, 14, 0)
346 arrow1 =
347 gtk_image_new_from_icon_name("open-menu-symbolic",
348 GTK_ICON_SIZE_BUTTON);
349 #else
350 arrow1 = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
351 #endif
352 gtk_widget_show(arrow1);
353 gtk_container_add(GTK_CONTAINER(navbar_book.button_list), arrow1);
354
355 navbar_book.button_left = gtk_button_new();
356 gtk_widget_show(navbar_book.button_left);
357 gtk_box_pack_start(GTK_BOX(hbox1), navbar_book.button_left, FALSE,
358 FALSE, 0);
359 gtk_widget_set_tooltip_text(navbar_book.button_left,
360 _("Go outward, to the section containing this one"));
361
362 gtk_button_set_relief(GTK_BUTTON(navbar_book.button_left),
363 GTK_RELIEF_NONE);
364 #if GTK_CHECK_VERSION(3, 20, 0)
365 gtk_widget_set_focus_on_click(GTK_WIDGET(navbar_book.button_left), FALSE);
366 #else
367 gtk_button_set_focus_on_click(GTK_BUTTON(navbar_book.button_left), FALSE);
368 #endif
369
370 image1 =
371 #if GTK_CHECK_VERSION(3, 10, 0)
372 gtk_image_new_from_icon_name("go-previous-symbolic", GTK_ICON_SIZE_BUTTON);
373 #else
374 gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON);
375 #endif
376 gtk_widget_show(image1);
377 gtk_container_add(GTK_CONTAINER(navbar_book.button_left), image1);
378
379 navbar_book.button_up = gtk_button_new();
380 gtk_widget_show(navbar_book.button_up);
381 gtk_box_pack_start(GTK_BOX(hbox1), navbar_book.button_up, FALSE,
382 FALSE, 0);
383 gtk_widget_set_tooltip_text(navbar_book.button_up,
384 _("Go to previous item"));
385 gtk_button_set_relief(GTK_BUTTON(navbar_book.button_up),
386 GTK_RELIEF_NONE);
387 #if GTK_CHECK_VERSION(3, 20, 0)
388 gtk_widget_set_focus_on_click(GTK_WIDGET(navbar_book.button_up), FALSE);
389 #else
390 gtk_button_set_focus_on_click(GTK_BUTTON(navbar_book.button_up), FALSE);
391 #endif
392
393 image1 =
394 #if GTK_CHECK_VERSION(3, 10, 0)
395 gtk_image_new_from_icon_name("go-up-symbolic", GTK_ICON_SIZE_BUTTON);
396 #else
397 gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
398 #endif
399 gtk_widget_show(image1);
400 gtk_container_add(GTK_CONTAINER(navbar_book.button_up), image1);
401
402 navbar_book.button_down = gtk_button_new();
403 gtk_widget_show(navbar_book.button_down);
404 gtk_box_pack_start(GTK_BOX(hbox1), navbar_book.button_down, FALSE,
405 FALSE, 0);
406 gtk_widget_set_tooltip_text(navbar_book.button_down,
407 _("Go to next item"));
408 gtk_button_set_relief(GTK_BUTTON(navbar_book.button_down),
409 GTK_RELIEF_NONE);
410 #if GTK_CHECK_VERSION(3, 20, 0)
411 gtk_widget_set_focus_on_click(GTK_WIDGET(navbar_book.button_down), FALSE);
412 #else
413 gtk_button_set_focus_on_click(GTK_BUTTON(navbar_book.button_down), FALSE);
414 #endif
415
416 image2 =
417 #if GTK_CHECK_VERSION(3, 10, 0)
418 gtk_image_new_from_icon_name("go-down-symbolic", GTK_ICON_SIZE_BUTTON);
419 #else
420 gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_BUTTON);
421 #endif
422
423 gtk_widget_show(image2);
424 gtk_container_add(GTK_CONTAINER(navbar_book.button_down), image2);
425
426 navbar_book.button_right = gtk_button_new();
427 gtk_widget_show(navbar_book.button_right);
428 gtk_box_pack_start(GTK_BOX(hbox1), navbar_book.button_right, FALSE,
429 FALSE, 0);
430 gtk_widget_set_tooltip_text(navbar_book.button_right,
431 _("Go inward, to the first subsection"));
432
433 gtk_button_set_relief(GTK_BUTTON(navbar_book.button_right),
434 GTK_RELIEF_NONE);
435 #if GTK_CHECK_VERSION(3, 20, 0)
436 gtk_widget_set_focus_on_click(GTK_WIDGET(navbar_book.button_right), FALSE);
437 #else
438 gtk_button_set_focus_on_click(GTK_BUTTON(navbar_book.button_right), FALSE);
439 #endif
440
441 image1 =
442 #if GTK_CHECK_VERSION(3, 10, 0)
443 gtk_image_new_from_icon_name("go-next-symbolic", GTK_ICON_SIZE_BUTTON);
444 #else
445 gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON);
446 #endif
447 gtk_widget_show(image1);
448 gtk_container_add(GTK_CONTAINER(navbar_book.button_right), image1);
449
450 g_signal_connect((gpointer)navbar_book.lookup_entry,
451 "activate", G_CALLBACK(on_entry_activate), NULL);
452 g_signal_connect((gpointer)navbar_book.button_up, "clicked",
453 G_CALLBACK(on_button_prev_clicked), NULL);
454 g_signal_connect((gpointer)navbar_book.button_down, "clicked",
455 G_CALLBACK(on_button_next_clicked), NULL);
456 g_signal_connect((gpointer)navbar_book.button_left, "clicked",
457 G_CALLBACK(on_button_parent_clicked), NULL);
458 g_signal_connect((gpointer)navbar_book.button_right, "clicked",
459 G_CALLBACK(on_button_child_clicked), NULL);
460 g_signal_connect((gpointer)navbar_book.button_list,
461 "button_press_event",
462 G_CALLBACK(select_button_press_callback), NULL);
463 g_signal_connect((gpointer)navbar_book.lookup_entry,
464 "key_press_event",
465 G_CALLBACK(lookup_entry_press_callback), NULL);
466 return vbox1;
467 }
468