static double goc_polyline_distance (GocItem *item, double x, double y, GocItem **near_item) { GocPolyline *polyline = GOC_POLYLINE (item); GOStyle *style = go_style_dup (go_styled_object_get_style (GO_STYLED_OBJECT (item))); double tmp_width = 0; double res = 20; double ppu = goc_canvas_get_pixels_per_unit (item->canvas); cairo_surface_t *surface; cairo_t *cr; if (polyline->nb_points == 0) return res; *near_item = item; tmp_width = style->line.width; if (style->line.width * ppu < 5) style->line.width = 5. / (ppu * ppu); else style->line.width /= ppu; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); cr = cairo_create (surface); if (goc_polyline_prepare_draw (item, cr, 0)) { if (cairo_in_stroke (cr, x, y)) res = 0; } g_object_unref (style); cairo_destroy (cr); cairo_surface_destroy (surface); style->line.width = tmp_width; return res; }
static void goc_line_update_bounds (GocItem *item) { GocLine *line = GOC_LINE (item); GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item)); double extra_width = style->line.width /2.; /* FIXME: take transform into account */ if (extra_width <= 0.) extra_width = .5; if (style->line.cap == CAIRO_LINE_CAP_SQUARE) extra_width *= 1.5; /* 1.4142 should be enough */ if (line->startx < line->endx) { item->x0 = line->startx - extra_width; item->x1 = line->endx + extra_width; } else { item->x0 = line->endx - extra_width; item->x1 = line->startx + extra_width; } if (line->starty < line->endy) { item->y0 = line->starty - extra_width; item->y1 = line->endy + extra_width; } else { item->y0 = line->endy - extra_width; item->y1 = line->starty + extra_width; } handle_arrow_bounds (&line->start_arrow, item); handle_arrow_bounds (&line->end_arrow, item); }
static void goc_line_draw (GocItem const *item, cairo_t *cr) { GocLine *line = GOC_LINE (item); GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item)); double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1: 1; double endx = (line->endx - line->startx) * sign, endy = line->endy - line->starty; double hoffs, voffs = ceil (style->line.width); double startx = 0, starty = 0; double phi; if (line->startx == line->endx && line->starty == line->endy) return; if (voffs <= 0.) voffs = 1.; hoffs = ((int) voffs & 1)? .5: 0.; voffs = (line->starty == line->endy)? hoffs: 0.; if (line->startx != line->endx) hoffs = 0.; cairo_save (cr); _goc_item_transform (item, cr, TRUE); goc_group_cairo_transform (item->parent, cr, hoffs + floor (line->startx), voffs + floor (line->starty)); endx = (endx > 0.)? ceil (endx): floor (endx); endy = (endy > 0.)? ceil (endy): floor (endy); phi = atan2 (endy, endx); draw_arrow (&line->start_arrow, cr, style, &startx, &starty, phi + M_PI); draw_arrow (&line->end_arrow, cr, style, &endx, &endy, phi); if ((endx != 0. || endy!= 0.) && go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr)) { /* try to avoid horizontal and vertical lines between two pixels */ cairo_move_to (cr, startx, starty); cairo_line_to (cr, endx, endy); cairo_stroke (cr); } cairo_restore (cr); }
/** * go_styled_object_fill : * @so: #GOStyledObject * @cr: #cairo_t * @preserve: whether the current path should be preserved * * fills the current path according to the * item style and canvas scale. * **/ void go_styled_object_fill (GOStyledObject const *so, cairo_t *cr, gboolean preserve) { GOStyle const *style; g_return_if_fail (GO_IS_STYLED_OBJECT (so)); style = go_styled_object_get_style (GO_STYLED_OBJECT (so)); go_style_fill (style, cr, preserve); }
/** * go_styled_object_set_cairo_line : * @so: #GOStyledObject * @cr: #cairo_t * * Prepares the cairo context @cr to draw a line according to the * item style and canvas scale. * * Returns: %TRUE if the line is not invisible **/ gboolean go_styled_object_set_cairo_line (GOStyledObject const *so, cairo_t *cr) { GOStyle const *style; g_return_val_if_fail (GO_IS_STYLED_OBJECT (so), FALSE); style = go_styled_object_get_style (GO_STYLED_OBJECT (so)); return go_style_set_cairo_line (style, cr); }
static void graph_setup_title (GogGraph *graph, const gchar *title) { GogLabel *label; GOData *data; GOStyle *style; PangoFontDescription *desc; label = g_object_new(GOG_TYPE_LABEL, NULL); data = go_data_scalar_str_new(title, FALSE); gog_dataset_set_dim(GOG_DATASET(label), 0, data, NULL); gog_object_add_by_name(GOG_OBJECT(graph), "Title", GOG_OBJECT(label)); style = go_styled_object_get_style(GO_STYLED_OBJECT(label)); desc = pango_font_description_from_string("Sans bold 16"); go_style_set_font_desc(style, desc); }
static GogPlot * setup_page (GtkNotebook *notebook, const gchar *service_id) { GtkWidget *child, *w; GogChart *chart; GogGraph *graph; GogLabel *label; GogPlot *plot; GOData *data; GOStyle *style; PangoFontDescription *desc; child = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_notebook_append_page (notebook, child, gtk_label_new (service_id)); /* Create a graph widget and add it to the GtkVBox */ w = go_graph_widget_new (NULL); gtk_box_pack_end (GTK_BOX (child), w, TRUE, TRUE, 0); /* Get the embedded graph */ graph = go_graph_widget_get_graph (GO_GRAPH_WIDGET (w)); /* Add a title */ label = (GogLabel *) g_object_new (GOG_TYPE_LABEL, NULL); data = go_data_scalar_str_new (service_id, FALSE); gog_dataset_set_dim (GOG_DATASET (label), 0, data, NULL); gog_object_add_by_name (GOG_OBJECT (graph), "Title", GOG_OBJECT (label)); /* Change the title font */ style = go_styled_object_get_style (GO_STYLED_OBJECT (label)); desc = pango_font_description_from_string ("Sans bold 16"); go_style_set_font_desc (style, desc); /* Get the chart created by the widget initialization */ chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (w)); /* Create a plot and add it to the chart */ plot = (GogPlot *) gog_plot_new_by_name (service_id); gog_object_add_by_name (GOG_OBJECT (chart), "Plot", GOG_OBJECT (plot)); /* Add a legend to the chart */ gog_object_add_by_name (GOG_OBJECT (chart), "Legend", NULL); return plot; }
static double goc_line_distance (GocItem *item, double x, double y, GocItem **near_item) { GocLine *line = GOC_LINE (item); double dx, dy, l, t; GOStyle *style; dx = line->endx - line->startx; dy = line->endy - line->starty; l = hypot (dx, dy); x -= line->startx; y -= line->starty; t = (x * dx + y * dy) / l; y = (-x * dy + y * dx) / l; *near_item = item; if (t < 0.) return hypot (t, y); /* that might be not fully exact, but we don't need a large precision */ if (t > l) return hypot (t - l, y); style = go_styled_object_get_style (GO_STYLED_OBJECT (item)); t = fabs (y) - ((style->line.width > 5)? style->line.width/ 2.: 2.5); /* FIXME: do we need to take the arrow end into account? */ return (t > 0.)? t: 0.; }
static void gog_pie_view_render (GogView *view, GogViewAllocation const *bbox) { GogPiePlot const *model = GOG_PIE_PLOT (view->model); GogPieSeries const *series = NULL; double separated_cx, separated_cy, cx, cy, r, theta, len, *vals, scale; double default_sep; unsigned elem, k; GOPath *path; GogTheme *theme = gog_object_get_theme (GOG_OBJECT (model)); GOStyle *style, *white_style = NULL, *elt_style = NULL; GSList *ptr; unsigned num_series = 0; unsigned index; double center_radius; double center_size = 0.0; double r_ext, r_int, r_tot; double outline_width_max; gboolean has_hole; double separation_max, separation; GogPieSeriesElement *gpse; GList const *overrides; GogShowNegsMode mode = model->show_negatives; gboolean negative; /* compute number of valid series */ for (ptr = model->base.series ; ptr != NULL ; ptr = ptr->next) { series = ptr->data; if (!gog_series_is_valid (GOG_SERIES (ptr->data))) continue; num_series++; } if (num_series <= 0) return; separation_max = .0; outline_width_max = .0; if ((style = go_styled_object_get_style (GO_STYLED_OBJECT (series)))) outline_width_max = gog_renderer_line_size (view->renderer, style->line.width); if (mode == GOG_SHOW_NEGS_WHITE) { white_style = go_style_dup (style); white_style->fill.type = GO_STYLE_FILL_PATTERN; go_pattern_set_solid (&white_style->fill.pattern, GO_COLOR_WHITE); } for (overrides = gog_series_get_overrides (GOG_SERIES (series)); overrides != NULL; overrides = overrides->next) { separation = GOG_PIE_SERIES_ELEMENT (overrides->data)->separation; if (separation_max < separation) separation_max = separation; style = go_styled_object_get_style (GO_STYLED_OBJECT (overrides->data)); if (outline_width_max < style->line.width) outline_width_max = style->line.width; } if (separation_max < -model->default_separation) separation_max = -model->default_separation; if (GOG_IS_RING_PLOT (model)) center_size = GOG_RING_PLOT(model)->center_size; else if (num_series > 1) num_series = 1; /* calculate things when span < 100. */ if (model->span < 100.) { double xmin, xmax, ymin, ymax, ratio; double begin, cur, end; if (num_series == 1) { begin = (model->initial_angle + series->initial_angle) * M_PI / 180. - M_PI / 2.; end = begin + model->span * M_PI / 50.; } else { /* WARNING: this code has not been checked */ ptr = model->base.series; while (!gog_series_is_valid (GOG_SERIES (ptr->data))) ptr = ptr->next; series = ptr->data; begin = end = series->initial_angle; for (ptr = ptr->next; ptr != NULL; ptr = ptr->next) { if (!gog_series_is_valid (GOG_SERIES (ptr->data))) continue; series = ptr->data; cur = series->initial_angle; if (cur < begin) begin = cur; if (cur > end) end = cur; } begin = (model->initial_angle + begin) * M_PI / 180. - M_PI / 2.; end = ((model->initial_angle + end) / 180. + model->span / 50.) * M_PI - M_PI / 2.; } cur = ceil (begin / M_PI * 2 - 1e-10) * M_PI / 2; xmin = xmax = cos (begin); ymin = ymax = sin (begin); while (cur < end) { cx = cos (cur); cy = sin (cur); if (cx > xmax) xmax = cx; if (cx < xmin) xmin = cx; if (cy > ymax) ymax = cy; if (cy < ymin) ymin = cy; cur += M_PI / 2; } cx = cos (end); cy = sin (end); if (cx > xmax) xmax = cx; if (cx < xmin) xmin = cx; if (cy > ymax) ymax = cy; if (cy < ymin) ymin = cy; /* we ensure that the center will be visible */ if (xmin > 0.) xmin = 0.; if (xmax < 0.) xmax = 0.; if (ymin > 0.) ymin = 0.; if (ymax < 0.) ymax = 0.; ratio = (ymax - ymin) / (xmax - xmin); if (view->allocation.h > view->allocation.w * ratio) { r_tot = view->allocation.w * MAX (xmax, -xmin) / (xmax - xmin); cx = view->allocation.x - view->allocation.w * xmin / (xmax - xmin); cy = view->allocation.y + (view->allocation.h + view->allocation.w * ratio) / 2. - view->allocation.w * ratio * ymax / (ymax - ymin); } else { r_tot = view->allocation.h * MAX (ymax, -ymin) / (ymax - ymin); cx = view->allocation.x + (view->allocation.w - view->allocation.h / ratio) / 2. - view->allocation.h / ratio * xmin / (xmax - xmin); cy = view->allocation.y - view->allocation.h * ymin / (ymax - ymin); } r_tot /= 1. + model->default_separation + separation_max; } else { /* centre things */ cx = view->allocation.x + view->allocation.w/2.; cy = view->allocation.y + view->allocation.h/2.; r_tot = view->allocation.h; if (r_tot > view->allocation.w) r_tot = view->allocation.w; r_tot /= 2. * (1. + model->default_separation + separation_max); } path = go_path_new (); default_sep = r_tot * model->default_separation; center_radius = r_tot * center_size; r = r_tot * (1. - center_size); elem = model->base.index_num; index = 1; for (ptr = model->base.series ; ptr != NULL ; ptr = ptr->next) { series = ptr->data; if (!gog_series_is_valid (GOG_SERIES (series))) continue; if (index > num_series) /* people snuck extra series into a pie */ break; if (num_series == index) r -= outline_width_max / 2.0; has_hole = center_radius > 0. || index > 1; r_int = center_radius + r * ((double)index - 1.0) / (double)num_series; r_ext = center_radius + r * (double)index / (double)num_series; theta = (model->initial_angle + series->initial_angle) * M_PI / 180. - M_PI / 2.; scale = 2 * M_PI / 100 * model->span / series->total; vals = go_data_get_values (series->base.values[1].data); style = GOG_STYLED_OBJECT (series)->style; if (model->base.vary_style_by_element || mode == GOG_SHOW_NEGS_WHITE) style = go_style_dup (style); gog_renderer_push_style (view->renderer, style); overrides = gog_series_get_overrides (GOG_SERIES (series)); for (k = 0 ; k < series->base.num_elements; k++) { len = vals[k] * scale; negative = len < 0; if (negative) { if (mode == GOG_SHOW_NEGS_SKIP) { if ((overrides != NULL) && (GOG_SERIES_ELEMENT (overrides->data)->index == k)) overrides = overrides->next; continue; } len = -len; } if (!go_finite (len) || len < 1e-3) { if ((overrides != NULL) && (GOG_SERIES_ELEMENT (overrides->data)->index == k)) overrides = overrides->next; continue; } gpse = NULL; if ((overrides != NULL) && (GOG_SERIES_ELEMENT (overrides->data)->index == k)) { gpse = GOG_PIE_SERIES_ELEMENT (overrides->data); overrides = overrides->next; if (negative && mode == GOG_SHOW_NEGS_WHITE) { elt_style = go_style_dup (go_styled_object_get_style ( GO_STYLED_OBJECT (gpse))); elt_style->fill.type = GO_STYLE_FILL_PATTERN; go_pattern_set_solid (&elt_style->fill.pattern, GO_COLOR_WHITE); gog_renderer_push_style (view->renderer, elt_style); } else gog_renderer_push_style (view->renderer, go_styled_object_get_style ( GO_STYLED_OBJECT (gpse))); } else { if (negative && mode == GOG_SHOW_NEGS_WHITE) gog_renderer_push_style (view->renderer, white_style); else if (model->base.vary_style_by_element) gog_theme_fillin_style (theme, style, GOG_OBJECT (series), model->base.index_num + k, GO_STYLE_FILL); } /* only separate the outer ring */ separated_cx = cx; separated_cy = cy; if (num_series == index && (default_sep > 0. || gpse != NULL)) { separation = default_sep; if (gpse != NULL) separation += gpse->separation * r_tot; separated_cx += separation * cos (theta + len/2.); separated_cy += separation * sin (theta + len/2.); } theta += len; go_path_ring_wedge (path, separated_cx, separated_cy, r_ext, r_ext, has_hole ? r_int : 0.0, has_hole ? r_int : 0.0, theta - len, theta); gog_renderer_draw_shape (view->renderer, path); go_path_clear (path); if (gpse != NULL || (negative && mode == GOG_SHOW_NEGS_WHITE)) { gog_renderer_pop_style (view->renderer); if (elt_style) { g_object_unref (elt_style); elt_style = NULL; } } } gog_renderer_pop_style (view->renderer); if (model->base.vary_style_by_element || mode == GOG_SHOW_NEGS_WHITE) g_object_unref (style); if (white_style) g_object_unref (white_style); index ++; } go_path_free (path); }
static int gog_pie_view_get_data_at_point (GogPlotView *view, double x, double y, GogSeries **series) { GogPiePlot const *model = GOG_PIE_PLOT (view->base.model); GogPieSeries const *pseries = NULL; double r_tot, r_cur, r_int, r_ext, cx, cy, r, th, th0, theta, scale, *vals; double separated_cx, separated_cy; unsigned int index, elem, k; double center_radius; double center_size = 0.0; unsigned num_series = 0; double default_sep, len; double separation_max = 0., separation; GSList *ptr; double outline_width_max = 0.; gboolean has_hole; GogPieSeriesElement *gpse; GList const *overrides; GogShowNegsMode mode = model->show_negatives; gboolean negative; GOStyle *style; *series = NULL; /* compute number of valid series */ for (ptr = model->base.series ; ptr != NULL ; ptr = ptr->next) { if (!gog_series_is_valid (GOG_SERIES (ptr->data))) continue; pseries = ptr->data; if ((style = go_styled_object_get_style (GO_STYLED_OBJECT (pseries)))) outline_width_max = MAX (outline_width_max, gog_renderer_line_size (view->base.renderer, style->line.width)); for (overrides = gog_series_get_overrides (GOG_SERIES (pseries)); overrides != NULL; overrides = overrides->next) { separation = GOG_PIE_SERIES_ELEMENT (overrides->data)->separation; if (separation_max < separation) separation_max = separation; style = go_styled_object_get_style (GO_STYLED_OBJECT (overrides->data)); if (outline_width_max < style->line.width) outline_width_max = style->line.width; } num_series++; } if (separation_max < -model->default_separation) separation_max = -model->default_separation; if (num_series <= 0) return -1; if (GOG_IS_RING_PLOT (model)) center_size = GOG_RING_PLOT(model)->center_size; else if (num_series > 1) num_series = 1; /* calculate things when span < 100. */ if (model->span < 100.) { double xmin, xmax, ymin, ymax, ratio; double begin, cur, end; if (num_series == 1) { pseries = model->base.series->data; begin = (model->initial_angle + pseries->initial_angle) * M_PI / 180. - M_PI / 2.; end = begin + model->span * M_PI / 50.; } else { /* WARNING: this code has not been checked */ ptr = model->base.series; while (!gog_series_is_valid (GOG_SERIES (ptr->data))) ptr = ptr->next; pseries = ptr->data; begin = end = pseries->initial_angle; for (ptr = ptr->next; ptr != NULL; ptr = ptr->next) { if (!gog_series_is_valid (GOG_SERIES (ptr->data))) continue; pseries = ptr->data; cur = pseries->initial_angle; if (cur < begin) begin = cur; if (cur > end) end = cur; } begin = (model->initial_angle + begin) * M_PI / 180. - M_PI / 2.; end = ((model->initial_angle + end) / 180. + model->span / 50.) * M_PI - M_PI / 2.; } cur = ceil (begin / M_PI * 2 - 1e-10) * M_PI / 2; xmin = xmax = cos (begin); ymin = ymax = sin (begin); while (cur < end) { cx = cos (cur); cy = sin (cur); if (cx > xmax) xmax = cx; if (cx < xmin) xmin = cx; if (cy > ymax) ymax = cy; if (cy < ymin) ymin = cy; cur += M_PI / 2; } cx = cos (end); cy = sin (end); if (cx > xmax) xmax = cx; if (cx < xmin) xmin = cx; if (cy > ymax) ymax = cy; if (cy < ymin) ymin = cy; /* we ensure that the center will be visible */ if (xmin > 0.) xmin = 0.; if (xmax < 0.) xmax = 0.; if (ymin > 0.) ymin = 0.; if (ymax < 0.) ymax = 0.; ratio = (ymax - ymin) / (xmax - xmin); if (view->base.allocation.h > view->base.allocation.w * ratio) { r_tot = view->base.allocation.w * MAX (xmax, -xmin) / (xmax - xmin); cx = view->base.allocation.x - view->base.allocation.w * xmin / (xmax - xmin); cy = view->base.allocation.y + (view->base.allocation.h + view->base.allocation.w * ratio) / 2. - view->base.allocation.w * ratio * ymax / (ymax - ymin); } else { r_tot = view->base.allocation.h * MAX (ymax, -ymin) / (ymax - ymin); cx = view->base.allocation.x + (view->base.allocation.w - view->base.allocation.h / ratio) / 2. - view->base.allocation.h / ratio * xmin / (xmax - xmin); cy = view->base.allocation.y - view->base.allocation.h * ymin / (ymax - ymin); } r_tot /= 1. + model->default_separation + separation_max; } else { /* centre things */ cx = view->base.allocation.x + view->base.allocation.w/2.; cy = view->base.allocation.y + view->base.allocation.h/2.; r_tot = view->base.allocation.h; if (r_tot > view->base.allocation.w) r_tot = view->base.allocation.w; r_tot /= 2. * (1. + model->default_separation + separation_max); } r = hypot (x - cx, y - cy); default_sep = r_tot * model->default_separation; center_radius = r_tot * center_size; r_cur = r_tot * (1. - center_size); if (r < center_radius) return -1; elem = model->base.index_num; index = 1; th0 = (model->initial_angle + pseries->initial_angle) * M_PI / 180. - M_PI / 2.; th = atan2 (y - cy, x - cx); if (th < th0) th += 2 * M_PI; for (ptr = model->base.series ; ptr != NULL ; ptr = ptr->next) { pseries = ptr->data; if (!gog_series_is_valid (GOG_SERIES (pseries))) continue; if (index > num_series) /* people snuck extra series into a pie */ break; if (num_series == index) r_cur -= outline_width_max / 2.0; has_hole = center_radius > 0. || index > 1; r_int = (has_hole)? (center_radius + r_cur * ((double) index - 1.0) / (double) num_series): 0.; r_ext = center_radius + r_cur * (double) index / (double) num_series; theta = th0; scale = 2 * M_PI / 100 * model->span / pseries->total; vals = go_data_get_values (pseries->base.values[1].data); overrides = gog_series_get_overrides (GOG_SERIES (pseries)); for (k = 0 ; k < pseries->base.num_elements; k++) { len = vals[k] * scale; negative = len < 0; if (negative) { if (mode == GOG_SHOW_NEGS_SKIP) { if ((overrides != NULL) && (GOG_SERIES_ELEMENT (overrides->data)->index == k)) overrides = overrides->next; continue; } len = -len; } if (!go_finite (len) || len < 1e-3) { if ((overrides != NULL) && (GOG_SERIES_ELEMENT (overrides->data)->index == k)) overrides = overrides->next; continue; } gpse = NULL; if ((overrides != NULL) && (GOG_SERIES_ELEMENT (overrides->data)->index == k)) { gpse = GOG_PIE_SERIES_ELEMENT (overrides->data); overrides = overrides->next; } /* only separate the outer ring */ separated_cx = cx; separated_cy = cy; if (num_series == index && (default_sep > 0. || gpse != NULL)) { separation = default_sep; if (gpse != NULL) separation += gpse->separation * r_tot; separated_cx += separation * cos (theta + len/2.); separated_cy += separation * sin (theta + len/2.); r = hypot (x - separated_cx, y - separated_cy); th = atan2 (y - separated_cy, x - separated_cx); if (th < th0) th += 2 * M_PI; } theta += len; if (r > r_int && r <= r_ext && th > theta - len && th <= theta) { *series = GOG_SERIES (pseries); return k; } if (gpse) { r = hypot (x - cx, y - cy); th = atan2 (y - cy, x - cx); if (th < th0) th += 2 * M_PI; } } index ++; } return -1; }
int main (int argc, char *argv[]) { GtkWidget *window, *box, *w; GogChart *chart; GogGraph *graph; GogLabel *label; GogPlot *pie; GogSeries *series; GOStyle *style; GOData *data; GError *error; PangoFontDescription *desc; char const *title = "Some statistics"; char const * const legends[] = {"first", "second", "third", "fourth"}; double values[] = {10., 20., 30., 40.}; gtk_init (&argc, &argv); /* Initialize libgoffice */ libgoffice_init (); /* Initialize plugins manager */ go_plugins_init (NULL, NULL, NULL, NULL, TRUE, GO_TYPE_PLUGIN_LOADER_MODULE); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_resize (GTK_WINDOW (window), 300, 340); gtk_window_set_title (GTK_WINDOW (window), "pie demo"); g_signal_connect (window, "destroy", gtk_main_quit, NULL); box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); w = gtk_button_new_from_stock (GTK_STOCK_QUIT); g_signal_connect_swapped (w, "clicked", G_CALLBACK (on_quit), window); gtk_box_pack_end (GTK_BOX (box), w, FALSE, FALSE, 0); w = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); 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 (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)); /* Add a title */ label = (GogLabel *) g_object_new (GOG_TYPE_LABEL, NULL); data = go_data_scalar_str_new (title, FALSE); gog_dataset_set_dim (GOG_DATASET (label), 0, data, NULL); gog_object_add_by_name (GOG_OBJECT (graph), "Title", GOG_OBJECT (label)); /* Change the title font */ style = go_styled_object_get_style (GO_STYLED_OBJECT (label)); desc = pango_font_description_from_string ("Sans bold 16"); go_style_set_font_desc (style, desc); /* Get the chart created by the widget initialization */ chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (w)); /* Create a pie plot and add it to the chart */ pie = (GogPlot *) gog_plot_new_by_name ("GogPiePlot"); gog_object_add_by_name (GOG_OBJECT (chart), "Plot", GOG_OBJECT (pie)); /* Create a series for the plot and populate it with some simple data */ series = gog_plot_new_series (pie); data = go_data_vector_str_new (legends, 4, NULL); gog_series_set_dim (series, 0, data, &error); data = go_data_vector_val_new (values, 4, NULL); gog_series_set_dim (series, 1, data, &error); /* Add a legend to the chart */ gog_object_add_by_name (GOG_OBJECT (chart), "Legend", NULL); gtk_container_add (GTK_CONTAINER (window), box); gtk_widget_show_all (GTK_WIDGET (window)); w = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0); gtk_main (); /* Clean libgoffice stuff */ libgoffice_shutdown (); return 0; }
static void cb_gnm_so_path_changed (GnmSOPath const *sop, G_GNUC_UNUSED GParamSpec *pspec, GnmSOPathView *group) { GList *ptr = GOC_GROUP (group)->children; for (; ptr && ptr->data; ptr = ptr->next) if (GOC_IS_PATH (ptr->data)) cb_gnm_so_path_style_changed (GOC_ITEM (ptr->data), sop); if (sop->text != NULL && *sop->text != 0) { /* set a font, a very bad solution, but will do until we move to GOString */ PangoFontDescription *desc = pango_font_description_from_string ("Sans 10"); GOStyle *style; if (group->text == NULL) { double x0, y0, x1, y1; if (group->path) goc_item_get_bounds (group->path, &x0, &y0, &x1, &y1); else { unsigned i; double mx, my, Mx, My; x0 = y0 = G_MAXDOUBLE; x1 = y1 = -G_MAXDOUBLE; for (i = 0; i < group->paths->len; i++) { goc_item_get_bounds (GOC_ITEM (g_ptr_array_index (group->paths, i)), &mx, &my, &Mx, &My); if (mx < x0) x0 = mx; if (my < y0) y0 = my; if (Mx > x1) x1 = Mx; if (My > y1) y1 = My; } } x1 -= x0 + sop->margin_pts.left + sop->margin_pts.right; y1 -= y0 + sop->margin_pts.top + sop->margin_pts.bottom; x0 += x1 / 2. + sop->margin_pts.left; y0 += y1 / 2. + sop->margin_pts.top; x1 = MAX (x1, DBL_MIN); y1 = MAX (y1, DBL_MIN); group->text = goc_item_new (GOC_GROUP (group), GOC_TYPE_TEXT, "anchor", GO_ANCHOR_CENTER, "clip", TRUE, "x", x0, "y", y0, "clip-height", y1, "clip-width", x1, "wrap-width", x1, "attributes", sop->markup, NULL); } style = go_styled_object_get_style (GO_STYLED_OBJECT (group->text)); go_style_set_font_desc (style, desc); goc_item_set (group->text, "text", sop->text, "attributes", sop->markup, NULL); } else if (group->text != NULL) { g_object_unref (group->text); group->text = NULL; } }