/*********************************************************************
 *
 *         EZWGL, the EZ Widget and Graphics Library
 *
 *             Copyright (C) 1996, 1997  Maorong Zou
 *  
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **********************************************************************/
/*
 *  June 1996.  Beta Release.
 *  Sept 1996.  Release Version 1.0
 *  Dec 1996.  Release Version 1.1 Beta
 *  April 1997.  Release Version 1.2
 *  November 1997.  Release Version 1.3
 */
/*****************************************************************
 ***                                                           ***
 ***              Widget Button                                ***
 ***                                                           ***
 *****************************************************************/
#define _EZ_WIDGET_BUTTONN_C_
#include <ctype.h>
#include "EZ_Widget.h"

/*********************************************************************
 * 
 *  Functions implemented in this file:
 */
EZ_Widget  *EZ_CreateButton MY_ANSIARGS((EZ_Widget *parent, char *label, int undline));
void             EZ_DrawWidgetButton MY_ANSIARGS((EZ_Widget *widget));
void             EZ_ComputeWidgetButtonSize MY_ANSIARGS((EZ_Widget *widget, int *w, int *h));
void             EZ_FreeWidgetNButtonData MY_ANSIARGS((EZ_Widget *widget));
void             EZ_NButtonEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));

/*********************************************************************/
static void  set_button_border_type MY_ANSIARGS((EZ_Widget *widget, int flag));
/*********************************************************************
 * 
 *  Local Variables.
 */
static EZ_WidgetHandle EZ_ButtonHandle =
{ 
  EZ_ComputeWidgetButtonSize,
  EZ_DrawWidgetButton,
  EZ_FreeWidgetNButtonData,
  EZ_NButtonEventHandle,
};

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

EZ_Widget  *EZ_CreateButton(parent,label, underline)
     EZ_Widget  *parent;     /* parent widget    */
     char       *label;
     int        underline;     
{
  EZ_Widget  *wptr;

  wptr = EZ_CreateNewWidget(parent);
  /*--------------------------------------------------
   * Register the handling functions for Button.
   *  has to be done after  EZ_CreateNewWiget.
   *-------------------------------------------------*/
  EZ_WidgetHandlingFunctions[EZ_WIDGET_NORMAL_BUTTON] = &EZ_ButtonHandle;

  EZ_SetWidgetTypeAndNames(wptr, EZ_WIDGET_NORMAL_BUTTON);
  EZ_ButtonLabel(wptr) = EZ_AllocCopyString(label);
  EZ_ButtonLabelLength(wptr) = (label == (char *)NULL? 1 : strlen(label));
  EZ_ButtonPixmap(wptr) = (EZ_Bitmap *)NULL;
  EZ_ButtonFont(wptr) = EZ_GetFontFromId(EZ_BUTTON_FONT);
  EZ_WidgetBorderStyle(wptr)  = EZ_BORDER_UP;
  EZ_ButtonTWidth(wptr)     = 0;
  EZ_ButtonTHeight(wptr)    = 0;
  EZ_ButtonFontAscent(wptr) = 0;
  EZ_ButtonLabel2(wptr)     = (char *)NULL;
  EZ_ButtonLabel2Length(wptr) = 0;
  EZ_ButtonLabel2Width(wptr)  = 0;
  EZ_ButtonLineLength(wptr) = EZ_DEFAULT_LABEL_LINE_LENGTH;
  EZ_ButtonNLines(wptr)  = 1;
  EZ_ButtonPressed(wptr) = 0;
  EZ_ButtonNoHighlight(wptr) = 0;
  EZ_ButtonSetBorder(wptr)  = 0;
  EZ_SetWidgetFocusableFlag(wptr);
  /* special fields */
  EZ_ButtonCompanion(wptr) = NULL;
  EZ_ButtonFSB(wptr)       = NULL;

  EZ_WidgetSepX(wptr) = EZ_WIDGET_DEFAULT_PADX;
  EZ_WidgetSepY(wptr) = EZ_WIDGET_DEFAULT_PADY;
  EZ_WidgetPadB(wptr) = 2;

  if(label && underline >= 0 && underline < EZ_ButtonLabelLength(wptr) && isprint(label[underline]))
    {
      EZ_ButtonUnderLine(wptr) = underline;
      EZ_ButtonModifiers(wptr) = Mod1Mask;
      EZ_ButtonShortcut(wptr)  = (EZ_ButtonLabel(wptr) + underline);
      /*-------------------------------------------------------------
       *  Register this shortcut in the globale KeyPress event table
       *------------------------------------------------------------*/
      EZ_InsertGlobalKeyPressEvent(wptr, Mod1Mask, (label+underline));
    }
  else
    {
      EZ_ButtonUnderLine(wptr) = -1;
      EZ_ButtonModifiers(wptr) = 0;
      EZ_ButtonShortcut(wptr)  = (char *)NULL;
    }
  EZ_ButtonCopy(wptr) = NULL;
  return(wptr);
}


