/* Copyright (C) 2008-2012 Christian Dywan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See the file COPYING for the full license text. */ #include "midori-findbar.h" #include "midori-browser.h" #include "midori-platform.h" #include #include #include #include "config.h" struct _MidoriFindbar { GtkToolbar parent_instance; GtkWidget* find_text; GtkToolItem* previous; GtkToolItem* next; GtkToolItem* find_case; GtkToolItem* find_close; gboolean find_typing; }; struct _MidoriFindbarClass { GtkToolbarClass parent_class; }; G_DEFINE_TYPE (MidoriFindbar, midori_findbar, GTK_TYPE_TOOLBAR); static void midori_findbar_class_init (MidoriFindbarClass* class) { /* Nothing to do */ } static void midori_findbar_set_icon (MidoriFindbar* findbar, GtkIconEntryPosition icon_pos, const gchar* icon_name) { if (icon_name != NULL) { gchar* symbolic_icon_name = g_strconcat (icon_name, "-symbolic", NULL); gtk_entry_set_icon_from_gicon (GTK_ENTRY (findbar->find_text), icon_pos, g_themed_icon_new_with_default_fallbacks (symbolic_icon_name)); g_free (symbolic_icon_name); } else gtk_icon_entry_set_icon_from_icon_name (GTK_ICON_ENTRY (findbar->find_text), icon_pos, NULL); } static void midori_findbar_done (MidoriFindbar* findbar) { MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (findbar)); GtkWidget* view = midori_browser_get_current_tab (browser); midori_tab_unmark_text_matches (MIDORI_TAB (view)); gtk_widget_hide (GTK_WIDGET (findbar)); findbar->find_typing = FALSE; gtk_widget_grab_focus (view); } static gboolean midori_findbar_find_key_press_event_cb (MidoriFindbar* findbar, GdkEventKey* event) { if (event->keyval == GDK_KEY_Escape) { midori_findbar_done (findbar); return TRUE; } else if (event->keyval == GDK_KEY_Return && (event->state & GDK_SHIFT_MASK)) { midori_findbar_continue (findbar, FALSE); return TRUE; } return FALSE; } static gboolean midori_findbar_case_sensitive (MidoriFindbar* findbar) { /* Smart case while typing: foo or fOO lowercase, Foo or FOO uppercase */ if (findbar->find_typing) { const gchar* text = gtk_entry_get_text (GTK_ENTRY (findbar->find_text)); return g_unichar_isupper (g_utf8_get_char (text)); } return gtk_toggle_tool_button_get_active ( GTK_TOGGLE_TOOL_BUTTON (findbar->find_case)); } void midori_findbar_continue (MidoriFindbar* findbar, gboolean forward) { MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (findbar)); const gchar* text; gboolean case_sensitive; GtkWidget* view; if (!(view = midori_browser_get_current_tab (browser))) return; text = gtk_entry_get_text (GTK_ENTRY (findbar->find_text)); case_sensitive = midori_findbar_case_sensitive (findbar); midori_tab_find (MIDORI_TAB (view), text, case_sensitive, forward); } /** * midori_findbar_get_text: * @findbar: #MidoriFindbar * * Returns: the text typed in the entry * * Since: 0.4.5 **/ const gchar* midori_findbar_get_text (MidoriFindbar* findbar) { g_return_val_if_fail (MIDORI_IS_FINDBAR (findbar), NULL); return gtk_entry_get_text (GTK_ENTRY (findbar->find_text)); } void midori_findbar_invoke (MidoriFindbar* findbar, const gchar* selected_text) { if (gtk_widget_get_visible (GTK_WIDGET (findbar))) gtk_widget_grab_focus (GTK_WIDGET (findbar->find_text)); else { midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_PRIMARY, STOCK_EDIT_FIND); gtk_widget_show (GTK_WIDGET (findbar->find_case)); gtk_widget_show (GTK_WIDGET (findbar->find_close)); if (selected_text != NULL) gtk_entry_set_text (GTK_ENTRY (findbar->find_text), selected_text); gtk_widget_show (GTK_WIDGET (findbar)); gtk_widget_grab_focus (GTK_WIDGET (findbar->find_text)); } } static void midori_findbar_next_activate_cb (GtkWidget* entry, MidoriFindbar* findbar) { midori_findbar_continue (findbar, TRUE); } static void midori_findbar_previous_clicked_cb (GtkWidget* entry, MidoriFindbar* findbar) { midori_findbar_continue (findbar, FALSE); } static void midori_findbar_button_close_clicked_cb (GtkWidget* widget, MidoriFindbar* findbar) { midori_findbar_done (findbar); } static void midori_findbar_preedit_changed_cb (GtkWidget* entry, const gchar* preedit, MidoriFindbar* findbar) { MidoriBrowser* browser = midori_browser_get_for_widget (entry); GtkWidget* view = midori_browser_get_current_tab (browser); midori_tab_unmark_text_matches (MIDORI_TAB (view)); if (g_utf8_strlen (preedit, -1) >= 1) { gboolean case_sensitive = midori_findbar_case_sensitive (findbar); midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_SECONDARY, STOCK_EDIT_CLEAR); midori_tab_find (MIDORI_TAB (view), preedit, case_sensitive, TRUE); } else midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_SECONDARY, NULL); } static void midori_findbar_text_changed_cb (GtkWidget* entry, MidoriFindbar* findbar) { const gchar* text = gtk_entry_get_text (GTK_ENTRY (entry)); midori_findbar_preedit_changed_cb (entry, text, findbar); } static gboolean midori_findbar_text_focus_out_event_cb (GtkWidget* entry, GdkEventFocus* event, MidoriFindbar* findbar) { if (findbar->find_typing) midori_findbar_done (findbar); return FALSE; } static void midori_findbar_init (MidoriFindbar* findbar) { GtkToolItem* toolitem; gtk_widget_set_name (GTK_WIDGET (findbar), "MidoriFindbar"); katze_widget_add_class (GTK_WIDGET (findbar), "bottom-toolbar"); gtk_toolbar_set_icon_size (GTK_TOOLBAR (findbar), GTK_ICON_SIZE_MENU); gtk_toolbar_set_style (GTK_TOOLBAR (findbar), GTK_TOOLBAR_BOTH_HORIZ); gtk_toolbar_set_show_arrow (GTK_TOOLBAR (findbar), FALSE); g_signal_connect (findbar, "key-press-event", G_CALLBACK (midori_findbar_find_key_press_event_cb), NULL); toolitem = gtk_tool_item_new (); gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6); gtk_container_add (GTK_CONTAINER (toolitem), /* i18n: A panel at the bottom, to search text in pages */ gtk_label_new_with_mnemonic (_("_Inline Find:"))); gtk_toolbar_insert (GTK_TOOLBAR (findbar), toolitem, -1); findbar->find_text = sokoke_search_entry_new (NULL); g_signal_connect (findbar->find_text, "activate", G_CALLBACK (midori_findbar_next_activate_cb), findbar); g_signal_connect (findbar->find_text, "preedit-changed", G_CALLBACK (midori_findbar_preedit_changed_cb), findbar); g_signal_connect (findbar->find_text, "changed", G_CALLBACK (midori_findbar_text_changed_cb), findbar); g_signal_connect (findbar->find_text, "focus-out-event", G_CALLBACK (midori_findbar_text_focus_out_event_cb), findbar); toolitem = gtk_tool_item_new (); gtk_container_add (GTK_CONTAINER (toolitem), findbar->find_text); gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); gtk_toolbar_insert (GTK_TOOLBAR (findbar), toolitem, -1); findbar->previous = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK); g_signal_connect (findbar->previous, "clicked", G_CALLBACK (midori_findbar_previous_clicked_cb), findbar); gtk_tool_button_set_label (GTK_TOOL_BUTTON (findbar->previous), _("Previous")); gtk_tool_item_set_is_important (findbar->previous, TRUE); gtk_toolbar_insert (GTK_TOOLBAR (findbar), findbar->previous, -1); findbar->next = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD); g_signal_connect (findbar->next, "clicked", G_CALLBACK (midori_findbar_next_activate_cb), findbar); gtk_tool_button_set_label (GTK_TOOL_BUTTON (findbar->next), _("Next")); gtk_tool_item_set_is_important (findbar->next, TRUE); gtk_toolbar_insert (GTK_TOOLBAR (findbar), findbar->next, -1); findbar->find_case = gtk_toggle_tool_button_new_from_stock (GTK_STOCK_SPELL_CHECK); gtk_tool_button_set_label (GTK_TOOL_BUTTON (findbar->find_case), _("Match Case")); gtk_tool_item_set_is_important (GTK_TOOL_ITEM (findbar->find_case), TRUE); gtk_toolbar_insert (GTK_TOOLBAR (findbar), findbar->find_case, -1); toolitem = gtk_separator_tool_item_new (); gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE); gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); gtk_toolbar_insert (GTK_TOOLBAR (findbar), toolitem, -1); findbar->find_close = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE); gtk_tool_button_set_label (GTK_TOOL_BUTTON (findbar->find_close), _("Close Findbar")); g_signal_connect (findbar->find_close, "clicked", G_CALLBACK (midori_findbar_button_close_clicked_cb), findbar); gtk_toolbar_insert (GTK_TOOLBAR (findbar), findbar->find_close, -1); gtk_container_foreach (GTK_CONTAINER (findbar), (GtkCallback)(gtk_widget_show_all), NULL); } void midori_findbar_set_can_find (MidoriFindbar* findbar, gboolean can_find) { gtk_widget_set_sensitive (GTK_WIDGET (findbar->next), can_find); gtk_widget_set_sensitive (GTK_WIDGET (findbar->previous), can_find); } void midori_findbar_search_text (MidoriFindbar* findbar, GtkWidget* view, gboolean found, const gchar* typing) { const gchar* text; gboolean case_sensitive; midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_PRIMARY, found ? STOCK_EDIT_FIND : STOCK_STOP); if (typing) { gint position = -1; findbar->find_typing = TRUE; gtk_widget_hide (GTK_WIDGET (findbar->find_case)); gtk_widget_hide (GTK_WIDGET (findbar->find_close)); if (!gtk_widget_get_visible (GTK_WIDGET (findbar))) gtk_entry_set_text (GTK_ENTRY (findbar->find_text), ""); gtk_widget_show (GTK_WIDGET (findbar)); gtk_widget_grab_focus (findbar->find_text); gtk_editable_insert_text (GTK_EDITABLE (findbar->find_text), typing, -1, &position); gtk_editable_set_position (GTK_EDITABLE (findbar->find_text), -1); } if (gtk_widget_get_visible (GTK_WIDGET (findbar)) && !typing) { text = gtk_entry_get_text (GTK_ENTRY (findbar->find_text)); case_sensitive = midori_findbar_case_sensitive (findbar); midori_tab_find (MIDORI_TAB (view), text, case_sensitive, TRUE); } } void midori_findbar_set_close_button_left (MidoriFindbar* findbar, gboolean close_button_left) { g_object_ref (findbar->find_close); gtk_container_remove (GTK_CONTAINER (findbar), GTK_WIDGET (findbar->find_close)); gtk_toolbar_insert (GTK_TOOLBAR (findbar), findbar->find_close, close_button_left ? 0 : -1); g_object_unref (findbar->find_close); }