/* This is -*- C -*- */
/* $Id: guppi-axis-print.c,v 1.16 2001/10/15 20:58:40 trow Exp $ */

/*
 * guppi-axis-print.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-axis-print.h"

#include <math.h>
#include <guppi-useful.h>
#include "guppi-axis-state.h"
#include "guppi-axis-view.h"

static GtkObjectClass *parent_class = NULL;

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

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

static void
print (GuppiElementPrint *ep)
{
  GuppiAxisState *state = GUPPI_AXIS_STATE (guppi_element_print_state (ep));
  GuppiElementView *view = guppi_element_print_view (ep);
  double bbx0, bbx1, bby0, bby1;
  gchar *legend_text;
  guppi_compass_t position;
  gboolean show_edge, shrink_labels_to_fit, horizontal, rotate_labels;
  double edge_thickness;
  GnomeFont *lfont;
  guint32 lcolor, edge_color;

  guppi_element_print_get_bbox (ep, &bbx0, &bby0, &bbx1, &bby1);

  guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
			   "position", &position,
			   "show_edge", &show_edge,
			   "shrink_labels_to_fit", &shrink_labels_to_fit,
			   "rotate_labels", &rotate_labels,
			   "edge_thickness", &edge_thickness,
			   "edge_color", &edge_color,
			   "legend_font", &lfont,
			   "legend_color", &lcolor,
			   NULL);

  horizontal = position == GUPPI_NORTH || position == GUPPI_SOUTH;
			   

  /* Draw edge */
  if (show_edge) {
    double x0 = 0, y0 = 0, x1 = 0, y1 = 0;

    switch (position) {

    case GUPPI_NORTH:
      x0 = bbx0;
      x1 = bbx1;
      y0 = y1 = bby0;
      break;

    case GUPPI_SOUTH:
      x0 = bbx0;
      x1 = bbx1;
      y0 = y1 = bby1;
      break;

    case GUPPI_WEST:
      x0 = x1 = bbx1;
      y0 = bby0;
      y1 = bby1;
      break;

    case GUPPI_EAST:
      x0 = x1 = bbx0;
      y0 = bby0;
      y1 = bby1;
      break;

    default:
      g_assert_not_reached ();
    }

    guppi_element_print_gsave (ep);

    /* We need to double the line width, since half of it
       disappears from the clipping. */
    guppi_element_print_setlinewidth (ep, 2 * edge_thickness);
    guppi_element_print_setrgbacolor_uint (ep, edge_color);

    guppi_element_print_newpath (ep);
    guppi_element_print_moveto (ep, x0, y0);
    guppi_element_print_lineto (ep, x1, y1);
    guppi_element_print_stroke (ep);
    guppi_element_print_grestore (ep);
  }

  /* Next, paint the legend */
  if ((legend_text = guppi_axis_state_displayed_legend (state)) != NULL) {
    double lx, ly, w, h, lrot = 0;

    w = gnome_font_get_width_string (lfont, legend_text);
    h = gnome_font_get_ascender (lfont) + gnome_font_get_descender (lfont);

    guppi_element_print_gsave (ep);

    guppi_element_print_setfont (ep, lfont);
    guppi_element_print_setrgbacolor_uint (ep, lcolor);

    switch (position) {

    case GUPPI_NORTH:
      lx = (bbx0 + bbx1) / 2 - w / 2;
      ly = bby1 - h;
      break;

    case GUPPI_SOUTH:
      lx = (bbx0 + bbx1) / 2 - w / 2;
      ly = bby0;
      break;

    case GUPPI_WEST:
      lx = bbx0 + h;
      ly = (bby0 + bby1) / 2 - w / 2;
      lrot = 90;
      break;

    case GUPPI_EAST:
      lx = bbx1 - h;
      ly = (bby0 + bby1) / 2 + w / 2;
      lrot = -90;
      break;

    default:
      lx = ly = 0;
      g_assert_not_reached ();

    }

    guppi_element_print_moveto (ep, lx, ly);
    if (lrot) {
      double rot_matrix[6];
      art_affine_rotate (rot_matrix, lrot);
      guppi_element_print_concat (ep, rot_matrix);
    }

    guppi_element_print_show (ep, legend_text);

    guppi_free (legend_text);

    guppi_element_print_grestore (ep);
  }


  /* Next, paint the markers */
  {
    GuppiAxisMarkers *marks = NULL;

    marks = guppi_element_view_axis_markers (view, horizontal ? GUPPI_X_AXIS : GUPPI_Y_AXIS);
    
    if (marks) {
      gint i, N;
      double shrink_factor = 1;

      if (shrink_labels_to_fit) {
	shrink_factor = guppi_axis_view_label_shrink_to_fit_factor ((GuppiAxisView *) view, marks);
      }


      N = guppi_axis_markers_size (marks);
      for (i = 0; i < N; ++i) {
	const GuppiTick *tick = guppi_axis_markers_get (marks, i);
	gboolean show = FALSE, show_label = FALSE;
	double pos, length = 0, thick = 0, label_offset;
	guint32 tick_color = 0, label_color = 0;
	GnomeFont *font = NULL;
	double x0 = 0, y0 = 0, x1 = 0, y1 = 0, lx = 0, ly = 0;

	pos = tick->position;

	guppi_axis_view_tick_properties ((GuppiAxisView *) view, tick,
					 shrink_factor,
					 &show, &tick_color, &thick, &length,
					 &show_label,
					 &label_offset, &label_color, &font);

	if (!show)
	  length = 0;


	if (horizontal)
	  guppi_element_print_vp2pt_auto (ep, &pos, NULL);
	else
	  guppi_element_print_vp2pt_auto (ep, NULL, &pos);


	switch (position) {

	case GUPPI_NORTH:
	  x0 = x1 = lx = pos;
	  y0 = bby0;
	  y1 = bby0 + length;
	  ly = y1 + label_offset;
	  break;

	case GUPPI_SOUTH:
	  x0 = x1 = lx = pos;
	  y0 = bby1;
	  y1 = bby1 - length;
	  ly = y1 - label_offset;
	  break;

	case GUPPI_WEST:
	  x0 = bbx1;
	  x1 = bbx1 - length;
	  lx = x1 - label_offset;
	  y0 = y1 = ly = pos;
	  break;

	case GUPPI_EAST:
	  x0 = bbx0;
	  x1 = bbx0 + length;
	  lx = x1 + label_offset;
	  y0 = y1 = ly = pos;
	  break;

	default:
	  g_assert_not_reached ();
	}

	if (show && length > 0) {
	  guppi_element_print_setrgbacolor_uint (ep, tick_color);
	  guppi_element_print_setlinewidth (ep, thick);
	  guppi_element_print_newpath (ep);
	  guppi_element_print_moveto (ep, x0, y0);
	  guppi_element_print_lineto (ep, x1, y1);
	  guppi_element_print_stroke (ep);
	}

	if (show_label && guppi_tick_label (tick) != NULL && font != NULL) {
	  const gchar *label = guppi_tick_label (tick);
	  gboolean rotate = FALSE;
	  double w, h;
	  GnomeFont *used_font;

	  if (shrink_factor < 1.0) {
	    used_font = gnome_font_new (gnome_font_get_name (font),
					gnome_font_get_size (font) *
					shrink_factor);
	  } else {
	    used_font = font;
	  }

	  guppi_element_print_setfont (ep, used_font);

	  guppi_element_print_setrgbacolor_uint (ep, label_color);

	  w = gnome_font_get_width_string (used_font, label);
	  h = gnome_font_get_ascender (used_font);

	  if (shrink_factor < 1.0) {
	    guppi_unref0 (used_font);
	  }

	  if (rotate_labels) {
	    double tmp = w;
	    w = h;
	    h = tmp;
	    rotate = TRUE;
	  }

	  /* Adjust label positioning */
	  switch (position) {
	  case GUPPI_NORTH:
	    lx -= w / 2;
	    break;
	  case GUPPI_SOUTH:
	    lx -= w / 2;
	    ly -= h;
	    break;
	  case GUPPI_WEST:
	    lx -= w;
	    ly -= h / 2;
	    break;
	  case GUPPI_EAST:
	    ly -= h / 2;
	    break;
	  default:
	    g_assert_not_reached ();
	  }

	  if (rotate)
	    lx += w;

	  guppi_element_print_moveto (ep, lx, ly);

	  if (rotate) {
	    double rot_matrix[6];
	    art_affine_rotate (rot_matrix, 90);
	    guppi_element_print_gsave (ep);
	    guppi_element_print_concat (ep, rot_matrix);
	  }

	  guppi_element_print_show (ep, label);

	  if (rotate)
	    guppi_element_print_grestore (ep);

	}
      }
    }
  }
}


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

