/*
    ProjectBrowser.m

    Implementation of the ProjectBrowser class for the
    ProjectManager application.

    Copyright (C) 2005  Saso Kiselkov

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#import "ProjectBrowser.h"

#import <AppKit/NSCell.h>
#import <AppKit/NSPasteboard.h>
#import <AppKit/NSMatrix.h>
#import <AppKit/NSEvent.h>

#import "FileManager.h"
#import "FileManagerDelegate.h"

@implementation ProjectBrowser

- (void) awakeFromNib
{
  [self registerForDraggedTypes: [NSArray arrayWithObjects:
    NSFilenamesPboardType,
    ProjectFilesPboardType,
    nil]];
}

- (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender
{
  return [self draggingUpdated: sender];
}

// tracks the mouse while dragging and allows the user to traverse the
// receiver's displayed hierarchy
- (unsigned int)draggingUpdated:(id <NSDraggingInfo>)sender
{
  NSPoint draggingLocation = [sender draggingLocation];
  unsigned int i, n;

  for (i=0, n = [self lastColumn]; i <= n; i++)
    {
      NSMatrix * matrix = [self matrixInColumn: i];
      NSPoint p = [matrix convertPoint: draggingLocation fromView: nil];
      NSSize matrixSize = [matrix frame].size;

      if (NSPointInRect(p, NSMakeRect(0,
                                      0,
                                      matrixSize.width,
                                      matrixSize.height)))
        {
          NSCell * cell;
          NSString * path;
          id <FileManagerDelegate> deleg;

          cell = [matrix cellAtRow: (p.y / [matrix cellSize].height)
                            column: 0];

          path = [[self pathToColumn: i]
            stringByAppendingPathComponent: [cell title]];
          if (![path isEqualToString: [self path]])
            {
              [self setPath: path];
              [self sendAction];
            }

          deleg = [fileManager delegate];
          // is adding files to this category allowed?
          if ([deleg canCreatePlainFilesAtPath: path] ||
              [deleg canCreateLinksAtPath: path] ||
              [deleg canCreateVirtualFilesAtPath: path])
            {
              NSArray * permissibleTypes = [[fileManager delegate]
                permissibleFileExtensionsInCategory: path];

              // if there are any permissible types, make sure they
              // are met
              if (permissibleTypes != nil)
                {
                  NSPasteboard * pb = [sender draggingPasteboard];
                  NSEnumerator * e = [[pb propertyListForType:
                    NSFilenamesPboardType] objectEnumerator];
                  NSString * filename;

                  while ((filename = [e nextObject]) != nil)
                    {
                      if (![permissibleTypes containsObject:
                        [filename pathExtension]])
                        {
                          return NSDragOperationNone;
                        }
                    }
                }

              return NSDragOperationMove | NSDragOperationCopy |
                NSDragOperationLink;
            }
          else
            {
              return NSDragOperationNone;
            }
        }
    }

  return NSDragOperationNone;
}

- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
{
  return YES;
}

- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
  return [fileManager performDragOperation: sender];
}

- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
}

// allows invoking the double action by pressing Return
- (void) keyDown: (NSEvent *) ev
{
  if ([[ev characters] characterAtIndex: 0] == '\r')
    {
      [self doDoubleClick: nil];
    }
  else
    {
      [super keyDown: ev];
    }
}

// allows selecting a column by clicking on it's title
- (void) mouseDown: (NSEvent *) ev
{
  NSPoint location = [ev locationInWindow];
  int i, n;

  for (i = 0, n = [self lastColumn]; i <= n; i++)
    {
      NSMatrix * matrix = [self matrixInColumn: i];

      if (matrix != nil)
        {
          NSSize matrixSize = [matrix frame].size;
          NSPoint p = [matrix convertPoint: location fromView: nil];

          // did the user click above the matrix?
          if (p.x >= 0 && p.x <= matrixSize.width && p.y < 0)
            {
              [self setPath: [self pathToColumn: i]];
              [self sendAction];

              return;
            }
        }
    }

  [super mouseDown: ev];
}

- (BOOL) setPath: (NSString *) aPath
{
  if ([super setPath: aPath])
    {
      if ([aPath isEqualToString: @"/"])
        {
          [[self matrixInColumn: 0] deselectAllCells];
        }

      return YES;
    }
  else
    {
      return NO;
    }
}

@end
