[goffice] Revisited the component API.
- From: Jean BrÃfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Revisited the component API.
- Date: Tue, 2 Aug 2011 19:04:17 +0000 (UTC)
commit 40f5a78a21b41446500cf17e6e7ea90300f31dc3
Author: Jean Brefort <jean brefort normalesup org>
Date: Tue Aug 2 20:59:36 2011 +0200
Revisited the component API.
ChangeLog | 25 ++
configure.in | 13 +
goffice/canvas/Makefile.am | 2 +
goffice/canvas/goc-component.c | 317 ++++++++++++++++++
goffice/canvas/goc-component.h | 40 +++
goffice/canvas/goffice-canvas.h | 2 +
goffice/component/Makefile.am | 6 +-
goffice/component/go-component-factory.c | 15 +-
goffice/component/go-component-factory.h | 1 +
goffice/component/go-component-mime-dialog.c | 102 ++++++
goffice/component/go-component-mime-dialog.h | 41 +++
goffice/component/go-component.c | 449 +++++++++++++++++++++++++-
goffice/component/go-component.h | 23 ++-
goffice/component/goffice-component.h | 2 +
goffice/graph/gog-axis-line.c | 6 +-
goffice/graph/gog-axis.c | 4 +-
goffice/graph/gog-renderer.c | 12 +-
goffice/graph/gog-renderer.h | 4 +-
goffice/graph/gog-series-labels.c | 6 +-
goffice/gtk/go-format-sel.c | 4 +-
goffice/utils/go-format.c | 24 +-
goffice/utils/go-pango-extras.h | 4 +-
plugins/plot_barcol/gog-barcol.c | 2 +-
23 files changed, 1061 insertions(+), 43 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index fa52a0a..5b1c8ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
2011-08-02 Jean Brefort <jean brefort normalesup org>
+ * configure.in: needs librsvg.
+ * goffice/canvas/Makefile.am: add component support to the canvas.
+ * goffice/canvas/goc-component.c: ditto.
+ * goffice/canvas/goc-component.h: ditto.
+ * goffice/canvas/goffice-canvas.h: ditto.
+ * goffice/component/Makefile.am: revisited the component API.
+ * goffice/component/go-component-factory.c: ditto.
+ * goffice/component/go-component-factory.h: ditto.
+ * goffice/component/go-component-mime-dialog.c: ditto.
+ * goffice/component/go-component-mime-dialog.h: ditto.
+ * goffice/component/go-component.c: ditto.
+ * goffice/component/go-component.h: ditto.
+ * goffice/component/goffice-component.h: ditto.
+ * goffice/graph/gog-axis-line.c: cleaned out extra spaces.
+ * goffice/graph/gog-axis.c: ditto.
+ * goffice/graph/gog-renderer.c: ditto.
+ * goffice/graph/gog-renderer.h: ditto.
+ * goffice/graph/gog-series-labels.c: ditto.
+ * goffice/gtk/go-format-sel.c: ditto.
+ * goffice/utils/go-format.c: ditto.
+ * goffice/utils/go-pango-extras.h: ditto.
+ * plugins/plot_barcol/gog-barcol.c: ditto.
+
+2011-08-02 Jean Brefort <jean brefort normalesup org>
+
* goffice/data/go-data-impl.h: add markup support.
* goffice/data/go-data.c: ditto.
* goffice/data/go-data.h: ditto.
diff --git a/configure.in b/configure.in
index 0f18cf9..3958d21 100644
--- a/configure.in
+++ b/configure.in
@@ -102,6 +102,7 @@ goffice_reqs="
pango >= 1.24.0
pangocairo >= 1.24.0
cairo >= 1.10.0
+ librsvg-2.0 >= 2.22.0
"
goffice_gtk_reqs="
@@ -134,6 +135,18 @@ if test "x$goffice_with_lasem" = "xtrue" ; then
EXTRA_DEPS="$EXTRA_DEPS lasem-0.4"
fi
+goffice_with_rsvg=false
+AC_ARG_WITH(librsvg, [ --with-librsvg Build with librsvg use])
+if test "x$with_librsvg" = xyes; then
+ PKG_CHECK_MODULES(rsvg, librsvg-2.0 >= 2.22.0)
+ goffice_with_rsvg=true
+fi
+if test "x$goffice_with_rsvg" = "xtrue" ; then
+ AC_DEFINE(GOFFICE_WITH_RSVG, 1, [Define if librsvg is used])
+ goffice_reqs="$goffice_reqs librsvg-2.0 >= 2.22.0 "
+ EXTRA_DEPS="$EXTRA_DEPS librsvg-2.0"
+fi
+
AM_CONDITIONAL(GOFFICE_WITH_LASEM, $goffice_with_lasem)
diff --git a/goffice/canvas/Makefile.am b/goffice/canvas/Makefile.am
index 20b4913..47b44bf 100644
--- a/goffice/canvas/Makefile.am
+++ b/goffice/canvas/Makefile.am
@@ -4,6 +4,7 @@ libgoffice_canvas_la_SOURCES = \
goc-arc.c \
goc-canvas.c \
goc-circle.c \
+ goc-component.c \
goc-ellipse.c \
goc-graph.c \
goc-group.c \
@@ -24,6 +25,7 @@ libgoffice_canvas_la_HEADERS = \
goc-arc.h \
goc-canvas.h \
goc-circle.h \
+ goc-component.h \
goc-ellipse.h \
goc-graph.h \
goc-group.h \
diff --git a/goffice/canvas/goc-component.c b/goffice/canvas/goc-component.c
new file mode 100644
index 0000000..ebfad44
--- /dev/null
+++ b/goffice/canvas/goc-component.c
@@ -0,0 +1,317 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * goc-component.c :
+ *
+ * Copyright (C) 2010 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include <goffice/goffice.h>
+
+#include <glib/gi18n-lib.h>
+#include <gsf/gsf-impl-utils.h>
+
+/**
+ * SECTION:goc-component
+ * @short_description: Components.
+ *
+ * #GocComponent implements #GOComponent embedding in the canvas.
+**/
+
+struct _GocComponent {
+ GocItem base;
+
+ double x, y, w, h;
+ double rotation;
+ GOComponent *component;
+};
+
+typedef GocItemClass GocComponentClass;
+
+static GObjectClass *parent_klass;
+
+enum {
+ COMPONENT_PROP_0,
+ COMPONENT_PROP_X,
+ COMPONENT_PROP_Y,
+ COMPONENT_PROP_H,
+ COMPONENT_PROP_W,
+ COMPONENT_PROP_ROTATION,
+ COMPONENT_PROP_OBJECT
+};
+
+static void
+goc_component_set_property (GObject *obj, guint param_id,
+ GValue const *value, GParamSpec *pspec)
+{
+ GocComponent *component = GOC_COMPONENT (obj);
+
+ switch (param_id) {
+ case COMPONENT_PROP_X: {
+ double x = g_value_get_double (value);
+ if (x == component->x)
+ return;
+ component->x = x;
+ return;
+ }
+ case COMPONENT_PROP_Y: {
+ double y = g_value_get_double (value);
+ if (y == component->y)
+ return;
+ component->y = y;
+ break;
+ }
+ /* NOTE: it is allowed to set width and height even if the component is not resizable
+ * but this should be only used to convert the size in inches to pixels.
+ * The default is 1 pixel == 1 point.
+ */
+ case COMPONENT_PROP_H: {
+ double h = g_value_get_double (value);
+ if (!component->component || h == component->h)
+ return;
+ component->h = h;
+ break;
+ }
+ case COMPONENT_PROP_W: {
+ double w = g_value_get_double (value);
+ if (!component->component || w == component->w)
+ return;
+ component->w = w;
+ break;
+ }
+ case COMPONENT_PROP_ROTATION: {
+ double r = g_value_get_double (value) / 180. * M_PI;
+ if (!component->component || go_component_needs_window (component->component) || r == component->rotation)
+ return;
+ component->rotation = r;
+ break;
+ }
+
+ case COMPONENT_PROP_OBJECT:
+ if (component->component != NULL)
+ g_object_unref (component->component);
+ component->component = GO_COMPONENT (g_value_get_object (value));
+ if (component->component != NULL) {
+ g_object_ref (component->component);
+ /* set default or fixed size */
+ go_component_get_size (component->component, &component->w, &component->h);
+ component->w = GO_IN_TO_PT (component->w);
+ component->h = GO_IN_TO_PT (component->h);
+ }
+ break;
+
+ default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+ return; /* NOTE : RETURN */
+ }
+
+ goc_item_bounds_changed (GOC_ITEM (component));
+}
+
+static void
+goc_component_get_property (GObject *obj, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GocComponent *component = GOC_COMPONENT (obj);
+
+ switch (param_id) {
+ case COMPONENT_PROP_X:
+ g_value_set_double (value, component->x);
+ break;
+ case COMPONENT_PROP_Y:
+ g_value_set_double (value, component->y);
+ break;
+ case COMPONENT_PROP_H:
+ g_value_set_double (value, component->h);
+ break;
+ case COMPONENT_PROP_W:
+ g_value_set_double (value, component->w);
+ break;
+ case COMPONENT_PROP_ROTATION:
+ g_value_set_double (value, component->rotation * 180. / M_PI);
+ break;
+ case COMPONENT_PROP_OBJECT:
+ g_value_set_object (value, component->component);
+ break;
+
+ default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+goc_component_finalize (GObject *obj)
+{
+ GocComponent *component = GOC_COMPONENT (obj);
+
+ if (component->component != NULL) {
+ g_object_unref (component->component);
+ component->component = NULL;
+ }
+ (*parent_klass->finalize) (obj);
+}
+
+static double
+goc_component_distance (GocItem *item, double x, double y, GocItem **near_item)
+{
+ GocComponent *component = GOC_COMPONENT (item);
+ double dx, dy;
+ x -= component->x;
+ y -= component->y;
+ /* adjust for rotation */
+ if (component->rotation != 0.) {
+ double sinr = sin (-component->rotation), cosr = cos (component->rotation), t;
+ x -= component->w / 2.;
+ y -= component->h / 2.;
+ t = x * cosr + y * sinr;
+ y = y * cosr - x * sinr;
+ x = t + component->w / 2.;
+ y += component->h / 2.;
+ }
+ if (x < 0) {
+ dx = -x;
+ } else if (x < component->w) {
+ dx = 0;
+ } else {
+ dx = x - component->w;
+ }
+ if (y < 0) {
+ dy = -y;
+ } else if (y < component->h) {
+ dy = 0;
+ } else {
+ dy = y - component->h;
+ }
+ *near_item = item;
+ return hypot (dx, dy);
+}
+
+static void
+goc_component_draw (GocItem const *item, cairo_t *cr)
+{
+ GocComponent *component = GOC_COMPONENT (item);
+ GocCanvas *canvas = item->canvas;
+ double x0, y0 = component->y;
+ if (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL) {
+ x0 = component->x + component->w;
+ goc_group_adjust_coords (item->parent, &x0, &y0);
+ x0 = canvas->width - (int) (x0 - canvas->scroll_x1) * canvas->pixels_per_unit;
+ } else {
+ x0 = component->x;
+ goc_group_adjust_coords (item->parent, &x0, &y0);
+ x0 = (int) (x0 - canvas->scroll_x1) * canvas->pixels_per_unit;
+ }
+ cairo_save (cr);
+ if (component->rotation == 0.)
+ cairo_translate (cr, x0,
+ (int) (y0 - canvas->scroll_y1) * canvas->pixels_per_unit);
+ else {
+ cairo_translate (cr, x0 + component->w / 2 * canvas->pixels_per_unit,
+ (int) (y0 - canvas->scroll_y1 + component->h / 2) * canvas->pixels_per_unit);
+ cairo_rotate (cr, -component->rotation);
+ cairo_translate (cr, -component->w / 2 * canvas->pixels_per_unit,
+ -component->h / 2 * canvas->pixels_per_unit);
+ }
+ cairo_rectangle (cr, 0., 0., component->w * canvas->pixels_per_unit,
+ component->h * canvas->pixels_per_unit);
+ cairo_clip (cr);
+ go_component_render (component->component, cr,
+ component->w * canvas->pixels_per_unit,
+ component->h * canvas->pixels_per_unit);
+ cairo_restore (cr);
+}
+
+static void
+goc_component_update_bounds (GocItem *item)
+{
+ GocComponent *component = GOC_COMPONENT (item);
+ if (component->rotation == 0.) {
+ item->x0 = component->x;
+ item->y0 = component->y;
+ item->x1 = component->x + component->w;
+ item->y1 = component->y + component->h;
+ } else {
+ double cosr = cos (component->rotation), sinr = sin (component->rotation);
+ double w = fabs (component->w * cosr) + fabs (component->h * sinr), h = fabs (component->h * cosr) + fabs (component->w * sinr);
+ item->x0 = component->x + (component->w - w) / 2.;
+ item->x1 = item->x0 + w;
+ item->y0 = component->y + (component->h - h) / 2.;
+ item->y1 = item->y0 + h;
+ }
+}
+
+static void
+goc_component_class_init (GocItemClass *item_klass)
+{
+ GObjectClass *obj_klass = (GObjectClass *) item_klass;
+
+ parent_klass = g_type_class_peek_parent (obj_klass);
+
+ obj_klass->set_property = goc_component_set_property;
+ obj_klass->get_property = goc_component_get_property;
+ obj_klass->finalize = goc_component_finalize;
+
+ g_object_class_install_property (obj_klass, COMPONENT_PROP_X,
+ g_param_spec_double ("x",
+ _("x"),
+ _("The object left position"),
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, COMPONENT_PROP_Y,
+ g_param_spec_double ("y",
+ _("y"),
+ _("The object top position"),
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, COMPONENT_PROP_H,
+ g_param_spec_double ("height",
+ _("Height"),
+ _("Height"),
+ 0, G_MAXDOUBLE, 100.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, COMPONENT_PROP_W,
+ g_param_spec_double ("width",
+ _("Width"),
+ _("Width"),
+ 0, G_MAXDOUBLE, 100.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, COMPONENT_PROP_ROTATION,
+ g_param_spec_double ("rotation",
+ _("Rotation"),
+ _("The rotation around center, only available for windowless components"),
+ 0., 360., 0.,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+ g_object_class_install_property (obj_klass, COMPONENT_PROP_OBJECT,
+ g_param_spec_object ("object",
+ _("Object"),
+ _("The embedded GOComponent object"),
+ GO_TYPE_COMPONENT,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+
+ item_klass->draw = goc_component_draw;
+ item_klass->update_bounds = goc_component_update_bounds;
+ item_klass->distance = goc_component_distance;
+}
+
+GSF_CLASS (GocComponent, goc_component,
+ goc_component_class_init, NULL,
+ GOC_TYPE_ITEM)
+
+GOComponent * goc_component_get_object (GocComponent *component)
+{
+ g_return_val_if_fail (GOC_IS_COMPONENT (component), NULL);
+ return component->component;
+}
diff --git a/goffice/canvas/goc-component.h b/goffice/canvas/goc-component.h
new file mode 100644
index 0000000..729b3cd
--- /dev/null
+++ b/goffice/canvas/goc-component.h
@@ -0,0 +1,40 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * goc-component.h :
+ *
+ * Copyright (C) 2010 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GOC_COMPONENT_H
+#define GOC_COMPONENT_H
+
+#include <goffice/goffice.h>
+#include <goffice/component/goffice-component.h>
+
+G_BEGIN_DECLS
+
+#define GOC_TYPE_COMPONENT (goc_component_get_type ())
+#define GOC_COMPONENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOC_TYPE_COMPONENT, GocComponent))
+#define GOC_IS_COMPONENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOC_TYPE_COMPONENT))
+
+GType goc_component_get_type (void);
+
+GOComponent * goc_component_get_object (GocComponent *component);
+
+G_END_DECLS
+
+#endif /* GOC_COMPONENT_H */
diff --git a/goffice/canvas/goffice-canvas.h b/goffice/canvas/goffice-canvas.h
index ff41f38..c5034bc 100644
--- a/goffice/canvas/goffice-canvas.h
+++ b/goffice/canvas/goffice-canvas.h
@@ -44,6 +44,7 @@ typedef struct _GocStyledItem GocStyledItem;
typedef struct _GocText GocText;
typedef struct _GocWidget GocWidget;
typedef struct _GocGraph GocGraph;
+typedef struct _GocComponent GocComponent;
G_END_DECLS
@@ -56,6 +57,7 @@ G_END_DECLS
#include <goffice/canvas/goc-utils.h>
#include <goffice/canvas/goc-circle.h>
+#include <goffice/canvas/goc-component.h>
#include <goffice/canvas/goc-ellipse.h>
#include <goffice/canvas/goc-graph.h>
#include <goffice/canvas/goc-group.h>
diff --git a/goffice/component/Makefile.am b/goffice/component/Makefile.am
index 76a4b05..c68f52b 100644
--- a/goffice/component/Makefile.am
+++ b/goffice/component/Makefile.am
@@ -2,13 +2,15 @@ noinst_LTLIBRARIES = libgoffice-component.la
libgoffice_component_la_SOURCES = \
go-component.c \
- go-component-factory.c
+ go-component-factory.c \
+ go-component-mime-dialog.c
libgoffice_component_ladir = $(goffice_include_dir)/component
libgoffice_component_la_HEADERS = \
goffice-component.h \
go-component.h \
- go-component-factory.h
+ go-component-factory.h \
+ go-component-mime-dialog.h
include $(top_srcdir)/goffice.mk
diff --git a/goffice/component/go-component-factory.c b/goffice/component/go-component-factory.c
index 469f6ad..f31b8a9 100644
--- a/goffice/component/go-component-factory.c
+++ b/goffice/component/go-component-factory.c
@@ -330,7 +330,7 @@ GOComponent *
go_component_new_by_mime_type (char const *mime_type)
{
GType type;
- GOMimeType *mtype = g_hash_table_lookup (mime_types, mime_type);
+ GOMimeType *mtype = (mime_types)? g_hash_table_lookup (mime_types, mime_type): NULL;
if (mtype == NULL)
return NULL;
type = g_type_from_name (mtype->component_type_name);
@@ -370,3 +370,16 @@ go_component_new_by_mime_type (char const *mime_type)
return g_object_new (type, "mime-type", mime_type, NULL);
}
+
+void go_components_add_filter (GtkFileChooser *chooser)
+{
+ GtkFileFilter* filter;
+ GSList *ptr;
+
+ g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
+
+ filter = gtk_file_filter_new ();
+ for (ptr = mime_types_names; ptr != NULL; ptr = ptr->next)
+ gtk_file_filter_add_mime_type (filter, (char const *) ptr->data);
+ gtk_file_chooser_set_filter (chooser, filter);
+}
diff --git a/goffice/component/go-component-factory.h b/goffice/component/go-component-factory.h
index 475a2ec..9553df7 100644
--- a/goffice/component/go-component-factory.h
+++ b/goffice/component/go-component-factory.h
@@ -47,6 +47,7 @@ gboolean go_components_support_clipboard (char const *mime_type);
void go_components_add_mime_type (char *mime, GOMimePriority priority, char const *service_id);
void go_components_set_mime_suffix (char const *mime, char const *suffix);
char const *go_components_get_mime_suffix (char const *mime);
+void go_components_add_filter (GtkFileChooser *chooser);
void _goc_plugin_services_init (void);
void _goc_plugin_services_shutdown (void);
diff --git a/goffice/component/go-component-mime-dialog.c b/goffice/component/go-component-mime-dialog.c
new file mode 100644
index 0000000..b024f0e
--- /dev/null
+++ b/goffice/component/go-component-mime-dialog.c
@@ -0,0 +1,102 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-component-mime-dialog.c :
+ *
+ * Copyright (C) 2010 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include <goffice/goffice.h>
+#include <goffice/component/goffice-component.h>
+#include <gsf/gsf-impl-utils.h>
+
+struct _GOComponentMimeDialog {
+ GtkDialog base;
+ GtkTreeSelection *sel;
+ GtkTreeModel *list;
+};
+typedef GtkDialogClass GOComponentMimeDialogClass;
+
+static gboolean
+button_press_cb (GtkDialog *dlg, GdkEventButton *ev)
+{
+ if (ev->type == GDK_2BUTTON_PRESS)
+ gtk_dialog_response (dlg, GTK_RESPONSE_OK);
+ return FALSE;
+}
+
+static void
+go_component_mime_dialog_init (GOComponentMimeDialog *dlg)
+{
+ GtkListStore *list = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ GtkWidget *w = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list));
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ GSList *mime_types = go_components_get_mime_types ();
+ GSList *l = mime_types;
+ GtkTreeIter iter;
+ char const *mime_type;
+
+ gtk_dialog_add_buttons (&dlg->base,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
+ dlg->sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (w));
+ g_signal_connect_swapped (w, "button-press-event", G_CALLBACK (button_press_cb), dlg);
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Object type:", renderer, "text", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (w), column);
+ gtk_tree_selection_set_mode (dlg->sel, GTK_SELECTION_BROWSE);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list), 0, GTK_SORT_ASCENDING);
+ while (l) {
+ mime_type = (char const *) l->data;
+ if (go_components_get_priority (mime_type) >= GO_MIME_PRIORITY_PARTIAL) {
+ gtk_list_store_append (list, &iter);
+ gtk_list_store_set (list, &iter,
+ 0, go_mime_type_get_description (mime_type),
+ 1, mime_type,
+ -1);
+ }
+ l = l->next;
+ }
+ dlg->list = GTK_TREE_MODEL (list);
+ gtk_container_addt (GTK_CONTAINER (gtk_dialog_get_content_area (&dlg->base)), w, FALSE, FALSE, 0);
+ gtk_widget_show_all (gtk_dialog_get_content_area (&dlg->base));
+}
+
+GSF_CLASS (GOComponentMimeDialog, go_component_mime_dialog,
+ NULL, go_component_mime_dialog_init,
+ GTK_TYPE_DIALOG)
+
+GtkWidget *
+go_component_mime_dialog_new ()
+{
+ return GTK_WIDGET (g_object_new (GO_TYPE_COMPONENT_MIME_DIALOG, NULL));
+}
+
+char const *
+go_component_mime_dialog_get_mime_type (GOComponentMimeDialog *dlg)
+{
+ GtkTreeIter iter;
+ char const *mime_type = NULL;
+ if (gtk_tree_selection_get_selected (dlg->sel, NULL, &iter))
+ gtk_tree_model_get (dlg->list, &iter, 1, &mime_type, -1);
+ return mime_type;
+}
+
diff --git a/goffice/component/go-component-mime-dialog.h b/goffice/component/go-component-mime-dialog.h
new file mode 100644
index 0000000..dd1a5ca
--- /dev/null
+++ b/goffice/component/go-component-mime-dialog.h
@@ -0,0 +1,41 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-component-mime-dialog.c :
+ *
+ * Copyright (C) 2010 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GO_COMPONENT_MIME_DIALOG_H
+#define GO_COMPONENT_MIME_DIALOG_H
+
+#include <glib-object.h>
+#include <goffice/goffice.h>
+#include <goffice/component/goffice-component.h>
+
+G_BEGIN_DECLS
+
+#define GO_TYPE_COMPONENT_MIME_DIALOG (go_component_mime_dialog_get_type ())
+#define GO_COMPONENT_MIME_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GO_TYPE_COMPONENT_MIME_DIALOG, GOComponentMimeDialog))
+#define GO_IS_COMPONENT_MIME_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GO_TYPE_COMPONENT_MIME_DIALOG))
+
+GType go_component_mime_dialog_get_type (void);
+GtkWidget *go_component_mime_dialog_new (void);
+char const *go_component_mime_dialog_get_mime_type (GOComponentMimeDialog *dlg);
+
+G_END_DECLS
+
+#endif /* GO_COMPONENT_MIME_DIALOG_H */
diff --git a/goffice/component/go-component.c b/goffice/component/go-component.c
index 95a4904..77df27c 100644
--- a/goffice/component/go-component.c
+++ b/goffice/component/go-component.c
@@ -2,7 +2,7 @@
/*
* go-component.c :
*
- * Copyright (C) 2005 Jean Brefort (jean brefort normalesup org)
+ * Copyright (C) 2005-2010 Jean Brefort (jean brefort normalesup org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -22,8 +22,39 @@
#include <goffice/goffice-config.h>
#include <goffice/component/goffice-component.h>
#include <goffice/component/go-component.h>
-
+#include <gsf/gsf-libxml.h>
#include <gsf/gsf-impl-utils.h>
+#include <gsf/gsf-input.h>
+#include <gsf/gsf-output-memory.h>
+#include <gio/gio.h>
+#include <cairo-svg.h>
+#include <librsvg/rsvg.h>
+#include <librsvg/rsvg-cairo.h>
+#include <string.h>
+
+static struct {
+ GOSnapshotType type;
+ char const *name;
+} snapshot_types[GO_SNAPSHOT_MAX] = {
+ { GO_SNAPSHOT_NONE, "none"},
+ { GO_SNAPSHOT_SVG, "svg"},
+ { GO_SNAPSHOT_PNG, "png"}
+};
+
+static GOSnapshotType
+go_snapshot_type_from_string (char const *name)
+{
+ unsigned i;
+ GOSnapshotType ret = GO_SNAPSHOT_NONE;
+
+ for (i = 0; i < GO_SNAPSHOT_MAX; i++) {
+ if (strcmp (snapshot_types[i].name, name) == 0) {
+ ret = snapshot_types[i].type;
+ break;
+ }
+ }
+ return ret;
+}
/**
* GOComponentClass:
@@ -59,6 +90,12 @@ enum {
};
static gulong go_component_signals [LAST_SIGNAL] = { 0, };
+enum {
+ GO_COMPONENT_SNAPSHOT_NONE,
+ GO_COMPONENT_SNAPSHOT_SVG,
+ GO_COMPONENT_SNAPSHOT_PNG,
+};
+
static GObjectClass *component_parent_klass;
static void go_component_set_property (GObject *obj, guint param_id,
@@ -125,6 +162,11 @@ go_component_finalize (GObject *obj)
g_free (component->mime_type);
+ if (component->destroy_notify != NULL) {
+ component->destroy_notify (component->destroy_data);
+ component->destroy_notify = NULL;
+ }
+
(*component_parent_klass->finalize) (obj);
}
@@ -140,7 +182,7 @@ go_component_class_init (GOComponentClass *klass)
g_object_class_install_property (gobject_klass, COMPONENT_PROP_MIME_TYPE,
g_param_spec_string ("mime-type", "mime-type", "mime type of the content of the component",
- NULL, G_PARAM_READWRITE));
+ NULL, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property (gobject_klass, COMPONENT_PROP_WIDTH,
g_param_spec_double ("width", "Width",
"Component width",
@@ -185,6 +227,123 @@ GSF_CLASS_ABSTRACT (GOComponent, go_component,
go_component_class_init, go_component_init,
G_TYPE_OBJECT)
+/******************************************************************************
+ * GOComponentSnapshot: component class used when actual class is not *
+ * available, just displays the snapshot *
+ ******************************************************************************/
+
+typedef struct {
+ GOComponent base;
+ gpointer *image;
+} GOComponentSnapshot;
+typedef GOComponentClass GOComponentSnapshotClass;
+
+GType go_component_snapshot_get_type (void);
+
+static GObjectClass *snapshot_parent_klass;
+
+static void
+go_component_snapshot_render (GOComponent *component, cairo_t *cr,
+ double width, double height)
+{
+ GOComponentSnapshot *snapshot = (GOComponentSnapshot *) component;
+ switch (component->snapshot_type) {
+ case GO_SNAPSHOT_SVG:
+#if defined(GOFFICE_WITH_RSVG)
+ if (snapshot->image == NULL) {
+ GError *err = NULL;
+ snapshot->image = (void *) rsvg_handle_new_from_data (
+ component->snapshot_data,
+ component->snapshot_length,
+ &err);
+ if (err) {
+ g_error_free (err);
+ if (snapshot->image)
+ g_object_unref (snapshot->image);
+ snapshot->image = NULL;
+ }
+ }
+ if (snapshot->image != NULL) {
+ RsvgDimensionData dim;
+ double scalex = 1., scaley = 1.;
+ cairo_save (cr);
+ rsvg_handle_get_dimensions (RSVG_HANDLE (snapshot->image), &dim);
+ cairo_user_to_device_distance (cr, &scalex, &scaley);
+ cairo_scale (cr, width * scalex / dim.width,
+ height * scaley / dim.height);
+ rsvg_handle_render_cairo (RSVG_HANDLE (snapshot->image), cr);
+ cairo_restore (cr);
+ }
+ break;
+#elif defined(GOFFICE_WITH_LASEM)
+ /* TODO: implement a Lasem based svg rendering when possible */
+#endif
+ case GO_SNAPSHOT_PNG: {
+ cairo_pattern_t *pattern;
+ if (snapshot->image == NULL) {
+ GInputStream *in = g_memory_input_stream_new_from_data (
+ component->snapshot_data,
+ component->snapshot_length,
+ NULL);
+ GError *err = NULL;
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_stream (in, NULL, &err);
+ if (err) {
+ g_error_free (err);
+ } else
+ snapshot->image = (void *) go_image_new_from_pixbuf (pixbuf);
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+ }
+ cairo_rectangle (cr, 0, 0, width, height);
+ if (snapshot->image != NULL) {
+ int w, h;
+ double scalex = 1., scaley = 1.;
+ cairo_matrix_t matrix;
+ pattern = go_image_create_cairo_pattern (GO_IMAGE (snapshot->image));
+ g_object_get (snapshot->image, "width", &w, "height", &h, NULL);
+ cairo_user_to_device_distance (cr, &scalex, &scaley);
+ cairo_matrix_init_scale (&matrix,
+ w / width * scalex,
+ h / height * scaley);
+ cairo_pattern_set_matrix (pattern, &matrix);
+ } else
+ pattern = cairo_pattern_create_rgba (1, 1, 1, 1);
+ cairo_set_source (cr, pattern);
+ cairo_pattern_destroy (pattern);
+ cairo_fill (cr);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void
+go_component_shapshot_finalize (GObject *obj)
+{
+ GOComponentSnapshot *snapshot = (GOComponentSnapshot *) obj;
+
+ if (G_IS_OBJECT (snapshot->image))
+ g_object_unref (G_OBJECT (snapshot->image));
+
+ (*snapshot_parent_klass->finalize) (obj);
+}
+
+static void
+go_component_snapshot_class_init (GOComponentClass *klass)
+{
+ snapshot_parent_klass = g_type_class_peek_parent (klass);
+ ((GObjectClass *) klass)->finalize = go_component_shapshot_finalize;
+ klass->render = go_component_snapshot_render;
+}
+
+GSF_CLASS (GOComponentSnapshot, go_component_snapshot,
+ go_component_snapshot_class_init, NULL,
+ GO_TYPE_COMPONENT)
+
+/******************************************************************************/
+
void
go_component_set_default_size (GOComponent *component, double width, double ascent, double descent)
{
@@ -255,13 +414,23 @@ go_component_get_data (GOComponent *component, gpointer *data, int *length,
GDestroyNotify *clearfunc, gpointer *user_data)
{
GOComponentClass *klass;
+ gboolean res = FALSE;
g_return_val_if_fail (GO_IS_COMPONENT (component), FALSE);
- klass = GO_COMPONENT_GET_CLASS(component);
+ if (component->destroy_notify != NULL) {
+ component->destroy_notify (component->destroy_data);
+ component->destroy_notify = NULL;
+ }
+
+ klass = GO_COMPONENT_GET_CLASS (component);
if (klass->get_data)
- return klass->get_data (component, data, length, clearfunc, user_data);
- return FALSE;
+ res = klass->get_data (component, data, length, clearfunc, user_data);
+ if (res) {
+ component->data = (char const *) *data;
+ component->length = *length;
+ }
+ return res;
}
void
@@ -324,6 +493,10 @@ go_component_emit_changed (GOComponent *component)
{
g_return_if_fail (GO_IS_COMPONENT (component));
+ g_free (component->snapshot_data);
+ component->snapshot_data = NULL;
+ component->snapshot_length = 0;
+
g_signal_emit (G_OBJECT (component),
go_component_signals [CHANGED], 0);
}
@@ -345,3 +518,267 @@ go_component_get_command_context (void)
{
return goc_cc;
}
+
+void
+go_component_get_size (GOComponent *component, double *width, double *height)
+{
+ *width = component->width;
+ if (component->height == 0.)
+ component->height = component->ascent >+ component->descent;
+ *height = component->height;
+}
+
+void
+go_component_write_xml_sax (GOComponent *component, GsfXMLOut *output)
+{
+ guint i, nbprops;
+ GType prop_type;
+ GValue value;
+ GParamSpec **specs = g_object_class_list_properties (
+ G_OBJECT_GET_CLASS (component), &nbprops);
+
+ gsf_xml_out_start_element (output, "GOComponent");
+ gsf_xml_out_add_cstr (output, "mime-type", component->mime_type);
+ gsf_xml_out_add_float (output, "width", component->width, 3);
+ gsf_xml_out_add_float (output, "height", component->height, 3);
+ /* save needed component specific properties */
+ for (i = 0; i < nbprops; i++)
+ if (specs[i]->flags & GOC_PARAM_PERSISTENT) {
+ prop_type = G_PARAM_SPEC_VALUE_TYPE (specs[i]);
+ memset (&value, 0, sizeof (value));
+ g_value_init (&value, prop_type);
+ g_object_get_property (G_OBJECT (component), specs[i]->name, &value);
+ if (!g_param_value_defaults (specs[i], &value))
+ gsf_xml_out_add_gvalue (output, specs[i]->name, &value);
+ g_value_unset (&value);
+ }
+ gsf_xml_out_start_element (output, "data");
+ if (component->length == 0)
+ go_component_get_data (component, (void **) &component->data, &component->length,
+ &component->destroy_notify, &component->destroy_data);
+ gsf_xml_out_add_base64 (output, NULL, component->data, component->length);
+ gsf_xml_out_end_element (output);
+ if (component->snapshot_type != GO_SNAPSHOT_NONE && component->snapshot_data == NULL)
+ go_component_build_snapshot (component);
+ if (component->snapshot_data != NULL) {
+ gsf_xml_out_start_element (output, "snapshot");
+ gsf_xml_out_add_cstr (output, "type", component->snapshot_type == GO_SNAPSHOT_SVG? "svg": "png");
+ gsf_xml_out_add_base64 (output, NULL, component->snapshot_data, component->snapshot_length);
+ gsf_xml_out_end_element (output);
+ }
+ gsf_xml_out_end_element (output);
+}
+
+typedef struct {
+ GOComponent *component;
+ unsigned dimension_id;
+
+ GOComponentSaxHandler handler;
+ gpointer user_data;
+} GOCompXMLReadState;
+
+static void
+_go_component_start (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ GOCompXMLReadState *state = (GOCompXMLReadState *) xin->user_state;
+ char const *mime_type = NULL;
+ int i;
+ double width = 1., height = 1.;
+
+ for (i = 0; attrs != NULL && attrs[i] && attrs[i+1] ; i += 2)
+ if (0 == strcmp (attrs[i], "mime-type"))
+ mime_type = (char const *) attrs[i+1];
+ else if (0 == strcmp (attrs[i], "width"))
+ width = go_ascii_strtod ((char const *) attrs[i+1], NULL);
+ else if (0 == strcmp (attrs[i], "height"))
+ height = go_ascii_strtod ((char const *) attrs[i+1], NULL);
+
+ g_return_if_fail (mime_type);
+ state->component = go_component_new_by_mime_type (mime_type);
+ if (!state->component) {
+ state->component = g_object_new (go_component_snapshot_get_type (), NULL);
+ state->component->mime_type = g_strdup (mime_type);
+ state->component->width = width;
+ state->component->height = height;
+ } else for (i = 0; attrs != NULL && attrs[i] && attrs[i+1] ; i += 2) {
+ GParamSpec *prop_spec;
+ GValue res;
+ memset (&res, 0, sizeof (res));
+ prop_spec = g_object_class_find_property (
+ G_OBJECT_GET_CLASS (state->component), attrs[i]);
+ if (prop_spec && (prop_spec->flags & GOC_PARAM_PERSISTENT) &&
+ gsf_xml_gvalue_from_str (&res,
+ G_TYPE_FUNDAMENTAL (G_PARAM_SPEC_VALUE_TYPE (prop_spec)),
+ attrs[i+1])) {
+ g_object_set_property (G_OBJECT (state->component), attrs[i], &res);
+ g_value_unset (&res);
+ }
+ }
+
+}
+
+static void
+_go_component_load_data (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *unknown)
+{
+ GOCompXMLReadState *state = (GOCompXMLReadState *) xin->user_state;
+ GOComponentClass *klass;
+ GOComponent *component = state->component;
+ size_t length;
+
+ g_return_if_fail (component);
+
+ component->data = component->destroy_data = g_base64_decode (xin->content->str, &length);
+ component->destroy_notify = g_free;
+ component->length = length;
+ klass = GO_COMPONENT_GET_CLASS (component);
+ if (klass->set_data)
+ klass->set_data (component);
+}
+
+static void
+_go_component_start_snapshot (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ GOCompXMLReadState *state = (GOCompXMLReadState *) xin->user_state;
+ int i;
+
+ for (i = 0; attrs != NULL && attrs[i] && attrs[i+1] ; i += 2)
+ if (0 == strcmp (attrs[i], "type"))
+ state->component->snapshot_type = go_snapshot_type_from_string ((char const *) attrs[i+1]);
+}
+
+static void
+_go_component_load_snapshot (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *unknown)
+{
+ GOCompXMLReadState *state = (GOCompXMLReadState *) xin->user_state;
+ size_t length;
+ state->component->snapshot_data = g_base64_decode (xin->content->str, &length);
+ state->component->snapshot_length = length;
+}
+
+static void
+_go_component_sax_parser_done (GsfXMLIn *xin, GOCompXMLReadState *state)
+{
+ (*state->handler) (state->component, state->user_data);
+ g_free (state);
+}
+
+void
+go_component_sax_push_parser (GsfXMLIn *xin, xmlChar const **attrs,
+ GOComponentSaxHandler handler, gpointer user_data)
+{
+ static GsfXMLInNode const dtd[] = {
+ GSF_XML_IN_NODE (GO_COMP, GO_COMP, -1, "GOComponent", GSF_XML_NO_CONTENT, &_go_component_start, NULL),
+ GSF_XML_IN_NODE (GO_COMP, GO_COMP_DATA, -1, "data", GSF_XML_CONTENT, NULL, &_go_component_load_data),
+ GSF_XML_IN_NODE (GO_COMP, GO_COMP_SNAPSHOT, -1, "snapshot", GSF_XML_CONTENT, &_go_component_start_snapshot, &_go_component_load_snapshot),
+ GSF_XML_IN_NODE_END
+ };
+ static GsfXMLInDoc *doc = NULL;
+ GOCompXMLReadState *state;
+
+ if (NULL == doc)
+ doc = gsf_xml_in_doc_new (dtd, NULL);
+ state = g_new0 (GOCompXMLReadState, 1);
+ state->handler = handler;
+ state->user_data = user_data;
+ gsf_xml_in_push_state (xin, doc, state,
+ (GsfXMLInExtDtor) _go_component_sax_parser_done, attrs);
+}
+
+struct write_state {
+ size_t length;
+ GsfOutput *output;
+};
+
+static cairo_status_t
+gsf_output_from_cairo (struct write_state *state, unsigned char *data, unsigned int length)
+{
+ if (gsf_output_write (state->output, length, data)) {
+ state->length += length;
+ return CAIRO_STATUS_SUCCESS;
+ } else
+ return CAIRO_STATUS_WRITE_ERROR;
+}
+
+GOSnapshotType
+go_component_build_snapshot (GOComponent *component)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ cairo_status_t status;
+ GOSnapshotType res;
+ struct write_state state;
+
+ g_return_val_if_fail (GO_IS_COMPONENT (component), GO_SNAPSHOT_NONE);
+
+ state.output = gsf_output_memory_new ();
+ state.length = 0;
+
+ switch (component->snapshot_type) {
+ case GO_SNAPSHOT_SVG:
+ surface = cairo_svg_surface_create_for_stream (
+ (cairo_write_func_t) gsf_output_from_cairo,
+ &state,
+ component->width * 72,
+ component->height * 72);
+ cr = cairo_create (surface);
+ go_component_render (component, cr, component->width * 72, component->height * 72);
+ break;
+ case GO_SNAPSHOT_PNG:
+ surface = cairo_image_surface_create (
+ CAIRO_FORMAT_ARGB32,
+ component->width * 300,
+ component->height * 300);
+ cr = cairo_create (surface);
+ go_component_render (component, cr, component->width * 300, component->height * 300);
+ cairo_surface_write_to_png_stream (surface,
+ (cairo_write_func_t) gsf_output_from_cairo,
+ &state);
+ break;
+ default:
+ return GO_SNAPSHOT_NONE;
+ }
+ if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS) {
+ } else
+ res = GO_SNAPSHOT_NONE;
+
+ cairo_surface_destroy (surface);
+ status = cairo_status (cr);
+ cairo_destroy (cr);
+ if (status == CAIRO_STATUS_SUCCESS && state.length > 0) {
+ component->snapshot_length = state.length;
+ component->snapshot_data = g_new (char, state.length);
+ memcpy(component->snapshot_data, gsf_output_memory_get_bytes ((GsfOutputMemory *) state.output), state.length);
+ }
+ g_object_unref (state.output);
+ return res;
+}
+
+GOComponent *
+go_component_new_from_uri (char const *uri)
+{
+ char *mime_type;
+ GsfInput *input;
+ GOComponent *component;
+ GError *err;
+ size_t length;
+ char *data;
+
+ g_return_val_if_fail (uri && *uri, NULL);
+
+ mime_type = go_get_mime_type (uri);
+ if (!mime_type)
+ return NULL;
+ component = go_component_new_by_mime_type (mime_type);
+ g_free (mime_type);
+ input = go_file_open (uri, &err);
+ if (err) {
+ g_error_free (err);
+ return NULL;
+ }
+ length = gsf_input_size (input);
+ data = g_new (guint8, length);
+ gsf_input_read (input, length, data);
+ go_component_set_data (component, data, length);
+ component->destroy_notify = g_free;
+ return component;
+}
diff --git a/goffice/component/go-component.h b/goffice/component/go-component.h
index 255c9bb..6444362 100644
--- a/goffice/component/go-component.h
+++ b/goffice/component/go-component.h
@@ -2,7 +2,7 @@
/*
* go-component.h :
*
- * Copyright (C) 2005 Jean Brefort (jean brefort normalesup org)
+ * Copyright (C) 2005-2010 Jean Brefort (jean brefort normalesup org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -30,6 +30,13 @@ G_BEGIN_DECLS
GO_VAR_DECL double GOCXres, GOCYres;
+typedef enum {
+ GO_SNAPSHOT_NONE,
+ GO_SNAPSHOT_SVG,
+ GO_SNAPSHOT_PNG,
+ GO_SNAPSHOT_MAX
+} GOSnapshotType;
+
struct _GOComponent {
GObject parent;
@@ -39,8 +46,13 @@ struct _GOComponent {
double default_width, default_ascent, default_descent;
gboolean needs_window, resizable, editable;
char const *data;
+ GDestroyNotify destroy_notify;
+ gpointer destroy_data;
int length;
GdkWindow *window;
+ GOSnapshotType snapshot_type;
+ void *snapshot_data;
+ size_t snapshot_length;
};
struct _GOComponentClass {
@@ -71,6 +83,7 @@ typedef struct _GOComponentClass GOComponentClass;
GType go_component_get_type (void);
GOComponent *go_component_new_by_mime_type (char const *mime_type);
+GOComponent *go_component_new_from_uri (char const *uri);
void go_component_set_default_size (GOComponent *component,
double width, double ascent, double descent);
@@ -89,6 +102,14 @@ void go_component_emit_changed (GOComponent *component);
void go_component_set_command_context (GOCmdContext *cc);
GOCmdContext *go_component_get_command_context (void);
void go_component_render (GOComponent *component, cairo_t *cr, double width, double height);
+void go_component_get_size (GOComponent *component, double *width, double *height);
+
+void go_component_write_xml_sax (GOComponent *component, GsfXMLOut *output);
+typedef void (*GOComponentSaxHandler)(GOComponent *component, gpointer user_data);
+void go_component_sax_push_parser (GsfXMLIn *xin, xmlChar const **attrs,
+ GOComponentSaxHandler handler, gpointer user_data);
+
+GOSnapshotType go_component_build_snapshot (GOComponent *component);
G_END_DECLS
diff --git a/goffice/component/goffice-component.h b/goffice/component/goffice-component.h
index a97e83a..2b2cc44 100644
--- a/goffice/component/goffice-component.h
+++ b/goffice/component/goffice-component.h
@@ -28,9 +28,11 @@ G_BEGIN_DECLS
typedef struct _GOComponent GOComponent;
typedef struct _GOComponentType GOComponentType;
+typedef struct _GOComponentMimeDialog GOComponentMimeDialog;
#include <goffice/component/go-component.h>
#include <goffice/component/go-component-factory.h>
+#include <goffice/component/go-component-mime-dialog.h>
G_END_DECLS
#endif /* GOFFICE_COMPONENT_H */
diff --git a/goffice/graph/gog-axis-line.c b/goffice/graph/gog-axis-line.c
index 44e924c..95dc8ff 100644
--- a/goffice/graph/gog-axis-line.c
+++ b/goffice/graph/gog-axis-line.c
@@ -1473,7 +1473,7 @@ axis_circle_render (GogAxisBase *axis_base, GogRenderer *renderer,
if (!first_label_done ||
(!go_geometry_test_OBR_overlap (&txt_obr, &txt_obr_old) &&
!go_geometry_test_OBR_overlap (&txt_obr, &txt_obr_first))) {
- gog_renderer_draw_gostring
+ gog_renderer_draw_gostring
(renderer, ticks[i].str,
&label_pos, GO_ANCHOR_CENTER);
txt_obr_old = txt_obr;
@@ -2063,9 +2063,9 @@ xyz_process (GogAxisBaseAction action, GogView *view, GogViewPadding *padding,
for (i = 0; i < tick_nbr; i++) {
if (ticks[i].str == NULL)
continue;
- gog_renderer_get_text_OBR
+ gog_renderer_get_text_OBR
(view->renderer,
- ticks[i].str->str,
+ ticks[i].str->str,
FALSE, &obr);
if (obr.w > label_w)
label_w = obr.w;
diff --git a/goffice/graph/gog-axis.c b/goffice/graph/gog-axis.c
index 61bbbdd..b9016e7 100644
--- a/goffice/graph/gog-axis.c
+++ b/goffice/graph/gog-axis.c
@@ -178,13 +178,13 @@ axis_format_value (GogAxis *axis, double val, GOString **str)
if (err)
*str = go_string_new ("#####");
else
- *str = go_string_new_rich
+ *str = go_string_new_rich
(g_strdup (pango_layout_get_text (layout)),
-1,
FALSE,
pango_attr_list_ref (pango_layout_get_attributes (layout)),
NULL);
-
+
g_object_unref (layout);
}
diff --git a/goffice/graph/gog-renderer.c b/goffice/graph/gog-renderer.c
index 9637ede..5bd6c41 100644
--- a/goffice/graph/gog-renderer.c
+++ b/goffice/graph/gog-renderer.c
@@ -818,9 +818,9 @@ gog_renderer_draw_gostring (GogRenderer *rend, GOString *str,
pango_layout_set_font_description (layout, style->font.font->desc);
pango_layout_get_size (layout, &iw, &ih);
- obr.w = rend->scale * ((double) iw + (double) PANGO_SCALE / 2.0)
+ obr.w = rend->scale * ((double) iw + (double) PANGO_SCALE / 2.0)
/ (double) PANGO_SCALE;
- obr.h = rend->scale * ((double) ih + (double) PANGO_SCALE / 2.0)
+ obr.h = rend->scale * ((double) ih + (double) PANGO_SCALE / 2.0)
/(double) PANGO_SCALE;
obr.alpha = -style->text_layout.angle * M_PI / 180.0;
obr.x = pos->x;
@@ -849,9 +849,9 @@ gog_renderer_draw_gostring (GogRenderer *rend, GOString *str,
cairo_save (cairo);
cairo_set_source_rgba (cairo, GO_COLOR_TO_CAIRO (style->font.color));
- cairo_move_to (cairo, obr.x - (obr.w / 2.0) * cos (obr.alpha) +
+ cairo_move_to (cairo, obr.x - (obr.w / 2.0) * cos (obr.alpha) +
(obr.h / 2.0) * sin (obr.alpha),
- obr.y - (obr.w / 2.0) * sin (obr.alpha) -
+ obr.y - (obr.w / 2.0) * sin (obr.alpha) -
(obr.h / 2.0) * cos (obr.alpha));
cairo_rotate (cairo, obr.alpha);
cairo_scale (cairo, rend->scale, rend->scale);
@@ -941,9 +941,9 @@ gog_renderer_get_gostring_OBR (GogRenderer *rend, GOString *str, GOGeometryOBR *
pango_layout_get_extents (layout, NULL, &logical);
g_object_unref (layout);
- obr->w = rend->scale * ((double) logical.width + (double) PANGO_SCALE / 2.0)
+ obr->w = rend->scale * ((double) logical.width + (double) PANGO_SCALE / 2.0)
/ (double) PANGO_SCALE;
- obr->h = rend->scale * ((double) logical.height + (double) PANGO_SCALE / 2.0)
+ obr->h = rend->scale * ((double) logical.height + (double) PANGO_SCALE / 2.0)
/(double) PANGO_SCALE;
/* Make sure invisible things don't skew size */
diff --git a/goffice/graph/gog-renderer.h b/goffice/graph/gog-renderer.h
index 203be4b..12414df 100644
--- a/goffice/graph/gog-renderer.h
+++ b/goffice/graph/gog-renderer.h
@@ -86,13 +86,13 @@ void gog_renderer_draw_selection_rectangle (GogRenderer *renderer, GogViewAlloc
void gog_renderer_draw_marker (GogRenderer *rend, double x, double y);
void gog_renderer_draw_text (GogRenderer *rend, char const *text,
- GogViewAllocation const *pos,
+ GogViewAllocation const *pos,
GOAnchorType anchor,
gboolean use_markup);
void gog_renderer_draw_gostring (GogRenderer *rend,
GOString *str,
- GogViewAllocation const *pos,
+ GogViewAllocation const *pos,
GOAnchorType anchor);
void gog_renderer_get_gostring_OBR (GogRenderer *rend, GOString *str,
diff --git a/goffice/graph/gog-series-labels.c b/goffice/graph/gog-series-labels.c
index 935d9ec..b027566 100644
--- a/goffice/graph/gog-series-labels.c
+++ b/goffice/graph/gog-series-labels.c
@@ -40,7 +40,7 @@ enum {
struct {
char const *label;
GogSeriesLabelsPos pos;
-} positions [] =
+} positions [] =
{
{ N_("Centered"), GOG_SERIES_LABELS_CENTERED },
{ N_("Top"), GOG_SERIES_LABELS_TOP },
@@ -566,7 +566,7 @@ gog_series_labels_parent_changed (GogObject *obj, gboolean was_set)
break;
}
}
-
+
}
static void
@@ -578,7 +578,7 @@ gog_series_labels_finalize (GObject *obj)
series_labels_parent_klass->finalize (obj);
}
-static void
+static void
gog_series_labels_class_init (GObjectClass *obj_klass)
{
GogObjectClass *gog_klass = (GogObjectClass *) obj_klass;
diff --git a/goffice/gtk/go-format-sel.c b/goffice/gtk/go-format-sel.c
index 78fad7c..6e75fbf 100644
--- a/goffice/gtk/go-format-sel.c
+++ b/goffice/gtk/go-format-sel.c
@@ -199,13 +199,13 @@ draw_format_preview (GOFormatSel *gfs, gboolean regen_format)
len = g_utf8_strlen (preview, -1);
if (len > FORMAT_PREVIEW_MAX)
- strcpy (g_utf8_offset_to_pointer (preview,
+ strcpy (g_utf8_offset_to_pointer (preview,
FORMAT_PREVIEW_MAX - 5),
"...");
gtk_text_buffer_set_text (gfs->format.preview_buffer, preview, -1);
- go_load_pango_attributes_into_buffer (attrs,
+ go_load_pango_attributes_into_buffer (attrs,
gfs->format.preview_buffer,
preview);
diff --git a/goffice/utils/go-format.c b/goffice/utils/go-format.c
index c1d94cb..b3be4d0 100644
--- a/goffice/utils/go-format.c
+++ b/goffice/utils/go-format.c
@@ -3076,13 +3076,13 @@ SUFFIX(go_format_execute) (PangoLayout *layout, GString *dst,
case OP_MARKUP_SUPERSCRIPT_START:
if (layout)
- markup_stack = g_slist_prepend
+ markup_stack = g_slist_prepend
(markup_stack, GSIZE_TO_POINTER (dst->len));
break;
- case OP_MARKUP_SUPERSCRIPT_END:
+ case OP_MARKUP_SUPERSCRIPT_END:
if (layout) {
- guint start = 0,
+ guint start = 0,
end = (guint)dst->len;
PangoAttribute *attr;
if (markup_stack) {
@@ -3168,12 +3168,12 @@ SUFFIX(go_format_execute) (PangoLayout *layout, GString *dst,
gsize denom_chars = g_utf8_strlen (dst->str + fraction.denominator_start, -1);
gsize nom_chars = total_chars - denom_chars - 1;
int diff = denom_chars - nom_chars;
-
+
if (fraction.n == 0) {
/* Replace all added characters by spaces of the right length. */
char const *f = dst->str + fraction.nominator_start;
gsize chars = g_utf8_strlen (f, -1);
-
+
if (chars > 0) {
/* We have layouts that have no fontmap set, we need to avoid them */
if (layout && pango_context_get_font_map (pango_layout_get_context (layout))) {
@@ -3209,12 +3209,12 @@ SUFFIX(go_format_execute) (PangoLayout *layout, GString *dst,
chars++;
}
go_list_free_custom (plist, (GFreeFunc) pango_item_free);
- }
-
+ }
+
memset (dst->str + fraction.nominator_start, ' ', chars);
g_string_truncate (dst, fraction.nominator_start + chars);
}
- }
+ }
if (layout && pango_context_get_font_map (pango_layout_get_context (layout))) {
if (diff > 0) {
@@ -3239,20 +3239,20 @@ SUFFIX(go_format_execute) (PangoLayout *layout, GString *dst,
PangoAttribute *attr;
PangoRectangle ink_rect;
PangoRectangle logical_rect;
-
+
pango_shape (zero_str->str, diff, &pi->analysis, glyphs);
pango_glyph_string_extents (glyphs,
pi->analysis.font,
&ink_rect,
&logical_rect);
pango_glyph_string_free (glyphs);
-
+
attr = pango_attr_shape_new (&ink_rect, &logical_rect);
attr->start_index = start;
attr->end_index = start + 1;
g_string_insert_c (dst, start, ' ');
pango_attr_list_insert (attrs, attr);
-
+
start++;
}
go_list_free_custom (plist, (GFreeFunc) pango_item_free);
@@ -3663,7 +3663,7 @@ SUFFIX(go_format_value_gstring) (PangoLayout *layout, GString *str,
unicode_minus);
FREE_NEW_STR;
return err;
-
+
case GO_FMT_EMPTY:
SETUP_LAYOUT;
FREE_NEW_STR;
diff --git a/goffice/utils/go-pango-extras.h b/goffice/utils/go-pango-extras.h
index 33c7339..97f7573 100644
--- a/goffice/utils/go-pango-extras.h
+++ b/goffice/utils/go-pango-extras.h
@@ -13,8 +13,8 @@ void go_pango_attr_list_unset (PangoAttrList *list,
PangoAttrType type);
gboolean go_pango_attr_list_is_empty (const PangoAttrList *attrs);
-void go_load_pango_attributes_into_buffer (PangoAttrList *markup,
- GtkTextBuffer *buffer,
+void go_load_pango_attributes_into_buffer (PangoAttrList *markup,
+ GtkTextBuffer *buffer,
gchar const *str);
void go_create_std_tags_for_buffer (GtkTextBuffer *buffer);
diff --git a/plugins/plot_barcol/gog-barcol.c b/plugins/plot_barcol/gog-barcol.c
index a940a01..684cd6d 100644
--- a/plugins/plot_barcol/gog-barcol.c
+++ b/plugins/plot_barcol/gog-barcol.c
@@ -867,7 +867,7 @@ gog_barcol_view_render (GogView *view, GogViewAllocation const *bbox)
}
gog_renderer_pop_style (view->renderer);
}
-
+
gog_chart_map_free (chart_map);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]