From 584f014b63c56fe3770cba9682fc21c31e09a2e9 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Tue, 20 Jul 2010 15:01:56 +0000 Subject: Preliminary support for adding new annotations At the moment only Text annotations can be added. See bug #168304. --- (limited to 'shell') diff --git a/shell/Makefile.am b/shell/Makefile.am index 523d299..8336230 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -32,6 +32,8 @@ endif evince_SOURCES= \ eggfindbar.c \ eggfindbar.h \ + ev-annotation-properties-dialog.h \ + ev-annotation-properties-dialog.c \ ev-application.c \ ev-application.h \ ev-file-monitor.h \ diff --git a/shell/ev-annotation-properties-dialog.c b/shell/ev-annotation-properties-dialog.c new file mode 100644 index 0000000..0f5c6e1 --- /dev/null +++ b/shell/ev-annotation-properties-dialog.c @@ -0,0 +1,327 @@ +/* ev-annotation-properties-dialog.c + * this file is part of evince, a gnome document viewer + * + * Copyright (C) 2010 Carlos Garcia Campos + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include + +#include "ev-annotation-properties-dialog.h" + +enum { + PROP_0, + PROP_ANNOT_TYPE +}; + +struct _EvAnnotationPropertiesDialog { + GtkDialog base_instance; + + EvAnnotationType annot_type; + EvAnnotation *annot; + + GtkWidget *table; + + GtkWidget *author; + GtkWidget *color; + GtkWidget *opacity; + GtkWidget *popup_state; + + /* Text Annotations */ + GtkWidget *icon; +}; + +struct _EvAnnotationPropertiesDialogClass { + GtkDialogClass base_class; +}; + +G_DEFINE_TYPE (EvAnnotationPropertiesDialog, ev_annotation_properties_dialog, GTK_TYPE_DIALOG) + +static void +ev_annotation_properties_dialog_dispose (GObject *object) +{ + EvAnnotationPropertiesDialog *dialog = EV_ANNOTATION_PROPERTIES_DIALOG (object); + + if (dialog->annot) { + g_object_unref (dialog->annot); + dialog->annot = NULL; + } + + G_OBJECT_CLASS (ev_annotation_properties_dialog_parent_class)->dispose (object); +} + +static void +ev_annotation_properties_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EvAnnotationPropertiesDialog *dialog = EV_ANNOTATION_PROPERTIES_DIALOG (object); + + switch (prop_id) { + case PROP_ANNOT_TYPE: + dialog->annot_type = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +ev_annotation_properties_dialog_constructed (GObject *object) +{ + EvAnnotationPropertiesDialog *dialog = EV_ANNOTATION_PROPERTIES_DIALOG (object); + GtkWidget *contant_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + GtkWidget *table = dialog->table; + GtkWidget *label; + + contant_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + + switch (dialog->annot_type) { + case EV_ANNOTATION_TYPE_TEXT: + label = gtk_label_new (_("Icon:")); + gtk_misc_set_alignment (GTK_MISC (label), 0., 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 5, 6, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); + + dialog->icon = gtk_combo_box_new_text (); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Note")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Comment")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Key")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Help")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("New Paragraph")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Paragraph")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Insert")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Cross")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Circle")); + gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->icon), _("Unknown")); + gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->icon), 0); + gtk_table_attach (GTK_TABLE (table), dialog->icon, + 1, 2, 5, 6, + GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_widget_show (dialog->icon); + + break; + case EV_ANNOTATION_TYPE_ATTACHMENT: + /* TODO */ + default: + break; + } +} + +static void +ev_annotation_properties_dialog_init (EvAnnotationPropertiesDialog *annot_dialog) +{ + GtkDialog *dialog = GTK_DIALOG (annot_dialog); + GtkWidget *content_area; + GtkWidget *label; + GtkWidget *table; + GtkWidget *hbox; + gchar *markup; + GdkColor color = { 0, 65535, 65535, 0 }; + + gtk_window_set_title (GTK_WINDOW (annot_dialog), _("Annotation Properties")); + gtk_window_set_destroy_with_parent (GTK_WINDOW (annot_dialog), TRUE); + gtk_container_set_border_width (GTK_CONTAINER (annot_dialog), 5); + gtk_dialog_set_has_separator (dialog, FALSE); + gtk_dialog_add_buttons (dialog, + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, + GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, + NULL); + gtk_dialog_set_default_response (dialog, GTK_RESPONSE_APPLY); + + content_area = gtk_dialog_get_content_area (dialog); + gtk_box_set_spacing (GTK_BOX (content_area), 2); + + table = gtk_table_new (5, 2, FALSE); + annot_dialog->table = table; + gtk_table_set_col_spacings (GTK_TABLE (table), 12); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_set_border_width (GTK_CONTAINER (table), 12); + gtk_box_pack_start (GTK_BOX (content_area), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + label = gtk_label_new (_("Author:")); + gtk_misc_set_alignment (GTK_MISC (label), 0., 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); + + annot_dialog->author = gtk_entry_new (); + gtk_entry_set_text (GTK_ENTRY (annot_dialog->author), g_get_real_name ()); + gtk_table_attach (GTK_TABLE (table), annot_dialog->author, + 1, 2, 0, 1, + GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_widget_show (annot_dialog->author); + + label = gtk_label_new (_("Color:")); + gtk_misc_set_alignment (GTK_MISC (label), 0., 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); + + annot_dialog->color = gtk_color_button_new_with_color (&color); + gtk_table_attach (GTK_TABLE (table), annot_dialog->color, + 1, 2, 1, 2, + GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_widget_show (annot_dialog->color); + + label = gtk_label_new (_("Style:")); + gtk_misc_set_alignment (GTK_MISC (label), 0., 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); + + annot_dialog->opacity = gtk_hscale_new_with_range (0, 100, 5); + gtk_range_set_value (GTK_RANGE (annot_dialog->opacity), 100); + gtk_table_attach (GTK_TABLE (table), annot_dialog->opacity, + 1, 2, 2, 3, + GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_widget_show (annot_dialog->opacity); + + hbox = gtk_hbox_new (FALSE, 6); + + label = gtk_label_new (NULL); + markup = g_strdup_printf ("%s", _("Transparent")); + gtk_label_set_markup (GTK_LABEL (label), markup); + g_free (markup); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + label = gtk_label_new (NULL); + markup = g_strdup_printf ("%s", _("Opaque")); + gtk_label_set_markup (GTK_LABEL (label), markup); + g_free (markup); + gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + gtk_table_attach (GTK_TABLE (table), hbox, + 1, 2, 3, 4, + GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_widget_show (hbox); + + label = gtk_label_new (_("Initial window state:")); + gtk_misc_set_alignment (GTK_MISC (label), 0., 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 4, 5, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); + + annot_dialog->popup_state = gtk_combo_box_new_text (); + gtk_combo_box_append_text (GTK_COMBO_BOX (annot_dialog->popup_state), _("Open")); + gtk_combo_box_append_text (GTK_COMBO_BOX (annot_dialog->popup_state), _("Close")); + gtk_combo_box_set_active (GTK_COMBO_BOX (annot_dialog->popup_state), 1); + gtk_table_attach (GTK_TABLE (table), annot_dialog->popup_state, + 1, 2, 4, 5, + GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_widget_show (annot_dialog->popup_state); +} + +static void +ev_annotation_properties_dialog_class_init (EvAnnotationPropertiesDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = ev_annotation_properties_dialog_dispose; + object_class->constructed = ev_annotation_properties_dialog_constructed; + object_class->set_property = ev_annotation_properties_dialog_set_property; + + g_object_class_install_property (object_class, + PROP_ANNOT_TYPE, + g_param_spec_enum ("annot-type", + "AnnotType", + "The type of annotation", + EV_TYPE_ANNOTATION_TYPE, + EV_ANNOTATION_TYPE_TEXT, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); +} + +GtkWidget * +ev_annotation_properties_dialog_new (EvAnnotationType annot_type) +{ + return GTK_WIDGET (g_object_new (EV_TYPE_ANNOTATION_PROPERTIES_DIALOG, + "annot-type", annot_type, + NULL)); +} + +GtkWidget * +ev_annotation_properties_dialog_new_with_annotation (EvAnnotation *annot) +{ + EvAnnotationPropertiesDialog *dialog; + const gchar *label; + gdouble opacity; + gboolean is_open; + GdkColor color; + + dialog = (EvAnnotationPropertiesDialog *)ev_annotation_properties_dialog_new (ev_annotation_get_annotation_type (annot)); + dialog->annot = g_object_ref (annot); + + label = ev_annotation_markup_get_label (EV_ANNOTATION_MARKUP (annot)); + if (label) + gtk_entry_set_text (GTK_ENTRY (dialog->author), label); + + ev_annotation_get_color (annot, &color); + gtk_color_button_set_color (GTK_COLOR_BUTTON (dialog->color), &color); + + opacity = ev_annotation_markup_get_opacity (EV_ANNOTATION_MARKUP (annot)); + gtk_range_set_value (GTK_RANGE (dialog->opacity), opacity * 100); + + is_open = ev_annotation_markup_get_popup_is_open (EV_ANNOTATION_MARKUP (annot)); + gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->popup_state), + is_open ? 0 : 1); + + if (EV_IS_ANNOTATION_TEXT (annot)) { + EvAnnotationText *annot_text = EV_ANNOTATION_TEXT (annot); + + gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->icon), + ev_annotation_text_get_icon (annot_text)); + } + + return GTK_WIDGET (dialog); +} + +const gchar * +ev_annotation_properties_dialog_get_author (EvAnnotationPropertiesDialog *dialog) +{ + return gtk_entry_get_text (GTK_ENTRY (dialog->author)); +} + +void +ev_annotation_properties_dialog_get_color (EvAnnotationPropertiesDialog *dialog, + GdkColor *color) +{ + gtk_color_button_get_color (GTK_COLOR_BUTTON (dialog->color), color); +} + +gdouble +ev_annotation_properties_dialog_get_opacity (EvAnnotationPropertiesDialog *dialog) +{ + return gtk_range_get_value (GTK_RANGE (dialog->opacity)) / 100; +} + +gboolean +ev_annotation_properties_dialog_get_popup_is_open (EvAnnotationPropertiesDialog *dialog) +{ + return gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->popup_state)) == 0; +} + +EvAnnotationTextIcon +ev_annotation_properties_dialog_get_text_icon (EvAnnotationPropertiesDialog *dialog) +{ + return gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->icon)); +} diff --git a/shell/ev-annotation-properties-dialog.h b/shell/ev-annotation-properties-dialog.h new file mode 100644 index 0000000..e21a883 --- /dev/null +++ b/shell/ev-annotation-properties-dialog.h @@ -0,0 +1,54 @@ +/* ev-annotation-properties-dialog.h + * this file is part of evince, a gnome document viewer + * + * Copyright (C) 2010 Carlos Garcia Campos + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __EV_ANNOTATION_PROPERTIES_DIALOG_H__ +#define __EV_ANNOTATION_PROPERTIES_DIALOG_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define EV_TYPE_ANNOTATION_PROPERTIES_DIALOG (ev_annotation_properties_dialog_get_type()) +#define EV_ANNOTATION_PROPERTIES_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST((o), EV_TYPE_ANNOTATION_PROPERTIES_DIALOG, EvAnnotationPropertiesDialog)) +#define EV_ANNOTATION_PROPERTIES_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_ANNOTATION_PROPERTIES_DIALOG, EvAnnotationPropertiesDialogClass)) +#define EV_IS_ANNOTATION_PROPERTIES_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), EV_TYPE_ANNOTATION_PROPERTIES_DIALOG)) +#define EV_IS_ANNOTATION_PROPERTIES_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), EV_TYPE_ANNOTATION_PROPERTIES_DIALOG)) +#define EV_ANNOTATION_PROPERTIES_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), EV_TYPE_ANNOTATION_PROPERTIES_DIALOG, EvAnnotationPropertiesDialogClass)) + +typedef struct _EvAnnotationPropertiesDialog EvAnnotationPropertiesDialog; +typedef struct _EvAnnotationPropertiesDialogClass EvAnnotationPropertiesDialogClass; + +GType ev_annotation_properties_dialog_get_type (void) G_GNUC_CONST; +GtkWidget *ev_annotation_properties_dialog_new (EvAnnotationType annot_type); +GtkWidget *ev_annotation_properties_dialog_new_with_annotation (EvAnnotation *annot); + +const gchar *ev_annotation_properties_dialog_get_author (EvAnnotationPropertiesDialog *dialog); +void ev_annotation_properties_dialog_get_color (EvAnnotationPropertiesDialog *dialog, + GdkColor *color); +gdouble ev_annotation_properties_dialog_get_opacity (EvAnnotationPropertiesDialog *dialog); +gboolean ev_annotation_properties_dialog_get_popup_is_open (EvAnnotationPropertiesDialog *dialog); +EvAnnotationTextIcon ev_annotation_properties_dialog_get_text_icon (EvAnnotationPropertiesDialog *dialog); + +G_END_DECLS + +#endif /* __EV_ANNOTATION_PROPERTIES_DIALOG_H__ */ diff --git a/shell/ev-sidebar-annotations.c b/shell/ev-sidebar-annotations.c index b1f0848..ec544fa 100644 --- a/shell/ev-sidebar-annotations.c +++ b/shell/ev-sidebar-annotations.c @@ -43,18 +43,25 @@ enum { enum { ANNOT_ACTIVATED, + BEGIN_ANNOT_ADD, + ANNOT_ADD_CANCELLED, N_SIGNALS }; struct _EvSidebarAnnotationsPrivate { - GtkWidget *notebook; - GtkWidget *tree_view; + EvDocument *document; - EvJob *job; - guint selection_changed_id; + GtkWidget *notebook; + GtkWidget *tree_view; + GtkWidget *palette; + GtkToolItem *annot_text_item; + + EvJob *job; + guint selection_changed_id; }; static void ev_sidebar_annotations_page_iface_init (EvSidebarPageInterface *iface); +static void ev_sidebar_annotations_load (EvSidebarAnnotations *sidebar_annots); static guint signals[N_SIGNALS]; @@ -68,6 +75,20 @@ G_DEFINE_TYPE_EXTENDED (EvSidebarAnnotations, #define EV_SIDEBAR_ANNOTATIONS_GET_PRIVATE(object) \ (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_ANNOTATIONS, EvSidebarAnnotationsPrivate)) +static void +ev_sidebar_annotations_dispose (GObject *object) +{ + EvSidebarAnnotations *sidebar_annots = EV_SIDEBAR_ANNOTATIONS (object); + EvSidebarAnnotationsPrivate *priv = sidebar_annots->priv; + + if (priv->document) { + g_object_unref (priv->document); + priv->document = NULL; + } + + G_OBJECT_CLASS (ev_sidebar_annotations_parent_class)->dispose (object); +} + static GtkTreeModel * ev_sidebar_annotations_create_simple_model (const gchar *message) { @@ -100,6 +121,7 @@ ev_sidebar_annotations_add_annots_list (EvSidebarAnnotations *ev_annots) GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; + GtkWidget *label; swindow = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), @@ -136,8 +158,71 @@ ev_sidebar_annotations_add_annots_list (EvSidebarAnnotations *ev_annots) gtk_container_add (GTK_CONTAINER (swindow), ev_annots->priv->tree_view); gtk_widget_show (ev_annots->priv->tree_view); + label = gtk_label_new (_("List")); + gtk_notebook_append_page (GTK_NOTEBOOK (ev_annots->priv->notebook), + swindow, label); + gtk_widget_show (label); + + gtk_widget_show (swindow); +} + +static void +ev_sidebar_annotations_text_annot_button_toggled (GtkToggleToolButton *toolbutton, + EvSidebarAnnotations *sidebar_annots) +{ + EvAnnotationType annot_type; + + if (!gtk_toggle_tool_button_get_active (toolbutton)) { + g_signal_emit (sidebar_annots, signals[ANNOT_ADD_CANCELLED], 0, NULL); + return; + } + + if (GTK_TOOL_ITEM (toolbutton) == sidebar_annots->priv->annot_text_item) + annot_type = EV_ANNOTATION_TYPE_TEXT; + else + annot_type = EV_ANNOTATION_TYPE_UNKNOWN; + + g_signal_emit (sidebar_annots, signals[BEGIN_ANNOT_ADD], 0, annot_type); +} + +static void +ev_sidebar_annotations_add_annots_palette (EvSidebarAnnotations *ev_annots) +{ + GtkWidget *swindow; + GtkWidget *group; + GtkToolItem *item; + GtkWidget *label; + + swindow = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow), + GTK_SHADOW_IN); + + ev_annots->priv->palette = gtk_tool_palette_new (); + group = gtk_tool_item_group_new (_("Annotations")); + gtk_container_add (GTK_CONTAINER (ev_annots->priv->palette), group); + + /* FIXME: use a better icon than EDIT */ + item = gtk_toggle_tool_button_new (); + gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), GTK_STOCK_EDIT); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), _("Text")); + gtk_widget_set_tooltip_text (GTK_WIDGET (item), _("Add text annotation")); + ev_annots->priv->annot_text_item = item; + g_signal_connect (item, "toggled", + G_CALLBACK (ev_sidebar_annotations_text_annot_button_toggled), + ev_annots); + gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1); + gtk_widget_show (GTK_WIDGET (item)); + + gtk_container_add (GTK_CONTAINER (swindow), ev_annots->priv->palette); + gtk_widget_show (ev_annots->priv->palette); + + label = gtk_label_new (_("Add")); gtk_notebook_append_page (GTK_NOTEBOOK (ev_annots->priv->notebook), - swindow, NULL); + swindow, label); + gtk_widget_show (label); + gtk_widget_show (swindow); } @@ -150,6 +235,7 @@ ev_sidebar_annotations_init (EvSidebarAnnotations *ev_annots) gtk_notebook_set_show_tabs (GTK_NOTEBOOK (ev_annots->priv->notebook), FALSE); gtk_notebook_set_show_border (GTK_NOTEBOOK (ev_annots->priv->notebook), FALSE); ev_sidebar_annotations_add_annots_list (ev_annots); + ev_sidebar_annotations_add_annots_palette (ev_annots); gtk_container_add (GTK_CONTAINER (ev_annots), ev_annots->priv->notebook); gtk_widget_show (ev_annots->priv->notebook); } @@ -180,6 +266,7 @@ ev_sidebar_annotations_class_init (EvSidebarAnnotationsClass *klass) GObjectClass *g_object_class = G_OBJECT_CLASS (klass); g_object_class->get_property = ev_sidebar_annotations_get_property; + g_object_class->dispose = ev_sidebar_annotations_dispose; g_type_class_add_private (g_object_class, sizeof (EvSidebarAnnotationsPrivate)); @@ -194,6 +281,24 @@ ev_sidebar_annotations_class_init (EvSidebarAnnotationsClass *klass) g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[BEGIN_ANNOT_ADD] = + g_signal_new ("begin-annot-add", + G_TYPE_FROM_CLASS (g_object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EvSidebarAnnotationsClass, begin_annot_add), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + EV_TYPE_ANNOTATION_TYPE); + signals[ANNOT_ADD_CANCELLED] = + g_signal_new ("annot-add-cancelled", + G_TYPE_FROM_CLASS (g_object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EvSidebarAnnotationsClass, annot_add_cancelled), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, + G_TYPE_NONE); } GtkWidget * @@ -202,6 +307,26 @@ ev_sidebar_annotations_new (void) return GTK_WIDGET (g_object_new (EV_TYPE_SIDEBAR_ANNOTATIONS, NULL)); } +void +ev_sidebar_annotations_annot_added (EvSidebarAnnotations *sidebar_annots, + EvAnnotation *annot) +{ + GtkToggleToolButton *toolbutton; + + if (EV_IS_ANNOTATION_TEXT (annot)) { + toolbutton = GTK_TOGGLE_TOOL_BUTTON (sidebar_annots->priv->annot_text_item); + g_signal_handlers_block_by_func (toolbutton, + ev_sidebar_annotations_text_annot_button_toggled, + sidebar_annots); + gtk_toggle_tool_button_set_active (toolbutton, FALSE); + g_signal_handlers_unblock_by_func (toolbutton, + ev_sidebar_annotations_text_annot_button_toggled, + sidebar_annots); + } + + ev_sidebar_annotations_load (sidebar_annots); +} + static void selection_changed_cb (GtkTreeSelection *selection, EvSidebarAnnotations *sidebar_annots) @@ -278,7 +403,8 @@ job_finished_callback (EvJobAnnots *job, for (ll = ev_mapping_list_get_list (mapping_list); ll; ll = g_list_next (ll)) { EvAnnotation *annot; - gchar *label; + const gchar *label; + const gchar *modified; gchar *markup; GtkTreeIter child_iter; GdkPixbuf *pixbuf = NULL; @@ -288,13 +414,13 @@ job_finished_callback (EvJobAnnots *job, continue; label = ev_annotation_markup_get_label (EV_ANNOTATION_MARKUP (annot)); - if (annot->modified) { + modified = ev_annotation_get_modified (annot); + if (modified) { markup = g_strdup_printf ("%s\n%s", - label, annot->modified); + label, modified); } else { markup = g_strdup_printf ("%s", label); } - g_free (label); if (EV_IS_ANNOTATION_TEXT (annot)) { if (!text_icon) { @@ -342,18 +468,11 @@ job_finished_callback (EvJobAnnots *job, priv->job = NULL; } - static void -ev_sidebar_annotations_document_changed_cb (EvDocumentModel *model, - GParamSpec *pspec, - EvSidebarAnnotations *sidebar_annots) +ev_sidebar_annotations_load (EvSidebarAnnotations *sidebar_annots) { - EvDocument *document = ev_document_model_get_document (model); EvSidebarAnnotationsPrivate *priv = sidebar_annots->priv; - if (!EV_IS_DOCUMENT_ANNOTATIONS (document)) - return; - if (priv->job) { g_signal_handlers_disconnect_by_func (priv->job, job_finished_callback, @@ -361,7 +480,7 @@ ev_sidebar_annotations_document_changed_cb (EvDocumentModel *model, g_object_unref (priv->job); } - priv->job = ev_job_annots_new (document); + priv->job = ev_job_annots_new (priv->document); g_signal_connect (priv->job, "finished", G_CALLBACK (job_finished_callback), sidebar_annots); @@ -369,6 +488,28 @@ ev_sidebar_annotations_document_changed_cb (EvDocumentModel *model, ev_job_scheduler_push_job (priv->job, EV_JOB_PRIORITY_NONE); } +static void +ev_sidebar_annotations_document_changed_cb (EvDocumentModel *model, + GParamSpec *pspec, + EvSidebarAnnotations *sidebar_annots) +{ + EvDocument *document = ev_document_model_get_document (model); + EvSidebarAnnotationsPrivate *priv = sidebar_annots->priv; + gboolean show_tabs; + + if (!EV_IS_DOCUMENT_ANNOTATIONS (document)) + return; + + if (priv->document) + g_object_unref (priv->document); + priv->document = g_object_ref (document); + + show_tabs = ev_document_annotations_can_add_annotation (EV_DOCUMENT_ANNOTATIONS (document)); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), show_tabs); + + ev_sidebar_annotations_load (sidebar_annots); +} + /* EvSidebarPageIface */ static void ev_sidebar_annotations_set_model (EvSidebarPage *sidebar_page, diff --git a/shell/ev-sidebar-annotations.h b/shell/ev-sidebar-annotations.h index 8762d78..544fc24 100644 --- a/shell/ev-sidebar-annotations.h +++ b/shell/ev-sidebar-annotations.h @@ -46,13 +46,17 @@ struct _EvSidebarAnnotations { struct _EvSidebarAnnotationsClass { GtkVBoxClass base_class; - void (* annot_activated) (EvSidebarAnnotations *sidebar_annots, - EvMapping *mapping); + void (* annot_activated) (EvSidebarAnnotations *sidebar_annots, + EvMapping *mapping); + void (* begin_annot_add) (EvSidebarAnnotations *sidebar_annots, + EvAnnotationType annot_type); + void (* annot_add_cancelled) (EvSidebarAnnotations *sidebar_annots); }; -GType ev_sidebar_annotations_get_type (void) G_GNUC_CONST; -GtkWidget *ev_sidebar_annotations_new (void); - +GType ev_sidebar_annotations_get_type (void) G_GNUC_CONST; +GtkWidget *ev_sidebar_annotations_new (void); +void ev_sidebar_annotations_annot_added (EvSidebarAnnotations *sidebar_annots, + EvAnnotation *annot); G_END_DECLS #endif /* __EV_SIDEBAR_ANNOTATIONS_H__ */ diff --git a/shell/ev-window.c b/shell/ev-window.c index c7e9c6d..ece97c7 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -95,6 +95,7 @@ #include "ev-window-title.h" #include "ev-print-operation.h" #include "ev-progress-message-area.h" +#include "ev-annotation-properties-dialog.h" #ifdef ENABLE_DBUS #include "ev-media-player-keys.h" @@ -172,9 +173,10 @@ struct _EvWindowPrivate { GtkWidget *fullscreen_toolbar; /* Popup view */ - GtkWidget *view_popup; - EvLink *link; - EvImage *image; + GtkWidget *view_popup; + EvLink *link; + EvImage *image; + EvAnnotation *annot; /* Popup attachment */ GtkWidget *attachment_popup; @@ -317,6 +319,8 @@ static void ev_view_popup_cmd_save_image_as (GtkAction *actio EvWindow *window); static void ev_view_popup_cmd_copy_image (GtkAction *action, EvWindow *window); +static void ev_view_popup_cmd_annot_properties (GtkAction *action, + EvWindow *window); static void ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window); static void ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, @@ -3307,6 +3311,8 @@ ev_window_cmd_file_close_window (GtkAction *action, EvWindow *ev_window) ev_document_model_set_page (ev_window->priv->model, current_page); } + /* TODO: warn about form fields, and annots not saved */ + n_print_jobs = ev_window->priv->print_queue ? g_queue_get_length (ev_window->priv->print_queue) : 0; @@ -4536,9 +4542,18 @@ view_menu_annot_popup (EvWindow *ev_window, GtkAction *action; gboolean show_annot = FALSE; + if (ev_window->priv->annot) + g_object_unref (ev_window->priv->annot); + ev_window->priv->annot = (annot) ? g_object_ref (annot) : NULL; + + action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group, + "AnnotProperties"); + gtk_action_set_visible (action, (annot != NULL && EV_IS_ANNOTATION_MARKUP (annot))); + if (annot && EV_IS_ANNOTATION_ATTACHMENT (annot)) { - EvAttachment *attachment = EV_ANNOTATION_ATTACHMENT (annot)->attachment; + EvAttachment *attachment; + attachment = ev_annotation_attachment_get_attachment (EV_ANNOTATION_ATTACHMENT (annot)); if (attachment) { show_annot = TRUE; if (ev_window->priv->attach_list) { @@ -5029,6 +5044,11 @@ ev_window_dispose (GObject *object) priv->image = NULL; } + if (priv->annot) { + g_object_unref (priv->annot); + priv->annot = NULL; + } + if (priv->attach_list) { g_list_foreach (priv->attach_list, (GFunc) g_object_unref, @@ -5338,6 +5358,8 @@ static const GtkActionEntry view_popup_entries [] = { NULL, G_CALLBACK (ev_view_popup_cmd_save_image_as) }, { "CopyImage", NULL, N_("Copy _Image"), NULL, NULL, G_CALLBACK (ev_view_popup_cmd_copy_image) }, + { "AnnotProperties", NULL, N_("Annotation Properties…"), NULL, + NULL, G_CALLBACK (ev_view_popup_cmd_annot_properties) } }; static const GtkActionEntry attachment_popup_entries [] = { @@ -5384,6 +5406,30 @@ sidebar_annots_annot_activated_cb (EvSidebarAnnotations *sidebar_annots, } static void +sidebar_annots_begin_annot_add (EvSidebarAnnotations *sidebar_annots, + EvAnnotationType annot_type, + EvWindow *window) +{ + ev_view_begin_add_annotation (EV_VIEW (window->priv->view), annot_type); +} + +static void +view_annot_added (EvView *view, + EvAnnotation *annot, + EvWindow *window) +{ + ev_sidebar_annotations_annot_added (EV_SIDEBAR_ANNOTATIONS (window->priv->sidebar_annots), + annot); +} + +static void +sidebar_annots_annot_add_cancelled (EvSidebarAnnotations *sidebar_annots, + EvWindow *window) +{ + ev_view_cancel_add_annotation (EV_VIEW (window->priv->view)); +} + +static void register_custom_actions (EvWindow *window, GtkActionGroup *group) { GtkAction *action; @@ -5995,6 +6041,67 @@ ev_view_popup_cmd_copy_image (GtkAction *action, EvWindow *window) } static void +ev_view_popup_cmd_annot_properties (GtkAction *action, + EvWindow *window) +{ + const gchar *author; + GdkColor color; + gdouble opacity; + gboolean popup_is_open; + EvAnnotationPropertiesDialog *dialog; + EvAnnotation *annot = window->priv->annot; + EvAnnotationsSaveMask mask = EV_ANNOTATIONS_SAVE_NONE; + + if (!annot) + return; + + dialog = EV_ANNOTATION_PROPERTIES_DIALOG (ev_annotation_properties_dialog_new_with_annotation (window->priv->annot)); + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_APPLY) { + gtk_widget_destroy (GTK_WIDGET (dialog)); + + return; + } + + /* Set annotations changes */ + author = ev_annotation_properties_dialog_get_author (dialog); + if (ev_annotation_markup_set_label (EV_ANNOTATION_MARKUP (annot), author)) + mask |= EV_ANNOTATIONS_SAVE_LABEL; + + ev_annotation_properties_dialog_get_color (dialog, &color); + if (ev_annotation_set_color (annot, &color)) + mask |= EV_ANNOTATIONS_SAVE_COLOR; + + opacity = ev_annotation_properties_dialog_get_opacity (dialog); + if (ev_annotation_markup_set_opacity (EV_ANNOTATION_MARKUP (annot), opacity)) + mask |= EV_ANNOTATIONS_SAVE_OPACITY; + + popup_is_open = ev_annotation_properties_dialog_get_popup_is_open (dialog); + if (ev_annotation_markup_set_popup_is_open (EV_ANNOTATION_MARKUP (annot), popup_is_open)) + mask |= EV_ANNOTATIONS_SAVE_POPUP_IS_OPEN; + + if (EV_IS_ANNOTATION_TEXT (annot)) { + EvAnnotationTextIcon icon; + + icon = ev_annotation_properties_dialog_get_text_icon (dialog); + if (ev_annotation_text_set_icon (EV_ANNOTATION_TEXT (annot), icon)) + mask |= EV_ANNOTATIONS_SAVE_TEXT_ICON; + } + + if (mask != EV_ANNOTATIONS_SAVE_NONE) { + ev_document_doc_mutex_lock (); + ev_document_annotations_save_annotation (EV_DOCUMENT_ANNOTATIONS (window->priv->document), + window->priv->annot, + mask); + ev_document_doc_mutex_unlock (); + + /* FIXME: update annot region only */ + ev_view_reload (EV_VIEW (window->priv->view)); + } + + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static void ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window) { GList *l; @@ -6553,6 +6660,14 @@ ev_window_init (EvWindow *ev_window) "annot_activated", G_CALLBACK (sidebar_annots_annot_activated_cb), ev_window); + g_signal_connect (sidebar_widget, + "begin_annot_add", + G_CALLBACK (sidebar_annots_begin_annot_add), + ev_window); + g_signal_connect (sidebar_widget, + "annot_add_cancelled", + G_CALLBACK (sidebar_annots_annot_add_cancelled), + ev_window); gtk_widget_show (sidebar_widget); ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar), sidebar_widget); @@ -6598,6 +6713,9 @@ ev_window_init (EvWindow *ev_window) g_signal_connect_object (ev_window->priv->view, "selection-changed", G_CALLBACK (view_selection_changed_cb), ev_window, 0); + g_signal_connect_object (ev_window->priv->view, "annot-added", + G_CALLBACK (view_annot_added), + ev_window, 0); #ifdef ENABLE_DBUS g_signal_connect_swapped (ev_window->priv->view, "sync-source", G_CALLBACK (ev_window_sync_source), -- cgit v0.9.1