/*********************************************************************
 *
 *         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 Frame.                                ***
 ***                                                           ***
 *****************************************************************/
#define _EZ_WIDGET_FRAME_C_
#include "EZ_Widget.h"

/*********************************************************************
 * 
 *  Functions implemented in this file:
 */
EZ_Widget         *EZ_CreateFrame MY_ANSIARGS((EZ_Widget *parent, char *label));
void              EZ_DrawWidgetFrame  MY_ANSIARGS((EZ_Widget *widget));
void              EZ_FreeWidgetFrameData MY_ANSIARGS((EZ_Widget *widget));
void              EZ_FrameEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));
void              EZ_ComputeWidgetFrameSize MY_ANSIARGS((EZ_Widget *widget, int *w, int *h));

/*********************************************************************
 * 
 *  Local Variables.
 */
static EZ_WidgetHandle EZ_FrameHandle =
{ 
  EZ_ComputeWidgetFrameSize,
  EZ_DrawWidgetFrame,
  EZ_FreeWidgetFrameData,
  EZ_FrameEventHandle,
};

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

EZ_Widget  *EZ_CreateFrame(parent,label)
     EZ_Widget  *parent;     /* parent widget    */
     char       *label;
{
  EZ_Widget  *tmp;

  tmp = EZ_CreateNewWidget(parent);
  /*--------------------------------------------------
   * Register the handling functions for Frame.
   *  has to be done after  EZ_CreateNewWiget.
   *-------------------------------------------------*/
  EZ_WidgetHandlingFunctions[EZ_WIDGET_FRAME] = &EZ_FrameHandle;

  EZ_SetWidgetTypeAndNames(tmp,EZ_WIDGET_FRAME);
  EZ_WidgetBorderWidth(tmp) = 0;
  EZ_WidgetPadB(tmp) = 0;
  EZ_WidgetBorderStyle(tmp)  = EZ_BORDER_NONE;;
  EZ_FramePixmap(tmp) = (EZ_Bitmap *)NULL;
  EZ_FrameFont(tmp) = EZ_GetFontFromId(EZ_LABEL_FONT);  
  EZ_FrameLabel(tmp) = EZ_AllocCopyString(label);
  EZ_FrameLabelLength(tmp) = (label == (char *)NULL ? 0 : strlen(label));
  EZ_FrameLineLength(tmp) = EZ_DEFAULT_LABEL_LINE_LENGTH;
  EZ_FrameNLines(tmp) = 1; 
  EZ_FrameTWidth(tmp) = 0;
  EZ_FrameTHeight(tmp) = 0;
  EZ_FrameFontAscent(tmp)= 0;
  EZ_FrameXIndent(tmp) = EZ_WIDGET_DEFAULT_PADX;
  EZ_FrameYIndent(tmp) = EZ_WIDGET_DEFAULT_PADY;
  EZ_FrameHasLabel(tmp) = 0;
  EZ_FrameWAdjust(tmp) = 0;

  EZ_FrameIntBdWidth(tmp) = 1;
  EZ_FrameIntBdType(tmp)  = EZ_BORDER_FRAMED_DOWN;
  EZ_FrameBrokenIntBdLength(tmp) = 0;

  return(tmp);
}

void   EZ_FreeWidgetFrameData(widget)
     EZ_Widget *widget;
{
  if(EZ_FramePixmap(widget) != (EZ_Bitmap *)NULL)
    EZ_FreeBitmap(EZ_FramePixmap(widget));
  if(EZ_FrameLabel(widget) != (char *)NULL)
    (void)my_free( (char *) EZ_FrameLabel(widget));
}
/*******************************************************************
 *
 * Compute Frame size.
 */
