Update Spanish translation
[gnumeric.git] / src / sheet-object-cell-comment.c
blobcd59172716028854d3c21afc8e808c99268df25a
2 /*
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
20 * USA
22 #include <gnumeric-config.h>
23 #include <gnumeric.h>
24 #include <sheet-object-cell-comment.h>
26 #include <gnm-pane-impl.h>
27 #include <sheet-object-impl.h>
28 #include <sheet.h>
29 #include <sheet-view.h>
30 #include <sheet-merge.h>
31 #include <sheet-control-gui-priv.h>
32 #include <dialogs/dialogs.h>
33 #include <gui-util.h>
34 #include <goffice/goffice.h>
36 #include <string.h>
37 #include <libxml/globals.h>
38 #include <gsf/gsf-impl-utils.h>
40 struct _GnmComment {
41 SheetObject base;
43 char *author, *text;
44 PangoAttrList *markup;
46 typedef SheetObjectClass GnmCommentClass;
47 static GObjectClass *cell_comment_parent_class;
48 enum {
49 CC_PROP_0,
50 CC_PROP_TEXT,
51 CC_PROP_AUTHOR,
52 CC_PROP_MARKUP
55 typedef struct {
56 SheetObjectView base;
58 GdkRGBA comment_indicator_color;
59 int comment_indicator_size;
60 } CommentView;
61 typedef SheetObjectViewClass CommentViewClass;
62 static GocItemClass *comment_view_parent_class;
64 static void
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,
79 NULL);
82 static void
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);
88 if (visible) {
89 SheetObject *so = sheet_object_view_get_so (sov);
90 SheetControlGUI const *scg = GNM_SIMPLE_CANVAS (item->canvas)->scg;
91 double scale;
92 gint64 x, y, dx;
93 int far_col;
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;
99 if (r != NULL)
100 far_col = 1 + r->end.col;
101 else
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));
121 } else
122 goc_item_hide (GOC_ITEM (sov));
125 static gboolean
126 comment_view_button_released (GocItem *item, int button, double x, double y)
128 SheetObject *so;
129 int ix, iy;
131 if (button != 1)
132 return FALSE;
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),
138 ix, iy);
140 return TRUE;
143 static gboolean
144 comment_view_button_pressed (GocItem *item, int button, double x, double y)
146 return TRUE;
149 static gboolean
150 comment_view_button2_pressed (GocItem *item, int button, double x, double y)
152 SheetObject *so;
153 GnmRange const *r;
154 SheetControlGUI *scg;
155 if (button !=1)
156 return FALSE;
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);
162 return TRUE;
165 static gboolean
166 comment_view_enter_notify (GocItem *item, double x, double y)
168 int ix, iy;
169 SheetObject *so;
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),
178 ix, iy);
179 return TRUE;
182 static gboolean
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))));
187 return TRUE;
190 static void
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,
208 GNM_SO_VIEW_TYPE)
210 static void
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););
223 g_free (cc->author);
224 cc->author = NULL;
225 g_free (cc->text);
226 cc->text = NULL;
228 if (NULL != cc->markup) {
229 pango_attr_list_unref (cc->markup);
230 cc->markup = NULL;
233 cell_comment_parent_class->finalize (object);
236 static void
237 cell_comment_set_property (GObject *obj, guint param_id,
238 GValue const *value, GParamSpec *pspec)
240 GnmComment *cc = GNM_CELL_COMMENT (obj);
242 switch (param_id) {
243 case CC_PROP_TEXT:
244 g_free (cc->text);
245 cc->text = g_value_dup_string (value);
246 break;
247 case CC_PROP_AUTHOR:
248 g_free (cc->author);
249 cc->author = g_value_dup_string (value);
250 break;
251 case CC_PROP_MARKUP:
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);
257 break;
259 default:
260 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
261 return;
265 static void
266 cell_comment_get_property (GObject *obj, guint param_id,
267 GValue *value, GParamSpec *pspec)
269 GnmComment *cc = GNM_CELL_COMMENT (obj);
270 switch (param_id) {
271 case CC_PROP_TEXT:
272 g_value_set_string (value, cc->text);
273 break;
274 case CC_PROP_AUTHOR:
275 g_value_set_string (value, cc->author);
276 break;
277 case CC_PROP_MARKUP:
278 g_value_set_boxed (value, cc->markup);
279 break;
280 default:
281 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
282 break;
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 (),
292 NULL);
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);
305 static void
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);
323 static void
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),
340 NULL);
341 go_format_unref (fmt);
346 static void
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);
357 static void
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";
387 static void
388 cell_comment_init (GnmComment *cc)
390 cc->markup = NULL;
393 GSF_CLASS (GnmComment, cell_comment,
394 cell_comment_class_init, cell_comment_init, GNM_SO_TYPE)
396 char const *
397 cell_comment_author_get (GnmComment const *cc)
399 g_return_val_if_fail (GNM_IS_CELL_COMMENT (cc), NULL);
400 return cc->author;
403 void
404 cell_comment_author_set (GnmComment *cc, char const *author)
406 char *tmp;
407 g_return_if_fail (GNM_IS_CELL_COMMENT (cc));
409 tmp = g_strdup (author);
410 g_free (cc->author);
411 cc->author = tmp;
414 char const *
415 cell_comment_text_get (GnmComment const *cc)
417 g_return_val_if_fail (GNM_IS_CELL_COMMENT (cc), NULL);
418 return cc->text;
421 void
422 cell_comment_text_set (GnmComment *cc, char const *text)
424 char *tmp;
425 g_return_if_fail (GNM_IS_CELL_COMMENT (cc));
427 tmp = g_strdup (text);
428 g_free (cc->text);
429 cc->text = tmp;
432 /* convenience routine */
433 void
434 cell_comment_set_pos (GnmComment *cc, GnmCellPos const *pos)
436 /* top right */
437 static double const a_offsets [4] = { 1., 0., 1., 0. };
438 SheetObjectAnchor anchor;
439 GnmRange r;
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);
450 * cell_set_comment:
451 * @sheet: #Sheet.
452 * @pos: the position.
453 * @author: comment author.
454 * @text: comment text.
455 * @markup: comment markup.
457 * Returns: (transfer none): the newly allocated #GnmComment.
459 GnmComment *
460 cell_set_comment (Sheet *sheet, GnmCellPos const *pos,
461 char const *author, char const *text,
462 PangoAttrList *attr)
464 GnmComment *cc;
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);
472 cc->markup = attr;
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 */
480 g_object_unref (cc);
482 return cc;