
/*
 * canvasWidget.c --
 *
 * This file implements the widget 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_StringBool widget;
   Gnocl_ObjBool    anchor;
} WidgetParams;

static const GnoclWidgetOptions widgetOptions[] = 
{
   { "-coords", GNOCL_LIST, GNOCL_OFFSET( WidgetParams, coords ) },
   { "-widget", GNOCL_STRING, GNOCL_OFFSET( WidgetParams, widget ) },
   { "-anchor", GNOCL_OBJ, GNOCL_OFFSET( WidgetParams, anchor ) },
   { NULL, 0, 0 }
};

static int freeParams( WidgetParams *params )
{
   GNOCL_FREE_TCL_OPT( params->coords );
   GNOCL_FREE_MEM_OPT( params->widget );
   GNOCL_FREE_TCL_OPT( params->anchor );

   return 0;
}

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

static int setParams( Tcl_Interp *interp, WidgetParams *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 )
            return TCL_ERROR;
      }

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

   if( params->anchor.changed )
   {
      GtkAnchorType style;
      if( gnoclGetAnchorStyle( interp, params->anchor.val, &style ) != TCL_OK )
         return TCL_ERROR;

      printf( "DEBUG: anchor: %d\n", style );
      gnome_canvas_item_set( info->item, "anchor", style, NULL );
   }

   if( params->widget.changed )
   {
      GtkWidget *widget = gnoclGetWidgetFromName( params->widget.val, interp );
      if( widget == NULL )
         return TCL_ERROR;

      gnome_canvas_item_set( info->item, "widget", widget, NULL );
   }

   return TCL_OK;
}

static int canvasConfigWidget( Tcl_Interp *interp, int objc, 
      Tcl_Obj * const objv[], Gnocl_CanvasItemInfo *info )
{
   WidgetParams params;
   int ret;

   memset( &params, 0, sizeof( params ) );
   /* canvas itemconfigure tag params ... */
   if( gnoclParseAllWidgetOpts( interp, objc, objv, 2,
         widgetOptions, (char *)&params ) != TCL_OK )
      ret = TCL_ERROR;
   else
      ret = setParams( interp, &params, info );

   freeParams( &params );
   return ret;
}


Gnocl_CanvasItemInfo *gnoclCanvasCreateWidget( Tcl_Interp *interp,
      int objc, Tcl_Obj * const objv[], GnomeCanvas *widget )
{
   Gnocl_CanvasItemInfo *info;
   WidgetParams params;
   char *txt;
   int  txtLen;

   memset( &params, 0, sizeof( params ) );
   if( objc < 5 )
   {
      Tcl_WrongNumArgs( interp, 2, objv, 
            /* canvas create */
            "type list-of-coordinates widget ?option val ...?" );
      info = NULL;
   }
   else if( gnoclParseAllWidgetOpts( interp, objc, objv, 4,
         widgetOptions, (char *)&params ) != TCL_OK )
   {
      info = NULL;
   }
   else if( params.coords.changed || params.widget.changed )
   {
      Tcl_SetResult( interp, 
            "in creating coordinates or widget may not be given as option",
            TCL_STATIC );
      info = NULL;
   }
   else
   {
      params.coords.changed = 1;
      params.coords.val = objv[3];
      Tcl_IncrRefCount( params.coords.val );

      txt = Tcl_GetStringFromObj( objv[4], &txtLen );
      params.widget.changed = 1;
      params.widget.val = g_memdup( txt, txtLen + 1 ); 

      info = g_new( Gnocl_CanvasItemInfo, 1 );
      info->canvas = widget;
      info->deleteFunc = &canvasDeleteWidget;
      info->configFunc = &canvasConfigWidget;
      info->group = gnome_canvas_root( widget );
      info->item = gnome_canvas_item_new( info->group, 
            gnome_canvas_widget_get_type( ), 
            NULL );

      setParams( interp, &params, info );
   }

   freeParams( &params );

   return info;
}

