/* This is -*- C -*- */
/* $Id: guppi-legend-state.c,v 1.17 2001/09/29 07:31:46 trow Exp $ */

/*
 * guppi-legend-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 <guppi-useful.h>
#include <guppi-rgb.h>
#include <guppi-seq-string.h>
#include <guppi-seq-categorical.h>
#include <guppi-data-table.h>
#include <guppi-data-socket.h>
#include <guppi-data-flavor.h>
#include <guppi-color-palette.h>
#include "guppi-legend-state.h"
#include "guppi-legend-view.h"

static GtkObjectClass *parent_class = NULL;

static void
guppi_legend_state_finalize (GtkObject *obj)
{
  if (parent_class->finalize)
    parent_class->finalize (obj);
}

/***************************************************************************/

static void
guppi_legend_state_class_init (GuppiLegendStateClass *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_legend_state_finalize;

  state_class->view_type = GUPPI_TYPE_LEGEND_VIEW;
}

static void
guppi_legend_state_init (GuppiLegendState *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, "labels::socket::adopt", NULL, guppi_data_socket_new ());

  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "swatch_width",      NULL, inch / 4);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "swatch_height",     NULL, inch / 4);

  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_COLOR_PALETTE, "swatch_colors",            NULL, NULL);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN,       "use_stock_colors",         NULL, FALSE);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN,       "fallback_to_stock_colors", NULL, TRUE);

  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "edge_thickness",    NULL, inch / 48);
  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_margin",       NULL, inch / 8);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "label_offset",      NULL, inch / 16);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_FONT,      "label_font::adopt", NULL, guppi_default_font ());
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA,      "label_color",       NULL, RGBA_BLACK);
}

GtkType guppi_legend_state_get_type (void)
{
  static GtkType guppi_legend_state_type = 0;
  if (!guppi_legend_state_type) {
    static const GtkTypeInfo guppi_legend_state_info = {
      "GuppiLegendState",
      sizeof (GuppiLegendState),
      sizeof (GuppiLegendStateClass),
      (GtkClassInitFunc) guppi_legend_state_class_init,
      (GtkObjectInitFunc) guppi_legend_state_init,
      NULL, NULL, (GtkClassInitFunc) NULL
    };
    guppi_legend_state_type =
      gtk_type_unique (GUPPI_TYPE_ELEMENT_STATE, &guppi_legend_state_info);
  }
  return guppi_legend_state_type;
}

GuppiElementState *
guppi_legend_state_new (void)
{
  return GUPPI_ELEMENT_STATE (guppi_type_new (guppi_legend_state_get_type ()));
}

/***************************************************************************/

void
guppi_legend_state_entry_bounds (GuppiLegendState *state,
				 gint *i0, gint *i1)
{
  GuppiData *labels;

  g_return_if_fail (state && GUPPI_IS_LEGEND_STATE (state));

  if (i0) *i0 = 0;
  if (i1) *i1 = -1;

  guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
			   "labels", &labels,
			   NULL);

  if (labels == NULL)
    return;

  if (GUPPI_IS_SEQ_STRING (labels)) {

    guppi_seq_bounds (GUPPI_SEQ (labels), i0, i1);

  } else if (GUPPI_IS_SEQ_CATEGORICAL (labels)) {

    GuppiCategory *cat;
    cat = guppi_seq_categorical_category (GUPPI_SEQ_CATEGORICAL (labels));
    if (i0) *i0 = 0;
    if (i1) *i1 = (gint)guppi_category_size (cat) - 1;

  } else if (GUPPI_IS_DATA_TABLE (labels)) {

    if (i0) *i0 = 0;
    if (i1) {
      gint C;
      guppi_data_table_get_dimensions (GUPPI_DATA_TABLE (labels), NULL, &C);
      *i1 = C - 1;
    }

  } else {

    g_warning ("Unknown data type.");

  }
}