void  EZ_ComputeWidgetFrameSize(widget, w,h)
     EZ_Widget *widget;
     int             *w, *h;
{
  int cw, ch, tmp, width, height, lab_padx = 0, lab_pady = 0, adjust = 0;

  if(!(EZ_GetWidgetSizeComputedFlag(widget)))
    {
      EZ_Bitmap *bitmap = EZ_FramePixmap(widget);
      char      *label =  EZ_FrameLabel(widget);

      if( bitmap || (label && *label))  /* frame has a label */
	{
	  EZ_FrameHasLabel(widget) = 1;
	  adjust = 6;
	  if(bitmap == (EZ_Bitmap *)NULL)
	    {
	      int nlines, twidth;
	      int labelLen = EZ_FrameLabelLength(widget);

	      if(labelLen < 2 && *label == ' ')
		{
		  EZ_FrameTWidth(widget) = 0;
		  EZ_FrameNLines(widget) = 0;
		  EZ_FrameTHeight(widget) = 0;
		}
	      else
		{
		  EZ_FigureLabelExtent(EZ_FrameFont(widget),
				       EZ_FrameLabel(widget),
				       (int)EZ_FrameLabelLength(widget),
				       (int)EZ_FrameLineLength(widget),
				       &nlines, &twidth);
		  EZ_FrameTWidth(widget) = twidth;
		  EZ_FrameNLines(widget) = nlines;
		  EZ_FrameTHeight(widget) = (EZ_FrameFont(widget)->ascent +
					     EZ_FrameFont(widget)->descent);
		  EZ_FrameFontAscent(widget) = EZ_FrameFont(widget)->ascent;
		}
	    }
	  else
	    {
	      EZ_FrameNLines(widget) = 1;
	      EZ_FrameTWidth(widget) =  bitmap->width;
	      EZ_FrameTHeight(widget)=  bitmap->height;
	    }
	  tmp = EZ_FrameIntBdWidth(widget) + 1;
	  lab_padx = EZ_FrameXIndent(widget) + tmp;
	  lab_pady = EZ_FrameYIndent(widget) + tmp;
	  EZ_WidgetHAdjust(widget) = EZ_FrameTHeight(widget) * EZ_FrameNLines(widget);
	}
      else  /* a regular frame */
	{ 
	  EZ_FrameHasLabel(widget) = 0;
	  EZ_FrameTWidth(widget) =  0;
	  EZ_FrameTHeight(widget)=  0;
	  EZ_WidgetAuxXLeft(widget) = 0;
	  EZ_WidgetAuxXRight(widget) = 0;
	  EZ_WidgetAuxY(widget) = 0;
	  EZ_WidgetHAdjust(widget) = 0;
	}
      EZ_FrameWAdjust(widget) = adjust;
      EZ_WidgetAuxXLeft(widget) = lab_padx;
      EZ_WidgetAuxXRight(widget) = lab_padx;
      EZ_WidgetAuxY(widget) = lab_pady;
      EZ_SetWidgetSizeComputedFlag(widget);
    }
  
  width = EZ_FrameTWidth(widget) + EZ_FrameWAdjust(widget);
  height= EZ_FrameTHeight(widget) * EZ_FrameNLines(widget);

  tmp = EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
  cw = EZ_WidgetPadX(widget) + tmp + EZ_WidgetAuxXLeft(widget);
  ch = EZ_WidgetPadY(widget) + tmp + EZ_WidgetAuxY(widget);

  *w = cw + cw + width;
  *h = ch + ch + height;
}
/*******************************************************************
 *
 *  Draw A Frame Widget. 
 */
