/**************************************************************************\
 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 "islider.h"

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

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

void ISlider::Init(char *t, IWindow *w, int xp, int yp, int xs, int ys)  {
  changecallback = NULL;
  text = new char[strlen(t)+2];
  sprintf(text, "%s%c", t, 0);
  value = 0;
  min = 0;
  max = 101;
  xpos = xp; ypos = yp; xsize = xs; ysize = ys;
  Win = w;
  Window wind = w->GetWindowBuffer();
  Display *disp = w->GetDisplay();
  unsigned int s, p, b, g, gl, gd;
  
  Img[0] = XCreatePixmap(disp, wind, xs, ys, DefaultDepth(disp, 0));
  Img[1] = XCreatePixmap(disp, wind, xs, ys, DefaultDepth(disp, 0));

  GC gc = Win->GetGC();

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

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

  XSetForeground(disp, gc, gl);
  XFillRectangle(disp, Img[0], gc, 0, 0, xs, ys);
  XFillRectangle(disp, Img[1], gc, 0, 0, xs, ys);

  XSetForeground(disp, gc, g);
  XFillRectangle(disp, Img[0], gc, 2, 2, xs-4, ys-4);
  XFillRectangle(disp, Img[1], gc, 2, 2, xs-4, ys-4);

  XSetForeground(disp, gc, gd);
  XFillRectangle(disp, Img[0], gc, 0, 0, xs-1, 2);
  XFillRectangle(disp, Img[0], gc, 0, 2, 2, ys-3);
  XDrawPoint(disp, Img[0], gc, 0, ys-1);
  XDrawPoint(disp, Img[0], gc, xs-1, 0);
  XFillRectangle(disp, Img[1], gc, 0, 0, xs-1, 2);
  XFillRectangle(disp, Img[1], gc, 0, 2, 2, ys-3);
  XDrawPoint(disp, Img[1], gc, 0, ys-1);
  XDrawPoint(disp, Img[1], gc, xs-1, 0);

  disabled = 0;
  parent=NULL;

  w->AddClaim(this, xp, yp, xs, ys);

  Rebuild();
  }

void ISlider::Redraw()  {
  if(hidden) { Win->Rebuild(xpos, ypos, xsize, ysize); return; }

  XCopyArea(Win->GetDisplay(), Img[disabled], Win->GetWindowBuffer(), Win->GetGC(),
	0, 0, xsize, ysize, xpos, ypos);
  Win->Redraw(xpos, ypos, xsize, ysize);
  }

void ISlider::Rebuild()  {
  Window w = Win->GetWindowBuffer();
  Display *disp = Win->GetDisplay();
  GC gc = Win->GetGC();
  char txt[256];
  if(max > min && value >= min)
    sprintf(txt, "%s%d%c", text, value, 0);
  XFontStruct *fs;
  XCharStruct cs;
  int dir, as, des;
  fs = Win->GetFontStruct();
  XTextExtents(fs, txt, strlen(txt), &dir, &as, &des, &cs);
  int len = cs.width;

  // Enabled
  XSetForeground(disp, gc, Win->GetBGColor());
  XFillRectangle(disp, Img[0], gc, 2, 2, xsize-4, ysize-4);

  // Disabled
  XSetForeground(disp, gc, Win->GetLBGColor());
  XFillRectangle(disp, Img[1], gc, 2, 2, xsize-4, ysize-4);

  // Enabled
  XSetBackground(disp, gc, Win->GetBGColor());
  XSetForeground(disp, gc, Win->GetFGColor());
  XDrawImageString(disp, Img[0], gc, (xsize-(len-1))>>1,
		   (ysize+ysize-(as+des-2))>>1, txt, strlen(txt));

  // Disabled
  XSetBackground(disp, gc, Win->GetLBGColor());
  XSetForeground(disp, gc, Win->GetDBGColor());
  XDrawImageString(disp, Img[1], gc, (xsize-(len-1))>>1,
		   (ysize+ysize-(as+des-2))>>1, txt, strlen(txt));



  if(max > min && (((value-min)*(xsize-4))/(max-min)) > 0)  {
    int xbar = (xsize-4) <? (((value-min)*(xsize-4))/(max-min));
    Wrk[0] = XCreatePixmap(disp, w, xbar, ysize-4, DefaultDepth(disp, 0));
    Wrk[1] = XCreatePixmap(disp, w, xbar, ysize-4, DefaultDepth(disp, 0));

    // Enabled
    XSetForeground(disp, gc, Win->GetSelectColor());
    XFillRectangle(disp, Wrk[0], gc, 0, 0, xbar, ysize-4);
    XSetForeground(disp, gc, Win->GetPaperColor());
    XSetBackground(disp, gc, Win->GetSelectColor());
    XDrawImageString(disp, Wrk[0], gc, ((xsize-(len-1))>>1)-2,
	((ysize+ysize-(as+des-2))>>1)-2, txt, strlen(txt));

    // Disabled
    XSetForeground(disp, gc, Win->GetBGColor());
    XFillRectangle(disp, Wrk[1], gc, 0, 0, xbar, ysize-4);
    XSetForeground(disp, gc, Win->GetDBGColor());
    XSetBackground(disp, gc, Win->GetBGColor());
    XDrawImageString(disp, Wrk[1], gc, ((xsize-(len-1))>>1)-2,
	((ysize+ysize-(as+des-2))>>1)-2, txt, strlen(txt));

    XCopyArea(disp, Wrk[disabled], Img[disabled], gc, 0, 0, xbar, ysize-4, 2, 2);
    XFreePixmap(disp, Wrk[0]);
    XFreePixmap(disp, Wrk[1]);
    }
  Redraw();
  if(!hidden) Win->Rebuild(xpos, ypos, xsize, ysize);
  }

int ISlider::Drag(int x, int y) {
  if(disabled) return 0;
  Press(1, x, y);
  return 1;
  }

int ISlider::Press(int b, int x, int y) {
  if(disabled) return 0;
  if(x<2) x=2;
  if(x>xsize-2) x=xsize-2;
  value = x-2;
  value *= (max-min);
  value /= (xsize-4);
  value += min;
  SetValue(value);
  return 1;
  }

void ISlider::SetChangeCallback(void (*cb)(IDoDad *, IDoDad *, int))  {
  changecallback = cb;
  if(changecallback != NULL) (*changecallback)(parent, this, value);
  }

void ISlider::SetValue(int v)  {
  if(disabled) return;
  value = v;
  if(value>max) value=max;
  if(value<min) value=min;
  Rebuild();
  if(changecallback != NULL) (*changecallback)(parent, this, value);
  }

void ISlider::Enable()  {
  disabled = 0;
  Rebuild();
  }

void ISlider::Disable()  {
  disabled = 1;
  Rebuild();
  }
