
/*
 * gnoclFontPicker.c --
 *
 * This file implements the fontPicker widget
 *
 * Copyright (c) 2001 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-07: Begin of developement
 */

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

typedef struct
{
   GNOCL_STD_OPTIONS_VARS;

   Gnocl_ObjBool    text;
   Gnocl_ObjBool    title;
   Gnocl_ObjBool    mode;
   Gnocl_StringBool command;
   Gnocl_StringBool variable;
} FontPickerOptions;

static const GnoclWidgetOptions widgetOptions[] =
{
   GNOCL_STD_OPTIONS_NAMES( FontPickerOptions ),
   { "-text", GNOCL_OBJ, GNOCL_OFFSET( FontPickerOptions, text ) },
   { "-title", GNOCL_OBJ, GNOCL_OFFSET( FontPickerOptions, title ) },
   { "-command", GNOCL_STRING, GNOCL_OFFSET( FontPickerOptions, command ) },
   { "-variable", GNOCL_STRING, GNOCL_OFFSET( FontPickerOptions, variable ) },
   { NULL, 0, 0 }
};

/*
   This struct contains only the necessary states to remember.
   Option values can be inquired via gtk
*/
typedef struct
{
   char             *name;
   Tcl_Interp       *interp;
   GnomeFontPicker  *fontPicker;
   char             *command;
   char             *variable;
   int              inSignal;
} FontPickerParams;

static void freeOpts( FontPickerOptions *p )
{
   GNOCL_STD_OPTIONS_FREE( p );
   GNOCL_FREE_MEM_OPT( p->command );
}

static void fontSetFunc( GtkWidget *widget, 
      gchar *font_name, gpointer data )
{
   FontPickerParams *para = (FontPickerParams *)data;

   para->inSignal = 1;
   printf( "DEBUG fontPicker signal %s: \"%s\"\n", para->name, font_name );

   if( para->variable )
   {
      Tcl_Obj *obj = Tcl_NewStringObj( font_name, -1 );
      Tcl_SetVar2Ex( para->interp, para->variable, NULL, obj, 0 );
   }
   if( para->command )
   {
      static Gnocl_PercSubst ps[] = {
         { 'w', GNOCL_STRING },     /* widget */
         { 'f', GNOCL_STRING },     /* font name */
         { 0 }
      };

      ps[0].val.str = para->name;
      ps[1].val.str = font_name;

      gnoclPercentSubstAndEval( para->interp, ps, para->command );
   }
   para->inSignal = 0;
}

static char *traceFunc( ClientData data,
      Tcl_Interp *interp, char *name1, char *name2, int flags)
{
   FontPickerParams *para = (FontPickerParams *)data;

   assert( name1 == para->variable );
   if( !para->inSignal )
   {
      Tcl_Obj *obj = Tcl_GetVar2Ex( interp, name1, name2, flags ); 
      if( obj == NULL ) /* var does not yet exist */
      {
         Tcl_Obj *obj = Tcl_NewStringObj( 
               gnome_font_picker_get_font_name( para->fontPicker ), -1 );
         Tcl_SetVar2Ex( para->interp, para->variable, NULL, obj, 0 );
      }
      else
      {
         const char *txt;
         if( gnoclGetFontTxt( interp, obj, &txt ) == TCL_OK )
         {
            printf( "DEBUG FontPicker trace %s: \"%s\"\n", para->name, txt );
            if( gnome_font_picker_set_font_name( para->fontPicker, txt ) == 0 )
            {
               Tcl_AppendResult( interp, "unknown font \"", txt, "\".", 
                     (char *)NULL );
            }
         }
      }
   }

   return NULL;
}

static void fontPickerDestroyFunc( GtkWidget *widget, gpointer data )
{
   FontPickerParams *para = (FontPickerParams *)data;

  /* untrace and free command and variable */
   gnoclAttacheCmdAndVar( 
         1, &para->command, NULL,
         1, &para->variable, NULL,
         "font_set", GTK_OBJECT( para->fontPicker ), fontSetFunc,
         para->interp, traceFunc, para );

   gnoclForgetWidgetFromName( para->name );
   Tcl_DeleteCommand( para->interp, para->name );

   g_free( para->name );
   g_free( para );
}

static int getFontPickerMode( Tcl_Interp *interp, Tcl_Obj *obj, 
      GnomeFontPickerMode *mode )
{
   char *txt[] = { "pixmap", "fontInfo", "userWidget", "unknown", NULL };
   GnomeFontPickerMode modes[] = { 
      GNOME_FONT_PICKER_MODE_PIXMAP, GNOME_FONT_PICKER_MODE_FONT_INFO,
      GNOME_FONT_PICKER_MODE_USER_WIDGET, GNOME_FONT_PICKER_MODE_UNKNOWN };

   int idx;
   if( Tcl_GetIndexFromObj( interp, obj, txt, "font picker mode",
         TCL_EXACT, &idx ) != TCL_OK )
      return TCL_ERROR;
   *mode = modes[idx];
   return TCL_OK;
}