void  EZ_DrawWidgetFrame(wptr)
     EZ_Widget *wptr;
{
  int             w, h, x,y, padb, padb2, filled = 0;
  Pixmap          pixmap;
  Window          win;
  GC              gc;
  unsigned long   bgpv, bgpva;

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

  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;  
  EZ_GetBackgroundGC(wptr, &gc,&bgpv, 0, 0);
  if(filled == 0 || bgpv != bgpva)
    XFillRectangle(EZ_DisplayForWidgets, pixmap, gc, padb,padb, w-padb2, h-padb2); 
  
  if(EZ_FrameHasLabel(wptr)) /* a labeled frame */
    {
      int xoff, yoff, ytmp, wtmp, htmp, itmp;
      
      itmp = EZ_WidgetBorderWidth(wptr) + padb;
      xoff = EZ_FrameXIndent(wptr) + itmp;
      yoff = EZ_FrameYIndent(wptr) + itmp;
      ytmp = (EZ_FrameTHeight(wptr) * EZ_FrameNLines(wptr)) >> 1;

      x = xoff;
      y = ytmp + yoff;
      wtmp = w - (xoff << 1);
      htmp = h - (yoff << 1) - ytmp;

      EZ_DrawRectBorderWithSize(wptr, pixmap, x,y,wtmp,htmp,
				(int)EZ_FrameIntBdWidth(wptr),
				(int)EZ_FrameIntBdType(wptr));

      /* find the place to render the label */

      switch(EZ_WidgetLabelPosition(wptr))
	{
	case EZ_CENTER:
	  x = ((w - (EZ_FrameTWidth(wptr)+6 )) >> 1);
	  break;
	case EZ_RIGHT:
	  x = w - (EZ_FrameTWidth(wptr)+6 + xoff + EZ_WidgetPadX(wptr));
	  x -= EZ_FrameIntBdWidth(wptr);
	  break;
	case EZ_LEFT:
	default:
	  x +=  EZ_WidgetPadX(wptr);
	  x += EZ_FrameIntBdWidth(wptr);
	  break;
	}

      /*
       * Now render the label.
       */
      if(EZ_FramePixmap(wptr) == (EZ_Bitmap *)NULL)  /* textual label */
	{
	  char *label = EZ_FrameLabel(wptr);
	  int labelLen =  EZ_FrameLabelLength(wptr);
	  if(labelLen >= 2 || *label != ' ') 
	    {
	      /*
	       * fix the border. The piece under the label should be erased 
	       */
	      XFillRectangle(EZ_Display, pixmap, gc, 
			     x,
			     y - 1, 
			     (int)(EZ_FrameTWidth(wptr)+6),
			     (int)(EZ_FrameIntBdWidth(wptr) + 2));
      
	      x += 3;

	      if(EZ_FrameForeground(wptr) != EZ_DefaultForeground ||
		 EZ_FrameFont(wptr) != EZ_GetFontFromId(EZ_LABEL_FONT))
		{
		  XSetFont(EZ_Display, EZ_WRITABLEGC, EZ_FrameFont(wptr)->fid);
		  XSetForeground(EZ_Display, EZ_WRITABLEGC, EZ_FrameForeground(wptr));
		  gc = EZ_WRITABLEGC;
		}
	      else  gc = EZ_LABEL_TEXTGC;

	      y = EZ_FrameFontAscent(wptr) + yoff;
	      EZ_RenderLabelText(pixmap, gc, x, y, (int)EZ_FrameTHeight(wptr),
				 EZ_FrameLabel(wptr),
				 (int)EZ_FrameLabelLength(wptr), 
				 (int)EZ_FrameLineLength(wptr),
				 (int)EZ_FrameNLines(wptr),
				 (int)EZ_FrameTWidth(wptr),
				 (int)EZ_WidgetJustification(wptr),
				 EZ_FrameFont(wptr));
	    }
	}
      else  /* bitmap label */
	{
	  EZ_Bitmap *tmp = EZ_FramePixmap(wptr);
	  /*
	   * fix the border. The piece under the label should be erased 
	   */
	  XFillRectangle(EZ_Display, pixmap, gc, 
			 x,
			 y - 1, 
			 (int)(EZ_FrameTWidth(wptr)+6),
			 (int)(EZ_FrameIntBdWidth(wptr) + 2));
	  x += 3;
	  y = yoff;
	  EZ_RenderPixmapLabel(wptr, tmp, pixmap, x, y);
	}
    }
  /*============================================================
   * for menubars
   */
  {
    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, 0, 1);
      }
  }
  /*============================================================*/  


  EZ_DrawRectBorder(wptr, pixmap); 
  XCopyArea(EZ_Display,pixmap,win, EZ_WRITABLEGC,0,0,w,h,0,0); 
  XFreePixmap(EZ_Display, pixmap); 
}

/*******************************************************************
 *
 *  Event handle
 */

void EZ_FrameEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent *event;
{
  if(widget)
    {
      if(event->type == Expose) EZ_DrawWidget(widget);      
      else if(event->type == ButtonPress)
	{
	  if(event->xbutton.button == EZ_Btn1)
	    { EZ_ExecuteWidgetCallBacks(widget);}
	  else if(event->xbutton.button == EZ_Btn3)
	    {
#include "EZ_DnDHandler1.c"
	      EZ_DnDEventHandler1(widget, event);
	    }
	}
    }
}

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

#undef _EZ_WIDGET_FRAME_C_
