Index: goffice/gtk/go-graph-widget.c =================================================================== RCS file: /cvs/gnome/goffice/goffice/gtk/go-graph-widget.c,v retrieving revision 1.4 diff -u -p -r1.4 go-graph-widget.c --- goffice/gtk/go-graph-widget.c 18 Nov 2005 15:50:56 -0000 1.4 +++ goffice/gtk/go-graph-widget.c 10 Dec 2005 13:52:55 -0000 @@ -20,7 +20,8 @@ #include #include "go-graph-widget.h" -#include +#include +#include #include #include #include @@ -30,42 +31,90 @@ enum { GRAPH_WIDGET_PROP_0, GRAPH_WIDGET_PROP_ASPECT_RATIO, + GRAPH_WIDGET_PROP_REFERENCE_DIRECTION, + GRAPH_WIDGET_PROP_ZOOM_FACTOR, + GRAPH_WIDGET_PROP_GRAPH }; -struct _GOGraphWidget{ - GtkDrawingArea base; +struct _GOGraphWidget { + GtkLayout base; GogRenderer *renderer; GogGraph *graph; - GogChart *chart; /* first chart created on init */ - double aspect_ratio, width, height, xoffset, yoffset; + + double aspect_ratio, zoom_factor; + int width, height, xoffset, yoffset; + GOGraphWidgetReferenceDirection reference_direction; /* Idle handler ID */ guint idle_id; }; -typedef GtkDrawingAreaClass GOGraphWidgetClass; +typedef struct _GOGraphWidgetClass GOGraphWidgetClass; + +struct _GOGraphWidgetClass { + GtkLayoutClass parent_class; +}; static GtkWidgetClass *graph_parent_klass; +static void go_graph_widget_request_update (GOGraphWidget *w); + +GType +go_graph_widget_reference_direction_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GEnumValue values [] = { + { GO_GRAPH_WIDGET_REFERENCE_DIRECTION_NONE, + (char *) "GO_GRAPH_WIDGET_REFERENCE_DIRECTION_NONE", + (char *) "none" }, + { GO_GRAPH_WIDGET_REFERENCE_DIRECTION_HORIZONTAL, + (char *) "GO_GRAPH_WIDGET_REFERENCE_DIRECTION_HORIZONTAL", + (char *) "horizontal" }, + { GO_GRAPH_WIDGET_REFERENCE_DIRECTION_VERTICAL, + (char *) "GO_GRAPH_WIDGET_REFERENCE_DIRECTION_VERTICAL", + (char *) "vertical" }, + { 0, NULL, NULL } + }; + + type = g_enum_register_static ("GOGraphWidgetReferenceDirection", values); + } + + return type; +} + /* Size allocation handler for the widget */ static void go_graph_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GOGraphWidget *w = GO_GRAPH_WIDGET (widget); + w->width = allocation->width; w->height = allocation->height; + if (w->aspect_ratio > 0.) { - if (w->height > w->width * w->aspect_ratio) { - w->yoffset = (w->height - w->width * w->aspect_ratio) / 2.; + if (w->reference_direction == GO_GRAPH_WIDGET_REFERENCE_DIRECTION_HORIZONTAL || + (w->reference_direction == GO_GRAPH_WIDGET_REFERENCE_DIRECTION_NONE && + (w->zoom_factor > 1.0 ? + w->height < w->width * w->aspect_ratio : + w->height > w->width * w->aspect_ratio))) { + w->yoffset = MAX (0, w->height - w->width * w->aspect_ratio) / 2.; w->height = w->width * w->aspect_ratio; w->xoffset = 0; } else { - w->xoffset = (w->width - w->height / w->aspect_ratio) / 2.; + w->xoffset = MAX (0, w->width - w->height / w->aspect_ratio) / 2.; w->width = w->height / w->aspect_ratio; w->yoffset = 0; } } + + w->height *= w->zoom_factor; + w->width *= w->zoom_factor; + + gtk_layout_set_size (GTK_LAYOUT (w), w->width - w->xoffset, w->height - w->yoffset); + gog_renderer_update (w->renderer, w->width, w->height, 1.0); graph_parent_klass->size_allocate (widget, allocation); } @@ -89,7 +138,7 @@ go_graph_widget_expose_event (GtkWidget gdk_region_intersect (draw_region, event->region); if (!gdk_region_empty (draw_region)) { gdk_region_get_clipbox (draw_region, &draw_rect); - gdk_draw_pixbuf (widget->window, NULL, pixbuf, + gdk_draw_pixbuf (GTK_LAYOUT (widget)->bin_window, NULL, pixbuf, /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */ draw_rect.x - display_rect.x, draw_rect.y - display_rect.y, @@ -123,7 +172,20 @@ go_graph_widget_set_property (GObject *o w->aspect_ratio = g_value_get_double (value); w->xoffset = w->yoffset = 0.; break; + case GRAPH_WIDGET_PROP_REFERENCE_DIRECTION : + w->reference_direction = g_value_get_enum (value); + w->xoffset = w->yoffset = 0.; + break; + case GRAPH_WIDGET_PROP_ZOOM_FACTOR : + w->zoom_factor = g_value_get_double (value); + break; + case GRAPH_WIDGET_PROP_GRAPH : + if (w->graph != NULL) + g_object_unref (w->graph); + w->graph = GOG_GRAPH (g_object_ref (g_value_get_object (value))); + g_object_set (w->renderer, "model", w->graph, NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec); return; /* NOTE : RETURN */ } @@ -140,6 +202,15 @@ go_graph_widget_get_property (GObject *o case GRAPH_WIDGET_PROP_ASPECT_RATIO : g_value_set_double (value, w->aspect_ratio); break; + case GRAPH_WIDGET_PROP_REFERENCE_DIRECTION : + g_value_set_enum (value, w->reference_direction); + break; + case GRAPH_WIDGET_PROP_ZOOM_FACTOR : + g_value_set_double (value, w->zoom_factor); + break; + case GRAPH_WIDGET_PROP_GRAPH : + g_value_set_object (value, w->graph); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec); break; @@ -163,7 +234,26 @@ go_graph_widget_class_init (GOGraphWidge GRAPH_WIDGET_PROP_ASPECT_RATIO, g_param_spec_double ("aspect-ratio", "aspect-ratio", "Aspect ratio for rendering the graph, used only if greater than 0.", - -G_MAXDOUBLE, G_MAXDOUBLE, -1., G_PARAM_READWRITE)); + -G_MAXDOUBLE, G_MAXDOUBLE, 1., G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, + GRAPH_WIDGET_PROP_REFERENCE_DIRECTION, + g_param_spec_enum ("reference-direction", "reference-direction", + "The direction that should be used as base direction for the aspect ratio. " + "The choice of this direction influences the size allocation behavior of the widget.", + go_graph_widget_reference_direction_get_type (), + GO_GRAPH_WIDGET_REFERENCE_DIRECTION_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, + GRAPH_WIDGET_PROP_ZOOM_FACTOR, + g_param_spec_double ("zoom-factor", "zoom-factor", + "This factor determines how big the widget will actually be compared to its allocation size.", + 0.0, G_MAXDOUBLE, 1.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, + GRAPH_WIDGET_PROP_GRAPH, + g_param_spec_object ("graph", "graph", + "The graph to render.", + gog_graph_get_type (), + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); } static gint @@ -197,28 +287,44 @@ go_graph_widget_init (GOGraphWidget *w) w->renderer = gog_renderer_new_for_pixbuf (w->graph); g_signal_connect_swapped (w->renderer, "request_update", G_CALLBACK (go_graph_widget_request_update), w); - /* by default, create one chart and add it to the graph */ - w->chart = (GogChart *) - gog_object_add_by_name (GOG_OBJECT (w->graph), "Chart", NULL); + w->idle_id = 0; } /** * go_graph_widget_new : * - * Creates a new #GOGraphWidget with an embedded #GogGraph. Also add a #GogChart inside - * graph. + * Creates a new #GOGraphWidget, which embeds the specified #GogGraph, + * or NULL to make #GOGraphWidget create its own graph, which will + * have an associated chart. * Returns the newly created #GOGraphWidget. **/ GtkWidget * -go_graph_widget_new (void) +go_graph_widget_new (GogGraph *graph) { - return GTK_WIDGET (g_object_new (GO_GRAPH_WIDGET_TYPE, NULL)); + GtkWidget *ret; + gboolean self_owned_graph; + + g_return_val_if_fail (graph == NULL || IS_GOG_GRAPH (graph), NULL); + + self_owned_graph = (graph == NULL); + + if (self_owned_graph) { + graph = g_object_new (GOG_GRAPH_TYPE, NULL); + gog_object_add_by_name (GOG_OBJECT (graph), "Chart", NULL); + } + + ret = GTK_WIDGET (g_object_new (GO_GRAPH_WIDGET_TYPE, "graph", graph, NULL)); + + if (self_owned_graph) + g_object_unref (graph); + + return ret; } GSF_CLASS (GOGraphWidget, go_graph_widget, go_graph_widget_class_init, go_graph_widget_init, - gtk_drawing_area_get_type ()) + gtk_layout_get_type ()) /** * go_graph_widget_get_graph : @@ -234,14 +340,35 @@ go_graph_widget_get_graph (GOGraphWidget } /** + * go_graph_widget_set_graph : + * @widget : #GOGraphWidget + * @graph: #GogGraph + * + * Sets the #GogGraph embedded in the widget. May not be NULL. + * The reference count of the @graph is increased by 1. + **/ +void +go_graph_widget_set_graph (GOGraphWidget *widget, + GogGraph *graph) +{ + g_return_if_fail (IS_GO_GRAPH_WIDGET (widget)); + g_return_if_fail (IS_GOG_GRAPH (graph)); + + g_object_set (widget, "graph", graph, NULL); +} + +/** * go_graph_widget_get_chart : * @widget : #GOGraphWidget * - * Returns the #GogChart created by go_graph_widget_new(). + * Returns the #GogChart of the embedded #GogGraph. + * The reference count of the returned chart is + * increased by 1, if it exists. **/ GogChart * go_graph_widget_get_chart (GOGraphWidget *widget) { g_return_val_if_fail (IS_GO_GRAPH_WIDGET (widget), NULL); - return widget->chart; + + return GOG_CHART (gog_object_get_child_by_name (GOG_OBJECT (widget->graph), "Chart")); } Index: goffice/gtk/go-graph-widget.h =================================================================== RCS file: /cvs/gnome/goffice/goffice/gtk/go-graph-widget.h,v retrieving revision 1.2 diff -u -p -r1.2 go-graph-widget.h --- goffice/gtk/go-graph-widget.h 8 Aug 2005 08:57:00 -0000 1.2 +++ goffice/gtk/go-graph-widget.h 10 Dec 2005 13:52:55 -0000 @@ -32,12 +32,22 @@ G_BEGIN_DECLS #define GO_GRAPH_WIDGET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GO_GRAPH_WIDGET_TYPE, GOGraphWidget)) #define IS_GO_GRAPH_WIDGET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GO_GRAPH_WIDGET_TYPE)) -typedef struct _GOGraphWidget GOGraphWidget; +typedef struct _GOGraphWidget GOGraphWidget; + +typedef enum { + GO_GRAPH_WIDGET_REFERENCE_DIRECTION_NONE, + GO_GRAPH_WIDGET_REFERENCE_DIRECTION_HORIZONTAL, + GO_GRAPH_WIDGET_REFERENCE_DIRECTION_VERTICAL +} GOGraphWidgetReferenceDirection; + +GType go_graph_widget_reference_direction_get_type (void); GType go_graph_widget_get_type (void); -GtkWidget *go_graph_widget_new (void); +GtkWidget *go_graph_widget_new (GogGraph *graph); GogGraph *go_graph_widget_get_graph (GOGraphWidget *widget); +void go_graph_widget_set_graph (GOGraphWidget *widget, + GogGraph *graph); GogChart *go_graph_widget_get_chart (GOGraphWidget *widget); G_END_DECLS Index: tests/pie-demo.c =================================================================== RCS file: /cvs/gnome/goffice/tests/pie-demo.c,v retrieving revision 1.7 diff -u -p -r1.7 pie-demo.c --- tests/pie-demo.c 8 Aug 2005 08:57:07 -0000 1.7 +++ tests/pie-demo.c 10 Dec 2005 13:52:55 -0000 @@ -75,7 +75,7 @@ main (int argc, char *argv[]) gtk_box_pack_end (GTK_BOX (box), w, FALSE, FALSE, 2); /* Create a graph widget and add it to the GtkVBox */ - w = go_graph_widget_new (); + w = go_graph_widget_new (NULL); gtk_box_pack_end (GTK_BOX (box), w, TRUE, TRUE, 0); /* Get the embedded graph */ graph = go_graph_widget_get_graph (GO_GRAPH_WIDGET (w));