source: trunk/macosx/FileOutlineController.m @ 12608

Last change on this file since 12608 was 12608, checked in by livings124, 10 years ago

more experimenting with locking in the files table

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