1/*
2   Project: LaternaMagica
3   FileTable.m
4
5   Copyright (C) 2006-2016 Riccardo Mottola
6
7   Author: Riccardo Mottola
8
9   Created: 2006-01-16
10
11   This application is free software; you can redistribute it and/or
12   modify it under the terms of the GNU General Public
13   License as published by the Free Software Foundation; either
14   version 2 of the License, or (at your option) any later version.
15
16   This application is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19   Library General Public License for more details.
20
21   You should have received a copy of the GNU General Public
22   License along with this library; if not, write to the Free
23   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24*/
25
26#include <math.h>
27
28#import "FileTable.h"
29#import "AppController.h"
30#import "LMImage.h"
31
32#ifdef __NetBSD__
33#if __NetBSD_Version__ <= 299000000
34#define lround (long)round
35#endif
36#endif
37
38#ifdef __sun__
39#define lround(x) (long)ceil(x)
40#endif
41
42#if defined(__MINGW32__)
43#define srandom srand
44#define random rand
45#endif
46
47@implementation FileTable
48
49- (id)init
50{
51  if ((self = [super init]))
52    {
53      filesToIgnore = [[NSArray arrayWithObjects:
54                                @".DS_Store",
55                                @".gwdir",
56                                @"Thumbs.db",
57                                nil] retain];
58      images = [[NSMutableArray arrayWithCapacity:5] retain];
59    }
60  return self;
61}
62
63-(BOOL)addPathAndRecurse: (NSString*)path
64{
65  NSDictionary *attrs;
66  BOOL result;
67  NSFileManager *fmgr;
68
69  result = NO;
70  fmgr = [NSFileManager defaultManager];
71  attrs = [fmgr fileAttributesAtPath:path traverseLink:YES];
72  if (attrs)
73    {
74      NSAutoreleasePool *pool;
75
76      pool = [[NSAutoreleasePool alloc] init];
77      if ([attrs objectForKey:NSFileType] == NSFileTypeDirectory)
78        {
79          NSArray      *dirContents;
80          NSEnumerator *e2;
81          NSString     *filename;
82          NSDictionary  *attrs2;
83
84          dirContents = [fmgr subpathsAtPath:path];
85          e2 = [dirContents objectEnumerator];
86          while ((filename = (NSString*)[e2 nextObject]))
87            {
88              NSString *tempName;
89              NSString *lastPathComponent;
90
91              lastPathComponent = [filename lastPathComponent];
92              tempName = [path stringByAppendingPathComponent:filename];
93              attrs2 = [[NSFileManager defaultManager] fileAttributesAtPath:tempName traverseLink:YES];
94              if (attrs2)
95                {
96                  if ([attrs2 objectForKey:NSFileType] != NSFileTypeDirectory)
97                    {
98                      if (![filesToIgnore containsObject:lastPathComponent])
99                        {
100                          /* hide dot files, eventually a preference could be implemented */
101                          if (![lastPathComponent hasPrefix: @"."])
102                            {
103                              [self addPath:tempName];
104                              result = YES;
105                            }
106                        }
107                    }
108                }
109            }
110        }
111      else
112        {
113          NSString *lastPathComponent;
114
115          lastPathComponent = [path lastPathComponent];
116          if (![filesToIgnore containsObject:lastPathComponent])
117            {
118              /* hide dot files, eventually a preference could be implemented */
119              if (![lastPathComponent hasPrefix: @"."])
120                {
121                  [self addPath:path];
122                  result = YES;
123                }
124            }
125        }
126      [pool release];
127    }
128  return result;
129}
130
131- (void)dealloc
132{
133  [filesToIgnore release];
134  [images release];
135  [super dealloc];
136}
137
138- (void)addPath :(NSString*)path
139{
140  LMImage *image;
141
142  image = [[LMImage alloc] init];
143  [image setPath: path];
144  [images addObject: image];
145  [image release];
146  [appController updateImageCount];
147}
148
149- (LMImage*)imageAtIndex :(NSUInteger)index
150{
151  return [images objectAtIndex:index];
152}
153
154- (NSString *)pathAtIndex :(NSUInteger)index
155{
156  return [[images objectAtIndex:index] path];
157}
158
159- (void)removeObjectAtIndex:(NSUInteger)index
160{
161  [images removeObjectAtIndex:index];
162  [appController updateImageCount];
163}
164
165- (void)scrambleObjects
166{
167  NSMutableArray *newImages;
168
169  newImages = [NSMutableArray arrayWithCapacity: [images count]];
170  while ([images count] > 0)
171    {
172      unsigned i;
173
174      /* get a rescaled random number */
175      i = (unsigned)lround(((double)(unsigned long)random() / RAND_MAX) * ([images count]-1));
176      [newImages addObject: [images objectAtIndex: i]];
177      [images removeObjectAtIndex: i];
178
179    }
180  [images release];
181
182  images = [newImages retain];
183}
184
185- (NSUInteger)imageCount
186{
187  return [images count];
188}
189
190/* methods implemented to follow the informal NSTableView protocol */
191- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
192{
193    return [images count];
194}
195
196- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
197{
198    id theElement;
199
200    theElement = nil;
201
202    NSParameterAssert(rowIndex >= 0 && rowIndex < [images count]);
203    if ([[aTableColumn identifier] isEqualToString:@"filename"])
204        theElement = [[images objectAtIndex:rowIndex] name];
205    else
206        NSLog(@"unknown table column ident");
207    return theElement;
208}
209
210
211- (NSDragOperation)tableView:(NSTableView *)aTableView validateDrop:(id < NSDraggingInfo >)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)operation
212{
213  NSPasteboard *pboard;
214  BOOL result;
215
216  result = NO;
217  pboard = [info draggingPasteboard];
218  if ([[pboard types] containsObject:NSFilenamesPboardType])
219    {
220      NSEnumerator *e;
221      NSArray *paths;
222      NSString *filename;
223
224      paths = [pboard propertyListForType:NSFilenamesPboardType];
225      if ([paths count] > 0)
226        {
227          e = [paths objectEnumerator];
228          while ((filename = (NSString*)[e nextObject]))
229            {
230              if (![filesToIgnore containsObject:[filename lastPathComponent]])
231                result = YES;
232            }
233        }
234    }
235  if (result)
236    return NSDragOperationEvery;
237  return NSDragOperationNone;
238}
239
240- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id < NSDraggingInfo >)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
241{
242  BOOL result;
243  NSPasteboard *pboard;
244  NSString *filename;
245  NSEnumerator *e;
246  NSArray *paths;
247
248  pboard = [info draggingPasteboard];
249  result = NO;
250  paths = [pboard propertyListForType:NSFilenamesPboardType];
251  e = [paths objectEnumerator];
252  while ((filename = (NSString*)[e nextObject]))
253    {
254      result = [self addPathAndRecurse:filename];
255    }
256  if (result)
257    {
258      [aTableView reloadData];
259    }
260  return result;
261}
262
263@end
264