void   EZ_FreeWidgetNButtonData(widget)
     EZ_Widget *widget;
{
  if(EZ_ButtonLabel(widget) != (char *)NULL)
    (void) my_free((char *)EZ_ButtonLabel(widget));
  if(EZ_ButtonPixmap(widget) != (EZ_Bitmap *)NULL)
    EZ_FreeBitmap(EZ_ButtonPixmap(widget));
  if(EZ_ButtonLabel2(widget)  != (char *)NULL)
    (void) my_free((char *)EZ_ButtonLabel2(widget));
  {
    EZ_Widget *clone = EZ_ButtonCopy(widget);
    if(clone) {EZ_ButtonCopy(clone) = NULL; }
  }
}
 
/********************************************************************
 *
 *  Figure out the dimension of a normal button
 */
void EZ_ComputeWidgetButtonSize(widget, w, h)
    EZ_Widget *widget;
     int             *w, *h;
{
  int length, height, cw, ch, bw;

  if(!(EZ_GetWidgetSizeComputedFlag(widget)))
    { 
      if( EZ_ButtonPixmap(widget) == (EZ_Bitmap *)NULL)
	{
	  int nlines, twidth;

	  EZ_FigureLabelExtent(EZ_ButtonFont(widget),
			       EZ_ButtonLabel(widget),
			       (int)EZ_ButtonLabelLength(widget),
			       (int)EZ_ButtonLineLength(widget),
			       &nlines, &twidth);
	  EZ_ButtonTWidth(widget) = twidth;
	  EZ_ButtonNLines(widget) = nlines;

	  EZ_ButtonTHeight(widget) = EZ_ButtonFont(widget)->ascent +
	    EZ_ButtonFont(widget)->descent;
	  EZ_ButtonFontAscent(widget) = EZ_ButtonFont(widget)->ascent;

	  if(EZ_ButtonLabel2Length(widget) != 0)
	    {
	      EZ_ButtonLabel2Width(widget) = EZ_LABEL_SEPARATION +
		XTextWidth(EZ_ButtonFont(widget), 
			   EZ_ButtonLabel2(widget),
			   EZ_ButtonLabel2Length(widget));
	      EZ_WidgetAuxXRight(widget) = EZ_ButtonLabel2Width(widget);
	    }
	}
      else
	{
	  EZ_Bitmap *tmp = EZ_ButtonPixmap(widget);
	  EZ_ButtonNLines(widget) = 1;
	  EZ_ButtonTWidth(widget) = tmp->width;
	  EZ_ButtonTHeight(widget)= tmp->height;
	}
      EZ_SetWidgetSizeComputedFlag(widget);
    }
  length = EZ_ButtonTWidth(widget) + EZ_ButtonLabel2Width(widget);
  height = EZ_ButtonTHeight(widget) * EZ_ButtonNLines(widget);

  bw =  EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
  cw = EZ_WidgetPadX(widget) + bw;
  ch = EZ_WidgetPadY(widget) + bw;
  cw = cw + cw + length;
  ch = ch + ch + height;

  *w = cw;
  *h = ch;
}

