3 * sheet-object-cell-comment.c: A SheetObject to support cell comments.
5 * Copyright (C) 2000-2004 Jody Goldberg (jody@gnome.org)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
22 #include <gnumeric-config.h>
24 #include <sheet-object-cell-comment.h>
26 #include <gnm-pane-impl.h>
27 #include <sheet-object-impl.h>
29 #include <sheet-view.h>
30 #include <sheet-merge.h>
31 #include <sheet-control-gui-priv.h>
32 #include <dialogs/dialogs.h>
34 #include <goffice/goffice.h>
37 #include <libxml/globals.h>
38 #include <gsf/gsf-impl-utils.h>
44 PangoAttrList
*markup
;
46 typedef SheetObjectClass GnmCommentClass
;
47 static GObjectClass
*cell_comment_parent_class
;
58 GdkRGBA comment_indicator_color
;
59 int comment_indicator_size
;
61 typedef SheetObjectViewClass CommentViewClass
;
62 static GocItemClass
*comment_view_parent_class
;
65 comment_view_reload_style (CommentView
*cv
)
67 GocItem
*item
= GOC_ITEM (cv
);
68 GnmPane
*pane
= GNM_PANE (item
->canvas
);
69 GtkStyleContext
*context
;
71 context
= goc_item_get_style_context (item
);
72 gnm_style_context_get_color (context
, GTK_STATE_FLAG_NORMAL
,
73 &cv
->comment_indicator_color
);
75 context
= gtk_widget_get_style_context (GTK_WIDGET (pane
));
76 gtk_widget_style_get (GTK_WIDGET (pane
),
77 "comment-indicator-size",
78 &cv
->comment_indicator_size
,
83 comment_view_set_bounds (SheetObjectView
*sov
, double const *coords
, gboolean visible
)
85 CommentView
*cv
= (CommentView
*)sov
;
86 GocPoints
*points
= goc_points_new (3);
87 GocItem
*item
= GOC_ITEM (GOC_GROUP (sov
)->children
->data
);
89 SheetObject
*so
= sheet_object_view_get_so (sov
);
90 SheetControlGUI
const *scg
= GNM_SIMPLE_CANVAS (item
->canvas
)->scg
;
94 GnmRange
const *r
= gnm_sheet_merge_is_corner (so
->sheet
,
95 &so
->anchor
.cell_bound
.start
);
97 scale
= 1. / item
->canvas
->pixels_per_unit
;
100 far_col
= 1 + r
->end
.col
;
102 far_col
= 1 + so
->anchor
.cell_bound
.start
.col
;
104 /* TODO : This could be optimized using the offsets associated with the visible region */
105 /* Add 1 to y because we measure from start, x is measured from end, so
106 * it does not need it */
107 y
= scg_colrow_distance_get (scg
, FALSE
, 0, so
->anchor
.cell_bound
.start
.row
)+ 1;
108 points
->points
[0].y
= scale
* y
;
109 points
->points
[1].y
= scale
* y
;
110 points
->points
[2].y
= scale
* y
+ cv
->comment_indicator_size
;
112 dx
= cv
->comment_indicator_size
;
113 x
= scg_colrow_distance_get (scg
, TRUE
, 0, far_col
);
114 points
->points
[0].x
= scale
* x
- dx
;
115 points
->points
[1].x
= scale
* x
;
116 points
->points
[2].x
= scale
* x
;
118 goc_item_set (item
, "points", points
, NULL
);
119 goc_points_unref (points
);
120 goc_item_show (GOC_ITEM (sov
));
122 goc_item_hide (GOC_ITEM (sov
));
126 comment_view_button_released (GocItem
*item
, int button
, double x
, double y
)
134 gnm_canvas_get_screen_position (item
->canvas
, x
, y
, &ix
, &iy
);
135 so
= sheet_object_view_get_so (GNM_SO_VIEW (item
));
136 scg_comment_display (GNM_PANE (item
->canvas
)->simple
.scg
,
137 GNM_CELL_COMMENT (so
),
144 comment_view_button_pressed (GocItem
*item
, int button
, double x
, double y
)
150 comment_view_button2_pressed (GocItem
*item
, int button
, double x
, double y
)
154 SheetControlGUI
*scg
;
158 scg
= GNM_PANE (item
->canvas
)->simple
.scg
;
159 so
= sheet_object_view_get_so (GNM_SO_VIEW (item
));
160 r
= sheet_object_get_range (so
);
161 dialog_cell_comment (scg
->wbcg
, so
->sheet
, &r
->start
);
166 comment_view_enter_notify (GocItem
*item
, double x
, double y
)
171 gnm_widget_set_cursor_type (GTK_WIDGET (item
->canvas
), GDK_ARROW
);
173 gnm_canvas_get_screen_position (item
->canvas
, x
, y
, &ix
, &iy
);
174 so
= sheet_object_view_get_so (GNM_SO_VIEW (item
));
176 scg_comment_select (GNM_PANE (item
->canvas
)->simple
.scg
,
177 GNM_CELL_COMMENT (so
),
183 comment_view_leave_notify (GocItem
*item
, double x
, double y
)
185 scg_comment_unselect (GNM_PANE (item
->canvas
)->simple
.scg
,
186 GNM_CELL_COMMENT (sheet_object_view_get_so (GNM_SO_VIEW (item
))));
191 comment_view_class_init (SheetObjectViewClass
*sov_klass
)
193 GocItemClass
*item_klass
= (GocItemClass
*) sov_klass
;
195 comment_view_parent_class
= g_type_class_peek_parent (sov_klass
);
197 sov_klass
->set_bounds
= comment_view_set_bounds
;
199 item_klass
->button_pressed
= comment_view_button_pressed
;
200 item_klass
->button_released
= comment_view_button_released
;
201 item_klass
->button2_pressed
= comment_view_button2_pressed
;
202 item_klass
->enter_notify
= comment_view_enter_notify
;
203 item_klass
->leave_notify
= comment_view_leave_notify
;
206 static GSF_CLASS (CommentView
, comment_view
,
207 comment_view_class_init
, NULL
,
211 cell_comment_finalize (GObject
*object
)
213 GnmComment
*cc
= GNM_CELL_COMMENT (object
);
215 g_return_if_fail (cc
!= NULL
);
217 /* If this comment is being displayed we shut down nicely */
218 if (cc
->base
.sheet
!= NULL
) {
219 SHEET_FOREACH_CONTROL (cc
->base
.sheet
, view
, control
,
220 scg_comment_unselect ((SheetControlGUI
*) control
, cc
););
228 if (NULL
!= cc
->markup
) {
229 pango_attr_list_unref (cc
->markup
);
233 cell_comment_parent_class
->finalize (object
);
237 cell_comment_set_property (GObject
*obj
, guint param_id
,
238 GValue
const *value
, GParamSpec
*pspec
)
240 GnmComment
*cc
= GNM_CELL_COMMENT (obj
);
245 cc
->text
= g_value_dup_string (value
);
249 cc
->author
= g_value_dup_string (value
);
252 if (cc
->markup
!= NULL
)
253 pango_attr_list_unref (cc
->markup
);
254 cc
->markup
= g_value_peek_pointer (value
);
255 if (cc
->markup
!= NULL
)
256 pango_attr_list_ref (cc
->markup
);
260 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj
, param_id
, pspec
);
266 cell_comment_get_property (GObject
*obj
, guint param_id
,
267 GValue
*value
, GParamSpec
*pspec
)
269 GnmComment
*cc
= GNM_CELL_COMMENT (obj
);
272 g_value_set_string (value
, cc
->text
);
275 g_value_set_string (value
, cc
->author
);
278 g_value_set_boxed (value
, cc
->markup
);
281 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj
, param_id
, pspec
);
286 static SheetObjectView
*
287 cell_comment_new_view (SheetObject
*so
, SheetObjectViewContainer
*container
)
289 GnmPane
*pane
= GNM_PANE (container
);
290 GocItem
*view
= goc_item_new (pane
->grid_items
,
291 comment_view_get_type (),
293 CommentView
*cv
= (CommentView
*)view
;
294 GOStyle
*style
= go_styled_object_get_style (
295 GO_STYLED_OBJECT (goc_item_new (GOC_GROUP (view
),
296 GOC_TYPE_POLYGON
, NULL
)));
298 comment_view_reload_style (cv
);
300 style
->line
.dash_type
= GO_LINE_NONE
;
301 style
->fill
.pattern
.back
= go_color_from_gdk_rgba (&cv
->comment_indicator_color
, NULL
);
302 return gnm_pane_object_register (so
, view
, FALSE
);
306 cell_comment_write_xml_sax (SheetObject
const *so
, GsfXMLOut
*output
,
307 GnmConventions
const *convs
)
309 GnmComment
const *cc
= GNM_CELL_COMMENT (so
);
310 if (NULL
!= cc
->author
)
311 gsf_xml_out_add_cstr (output
, "Author", cc
->author
);
312 if (NULL
!= cc
->text
) {
313 gsf_xml_out_add_cstr (output
, "Text", cc
->text
);
314 if (NULL
!= cc
->markup
) {
315 GOFormat
*fmt
= go_format_new_markup (cc
->markup
, TRUE
);
316 gsf_xml_out_add_cstr (output
, "TextFormat",
317 go_format_as_XL (fmt
));
318 go_format_unref (fmt
);
324 cell_comment_prep_sax_parser (SheetObject
*so
, GsfXMLIn
*xin
,
325 xmlChar
const **attrs
,
326 GnmConventions
const *convs
)
328 GnmComment
*cc
= GNM_CELL_COMMENT (so
);
330 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
331 if (!strcmp (attrs
[0], "Text"))
332 cc
->text
= g_strdup (attrs
[1]);
333 else if (!strcmp (attrs
[0], "Author"))
334 cc
->author
= g_strdup (attrs
[1]);
335 else if (!strcmp (attrs
[0], "TextFormat")) {
336 GOFormat
* fmt
= go_format_new_from_XL (attrs
[1]);
337 if (go_format_is_markup (fmt
))
338 g_object_set (G_OBJECT (cc
),
339 "markup", go_format_get_markup (fmt
),
341 go_format_unref (fmt
);
347 cell_comment_copy (SheetObject
*dst
, SheetObject
const *src
)
349 GnmComment
const *comment
= GNM_CELL_COMMENT (src
);
350 GnmComment
*new_comment
= GNM_CELL_COMMENT (dst
);
351 new_comment
->author
= g_strdup (comment
->author
);
352 new_comment
->text
= g_strdup (comment
->text
);
353 new_comment
->markup
= comment
->markup
;
354 pango_attr_list_ref (new_comment
->markup
);
358 cell_comment_class_init (GObjectClass
*gobject_class
)
360 SheetObjectClass
*sheet_object_class
= GNM_SO_CLASS (gobject_class
);
362 cell_comment_parent_class
= g_type_class_peek_parent (gobject_class
);
364 /* Object class method overrides */
365 gobject_class
->finalize
= cell_comment_finalize
;
366 gobject_class
->set_property
= cell_comment_set_property
;
367 gobject_class
->get_property
= cell_comment_get_property
;
368 g_object_class_install_property (gobject_class
, CC_PROP_TEXT
,
369 g_param_spec_string ("text", NULL
, NULL
, NULL
,
370 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
371 g_object_class_install_property (gobject_class
, CC_PROP_AUTHOR
,
372 g_param_spec_string ("author", NULL
, NULL
, NULL
,
373 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
374 g_object_class_install_property (gobject_class
, CC_PROP_MARKUP
,
375 g_param_spec_boxed ("markup", NULL
, NULL
,
376 PANGO_TYPE_ATTR_LIST
,
377 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
379 /* SheetObject class method overrides */
380 sheet_object_class
->new_view
= &cell_comment_new_view
;
381 sheet_object_class
->write_xml_sax
= &cell_comment_write_xml_sax
;
382 sheet_object_class
->prep_sax_parser
= &cell_comment_prep_sax_parser
;
383 sheet_object_class
->copy
= &cell_comment_copy
;
384 sheet_object_class
->xml_export_name
= "CellComment";
388 cell_comment_init (GnmComment
*cc
)
393 GSF_CLASS (GnmComment
, cell_comment
,
394 cell_comment_class_init
, cell_comment_init
, GNM_SO_TYPE
)
397 cell_comment_author_get (GnmComment
const *cc
)
399 g_return_val_if_fail (GNM_IS_CELL_COMMENT (cc
), NULL
);
404 cell_comment_author_set (GnmComment
*cc
, char const *author
)
407 g_return_if_fail (GNM_IS_CELL_COMMENT (cc
));
409 tmp
= g_strdup (author
);
415 cell_comment_text_get (GnmComment
const *cc
)
417 g_return_val_if_fail (GNM_IS_CELL_COMMENT (cc
), NULL
);
422 cell_comment_text_set (GnmComment
*cc
, char const *text
)
425 g_return_if_fail (GNM_IS_CELL_COMMENT (cc
));
427 tmp
= g_strdup (text
);
432 /* convenience routine */
434 cell_comment_set_pos (GnmComment
*cc
, GnmCellPos
const *pos
)
437 static double const a_offsets
[4] = { 1., 0., 1., 0. };
438 SheetObjectAnchor anchor
;
441 g_return_if_fail (GNM_IS_CELL_COMMENT (cc
));
443 r
.start
= r
.end
= *pos
;
444 sheet_object_anchor_init (&anchor
, &r
, a_offsets
,
445 GOD_ANCHOR_DIR_DOWN_RIGHT
, GNM_SO_ANCHOR_TWO_CELLS
);
446 sheet_object_set_anchor (GNM_SO (cc
), &anchor
);
452 * @pos: the position.
453 * @author: comment author.
454 * @text: comment text.
455 * @markup: comment markup.
457 * Returns: (transfer none): the newly allocated #GnmComment.
460 cell_set_comment (Sheet
*sheet
, GnmCellPos
const *pos
,
461 char const *author
, char const *text
,
466 g_return_val_if_fail (IS_SHEET (sheet
), NULL
);
467 g_return_val_if_fail (pos
!= NULL
, NULL
);
469 cc
= g_object_new (GNM_CELL_COMMENT_TYPE
, NULL
);
470 cc
->author
= g_strdup (author
);
471 cc
->text
= g_strdup (text
);
473 if (cc
->markup
!= NULL
)
474 pango_attr_list_ref (cc
->markup
);
476 cell_comment_set_pos (cc
, pos
);
478 sheet_object_set_sheet (GNM_SO (cc
), sheet
);
479 /* setting the sheet added a reference */