#import "FileShelfView.h"
#import "TokenString.h"

@interface FileShelfView (Private)
- burstNames;
@end

@implementation FileShelfView

-initFrame:(const NXRect *)rect
{
   [super initFrame: rect];
   [self registerForDraggedTypes:&NXFilenamePboardType count:1];
   images = [[List alloc] init];
   fileNames = [[List alloc] init];
   singleNames = [[List alloc] init];
   nameListDirty = NO;
   enabled = YES;
   return self;
}

- free
{
   [self unregisterDraggedTypes];
   [images freeObjects];
   [images free];
   [fileNames freeObjects];
   [fileNames free];
   [singleNames freeObjects];
   [singleNames free];
   return [super free];
}

- empty
{
   [images freeObjects];
   [fileNames freeObjects];
   [self display];
   return self;
}

- drawSelf:(NXRect *)r :(int) count
{
   int cnt, x;
   NXPoint zeroPoint = {0.0, 0.0};

   /* Erase the whole view */
   if(enabled)
       NXDrawGrayBezel(&bounds, &bounds);    /* with bezel if enabled */
   else
   {
      NXSetColor ([window backgroundColor]);
      NXRectFill (&bounds);
   }
   
   zeroPoint.y = (bounds.size.height / 2) - 24;
   for(x = 0, cnt = [images count]; x < cnt; x++)
   {
      zeroPoint.x = (x * 50) + 2;
      [[images objectAt: x] composite: NX_SOVER toPoint: &zeroPoint];
   }
   return self;
}

- fileNames
{
   if(nameListDirty)
       [self burstNames];

   return singleNames;
}

- setEnabled: (BOOL)flag
{
   if(flag == enabled)
       return self;

   enabled = flag;
   [self empty];
   [self display];
   return self;
}

- (BOOL) enabled
{
   return enabled;
}

- addFile: (const char *)filename
{
   id file = [[StringStorage alloc] init: filename];
   NXImage *image;
   
   image = [[Application workspace] getIconForFile: [file stringValue]];

   if(!(image && enabled))
   {
      [file free];
      return nil;
   }

   [images addObject: image];
   [fileNames addObject: file];
   [self display];
   nameListDirty = YES;
   return self;
}

- mouseDown: (NXEvent *)anEvent
{
   NXEvent saveEvent;
   NXPoint origin, offset;
   Pasteboard *dragPasteboard;
   int x;

   saveEvent = *anEvent;
					     /* find the hit icon and its origin */
   origin = anEvent->location;
   [self convertPoint: &origin fromView: nil];
   origin.y = (bounds.size.height / 2) - 24;
   x = origin.x;
   x -= 2;
   origin.x = ((x / 50) * 50) + 2;
   dragIndex = x / 50;
   offset.x = offset.y = 0;

					     /* create and load pasteboard - then start drag */
   dragPasteboard = [Pasteboard newName: NXDragPboard];
   [dragPasteboard declareTypes: &NXFilenamePboardType num:1 owner:self];

   [self dragImage: [images objectAt: dragIndex] at: &origin offset: &offset
    event: &saveEvent pasteboard: dragPasteboard source: self slideBack: NO];

    return [super mouseDown: anEvent];
}

@end

@implementation FileShelfView (NXDraggingDestinationProtocol)
- (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
{
   NXLogError("draggingEntered\n");

   if(enabled && ([sender draggingSourceOperationMask] & NX_DragOperationCopy))
       return NX_DragOperationCopy;
   else
       return NX_DragOperationNone;
}

- draggingExited:sender
{
   NXLogError("draggingExited\n");
   return self;
}

- (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
{
   NXLogError("performDragOperation\n");
   return ([self draggingEntered: sender] == NX_DragOperationNone) ? NO : YES;
}

- concludeDragOperation:(id <NXDraggingInfo>)sender
{
   Pasteboard *pboard = [sender draggingPasteboard];
   char *files;
   int len;
   id aFile;

   NXLogError("concludeDragOperation\n");
   [images addObject: [sender draggedImageCopy]];
   [pboard readType:NXFilenamePboardType data: &files length: &len];
   aFile = [[StringStorage alloc] init: files];
   [fileNames addObject:aFile];
   [self display];
   nameListDirty = YES;
   return self;
}


@end

@implementation FileShelfView (FSVNXDraggingSource)

- (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
{
   return NX_DragOperationCopy;
}

- draggedImage:(NXImage *)image endedAt:(NXPoint *)screenPoint deposited:(BOOL)didDeposit
{
   NXLogError("draggedImage:endedAt:deposited: %d", didDeposit);

   if(!didDeposit)
   {
      [[images removeObjectAt: dragIndex] free];
      [[fileNames removeObjectAt: dragIndex] free];
      [self display];
      nameListDirty = YES;
   }
   return self;
}

@end

@implementation FileShelfView (Private)
					     /* fileNames may contain multiple file entries - burst them */
- burstNames
{
   int x, cnt;
   id someNames = [[TokenString alloc] init];
   id aFileName;
   const char *fileNameStr;
   
   [singleNames freeObjects];		     /* free old version of the list */
   [someNames setSeparator: '\t'];

   for(x = 0, cnt = [fileNames count]; x < cnt; x++)
   {
      [someNames setStringValue: [[fileNames objectAt: x] stringValue]];
      
      while(fileNameStr = [someNames popString])
      {
	 aFileName = [[StringStorage alloc] init: fileNameStr];
	 [singleNames addObject: aFileName];
      }
   }

   [someNames free];
   nameListDirty = NO;
   return self;
}

@end