/****************************************************************************
 *
 *  Draw a normal button.
 */

void  EZ_DrawWidgetButton(wptr)
     EZ_Widget *wptr;
{
  int             w, h,x,y,xx,yy,fillx,filly, padb, padb2, filled = 0;
  Pixmap          pixmap;
  Window          win;
  GC              gc;
  int             offset, offseta = 0;
  unsigned long   bgpv,bgpva;

  win = EZ_WidgetWindow(wptr);
  w   = EZ_WidgetWidth(wptr);
  h   = EZ_WidgetHeight(wptr);
  padb = EZ_WidgetPadB(wptr);
  padb2 = padb + padb;

  EZ_GetWidgetLabelPosition(wptr, &fillx, &filly);
  /*-----------------------------------------------------------
   *  Create a pixmap, draw into this pixmap in background and
   *  copy to the button window when finished.
   *----------------------------------------------------------*/
  pixmap = XCreatePixmap(EZ_DisplayForWidgets, win, w, h, EZ_DepthForWidgets);    
  if(padb > 0)
    {
      EZ_GetParentBgGCN(wptr, &gc,&bgpva);
      XFillRectangle(EZ_DisplayForWidgets, pixmap, gc, 0,0, w, h); 
      filled = 1;
    }
  else bgpva = 0;  
  if(EZ_ButtonNoHighlight(wptr)) EZ_ClearWidgetHighlightFlag(wptr);
  EZ_GetBackgroundGC(wptr, &gc,&bgpv,1,0);
  if(filled == 0 || bgpv != bgpva)
    {
      if(EZ_WidgetBorderStyle(wptr) == EZ_BORDER_NB_UP || EZ_WidgetBorderStyle(wptr) == EZ_BORDER_NB_DOWN)
	XFillRectangle(EZ_Display, pixmap, gc, padb,padb, w-padb2, h); 
      else
	XFillRectangle(EZ_Display, pixmap, gc, padb,padb, w-padb2, h-padb2); 
    }

  /*--------------------------------------------------------
   *  Draw the label.
   *-------------------------------------------------------*/
  xx = fillx + EZ_WidgetXOffset(wptr);
  yy = filly + EZ_WidgetYOffset(wptr);
  if(EZ_OffsetEnabled && EZ_WidgetBorderStyle(wptr) == EZ_BORDER_DOWN) offseta = 1;
  offset = offseta + padb;
  
  x = xx + EZ_WidgetPadX(wptr) + EZ_WidgetBorderWidth(wptr) + offset;
  y = yy + EZ_ButtonFontAscent(wptr) + EZ_WidgetBorderWidth(wptr) + EZ_WidgetPadY(wptr) + offset;

  if(EZ_ButtonPixmap(wptr) == (EZ_Bitmap *)NULL)
    {
      if( EZ_GetWidgetDisabledFlag(wptr) )
	{
	  GC  bgc, lgc, ngc;
	  EZ_GetDarkBrightNormalBDGC(wptr, &bgc, &lgc, &ngc);
	  XSetFont(EZ_DisplayForWidgets, bgc, EZ_WidgetFont(wptr)->fid);
	  XSetFont(EZ_DisplayForWidgets, lgc, EZ_WidgetFont(wptr)->fid);
	  XSetFont(EZ_DisplayForWidgets, ngc, EZ_WidgetFont(wptr)->fid);

	  EZ_RenderLabelTextDisabled(pixmap, lgc, bgc, ngc, x, y, 
				     (int)EZ_ButtonTHeight(wptr), EZ_ButtonLabel(wptr),
				     (int)EZ_ButtonLabelLength(wptr), (int)EZ_ButtonLineLength(wptr),
				     (int)EZ_ButtonNLines(wptr),
				     (int)EZ_ButtonTWidth(wptr),
				     (int)EZ_WidgetJustification(wptr),
				     EZ_ButtonFont(wptr));

	}
      else
	{
	  if(EZ_ButtonForeground(wptr) != EZ_DefaultForeground || 
	     EZ_ButtonFont(wptr) != EZ_GetFontFromId(EZ_BUTTON_FONT))
	    {
	      XSetFont(EZ_DisplayForWidgets,  EZ_WRITABLEGC, EZ_ButtonFont(wptr)->fid);
	      XSetForeground(EZ_DisplayForWidgets, EZ_WRITABLEGC, EZ_ButtonForeground(wptr));
	      gc =  EZ_WRITABLEGC;
	    }
	  else 
	    gc = EZ_BUTTON_TEXTGC;

	  EZ_RenderLabelText(pixmap, gc, x, y, 
			     (int)EZ_ButtonTHeight(wptr), EZ_ButtonLabel(wptr),
			     (int)EZ_ButtonLabelLength(wptr), (int)EZ_ButtonLineLength(wptr),
			     (int)EZ_ButtonNLines(wptr),
			     (int)EZ_ButtonTWidth(wptr),
			     (int)EZ_WidgetJustification(wptr),
			     EZ_ButtonFont(wptr));
	  if(EZ_ButtonLabel2Length(wptr) != 0)
	    {
	      int tmpx;
	      tmpx = EZ_GetLabel2XPosition(wptr,
					   EZ_ButtonLabel2Width(wptr) -
					   EZ_LABEL_SEPARATION, offseta);
	  
	      XDrawString(EZ_DisplayForWidgets, 
			  pixmap,  gc,
			  tmpx, ((h+EZ_ButtonFontAscent(wptr))>>1) + offseta,
			  EZ_ButtonLabel2(wptr),
			  EZ_ButtonLabel2Length(wptr));
	    }
	  else if(EZ_ButtonUnderLine(wptr) >= 0 && 
		  EZ_ButtonUnderLine(wptr) < ((int)EZ_ButtonLineLength(wptr)>>1))
	    {
	      int tlen = XTextWidth(EZ_ButtonFont(wptr),EZ_ButtonLabel(wptr),
				    EZ_ButtonUnderLine(wptr));
	      int tlen1 = tlen + XTextWidth(EZ_ButtonFont(wptr),
					    EZ_ButtonLabel(wptr)+EZ_ButtonUnderLine(wptr), 1);
	      int base = y + EZ_ButtonTHeight(wptr) - EZ_ButtonFontAscent(wptr)-1;
	      int boldfont;

	      if(EZ_ButtonFont(wptr) != EZ_GetFontFromId(EZ_BUTTON_FONT))
		boldfont = (EZ_GetWidgetThinFontFlag(wptr) == 0);
	      else boldfont = EZ_LabelFontIsBold;
	      
	      XDrawLine(EZ_DisplayForWidgets, pixmap, gc,
			x+tlen, base, x+tlen1, base);
	      if(boldfont)
		XDrawLine(EZ_DisplayForWidgets, pixmap, gc,
			  x+tlen, base+1, x+tlen1, base+1);
	    }
	}
    }
  else    /* copy the pixmap */
    {
      EZ_Bitmap *tmp = EZ_ButtonPixmap(wptr);
      EZ_RenderPixmapLabel(wptr, tmp, pixmap, x, y - (int) (EZ_ButtonFontAscent(wptr)));
    }

  /*============================================================
   *for complex button with  NW labels 
   */
  {
    EZ_Widget *children = EZ_WidgetChildren(wptr);
    if(children && EZ_WidgetType(children) == EZ_WIDGET_NW_LABEL)
      {
	EZ_DisplayNWLabel(children, pixmap, EZ_WidgetForeground(wptr), bgpv,
			  EZ_GetWidgetDisabledFlag(wptr),EZ_GetWidgetHighlightFlag(wptr),
			  0, 0, offseta, 1);
      }
  }
  /*============================================================*/  
  
  EZ_DrawRectBorder(wptr, pixmap);
  XCopyArea(EZ_DisplayForWidgets,pixmap,win, EZ_WRITABLEGC,0,0,w,h,0,0);  
  XFreePixmap(EZ_DisplayForWidgets, pixmap);                             
}