static void
guppi_axis_print_class_init (GuppiAxisPrintClass *klass)
{
  GtkObjectClass *object_class = (GtkObjectClass *) klass;
  GuppiElementPrintClass *ep_class = GUPPI_ELEMENT_PRINT_CLASS (klass);

  parent_class = gtk_type_class (GUPPI_TYPE_ELEMENT_PRINT);

  object_class->finalize = guppi_axis_print_finalize;

  ep_class->print = print;
}

static void
guppi_axis_print_init (GuppiAxisPrint *obj)
{

}

GtkType guppi_axis_print_get_type (void)
{
  static GtkType guppi_axis_print_type = 0;
  if (!guppi_axis_print_type) {
    static const GtkTypeInfo guppi_axis_print_info = {
      "GuppiAxisPrint",
      sizeof (GuppiAxisPrint),
      sizeof (GuppiAxisPrintClass),
      (GtkClassInitFunc) guppi_axis_print_class_init,
      (GtkObjectInitFunc) guppi_axis_print_init,
      NULL, NULL, (GtkClassInitFunc) NULL
    };
    guppi_axis_print_type =
      gtk_type_unique (GUPPI_TYPE_ELEMENT_PRINT, &guppi_axis_print_info);
  }
  return guppi_axis_print_type;
}

/* $Id: guppi-axis-print.c,v 1.16 2001/10/15 20:58:40 trow Exp $ */


syntax highlighted by Code2HTML, v. 0.9.1