/* This is -*- C -*- */ /* $Id: guppi-axis-state.c,v 1.30 2002/01/14 05:00:55 trow Exp $ */ /* * guppi-axis-state.c * * Copyright (C) 2000 EMC Capital Management, Inc. * Copyright (C) 2001 The Free Software Foundation * * Developed by Jon Trowbridge and * Havoc Pennington . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include #include #include #include #include #include #include #include #include #include "guppi-axis-state.h" #include "guppi-axis-view.h" static GtkObjectClass *parent_class = NULL; static void guppi_axis_state_finalize (GtkObject *obj) { if (parent_class->finalize) parent_class->finalize (obj); } /***************************************************************************/ static GuppiElementView * make_view (GuppiElementState *state) { return GUPPI_ELEMENT_VIEW (guppi_type_new (GUPPI_TYPE_AXIS_VIEW)); } /***************************************************************************/ static void guppi_axis_state_class_init (GuppiAxisStateClass *klass) { GtkObjectClass *object_class = (GtkObjectClass *) klass; GuppiElementStateClass *state_class = GUPPI_ELEMENT_STATE_CLASS (klass); parent_class = gtk_type_class (GUPPI_TYPE_ELEMENT_STATE); object_class->finalize = guppi_axis_state_finalize; state_class->name = _("Axis"); state_class->make_view = make_view; } static void guppi_axis_state_init (GuppiAxisState *obj) { GuppiAttributeBag *bag; double inch = guppi_in2pt (1.0); bag = guppi_element_state_attribute_bag (GUPPI_ELEMENT_STATE (obj)); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DATA_SOCKET, "data::socket::adopt", NULL, guppi_data_socket_new_by_type (GUPPI_TYPE_SEQ_SCALAR)); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_INT, "position", NULL, GUPPI_NORTH); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_edge", NULL, TRUE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "edge_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "edge_thickness", NULL, inch / 64); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_legend", NULL, TRUE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_STRING, "legend", NULL, ""); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "legend_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_FONT, "legend_font", NULL, guppi_default_font ()); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "legend_offset", NULL, inch / 16); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "label_offset", NULL, inch / 32); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "rotate_labels", NULL, FALSE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "shrink_labels_to_fit", NULL, TRUE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_lone_labels", NULL, TRUE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "extra_lone_label_offset", NULL, inch / 16); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "lone_label_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_FONT, "lone_label_font", NULL, guppi_default_font ()); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_major_ticks", NULL, TRUE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "major_tick_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "major_tick_thickness", NULL, inch / 64); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "major_tick_length", NULL, inch / 12); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_major_labels", NULL, TRUE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "major_label_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_FONT, "major_label_font", NULL, guppi_default_font ()); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_minor_ticks", NULL, TRUE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "minor_tick_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "minor_tick_thickness", NULL, inch / 96); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "minor_tick_length", NULL, inch / 16); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_minor_labels", NULL, FALSE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "minor_label_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_FONT, "minor_label_font", NULL, guppi_default_font ()); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_micro_ticks", NULL, TRUE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "micro_tick_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "micro_tick_thickness", NULL, inch / 128); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "micro_tick_length", NULL, inch / 24); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "show_micro_labels", NULL, FALSE); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA, "micro_label_color", NULL, RGBA_BLACK); guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_FONT, "micro_label_font", NULL, guppi_default_font ()); } GtkType guppi_axis_state_get_type (void) { static GtkType guppi_axis_state_type = 0; if (!guppi_axis_state_type) { static const GtkTypeInfo guppi_axis_state_info = { "GuppiAxisState", sizeof (GuppiAxisState), sizeof (GuppiAxisStateClass), (GtkClassInitFunc) guppi_axis_state_class_init, (GtkObjectInitFunc) guppi_axis_state_init, NULL, NULL, (GtkClassInitFunc) NULL }; guppi_axis_state_type = gtk_type_unique (GUPPI_TYPE_ELEMENT_STATE, &guppi_axis_state_info); } return guppi_axis_state_type; } GuppiElementState * guppi_axis_state_new (void) { return GUPPI_ELEMENT_STATE (guppi_type_new (guppi_axis_state_get_type ())); } /***************************************************************************/ void guppi_axis_state_tick_properties (GuppiAxisState *state, const GuppiTick *tick, gboolean *show_tick, guint32 *color, double *thickness, double *length, gboolean *show_label, double *label_offset, guint32 *label_color, GnomeFont **label_font) { g_return_if_fail (GUPPI_IS_AXIS_STATE (state)); if (show_tick) *show_tick = FALSE; if (show_label) *show_label = FALSE; g_return_if_fail (state != NULL); g_return_if_fail (GUPPI_IS_AXIS_STATE (state)); g_return_if_fail (tick != NULL); if (label_offset) guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "label_offset", label_offset, NULL); switch (guppi_tick_type (tick)) { case GUPPI_TICK_NONE: if (show_tick) *show_tick = FALSE; if (color) *color = 0; if (thickness) *thickness = 0; if (length) *length = 0; guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "show_lone_labels", show_label, "extra_lone_label_offset", label_offset, "lone_label_color", label_color, "lone_label_font", label_font, NULL); break; case GUPPI_TICK_MAJOR: case GUPPI_TICK_MAJOR_RULE: guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "show_major_ticks", show_tick, "major_tick_color", color, "major_tick_thickness", thickness, "major_tick_length", length, "show_major_labels", show_label, "major_label_color", label_color, "major_label_font", label_font, NULL); break; case GUPPI_TICK_MINOR: case GUPPI_TICK_MINOR_RULE: guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "show_minor_ticks", show_tick, "minor_tick_color", color, "minor_tick_thickness", thickness, "minor_tick_length", length, "show_minor_labels", show_label, "minor_label_color", label_color, "minor_label_font", label_font, NULL); break; case GUPPI_TICK_MICRO: case GUPPI_TICK_MICRO_RULE: guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "show_micro_ticks", show_tick, "micro_tick_color", color, "micro_tick_thickness", thickness, "micro_tick_length", length, "show_micro_labels", show_label, "micro_label_color", label_color, "micro_label_font", label_font, NULL); break; default: g_assert_not_reached (); } } gchar * guppi_axis_state_displayed_legend (GuppiAxisState *state) { gboolean show_legend; gchar *legend = NULL; GuppiData *data = NULL; g_return_val_if_fail (GUPPI_IS_AXIS_STATE (state), NULL); guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "show_legend", &show_legend, "legend", &legend, "data", &data, NULL); if (show_legend && data != NULL) { legend = guppi_strdup (guppi_data_get_label (data)); } guppi_unref (data); return legend; } double guppi_axis_state_legend_span (GuppiAxisState *state) { gchar *txt; GnomeFont *font; gint span = 0; double offset; g_return_val_if_fail (GUPPI_IS_AXIS_STATE (state), 0); guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "legend_font", &font, "legend_offset", &offset, NULL); txt = guppi_axis_state_displayed_legend (state); if (txt && *txt && font) { span = gnome_font_get_ascender (font) + gnome_font_get_descender (font) + offset; } guppi_free (txt); return span; } double guppi_axis_state_maximum_span (GuppiAxisState *state, double label_scale, GuppiAxisMarkers *marks) { gint i; double offset, max_span = 0, edge_thickness = 0; guppi_compass_t position; gboolean show_edge, care_about_width, rotate_labels; g_return_val_if_fail (GUPPI_IS_AXIS_STATE (state), 0); g_return_val_if_fail (label_scale > 0, 0); g_return_val_if_fail (GUPPI_IS_AXIS_MARKERS (marks), 0); guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "position", &position, "show_edge", &show_edge, "edge_thickness", &edge_thickness, "rotate_labels", &rotate_labels, "label_offset", &offset, NULL); if (show_edge) { /* Make our span slightly larger than the edge thickness, which tends to be a very small number. */ max_span = edge_thickness * 1.20; } care_about_width = (position == GUPPI_WEST || position == GUPPI_EAST); if (rotate_labels) care_about_width = !care_about_width; for (i = 0; i < guppi_axis_markers_size (marks); ++i) { const GuppiTick *tick = guppi_axis_markers_get (marks, i); gboolean show_tick, show_label; double length; GnomeFont *font; double span = 0; guppi_axis_state_tick_properties (state, tick, &show_tick, NULL, NULL, &length, &show_label, &offset, NULL, &font); if (show_tick) { span += length; } if (show_label) { span += offset; if (care_about_width) { if (guppi_tick_label (tick) != NULL) span += label_scale * gnome_font_get_width_string (font, guppi_tick_label (tick)); } else { span += label_scale * (gnome_font_get_ascender (font) + gnome_font_get_descender (font)); } } max_span = MAX (span, max_span); } max_span += guppi_axis_state_legend_span (state); /* This should become an optional parameter: */ /* Round up to nearest eighth of an inch (72/8=9) */ /* max_span = 9*ceil(max_span/9); */ return max_span; } double guppi_axis_state_label_shrink_to_fit_factor (GuppiAxisState *state, GuppiAxisMarkers *marks, double span) { gint i; gboolean rotate_labels; double offset, min_factor = 1; g_return_val_if_fail (GUPPI_IS_AXIS_STATE (state), 0); g_return_val_if_fail (GUPPI_IS_AXIS_MARKERS (marks), 0); guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "rotate_labels", &rotate_labels, NULL); /* This is not exactly the right thing to do... */ if (!rotate_labels) return 1.0; for (i = 0; i < guppi_axis_markers_size (marks); ++i) { const GuppiTick *tick = guppi_axis_markers_get (marks, i); gboolean show_tick, show_label; double length; GnomeFont *font; guppi_axis_state_tick_properties (state, tick, &show_tick, NULL, NULL, &length, &show_label, &offset, NULL, &font); if (show_label && guppi_tick_label (tick) != NULL && font != NULL) { if (!show_tick) length = 0; if (show_label) { double w = gnome_font_get_width_string (font, guppi_tick_label (tick)); double t = (span - length - offset) / w; min_factor = MIN (t, min_factor); } } } return min_factor; } void guppi_axis_state_get_size (GuppiAxisState *state, double text_scale, GuppiAxisMarkers *am, double *w, double *h) { guppi_compass_t pos; double span = 0; g_return_if_fail (GUPPI_IS_AXIS_STATE (state)); if (text_scale < 1e-8) { text_scale = 1.0; } guppi_element_state_get (GUPPI_ELEMENT_STATE (state), "position", &pos, NULL); if (am != NULL) { span = guppi_axis_state_maximum_span (state, text_scale, am); } if (pos == GUPPI_NORTH || pos == GUPPI_SOUTH) { if (w) *w = -1; if (h) *h = span; } else { if (w) *w = span; if (h) *h = -1; } } /* $Id: guppi-axis-state.c,v 1.30 2002/01/14 05:00:55 trow Exp $ */