guint32
guppi_legend_state_entry_color (GuppiLegendState *state, gint i)
{
  GuppiColorPalette *pal = NULL;
  static GuppiColorPalette *stock_pal = NULL;
  gboolean use_stock_colors, fallback_to_stock_colors;
  gint i0, i1;
  guint32 color;

  g_return_val_if_fail (GUPPI_IS_LEGEND_STATE (state), 0);

  guppi_legend_state_entry_bounds (state, &i0, &i1);
  g_return_val_if_fail (i0 <= i && i <= i1, 0);

  if (stock_pal == NULL) {
    stock_pal = guppi_color_palette_new ();
    guppi_permanent_alloc (stock_pal);
  }
  
  guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
			   "swatch_colors::raw", &pal,
			   "use_stock_colors", &use_stock_colors,
			   "fallback_to_stock_colors", &fallback_to_stock_colors,
			   NULL);

  color = RGBA_RED; /* Our fallback color: all red means something is wrong... */

  if (use_stock_colors || (pal == NULL && fallback_to_stock_colors)) {
    color = guppi_color_palette_get (stock_pal, i);
  } else if (pal != NULL) {
    color = guppi_color_palette_get (pal, i);
  }

  return color;
}

const gchar *
guppi_legend_state_entry_text (GuppiLegendState *state, gint i)
{
  GuppiData *labels;
  gint i0, i1;

  g_return_val_if_fail (GUPPI_IS_LEGEND_STATE (state), NULL);

  guppi_legend_state_entry_bounds (state, &i0, &i1);
  if (i < i0 || i > i1)
    return "-OutOfBounds-";

  guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
			   "labels", &labels,
			   NULL);
  
  if (GUPPI_IS_SEQ_STRING (labels)) {

    return guppi_seq_string_get (GUPPI_SEQ_STRING (labels), i);

  } else if (GUPPI_IS_SEQ_CATEGORICAL (labels)) {

    GuppiCategory *cat;
    cat = guppi_seq_categorical_category (GUPPI_SEQ_CATEGORICAL (labels));
    return guppi_category_find_by_code (cat, i);

  } else if (GUPPI_IS_DATA_TABLE (labels)) {

    return guppi_data_table_get_col_label (GUPPI_DATA_TABLE (labels), i);

  }

  return "-Missing-";
}

double
guppi_legend_state_max_label_width (GuppiLegendState *state)
{
  GnomeFont *font;
  gint i, i0, i1;
  double max = 0;

  g_return_val_if_fail (GUPPI_IS_LEGEND_STATE (state), 0);

  guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
			   "label_font", &font,
			   NULL);

  guppi_legend_state_entry_bounds (state, &i0, &i1);

  for (i = i0; i <= i1; ++i) {
    const gchar *txt = guppi_legend_state_entry_text (state, i);
    double len = gnome_font_get_width_string (font, txt);
    max = MAX (len, max);
  }

  guppi_unref (font);

  return max;
}

double
guppi_legend_state_natural_width (GuppiLegendState *state)
{
  double nat_w = 0;
  double edge_margin, label_offset, swatch_width;

  g_return_val_if_fail (GUPPI_IS_LEGEND_STATE (state), 0);

  guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
			   "edge_margin", &edge_margin,
			   "label_offset", &label_offset,
			   "swatch_width", &swatch_width,
			   NULL);

  nat_w = 2 * edge_margin + label_offset + swatch_width;
  nat_w += guppi_legend_state_max_label_width (state);

  return nat_w;
}

double
guppi_legend_state_natural_height (GuppiLegendState *state)
{
  GnomeFont *font;
  double nat_h = 0;
  double natural_skip, edge_margin, edge_thickness, swatch_height;
  gint i0, i1, N;

  g_return_val_if_fail (GUPPI_IS_LEGEND_STATE (state), 0);

  guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
			   "label_font", &font,
			   "edge_margin", &edge_margin,
			   "edge_thickness", &edge_thickness,
			   "swatch_height", &swatch_height,
			   NULL);

  natural_skip = MAX (0.5 * gnome_font_get_ascender (font), edge_thickness);

  guppi_legend_state_entry_bounds (state, &i0, &i1);
  N = i1 - i0 + 1;

  nat_h = 2 * edge_margin + (N - 1) * natural_skip;
  nat_h += N * MAX (swatch_height, gnome_font_get_ascender (font));

  return nat_h;
}



/* $Id: guppi-legend-state.c,v 1.17 2001/09/29 07:31:46 trow Exp $ */


syntax highlighted by Code2HTML, v. 0.9.1