source: trunk/macosx/FileOutlineController.m @ 12991

Last change on this file since 12991 was 12991, checked in by livings124, 11 years ago

Silence some new warnings with LLVM 3.0/Xcode 4.2

  • Property svn:keywords set to Date Rev Author Id
File size: 22.6 KB
Line 
1/******************************************************************************
2 * $Id: FileOutlineController.m 12991 2011-10-18 02:30:22Z livings124 $
3 *
4 * Copyright (c) 2008-2011 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#import "FileOutlineController.h"
26#import "Torrent.h"
27#import "FileOutlineView.h"
28#import "FilePriorityCell.h"
29#import "FileListNode.h"
30#import "NSApplicationAdditions.h"
31#import "NSMutableArrayAdditions.h"
32#import "NSStringAdditions.h"
33#import <Quartz/Quartz.h>
34
35#import "utils.h"
36
37#define ROW_SMALL_HEIGHT 18.0
38
39typedef enum
40{
41    FILE_CHECK_TAG,
42    FILE_UNCHECK_TAG
43} fileCheckMenuTag;
44
45typedef enum
46{
47    FILE_PRIORITY_HIGH_TAG,
48    FILE_PRIORITY_NORMAL_TAG,
49    FILE_PRIORITY_LOW_TAG
50} filePriorityMenuTag;
51
52@interface FileOutlineController (Private)
53
54- (NSMenu *) menu;
55
56- (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list inRange: (NSRange) range currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent;
57
58@end
59
60@implementation FileOutlineController
61
62- (void) awakeFromNib
63{
64    fFileList = [[NSMutableArray alloc] init];
65   
66    [fOutline setDoubleAction: @selector(revealFile:)];
67    [fOutline setTarget: self];
68   
69    //set table header tool tips
70    [[fOutline tableColumnWithIdentifier: @"Check"] setHeaderToolTip: NSLocalizedString(@"Download", "file table -> header tool tip")];
71    [[fOutline tableColumnWithIdentifier: @"Priority"] setHeaderToolTip: NSLocalizedString(@"Priority", "file table -> header tool tip")];
72   
73    [fOutline setMenu: [self menu]];
74   
75    fLock = [[NSRecursiveLock alloc] init];
76    [fLock setName: @"File Table"];
77   
78    [self setTorrent: nil];
79}
80
81- (void) dealloc
82{
83    [fFileList release];
84    [fFilterText release];
85   
86    [fLock release];
87   
88    [super dealloc];
89}
90
91- (FileOutlineView *) outlineView
92{
93    return fOutline;
94}
95
96- (void) setTorrent: (Torrent *) torrent
97{
98    fTorrent = torrent;
99   
100    [fFileList setArray: [fTorrent fileList]];
101   
102    [fFilterText release];
103    fFilterText = nil;
104   
105    while (![fLock tryLock])
106        tr_wait_msec(100);
107   
108    [fOutline deselectAll: nil];
109    [fOutline reloadData];
110   
111    [fLock unlock];
112}
113
114- (void) setFilterText: (NSString *) text
115{
116    NSArray * components = [text betterComponentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
117    if (!components || [components count] == 0)
118    {
119        text = nil;
120        components = nil;
121    }
122   
123    if ((!text && !fFilterText) || (text && fFilterText && [text isEqualToString: fFilterText]))
124        return;
125   
126    const BOOL onLion = [NSApp isOnLionOrBetter];
127   
128    while (![fLock tryLock])
129        tr_wait_msec(100);
130   
131    if (onLion)
132    {
133        [[NSAnimationContext currentContext] setCompletionHandler: ^{ [fLock unlock]; }];
134        [NSAnimationContext beginGrouping];
135       
136        [fOutline beginUpdates];
137    }
138   
139    NSUInteger currentIndex = 0, totalCount = 0;
140    NSMutableArray * itemsToAdd = [NSMutableArray array];
141    NSMutableIndexSet * itemsToAddIndexes = [NSMutableIndexSet indexSet];
142   
143    NSMutableDictionary * removedIndexesForParents = nil; //ugly, but we can't modify the actual file nodes
144   
145    NSArray * tempList = !text ? [fTorrent fileList] : [fTorrent flatFileList];
146    for (FileListNode * item in tempList)
147    {
148        BOOL filter = NO;
149        if (components)
150        {
151            for (NSString * sub in components)
152                if ([[item name] rangeOfString: sub options: (NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch)].location == NSNotFound)
153                {
154                    filter = YES;
155                    break;
156                }
157        }
158       
159        if (!filter)
160        {
161            FileListNode * parent = nil;
162            NSUInteger previousIndex = ![item isFolder] ? [self findFileNode: item inList: fFileList inRange: NSMakeRange(currentIndex, [fFileList count]-currentIndex) currentParent: nil finalParent: &parent] : NSNotFound;
163           
164            if (previousIndex == NSNotFound)
165            {
166                [itemsToAdd addObject: item];
167                [itemsToAddIndexes addIndex: totalCount];
168            }
169            else
170            {
171                BOOL move = YES;
172                if (!parent)
173                {
174                    if (previousIndex != currentIndex)
175                        [fFileList moveObjectAtIndex: previousIndex toIndex: currentIndex];
176                    else
177                        move = NO;
178                }
179                else
180                {
181                    [fFileList insertObject: item atIndex: currentIndex];
182                   
183                    //figure out the index within the semi-edited table - UGLY
184                    if (!removedIndexesForParents)
185                        removedIndexesForParents = [NSMutableDictionary dictionary];
186                   
187                    NSMutableIndexSet * removedIndexes = [removedIndexesForParents objectForKey: parent];
188                    if (!removedIndexes)
189                    {
190                        removedIndexes = [NSMutableIndexSet indexSetWithIndex: previousIndex];
191                        [removedIndexesForParents setObject: removedIndexes forKey: parent];
192                    }
193                    else
194                    {
195                        [removedIndexes addIndex: previousIndex];
196                        previousIndex -= [removedIndexes countOfIndexesInRange: NSMakeRange(0, previousIndex)];
197                    }
198                }
199               
200                if (move && onLion)
201                    [fOutline moveItemAtIndex: previousIndex inParent: parent toIndex: currentIndex inParent: nil];
202               
203                ++currentIndex;
204            }
205           
206            ++totalCount;
207        }
208    }
209   
210    //remove trailing items - those are the unused
211    if (currentIndex  < [fFileList count])
212    {
213        const NSRange removeRange = NSMakeRange(currentIndex, [fFileList count]-currentIndex);
214        [fFileList removeObjectsInRange: removeRange];
215        if (onLion)
216            [fOutline removeItemsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: removeRange] inParent: nil withAnimation: NSTableViewAnimationSlideDown];
217    }
218   
219    //add new items
220    [fFileList insertObjects: itemsToAdd atIndexes: itemsToAddIndexes];
221    if (onLion)
222        [fOutline insertItemsAtIndexes: itemsToAddIndexes inParent: nil withAnimation: NSTableViewAnimationSlideUp];
223   
224    if (onLion)
225    {
226        [fOutline endUpdates];
227       
228        [NSAnimationContext endGrouping];
229    }
230    else
231    {
232        [fOutline reloadData];
233   
234        [fLock unlock];
235    }
236   
237    [fFilterText release];
238    fFilterText = [text retain];
239}
240
241- (void) reloadData
242{
243    [fTorrent updateFileStat];
244   
245    while (![fLock tryLock])
246        tr_wait_msec(100);
247   
248    [fOutline reloadData];
249   
250    [fLock unlock];
251}
252
253- (void) outlineViewSelectionDidChange: (NSNotification *) notification
254{
255    if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible])
256        [[QLPreviewPanel sharedPreviewPanel] reloadData];
257}
258
259- (NSInteger) outlineView: (NSOutlineView *) outlineView numberOfChildrenOfItem: (id) item
260{
261    if (!item)
262        return fFileList ? [fFileList count] : 0;
263    else
264    {
265        FileListNode * node = (FileListNode *)item;
266        return [node isFolder] ? [[node children] count] : 0;
267    }
268}
269
270- (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item
271{
272    return [(FileListNode *)item isFolder];
273}
274
275- (id) outlineView: (NSOutlineView *) outlineView child: (NSInteger) index ofItem: (id) item
276{
277    return [(item ? [(FileListNode *)item children] : fFileList) objectAtIndex: index];
278}
279
280- (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
281{
282    if ([[tableColumn identifier] isEqualToString: @"Check"])
283        return [NSNumber numberWithInteger: [fTorrent checkForFiles: [(FileListNode *)item indexes]]];
284    else
285        return item;
286}
287
288- (void) outlineView: (NSOutlineView *) outlineView willDisplayCell: (id) cell
289            forTableColumn: (NSTableColumn *) tableColumn item: (id) item
290{
291    NSString * identifier = [tableColumn identifier];
292    if ([identifier isEqualToString: @"Check"])
293        [cell setEnabled: [fTorrent canChangeDownloadCheckForFiles: [(FileListNode *)item indexes]]];
294    else if ([identifier isEqualToString: @"Priority"])
295    {
296        [cell setRepresentedObject: item];
297       
298        NSInteger hoveredRow = [fOutline hoveredRow];
299        [(FilePriorityCell *)cell setHovered: hoveredRow != -1 && hoveredRow == [fOutline rowForItem: item]];
300    }
301    else;
302}
303
304- (void) outlineView: (NSOutlineView *) outlineView setObjectValue: (id) object
305        forTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
306{
307    NSString * identifier = [tableColumn identifier];
308    if ([identifier isEqualToString: @"Check"])
309    {
310        NSIndexSet * indexSet;
311        if ([NSEvent modifierFlags] & NSAlternateKeyMask)
312            indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
313        else
314            indexSet = [(FileListNode *)item indexes];
315       
316        [fTorrent setFileCheckState: [object intValue] != NSOffState ? NSOnState : NSOffState forIndexes: indexSet];
317        [fOutline reloadData];
318       
319        [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: nil];
320    }
321}
322
323- (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item
324{
325    return [(FileListNode *)item name];
326}
327
328- (NSString *) outlineView: (NSOutlineView *) outlineView toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect
329        tableColumn: (NSTableColumn *) tableColumn item: (id) item mouseLocation: (NSPoint) mouseLocation
330{
331    NSString * ident = [tableColumn identifier];
332    if ([ident isEqualToString: @"Name"])
333    {
334        NSString * path = [fTorrent fileLocation: item];
335        if (!path)
336            path = [[(FileListNode *)item path] stringByAppendingPathComponent: [(FileListNode *)item name]];
337        return path;
338    }
339    else if ([ident isEqualToString: @"Check"])
340    {
341        switch ([cell state])
342        {
343            case NSOffState:
344                return NSLocalizedString(@"Don't Download", "files tab -> tooltip");
345            case NSOnState:
346                return NSLocalizedString(@"Download", "files tab -> tooltip");
347            case NSMixedState:
348                return NSLocalizedString(@"Download Some", "files tab -> tooltip");
349        }
350    }
351    else if ([ident isEqualToString: @"Priority"])
352    {
353        NSSet * priorities = [fTorrent filePrioritiesForIndexes: [(FileListNode *)item indexes]];
354        switch ([priorities count])
355        {
356            case 0:
357                return NSLocalizedString(@"Priority Not Available", "files tab -> tooltip");
358            case 1:
359                switch ([[priorities anyObject] intValue])
360                {
361                    case TR_PRI_LOW:
362                        return NSLocalizedString(@"Low Priority", "files tab -> tooltip");
363                    case TR_PRI_HIGH:
364                        return NSLocalizedString(@"High Priority", "files tab -> tooltip");
365                    case TR_PRI_NORMAL:
366                        return NSLocalizedString(@"Normal Priority", "files tab -> tooltip");
367                }
368                break;
369            default:
370                return NSLocalizedString(@"Multiple Priorities", "files tab -> tooltip");
371        }
372    }
373    else;
374   
375    return nil;
376}
377
378- (CGFloat) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item
379{
380    if ([(FileListNode *)item isFolder])
381        return ROW_SMALL_HEIGHT;
382    else
383        return [outlineView rowHeight];
384}
385
386- (void) setCheck: (id) sender
387{
388    while (![fLock tryLock])
389        tr_wait_msec(100);
390   
391    NSInteger state = [sender tag] == FILE_UNCHECK_TAG ? NSOffState : NSOnState;
392   
393    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
394    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
395    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
396        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
397   
398    [fTorrent setFileCheckState: state forIndexes: itemIndexes];
399    [fOutline reloadData];
400   
401    [fLock unlock];
402}
403
404- (void) setOnlySelectedCheck: (id) sender
405{
406    while (![fLock tryLock])
407        tr_wait_msec(100);
408   
409    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
410    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
411    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
412        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
413   
414    [fTorrent setFileCheckState: NSOnState forIndexes: itemIndexes];
415   
416    NSMutableIndexSet * remainingItemIndexes = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])];
417    [remainingItemIndexes removeIndexes: itemIndexes];
418    [fTorrent setFileCheckState: NSOffState forIndexes: remainingItemIndexes];
419   
420    [fOutline reloadData];
421   
422    [fLock unlock];
423}
424
425- (void) setPriority: (id) sender
426{
427    tr_priority_t priority;
428    switch ([sender tag])
429    {
430        case FILE_PRIORITY_HIGH_TAG:
431            priority = TR_PRI_HIGH;
432            break;
433        case FILE_PRIORITY_NORMAL_TAG:
434            priority = TR_PRI_NORMAL;
435            break;
436        case FILE_PRIORITY_LOW_TAG:
437            priority = TR_PRI_LOW;
438    }
439   
440    while (![fLock tryLock])
441        tr_wait_msec(100);
442   
443    NSIndexSet * indexSet = [fOutline selectedRowIndexes];
444    NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
445    for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
446        [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
447   
448    [fTorrent setFilePriority: priority forIndexes: itemIndexes];
449    [fOutline reloadData];
450   
451    [fLock unlock];
452}
453
454- (void) revealFile: (id) sender
455{
456    while (![fLock tryLock])
457        tr_wait_msec(100);
458   
459    NSIndexSet * indexes = [fOutline selectedRowIndexes];
460    NSMutableArray * paths = [NSMutableArray arrayWithCapacity: [indexes count]];
461    for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
462    {
463        NSString * path = [fTorrent fileLocation: [fOutline itemAtRow: i]];
464        if (path)
465            [paths addObject: [NSURL fileURLWithPath: path]];
466    }
467   
468    if ([paths count] > 0)
469        [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs: paths];
470   
471    [fLock unlock];
472}
473
474#warning make real view controller (Leopard-only) so that Command-R will work
475- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
476{
477    if (!fTorrent)
478        return NO;
479   
480    SEL action = [menuItem action];
481   
482    if (action == @selector(revealFile:))
483    {
484        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
485        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
486            if ([fTorrent fileLocation: [fOutline itemAtRow: i]] != nil)
487                return YES;
488        return NO;
489    }
490   
491    if (action == @selector(setCheck:))
492    {
493        if ([fOutline numberOfSelectedRows] == 0)
494            return NO;
495       
496        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
497        NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
498        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
499            [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
500       
501        NSInteger state = ([menuItem tag] == FILE_CHECK_TAG) ? NSOnState : NSOffState;
502        return [fTorrent checkForFiles: itemIndexes] != state && [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
503    }
504   
505    if (action == @selector(setOnlySelectedCheck:))
506    {
507        if ([fOutline numberOfSelectedRows] == 0)
508            return NO;
509       
510        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
511        NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
512        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
513            [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]];
514       
515        return [fTorrent canChangeDownloadCheckForFiles: itemIndexes];
516    }
517   
518    if (action == @selector(setPriority:))
519    {
520        if ([fOutline numberOfSelectedRows] == 0)
521        {
522            [menuItem setState: NSOffState];
523            return NO;
524        }
525       
526        //determine which priorities are checked
527        NSIndexSet * indexSet = [fOutline selectedRowIndexes];
528        tr_priority_t priority;
529        switch ([menuItem tag])
530        {
531            case FILE_PRIORITY_HIGH_TAG:
532                priority = TR_PRI_HIGH;
533                break;
534            case FILE_PRIORITY_NORMAL_TAG:
535                priority = TR_PRI_NORMAL;
536                break;
537            case FILE_PRIORITY_LOW_TAG:
538                priority = TR_PRI_LOW;
539                break;
540        }
541       
542        BOOL current = NO, canChange = NO;
543        for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
544        {
545            NSIndexSet * fileIndexSet = [[fOutline itemAtRow: i] indexes];
546            if (![fTorrent canChangeDownloadCheckForFiles: fileIndexSet])
547                continue;
548           
549            canChange = YES;
550            if ([fTorrent hasFilePriority: priority forIndexes: fileIndexSet])
551            {
552                current = YES;
553                break;
554            }
555        }
556       
557        [menuItem setState: current ? NSOnState : NSOffState];
558        return canChange;
559    }
560   
561    return YES;
562}
563
564@end
565
566@implementation FileOutlineController (Private)
567
568- (NSMenu *) menu
569{
570    NSMenu * menu = [[NSMenu alloc] initWithTitle: @"File Outline Menu"];
571   
572    //check and uncheck
573    NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Check Selected", "File Outline -> Menu")
574                            action: @selector(setCheck:) keyEquivalent: @""];
575    [item setTarget: self];
576    [item setTag: FILE_CHECK_TAG];
577    [menu addItem: item];
578    [item release];
579   
580    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Uncheck Selected", "File Outline -> Menu")
581            action: @selector(setCheck:) keyEquivalent: @""];
582    [item setTarget: self];
583    [item setTag: FILE_UNCHECK_TAG];
584    [menu addItem: item];
585    [item release];
586   
587    //only check selected
588    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Only Check Selected", "File Outline -> Menu")
589            action: @selector(setOnlySelectedCheck:) keyEquivalent: @""];
590    [item setTarget: self];
591    [menu addItem: item];
592    [item release];
593   
594    [menu addItem: [NSMenuItem separatorItem]];
595   
596    //priority
597    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Priority", "File Outline -> Menu") action: NULL keyEquivalent: @""];
598    NSMenu * priorityMenu = [[NSMenu alloc] initWithTitle: @"File Priority Menu"];
599    [item setSubmenu: priorityMenu];
600    [menu addItem: item];
601    [item release];
602   
603    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"High", "File Outline -> Priority Menu")
604            action: @selector(setPriority:) keyEquivalent: @""];
605    [item setTarget: self];
606    [item setTag: FILE_PRIORITY_HIGH_TAG];
607    [item setImage: [NSImage imageNamed: @"PriorityHigh.png"]];
608    [priorityMenu addItem: item];
609    [item release];
610   
611    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Normal", "File Outline -> Priority Menu")
612            action: @selector(setPriority:) keyEquivalent: @""];
613    [item setTarget: self];
614    [item setTag: FILE_PRIORITY_NORMAL_TAG];
615    [item setImage: [NSImage imageNamed: @"PriorityNormal.png"]];
616    [priorityMenu addItem: item];
617    [item release];
618   
619    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Low", "File Outline -> Priority Menu")
620            action: @selector(setPriority:) keyEquivalent: @""];
621    [item setTarget: self];
622    [item setTag: FILE_PRIORITY_LOW_TAG];
623    [item setImage: [NSImage imageNamed: @"PriorityLow.png"]];
624    [priorityMenu addItem: item];
625    [item release];
626   
627    [priorityMenu release];
628   
629    [menu addItem: [NSMenuItem separatorItem]];
630   
631    //reveal in finder
632    item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"Show in Finder", "File Outline -> Menu")
633            action: @selector(revealFile:) keyEquivalent: @""];
634    [item setTarget: self];
635    [menu addItem: item];
636    [item release];
637   
638    return [menu autorelease];
639}
640
641- (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list inRange: (NSRange) range currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent
642{
643    NSAssert(![node isFolder], @"Looking up folder node!");
644   
645    const NSUInteger nodeIndex = [[node indexes] firstIndex];
646    for (NSUInteger index = range.location; index < NSMaxRange(range); ++index)
647    {
648        FileListNode * checkNode = [list objectAtIndex: index];
649        if ([checkNode isEqualTo: node])
650        {
651            *parent = currentParent;
652            return index;
653        }
654        else if ([checkNode isFolder] && [[checkNode indexes] containsIndex: nodeIndex])
655        {
656            const NSUInteger subIndex = [self findFileNode: node inList: [checkNode children] inRange: NSMakeRange(0, [[checkNode children] count]) currentParent: checkNode finalParent: parent];
657            NSAssert(subIndex != NSNotFound, @"We didn't find an expected file node.");
658            return subIndex;
659        }
660    }
661   
662    return NSNotFound;
663}
664
665@end
Note: See TracBrowser for help on using the repository browser.