/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gog-grid-line.c * * Copyright (C) 2004 Emmanuel Pacaud (emmanuel.pacaud@univ-poitiers.fr) * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct _GogGridLine { GogStyledObject base; gboolean is_minor; }; typedef GogStyledObjectClass GogGridLineClass; static GType gog_grid_line_view_get_type (void); static GogViewClass *gview_parent_klass; enum { GRID_LINE_PROP_0, GRID_LINE_PROP_IS_MINOR, }; gboolean gog_grid_line_is_minor (GogGridLine *ggl) { g_return_val_if_fail (IS_GOG_GRID_LINE (ggl), FALSE); return ggl->is_minor; } static void gog_grid_line_init_style (GogStyledObject *gso, GogStyle *style) { style->interesting_fields = GOG_STYLE_LINE; gog_theme_fillin_style (gog_object_get_theme (GOG_OBJECT (gso)), style, GOG_OBJECT (gso), 0, FALSE); } static void gog_grid_line_set_property (GObject *obj, guint param_id, GValue const *value, GParamSpec *pspec) { GogGridLine *grid_line = GOG_GRID_LINE (obj); switch (param_id) { case GRID_LINE_PROP_IS_MINOR: grid_line->is_minor = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec); return; /* NOTE : RETURN */ } gog_object_emit_changed (GOG_OBJECT (obj), FALSE); } static void gog_grid_line_get_property (GObject *obj, guint param_id, GValue *value, GParamSpec *pspec) { GogGridLine *grid_line = GOG_GRID_LINE (obj); switch (param_id) { case GRID_LINE_PROP_IS_MINOR: g_value_set_boolean (value, grid_line->is_minor); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec); break; } } static void gog_grid_line_class_init (GogGridLineClass *klass) { GObjectClass *gobject_klass = (GObjectClass *) klass; GogObjectClass *gog_klass = (GogObjectClass *) klass; GogStyledObjectClass *style_klass = (GogStyledObjectClass *) klass; gobject_klass->set_property = gog_grid_line_set_property; gobject_klass->get_property = gog_grid_line_get_property; gog_klass->view_type = gog_grid_line_view_get_type (); style_klass->init_style = gog_grid_line_init_style; g_object_class_install_property (gobject_klass, GRID_LINE_PROP_IS_MINOR, g_param_spec_boolean ("is-minor", "is-minor", "Are these minor grid lines", FALSE, G_PARAM_READWRITE)); } GSF_CLASS (GogGridLine, gog_grid_line, gog_grid_line_class_init, NULL, GOG_STYLED_OBJECT_TYPE) /************************************************************************/ typedef GogView GogGridLineView; typedef GogViewClass GogGridLineViewClass; #define GOG_GRID_LINE_VIEW_TYPE (gog_grid_line_view_get_type ()) #define GOG_GRID_LINE_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_GRID_LINE_VIEW_TYPE, GogGridLineView)) #define IS_GOG_GRID_LINE_VIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_GRID_LINE_VIEW_TYPE)) static void gog_grid_line_view_render (GogView *view, GogViewAllocation const *bbox) { GogGridLine *grid_line = GOG_GRID_LINE (view->model); GSList *axis_list; GogAxis *axis; GogChart *chart; GogView *chart_view; GogStyle *style; GogAxisType axis_type; GogAxisMap *map = NULL; GogAxisTick *ticks; unsigned tick_nbr, i, j; ArtVpath path[3]; ArtVpath *c_path; GogViewAllocation const *plot_area; double line_width; axis = GOG_AXIS (view->model->parent); g_return_if_fail (axis != NULL); chart = GOG_CHART (view->model->parent->parent); g_return_if_fail (chart != NULL); g_return_if_fail (view->parent != NULL); chart_view = GOG_VIEW (view->parent->parent); g_return_if_fail (chart_view != NULL); axis_type = gog_axis_get_atype (axis); tick_nbr = gog_axis_get_ticks (axis, &ticks); if (tick_nbr < 1) return; plot_area = gog_chart_view_get_plot_area (chart_view); style = gog_styled_object_get_style (GOG_STYLED_OBJECT (grid_line)); gog_renderer_push_style (view->renderer, style); line_width = gog_renderer_line_size (view->renderer, style->line.width); path[0].code = ART_MOVETO; path[1].code = ART_LINETO; path[2].code = ART_END; if (line_width > 0) { switch (axis_type) { case GOG_AXIS_X: case GOG_AXIS_Y: switch (axis_type) { case GOG_AXIS_X: map = gog_axis_map_new (axis, plot_area->x, plot_area->w); break; case GOG_AXIS_Y: map = gog_axis_map_new (axis, plot_area->y +plot_area->h, -plot_area->h); break; default: return; } switch (axis_type) { case GOG_AXIS_X: for (i = 0; i < tick_nbr; i++) { if ((ticks[i].type == GOG_AXIS_TICK_MAJOR && !grid_line->is_minor) || (ticks[i].type == GOG_AXIS_TICK_MINOR && grid_line->is_minor)) { path[0].y = plot_area->y; path[1].y = plot_area->y + plot_area->h; path[0].x = path[1].x = gog_axis_map_to_view (map, ticks[i].position); gog_renderer_draw_sharp_path (view->renderer, path); } } break; case GOG_AXIS_Y: for (i = 0; i < tick_nbr; i++) { if ((ticks[i].type == GOG_AXIS_TICK_MAJOR && !grid_line->is_minor) || (ticks[i].type == GOG_AXIS_TICK_MINOR && grid_line->is_minor)) { path[0].x = plot_area->x; path[1].x = plot_area->x + plot_area->w; path[0].y = path[1].y = gog_axis_map_to_view (map, ticks[i].position); gog_renderer_draw_sharp_path (view->renderer, path); } } break; default: break; } gog_axis_map_free (map); break; case GOG_AXIS_RADIAL: { GogAxis *circular_axis; GogChartMap *c_map; GogChartMapPolarData *parms; axis_list = gog_chart_get_axes (chart, GOG_AXIS_CIRCULAR); if (axis_list == NULL) break; circular_axis = GOG_AXIS (axis_list->data); g_slist_free (axis_list); c_map = gog_chart_map_new (GOG_CHART (chart), plot_area, circular_axis, axis, NULL, FALSE); parms = gog_chart_map_get_polar_parms (c_map); if (gog_axis_is_discrete (circular_axis)) { unsigned step_nbr; double start, stop; map = gog_chart_map_get_axis_map (c_map, 0); gog_axis_map_get_extents (map, &start, &stop); step_nbr = go_rint (parms->th1 - parms->th0) + 1; c_path = art_new (ArtVpath, step_nbr + 2); for (i = 0; i < tick_nbr; i++) { if ((ticks[i].type == GOG_AXIS_TICK_MAJOR && !grid_line->is_minor) || (ticks[i].type == GOG_AXIS_TICK_MINOR && grid_line->is_minor)) { for (j = 0; j <= step_nbr; j++) { gog_chart_map_2D_to_view (c_map, j + parms->th0 , ticks[i].position, &c_path[j].x, &c_path[j].y); c_path[j].code = ART_LINETO; } c_path[0].code = ART_MOVETO; c_path[step_nbr + 1].code = ART_END; gog_renderer_draw_path (view->renderer, c_path); } } g_free (c_path); } else { double position; map = gog_chart_map_get_axis_map (c_map, 1); for (i = 0; i < tick_nbr; i++) { if ((ticks[i].type == GOG_AXIS_TICK_MAJOR && !grid_line->is_minor) || (ticks[i].type == GOG_AXIS_TICK_MINOR && grid_line->is_minor)) { position = gog_axis_map (map, ticks[i].position); gog_renderer_draw_arc (view->renderer, parms->cx, parms->cy, position * parms->rx, position * parms->ry, -parms->th1, -parms->th0); } } } gog_chart_map_free (c_map); break; } case GOG_AXIS_CIRCULAR: { GogAxis *radial_axis; GogChartMap *c_map; double start, stop; axis_list = gog_chart_get_axes (chart, GOG_AXIS_RADIAL); if (axis_list == NULL) break; radial_axis = GOG_AXIS (axis_list->data); g_slist_free (axis_list); c_map = gog_chart_map_new (GOG_CHART (chart), plot_area, axis, radial_axis, NULL, FALSE); map = gog_chart_map_get_axis_map (c_map, 1); gog_axis_map_get_extents (map, &start, &stop); gog_chart_map_2D_to_view (c_map, 0, start, &path[0].x, &path[0].y); path[0].code = ART_MOVETO; path[1].code = ART_LINETO; path[2].code = ART_END; for (i = 0; i < tick_nbr; i++) if ((ticks[i].type == GOG_AXIS_TICK_MAJOR && !grid_line->is_minor) || (ticks[i].type == GOG_AXIS_TICK_MINOR && grid_line->is_minor)) { gog_chart_map_2D_to_view (c_map, ticks[i].position, stop, &path[1].x, &path[1].y); gog_renderer_draw_path (view->renderer, path); } gog_chart_map_free (c_map); } default: break; } } gog_renderer_pop_style (view->renderer); } static void gog_grid_line_view_class_init (GogGridLineViewClass *gview_klass) { GogViewClass *view_klass = (GogViewClass *) gview_klass; gview_parent_klass = g_type_class_peek_parent (gview_klass); view_klass->render = gog_grid_line_view_render; } static GSF_CLASS (GogGridLineView, gog_grid_line_view, gog_grid_line_view_class_init, NULL, GOG_VIEW_TYPE)