From cad440fa3399b97e1c9c99b076982200151a5709 Mon Sep 17 00:00:00 2001 From: Christian Dywan Date: Sun, 31 Aug 2008 02:45:13 +0200 Subject: [PATCH] Show progress in location entry if statusbar is hidden --- AUTHORS | 2 + midori/midori-browser.c | 32 ++-- midori/midori-locationaction.c | 59 +++++++- midori/midori-locationaction.h | 7 + midori/midori-locationentry.c | 267 ++++++++++++++++++++++++++++++++- midori/midori-locationentry.h | 7 + 6 files changed, 362 insertions(+), 12 deletions(-) diff --git a/AUTHORS b/AUTHORS index 2b93c60c..161eb23a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -29,3 +29,5 @@ Translations: Code from other projects: GTK+/ GdkPixbuf, Matthias Clasen + GTK+/ GtkEntry, Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + Modified by the GTK+ Team and others 1997-2000 diff --git a/midori/midori-browser.c b/midori/midori-browser.c index 3db8f8e6..78aff86f 100644 --- a/midori/midori-browser.c +++ b/midori/midori-browser.c @@ -271,9 +271,9 @@ _midori_browser_update_interface (MidoriBrowser* browser) gtk_widget_set_sensitive (browser->throbber, FALSE); g_object_set (action, "stock-id", GTK_STOCK_REFRESH, - "tooltip", _("Reload the current page"), NULL); + "tooltip", _("Reload the current page"), + "sensitive", web_view != NULL, NULL); gtk_widget_hide (browser->progressbar); - gtk_action_set_sensitive (action, web_view != NULL); } else { @@ -282,6 +282,9 @@ _midori_browser_update_interface (MidoriBrowser* browser) "stock-id", GTK_STOCK_STOP, "tooltip", _("Stop loading the current page"), NULL); gtk_widget_show (browser->progressbar); + if (!GTK_WIDGET_VISIBLE (browser->statusbar)) + g_object_set (_action_by_name (browser, "Location"), "progress", + midori_web_view_get_progress (MIDORI_WEB_VIEW (web_view)), NULL); } katze_throbber_set_animated (KATZE_THROBBER (browser->throbber), loading); @@ -339,10 +342,15 @@ static void _midori_browser_update_progress (MidoriBrowser* browser, MidoriWebView* web_view) { + MidoriLocationAction* action; gdouble progress; gchar* message; + action = MIDORI_LOCATION_ACTION (_action_by_name (browser, "Location")); progress = midori_web_view_get_progress (web_view); + /* When we are finished, we don't want to *see* progress anymore */ + if (midori_web_view_get_load_status (web_view) == MIDORI_LOAD_FINISHED) + progress = 0.0; if (progress > 0.0) { gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (browser->progressbar), @@ -351,12 +359,15 @@ _midori_browser_update_progress (MidoriBrowser* browser, gtk_progress_bar_set_text (GTK_PROGRESS_BAR (browser->progressbar), message); g_free (message); + if (!GTK_WIDGET_VISIBLE (browser->statusbar)) + midori_location_action_set_progress (action, progress); } else { gtk_progress_bar_pulse (GTK_PROGRESS_BAR (browser->progressbar)); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (browser->progressbar), NULL); + midori_location_action_set_progress (action, 0.0); } } @@ -634,7 +645,7 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE); gtk_entry_set_text (GTK_ENTRY (entry_uri), katze_xbel_bookmark_get_href (bookmark)); - gtk_box_pack_start (GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), entry_uri, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox); gtk_widget_show_all (hbox); } @@ -661,7 +672,7 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, katze_xbel_item_set_title (bookmark, gtk_entry_get_text (GTK_ENTRY (entry_title))); katze_xbel_item_set_desc (bookmark, - gtk_entry_get_text(GTK_ENTRY(entry_desc))); + gtk_entry_get_text (GTK_ENTRY (entry_desc))); if (katze_xbel_item_is_bookmark (bookmark)) katze_xbel_bookmark_set_href (bookmark, gtk_entry_get_text (GTK_ENTRY (entry_uri))); @@ -1582,8 +1593,8 @@ _midori_browser_tab_set_highlight_text_matches (MidoriBrowser* browser, } static void -_action_find_activate(GtkAction* action, - MidoriBrowser* browser) +_action_find_activate (GtkAction* action, + MidoriBrowser* browser) { if (GTK_WIDGET_VISIBLE (browser->find)) { @@ -1609,7 +1620,7 @@ _midori_browser_find (MidoriBrowser* browser, { const gchar* text = gtk_entry_get_text (GTK_ENTRY (browser->find_text)); const gboolean case_sensitive = gtk_toggle_tool_button_get_active ( - GTK_TOGGLE_TOOL_BUTTON(browser->find_case)); + GTK_TOGGLE_TOOL_BUTTON (browser->find_case)); GtkWidget* widget = midori_browser_get_current_tab (browser); if (GTK_WIDGET_VISIBLE (browser->find)) _midori_browser_tab_unmark_text_matches (browser, widget); @@ -1772,6 +1783,9 @@ _action_statusbar_activate (GtkToggleAction* action, gboolean active = gtk_toggle_action_get_active (action); g_object_set (browser->settings, "show-statusbar", active, NULL); sokoke_widget_set_visible (browser->statusbar, active); + if (active) + g_object_set (_action_by_name (browser, "Location"), + "progress", 0.0, NULL); } static void @@ -3237,8 +3251,8 @@ midori_browser_init (MidoriBrowser* browser) browser->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar"); GtkWidget* menuitem = gtk_menu_item_new (); gtk_widget_show (menuitem); - browser->throbber = katze_throbber_new(); - gtk_widget_show(browser->throbber); + browser->throbber = katze_throbber_new (); + gtk_widget_show (browser->throbber); gtk_container_add (GTK_CONTAINER (menuitem), browser->throbber); gtk_widget_set_sensitive (menuitem, FALSE); gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE); diff --git a/midori/midori-locationaction.c b/midori/midori-locationaction.c index d8d285ac..503740b8 100644 --- a/midori/midori-locationaction.c +++ b/midori/midori-locationaction.c @@ -23,6 +23,7 @@ struct _MidoriLocationAction GtkAction parent_instance; gchar* uri; + gdouble progress; }; struct _MidoriLocationActionClass @@ -36,6 +37,7 @@ enum { PROP_0, + PROP_PROGRESS, PROP_SECONDARY_ICON }; @@ -138,11 +140,20 @@ midori_location_action_class_init (MidoriLocationActionClass* class) action_class->connect_proxy = midori_location_action_connect_proxy; action_class->disconnect_proxy = midori_location_action_disconnect_proxy; + g_object_class_install_property (gobject_class, + PROP_PROGRESS, + g_param_spec_double ( + "progress", + _("Progress"), + _("The current progress of the action"), + 0.0, 1.0, 0.0, + G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, PROP_SECONDARY_ICON, g_param_spec_string ( "secondary-icon", - "Secondary", + _("Secondary"), _("The stock ID of the secondary icon"), NULL, G_PARAM_WRITABLE)); @@ -152,6 +163,7 @@ static void midori_location_action_init (MidoriLocationAction* location_action) { location_action->uri = NULL; + location_action->progress = 0.0; } static void @@ -174,6 +186,12 @@ midori_location_action_set_property (GObject* object, switch (prop_id) { + case PROP_PROGRESS: + { + midori_location_action_set_progress (location_action, + g_value_get_double (value)); + break; + } case PROP_SECONDARY_ICON: { midori_location_action_set_secondary_icon (location_action, @@ -223,6 +241,8 @@ midori_location_action_create_tool_item (GtkAction* action) toolitem = GTK_WIDGET (gtk_tool_item_new ()); gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); entry = midori_location_entry_new (); + midori_location_entry_set_progress (MIDORI_LOCATION_ENTRY (entry), + MIDORI_LOCATION_ACTION (action)->progress); gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY ( gtk_bin_get_child (GTK_BIN (entry))), GTK_ICON_ENTRY_SECONDARY, TRUE); @@ -355,7 +375,6 @@ midori_location_action_set_uri (MidoriLocationAction* location_action, g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); g_return_if_fail (uri != NULL); - katze_assign (location_action->uri, g_strdup (uri)); proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); @@ -478,6 +497,42 @@ midori_location_action_set_title_for_uri (MidoriLocationAction* location_action, while ((proxies = g_slist_next (proxies))); } +gdouble +midori_location_action_get_progress (MidoriLocationAction* location_action) +{ + g_return_val_if_fail (MIDORI_IS_LOCATION_ACTION (location_action), 0.0); + + return location_action->progress; +} + +void +midori_location_action_set_progress (MidoriLocationAction* location_action, + gdouble progress) +{ + GSList* proxies; + GtkWidget* alignment; + GtkWidget* entry; + + g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); + + location_action->progress = CLAMP (progress, 0.0, 1.0); + + proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); + if (!proxies) + return; + + do + if (GTK_IS_TOOL_ITEM (proxies->data)) + { + alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); + entry = gtk_bin_get_child (GTK_BIN (alignment)); + + midori_location_entry_set_progress (MIDORI_LOCATION_ENTRY (entry), + location_action->progress); + } + while ((proxies = g_slist_next (proxies))); +} + void midori_location_action_set_secondary_icon (MidoriLocationAction* location_action, const gchar* stock_id) diff --git a/midori/midori-locationaction.h b/midori/midori-locationaction.h index 5310c4d1..c6d1e2cd 100644 --- a/midori/midori-locationaction.h +++ b/midori/midori-locationaction.h @@ -53,6 +53,13 @@ midori_location_action_set_title_for_uri (MidoriLocationAction* location_action const gchar* title, const gchar* text); +gdouble +midori_location_action_get_progress (MidoriLocationAction* location_action); + +void +midori_location_action_set_progress (MidoriLocationAction* location_action, + gdouble progress); + void midori_location_action_set_secondary_icon (MidoriLocationAction* location_action, const gchar* stock_id); diff --git a/midori/midori-locationentry.c b/midori/midori-locationentry.c index 24508505..70466eaf 100644 --- a/midori/midori-locationentry.c +++ b/midori/midori-locationentry.c @@ -20,6 +20,8 @@ struct _MidoriLocationEntry { GtkComboBoxEntry parent_instance; + + gdouble progress; }; struct _MidoriLocationEntryClass @@ -68,6 +70,263 @@ midori_location_entry_class_init (MidoriLocationEntryClass* class) G_TYPE_INT); } +#define HAVE_ENTRY_PROGRESS GTK_CHECK_VERSION (2, 10, 0) + +#ifdef HAVE_ENTRY_PROGRESS + +/* GTK+/ GtkEntry internal helper function + Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + Modified by the GTK+ Team and others 1997-2000 + Copied from Gtk+ 2.13, whitespace adjusted */ +static void +gtk_entry_get_pixel_ranges (GtkEntry *entry, + gint **ranges, + gint *n_ranges) +{ + gint start_char, end_char; + + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_char, &end_char)) + { + PangoLayout *layout = gtk_entry_get_layout (entry); + PangoLayoutLine *line = pango_layout_get_lines (layout)->data; + const char *text = pango_layout_get_text (layout); + gint start_index = g_utf8_offset_to_pointer (text, start_char) - text; + gint end_index = g_utf8_offset_to_pointer (text, end_char) - text; + gint real_n_ranges, i; + + pango_layout_line_get_x_ranges (line, start_index, end_index, ranges, &real_n_ranges); + + if (ranges) + { + gint *r = *ranges; + + for (i = 0; i < real_n_ranges; ++i) + { + r[2 * i + 1] = (r[2 * i + 1] - r[2 * i]) / PANGO_SCALE; + r[2 * i] = r[2 * i] / PANGO_SCALE; + } + } + + if (n_ranges) + *n_ranges = real_n_ranges; + } + else + { + if (n_ranges) + *n_ranges = 0; + if (ranges) + *ranges = NULL; + } +} + +/* GTK+/ GtkEntry internal helper function + Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + Modified by the GTK+ Team and others 1997-2000 + Copied from Gtk+ 2.13, whitespace adjusted + Code adjusted to not rely on internal qdata */ +static void +_gtk_entry_effective_inner_border (GtkEntry *entry, + GtkBorder *border) +{ + static const GtkBorder default_inner_border = { 2, 2, 2, 2 }; + GtkBorder *tmp_border; + + tmp_border = (GtkBorder*) gtk_entry_get_inner_border (entry); + + if (tmp_border) + { + *border = *tmp_border; + return; + } + + gtk_widget_style_get (GTK_WIDGET (entry), "inner-border", &tmp_border, NULL); + + if (tmp_border) + { + *border = *tmp_border; + gtk_border_free (tmp_border); + return; + } + + *border = default_inner_border; +} + +/* GTK+/ GtkEntry internal helper function + Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + Modified by the GTK+ Team and others 1997-2000 + Copied from Gtk+ 2.13, whitespace adjusted */ +static void +get_layout_position (GtkEntry *entry, + gint *x, + gint *y) +{ + PangoLayout *layout; + PangoRectangle logical_rect; + gint area_width, area_height; + GtkBorder inner_border; + gint y_pos; + PangoLayoutLine *line; + + layout = gtk_entry_get_layout (entry); + + GTK_ENTRY_CLASS (G_OBJECT_GET_CLASS (entry))->get_text_area_size (entry, NULL, NULL, &area_width, &area_height); + _gtk_entry_effective_inner_border (entry, &inner_border); + + area_height = PANGO_SCALE * (area_height - inner_border.top - inner_border.bottom); + + line = pango_layout_get_lines (layout)->data; + pango_layout_line_get_extents (line, NULL, &logical_rect); + + /* Align primarily for locale's ascent/descent */ + y_pos = ((area_height - entry->ascent - entry->descent) / 2 + + entry->ascent + logical_rect.y); + + /* Now see if we need to adjust to fit in actual drawn string */ + if (logical_rect.height > area_height) + y_pos = (area_height - logical_rect.height) / 2; + else if (y_pos < 0) + y_pos = 0; + else if (y_pos + logical_rect.height > area_height) + y_pos = area_height - logical_rect.height; + + y_pos = inner_border.top + y_pos / PANGO_SCALE; + + if (x) + *x = inner_border.left - entry->scroll_offset; + + if (y) + *y = y_pos; +} + +/* GTK+/ GtkEntry internal helper function + Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + Modified by the GTK+ Team and others 1997-2000 + Copied from Gtk+ 2.13, whitespace adjusted + Code adjusted to not rely on internal _gtk_entry_ensure_layout */ +static void +gtk_entry_draw_text (GtkEntry *entry) +{ + GtkWidget *widget; + + if (!entry->visible && entry->invisible_char == 0) + return; + + if (GTK_WIDGET_DRAWABLE (entry)) + { + PangoLayout *layout = gtk_entry_get_layout (entry); + cairo_t *cr; + gint x, y; + gint start_pos, end_pos; + + widget = GTK_WIDGET (entry); + + get_layout_position (entry, &x, &y); + + cr = gdk_cairo_create (entry->text_area); + + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]); + pango_cairo_show_layout (cr, layout); + + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) + { + gint *ranges; + gint n_ranges, i; + PangoRectangle logical_rect; + GdkColor *selection_color, *text_color; + GtkBorder inner_border; + + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges); + + if (GTK_WIDGET_HAS_FOCUS (entry)) + { + selection_color = &widget->style->base [GTK_STATE_SELECTED]; + text_color = &widget->style->text [GTK_STATE_SELECTED]; + } + else + { + selection_color = &widget->style->base [GTK_STATE_ACTIVE]; + text_color = &widget->style->text [GTK_STATE_ACTIVE]; + } + + _gtk_entry_effective_inner_border (entry, &inner_border); + + for (i = 0; i < n_ranges; ++i) + cairo_rectangle (cr, + inner_border.left - entry->scroll_offset + ranges[2 * i], + y, + ranges[2 * i + 1], + logical_rect.height); + + cairo_clip (cr); + + gdk_cairo_set_source_color (cr, selection_color); + cairo_paint (cr); + + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, text_color); + pango_cairo_show_layout (cr, layout); + + g_free (ranges); + } + + cairo_destroy (cr); + } +} + +static gboolean +entry_expose_event (GtkWidget* entry, + GdkEventExpose* event, + MidoriLocationEntry* location_entry) +{ + GdkWindow* text_area; + gint width, height; + + text_area = GTK_ENTRY (entry)->text_area; + + gdk_drawable_get_size (text_area, &width, &height); + + if (location_entry->progress > 0.0/* && location_entry->progress < 1.0*/) + { + gtk_paint_box (entry->style, text_area, + GTK_STATE_SELECTED, GTK_SHADOW_OUT, + &event->area, entry, "bar", + 0, 0, location_entry->progress * width, height); + gtk_entry_draw_text (GTK_ENTRY (entry)); + } + return FALSE; +} + +#endif + +gdouble +midori_location_entry_get_progress (MidoriLocationEntry* location_entry) +{ + g_return_val_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry), 0.0); + + return location_entry->progress; +} + +void +midori_location_entry_set_progress (MidoriLocationEntry* location_entry, + gdouble progress) +{ + #ifdef HAVE_ENTRY_PROGRESS + GtkWidget* child; + #endif + + g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry)); + + location_entry->progress = CLAMP (progress, 0.0, 1.0); + + #ifdef HAVE_ENTRY_PROGRESS + child = gtk_bin_get_child (GTK_BIN (location_entry)); + if (GTK_ENTRY (child)->text_area) + gdk_window_invalidate_rect (GTK_ENTRY (child)->text_area, NULL, FALSE); + #endif +} + static void midori_location_entry_init (MidoriLocationEntry* location_entry) { @@ -81,16 +340,22 @@ midori_location_entry_init (MidoriLocationEntry* location_entry) "widget_class \"*MidoriLocationEntry\" " "style \"midori-location-entry-style\"\n"); + location_entry->progress = 0.0; + entry = gtk_icon_entry_new (); gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), GTK_ICON_ENTRY_PRIMARY, DEFAULT_ICON); g_signal_connect (entry, "key-press-event", G_CALLBACK (entry_key_press_event), location_entry); + #ifdef HAVE_ENTRY_PROGRESS + g_signal_connect_after (entry, "expose-event", + G_CALLBACK (entry_expose_event), location_entry); + #endif gtk_widget_show (entry); gtk_container_add (GTK_CONTAINER (location_entry), entry); store = gtk_list_store_new (N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); g_object_set (G_OBJECT (location_entry), "model", store, NULL); - g_object_unref(store); + g_object_unref (store); gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (location_entry), URI_COL); gtk_cell_layout_clear (GTK_CELL_LAYOUT (location_entry)); diff --git a/midori/midori-locationentry.h b/midori/midori-locationentry.h index d6421b47..53f8a6fc 100644 --- a/midori/midori-locationentry.h +++ b/midori/midori-locationentry.h @@ -63,6 +63,13 @@ void midori_location_entry_add_item (MidoriLocationEntry* location_entry, MidoriLocationEntryItem* item); +gdouble +midori_location_entry_get_progress (MidoriLocationEntry* location_entry); + +void +midori_location_entry_set_progress (MidoriLocationEntry* location_entry, + gdouble progress); + G_END_DECLS #endif /* __MIDORI_LOCATION_ENTRY_H__ */