#include "stardraw.h"
#include "struc/iterator.h"
#include "struc/linebuff.h"

#define X_ORG 20
#define Y_ORG 20
#define X_OFFSET 200
#define Y_OFFSET 10
#define X_WIDTH 6
#define Y_HEIGHT 13
#define SCROLL 30
#define EDGY 5
#define MAXPOPUPWIDTH 9000
#define MAXPOPUPHEIGHT 600
#define RED 3
#define BLUE 4
#define BROWN 5
#define GREEN 6


@implementation WDCLListOfDrawObject

- setPopup:popup
{
  return [self setSelectable:(_popup=popup)?YES:NO];
}

- getPopup
{
  return _popup;
}

- setSelectable:(BOOL)selectable
{
  _selectable=selectable;
  return self;
}

- (BOOL)isSelectable
{
  return _selectable;
}

- setX:(Dimension)x
{
  _x=x;
  return self;
}

- (Dimension)getX
{
  return _x;
}

- setY:(Dimension)y
{
  _y=y;
  return self;
}

- (Dimension)getY
{
  return _y;
}

- setX1:(Dimension)x1
{
  _x1=x1;
  return self;
}

- (Dimension)getX1
{
  return _x1;
}

- setY1:(Dimension)y1
{
  _y1=y1;
  return self;
}

- (Dimension)getY1
{
  return _y1;
}

- setDimension:(Dimension)x :(Dimension)y
{
  id iter, object;
  int i=0, length=0, len;
  [[self setX:x] setY:y];
  object=[self getContent];
  if ([object isMemberOfClassNamed:"WDCString"]){
    i++;
    length=strlen([object cStringValue]);
  }
  else if ([object isMemberOfClassNamed:"WDCLineBuffer"]){
    iter=[[WDCListIterator alloc] initFrom:object];
    while ([iter goNext]){
      i++;
      len=strlen([[iter getCurrentObject] cStringValue]);
      if (len>length) length=len;
    }
  }
  [self setX1:x+(length*X_WIDTH)];
  [self setY1:y+i*Y_HEIGHT];
  return self;
}

- (BOOL)isInXY:(Dimension)x :(Dimension)y
{
  y=y+Y_HEIGHT;
  return (x>_x && x<_x1 && y>_y && y<_y1)?YES:NO;
}

- setManaged:(BOOL)value
{
  _managed=value;
  return self;
}

- manageChild
{
  [[[self setManaged:YES] getPopup] manage];
  return self;
}

- unManageChild
{
  [[[self setManaged:NO] getPopup] unManage];
  return self;
}

- (BOOL)isChildManaged
{
  return _managed;
}

- toggleManageState
{
  if ([self isChildManaged])
    [self unManageChild];
  else
    [self manageChild];
  return self;
}

- addContent: object with:aRelatedPopup 
{
  if (![self getContent]) {
    [[self setContent: object] setPopup:aRelatedPopup];
    [self setDimension:X_ORG :Y_ORG];
  }
  else{
    if (![self nextLink]){
      [self setNextLink:[[[[[self class] alloc] setContent :object] 
			setPopup :aRelatedPopup] setPrevLink :self]];
      if (_x==X_ORG){
	[[self nextLink] setDimension:X_ORG+X_OFFSET :_y];
      }
      else {
	[[self nextLink] setDimension:X_ORG :_y1+Y_OFFSET];
      }
     }
    else [_next addContent:object with:aRelatedPopup];
  }
  return self;
}

- addContent
{
  return [self shouldNotImplement:_cmd];
}

@end

@implementation WDCStarDrawArea 

//
// This is for the StarItemAssocValues. StarDataBlock should remain to be
// toggle buttons. _loop objects should be changed to DrawTable form.
//

static GC _selectableGC_;
static GC _selectedGC_;

- setSelectableGC
{
  if (!_selectableGC_){
    _selectableGC_=XCreateGC([self getDisplay],
			    RootWindowOfScreen(XtScreen([self getWidget])),
			    0 ,NULL);
    XSetForeground([self getDisplay],_selectableGC_, BLUE);
  }
  return self;
}

- setSelectedGC
{
  if (!_selectedGC_) {
    _selectedGC_=XCreateGC([self getDisplay],
			  RootWindowOfScreen(XtScreen([self getWidget])),
			  0 ,NULL);
    XSetForeground([self getDisplay], _selectedGC_, 20);
  }
  return self;
}

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

- addDrawObject: anObject with:aRelatedPopup 
{
  if (![self getDrawObjects])
    _drawObjects=[WDCLListOfDrawObject alloc];
  [[self getDrawObjects] addContent:anObject with:aRelatedPopup];
  return self;
}

- (GC)getSelectableGC
{
  return _selectableGC_;
}

- (GC)getSelectedGC
{
  return _selectedGC_;
}

- getDrawObjects
{
  return _drawObjects;
}

