/* 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 <trow@gnu.org> and
* Havoc Pennington <hp@pobox.com>.
*
* 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 <config.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>
#include <math.h>
#include <guppi-useful.h>
#include <guppi-data-flavor.h>
#include <guppi-data-socket.h>
#include <guppi-seq-scalar.h>
#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 $ */
syntax highlighted by Code2HTML, v. 0.9.1