yelp-docbook-document: Get rid of last bits of tree store code
[yelp.git] / src / yelp-window.c
blob7f1889ae749f0d6c608793deff31d39d3d6c3fe0
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Copyright (C) 2010 Shaun McCance <shaunm@gnome.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Shaun McCance <shaunm@gnome.org>
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <math.h>
29 #include <gdk/gdkkeysyms.h>
30 #include <glib/gi18n.h>
31 #include <gtk/gtk.h>
33 #include "yelp-location-entry.h"
34 #include "yelp-settings.h"
35 #include "yelp-uri.h"
36 #include "yelp-view.h"
38 #include "yelp-application.h"
39 #include "yelp-window.h"
41 static void yelp_window_init (YelpWindow *window);
42 static void yelp_window_class_init (YelpWindowClass *klass);
43 static void yelp_window_dispose (GObject *object);
44 static void yelp_window_finalize (GObject *object);
45 static void yelp_window_get_property (GObject *object,
46 guint prop_id,
47 GValue *value,
48 GParamSpec *pspec);
49 static void yelp_window_set_property (GObject *object,
50 guint prop_id,
51 const GValue *value,
52 GParamSpec *pspec);
54 static void window_construct (YelpWindow *window);
55 static void window_new (GtkAction *action,
56 YelpWindow *window);
57 static gboolean window_map_event (YelpWindow *window,
58 GdkEvent *event,
59 gpointer user_data);
60 static gboolean window_configure_event (YelpWindow *window,
61 GdkEventConfigure *event,
62 gpointer user_data);
63 static void window_drag_received (YelpWindow *window,
64 GdkDragContext *context,
65 gint x,
66 gint y,
67 GtkSelectionData *data,
68 guint info,
69 guint time,
70 gpointer userdata);
71 static gboolean window_resize_signal (YelpWindow *window);
72 static void window_close (GtkAction *action,
73 YelpWindow *window);
74 static void window_go_all (GtkAction *action,
75 YelpWindow *window);
76 static void window_add_bookmark (GtkAction *action,
77 YelpWindow *window);
78 static void window_remove_bookmark (GtkAction *action,
79 YelpWindow *window);
80 static void window_load_bookmark (GtkAction *action,
81 YelpWindow *window);
82 static void window_find_in_page (GtkAction *action,
83 YelpWindow *window);
84 static void window_start_search (GtkAction *action,
85 YelpWindow *window);
86 static void window_open_location (GtkAction *action,
87 YelpWindow *window);
88 static void window_read_later (GtkAction *action,
89 YelpWindow *window);
90 static gboolean read_later_clicked (GtkLinkButton *button,
91 YelpWindow *window);
92 static void app_read_later_changed (YelpApplication *app,
93 const gchar *doc_uri,
94 YelpWindow *window);
95 static void app_bookmarks_changed (YelpApplication *app,
96 const gchar *doc_uri,
97 YelpWindow *window);
98 static void window_set_bookmarks (YelpWindow *window,
99 const gchar *doc_uri);
100 static void window_set_bookmark_action (YelpWindow *window);
101 static gboolean find_entry_focus_out (GtkEntry *entry,
102 GdkEventFocus *event,
103 YelpWindow *window);
104 static gboolean find_entry_key_press (GtkEntry *entry,
105 GdkEventKey *event,
106 YelpWindow *window);
107 static void find_entry_changed (GtkEntry *entry,
108 YelpWindow *window);
110 static gboolean entry_focus_in (GtkEntry *entry,
111 GdkEventFocus *event,
112 YelpWindow *window);
113 static gboolean entry_focus_out (YelpLocationEntry *entry,
114 GdkEventFocus *event,
115 YelpWindow *window);
117 static void view_new_window (YelpView *view,
118 YelpUri *uri,
119 YelpWindow *window);
120 static void view_loaded (YelpView *view,
121 YelpWindow *window);
122 static void view_uri_selected (YelpView *view,
123 GParamSpec *pspec,
124 YelpWindow *window);
125 static void view_root_title (YelpView *view,
126 GParamSpec *pspec,
127 YelpWindow *window);
128 static gboolean view_is_xref_uri (YelpView *view,
129 GtkAction *action,
130 const gchar *uri,
131 YelpWindow *window);
133 static void hidden_entry_activate (GtkEntry *entry,
134 YelpWindow *window);
135 static void hidden_entry_hide (YelpWindow *window);
136 static gboolean hidden_key_press (GtkWidget *widget,
137 GdkEventKey *event,
138 YelpWindow *window);
140 enum {
141 PROP_0,
142 PROP_APPLICATION
145 enum {
146 RESIZE_EVENT,
147 LAST_SIGNAL
150 static guint signals[LAST_SIGNAL] = { 0 };
152 G_DEFINE_TYPE (YelpWindow, yelp_window, GTK_TYPE_WINDOW);
153 #define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_WINDOW, YelpWindowPrivate))
155 static const gchar *YELP_UI =
156 "<ui>"
157 "<menubar>"
158 "<menu action='PageMenu'>"
159 "<menuitem action='NewWindow'/>"
160 "<menuitem action='Find'/>"
161 "<separator/>"
162 "<menuitem action='YelpViewPrint'/>"
163 "<separator/>"
164 "<menuitem action='CloseWindow'/>"
165 "</menu>"
166 "<menu action='ViewMenu'>"
167 "<menuitem action='LargerText'/>"
168 "<menuitem action='SmallerText'/>"
169 "<separator/>"
170 "<menuitem action='ShowTextCursor'/>"
171 "</menu>"
172 "<menu action='GoMenu'>"
173 "<menuitem action='YelpViewGoBack'/>"
174 "<menuitem action='YelpViewGoForward'/>"
175 "<separator/>"
176 "<menuitem action='YelpViewGoPrevious'/>"
177 "<menuitem action='YelpViewGoNext'/>"
178 "<separator/>"
179 "<menuitem action='GoAll'/>"
180 "</menu>"
181 "<menu action='BookmarksMenu'>"
182 "<menuitem action='AddBookmark'/>"
183 "<menuitem action='RemoveBookmark'/>"
184 "<separator/>"
185 "<placeholder name='Bookmarks'/>"
186 "</menu>"
187 "</menubar>"
188 "<accelerator action='Find'/>"
189 "<accelerator action='Search'/>"
190 "<accelerator action='OpenLocation'/>"
191 "</ui>";
193 typedef struct _YelpWindowPrivate YelpWindowPrivate;
194 struct _YelpWindowPrivate {
195 GtkListStore *history;
196 GtkUIManager *ui_manager;
197 GtkActionGroup *action_group;
198 YelpApplication *application;
200 gulong bookmarks_changed;
201 gulong read_later_changed;
203 /* no refs on these, owned by containers */
204 YelpView *view;
205 GtkWidget *vbox_view;
206 GtkWidget *vbox_full;
207 GtkWidget *hbox;
208 YelpLocationEntry *entry;
209 GtkWidget *hidden_entry;
210 GtkWidget *find_entry;
211 GtkWidget *find_label;
212 GtkWidget *read_later_vbox;
214 /* refs because we dynamically add & remove */
215 GtkWidget *find_bar;
216 GtkWidget *align_location;
217 GtkWidget *align_hidden;
218 GtkWidget *read_later;
220 gchar *doc_uri;
222 GtkActionGroup *bookmark_actions;
223 guint bookmarks_merge_id;
225 guint resize_signal;
226 gint width;
227 gint height;
229 guint entry_color_animate;
230 gfloat entry_color_step;
232 gboolean configured;
235 static const GtkActionEntry entries[] = {
236 { "PageMenu", NULL, N_("_Page") },
237 { "ViewMenu", NULL, N_("_View") },
238 { "GoMenu", NULL, N_("_Go") },
239 { "BookmarksMenu", NULL, N_("_Bookmarks") },
241 { "NewWindow", NULL,
242 N_("_New Window"),
243 "<Control>N",
244 NULL,
245 G_CALLBACK (window_new) },
246 { "CloseWindow", NULL,
247 N_("_Close"),
248 "<Control>W",
249 NULL,
250 G_CALLBACK (window_close) },
251 { "GoAll", NULL,
252 N_("_All Documents"),
253 NULL, NULL,
254 G_CALLBACK (window_go_all) },
255 { "AddBookmark", NULL,
256 N_("_Add Bookmark"),
257 "<Control>D",
258 NULL,
259 G_CALLBACK (window_add_bookmark) },
260 { "RemoveBookmark", NULL,
261 N_("_Remove Bookmark"),
262 NULL, NULL,
263 G_CALLBACK (window_remove_bookmark) },
264 { "Find", NULL,
265 N_("Find in Page..."),
266 "<Control>F",
267 NULL,
268 G_CALLBACK (window_find_in_page) },
269 { "Search", NULL,
270 N_("Search..."),
271 "<Control>S",
272 NULL,
273 G_CALLBACK (window_start_search) },
274 { "OpenLocation", NULL,
275 N_("Open Location"),
276 "<Control>L",
277 NULL,
278 G_CALLBACK (window_open_location) }
281 static void
282 yelp_window_init (YelpWindow *window)
284 g_signal_connect (window, "configure-event", G_CALLBACK (window_configure_event), NULL);
285 g_signal_connect (window, "map-event", G_CALLBACK (window_map_event), NULL);
288 static void
289 yelp_window_class_init (YelpWindowClass *klass)
291 GObjectClass *object_class = G_OBJECT_CLASS (klass);
293 object_class->dispose = yelp_window_dispose;
294 object_class->finalize = yelp_window_finalize;
295 object_class->get_property = yelp_window_get_property;
296 object_class->set_property = yelp_window_set_property;
298 g_object_class_install_property (object_class,
299 PROP_APPLICATION,
300 g_param_spec_object ("application",
301 _("Application"),
302 _("A YelpApplication instance that controls this window"),
303 YELP_TYPE_APPLICATION,
304 G_PARAM_CONSTRUCT_ONLY |
305 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
306 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
308 signals[RESIZE_EVENT] =
309 g_signal_new ("resized",
310 G_OBJECT_CLASS_TYPE (klass),
311 G_SIGNAL_RUN_LAST,
312 0, NULL, NULL,
313 g_cclosure_marshal_VOID__VOID,
314 G_TYPE_NONE, 0);
316 g_type_class_add_private (klass, sizeof (YelpWindowPrivate));
319 static void
320 yelp_window_dispose (GObject *object)
322 YelpWindowPrivate *priv = GET_PRIV (object);
324 if (priv->history) {
325 g_object_unref (priv->history);
326 priv->history = NULL;
329 if (priv->action_group) {
330 g_object_unref (priv->action_group);
331 priv->action_group = NULL;
334 if (priv->bookmark_actions) {
335 g_object_unref (priv->bookmark_actions);
336 priv->bookmark_actions = NULL;
339 if (priv->read_later_changed) {
340 g_source_remove (priv->read_later_changed);
341 priv->read_later_changed = 0;
344 if (priv->bookmarks_changed) {
345 g_source_remove (priv->bookmarks_changed);
346 priv->bookmarks_changed = 0;
349 if (priv->align_location) {
350 g_object_unref (priv->align_location);
351 priv->align_location = NULL;
354 if (priv->align_hidden) {
355 g_object_unref (priv->align_hidden);
356 priv->align_hidden = NULL;
359 if (priv->find_bar) {
360 g_object_unref (priv->find_bar);
361 priv->find_bar = NULL;
364 if (priv->entry_color_animate != 0) {
365 g_source_remove (priv->entry_color_animate);
366 priv->entry_color_animate = 0;
369 G_OBJECT_CLASS (yelp_window_parent_class)->dispose (object);
372 static void
373 yelp_window_finalize (GObject *object)
375 YelpWindowPrivate *priv = GET_PRIV (object);
376 g_free (priv->doc_uri);
377 G_OBJECT_CLASS (yelp_window_parent_class)->finalize (object);
380 static void
381 yelp_window_get_property (GObject *object,
382 guint prop_id,
383 GValue *value,
384 GParamSpec *pspec)
386 YelpWindowPrivate *priv = GET_PRIV (object);
387 switch (prop_id) {
388 case PROP_APPLICATION:
389 g_value_set_object (value, priv->application);
390 break;
391 default:
392 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
393 break;
397 static void
398 yelp_window_set_property (GObject *object,
399 guint prop_id,
400 const GValue *value,
401 GParamSpec *pspec)
403 YelpWindowPrivate *priv = GET_PRIV (object);
404 switch (prop_id) {
405 case PROP_APPLICATION:
406 priv->application = g_value_get_object (value);
407 window_construct ((YelpWindow *) object);
408 break;
409 default:
410 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
411 break;
415 static void
416 window_construct (YelpWindow *window)
418 GtkWidget *scroll;
419 GtkActionGroup *view_actions;
420 GtkAction *action;
421 GtkWidget *vbox, *button, *label;
422 gchar *color, *text;
423 YelpWindowPrivate *priv = GET_PRIV (window);
425 gtk_window_set_icon_name (GTK_WINDOW (window), "help-browser");
427 priv->view = (YelpView *) yelp_view_new ();
429 action = gtk_action_new ("ReadLinkLater", _("Read Link _Later"), NULL, NULL);
430 g_signal_connect (action, "activate", G_CALLBACK (window_read_later), window);
431 yelp_view_add_link_action (priv->view, action,
432 (YelpViewActionValidFunc) view_is_xref_uri,
433 window);
434 priv->read_later_changed =
435 g_signal_connect (priv->application, "read-later-changed",
436 G_CALLBACK (app_read_later_changed), window);
438 priv->vbox_full = gtk_vbox_new (FALSE, 3);
439 gtk_container_add (GTK_CONTAINER (window), priv->vbox_full);
441 priv->vbox_view = gtk_vbox_new (FALSE, 0);
442 gtk_box_pack_start (GTK_BOX (priv->vbox_full), priv->vbox_view, TRUE, TRUE, 0);
444 priv->action_group = gtk_action_group_new ("YelpWindowActions");
445 gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE);
446 gtk_action_group_add_actions (priv->action_group,
447 entries, G_N_ELEMENTS (entries),
448 window);
450 priv->bookmark_actions = gtk_action_group_new ("BookmarkActions");
451 gtk_action_group_set_translate_func (priv->bookmark_actions, NULL, NULL, NULL);
453 priv->ui_manager = gtk_ui_manager_new ();
454 gtk_ui_manager_insert_action_group (priv->ui_manager, priv->action_group, 0);
455 gtk_ui_manager_insert_action_group (priv->ui_manager, priv->bookmark_actions, 1);
456 gtk_ui_manager_insert_action_group (priv->ui_manager,
457 yelp_application_get_action_group (priv->application),
459 view_actions = yelp_view_get_action_group (priv->view);
460 gtk_ui_manager_insert_action_group (priv->ui_manager, view_actions, 3);
461 gtk_window_add_accel_group (GTK_WINDOW (window),
462 gtk_ui_manager_get_accel_group (priv->ui_manager));
463 gtk_ui_manager_add_ui_from_string (priv->ui_manager, YELP_UI, -1, NULL);
464 gtk_box_pack_start (GTK_BOX (priv->vbox_view),
465 gtk_ui_manager_get_widget (priv->ui_manager, "/ui/menubar"),
466 FALSE, FALSE, 0);
468 priv->bookmarks_merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
469 priv->bookmarks_changed =
470 g_signal_connect (priv->application, "bookmarks-changed",
471 G_CALLBACK (app_bookmarks_changed), window);
473 priv->hbox = gtk_hbox_new (FALSE, 0);
474 g_object_set (priv->hbox, "border-width", 2, NULL);
475 gtk_box_pack_start (GTK_BOX (priv->vbox_view), priv->hbox, FALSE, FALSE, 0);
477 action = gtk_action_group_get_action (view_actions, "YelpViewGoBack");
478 button = gtk_action_create_tool_item (action);
479 gtk_box_pack_start (GTK_BOX (priv->hbox),
480 button,
481 FALSE, FALSE, 0);
482 action = gtk_action_group_get_action (view_actions, "YelpViewGoForward");
483 button = gtk_action_create_tool_item (action);
484 gtk_box_pack_start (GTK_BOX (priv->hbox),
485 button,
486 FALSE, FALSE, 0);
488 priv->entry = (YelpLocationEntry *) yelp_location_entry_new (priv->view,
489 YELP_BOOKMARKS (priv->application));
490 g_signal_connect (gtk_bin_get_child (GTK_BIN (priv->entry)), "focus-in-event",
491 G_CALLBACK (entry_focus_in), window);
492 g_signal_connect (priv->entry, "focus-out-event",
493 G_CALLBACK (entry_focus_out), window);
495 priv->align_location = g_object_ref_sink (gtk_alignment_new (0.0, 0.5, 1.0, 0.0));
496 gtk_box_pack_start (GTK_BOX (priv->hbox),
497 GTK_WIDGET (priv->align_location),
498 TRUE, TRUE, 0);
499 gtk_container_add (GTK_CONTAINER (priv->align_location), GTK_WIDGET (priv->entry));
501 priv->hidden_entry = gtk_entry_new ();
502 priv->align_hidden = g_object_ref_sink (gtk_alignment_new (0.0, 0.5, 1.0, 0.0));
503 gtk_container_add (GTK_CONTAINER (priv->align_hidden), GTK_WIDGET (priv->hidden_entry));
505 g_signal_connect (priv->hidden_entry, "activate",
506 G_CALLBACK (hidden_entry_activate), window);
507 g_signal_connect_swapped (priv->hidden_entry, "focus-out-event",
508 G_CALLBACK (hidden_entry_hide), window);
509 g_signal_connect (priv->hidden_entry, "key-press-event",
510 G_CALLBACK (hidden_key_press), window);
512 scroll = gtk_scrolled_window_new (NULL, NULL);
513 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
514 GTK_POLICY_AUTOMATIC,
515 GTK_POLICY_AUTOMATIC);
516 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
517 GTK_SHADOW_IN);
518 gtk_box_pack_start (GTK_BOX (priv->vbox_view), scroll, TRUE, TRUE, 0);
520 priv->find_bar = g_object_ref_sink (gtk_hbox_new (FALSE, 6));
521 g_object_set (priv->find_bar,
522 "border-width", 2,
523 "margin-right", 16,
524 NULL);
526 label = gtk_label_new (_("Find:"));
527 gtk_box_pack_start (GTK_BOX (priv->find_bar), label, FALSE, FALSE, 6);
529 priv->find_entry = gtk_entry_new ();
530 g_signal_connect (priv->find_entry, "changed",
531 G_CALLBACK (find_entry_changed), window);
532 g_signal_connect (priv->find_entry, "key-press-event",
533 G_CALLBACK (find_entry_key_press), window);
534 g_signal_connect (priv->find_entry, "focus-out-event",
535 G_CALLBACK (find_entry_focus_out), window);
536 g_object_set (priv->find_entry, "width-request", 300, NULL);
537 gtk_box_pack_start (GTK_BOX (priv->find_bar), priv->find_entry, FALSE, FALSE, 0);
539 priv->find_label = gtk_label_new ("");
540 g_object_set (priv->find_label, "xalign", 0.0, NULL);
541 gtk_box_pack_start (GTK_BOX (priv->find_bar), priv->find_label, FALSE, FALSE, 0);
543 priv->read_later = g_object_ref_sink (gtk_info_bar_new ());
544 vbox = gtk_vbox_new (FALSE, 0);
545 color = yelp_settings_get_color (yelp_settings_get_default (),
546 YELP_SETTINGS_COLOR_TEXT_LIGHT);
547 text = g_markup_printf_escaped ("<span weight='bold' color='%s'>%s</span>",
548 color, _("Read Later"));
549 button = gtk_label_new (text);
550 g_object_set (button, "use-markup", TRUE, "xalign", 0.0, NULL);
551 g_free (color);
552 g_free (text);
553 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
554 gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (priv->read_later))),
555 vbox,
556 FALSE, FALSE, 0);
557 priv->read_later_vbox = gtk_vbox_new (FALSE, 0);
558 gtk_box_pack_start (GTK_BOX (vbox), priv->read_later_vbox, FALSE, FALSE, 0);
560 g_signal_connect (priv->view, "new-view-requested", G_CALLBACK (view_new_window), window);
561 g_signal_connect (priv->view, "loaded", G_CALLBACK (view_loaded), window);
562 g_signal_connect (priv->view, "notify::yelp-uri", G_CALLBACK (view_uri_selected), window);
563 g_signal_connect_swapped (priv->view, "notify::page-id",
564 G_CALLBACK (window_set_bookmark_action), window);
565 window_set_bookmark_action (window);
566 g_signal_connect (priv->view, "notify::root-title", G_CALLBACK (view_root_title), window);
567 gtk_container_add (GTK_CONTAINER (scroll), GTK_WIDGET (priv->view));
568 gtk_widget_grab_focus (GTK_WIDGET (priv->view));
570 gtk_drag_dest_set (GTK_WIDGET (window),
571 GTK_DEST_DEFAULT_ALL,
572 NULL, 0,
573 GDK_ACTION_COPY);
574 gtk_drag_dest_add_uri_targets (GTK_WIDGET (window));
575 g_signal_connect (window, "drag-data-received",
576 G_CALLBACK (window_drag_received), NULL);
579 /******************************************************************************/
581 YelpWindow *
582 yelp_window_new (YelpApplication *app)
584 YelpWindow *window;
586 window = (YelpWindow *) g_object_new (YELP_TYPE_WINDOW, "application", app, NULL);
588 return window;
591 void
592 yelp_window_load_uri (YelpWindow *window,
593 YelpUri *uri)
595 YelpWindowPrivate *priv = GET_PRIV (window);
597 yelp_view_load_uri (priv->view, uri);
600 YelpUri *
601 yelp_window_get_uri (YelpWindow *window)
603 YelpUri *uri;
604 YelpWindowPrivate *priv = GET_PRIV (window);
605 g_object_get (G_OBJECT (priv->view), "yelp-uri", &uri, NULL);
606 return uri;
609 void
610 yelp_window_get_geometry (YelpWindow *window,
611 gint *width,
612 gint *height)
614 YelpWindowPrivate *priv = GET_PRIV (window);
615 *width = priv->width;
616 *height = priv->height;
619 /******************************************************************************/
621 static void
622 window_new (GtkAction *action, YelpWindow *window)
624 YelpUri *yuri;
625 gchar *uri = NULL;
626 YelpWindowPrivate *priv = GET_PRIV (window);
628 g_object_get (priv->view, "yelp-uri", &yuri, NULL);
629 uri = yelp_uri_get_document_uri (yuri);
631 yelp_application_new_window (priv->application, uri);
633 g_free (uri);
634 g_object_unref (yuri);
637 static void
638 window_drag_received (YelpWindow *window,
639 GdkDragContext *context,
640 gint x,
641 gint y,
642 GtkSelectionData *data,
643 guint info,
644 guint time,
645 gpointer userdata)
647 gchar **uris = gtk_selection_data_get_uris (data);
648 if (uris && uris[0]) {
649 YelpUri *uri = yelp_uri_new (uris[0]);
650 yelp_window_load_uri (window, uri);
651 g_object_unref (uri);
652 g_strfreev (uris);
653 gtk_drag_finish (context, TRUE, FALSE, time);
655 gtk_drag_finish (context, FALSE, FALSE, time);
658 static gboolean
659 window_map_event (YelpWindow *window,
660 GdkEvent *event,
661 gpointer user_data)
663 YelpWindowPrivate *priv = GET_PRIV (window);
664 priv->configured = TRUE;
665 return FALSE;
668 static gboolean
669 window_configure_event (YelpWindow *window,
670 GdkEventConfigure *event,
671 gpointer user_data)
673 YelpWindowPrivate *priv = GET_PRIV (window);
674 gboolean skip = TRUE;
675 if (priv->width != event->width) {
676 skip = FALSE;
677 priv->width = event->width;
679 if (priv->height != event->height) {
680 skip = FALSE;
681 priv->height = event->height;
683 /* Skip the configure-event signals that GTK+ sends as it's mapping
684 * the window, and also skip if the event didn't change the size of
685 * the window (i.e. it was just a move).
687 if (!priv->configured || skip)
688 return FALSE;
690 if (priv->resize_signal > 0)
691 g_source_remove (priv->resize_signal);
692 priv->resize_signal = g_timeout_add (200,
693 (GSourceFunc) window_resize_signal,
694 window);
695 g_object_set (priv->find_entry, "width-request", 2 * priv->width / 3, NULL);
696 return FALSE;
699 static gboolean
700 window_resize_signal (YelpWindow *window)
702 YelpWindowPrivate *priv = GET_PRIV (window);
703 g_signal_emit (window, signals[RESIZE_EVENT], 0);
704 priv->resize_signal = 0;
705 return FALSE;
708 static void
709 window_close (GtkAction *action, YelpWindow *window)
711 gboolean ret;
712 g_signal_emit_by_name (window, "delete-event", NULL, &ret);
713 gtk_widget_destroy (GTK_WIDGET (window));
716 static void
717 window_go_all (GtkAction *action,
718 YelpWindow *window)
720 YelpWindowPrivate *priv = GET_PRIV (window);
721 yelp_view_load (priv->view, "help-list:");
724 static void
725 window_add_bookmark (GtkAction *action,
726 YelpWindow *window)
728 YelpUri *uri;
729 gchar *doc_uri, *page_id, *icon, *title;
730 YelpWindowPrivate *priv = GET_PRIV (window);
732 g_object_get (priv->view,
733 "yelp-uri", &uri,
734 "page-id", &page_id,
735 "page-icon", &icon,
736 "page-title", &title,
737 NULL);
738 doc_uri = yelp_uri_get_document_uri (uri);
739 yelp_application_add_bookmark (YELP_BOOKMARKS (priv->application),
740 doc_uri, page_id, icon, title);
741 g_free (doc_uri);
742 g_free (page_id);
743 g_free (icon);
744 g_free (title);
745 g_object_unref (uri);
748 static void
749 window_remove_bookmark (GtkAction *action,
750 YelpWindow *window)
752 YelpUri *uri;
753 gchar *doc_uri, *page_id;
754 YelpWindowPrivate *priv = GET_PRIV (window);
756 g_object_get (priv->view,
757 "yelp-uri", &uri,
758 "page-id", &page_id,
759 NULL);
760 doc_uri = yelp_uri_get_document_uri (uri);
761 yelp_application_remove_bookmark (YELP_BOOKMARKS (priv->application),
762 doc_uri, page_id);
763 g_free (doc_uri);
764 g_free (page_id);
765 g_object_unref (uri);
767 static void
768 window_load_bookmark (GtkAction *action,
769 YelpWindow *window)
771 YelpUri *base, *uri;
772 gchar *xref;
773 YelpWindowPrivate *priv = GET_PRIV (window);
775 /* Bookmark action names are prefixed with 'LoadBookmark-' */
776 xref = g_strconcat ("xref:", gtk_action_get_name (action) + 13, NULL);
777 g_object_get (priv->view, "yelp-uri", &base, NULL);
778 uri = yelp_uri_new_relative (base, xref);
780 yelp_view_load_uri (priv->view, uri);
782 g_object_unref (base);
783 g_object_unref (uri);
784 g_free (xref);
787 static void
788 app_bookmarks_changed (YelpApplication *app,
789 const gchar *doc_uri,
790 YelpWindow *window)
792 YelpUri *uri;
793 gchar *this_doc_uri;
794 YelpWindowPrivate *priv = GET_PRIV (window);
796 g_object_get (priv->view, "yelp-uri", &uri, NULL);
797 this_doc_uri = yelp_uri_get_document_uri (uri);
799 if (g_str_equal (this_doc_uri, doc_uri)) {
800 window_set_bookmarks (window, doc_uri);
803 g_free (this_doc_uri);
804 g_object_unref (uri);
807 typedef struct _YelpMenuEntry YelpMenuEntry;
808 struct _YelpMenuEntry {
809 gchar *page_id;
810 gchar *icon;
811 gchar *title;
814 static gint
815 entry_compare (YelpMenuEntry *a, YelpMenuEntry *b)
817 gint ret = yelp_settings_cmp_icons (a->icon, b->icon);
818 if (ret != 0)
819 return ret;
821 if (a->title && b->title)
822 return g_utf8_collate (a->title, b->title);
823 else if (b->title == NULL)
824 return -1;
825 else if (a->title == NULL)
826 return 1;
828 return 0;
831 static void
832 window_set_bookmarks (YelpWindow *window,
833 const gchar *doc_uri)
835 GVariant *value;
836 GVariantIter *iter;
837 gchar *page_id, *icon, *title;
838 YelpWindowPrivate *priv = GET_PRIV (window);
839 GSList *entries = NULL;
841 window_set_bookmark_action (window);
843 gtk_ui_manager_remove_ui (priv->ui_manager, priv->bookmarks_merge_id);
845 value = yelp_application_get_bookmarks (priv->application, doc_uri);
846 g_variant_get (value, "a(sss)", &iter);
847 while (g_variant_iter_loop (iter, "(&s&s&s)", &page_id, &icon, &title)) {
848 YelpMenuEntry *entry = g_new0 (YelpMenuEntry, 1);
849 entry->page_id = page_id;
850 entry->icon = g_strdup (icon);
851 entry->title = title;
852 entries = g_slist_insert_sorted (entries, entry, (GCompareFunc) entry_compare);
854 for ( ; entries != NULL; entries = g_slist_delete_link (entries, entries)) {
855 GSList *cur;
856 GtkAction *bookmark;
857 YelpMenuEntry *entry = (YelpMenuEntry *) entries->data;
858 gchar *action_id = g_strconcat ("LoadBookmark-", entry->page_id, NULL);
860 bookmark = gtk_action_group_get_action (priv->bookmark_actions, action_id);
861 if (bookmark) {
862 /* The action might have been set by a different document using
863 * the same page ID. We can just reuse the action, since it's
864 * just a page ID relative to the current URI, but we need to
865 * reset the title and icon.
867 g_object_set (bookmark,
868 "label", entry->title,
869 "icon-name", entry->icon,
870 NULL);
871 } else {
872 bookmark = gtk_action_new (action_id, entry->title, NULL, NULL);
873 g_signal_connect (bookmark, "activate",
874 G_CALLBACK (window_load_bookmark), window);
875 gtk_action_set_icon_name (bookmark, entry->icon);
876 gtk_action_group_add_action (priv->bookmark_actions, bookmark);
878 gtk_ui_manager_add_ui (priv->ui_manager,
879 priv->bookmarks_merge_id,
880 "ui/menubar/BookmarksMenu/Bookmarks",
881 action_id, action_id,
882 GTK_UI_MANAGER_MENUITEM,
883 FALSE);
884 gtk_ui_manager_ensure_update (priv->ui_manager);
885 for (cur = gtk_action_get_proxies (bookmark); cur != NULL; cur = cur->next) {
886 if (GTK_IS_IMAGE_MENU_ITEM (cur->data))
887 g_object_set (cur->data, "always-show-image", TRUE, NULL);
889 g_free (action_id);
890 g_free (entry->icon);
891 g_free (entry);
894 g_variant_iter_free (iter);
895 g_variant_unref (value);
898 static void
899 window_set_bookmark_action (YelpWindow *window)
901 YelpUri *uri = NULL;
902 gchar *doc_uri = NULL, *page_id = NULL;
903 GtkAction *action_add, *action_del;
904 gboolean bookmarked;
905 YelpWindowPrivate *priv = GET_PRIV (window);
907 action_add = gtk_action_group_get_action (priv->action_group, "AddBookmark");
908 action_del = gtk_action_group_get_action (priv->action_group, "RemoveBookmark");
910 g_object_get (priv->view,
911 "yelp-uri", &uri,
912 "page-id", &page_id,
913 NULL);
914 if (page_id == NULL || uri == NULL) {
915 gtk_action_set_sensitive (action_add, FALSE);
916 gtk_action_set_sensitive (action_del, FALSE);
917 goto done;
919 doc_uri = yelp_uri_get_document_uri (uri);
920 bookmarked = yelp_application_is_bookmarked (YELP_BOOKMARKS (priv->application),
921 doc_uri, page_id);
922 gtk_action_set_sensitive (action_add, !bookmarked);
923 gtk_action_set_sensitive (action_del, bookmarked);
925 done:
926 g_free (page_id);
927 g_free (doc_uri);
928 if (uri)
929 g_object_unref (uri);
932 static void
933 window_start_search (GtkAction *action, YelpWindow *window)
935 YelpWindowPrivate *priv = GET_PRIV (window);
937 yelp_location_entry_start_search (priv->entry);
940 static void
941 window_open_location (GtkAction *action, YelpWindow *window)
943 YelpUri *yuri = NULL;
944 gchar *uri = NULL;
945 GdkColor yellow;
946 gchar *color;
947 YelpWindowPrivate *priv = GET_PRIV (window);
949 gtk_container_remove (GTK_CONTAINER (priv->hbox),
950 priv->align_location);
951 gtk_box_pack_start (GTK_BOX (priv->hbox),
952 priv->align_hidden,
953 TRUE, TRUE, 0);
955 gtk_widget_show_all (priv->align_hidden);
956 gtk_entry_set_text (GTK_ENTRY (priv->hidden_entry), "");
957 gtk_widget_grab_focus (priv->hidden_entry);
959 color = yelp_settings_get_color (yelp_settings_get_default (),
960 YELP_SETTINGS_COLOR_YELLOW_BASE);
961 if (gdk_color_parse (color, &yellow)) {
962 gtk_widget_modify_base (priv->hidden_entry,
963 GTK_STATE_NORMAL,
964 &yellow);
966 g_free (color);
968 g_object_get (priv->view, "yelp-uri", &yuri, NULL);
969 if (yuri) {
970 uri = yelp_uri_get_canonical_uri (yuri);
971 g_object_unref (yuri);
973 if (uri) {
974 gchar *c;
975 gtk_entry_set_text (GTK_ENTRY (priv->hidden_entry), uri);
976 c = strchr (uri, ':');
977 if (c)
978 gtk_editable_select_region (GTK_EDITABLE (priv->hidden_entry), c - uri + 1, -1);
979 else
980 gtk_editable_select_region (GTK_EDITABLE (priv->hidden_entry), 5, -1);
981 g_free (uri);
985 static void
986 read_later_resolved (YelpUri *uri,
987 YelpWindow *window)
989 gchar *fulluri;
990 const gchar *text = (const gchar *) g_object_get_data ((GObject *) uri, "link-text");
991 YelpWindowPrivate *priv = GET_PRIV (window);
992 YelpUri *base;
993 gchar *doc_uri;
995 g_object_get (priv->view, "yelp-uri", &base, NULL);
996 doc_uri = yelp_uri_get_document_uri (uri);
997 fulluri = yelp_uri_get_canonical_uri (uri);
999 yelp_application_add_read_later (priv->application, doc_uri, fulluri, text);
1001 g_object_unref (base);
1002 g_free (doc_uri);
1003 g_free (fulluri);
1006 static void
1007 window_read_later (GtkAction *action,
1008 YelpWindow *window)
1010 YelpWindowPrivate *priv = GET_PRIV (window);
1011 YelpUri *uri;
1012 gchar *text;
1014 uri = yelp_view_get_active_link_uri (priv->view);
1015 text = yelp_view_get_active_link_text (priv->view);
1017 g_object_set_data_full ((GObject *) uri, "link-text", text, g_free);
1019 if (!yelp_uri_is_resolved (uri)) {
1020 g_signal_connect (uri, "resolved",
1021 G_CALLBACK (read_later_resolved),
1022 window);
1023 yelp_uri_resolve (uri);
1025 else {
1026 read_later_resolved (uri, window);
1030 static gboolean
1031 read_later_clicked (GtkLinkButton *button,
1032 YelpWindow *window)
1034 YelpWindowPrivate *priv = GET_PRIV (window);
1035 YelpUri *base;
1036 gchar *doc_uri;
1037 gchar *fulluri;
1039 fulluri = g_strdup (gtk_link_button_get_uri (button));
1041 g_object_get (priv->view, "yelp-uri", &base, NULL);
1042 doc_uri = yelp_uri_get_document_uri (base);
1044 yelp_application_remove_read_later (priv->application, doc_uri, fulluri);
1046 g_object_unref (base);
1047 g_free (doc_uri);
1049 yelp_view_load (priv->view, fulluri);
1051 g_free (fulluri);
1052 return TRUE;
1055 static void
1056 app_read_later_changed (YelpApplication *app,
1057 const gchar *doc_uri,
1058 YelpWindow *window)
1060 GVariant *value;
1061 GVariantIter *viter;
1062 gchar *uri, *title; /* do not free */
1063 GList *children;
1064 gboolean has_children = FALSE;
1065 YelpWindowPrivate *priv = GET_PRIV (window);
1067 children = gtk_container_get_children (GTK_CONTAINER (priv->read_later_vbox));
1068 while (children) {
1069 gtk_container_remove (GTK_CONTAINER (priv->read_later_vbox),
1070 GTK_WIDGET (children->data));
1071 children = g_list_delete_link (children, children);
1074 value = yelp_application_get_read_later (priv->application, doc_uri);
1075 g_variant_get (value, "a(ss)", &viter);
1076 while (g_variant_iter_loop (viter, "(&s&s)", &uri, &title)) {
1077 GtkWidget *align, *link;
1079 align = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
1080 g_object_set (align, "left-padding", 6, NULL);
1081 gtk_box_pack_start (GTK_BOX (priv->read_later_vbox), align, FALSE, FALSE, 0);
1083 link = gtk_link_button_new_with_label (uri, title);
1084 g_object_set (link, "xalign", 0.0, NULL);
1085 g_signal_connect (link, "activate-link", G_CALLBACK (read_later_clicked), window);
1086 gtk_container_add (GTK_CONTAINER (align), link);
1088 gtk_widget_show_all (align);
1089 has_children = TRUE;
1091 g_variant_iter_free (viter);
1092 g_variant_unref (value);
1094 if (has_children) {
1095 if (gtk_widget_get_parent (priv->read_later) == NULL) {
1096 gtk_box_pack_end (GTK_BOX (priv->vbox_full), priv->read_later, FALSE, FALSE, 0);
1097 gtk_widget_show_all (priv->read_later);
1100 else {
1101 if (gtk_widget_get_parent (priv->read_later) != NULL)
1102 gtk_container_remove (GTK_CONTAINER (priv->vbox_full), priv->read_later);
1106 static void
1107 window_find_in_page (GtkAction *action,
1108 YelpWindow *window)
1110 YelpWindowPrivate *priv = GET_PRIV (window);
1112 if (gtk_widget_get_parent (priv->find_bar) != NULL) {
1113 gtk_widget_grab_focus (priv->find_entry);
1114 return;
1117 g_object_set (priv->find_entry, "width-request", 2 * priv->width / 3, NULL);
1119 gtk_box_pack_end (GTK_BOX (priv->vbox_view), priv->find_bar, FALSE, FALSE, 0);
1120 gtk_widget_show_all (priv->find_bar);
1121 gtk_widget_grab_focus (priv->find_entry);
1124 static gboolean
1125 find_entry_key_press (GtkEntry *entry,
1126 GdkEventKey *event,
1127 YelpWindow *window)
1129 YelpWindowPrivate *priv = GET_PRIV (window);
1131 if (event->keyval == GDK_KEY_Escape) {
1132 gtk_widget_grab_focus (GTK_WIDGET (priv->view));
1133 return TRUE;
1136 if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) {
1137 gchar *text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
1138 webkit_web_view_search_text (WEBKIT_WEB_VIEW (priv->view),
1139 text, FALSE, TRUE, TRUE);
1140 g_free (text);
1141 return TRUE;
1144 return FALSE;
1147 static gboolean
1148 find_entry_focus_out (GtkEntry *entry,
1149 GdkEventFocus *event,
1150 YelpWindow *window)
1152 YelpWindowPrivate *priv = GET_PRIV (window);
1153 webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (priv->view));
1154 webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (priv->view), FALSE);
1155 if (gtk_widget_get_parent (priv->find_bar) != NULL)
1156 gtk_container_remove (GTK_CONTAINER (priv->vbox_view), priv->find_bar);
1157 return FALSE;
1160 static void
1161 find_entry_changed (GtkEntry *entry,
1162 YelpWindow *window)
1164 gchar *text;
1165 gint count;
1166 YelpWindowPrivate *priv = GET_PRIV (window);
1168 webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (priv->view));
1170 text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
1172 if (text[0] == '\0') {
1173 gtk_label_set_text (GTK_LABEL (priv->find_label), "");
1174 return;
1177 count = webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (priv->view),
1178 text, FALSE, 0);
1179 if (count > 0) {
1180 gchar *label = g_strdup_printf (ngettext ("%i match", "%i matches", count), count);
1181 webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (priv->view), TRUE);
1182 webkit_web_view_search_text (WEBKIT_WEB_VIEW (priv->view),
1183 text, FALSE, TRUE, TRUE);
1184 gtk_label_set_text (GTK_LABEL (priv->find_label), label);
1185 g_free (label);
1187 else {
1188 webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (priv->view), FALSE);
1189 gtk_label_set_text (GTK_LABEL (priv->find_label), _("No matches"));
1192 g_free (text);
1195 static gboolean
1196 entry_color_animate (YelpWindow *window)
1198 gchar *color;
1199 GdkColor yellow, base;
1200 YelpWindowPrivate *priv = GET_PRIV (window);
1202 color = yelp_settings_get_color (yelp_settings_get_default (),
1203 YELP_SETTINGS_COLOR_YELLOW_BASE);
1204 gdk_color_parse (color, &yellow);
1205 g_free (color);
1207 color = yelp_settings_get_color (yelp_settings_get_default (),
1208 YELP_SETTINGS_COLOR_BASE);
1209 gdk_color_parse (color, &base);
1210 g_free (color);
1212 yellow.red = priv->entry_color_step * yellow.red + (1.0 - priv->entry_color_step) * base.red;
1213 yellow.green = priv->entry_color_step * yellow.green + (1.0 - priv->entry_color_step) * base.green;
1214 yellow.blue = priv->entry_color_step * yellow.blue + (1.0 - priv->entry_color_step) * base.blue;
1216 gtk_widget_modify_base (gtk_bin_get_child (GTK_BIN (priv->entry)), GTK_STATE_NORMAL, &yellow);
1218 priv->entry_color_step -= 0.05;
1220 if (priv->entry_color_step < 0.0) {
1221 priv->entry_color_animate = 0;
1222 return FALSE;
1225 return TRUE;
1228 static gboolean
1229 entry_focus_in (GtkEntry *entry,
1230 GdkEventFocus *event,
1231 YelpWindow *window)
1233 YelpWindowPrivate *priv = GET_PRIV (window);
1235 if (priv->entry_color_animate != 0)
1236 return FALSE;
1238 priv->entry_color_step = 1.0;
1239 priv->entry_color_animate = g_timeout_add (40, (GSourceFunc) entry_color_animate, window);
1241 return FALSE;
1244 static gboolean
1245 entry_focus_out (YelpLocationEntry *entry,
1246 GdkEventFocus *event,
1247 YelpWindow *window)
1249 YelpWindowPrivate *priv = GET_PRIV (window);
1250 gtk_widget_grab_focus (GTK_WIDGET (priv->view));
1251 return FALSE;
1254 static void
1255 view_new_window (YelpView *view,
1256 YelpUri *uri,
1257 YelpWindow *window)
1259 YelpWindowPrivate *priv = GET_PRIV (window);
1260 yelp_application_new_window_uri (priv->application, uri);
1263 static void
1264 view_loaded (YelpView *view,
1265 YelpWindow *window)
1268 YelpUri *uri;
1269 gchar *doc_uri;
1270 YelpViewState state;
1271 GdkWindow *gdkwin;
1272 YelpWindowPrivate *priv = GET_PRIV (window);
1274 g_object_get (view,
1275 "yelp-uri", &uri,
1276 "state", &state,
1277 NULL);
1278 doc_uri = yelp_uri_get_document_uri (uri);
1280 gdkwin = gtk_widget_get_window (GTK_WIDGET (window));
1281 if (gdkwin != NULL)
1282 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
1284 if (state != YELP_VIEW_STATE_ERROR) {
1285 gchar *page_id, *icon, *title;
1286 g_object_get (view,
1287 "page-id", &page_id,
1288 "page-icon", &icon,
1289 "page-title", &title,
1290 NULL);
1291 yelp_application_update_bookmarks (priv->application,
1292 doc_uri,
1293 page_id,
1294 icon,
1295 title);
1296 app_read_later_changed (priv->application, doc_uri, window);
1297 g_free (page_id);
1298 g_free (icon);
1299 g_free (title);
1302 g_free (doc_uri);
1303 g_object_unref (uri);
1306 static void
1307 view_uri_selected (YelpView *view,
1308 GParamSpec *pspec,
1309 YelpWindow *window)
1311 YelpUri *uri;
1312 gchar *doc_uri;
1313 GdkWindow *gdkwin;
1314 YelpWindowPrivate *priv = GET_PRIV (window);
1316 g_object_get (G_OBJECT (view), "yelp-uri", &uri, NULL);
1317 if (uri == NULL)
1318 return;
1320 gdkwin = gtk_widget_get_window (GTK_WIDGET (window));
1321 if (gdkwin != NULL)
1322 gdk_window_set_cursor (gdkwin,
1323 gdk_cursor_new_for_display (gdk_window_get_display (gdkwin),
1324 GDK_WATCH));
1326 doc_uri = yelp_uri_get_document_uri (uri);
1327 if (priv->doc_uri == NULL || !g_str_equal (priv->doc_uri, doc_uri)) {
1328 window_set_bookmarks (window, doc_uri);
1329 g_free (priv->doc_uri);
1330 priv->doc_uri = doc_uri;
1332 else {
1333 g_free (doc_uri);
1336 g_object_unref (uri);
1339 static gboolean
1340 view_is_xref_uri (YelpView *view,
1341 GtkAction *action,
1342 const gchar *uri,
1343 YelpWindow *window)
1345 return g_str_has_prefix (uri, "xref:");
1348 static void
1349 view_root_title (YelpView *view,
1350 GParamSpec *pspec,
1351 YelpWindow *window)
1353 gchar *title;
1354 g_object_get (view, "root-title", &title, NULL);
1356 if (title) {
1357 gtk_window_set_title (GTK_WINDOW (window), title);
1358 g_free (title);
1359 } else {
1360 gtk_window_set_title (GTK_WINDOW (window), _("Help"));
1364 static void
1365 hidden_entry_activate (GtkEntry *entry,
1366 YelpWindow *window)
1368 YelpWindowPrivate *priv = GET_PRIV (window);
1369 YelpUri *uri = yelp_uri_new (gtk_entry_get_text (entry));
1371 yelp_window_load_uri (window, uri);
1372 g_object_unref (uri);
1374 gtk_widget_grab_focus (GTK_WIDGET (priv->view));
1377 static void
1378 hidden_entry_hide (YelpWindow *window)
1380 YelpWindowPrivate *priv = GET_PRIV (window);
1382 if (gtk_widget_get_parent (priv->align_hidden) != NULL) {
1383 gtk_container_remove (GTK_CONTAINER (priv->hbox),
1384 priv->align_hidden);
1385 gtk_box_pack_start (GTK_BOX (priv->hbox),
1386 priv->align_location,
1387 TRUE, TRUE, 0);
1391 static gboolean
1392 hidden_key_press (GtkWidget *widget,
1393 GdkEventKey *event,
1394 YelpWindow *window)
1396 YelpWindowPrivate *priv = GET_PRIV (window);
1397 if (event->keyval == GDK_KEY_Escape) {
1398 gtk_widget_grab_focus (GTK_WIDGET (priv->view));
1399 return TRUE;
1401 return FALSE;