static int fontPickerConfigure( Tcl_Interp *interp, FontPickerParams *para, 
      FontPickerOptions *popt )
{
   GNOCL_STD_OPTIONS_HANDLE( popt, GTK_WIDGET( para->fontPicker ) );

   gnoclAttacheCmdAndVar( 
         popt->command.changed, &para->command, &popt->command.val,
         popt->variable.changed, &para->variable, &popt->variable.val,
         "font_set", GTK_OBJECT( para->fontPicker ), fontSetFunc,
         interp, traceFunc, para );

   if( popt->title.changed )
   {
      gnome_font_picker_set_title( para->fontPicker, 
         gnoclGetString( popt->title.val ) );
   }

   if( popt->mode.changed )
   {
      GnomeFontPickerMode mode;
      if( getFontPickerMode( interp, popt->mode.val, &mode ) != TCL_OK )
         return TCL_ERROR;

      gnome_font_picker_set_mode( para->fontPicker, mode );
   }

   return TCL_OK;
}

static int fontPickerFunc( ClientData data, Tcl_Interp *interp,
      int objc, Tcl_Obj * const objv[] )
{
   static char *cmds[] = { GNOCL_STD_CMD_NAMES,
         "configure", 
         "getValue", "getFont",
         "setValue", "setFont",
         NULL };
   enum cmdIdx { GNOCL_STD_CMD_ENUMS, 
         ConfigureIdx, 
         GetValueIdx, SetValueIdx,
         GetFontIdx, SetFontIdx 
         };
   FontPickerParams *para = (FontPickerParams *)data;
   GtkWidget *widget = GTK_WIDGET( para->fontPicker );
   int idx;

   if( Tcl_GetIndexFromObj( interp, objv[1], cmds, "command", 
         TCL_EXACT, &idx ) != TCL_OK )
      return TCL_ERROR;

   switch( idx )
   {
      GNCOL_STD_CMD_CASE( interp, objc, objv, widget );
            break;

      case ConfigureIdx:
            {
               FontPickerOptions opt;
               int ret = TCL_ERROR;
               memset( &opt, 0, sizeof( opt ) );
               if( gnoclParseAllWidgetOpts( interp, objc, objv, 1,
                     widgetOptions, (char *)&opt ) == TCL_OK )
                  ret = fontPickerConfigure( interp, para, &opt );

               freeOpts( &opt );
               if( ret != TCL_OK )
                  return TCL_ERROR;
            }
            break;
      case GetFontIdx:
      case GetValueIdx:
            {
               Tcl_Obj *obj;
               if( objc != 2 )
               {
                  Tcl_WrongNumArgs( interp, 2, objv, "" );
                  return TCL_ERROR;
               }
               obj = Tcl_NewStringObj( gnome_font_picker_get_font_name( 
                     para->fontPicker ), -1 );
               Tcl_SetObjResult( interp, obj );
            }
            break;

      case SetFontIdx:
      case SetValueIdx:
            {
               const char *txt;
               if( objc != 3 )
               {
                  Tcl_WrongNumArgs( interp, 2, objv, "value" );
                  return TCL_ERROR;
               }


               if( gnoclGetFontTxt( interp, objv[2], &txt ) != TCL_OK )
                  return TCL_ERROR;
               if( gnome_font_picker_set_font_name( para->fontPicker, txt ) 
                     == 0 )
               {
                  Tcl_AppendResult( interp, "unknown font \"", txt, "\".", 
                        (char *)NULL );
                  return TCL_ERROR;
               }
               fontSetFunc( GTK_WIDGET( para->fontPicker ), 
                     (gchar *)txt, para );
            }
            break;
   }

   return TCL_OK;
}

int gnoclFontPickerCmd( ClientData data, Tcl_Interp *interp,
      int objc, Tcl_Obj * const objv[] )
{
   FontPickerOptions opt;
   FontPickerParams *para;
   int          ret;
   
   memset( &opt, 0, sizeof( opt ) );
   if( gnoclParseAllWidgetOpts( interp, objc, objv, 0,
         widgetOptions, (char *)&opt ) != TCL_OK )
      return TCL_ERROR;

   para = g_new( FontPickerParams, 1 );
   para->interp = interp;
   para->command = NULL;
   para->variable = NULL;
   para->name = gnoclGetAutoWidgetId();
   para->inSignal = 0;

   para->fontPicker = GNOME_FONT_PICKER( gnome_font_picker_new( ) );
   ret = fontPickerConfigure( interp, para, &opt );
   freeOpts( &opt );
   if( ret != TCL_OK )
   {
      /* FIXME: g_free pp->name ... */
      gtk_widget_destroy( GTK_WIDGET( para->fontPicker ) );
      return TCL_ERROR;
   }
   /*
   gtk_signal_connect( GTK_OBJECT( para->fontPicker ), "clicked", 
         GTK_SIGNAL_FUNC( commandFunc ), para );
   */
   gtk_signal_connect( GTK_OBJECT( para->fontPicker ), "font_set", 
         GTK_SIGNAL_FUNC( fontSetFunc ), para );
   gtk_signal_connect( GTK_OBJECT( para->fontPicker ), "destroy", 
         GTK_SIGNAL_FUNC( fontPickerDestroyFunc ), para );

   gnoclMemNameAndWidget( para->name, GTK_WIDGET( para->fontPicker ) );
   gtk_widget_show( GTK_WIDGET( para->fontPicker ) );

   Tcl_CreateObjCommand( interp, para->name, fontPickerFunc, para, NULL );
   Tcl_SetObjResult( interp, Tcl_NewStringObj( para->name, -1 ) );

   return TCL_OK;
}

