Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
/**
 * 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);
}
Exemplo n.º 4
0
/**
 * 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);
}
Exemplo n.º 5
0
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);
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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.;
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
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;
	}
}