/* This is -*- C -*- */
/* $Id: guppi-text-state.c,v 1.27 2001/11/19 05:40:53 trow Exp $ */

/*
 * guppi-text-state.c
 *
 * Copyright (C) 2000 EMC Capital Management, Inc.
 * Copyright (C) 2001 Free Software Foundation, Inc.
 *
 * 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 <libgnomeui/gnome-color-picker.h>
#include <libgnomeui/gnome-font-picker.h>

#include <glade/glade.h>
#include <guppi-convenient.h>
#include <guppi-useful.h>
#include "guppi-text-state.h"
#include "guppi-text-view.h"

static GtkObjectClass *parent_class = NULL;

static void
guppi_text_state_finalize (GtkObject * obj)
{
  GuppiTextState *state = GUPPI_TEXT_STATE (obj);

  guppi_unref0 (state->block);

  if (parent_class->finalize)
    parent_class->finalize (obj);
}

static GuppiElementView *
make_view (GuppiElementState * state)
{
  return GUPPI_ELEMENT_VIEW (guppi_type_new (GUPPI_TYPE_TEXT_VIEW));
}

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

#if 0
/** Code for config widget **/

static void
push_state_to_widget (GuppiTextState * state, GladeXML * xml)
{
  GtkWidget *w;
  guint8 r, g, b, a;
  gboolean outline;

  w = glade_xml_get_widget (xml, "text_entry");
  gtk_entry_set_text (GTK_ENTRY (w), guppi_text_state_text (state));


  w = glade_xml_get_widget (xml, "font_picker");
  gtk_widget_set_sensitive (w, FALSE);


  w = glade_xml_get_widget (xml, "color_picker");
  UINT_TO_RGBA (guppi_text_state_color (state), &r, &g, &b, &a);
  gnome_color_picker_set_i8 (GNOME_COLOR_PICKER (w), r, g, b, a);


  outline = guppi_text_state_outline (state);
  w = glade_xml_get_widget (xml, "outline_check_button");
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), outline);

  w = glade_xml_get_widget (xml, "thickness_spinner");
  gtk_spin_button_set_value (GTK_SPIN_BUTTON (w),
			     guppi_text_state_outline_width (state));
  gtk_widget_set_sensitive (w, outline);

  w = glade_xml_get_widget (xml, "thickness_label");
  gtk_widget_set_sensitive (w, outline);
}

static void
text_cb (GtkEntry * entry, GuppiTextState * state)
{
  guppi_text_state_set_text (state, gtk_entry_get_text (entry));
}

static void
font_cb (GnomeFontPicker * fp, const gchar * font_name,
	 GuppiTextState * state)
{
#if 0
  GnomeFont *font;
  font = gnome_font_new_from_full_name (font_name);
  guppi_text_state_set_font (state, font);
  guppi_unref (font);
#endif
}

static void
color_cb (GnomeColorPicker * cp,
	  guint r, guint g, guint b, guint a, GuppiTextState * state)
{
  guint32 color;

  color = RGBA_TO_UINT (r >> 8, g >> 8, b >> 8, a >> 8);
  guppi_text_state_set_color (state, color);
}

static void
outline_checkbox_cb (GtkToggleButton * b, GuppiTextState * state)
{
  guppi_text_state_set_outline (state, gtk_toggle_button_get_active (b));
}

static void
outline_spinner_cb (GtkSpinButton * sb, GuppiTextState * state)
{
  double w = gtk_spin_button_get_value_as_float (sb);

  if (guppi_text_state_outline (state))
    guppi_text_state_set_outline_width (state, w);
}

static void
destroy_cb (GtkObject * w, GladeXML * xml)
{
  gtk_signal_disconnect_by_func (GTK_OBJECT (gtk_object_get_user_data (w)),
				 push_state_to_widget, xml);
}

static void
connect_signals (GuppiTextState * state, GladeXML * xml)
{
  GtkWidget *w;

  w = glade_xml_get_widget (xml, "text_entry");
  gtk_signal_connect (GTK_OBJECT (w), "changed",
		      GTK_SIGNAL_FUNC (text_cb), state);

  w = glade_xml_get_widget (xml, "font_picker");
  gtk_signal_connect (GTK_OBJECT (w), "font_set",
		      GTK_SIGNAL_FUNC (font_cb), state);

  w = glade_xml_get_widget (xml, "outline_check_button");
  gtk_signal_connect (GTK_OBJECT (w), "toggled",
		      GTK_SIGNAL_FUNC (outline_checkbox_cb), state);

  w = glade_xml_get_widget (xml, "thickness_spinner");
  gtk_signal_connect (GTK_OBJECT (w), "changed",
		      GTK_SIGNAL_FUNC (outline_spinner_cb), state);

  w = glade_xml_get_widget (xml, "color_picker");
  gtk_signal_connect (GTK_OBJECT (w), "color_set",
		      GTK_SIGNAL_FUNC (color_cb), state);
}


