
/*
 * canvasText.c --
 *
 * This file implements the text item of the canvas widget
 *
 * Copyright (c) 2001 - 2002 P.G. Baum
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
   History:
   2001-05: Begin of developement
 */

#include "canvas.h"
#include <string.h>
#include <assert.h>

typedef struct
{
   Gnocl_ListBool   coords;
   Gnocl_ObjBool    label;
   Gnocl_StringBool font;
   Gnocl_ObjBool    fill;
   Gnocl_ObjBool    anchor;
   Gnocl_ListBool   offset;
   Gnocl_ListBool   clip;
} TextParams;

static const GnoclWidgetOptions textOptions[] = 
{
   { "-coords", GNOCL_LIST, GNOCL_OFFSET( TextParams, coords ) },
   { "-label", GNOCL_OBJ, GNOCL_OFFSET( TextParams, label ) },
   { "-font", GNOCL_STRING, GNOCL_OFFSET( TextParams, font ) },
   { "-fill", GNOCL_OBJ, GNOCL_OFFSET( TextParams, fill ) },
   { "-anchor", GNOCL_OBJ, GNOCL_OFFSET( TextParams, anchor ) },
   { "-offset", GNOCL_LIST, GNOCL_OFFSET( TextParams, offset ) },
   /* { "-clip", GNOCL_LIST, GNOCL_OFFSET( TextParams, clip ) }, */
   { NULL, 0, 0 }
};

static int freeParams( TextParams *params )
{
   #if 0
   if( params->coords.val )
      Tcl_DecrRefCount( params->coords.val );  /* FIXME: is this correct? */
   #endif
   GNOCL_FREE_TCL_OPT( params->coords );
   GNOCL_FREE_TCL_OPT( params->label );
   GNOCL_FREE_MEM_OPT( params->font );
   GNOCL_FREE_TCL_OPT( params->fill );
   GNOCL_FREE_TCL_OPT( params->anchor );
   GNOCL_FREE_TCL_OPT( params->offset );
   GNOCL_FREE_TCL_OPT( params->clip );

   return 0;
}

static int canvasDeleteText( Tcl_Interp *interp, 
      Gnocl_CanvasItemInfo *info )
{
   /* no internal params, so no need to free anything */
   return 0;
}

static int setParams( Tcl_Interp *interp, TextParams *params,
      Gnocl_CanvasItemInfo *info )
{
   if( params->coords.val )
   {
      int    noCoords;
      double coords[2];
      int    n;

      if( Tcl_ListObjLength( interp, params->coords.val, &noCoords ) != TCL_OK
            || noCoords != 2 )
      {
         Tcl_SetResult( interp, "list-of-coordinates must contain exactly "
               "2 elements", TCL_STATIC );
         return TCL_ERROR;
      }
      for( n = 0; n < 2; ++n )
      {
         Tcl_Obj *tp;
         if( Tcl_ListObjIndex( interp, params->coords.val, n, &tp ) != TCL_OK 
               || Tcl_GetDoubleFromObj( interp, tp, &coords[n] ) != TCL_OK )
         {
            freeParams( params );
            return TCL_ERROR;
         }
      }

      gnome_canvas_item_set( info->item, "x", coords[0], "y", coords[1], 
            NULL );
   }


   if( params->label.changed )
      gnome_canvas_item_set( info->item, 
            "text", gnoclGetString( params->label.val ), NULL );

   /* TODO: use tk's font substitution mechanism? Or has gtk/gnome
            something similar? 
   */
   if( params->font.changed )
      gnome_canvas_item_set( info->item, 
            "font", params->font.val, NULL );

   if( params->fill.changed )
   {
      GdkColor color;
      int      alpha;
      if( gnoclGetGdkColorAlloc( interp, params->fill.val, 
            GTK_WIDGET( info->canvas ), &color, &alpha ) != TCL_OK )
         return TCL_ERROR;
      if( alpha == 0 ) /* it seems that transparancy does not work for line */
         gnome_canvas_item_set( info->item, "fill_color", NULL, NULL );
      else
         gnome_canvas_item_set( info->item, "fill_color_gdk", &color, NULL );
   }

   if( params->anchor.changed )
   {
      GtkAnchorType style;
      if( gnoclGetAnchorStyle( interp, params->anchor.val, &style ) != TCL_OK )
      {
         freeParams( params );
         return TCL_ERROR;
      }
      gnome_canvas_item_set( info->item, 
            "anchor", style, NULL );
   }

   if( params->offset.val )
   {
      int    noCoords;
      double offset[2];
      int    n;

      if( Tcl_ListObjLength( interp, params->offset.val, &noCoords ) != TCL_OK
            || noCoords != 2 )
      {
         Tcl_SetResult( interp, "list-of-coordinates must contain exactly "
               "2 elements", TCL_STATIC );
         return TCL_ERROR;
      }
      for( n = 0; n < 2; ++n )
      {
         Tcl_Obj *tp;
         if( Tcl_ListObjIndex( interp, params->offset.val, n, &tp ) != TCL_OK 
               || Tcl_GetDoubleFromObj( interp, tp, &offset[n] ) != TCL_OK )
         {
            freeParams( params );
            return TCL_ERROR;
         }
      }

      /* printf( "%f %f\n", offset[0], offset[1] ); */
      gnome_canvas_item_set( info->item, "x_offset", offset[0], 
            "y_offset", offset[1], NULL );
   }

   return TCL_OK;
}

static int canvasConfigText( Tcl_Interp *interp, int objc, 
      Tcl_Obj * const objv[], Gnocl_CanvasItemInfo *info )
{
   TextParams params;
   memset( &params, 0, sizeof( params ) );
   /* canvas itemconfigure tag params ... */
   if( gnoclParseAllWidgetOpts( interp, objc, objv, 2,
         textOptions, (char *)&params ) != TCL_OK )
      return TCL_ERROR;

   return setParams( interp, &params, info );
}


Gnocl_CanvasItemInfo *gnoclCanvasCreateText( Tcl_Interp *interp,
      int objc, Tcl_Obj * const objv[], GnomeCanvas *widget )
{
   Gnocl_CanvasItemInfo *info;
   TextParams params;

   memset( &params, 0, sizeof( params ) );
   if( gnoclParseAllWidgetOpts( interp, objc, objv, 3,
         textOptions, (char *)&params ) != TCL_OK )
      return NULL;

   if( params.coords.changed == 1 )
   {
      Tcl_SetResult( interp, 
            "in creating coordinates may not be given as option",
            TCL_STATIC );
      return NULL;
   }

   params.coords.val = objv[3];

   info = g_new( Gnocl_CanvasItemInfo, 1 );
   info->canvas = widget;
   info->deleteFunc = &canvasDeleteText;
   info->configFunc = &canvasConfigText;
   info->group = gnome_canvas_root( widget );
   info->item = gnome_canvas_item_new( info->group, 
         gnome_canvas_text_get_type( ), 
         "fill_color", "black", 
         "font", "-adobe-courier-bold-r-normal-*-*-140-*-*-m-*-iso8859-1",
         NULL );

   setParams( interp, &params, info );

   return info;
}

