1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
5 * Copyright (C) 2012 Jean Bréfort <jean.brefort@normalesup.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) version 3.
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
23 #include <gnumeric-config.h>
25 #include "application.h"
26 #include "gnm-so-path.h"
27 #include "sheet-object-impl.h"
32 #include <goffice/goffice.h>
33 #include <gsf/gsf-impl-utils.h>
34 #include <glib/gi18n-lib.h>
36 #define CXML2C(s) ((char const *)(s))
38 static inline gboolean
39 attr_eq (const xmlChar
*a
, const char *s
)
41 return !strcmp (CXML2C (a
), s
);
44 #define GNM_SO_PATH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GNM_SO_PATH_TYPE, GnmSOPath))
50 double x_offset
, y_offset
, width
, height
;
51 GPtrArray
*paths
, *styles
;
54 PangoAttrList
*markup
;
56 double top
, bottom
, left
, right
;
59 typedef SheetObjectClass GnmSOPathClass
;
71 so_path_view_set_bounds (SheetObjectView
*sov
, double const *coords
, gboolean visible
)
73 GnmSOPathView
*spv
= (GnmSOPathView
*) sov
;
76 SheetObject
*so
= sheet_object_view_get_so (sov
);
77 GnmSOPath
const *sop
= GNM_SO_PATH (so
);
79 double scale
, x_scale
, y_scale
, x
, y
;
80 if ((sop
->path
== NULL
&& sop
->paths
== NULL
) || sop
->width
<=0. || sop
->height
<=0.)
83 scale
= goc_canvas_get_pixels_per_unit (GOC_ITEM (sov
)->canvas
);
84 x_scale
= fabs (coords
[2] - coords
[0]) / sop
->width
/ scale
;
85 y_scale
= fabs (coords
[3] - coords
[1]) / sop
->height
/ scale
;
86 x
= MIN (coords
[0], coords
[2]) / scale
- sop
->x_offset
* x_scale
;
87 y
= MIN (coords
[1], coords
[3]) / scale
- sop
->y_offset
* y_scale
;
89 if (sop
->path
!= NULL
) {
90 path
= go_path_scale (sop
->path
, x_scale
, y_scale
);
91 goc_item_set (spv
->path
, "x", x
, "y", y
, "path", path
, NULL
);
95 for (i
= 0; i
< sop
->paths
->len
; i
++) {
96 path
= go_path_scale ((GOPath
*) g_ptr_array_index (sop
->paths
, i
), x_scale
, y_scale
);
97 goc_item_set (GOC_ITEM (g_ptr_array_index (spv
->paths
, i
)), "x", x
, "y", y
, "path", path
, NULL
);
102 if (spv
->text
!= NULL
&& GOC_ITEM (spv
->text
)) {
103 double x0
, y0
, x1
, y1
;
105 goc_item_get_bounds (spv
->path
, &x0
, &y0
, &x1
, &y1
);
108 double mx
, my
, Mx
, My
;
109 x0
= y0
= G_MAXDOUBLE
;
110 x1
= y1
= -G_MAXDOUBLE
;
111 for (i
= 0; i
< spv
->paths
->len
; i
++) {
112 goc_item_get_bounds (GOC_ITEM (g_ptr_array_index (spv
->paths
, i
)), &mx
, &my
, &Mx
, &My
);
123 x1
-= x0
+ sop
->margin_pts
.left
+ sop
->margin_pts
.right
;
124 y1
-= y0
+ sop
->margin_pts
.top
+ sop
->margin_pts
.bottom
;
125 x0
+= x1
/ 2. + sop
->margin_pts
.left
;
126 y0
+= y1
/ 2. + sop
->margin_pts
.top
;
127 x1
= MAX (x1
, DBL_MIN
);
128 y1
= MAX (y1
, DBL_MIN
);
130 goc_item_set (GOC_ITEM (spv
->text
),
139 goc_item_hide (GOC_ITEM (sov
));
143 so_path_goc_view_class_init (SheetObjectViewClass
*sov_klass
)
145 sov_klass
->set_bounds
= so_path_view_set_bounds
;
148 typedef SheetObjectViewClass GnmSOPathViewClass
;
149 static GSF_CLASS (GnmSOPathView
, so_path_goc_view
,
150 so_path_goc_view_class_init
, NULL
,
155 /*****************************************************************************/
157 static SheetObjectClass
*gnm_so_path_parent_class
;
170 sop_default_style (void)
172 GOStyle
*res
= go_style_new ();
173 res
->interesting_fields
= GO_STYLE_OUTLINE
| GO_STYLE_FILL
;
174 res
->line
.width
= 0; /* hairline */
175 res
->line
.color
= GO_COLOR_BLACK
;
176 res
->line
.dash_type
= GO_LINE_SOLID
; /* anything but 0 */
177 res
->line
.join
= CAIRO_LINE_JOIN_ROUND
;
178 res
->fill
.type
= GO_STYLE_FILL_PATTERN
;
179 go_pattern_set_solid (&res
->fill
.pattern
, GO_COLOR_WHITE
);
184 #include <sheet-control-gui.h>
185 #include <dialogs/dialogs.h>
188 cb_gnm_so_path_style_changed (GocItem
*item
, GnmSOPath
const *sop
)
190 GOStyle
const *style
= sop
->style
;
191 goc_item_set (item
, "style", style
, NULL
);
195 gnm_so_path_user_config (SheetObject
*so
, SheetControl
*sc
)
197 GnmSOPath
*sop
= GNM_SO_PATH (so
);
198 dialog_so_styled (scg_wbcg (GNM_SCG (sc
)), G_OBJECT (sop
),
199 sop_default_style (),
200 _("Filled Object Properties"),
205 cb_gnm_so_path_changed (GnmSOPath
const *sop
,
206 G_GNUC_UNUSED GParamSpec
*pspec
,
207 GnmSOPathView
*group
)
209 GList
*ptr
= GOC_GROUP (group
)->children
;
210 for (; ptr
&& ptr
->data
; ptr
= ptr
->next
)
211 if (GOC_IS_PATH (ptr
->data
))
212 cb_gnm_so_path_style_changed (GOC_ITEM (ptr
->data
), sop
);
214 if (sop
->text
!= NULL
&& *sop
->text
!= 0) {
215 /* set a font, a very bad solution, but will do until we move to GOString */
216 PangoFontDescription
*desc
= pango_font_description_from_string ("Sans 10");
218 if (group
->text
== NULL
) {
219 double x0
, y0
, x1
, y1
;
221 goc_item_get_bounds (group
->path
, &x0
, &y0
, &x1
, &y1
);
224 double mx
, my
, Mx
, My
;
225 x0
= y0
= G_MAXDOUBLE
;
226 x1
= y1
= -G_MAXDOUBLE
;
227 for (i
= 0; i
< group
->paths
->len
; i
++) {
228 goc_item_get_bounds (GOC_ITEM (g_ptr_array_index (group
->paths
, i
)), &mx
, &my
, &Mx
, &My
);
239 x1
-= x0
+ sop
->margin_pts
.left
+ sop
->margin_pts
.right
;
240 y1
-= y0
+ sop
->margin_pts
.top
+ sop
->margin_pts
.bottom
;
241 x0
+= x1
/ 2. + sop
->margin_pts
.left
;
242 y0
+= y1
/ 2. + sop
->margin_pts
.top
;
243 x1
= MAX (x1
, DBL_MIN
);
244 y1
= MAX (y1
, DBL_MIN
);
245 group
->text
= goc_item_new (GOC_GROUP (group
), GOC_TYPE_TEXT
,
246 "anchor", GO_ANCHOR_CENTER
,
253 "attributes", sop
->markup
,
256 style
= go_styled_object_get_style (GO_STYLED_OBJECT (group
->text
));
257 go_style_set_font_desc (style
, desc
);
258 goc_item_set (group
->text
,
260 "attributes", sop
->markup
,
262 } else if (group
->text
!= NULL
) {
263 g_object_unref (group
->text
);
268 static SheetObjectView
*
269 gnm_so_path_new_view (SheetObject
*so
, SheetObjectViewContainer
*container
)
271 GnmSOPath
*sop
= GNM_SO_PATH (so
);
273 /* FIXME: this is unsafe if the paths change after the view is created,
274 * but this can't occur for now */
277 if (sop
->path
== NULL
&& sop
->paths
== NULL
)
279 item
= (GnmSOPathView
*) goc_item_new (
280 gnm_pane_object_group (GNM_PANE (container
)),
281 so_path_goc_view_get_type (),
284 item
->path
= goc_item_new (GOC_GROUP (item
),
290 item
->paths
= g_ptr_array_sized_new (sop
->paths
->len
);
291 g_ptr_array_set_free_func (item
->paths
, g_object_unref
);
292 for (i
= 0; i
< sop
->paths
->len
; i
++)
293 g_ptr_array_add (item
->paths
,
294 goc_item_new (GOC_GROUP (item
),
300 cb_gnm_so_path_changed (sop
, NULL
, item
);
301 g_signal_connect_object (sop
,
302 "notify::style", G_CALLBACK (cb_gnm_so_path_changed
),
304 return gnm_pane_object_register (so
, GOC_ITEM (item
), TRUE
);
310 gnm_so_path_draw_cairo (SheetObject
const *so
, cairo_t
*cr
,
311 double width
, double height
)
313 GnmSOPath
*sop
= GNM_SO_PATH (so
);
314 GOStyle
const *style
= sop
->style
;
318 cairo_move_to (cr
, -sop
->x_offset
, -sop
->y_offset
);
319 cairo_scale (cr
, width
/ sop
->width
, height
/ sop
->height
);
320 go_path_to_cairo (sop
->path
, GO_PATH_DIRECTION_FORWARD
, cr
);
323 cairo_set_fill_rule (cr
, CAIRO_FILL_RULE_EVEN_ODD
); /* might be an option */
324 go_style_fill (style
, cr
, TRUE
);
326 if (go_style_set_cairo_line (style
, cr
))
331 if (sop
->text
!= NULL
&& *(sop
->text
) != '\0') {
332 PangoLayout
*pl
= pango_cairo_create_layout (cr
);
333 double const scale_h
= 72. / gnm_app_display_dpi_get (TRUE
);
334 double const scale_v
= 72. / gnm_app_display_dpi_get (FALSE
);
335 double pl_height
= (height
- sop
->margin_pts
.top
336 - sop
->margin_pts
.bottom
) * PANGO_SCALE
338 double pl_width
= (width
- sop
->margin_pts
.left
339 - sop
->margin_pts
.right
) * PANGO_SCALE
341 /* set a font, a very bad solution, but will do until we move to GOString */
342 PangoFontDescription
*desc
= pango_font_description_from_string ("Sans 10");
344 pango_layout_set_font_description (pl
, desc
);
345 pango_layout_set_text (pl
, sop
->text
, -1);
346 pango_layout_set_attributes (pl
, sop
->markup
);
347 pango_layout_set_width (pl
, pl_width
);
348 pango_layout_set_height (pl
, pl_height
);
350 pango_layout_get_extents (pl
, NULL
, &r
);
352 (width
- r
.width
/ PANGO_SCALE
* scale_h
) / 2.,
353 (height
- r
.height
/ PANGO_SCALE
* scale_v
) / 2.);
354 cairo_scale (cr
, scale_h
, scale_v
);
355 cairo_set_source_rgba (cr
, GO_COLOR_TO_CAIRO (style
->font
.color
));
356 pango_cairo_show_layout (cr
, pl
);
364 gnm_so_path_write_xml_sax (SheetObject
const *so
, GsfXMLOut
*output
,
365 G_GNUC_UNUSED GnmConventions
const *convs
)
367 GnmSOPath
const *sop
= GNM_SO_PATH (so
);
370 if (sop
->text
!= NULL
&& *(sop
->text
) != '\0') {
371 gsf_xml_out_add_cstr (output
, "Label", sop
->text
);
372 if (sop
->markup
!= NULL
) {
373 GOFormat
*fmt
= go_format_new_markup (sop
->markup
, TRUE
);
374 gsf_xml_out_add_cstr (output
, "LabelFormat",
375 go_format_as_XL (fmt
));
376 go_format_unref (fmt
);
380 svg
= go_path_to_svg (sop
->path
);
381 gsf_xml_out_add_cstr (output
, "Path", svg
);
383 } else if (sop
->paths
) {
385 for (i
= 0; i
< sop
->paths
->len
; i
++) {
386 gsf_xml_out_start_element (output
, "Path");
387 svg
= go_path_to_svg ((GOPath
*) g_ptr_array_index (sop
->paths
, i
));
388 gsf_xml_out_add_cstr (output
, "Path", svg
);
390 gsf_xml_out_end_element (output
); /* </Path> */
394 gsf_xml_out_start_element (output
, "Style");
395 go_persist_sax_save (GO_PERSIST (sop
->style
), output
);
396 gsf_xml_out_end_element (output
); /* </Style> */
400 sop_sax_path (GsfXMLIn
*xin
, xmlChar
const **attrs
)
402 SheetObject
*so
= gnm_xml_in_cur_obj (xin
);
403 GnmSOPath
*sop
= GNM_SO_PATH (so
);
405 g_return_if_fail (sop
->path
== NULL
);
406 if (sop
->paths
== NULL
)
407 sop
->paths
= g_ptr_array_new_with_free_func ((GDestroyNotify
) go_path_free
);
408 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
409 if (attr_eq (attrs
[0], "Path")) {
410 path
= go_path_new_from_svg (attrs
[1]);
412 g_ptr_array_add (sop
->paths
, path
);
413 /* we need to update the extents, not optimal */
414 g_ptr_array_ref (sop
->paths
);
415 g_object_set (G_OBJECT (sop
), "paths", sop
->paths
, NULL
);
416 g_ptr_array_unref (sop
->paths
);
422 sop_sax_style (GsfXMLIn
*xin
, xmlChar
const **attrs
)
424 SheetObject
*so
= gnm_xml_in_cur_obj (xin
);
425 GnmSOPath
*sop
= GNM_SO_PATH (so
);
426 go_persist_prep_sax (GO_PERSIST (sop
->style
), xin
, attrs
);
430 gnm_so_path_prep_sax_parser (SheetObject
*so
, GsfXMLIn
*xin
,
431 xmlChar
const **attrs
,
432 G_GNUC_UNUSED GnmConventions
const *convs
)
434 static GsfXMLInNode
const dtd
[] = {
435 GSF_XML_IN_NODE (SOPATH
, SOPATH
, -1, "SheetObjectPath", GSF_XML_NO_CONTENT
, NULL
, NULL
),
436 GSF_XML_IN_NODE (SOPATH
, PATH
, -1, "Path", GSF_XML_NO_CONTENT
, &sop_sax_path
, NULL
),
437 GSF_XML_IN_NODE (SOPATH
, STYLE
, -1, "Style", GSF_XML_NO_CONTENT
, &sop_sax_style
, NULL
),
440 static GsfXMLInDoc
*doc
= NULL
;
441 GnmSOPath
*sop
= GNM_SO_PATH(so
);
444 doc
= gsf_xml_in_doc_new (dtd
, NULL
);
445 gnm_xml_in_doc_dispose_on_exit (&doc
);
447 gsf_xml_in_push_state (xin
, doc
, NULL
, NULL
, attrs
);
449 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
450 if (attr_eq (attrs
[0], "Label"))
451 g_object_set (G_OBJECT (sop
), "text", attrs
[1], NULL
);
452 else if (attr_eq (attrs
[0], "LabelFormat")) {
453 GOFormat
* fmt
= go_format_new_from_XL (attrs
[1]);
454 if (go_format_is_markup (fmt
))
455 g_object_set (G_OBJECT (sop
),
456 "markup", go_format_get_markup (fmt
),
458 go_format_unref (fmt
);
459 } else if (attr_eq (attrs
[0], "Path")) {
460 GOPath
*path
= go_path_new_from_svg (attrs
[1]);
462 g_object_set (G_OBJECT (sop
), "path", path
, NULL
);
469 gnm_so_path_copy (SheetObject
*dst
, SheetObject
const *src
)
471 GnmSOPath
const *sop
= GNM_SO_PATH (src
);
472 GnmSOPath
*new_sop
= GNM_SO_PATH (dst
);
474 g_object_unref (new_sop
->style
);
475 new_sop
->style
= go_style_dup (sop
->style
);
476 new_sop
->x_offset
= sop
->x_offset
;
477 new_sop
->y_offset
= sop
->y_offset
;
478 new_sop
->width
= sop
->width
;
479 new_sop
->height
= sop
->height
;
481 go_path_free (new_sop
->path
);
482 new_sop
->path
= NULL
;
483 } else if (new_sop
->paths
) {
484 g_ptr_array_unref (new_sop
->paths
);
485 new_sop
->paths
= NULL
;
488 new_sop
->path
= go_path_ref (sop
->path
);
491 new_sop
->paths
= g_ptr_array_new_full (sop
->paths
->len
,
492 (GDestroyNotify
) go_path_free
);
493 for (i
= 0; i
< sop
->paths
->len
; i
++)
494 g_ptr_array_add (new_sop
->paths
, go_path_ref (g_ptr_array_index (sop
->paths
, i
)));
496 gnm_so_path_parent_class
->copy (dst
, src
);
500 gnm_so_path_set_property (GObject
*obj
, guint param_id
,
501 GValue
const *value
, GParamSpec
*pspec
)
503 GnmSOPath
*sop
= GNM_SO_PATH (obj
);
506 case SOP_PROP_STYLE
: {
507 GOStyle
*style
= go_style_dup (g_value_get_object (value
));
508 style
->interesting_fields
= GO_STYLE_OUTLINE
| GO_STYLE_FILL
;
509 g_object_unref (sop
->style
);
513 case SOP_PROP_PATH
: {
514 GOPath
*path
= g_value_get_boxed (value
);
516 go_path_free (sop
->path
);
518 g_ptr_array_unref (sop
->paths
);
522 cairo_surface_t
*surface
= cairo_image_surface_create (CAIRO_FORMAT_ARGB32
, 1, 1);
523 cairo_t
*cr
= cairo_create (surface
);
525 sop
->path
= go_path_ref (path
);
526 /* evaluates the bounding rectangle */
527 go_path_to_cairo (path
, GO_PATH_DIRECTION_FORWARD
, cr
);
528 cairo_fill_extents (cr
,
529 &sop
->x_offset
, &sop
->y_offset
,
530 &sop
->width
, &sop
->height
);
531 sop
->width
-= sop
->x_offset
;
532 sop
->height
-= sop
->y_offset
;
534 cairo_surface_destroy (surface
);
538 case SOP_PROP_PATHS
: {
539 GPtrArray
*paths
= g_value_get_boxed (value
);
541 for (i
= 0; i
< paths
->len
; i
++)
542 /* we can only check that the path is not NULL */
543 g_return_if_fail (g_ptr_array_index (paths
, i
) != NULL
);
545 go_path_free (sop
->path
);
547 g_ptr_array_unref (sop
->paths
);
551 cairo_surface_t
*surface
= cairo_image_surface_create (CAIRO_FORMAT_ARGB32
, 1, 1);
552 cairo_t
*cr
= cairo_create (surface
);
554 sop
->paths
= g_ptr_array_ref (paths
);
555 /* evaluates the bounding rectangle */
556 for (i
= 0; i
< paths
->len
; i
++)
557 go_path_to_cairo ((GOPath
*) g_ptr_array_index (paths
, i
),
558 GO_PATH_DIRECTION_FORWARD
, cr
);
559 cairo_fill_extents (cr
,
560 &sop
->x_offset
, &sop
->y_offset
,
561 &sop
->width
, &sop
->height
);
562 sop
->width
-= sop
->x_offset
;
563 sop
->height
-= sop
->y_offset
;
565 cairo_surface_destroy (surface
);
569 case SOP_PROP_TEXT
: {
570 char const *str
= g_value_get_string (value
);
572 sop
->text
= g_strdup (str
== NULL
? "" : str
);
575 case SOP_PROP_MARKUP
:
576 if (sop
->markup
!= NULL
)
577 pango_attr_list_unref (sop
->markup
);
578 sop
->markup
= g_value_peek_pointer (value
);
579 if (sop
->markup
!= NULL
)
580 pango_attr_list_ref (sop
->markup
);
583 case SOP_PROP_VIEWBOX
:
586 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj
, param_id
, pspec
);
592 gnm_so_path_get_property (GObject
*obj
, guint param_id
,
593 GValue
*value
, GParamSpec
*pspec
)
595 GnmSOPath
*sop
= GNM_SO_PATH (obj
);
598 g_value_set_object (value
, sop
->style
);
601 g_value_set_boxed (value
, sop
->path
);
604 g_value_set_boxed (value
, sop
->paths
);
607 g_value_set_string (value
, sop
->text
);
609 case SOP_PROP_MARKUP
:
610 g_value_set_boxed (value
, sop
->markup
);
612 case SOP_PROP_VIEWBOX
:
615 g_strdup_printf ("%0.0f %0.0f %0.0f %0.0f", sop
->x_offset
, sop
->y_offset
,
616 sop
->width
+ sop
->x_offset
, sop
->height
+ sop
->y_offset
));
619 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj
, param_id
, pspec
);
625 gnm_so_path_finalize (GObject
*object
)
627 GnmSOPath
*sop
= GNM_SO_PATH (object
);
629 if (sop
->path
!= NULL
)
630 go_path_free (sop
->path
);
632 if (sop
->paths
!= NULL
)
633 g_ptr_array_unref (sop
->paths
);
635 g_object_unref (sop
->style
);
640 if (NULL
!= sop
->markup
) {
641 pango_attr_list_unref (sop
->markup
);
644 G_OBJECT_CLASS (gnm_so_path_parent_class
)->finalize (object
);
648 gnm_so_path_class_init (GObjectClass
*gobject_class
)
650 SheetObjectClass
*so_class
= GNM_SO_CLASS (gobject_class
);
652 gnm_so_path_parent_class
= g_type_class_peek_parent (gobject_class
);
654 gobject_class
->finalize
= gnm_so_path_finalize
;
655 gobject_class
->set_property
= gnm_so_path_set_property
;
656 gobject_class
->get_property
= gnm_so_path_get_property
;
657 so_class
->write_xml_sax
= gnm_so_path_write_xml_sax
;
658 so_class
->prep_sax_parser
= gnm_so_path_prep_sax_parser
;
659 so_class
->copy
= gnm_so_path_copy
;
660 so_class
->rubber_band_directly
= FALSE
;
661 so_class
->xml_export_name
= "SheetObjectPath";
664 so_class
->new_view
= gnm_so_path_new_view
;
665 so_class
->user_config
= gnm_so_path_user_config
;
666 #endif /* GNM_WITH_GTK */
667 so_class
->draw_cairo
= gnm_so_path_draw_cairo
;
669 g_object_class_install_property (gobject_class
, SOP_PROP_PATH
,
670 g_param_spec_boxed ("path", NULL
, NULL
, GO_TYPE_PATH
,
671 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
672 g_object_class_install_property (gobject_class
, SOP_PROP_STYLE
,
673 g_param_spec_object ("style", NULL
, NULL
, GO_TYPE_STYLE
,
674 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
675 g_object_class_install_property (gobject_class
, SOP_PROP_TEXT
,
676 g_param_spec_string ("text", NULL
, NULL
, NULL
,
677 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
678 g_object_class_install_property (gobject_class
, SOP_PROP_MARKUP
,
679 g_param_spec_boxed ("markup", NULL
, NULL
, PANGO_TYPE_ATTR_LIST
,
680 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
681 g_object_class_install_property (gobject_class
, SOP_PROP_PATHS
,
682 g_param_spec_boxed ("paths", NULL
, NULL
, G_TYPE_PTR_ARRAY
,
683 GSF_PARAM_STATIC
| G_PARAM_READWRITE
));
684 g_object_class_install_property (gobject_class
, SOP_PROP_VIEWBOX
,
685 g_param_spec_string ("viewbox", NULL
, NULL
, NULL
,
686 GSF_PARAM_STATIC
| G_PARAM_READABLE
));
690 gnm_so_path_init (GObject
*obj
)
692 GnmSOPath
*sop
= GNM_SO_PATH (obj
);
693 sop
->style
= sop_default_style ();
696 GSF_CLASS (GnmSOPath
, gnm_so_path
,
697 gnm_so_path_class_init
, gnm_so_path_init
,