diff --git a/po/POTFILES.in b/po/POTFILES.in index 87cc0c23..e02c4f10 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -54,6 +54,5 @@ shell/ev-sidebar-thumbnails.c shell/ev-utils.c shell/ev-window.c shell/ev-window-title.c -shell/ev-zoom-action-widget.c shell/main.c [type: gettext/glade]shell/evince-appmenu.ui diff --git a/shell/ev-window.c b/shell/ev-window.c index db259721..06ce072c 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -173,6 +173,7 @@ struct _EvWindowPrivate { GtkActionGroup *action_group; GtkActionGroup *view_popup_action_group; GtkActionGroup *attachment_popup_action_group; + GtkActionGroup *zoom_selector_popup_action_group; GtkRecentManager *recent_manager; GtkActionGroup *recent_action_group; guint recent_ui_id; @@ -474,8 +475,6 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window) ev_window_set_action_sensitive (ev_window, "ViewContinuous", has_pages); ev_window_set_action_sensitive (ev_window, "ViewDual", has_pages); ev_window_set_action_sensitive (ev_window, "ViewDualOddLeft", has_pages); - ev_window_set_action_sensitive (ev_window, "ViewFitPage", has_pages); - ev_window_set_action_sensitive (ev_window, "ViewFitWidth", has_pages); ev_window_set_action_sensitive (ev_window, "ViewReload", has_pages); ev_window_set_action_sensitive (ev_window, "ViewAutoscroll", has_pages); ev_window_set_action_sensitive (ev_window, "ViewInvertedColors", has_pages); @@ -597,7 +596,7 @@ update_chrome_flag (EvWindow *window, EvChrome flag, gboolean active) static void update_sizing_buttons (EvWindow *window) { - GtkActionGroup *action_group = window->priv->action_group; + GtkActionGroup *action_group = window->priv->zoom_selector_popup_action_group; GtkAction *action; gboolean fit_page, fit_width; @@ -3852,6 +3851,26 @@ ev_window_cmd_fit_width (GtkAction *action, EvWindow *ev_window) ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FIT_WIDTH); } +static void +ev_window_cmd_view_zoom_activate (GtkAction *action, + EvWindow *ev_window) +{ + const char *action_name = gtk_action_get_name (action); + gdouble zoom = 0; + guint i; + + for (i = 0; i < G_N_ELEMENTS (zoom_levels); i++) { + if (strcmp (action_name, zoom_levels[i].name) == 0) { + zoom = zoom_levels[i].level; + break; + } + } + g_assert (zoom > 0); + + ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FREE); + ev_document_model_set_scale (ev_window->priv->model, + zoom * get_screen_dpi (ev_window) / 72.0); +} static void ev_window_cmd_edit_select_all (GtkAction *action, EvWindow *ev_window) @@ -4766,15 +4785,24 @@ ev_window_zoom_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvWindow * } static void -ev_window_max_zoom_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvWindow *window) +ev_window_setup_zoom_actions_visibility (EvWindow *window, + gdouble max_scale) { - GtkAction *action; - gdouble max_scale; + GtkActionGroup *action_group = window->priv->zoom_selector_popup_action_group; + guint i; - max_scale = ev_document_model_get_max_scale (model); - action = gtk_action_group_get_action (window->priv->action_group, - ZOOM_CONTROL_ACTION); - ev_zoom_action_set_max_zoom_level (EV_ZOOM_ACTION (action), max_scale); + for (i = 0; i < G_N_ELEMENTS (zoom_levels); i++) { + GtkAction *action; + + action = gtk_action_group_get_action (action_group, zoom_levels[i].name); + gtk_action_set_visible (action, zoom_levels[i].level <= max_scale); + } +} + +static void +ev_window_max_zoom_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvWindow *window) +{ + ev_window_setup_zoom_actions_visibility (window, ev_document_model_get_max_scale (model)); } static void @@ -5612,6 +5640,8 @@ ev_window_dispose (GObject *object) priv->attachment_popup_action_group = NULL; } + g_clear_object (&priv->zoom_selector_popup_action_group); + if (priv->recent_action_group) { g_object_unref (priv->recent_action_group); priv->recent_action_group = NULL; @@ -5982,12 +6012,6 @@ static const GtkToggleActionEntry toggle_entries[] = { { "ViewPresentation", EV_STOCK_RUN_PRESENTATION, N_("Pre_sentation"), "F5", N_("Run document as a presentation"), G_CALLBACK (ev_window_cmd_view_presentation) }, - { "ViewFitPage", EV_STOCK_ZOOM_PAGE, N_("Fit Pa_ge"), NULL, - N_("Make the current document fill the window"), - G_CALLBACK (ev_window_cmd_view_fit_page) }, - { "ViewFitWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit _Width"), NULL, - N_("Make the current document fill the window width"), - G_CALLBACK (ev_window_cmd_view_fit_width) }, { "ViewInvertedColors", EV_STOCK_INVERTED_COLORS, N_("_Inverted Colors"), "I", N_("Show page contents with the colors inverted"), G_CALLBACK (ev_window_cmd_view_inverted_colors) }, @@ -5995,7 +6019,6 @@ static const GtkToggleActionEntry toggle_entries[] = { { "EditFind", "edit-find-symbolic", N_("_Find…"), "F", N_("Find a word or phrase in the document"), G_CALLBACK (ev_window_cmd_toggle_find) }, - }; /* Popups specific items */ @@ -6024,6 +6047,15 @@ static const GtkActionEntry attachment_popup_entries [] = { NULL, G_CALLBACK (ev_attachment_popup_cmd_save_attachment_as) }, }; +static const GtkToggleActionEntry zoom_selector_popup_actions[] = { + { "ViewFitPage", EV_STOCK_ZOOM_PAGE, N_("Fit Pa_ge"), NULL, + N_("Make the current document fill the window"), + G_CALLBACK (ev_window_cmd_view_fit_page) }, + { "ViewFitWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit _Width"), NULL, + N_("Make the current document fill the window width"), + G_CALLBACK (ev_window_cmd_view_fit_width) } +}; + static void sidebar_links_link_activated_cb (EvSidebarLinks *sidebar_links, EvLink *link, EvWindow *window) { @@ -6090,6 +6122,36 @@ zoom_action_activated_cb (EvZoomAction *action, gtk_widget_grab_focus (window->priv->view); } +static void +ev_window_register_zoom_selector_popup_actions (EvWindow *window) +{ + GtkActionGroup *action_group = window->priv->zoom_selector_popup_action_group; + guint i, new_ui_id; + + new_ui_id = gtk_ui_manager_new_merge_id (window->priv->ui_manager); + + for (i = 0; i < G_N_ELEMENTS (zoom_levels); i++) { + GtkAction *action; + + action = gtk_action_new (zoom_levels[i].name, + _(zoom_levels[i].name), + NULL, NULL); + g_signal_connect (action, "activate", + G_CALLBACK (ev_window_cmd_view_zoom_activate), + window); + gtk_action_group_add_action (action_group, action); + g_object_unref (action); + + gtk_ui_manager_add_ui (window->priv->ui_manager, + new_ui_id, + "/ZoomSelectorPopup/ViewZoomItems", + _(zoom_levels[i].name), + zoom_levels[i].name, + GTK_UI_MANAGER_MENUITEM, + FALSE); + } +} + static void register_custom_actions (EvWindow *window, GtkActionGroup *group) { @@ -6117,6 +6179,8 @@ register_custom_actions (EvWindow *window, GtkActionGroup *group) NULL); ev_zoom_action_set_model (EV_ZOOM_ACTION (action), window->priv->model); + ev_zoom_action_set_window (EV_ZOOM_ACTION (action), + window); g_signal_connect (action, "activated", G_CALLBACK (zoom_action_activated_cb), window); gtk_action_group_add_action (group, action); @@ -6178,14 +6242,6 @@ set_action_properties (GtkActionGroup *action_group) /*translators: this is the label for toolbar button*/ g_object_set (action, "short_label", _("Zoom Out"), NULL); - action = gtk_action_group_get_action (action_group, "ViewFitPage"); - /*translators: this is the label for toolbar button*/ - g_object_set (action, "short_label", _("Fit Page"), NULL); - - action = gtk_action_group_get_action (action_group, "ViewFitWidth"); - /*translators: this is the label for toolbar button*/ - g_object_set (action, "short_label", _("Fit Width"), NULL); - action = gtk_action_group_get_action (action_group, "LeaveFullscreen"); g_object_set (action, "is-important", TRUE, NULL); } @@ -7160,11 +7216,22 @@ ev_window_init (EvWindow *ev_window) gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager, action_group, 0); + action_group = gtk_action_group_new ("ZoomSelectorPopupActions"); + ev_window->priv->zoom_selector_popup_action_group = action_group; + gtk_action_group_set_translation_domain (action_group, NULL); + gtk_action_group_add_toggle_actions (action_group, zoom_selector_popup_actions, + G_N_ELEMENTS (zoom_selector_popup_actions), + ev_window); + gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager, + action_group, 0); + gtk_ui_manager_add_ui_from_resource (ev_window->priv->ui_manager, "/org/gnome/evince/shell/ui/evince.xml", &error); g_assert_no_error (error); + ev_window_register_zoom_selector_popup_actions (ev_window); + css_provider = gtk_css_provider_new (); _gtk_css_provider_load_from_resource (css_provider, "/org/gnome/evince/shell/ui/evince.css", @@ -7547,3 +7614,11 @@ ev_window_get_main_action_group (EvWindow *ev_window) return ev_window->priv->action_group; } + +GtkActionGroup * +ev_window_get_zoom_selector_action_group (EvWindow *ev_window) +{ + g_return_val_if_fail (EV_WINDOW (ev_window), NULL); + + return ev_window->priv->zoom_selector_popup_action_group; +} diff --git a/shell/ev-window.h b/shell/ev-window.h index 5c618e78..fd2d0b5d 100644 --- a/shell/ev-window.h +++ b/shell/ev-window.h @@ -68,26 +68,27 @@ struct _EvWindowClass { GtkApplicationWindowClass base_class; }; -GType ev_window_get_type (void) G_GNUC_CONST; -GtkWidget *ev_window_new (void); -const char *ev_window_get_uri (EvWindow *ev_window); -void ev_window_open_uri (EvWindow *ev_window, - const char *uri, - EvLinkDest *dest, - EvWindowRunMode mode, - const gchar *search_string); -void ev_window_open_document (EvWindow *ev_window, - EvDocument *document, - EvLinkDest *dest, - EvWindowRunMode mode, - const gchar *search_string); -gboolean ev_window_is_empty (const EvWindow *ev_window); -void ev_window_print_range (EvWindow *ev_window, - int first_page, - int last_page); -const gchar *ev_window_get_dbus_object_path (EvWindow *ev_window); -GtkUIManager *ev_window_get_ui_manager (EvWindow *ev_window); -GtkActionGroup *ev_window_get_main_action_group (EvWindow *ev_window); +GType ev_window_get_type (void) G_GNUC_CONST; +GtkWidget *ev_window_new (void); +const char *ev_window_get_uri (EvWindow *ev_window); +void ev_window_open_uri (EvWindow *ev_window, + const char *uri, + EvLinkDest *dest, + EvWindowRunMode mode, + const gchar *search_string); +void ev_window_open_document (EvWindow *ev_window, + EvDocument *document, + EvLinkDest *dest, + EvWindowRunMode mode, + const gchar *search_string); +gboolean ev_window_is_empty (const EvWindow *ev_window); +void ev_window_print_range (EvWindow *ev_window, + int first_page, + int last_page); +const gchar *ev_window_get_dbus_object_path (EvWindow *ev_window); +GtkUIManager *ev_window_get_ui_manager (EvWindow *ev_window); +GtkActionGroup *ev_window_get_main_action_group (EvWindow *ev_window); +GtkActionGroup *ev_window_get_zoom_selector_action_group (EvWindow *ev_window); G_END_DECLS diff --git a/shell/ev-zoom-action-widget.c b/shell/ev-zoom-action-widget.c index 379e43d6..95a7f3bf 100644 --- a/shell/ev-zoom-action-widget.c +++ b/shell/ev-zoom-action-widget.c @@ -21,48 +21,22 @@ #include "config.h" #include "ev-zoom-action-widget.h" +#include "ev-zoom-action.h" #include -struct _EvZoomActionWidgetPrivate { - GtkWidget *combo; - - EvDocumentModel *model; - gulong combo_changed_handler; -}; - -#define EV_ZOOM_FIT_PAGE (-3.0) -#define EV_ZOOM_FIT_WIDTH (-4.0) -#define EV_ZOOM_SEPARATOR (-5.0) - -static const struct { - const gchar *name; - float level; -} zoom_levels[] = { - { N_("Fit Page"), EV_ZOOM_FIT_PAGE }, - { N_("Fit Width"), EV_ZOOM_FIT_WIDTH }, - { NULL, EV_ZOOM_SEPARATOR }, - { N_("50%"), 0.5 }, - { N_("70%"), 0.7071067811 }, - { N_("85%"), 0.8408964152 }, - { N_("100%"), 1.0 }, - { N_("125%"), 1.1892071149 }, - { N_("150%"), 1.4142135623 }, - { N_("175%"), 1.6817928304 }, - { N_("200%"), 2.0 }, - { N_("300%"), 2.8284271247 }, - { N_("400%"), 4.0 }, - { N_("800%"), 8.0 }, - { N_("1600%"), 16.0 }, - { N_("3200%"), 32.0 }, - { N_("6400%"), 64.0 } +enum { + PROP_0, + PROP_POPUP_SHOWN }; -enum { - TEXT_COLUMN, - IS_SEPARATOR_COLUMN, +struct _EvZoomActionWidgetPrivate { + GtkWidget *entry; - N_COLUMNS + EvDocumentModel *model; + EvWindow *window; + GtkWidget *popup; + gboolean popup_shown; }; G_DEFINE_TYPE (EvZoomActionWidget, ev_zoom_action_widget, GTK_TYPE_TOOL_ITEM) @@ -73,14 +47,14 @@ static void ev_zoom_action_widget_set_zoom_level (EvZoomActionWidget *control, float zoom) { - GtkWidget *entry = gtk_bin_get_child (GTK_BIN (control->priv->combo)); - gchar *zoom_str; - float zoom_perc; - guint i; + gchar *zoom_str; + float zoom_perc; + guint i; for (i = 3; i < G_N_ELEMENTS (zoom_levels); i++) { if (ABS (zoom - zoom_levels[i].level) < EPSILON) { - gtk_entry_set_text (GTK_ENTRY (entry), zoom_levels[i].name); + gtk_entry_set_text (GTK_ENTRY (control->priv->entry), + zoom_levels[i].name); return; } } @@ -90,7 +64,7 @@ ev_zoom_action_widget_set_zoom_level (EvZoomActionWidget *control, zoom_str = g_strdup_printf ("%d%%", (gint)zoom_perc); else zoom_str = g_strdup_printf ("%.2f%%", zoom_perc); - gtk_entry_set_text (GTK_ENTRY (entry), zoom_str); + gtk_entry_set_text (GTK_ENTRY (control->priv->entry), zoom_str); g_free (zoom_str); } @@ -124,36 +98,7 @@ document_changed_cb (EvDocumentModel *model, } static void -combo_changed_cb (GtkComboBox *combo, - EvZoomActionWidget *control) -{ - gint index; - float zoom; - EvSizingMode mode; - - index = gtk_combo_box_get_active (combo); - if (index == -1) - return; - - zoom = zoom_levels[index].level; - if (zoom == EV_ZOOM_FIT_PAGE) - mode = EV_SIZING_FIT_PAGE; - else if (zoom == EV_ZOOM_FIT_WIDTH) - mode = EV_SIZING_FIT_WIDTH; - else - mode = EV_SIZING_FREE; - - ev_document_model_set_sizing_mode (control->priv->model, mode); - if (mode == EV_SIZING_FREE) { - GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (control)); - - ev_document_model_set_scale (control->priv->model, - zoom * ev_document_misc_get_screen_dpi (screen) / 72.0); - } -} - -static void -combo_activated_cb (GtkEntry *entry, +entry_activated_cb (GtkEntry *entry, EvZoomActionWidget *control) { GdkScreen *screen; @@ -181,124 +126,233 @@ combo_activated_cb (GtkEntry *entry, } static gboolean -combo_focus_out_cb (EvZoomActionWidget *control) +focus_out_cb (EvZoomActionWidget *control) { ev_zoom_action_widget_update_zoom_level (control); return FALSE; } -static gchar * -combo_format_entry_text (GtkComboBox *combo, - const gchar *path, - EvZoomActionWidget *control) +static gint +get_max_zoom_level_label (EvZoomActionWidget *control) { - GtkWidget *entry = gtk_bin_get_child (GTK_BIN (combo)); + GList *actions, *l; + gint width = 0; - return g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); + actions = gtk_action_group_list_actions (ev_window_get_zoom_selector_action_group (control->priv->window)); + + for (l = actions; l; l = g_list_next (l)) { + GtkAction *action = (GtkAction *)l->data; + int length; + + length = g_utf8_strlen (gtk_action_get_label (action), -1); + if (length > width) + width = length; + } + + g_list_free (actions); + + /* Count the toggle size as one character more */ + return width + 1; } -static gboolean -row_is_separator (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data) +static void +popup_menu_show_cb (GtkWidget *widget, + EvZoomActionWidget *control) { - gboolean is_sep; - - gtk_tree_model_get (model, iter, IS_SEPARATOR_COLUMN, &is_sep, -1); + control->priv->popup_shown = TRUE; + g_object_notify (G_OBJECT (control), "popup-shown"); +} - return is_sep; +static void +popup_menu_hide_cb (GtkWidget *widget, + EvZoomActionWidget *control) +{ + control->priv->popup_shown = FALSE; + g_object_notify (G_OBJECT (control), "popup-shown"); } static void -ev_zoom_action_widget_finalize (GObject *object) +popup_menu_detached (EvZoomActionWidget *control, + GtkWidget *popup) { - EvZoomActionWidget *control = EV_ZOOM_ACTION_WIDGET (object); + GtkWidget *toplevel; - ev_zoom_action_widget_set_model (control, NULL); + if (control->priv->popup != popup) + return; + + toplevel = gtk_widget_get_toplevel (control->priv->popup); + g_signal_handlers_disconnect_by_func (toplevel, + popup_menu_show_cb, + control); + g_signal_handlers_disconnect_by_func (toplevel, + popup_menu_hide_cb, + control); - G_OBJECT_CLASS (ev_zoom_action_widget_parent_class)->finalize (object); + control->priv->popup = NULL; } -static void -fill_combo_model (GtkListStore *model, - guint max_level) +static GtkWidget * +get_popup (EvZoomActionWidget *control) { - guint i; + GtkUIManager *ui_manager; + GtkWidget *toplevel; + + if (control->priv->popup) + return control->priv->popup; + + ui_manager = ev_window_get_ui_manager (control->priv->window); + control->priv->popup = gtk_ui_manager_get_widget (ui_manager, "/ZoomSelectorPopup"); + gtk_menu_attach_to_widget (GTK_MENU (control->priv->popup), GTK_WIDGET (control), + (GtkMenuDetachFunc)popup_menu_detached); + toplevel = gtk_widget_get_toplevel (control->priv->popup); + g_signal_connect (toplevel, "show", + G_CALLBACK (popup_menu_show_cb), + control); + g_signal_connect (toplevel, "hide", + G_CALLBACK (popup_menu_hide_cb), + control); - for (i = 0; i < max_level; i++) { - GtkTreeIter iter; + return control->priv->popup; +} - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - TEXT_COLUMN, _(zoom_levels[i].name), - IS_SEPARATOR_COLUMN, zoom_levels[i].name == NULL, - -1); +static void +menu_position_below (GtkMenu *menu, + gint *x, + gint *y, + gint *push_in, + gpointer user_data) +{ + EvZoomActionWidget *control; + GtkWidget *widget; + GtkAllocation child_allocation; + GtkRequisition req; + GdkScreen *screen; + gint monitor_num; + GdkRectangle monitor; + gint sx = 0, sy = 0; + + control = EV_ZOOM_ACTION_WIDGET (user_data); + widget = GTK_WIDGET (control); + + gtk_widget_get_allocation (control->priv->entry, &child_allocation); + + if (!gtk_widget_get_has_window (control->priv->entry)) { + sx += child_allocation.x; + sy += child_allocation.y; } + + gdk_window_get_root_coords (gtk_widget_get_window (control->priv->entry), + sx, sy, &sx, &sy); + + gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL); + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + *x = sx; + else + *x = sx + child_allocation.width - req.width; + *y = sy; + + screen = gtk_widget_get_screen (widget); + monitor_num = gdk_screen_get_monitor_at_window (screen, + gtk_widget_get_window (widget)); + gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor); + + if (*x < monitor.x) + *x = monitor.x; + else if (*x + req.width > monitor.x + monitor.width) + *x = monitor.x + monitor.width - req.width; + + if (monitor.y + monitor.height - *y - child_allocation.height >= req.height) + *y += child_allocation.height; + else if (*y - monitor.y >= req.height) + *y -= req.height; + else if (monitor.y + monitor.height - *y - child_allocation.height > *y - monitor.y) + *y += child_allocation.height; + else + *y -= req.height; + + *push_in = FALSE; } -static gint -get_max_zoom_level_label (void) +static void +entry_icon_press_callback (GtkEntry *entry, + GtkEntryIconPosition icon_pos, + GdkEventButton *event, + EvZoomActionWidget *control) { - gint i; - gint width = 0; + GtkWidget *menu; - for (i = 0; i < G_N_ELEMENTS (zoom_levels); i++) { - int length; + if (!control->priv->window || event->button != GDK_BUTTON_PRIMARY) + return; - length = zoom_levels[i].name ? strlen (_(zoom_levels[i].name)) : 0; - if (length > width) - width = length; - } + menu = get_popup (control); + gtk_widget_set_size_request (menu, + gtk_widget_get_allocated_width (GTK_WIDGET (control)), + -1); - return width; + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, + menu_position_below, control, + event->button, event->time); +} + +static gboolean +setup_initial_entry_size (EvZoomActionWidget *control) +{ + gtk_entry_set_width_chars (GTK_ENTRY (control->priv->entry), + get_max_zoom_level_label (control)); + return FALSE; } static void ev_zoom_action_widget_init (EvZoomActionWidget *control) { EvZoomActionWidgetPrivate *priv; - GtkWidget *entry; GtkWidget *vbox; - GtkListStore *store; control->priv = G_TYPE_INSTANCE_GET_PRIVATE (control, EV_TYPE_ZOOM_ACTION_WIDGET, EvZoomActionWidgetPrivate); priv = control->priv; - store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN); - fill_combo_model (store, G_N_ELEMENTS (zoom_levels)); - - priv->combo = gtk_combo_box_new_with_model_and_entry (GTK_TREE_MODEL (store)); - gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (priv->combo), FALSE); - gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->combo), TEXT_COLUMN); - gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (priv->combo), - (GtkTreeViewRowSeparatorFunc)row_is_separator, - NULL, NULL); - g_object_unref (store); - - entry = gtk_bin_get_child (GTK_BIN (priv->combo)); - gtk_entry_set_width_chars (GTK_ENTRY (entry), get_max_zoom_level_label ()); - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_box_pack_start (GTK_BOX (vbox), priv->combo, TRUE, FALSE, 0); - gtk_widget_show (priv->combo); + + priv->entry = gtk_entry_new (); + gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->entry), + GTK_ENTRY_ICON_SECONDARY, + "go-down-symbolic"); + gtk_box_pack_start (GTK_BOX (vbox), priv->entry, TRUE, FALSE, 0); + gtk_widget_show (priv->entry); gtk_container_add (GTK_CONTAINER (control), vbox); gtk_widget_show (vbox); - priv->combo_changed_handler = - g_signal_connect (priv->combo, "changed", - G_CALLBACK (combo_changed_cb), - control); - g_signal_connect (priv->combo, "format-entry-text", - G_CALLBACK (combo_format_entry_text), + g_signal_connect (priv->entry, "icon-press", + G_CALLBACK (entry_icon_press_callback), control); - g_signal_connect (entry, "activate", - G_CALLBACK (combo_activated_cb), + g_signal_connect (priv->entry, "activate", + G_CALLBACK (entry_activated_cb), control); - g_signal_connect_swapped (entry, "focus-out-event", - G_CALLBACK (combo_focus_out_cb), + g_signal_connect_swapped (priv->entry, "focus-out-event", + G_CALLBACK (focus_out_cb), control); + + g_idle_add ((GSourceFunc)setup_initial_entry_size, control); +} + +static void +ev_zoom_action_widget_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EvZoomActionWidget *control = EV_ZOOM_ACTION_WIDGET (object); + + switch (prop_id) { + case PROP_POPUP_SHOWN: + g_value_set_boolean (value, control->priv->popup_shown); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void @@ -306,7 +360,15 @@ ev_zoom_action_widget_class_init (EvZoomActionWidgetClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = ev_zoom_action_widget_finalize; + object_class->get_property = ev_zoom_action_widget_get_property; + + g_object_class_install_property (object_class, + PROP_POPUP_SHOWN, + g_param_spec_boolean ("popup-shown", + "Popup shown", + "Whether the zoom control's dropdown is shown", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_type_class_add_private (object_class, sizeof (EvZoomActionWidgetPrivate)); } @@ -349,36 +411,19 @@ ev_zoom_action_widget_set_model (EvZoomActionWidget *control, } void -ev_zoom_action_widget_set_max_zoom_level (EvZoomActionWidget *control, - float max_zoom) +ev_zoom_action_widget_set_window (EvZoomActionWidget *control, + EvWindow *window) { - EvZoomActionWidgetPrivate *priv; - GtkListStore *model; - guint max_level_index = 3; - guint i; - - g_return_if_fail (EV_IS_ZOOM_ACTION_WIDGET (control)); - - priv = control->priv; - - for (i = 3; i < G_N_ELEMENTS (zoom_levels); i++, max_level_index++) { - if (zoom_levels[i].level > max_zoom) - break; - } - - g_signal_handler_block (priv->combo, priv->combo_changed_handler); - - model = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->combo))); - gtk_list_store_clear (model); - fill_combo_model (model, max_level_index); + if (control->priv->window == window) + return; - g_signal_handler_unblock (priv->combo, priv->combo_changed_handler); + control->priv->window = window; } GtkWidget * -ev_zoom_action_widget_get_combo_box (EvZoomActionWidget *control) +ev_zoom_action_widget_get_entry (EvZoomActionWidget *control) { g_return_val_if_fail (EV_IS_ZOOM_ACTION_WIDGET (control), NULL); - return control->priv->combo; + return control->priv->entry; } diff --git a/shell/ev-zoom-action-widget.h b/shell/ev-zoom-action-widget.h index c42c7d33..a2dc293f 100644 --- a/shell/ev-zoom-action-widget.h +++ b/shell/ev-zoom-action-widget.h @@ -25,6 +25,8 @@ #include #include +#include "ev-window.h" + G_BEGIN_DECLS #define EV_TYPE_ZOOM_ACTION_WIDGET (ev_zoom_action_widget_get_type()) @@ -48,13 +50,13 @@ struct _EvZoomActionWidgetClass { GtkToolItemClass parent_class; }; -GType ev_zoom_action_widget_get_type (void); +GType ev_zoom_action_widget_get_type (void); -void ev_zoom_action_widget_set_model (EvZoomActionWidget *control, - EvDocumentModel *model); -GtkWidget *ev_zoom_action_widget_get_combo_box (EvZoomActionWidget *control); -void ev_zoom_action_widget_set_max_zoom_level (EvZoomActionWidget *control, - float max_zoom); +void ev_zoom_action_widget_set_model (EvZoomActionWidget *control, + EvDocumentModel *model); +GtkWidget *ev_zoom_action_widget_get_entry (EvZoomActionWidget *control); +void ev_zoom_action_widget_set_window (EvZoomActionWidget *control, + EvWindow *window); G_END_DECLS diff --git a/shell/ev-zoom-action.c b/shell/ev-zoom-action.c index f75d853e..920fb9c2 100644 --- a/shell/ev-zoom-action.c +++ b/shell/ev-zoom-action.c @@ -31,8 +31,8 @@ enum { struct _EvZoomActionPrivate { EvDocumentModel *model; + EvWindow *window; gboolean popup_shown; - float max_zoom; }; G_DEFINE_TYPE (EvZoomAction, ev_zoom_action, GTK_TYPE_ACTION) @@ -40,11 +40,11 @@ G_DEFINE_TYPE (EvZoomAction, ev_zoom_action, GTK_TYPE_ACTION) static guint signals[LAST_SIGNAL] = { 0 }; static void -popup_shown_cb (GObject *combo, +popup_shown_cb (GObject *zoom_widget, GParamSpec *pspec, EvZoomAction *zoom_action) { - g_object_get (combo, "popup-shown", &zoom_action->priv->popup_shown, NULL); + g_object_get (zoom_widget, "popup-shown", &zoom_action->priv->popup_shown, NULL); } static void @@ -61,16 +61,13 @@ connect_proxy (GtkAction *action, if (EV_IS_ZOOM_ACTION_WIDGET (proxy)) { EvZoomAction *zoom_action = EV_ZOOM_ACTION (action); EvZoomActionWidget* zoom_widget = EV_ZOOM_ACTION_WIDGET (proxy); - GtkWidget *combo; ev_zoom_action_widget_set_model (zoom_widget, zoom_action->priv->model); - ev_zoom_action_widget_set_max_zoom_level (zoom_widget, zoom_action->priv->max_zoom); - - combo = ev_zoom_action_widget_get_combo_box (zoom_widget); - g_signal_connect (combo, "notify::popup-shown", + ev_zoom_action_widget_set_window (zoom_widget, zoom_action->priv->window); + g_signal_connect (zoom_widget, "notify::popup-shown", G_CALLBACK (popup_shown_cb), action); - g_signal_connect (gtk_bin_get_child (GTK_BIN (combo)), "activate", + g_signal_connect (ev_zoom_action_widget_get_entry (zoom_widget), "activate", G_CALLBACK (zoom_widget_activated_cb), action); } @@ -124,29 +121,31 @@ ev_zoom_action_set_model (EvZoomAction *action, } } -gboolean -ev_zoom_action_get_popup_shown (EvZoomAction *action) -{ - g_return_val_if_fail (EV_IS_ZOOM_ACTION (action), FALSE); - - return action->priv->popup_shown; -} - void -ev_zoom_action_set_max_zoom_level (EvZoomAction *action, - float max_zoom) +ev_zoom_action_set_window (EvZoomAction *action, + EvWindow *window) { + GSList *proxies, *l; g_return_if_fail (EV_IS_ZOOM_ACTION (action)); + g_return_if_fail (EV_IS_WINDOW (window)); - if (action->priv->max_zoom == max_zoom) + if (action->priv->window == window) return; - action->priv->max_zoom = max_zoom; + action->priv->window = window; proxies = gtk_action_get_proxies (GTK_ACTION (action)); for (l = proxies; l && l->data; l = g_slist_next (l)) { if (EV_IS_ZOOM_ACTION_WIDGET (l->data)) - ev_zoom_action_widget_set_max_zoom_level (EV_ZOOM_ACTION_WIDGET (l->data), max_zoom); + ev_zoom_action_widget_set_window (EV_ZOOM_ACTION_WIDGET (l->data), window); } } + +gboolean +ev_zoom_action_get_popup_shown (EvZoomAction *action) +{ + g_return_val_if_fail (EV_IS_ZOOM_ACTION (action), FALSE); + + return action->priv->popup_shown; +} diff --git a/shell/ev-zoom-action.h b/shell/ev-zoom-action.h index 4ef66fe1..6cb92c55 100644 --- a/shell/ev-zoom-action.h +++ b/shell/ev-zoom-action.h @@ -25,6 +25,8 @@ #include #include +#include "ev-window.h" + G_BEGIN_DECLS #define EV_TYPE_ZOOM_ACTION (ev_zoom_action_get_type ()) @@ -48,13 +50,33 @@ struct _EvZoomActionClass { GtkActionClass parent_class; }; -GType ev_zoom_action_get_type (void); +static const struct { + const gchar *name; + float level; +} zoom_levels[] = { + { "50%", 0.5 }, + { "70%", 0.7071067811 }, + { "85%", 0.8408964152 }, + { "100%", 1.0 }, + { "125%", 1.1892071149 }, + { "150%", 1.4142135623 }, + { "175%", 1.6817928304 }, + { "200%", 2.0 }, + { "300%", 2.8284271247 }, + { "400%", 4.0 }, + { "800%", 8.0 }, + { "1600%", 16.0 }, + { "3200%", 32.0 }, + { "6400%", 64.0 } +}; + +GType ev_zoom_action_get_type (void); -void ev_zoom_action_set_model (EvZoomAction *action, - EvDocumentModel *model); -gboolean ev_zoom_action_get_popup_shown (EvZoomAction *action); -void ev_zoom_action_set_max_zoom_level (EvZoomAction *action, - float max_zoom); +void ev_zoom_action_set_model (EvZoomAction *action, + EvDocumentModel *model); +gboolean ev_zoom_action_get_popup_shown (EvZoomAction *action); +void ev_zoom_action_set_window (EvZoomAction *action, + EvWindow *window); G_END_DECLS diff --git a/shell/evince-ui.xml b/shell/evince-ui.xml index 39e61dbd..db23f9c0 100644 --- a/shell/evince-ui.xml +++ b/shell/evince-ui.xml @@ -81,6 +81,13 @@ + + + + + + +