
/*
 * label.c --
 *
 * This file implements the label 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:
   2002-01: _realy_ set STD_OPTIONS
        12: removed {x,y}{Align,Pad}, use list parameters instead
        12: {x,y}{Align,Pad}
        09: underlined accelerators; bindUnderline widgetID
        07: Fixed reconfiguration, added std options
   2001-03: Begin of developement
 */

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

typedef struct
{
   GNOCL_STD_OPTIONS_VARS;

   Gnocl_ObjBool    text;
   Gnocl_ObjBool    justify;
   Gnocl_BoolBool   lineWrap;
   Gnocl_StringBool bindUnderline;
   Gnocl_ListBool   align;
   Gnocl_ListBool   padding;

   GtkLabel *widget;
} LabelOptions;

static const GnoclWidgetOptions widgetOptions[] =
{
   GNOCL_STD_OPTIONS_NAMES( LabelOptions ),

   { "-text", GNOCL_OBJ, GNOCL_OFFSET( LabelOptions, text ) },
   { "-justify", GNOCL_OBJ, GNOCL_OFFSET( LabelOptions, justify ) },
   { "-lineWrap", GNOCL_BOOL, GNOCL_OFFSET( LabelOptions, lineWrap ) },
   { "-bindUnderline", GNOCL_STRING, GNOCL_OFFSET( LabelOptions, 
         bindUnderline ) },
   { "-align", GNOCL_LIST, GNOCL_OFFSET( LabelOptions, align ) },
   { "-padding", GNOCL_LIST, GNOCL_OFFSET( LabelOptions, padding ) },
   { NULL, 0, 0 }
};

static void freeOpts( LabelOptions *p )
{
   GNOCL_STD_OPTIONS_FREE( p );

   GNOCL_FREE_TCL_OPT( p->text );
   GNOCL_FREE_TCL_OPT( p->justify );
   GNOCL_FREE_TCL_OPT( p->align );
   GNOCL_FREE_TCL_OPT( p->padding );
}


static int labelConfigure( Tcl_Interp *interp, GtkLabel *widget, 
      LabelOptions *popt )
{
   GNOCL_STD_OPTIONS_HANDLE( popt, GTK_WIDGET( widget ) );

   if( popt->text.changed )
   {
      GnoclStringType type = gnoclGetStringType( popt->text.val );
      char *txt = gnoclGetString( popt->text.val );

      gtk_label_set_text( widget, txt );

      if( type & GNOCL_STR_UNDERLINE )
      {
         guint key = gnoclLabelParseULine( GTK_WIDGET( widget ), txt );
         if( key != GDK_VoidSymbol && popt->bindUnderline.changed )
         {
            const char *signal = NULL;
            GtkWidget *actWidget = gnoclGetWidgetFromName( 
                  popt->bindUnderline.val, interp );

            if( actWidget == NULL )
               return TCL_ERROR;

            if( GTK_IS_BUTTON( actWidget ) )
               signal = "clicked";
            else if( GTK_IS_ENTRY( actWidget ) )
               signal = "grab_focus";
            else if( GTK_IS_COMBO( actWidget ) )
            {
               signal = "grab_focus";
               actWidget = GTK_COMBO( actWidget )->entry;
            }
            /* printf( "DEBUG: in label.c: signal: %s\n", signal ); */
            if( signal != NULL )
               gtk_widget_add_accelerator( actWidget, signal,
                  gnoclGetAccelGroup(), key, 
                  GDK_MOD1_MASK, GTK_ACCEL_LOCKED );
         }
      }
   }

   if( popt->justify.changed )
   {
      GtkJustification justify = GTK_JUSTIFY_CENTER;
      if( gnoclGetJustification( interp, popt->justify.val, &justify )
            != TCL_OK )
         return TCL_ERROR;
      gtk_label_set_justify( widget, justify );
   }

   if( popt->lineWrap.changed )
      gtk_label_set_line_wrap( widget, popt->lineWrap.val );
   
   if( popt->align.changed )
   {
      double xAlign, yAlign;

      if( gnoclGet2Double( interp, popt->align.val, 
            &xAlign, &yAlign ) != TCL_OK )
            return TCL_ERROR;
 
      gtk_misc_set_alignment( GTK_MISC( widget ), xAlign, yAlign );
   }

   if( popt->align.changed )
   {
      int xPad, yPad;

      if( gnoclGet2Int( interp, popt->padding.val, &xPad, &yPad ) != TCL_OK )
            return TCL_ERROR;
 
      gtk_misc_set_padding( GTK_MISC( widget ), xPad, yPad );
   }

   return TCL_OK;
}

static int labelFunc( ClientData data, Tcl_Interp *interp,
      int objc, Tcl_Obj * const objv[] )
{

   static char *cmds[] = { GNOCL_STD_CMD_NAMES,
         "configure", NULL };
   enum cmdIdx { GNOCL_STD_CMD_ENUMS, ConfigureIdx };
   int idx;
   GtkLabel *widget = (GtkLabel *)data;

   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, GTK_WIDGET( widget ) );
            break;

      case ConfigureIdx:
            {
               LabelOptions opt;
               int ret = TCL_ERROR;

               memset( &opt, 0, sizeof( opt ) );
               if( gnoclParseAllWidgetOpts( interp, objc, objv, 1,
                     widgetOptions, (char *)&opt ) == TCL_OK )
                  ret = labelConfigure( interp, widget, &opt );
               freeOpts( &opt );
               if( ret != TCL_OK )
                  return TCL_ERROR;
            }
            break;
   }

   return TCL_OK;
}

int gnoclLabelCmd( ClientData data, Tcl_Interp *interp,
      int objc, Tcl_Obj * const objv[] )
{
   LabelOptions opt;
   char *name = gnoclGetAutoWidgetId();
   GtkLabel *widget;
   
   memset( &opt, 0, sizeof( opt ) );
   if( gnoclParseAllWidgetOpts( interp, objc, objv, 0,
         widgetOptions, (char *)&opt ) != TCL_OK )
      return TCL_ERROR;

   widget = GTK_LABEL( gtk_label_new( NULL ) );

   if( labelConfigure( interp, widget, &opt ) != TCL_OK )
   {
      /* FIXME: g_free pp->name ... */
      gtk_widget_destroy( GTK_WIDGET( widget ) );
      return TCL_ERROR;
   }

   gnoclMemNameAndWidget( name, GTK_WIDGET( widget ) );
   gtk_widget_show( GTK_WIDGET( widget ) );

   Tcl_CreateObjCommand( interp, name, labelFunc, widget, NULL );
   Tcl_SetObjResult( interp, Tcl_NewStringObj( name, -1 ) );

   return TCL_OK;
}