/*************************************************************************
 *
 *  Event handling
 */


void  EZ_NButtonEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent          *event;
{
  int x, y;
  if(widget == (EZ_Widget *)NULL)   return;

  if(event->type == Expose)   EZ_DrawWidget(widget);      
  if( EZ_GetWidgetDisabledFlag(widget) )  return;

  switch(event->type)
    {
    case ButtonPress:
      if(event->xbutton.button == EZ_Btn1)
	{
	  EZ_ButtonPressed(widget) = 1;
	  set_button_border_type(widget, 1);
	  EZ_DrawWidget(widget);
	}
      else if(event->xbutton.button == EZ_Btn3)
	{
#include "EZ_DnDHandler1.c"
	  EZ_DnDEventHandler1(widget, event);
	}
      break;
    case ButtonRelease:
      if(event->xbutton.button == EZ_Btn1)
	{
	  if(EZ_ButtonPressed(widget))
	    {
	      EZ_ButtonPressed(widget) = 0;
	      set_button_border_type(widget, 0);
	      EZ_DrawWidget(widget);
	      x = event->xbutton.x;
	      y = event->xbutton.y;
	      if( x >=0 && x <= EZ_WidgetWidth(widget) && y >= 0 &&
		  y <= EZ_WidgetHeight(widget))
		{ EZ_ExecuteWidgetCallBacks(widget);}
	    }
	}
      break;
    case EnterNotify:
      if(EZ_ButtonPressed(widget) == 1)
	set_button_border_type(widget, 1);
      EZ_SetWidgetHighlightFlag(widget);
      EZ_DrawWidget(widget);
      break;
    case LeaveNotify:
      set_button_border_type(widget, 0);
      EZ_ClearWidgetHighlightFlag(widget);
      EZ_DrawWidget(widget);
      break;
    default:
      break;
    }
}
/****************************************************************/
static void  set_button_border_type(widget, flag)
     EZ_Widget *widget;
     int flag;
{
  if(flag)
    {
      EZ_ButtonSetBorder(widget) = 1;
      switch(EZ_WidgetBorderStyle(widget))
	{
	case EZ_BORDER_UP:
	  EZ_WidgetBorderStyle(widget) = EZ_BORDER_DOWN;
	  break;
	case EZ_BORDER_FRAMED_UP:
	  EZ_WidgetBorderStyle(widget) = EZ_BORDER_FRAMED_DOWN;
	  break;
	case EZ_BORDER_NB_UP:
	  EZ_WidgetBorderStyle(widget) = EZ_BORDER_NB_DOWN;
	  break;
	case EZ_BORDER_FRAMED:
	  EZ_WidgetBorderStyle(widget) = EZ_BORDER_CARVED;
	  break;
	default:
	  EZ_ButtonSetBorder(widget) = 0;
	  break;
	}
    }
  else
    {
      if(EZ_ButtonSetBorder(widget))
	{
	  switch(EZ_WidgetBorderStyle(widget))
	    {
	    case EZ_BORDER_DOWN:
	      EZ_WidgetBorderStyle(widget) = EZ_BORDER_UP;
	      break;
	    case EZ_BORDER_FRAMED_DOWN:
	      EZ_WidgetBorderStyle(widget) = EZ_BORDER_FRAMED_UP;
	      break;
	    case EZ_BORDER_NB_DOWN:
	      EZ_WidgetBorderStyle(widget) = EZ_BORDER_NB_UP;
	      break;
	    case EZ_BORDER_CARVED:
	      EZ_WidgetBorderStyle(widget) = EZ_BORDER_FRAMED;
	      break;
	    default:
	      break;
	    }
	}
    }
}
/********************************************************************************/
#undef _EZ_WIDGET_BUTTONN_C_
