#include "drawarea.h"

@implementation WDCDrawArea

static GC _gc_;

- setGC:(GC)gc
{
  _gc_=gc;
  return self;
}

- setGC
{
  if (!_gc_){
    [self setGC:XCreateGC([self getDisplay],
			  RootWindowOfScreen(XtScreen([self getWidget])),
			  0 ,NULL)];
    XSetForeground([self getDisplay], [self getGC],
		   BlackPixelOfScreen(XtScreen([self getWidget])));
  }
  return self;
}

- initWithName:(char*)aName managedBy:anObject
{
  [super initWithName:aName managedBy:anObject];
  [self setGC];
  return self;
}

- (GC)getGC
{
  return _gc_;
}

- setPixmap
{
  Dimension width, height;
  Widget widget=[self getWidget];
  Display* dspy=[self getDisplay];
  [self getArg:"width" into:&width];
  [self getArg:"height"into:&height];
  // printf("width %d height %d\n", width, height);
  _pixmap=XCreatePixmap(dspy, 
			RootWindowOfScreen(XtScreen(widget)),
			width, height,
			DefaultDepthOfScreen(XtScreen(widget)));
  XSetForeground(dspy,[self getGC],WhitePixelOfScreen(XtScreen(widget)));
  XFillRectangle(dspy,[self getPixmap],[self getGC],0,0,width,height); 
  XSetForeground(dspy,[self getGC],BlackPixelOfScreen(XtScreen(widget)));
  return self;
}

- (Pixmap)getPixmap
{
  return _pixmap?_pixmap:[[self setPixmap] getPixmap];
}

- (WidgetClass)getWidgetClass
{
  return xmDrawingAreaWidgetClass;
}

- setDisplay:(Display*)display
{
  _display=display;
  return self;
}

- setWindow:(Window)window
{
  _window=window;
  return self;
}

- (Display*)getDisplay
{
  return _display?_display:(_display=[super getDisplay]);
}

- (Window)getWindow
{
  return _window?_window:(_window=[super getWindow]);
}

- setCallData:(XtPointer)aCall_data
{
  Position i;
  XmDrawingAreaCallbackStruct *aCall_data_ptr
    =(XmDrawingAreaCallbackStruct*)aCall_data;
  _call_data.reason=aCall_data_ptr->reason;
  _call_data.event=aCall_data_ptr->event;
  _call_data.window=aCall_data_ptr->window;
  return self;
}

- setAction
{
  XtAddCallback([self getWidget], XmNinputCallback, theCallback, self);  
  XtAddCallback([self getWidget], XmNexposeCallback, theCallback, self);  
  XtAddCallback([self getWidget], XmNresizeCallback, theCallback, self);    
  return self;
}

- manageChild
{
  id child=[self getChildObject];
  if ([child isKindOfClassNamed:"WDCMenu"])
    {
      // to position a menu according to the button pressed position.
      XmMenuPosition([child getWidget], _call_data.event);
    }
  [child manage];
  return self;
}

- drawCString:(char*)aCString at:(int)x :(int)y
{
  XDrawString([self getDisplay], [self getWindow], 
	      [self getGC], x, y, aCString, strlen(aCString));
  XDrawString([self getDisplay], [self getPixmap], 
	      [self getGC], x, y, aCString, strlen(aCString));
  return self;
}

- redraw
{
  return [self notImplemented:_cmd];
}

- refresh
{
  Dimension width, height;
  [self getArg:"width" into:&width];
  [self getArg:"height" into:&height];
  XCopyArea([self getDisplay], [self getPixmap], 
	    _call_data.event->xany.window, [self getGC], 0, 0,
	    width, height, 0, 0);
  return self;
}

- clear
{
  Dimension width, height;
  Display* dspy=[self getDisplay];
  Widget widget=[self getWidget];
  [self getArg:"width" into:&width];
  [self getArg:"height" into:&height];
  // printf("width %d height %d\n", width, height);
  XSetForeground(dspy,[self getGC],WhitePixelOfScreen(XtScreen(widget)));
  XFillRectangle(dspy,[self getPixmap],[self getGC],0,0,width,height); 
  XSetForeground(dspy,[self getGC],BlackPixelOfScreen(XtScreen(widget)));
  [self refresh];
  return self;
}

- doSelected
{
  static int i=0;
  char output[10];
  if (_call_data.event->xany.type==ButtonPress) { // ButtonRelease
    i=i+1;
    sprintf(output, "This is %d.", i);
    XSetForeground([self getDisplay],[self getGC],i);
    [self drawCString:output 
     at :(_call_data.event->xbutton.x) :_call_data.event->xbutton.y];
  }
  return self;
}

- doAreaExposed 
{
  return [self refresh];
}

- doAreaResized
{

  // printf("do resizing\n");
  // this method get invoked when the object's height or weight have been 
  // changed. (i.e. [self setArg:"height" to:(char*)100]) 

  Pixmap pixmap=[self getPixmap];
  free(pixmap);
  [self setPixmap];
  return self;
}

- doAction
{
  if (_call_data.reason==XmCR_INPUT) [self doSelected];
  else if (_call_data.reason==XmCR_EXPOSE)[self doAreaExposed];
  else if (_call_data.reason==XmCR_RESIZE)[self doAreaResized];
  return self;
}

@end