- getDrawObjectAt:(Dimension)x :(Dimension)y
{
  id iter;
  iter=[[WDCListIterator alloc] initFrom:[self getDrawObjects]];
  while ([iter goNext])
    if ([[iter getCurrentObject] isInXY:x :y])
      return [iter getCurrentObject];
  return 0;
}

- getObjectAt:(Dimension)x :(Dimension)y
{
  return [[self getDrawObjectAt:x :y] getContent];
}

- draw:o :(Display*)d :(Pixmap)p :(GC)g
{
  const char* charPtr;
  id iter, object=[o getContent];
  Dimension x=0, y=0;
  if ([object isMemberOfClassNamed:"WDCString"]){
    charPtr=[object cStringValue];
    XDrawString(d, p, g, [o getX], [o getY], charPtr, strlen(charPtr));
  }
  else if ([object isMemberOfClassNamed:"WDCLineBuffer"]){
    iter=[[WDCListIterator alloc] initFrom:object];
    x=[o getX]; y=[o getY];
    while ([iter goNext]){
      charPtr=(char*)[[iter getCurrentObject] cStringValue];
      XDrawString(d, p, g, x, y, charPtr, strlen(charPtr));
      y=y+Y_HEIGHT;
    }
  }
  return self;
}

- setDimension
{
  int i=0,j=0;
  Dimension j1;
  id currentid, iter=[[WDCListIterator alloc] initFrom:[self getDrawObjects]];
  while ([iter goNext]){
    currentid=[iter getCurrentObject];
    if (i<[currentid getX1]) i=[currentid getX1];
    if (j<[currentid getY1]) j=[currentid getY1];
  }
  [[self setArg:"width" to:(char*)i+X_ORG] setArg:"height" to:(char*)j+Y_ORG];
  return self;
}

- toggleSelectableStateFor:aDrawObject
{
  Dimension x=[aDrawObject getX], y=[aDrawObject getY];
  Display* dspy=[self getDisplay];
  Pixmap pixmap=[self getPixmap];
  [self draw:aDrawObject :dspy :pixmap 
   :[aDrawObject isChildManaged]?[self getSelectableGC]:[self getSelectedGC]];
  [self refresh];
  [aDrawObject toggleManageState];
  return self;
}

- draw
{
  id iter, drawObject;
  Display* dspy=[self getDisplay];
  GC gc0=[self getGC];
  GC gc1=[self getSelectableGC];
  GC gc;
  Pixmap pixmap=[self getPixmap];
  iter=[[WDCListIterator alloc] initFrom:[self getDrawObjects]];
  while ([iter goNext]){
    drawObject=[iter getCurrentObject];
    gc=([drawObject isSelectable])?gc1:gc0;
    [self draw:drawObject :dspy :pixmap :gc];
  } 
 return self;
}

- redraw
{
  return [[self draw] refresh];
}

- doSelected
{
  id drawObject;
  if (_call_data.event->xany.type==ButtonPress) { // ButtonRelease
    drawObject=[self getDrawObjectAt : _call_data.event->xbutton.x
		: _call_data.event->xbutton.y];
    if ([drawObject isSelectable]){
      [self toggleSelectableStateFor:drawObject];
    }
  }
  return self;
}

@end

@implementation WDCStarDrawBox

- setArg:(char*)aName to:(char*)aValue
{
  id object;
  if (object=[self getPopupShell])
    {
      [object setArg:aName to:aValue];
      [[self getPopupWindow] setArg:aName to:aValue];
    } 
  return self;
}

- initWithName:(char*)aName managedBy:anObject
{
  if (![anObject isKindOfClassNamed:"WDCWindow"]
      && ![anObject isKindOfClassNamed:"WDCFrame"])
    {
      [self buildPopupShellWithName:aName managedBy:anObject];
      anObject=[self getPopupWindow];
    }
  [self setDrawArea:[[WDCStarDrawArea alloc] 
		     initWithName : aName managedBy : anObject]];
  [self setWidget : [[self getDrawArea] getWidget]];
  [self setParentObject: anObject];

  // this need to be managed before its parent. So, just do this for now.
  // I don't like this, however, it does work.
  XtManageChild([self getWidget]);
  return self;
}

- setDimension
{
  Dimension i, j;
  int x, y;
  [_drawArea setDimension];
  [_drawArea getArg:"width" into:&i];
  [_drawArea getArg:"height" into:&j];
  x=((i>MAXPOPUPWIDTH)?MAXPOPUPWIDTH:i)+((j>MAXPOPUPHEIGHT)?SCROLL:0);
  y=((j>MAXPOPUPHEIGHT)?MAXPOPUPHEIGHT:j)+((i>MAXPOPUPWIDTH)?SCROLL:0);
  [self setArg:"width" to:(char*)x+EDGY];
  [self setArg:"height" to:(char*)y+EDGY];   
}

@end




