/**************************************************************************\
 ibtk (Insomnia's Basic ToolKit)

  By Insomnia (Steaphan Greene)
  (insomnia@core.binghamton.edu)

  Copyright (C) 1999 Steaphan Greene

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.

\**************************************************************************/

#include <stdio.h>
#include <string.h>

#include "ibutton.h"

IButton::~IButton()  {
  Win->RemoveClaim(this);
  }

IButton::IButton(char *txt, IWindow *w, int xp, int yp, int xs, int ys)  {
  Init(txt, w, xp, yp, xs, ys);
  }

void IButton::Init(char *txt, IWindow *w, int xp, int yp, int xs, int ys)  {
  text = new char[strlen(txt)+2];
  sprintf(text, "%s%c", txt, 0);
  xpos = xp; ypos = yp; xsize = xs; ysize = ys;
  Win = w;
  Img[0] = None;  Img[1] = None;  Img[2] = None;
  state = BUTTON_UP;
  clickcallback=NULL;
  upcallback=NULL;
  downcallback=NULL;
  parent=NULL;
  Create();
  }

void IButton::Create()  {
  Window wind = Win->GetWindowBuffer();
  Display *disp = Win->GetDisplay();
  unsigned int p, b, g, gl, gd;
  if(Img[0] != None)  XFreePixmap(disp, Img[0]);
  if(Img[1] != None)  XFreePixmap(disp, Img[1]);
  if(Img[2] != None)  XFreePixmap(disp, Img[2]);
  Img[0] = XCreatePixmap(disp, wind, xsize, ysize, DefaultDepth(disp, 0));
  Img[1] = XCreatePixmap(disp, wind, xsize, ysize, DefaultDepth(disp, 0));
  Img[2] = XCreatePixmap(disp, wind, xsize, ysize, DefaultDepth(disp, 0));
  GC gc = Win->GetGC();

//  printf("Depth = %d\n", DefaultDepth(disp, 0));

  p = Win->GetPaperColor();
  b = Win->GetFGColor();
  g = Win->GetBGColor();
  gl = Win->GetLBGColor();
  gd = Win->GetDBGColor();

  XSetForeground(disp, gc, gd);
  XFillRectangle(disp, Img[0], gc, 0, 0, xsize, ysize);
  XFillRectangle(disp, Img[1], gc, 0, 0, xsize, ysize);
  XFillRectangle(disp, Img[2], gc, 0, 0, xsize, ysize);

  XSetForeground(disp, gc, g);
  XFillRectangle(disp, Img[0], gc, 2, 2, xsize-4, ysize-4);
  XFillRectangle(disp, Img[1], gc, 3, 3, xsize-4, ysize-4);
  XFillRectangle(disp, Img[2], gc, 2, 2, xsize-4, ysize-4);

  XSetForeground(disp, gc, gl);
  XFillRectangle(disp, Img[0], gc, 0, 0, xsize-1, 2);
  XFillRectangle(disp, Img[0], gc, 0, 2, 2, ysize-3);
  XDrawPoint(disp, Img[0], gc, 0, ysize-1);
  XDrawPoint(disp, Img[0], gc, xsize-1, 0);
  XFillRectangle(disp, Img[1], gc, xsize-1, 2, 1, ysize-2);
  XFillRectangle(disp, Img[1], gc, 2, ysize-1, xsize-2, 1);
  XFillRectangle(disp, Img[2], gc, 0, 0, xsize-1, 2);
  XFillRectangle(disp, Img[2], gc, 0, 2, 2, ysize-3);
  XDrawPoint(disp, Img[2], gc, 0, ysize-1);
  XDrawPoint(disp, Img[2], gc, xsize-1, 0);

  XFontStruct *fs;
  XCharStruct cs;
  int dir, as, des;
  fs = Win->GetFontStruct();
//  XLoadQueryFont(disp, "Helvetica");
//  int len = XTextWidth(fs, text, strlen(text));
  XTextExtents(fs, text, strlen(text), &dir, &as, &des, &cs);
//  printf("dir = %d, as = %d, des = %d\n", dir, as, des);
  int len = cs.width;
//  int hgt = cs.
  XSetBackground(disp, gc, g);
  XSetForeground(disp, gc, b);
  XDrawImageString(disp, Img[0], gc, (xsize-(len-1))>>1, ((ysize+as+des)>>1)-des,
	text, strlen(text));
  XDrawImageString(disp, Img[1], gc, ((xsize-(len-1))>>1)+1, ((ysize+as+des)>>1)+1-des,
	text, strlen(text));
  XSetForeground(disp, gc, gl);
  XDrawString(disp, Img[2], gc, ((xsize-(len-1))>>1)+1, ((ysize+as+des)>>1)+1-des,
	text, strlen(text));
  XSetForeground(disp, gc, gd);
  XDrawString(disp, Img[2], gc, (xsize-(len-1))>>1, ((ysize+as+des)>>1)-des,
	text, strlen(text));

  Win->AddClaim(this, xpos, ypos, xsize, ysize);

  Redraw();
  }

void IButton::Rebuild()  {
  Redraw();
  }

void IButton::Redraw()  {
  if(!hidden) {
    XCopyArea(Win->GetDisplay(), Img[state<?2], Win->GetWindowBuffer(), Win->GetGC(),
	0, 0, xsize, ysize, xpos, ypos);
    Win->Redraw(xpos, ypos, xsize, ysize);
    }
  else {
    Win->Rebuild(xpos, ypos, xsize, ysize);
    }
  }

void IButton::Disable()  {
  if(state < 2) state += 2;
  Redraw();
  }

void IButton::Enable()  {
  if(state >= 2) state -= 2;
  Redraw();
  }

int IButton::Press(int b, int x, int y)  {
  if(state == 2) return 0;
  state = 1;
  Redraw();
  if(downcallback != NULL)  (*downcallback)(parent, this, b);
  return 1;
  }

int IButton::Release(int b, int x, int y)  {
  if(state == 2) return 0;
  state = 0;
  Redraw();
  if(b != 0 && clickcallback != NULL)  (*clickcallback)(parent, this, b);
  if(upcallback != NULL)  (*upcallback)(parent, this, b);
  return 1;
  }

void IButton::SetClickCallback(void (*cb)(IDoDad *, IDoDad *, int))  {
  clickcallback = cb;
  }

void IButton::SetUpCallback(void (*cb)(IDoDad *, IDoDad *, int))  {
  upcallback = cb;
  }

void IButton::SetDownCallback(void (*cb)(IDoDad *, IDoDad *, int))  {
  downcallback = cb;
  }

void IButton::Resize(int xs, int ys)  {
  xsize = xs; ysize = ys;
  Create();
  }

void IButton::Move(int xp, int yp)  {
  xpos = xp; ypos = yp;
  Create();
  }

void IButton::MoveAndResize(int xp, int yp, int xs, int ys)  {
  xsize = xs; ysize = ys; xpos = xp; ypos = yp;
//  printf("MoveAndResize(%d, %d, %d, %d)\n", xp, yp, xs, ys);
  Create();
  }