static GtkWidget *
config_widget_cb (gpointer user_data)
{
  GuppiTextState *state = GUPPI_TEXT_STATE (user_data);
  const gchar *glade_xml_path;
  GladeXML *xml;
  GtkWidget *w;

  glade_xml_path = guppi_glade_path ("guppi-text-state.glade");
  g_return_val_if_fail (glade_xml_path != NULL, NULL);

  xml = glade_xml_new (glade_xml_path, "text_state_control");
  g_return_val_if_fail (xml != NULL, NULL);

  push_state_to_widget (state, xml);

  connect_signals (state, xml);
  gtk_signal_connect (GTK_OBJECT (state), "changed",
		      GTK_SIGNAL_FUNC (push_state_to_widget), xml);

  w = glade_xml_get_widget (xml, "text_state_control");
  gtk_object_set_user_data (GTK_OBJECT (w), state);

  gtk_signal_connect (GTK_OBJECT (w), "destroy",
		      GTK_SIGNAL_FUNC (destroy_cb), xml);

  return w;
}

static GuppiConfigItem *
config_tree (GuppiElementState * state)
{
  GuppiConfigItem *top_node;

  top_node = guppi_config_item_new (_("Configure Text"),
				    _("Configure"), config_widget_cb, state);
  return top_node;
}
#endif

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

static void
guppi_text_state_class_init (GuppiTextStateClass * 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_text_state_finalize;

  state_class->name = _("Text");

  state_class->make_view = make_view;
  /* state_class->config_tree = config_tree; */
}

static void
bag_changed_cb (GuppiAttributeBag *bag, const gchar *key, gpointer closure)
{
  GuppiTextState *state = GUPPI_TEXT_STATE (closure);

  if (!strcmp (key, "text")) {
    /* This forces our changed_size emission to happen now, rather than during
       the update -- which causes us to render twice: once when the text
       has changed but the item hasn't resized, and then once when the item
       is the right size.  This is jerky and ugly... */
    guppi_text_state_get_block (state);
  }
}

static void
guppi_text_state_init (GuppiTextState *obj)
{
  GuppiAttributeBag *bag = guppi_element_state_attribute_bag (GUPPI_ELEMENT_STATE (obj));
  double inch = guppi_in2pt (1.0);

  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_STRING,    "text",          NULL, "");
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_FONT,      "font::adopt",   NULL, guppi_default_font ());
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA,      "color",         NULL, RGBA_BLACK);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DOUBLE,    "angle",         NULL, 0.0);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN,   "filled",        NULL, TRUE);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "outline_width", NULL,  0.5);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "top_margin",    NULL, inch / 64);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "bottom_margin", NULL, inch / 64);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "left_margin",   NULL, inch / 64);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_DIMENSION, "right_margin",  NULL, inch / 64);

  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_BOOLEAN, "gradient", NULL, FALSE);
  guppi_attribute_bag_add_with_default (bag, GUPPI_ATTR_RGBA,    "color_final", NULL, RGBA_RED);

  gtk_signal_connect (GTK_OBJECT (bag),
		      "changed",
		      GTK_SIGNAL_FUNC (bag_changed_cb),
		      obj);

  obj->block = guppi_text_block_new ();
}

GtkType 
guppi_text_state_get_type (void)
{
  static GtkType guppi_text_state_type = 0;
  if (!guppi_text_state_type) {
    static const GtkTypeInfo guppi_text_state_info = {
      "GuppiTextState",
      sizeof (GuppiTextState),
      sizeof (GuppiTextStateClass),
      (GtkClassInitFunc) guppi_text_state_class_init,
      (GtkObjectInitFunc) guppi_text_state_init,
      NULL, NULL, (GtkClassInitFunc) NULL
    };
    guppi_text_state_type =
      gtk_type_unique (GUPPI_TYPE_ELEMENT_STATE, &guppi_text_state_info);
  }
  return guppi_text_state_type;
}

GuppiElementState *
guppi_text_state_new (void)
{
  return GUPPI_ELEMENT_STATE (guppi_type_new (guppi_text_state_get_type ()));
}

GuppiTextBlock *
guppi_text_state_get_block (GuppiTextState *state)
{
  gchar *text;
  gchar *block_text;
  GnomeFont *font;
  double tm, bm, rm, lm;
  double w, h;

  guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
			   "text", &text,
			   "font", &font,
			   "top_margin", &tm,
			   "bottom_margin", &bm,
			   "left_margin", &lm,
			   "right_margin", &rm,
			   NULL);

  guppi_text_block_freeze (state->block);
  if (guppi_text_block_font (state->block) != font) {
    guppi_text_block_set_font (state->block, font);
  }

  block_text = guppi_text_block_text (state->block);
  if (block_text == NULL || strcmp (block_text, text)) {
    guppi_text_block_set_max_width (state->block, -1);
    guppi_text_block_set_text (state->block, text);
  }
  guppi_free0 (block_text);

  guppi_text_block_thaw (state->block);
  
  w = guppi_text_block_width (state->block) + lm + rm;
  h = guppi_text_block_height (state->block) + tm + bm;

  guppi_debug_v ("text changed size %g %g", w, h);
  guppi_element_state_changed_size (GUPPI_ELEMENT_STATE (state), w, h);

  guppi_free (text);
  guppi_unref (font);

  return state->block;
}

/* $Id: guppi-text-state.c,v 1.27 2001/11/19 05:40:53 trow Exp $ */



syntax highlighted by Code2HTML, v. 0.9.1