1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * sheet-object-cell-comment.c: A SheetObject to support cell comments.
6 * Copyright (C) 2000-2004 Jody Goldberg (jody@gnome.org)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 #include <gnumeric-config.h>
25 #include "sheet-object-cell-comment.h"
27 #include "gnm-pane-impl.h"
28 #include "sheet-object-impl.h"
30 #include "sheet-view.h"
31 #include "sheet-merge.h"
32 #include "sheet-control-gui-priv.h"
35 #include <goffice/goffice.h>
38 #include <libxml/globals.h>
39 #include <gsf/gsf-impl-utils.h>
45 PangoAttrList
*markup
;
47 typedef SheetObjectClass GnmCommentClass
;
48 static GObjectClass
*cell_comment_parent_class
;
59 GdkRGBA comment_indicator_color
;
60 int comment_indicator_size
;
62 typedef SheetObjectViewClass CommentViewClass
;
63 static GocItemClass
*comment_view_parent_class
;
66 comment_view_reload_style (CommentView
*cv
)
68 GocItem
*item
= GOC_ITEM (cv
);
69 GnmPane
*pane
= GNM_PANE (item
->canvas
);
70 GtkStyleContext
*context
;
72 context
= goc_item_get_style_context (item
);
73 gnm_style_context_get_color (context
, GTK_STATE_FLAG_NORMAL
,
74 &cv
->comment_indicator_color
);
76 context
= gtk_widget_get_style_context (GTK_WIDGET (pane
));
77 gtk_widget_style_get (GTK_WIDGET (pane
),
78 "comment-indicator-size",
79 &cv
->comment_indicator_size
,
84 comment_view_set_bounds (SheetObjectView
*sov
, double const *coords
, gboolean visible
)
86 CommentView
*cv
= (CommentView
*)sov
;
87 GocPoints
*points
= goc_points_new (3);
88 GocItem
*item
= GOC_ITEM (GOC_GROUP (sov
)->children
->data
);
90 SheetObject
*so
= sheet_object_view_get_so (sov
);
91 SheetControlGUI
const *scg
= GNM_SIMPLE_CANVAS (item
->canvas
)->scg
;
95 GnmRange
const *r
= gnm_sheet_merge_is_corner (so
->sheet
,
96 &so
->anchor
.cell_bound
.start
);
98 scale
= 1. / item
->canvas
->pixels_per_unit
;
101 far_col
= 1 + r
->end
.col
;
103 far_col
= 1 + so
->anchor
.cell_bound
.start
.col
;
105 /* TODO : This could be optimized using the offsets associated with the visible region */
106 /* Add 1 to y because we measure from start, x is measured from end, so
107 * it does not need it */
108 y
= scg_colrow_distance_get (scg
, FALSE
, 0, so
->anchor
.cell_bound
.start
.row
)+ 1;
109 points
->points
[0].y
= scale
* y
;
110 points
->points
[1].y
= scale
* y
;
111 points
->points
[2].y
= scale
* y
+ cv
->comment_indicator_size
;
113 dx
= cv
->comment_indicator_size
;
114 x
= scg_colrow_distance_get (scg
, TRUE
, 0, far_col
);
115 points
->points
[0].x
= scale
* x
- dx
;
116 points
->points
[1].x
= scale
* x
;
117 points
->points
[2].x
= scale
* x
;
119 goc_item_set (item
, "points", points
, NULL
);
120 goc_points_unref (points
);
121 goc_item_show (GOC_ITEM (sov
));
123 goc_item_hide (GOC_ITEM (sov
));
127 comment_view_button_released (GocItem
*item
, int button
, double x
, double y
)
135 gnm_canvas_get_screen_position (item
->canvas
, x
, y
, &ix
, &iy
);
136 so
= sheet_object_view_get_so (GNM_SO_VIEW (item
));
137 scg_comment_display (GNM_PANE (item
->canvas
)->simple
.scg
,
138 GNM_CELL_COMMENT (so
),
145 comment_view_button_pressed (GocItem
*item
, int button
, double x
, double y
)
151 comment_view_button2_pressed (GocItem
*item
, int button
, double x
, double y
)
155 SheetControlGUI
*scg
;
159 scg
= GNM_PANE (item
->canvas
)->simple
.scg
;
160 so
= sheet_object_view_get_so (GNM_SO_VIEW (item
));
161 r
= sheet_object_get_range (so
);
162 dialog_cell_comment (scg
->wbcg
, so
->sheet
, &r
->start
);
167 comment_view_enter_notify (GocItem
*item
, double x
, double y
)
172 gnm_widget_set_cursor_type (GTK_WIDGET (item
->canvas
), GDK_ARROW
);
174 gnm_canvas_get_screen_position (item
->canvas
, x
, y
, &ix
, &iy
);
175 so
= sheet_object_view_get_so (GNM_SO_VIEW (item
));
177 scg_comment_select (GNM_PANE (item
->canvas
)->simple
.scg
,
178 GNM_CELL_COMMENT (so
),
184 comment_view_leave_notify (GocItem
*item
, double x
, double y
)
186 scg_comment_unselect (GNM_PANE (item
->canvas
)->simple
.scg
,
187 GNM_CELL_COMMENT (sheet_object_view_get_so (GNM_SO_VIEW (item
))));
192 comment_view_class_init (SheetObjectViewClass
*sov_klass
)
194 GocItemClass
*item_klass
= (GocItemClass
*) sov_klass
;
196 comment_view_parent_class
= g_type_class_peek_parent (sov_klass
);
198 sov_klass
->set_bounds
= comment_view_set_bounds
;
200 item_klass
->button_pressed
= comment_view_button_pressed
;
201 item_klass
->button_released
= comment_view_button_released
;
202 item_klass
->button2_pressed
= comment_view_button2_pressed
;
203 item_klass
->enter_notify
= comment_view_enter_notify
;
204 item_klass
->leave_notify
= comment_view_leave_notify
;
207 static GSF_CLASS (CommentView
, comment_view
,
208 comment_view_class_init
, NULL
,
212 cell_comment_finalize (GObject
*object
)
214 GnmComment
*cc
= GNM_CELL_COMMENT (object
);
216 g_return_if_fail (cc
!= NULL
);
218 /* If this comment is being displayed we shut down nicely */
219 if (cc
->base
.sheet
!= NULL
) {
220 SHEET_FOREACH_CONTROL (cc
->base
.sheet
, view
, control
,
221 scg_comment_unselect ((SheetControlGUI
*) control
, cc
););
229 if (NULL
!= cc
->markup
) {
230 pango_attr_list_unref (cc
->markup
);
234 cell_comment_parent_class
->finalize (object
);
238 cell_comment_set_property (GObject
*obj
, guint param_id
,
239 GValue
const *value
, GParamSpec
*pspec
)
241 GnmComment
*cc
= GNM_CELL_COMMENT (obj
);
246 cc
->text
= g_value_dup_string (value
);
250 cc
->author
= g_value_dup_string (value
);
253 if (cc
->markup
!= NULL
)
254 pango_attr_list_unref (cc
->markup
);
255 cc
->markup
= g_value_peek_pointer (value
);
256 if (cc
->markup
!= NULL
)
257 pango_attr_list_ref (cc
->markup
);
261 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj
, param_id
, pspec
);
267 cell_comment_get_property (GObject
*obj
, guint param_id
,
268 GValue
*value
, GParamSpec
*pspec
)
270 GnmComment
*cc
= GNM_CELL_COMMENT (obj
);
273 g_value_set_string (value
, cc
->text
);
276 g_value_set_string (value
, cc
->author
);
279 g_value_set_boxed (value
, cc
->markup
);
282 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj
, param_id
, pspec
);
287 static SheetObjectView
*
288 cell_comment_new_view (SheetObject
*so
, SheetObjectViewContainer
*container
)
290 GnmPane
*pane
= GNM_PANE (container
);
291 GocItem
*view
= goc_item_new (pane
->grid_items
,
292 comment_view_get_type (),
294 CommentView
*cv
= (CommentView
*)view
;
295 GOStyle
*style
= go_styled_object_get_style (
296 GO_STYLED_OBJECT (goc_item_new (GOC_GROUP (view
),
297 GOC_TYPE_POLYGON
, NULL
)));
299 comment_view_reload_style (cv
);
301 style
->line
.dash_type
= GO_LINE_NONE
;
302 style
->fill
.pattern
.back
= go_color_from_gdk_rgba (&cv
->comment_indicator_color
, NULL
);
303 return gnm_pane_object_register (so
, view
, FALSE
);
307 cell_comment_write_xml_sax (SheetObject
const *so
, GsfXMLOut
*output
,
308 GnmConventions
const *convs
)
310 GnmComment
const *cc
= GNM_CELL_COMMENT (so
);
311 if (NULL
!= cc
->author
)
312 gsf_xml_out_add_cstr (output
, "Author", cc
->author
);
313 if (NULL
!= cc
->text
) {
314 gsf_xml_out_add_cstr (output
, "Text", cc
->text
);
315 if (NULL
!= cc
->markup
) {
316 GOFormat
*fmt
= go_format_new_markup (cc
->markup
, TRUE
);
317 gsf_xml_out_add_cstr (output
, "TextFormat",
318 go_format_as_XL (fmt
));
319 go_format_unref (fmt
);
325 cell_comment_prep_sax_parser (SheetObject
*so
, GsfXMLIn
*xin
,
326 xmlChar
const **attrs
,
327 GnmConventions
const *convs
)
329 GnmComment
*cc
= GNM_CELL_COMMENT (so
);
331 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
332 if (!strcmp (attrs
[0], "Text"))
333 cc
->text
= g_strdup (attrs
[1]);
334 else if (!strcmp (attrs
[0], "Author"))
335 cc
->author
= g_strdup (attrs
[1]);
336 else if (!strcmp (attrs
[0], "TextFormat")) {
337 GOFormat
* fmt
= go_format_new_from_XL (attrs
[1]);
338 if (go_format_is_markup (fmt
))
339 g_object_set (G_OBJECT (cc
),
340 "markup", go_format_get_markup (fmt
),
342 go_format_unref (fmt
);
348 cell_comment_copy (SheetObject
*dst
, SheetObject
const *src
)
350 GnmComment
const *comment
= GNM_CELL_COMMENT (src
);
351 GnmComment
*new_comment
= GNM_CELL_COMMENT (dst
);
352 new_comment
->author
= g_strdup (comment
->author
);
353 new_comment
->text
= g_strdup (comment
->text
);
354 new_comment
->markup
= comment
->markup
;
355 pango_attr_list_ref (new_comment
->markup
);
359 cell_comment_class_init (GObjectClass
*gobject_class
)
361 SheetObjectClass
*sheet_object_class
= GNM_SO_CLASS (gobject_class
);
363 cell_comment_parent_class
= g_type_class_peek_parent (gobject_class
);
365 /* Object class method overrides */
366 gobject_class
->finalize
= cell_comment_finalize
;
367 gobject_class
->set_property
= cell_comment_set_property
;
368 gobject_class
->get_property
= cell_comment_get_property
;
369 g_object_class_install_property (gobject_class
, CC_PROP_TEXT
,
370 g_param_spec_string ("text", NULL
, NULL
, NULL
,
371 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
372 g_object_class_install_property (gobject_class
, CC_PROP_AUTHOR
,
373 g_param_spec_string ("author", NULL
, NULL
, NULL
,
374 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
375 g_object_class_install_property (gobject_class
, CC_PROP_MARKUP
,
376 g_param_spec_boxed ("markup", NULL
, NULL
,
377 PANGO_TYPE_ATTR_LIST
,
378 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
380 /* SheetObject class method overrides */
381 sheet_object_class
->new_view
= &cell_comment_new_view
;
382 sheet_object_class
->write_xml_sax
= &cell_comment_write_xml_sax
;
383 sheet_object_class
->prep_sax_parser
= &cell_comment_prep_sax_parser
;
384 sheet_object_class
->copy
= &cell_comment_copy
;
385 sheet_object_class
->xml_export_name
= "CellComment";
389 cell_comment_init (GnmComment
*cc
)
394 GSF_CLASS (GnmComment
, cell_comment
,
395 cell_comment_class_init
, cell_comment_init
, GNM_SO_TYPE
)
398 cell_comment_author_get (GnmComment
const *cc
)
400 g_return_val_if_fail (GNM_IS_CELL_COMMENT (cc
), NULL
);
405 cell_comment_author_set (GnmComment
*cc
, char const *author
)
408 g_return_if_fail (GNM_IS_CELL_COMMENT (cc
));
410 tmp
= g_strdup (author
);
416 cell_comment_text_get (GnmComment
const *cc
)
418 g_return_val_if_fail (GNM_IS_CELL_COMMENT (cc
), NULL
);
423 cell_comment_text_set (GnmComment
*cc
, char const *text
)
426 g_return_if_fail (GNM_IS_CELL_COMMENT (cc
));
428 tmp
= g_strdup (text
);
433 /* convenience routine */
435 cell_comment_set_pos (GnmComment
*cc
, GnmCellPos
const *pos
)
438 static double const a_offsets
[4] = { 1., 0., 1., 0. };
439 SheetObjectAnchor anchor
;
442 g_return_if_fail (GNM_IS_CELL_COMMENT (cc
));
444 r
.start
= r
.end
= *pos
;
445 sheet_object_anchor_init (&anchor
, &r
, a_offsets
,
446 GOD_ANCHOR_DIR_DOWN_RIGHT
, GNM_SO_ANCHOR_TWO_CELLS
);
447 sheet_object_set_anchor (GNM_SO (cc
), &anchor
);
453 * @pos: the position.
454 * @author: comment author.
455 * @text: comment text.
456 * @markup: comment markup.
458 * Returns: (transfer none): the newly allocated #GnmComment.
461 cell_set_comment (Sheet
*sheet
, GnmCellPos
const *pos
,
462 char const *author
, char const *text
,
467 g_return_val_if_fail (IS_SHEET (sheet
), NULL
);
468 g_return_val_if_fail (pos
!= NULL
, NULL
);
470 cc
= g_object_new (GNM_CELL_COMMENT_TYPE
, NULL
);
471 cc
->author
= g_strdup (author
);
472 cc
->text
= g_strdup (text
);
474 if (cc
->markup
!= NULL
)
475 pango_attr_list_ref (cc
->markup
);
477 cell_comment_set_pos (cc
, pos
);
479 sheet_object_set_sheet (GNM_SO (cc
), sheet
);
480 /* setting the sheet added a reference */