source: trunk/macosx/TorrentTableView.m @ 4936

Last change on this file since 4936 was 4936, checked in by livings124, 15 years ago

expand a torrent's group when removing it, since either the whole group is being removed or it is already expanded

  • Property svn:keywords set to Date Rev Author Id
File size: 24.8 KB
Line 
1/******************************************************************************
2 * $Id: TorrentTableView.m 4936 2008-02-07 02:11:26Z livings124 $
3 *
4 * Copyright (c) 2005-2008 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 "TorrentTableView.h"
26#import "TorrentCell.h"
27#import "Torrent.h"
28#import "NSApplicationAdditions.h"
29#import "NSMenuAdditions.h"
30
31#define ACTION_MENU_GLOBAL_TAG 101
32#define ACTION_MENU_UNLIMITED_TAG 102
33#define ACTION_MENU_LIMIT_TAG 103
34
35#define PIECE_CHANGE 0.1
36#define PIECE_TIME 0.01
37
38@interface TorrentTableView (Private)
39
40- (BOOL) pointInControlRect: (NSPoint) point;
41- (BOOL) pointInRevealRect: (NSPoint) point;
42- (BOOL) pointInActionRect: (NSPoint) point;
43
44- (BOOL) pointInProgressRect: (NSPoint) point;
45- (BOOL) pointInMinimalStatusRect: (NSPoint) point;
46- (void) updateFileMenu: (NSMenu *) menu forFiles: (NSArray *) files;
47
48- (void) resizePiecesBarIncrement;
49
50@end
51
52@implementation TorrentTableView
53
54- (id) initWithCoder: (NSCoder *) decoder
55{
56    if ((self = [super initWithCoder: decoder]))
57    {
58        fDefaults = [NSUserDefaults standardUserDefaults];
59       
60        fTorrentCell = [[TorrentCell alloc] init];
61        if (![NSApp isOnLeopardOrBetter])
62            [[self tableColumnWithIdentifier: @"Torrent"] setDataCell: fTorrentCell];
63       
64        fCollapsedGroups = [[NSMutableIndexSet alloc] init];
65       
66        fMouseControlRow = -1;
67        fMouseRevealRow = -1;
68        fMouseActionRow = -1;
69        fActionPushedRow = -1;
70       
71        [self setDelegate: self];
72       
73        fPiecesBarPercent = [fDefaults boolForKey: @"PiecesBar"] ? 1.0 : 0.0;
74    }
75   
76    return self;
77}
78
79- (void) dealloc
80{
81    [fCollapsedGroups release];
82   
83    [fPiecesBarTimer invalidate];
84    [fMenuTorrent release];
85   
86    [fSelectedValues release];
87   
88    [fTorrentCell release];
89   
90    [super dealloc];
91}
92
93- (NSIndexSet *) collapsedGroupsIndexes
94{
95    return fCollapsedGroups;
96}
97
98- (void) removeCollapsedGroup: (int) value
99{
100    if (value < 0)
101        value = INT_MAX;
102   
103    [fCollapsedGroups removeIndex: value];
104}
105
106- (BOOL) outlineView: (NSOutlineView *) outlineView isGroupItem: (id) item
107{
108    return ![item isKindOfClass: [Torrent class]];
109}
110
111- (CGFloat) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item
112{
113    return [item isKindOfClass: [Torrent class]] ? [self rowHeight] : GROUP_SEPARATOR_HEIGHT;
114}
115
116- (NSCell *) outlineView: (NSOutlineView *) outlineView dataCellForTableColumn: (NSTableColumn *) tableColumn item: (id) item
117{
118    if (!tableColumn)
119        return nil;
120    return [item isKindOfClass: [Torrent class]] ? fTorrentCell : nil;
121}
122
123- (void) outlineView: (NSOutlineView *) outlineView willDisplayCell: (id) cell forTableColumn: (NSTableColumn *) tableColumn
124    item: (id) item
125{
126    if (![item isKindOfClass: [Torrent class]])
127        return;
128   
129    [cell setRepresentedObject: item];
130   
131    int row = [self rowForItem: item];
132    [cell setControlHover: row == fMouseControlRow];
133    [cell setRevealHover: row == fMouseRevealRow];
134    [cell setActionHover: row == fMouseActionRow];
135    [cell setActionPushed: row == fActionPushedRow];
136}
137
138- (NSRect) frameOfCellAtColumn: (NSInteger) column row: (NSInteger) row
139{
140    NSRect rect = [super frameOfCellAtColumn: column row: row];
141   
142    if ([[self itemAtRow: row] isKindOfClass: [Torrent class]])
143    {
144        rect.size.width += rect.origin.x;
145        rect.origin.x = 0.0;
146    }
147   
148    return rect;
149}
150
151- (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item
152{
153    return [item isKindOfClass: [Torrent class]] ? [item name]
154            : [[self preparedCellAtColumn: 0 row: [self rowForItem: item]] stringValue];
155}
156
157- (void) updateTrackingAreas
158{
159    [super updateTrackingAreas];
160    [self removeButtonTrackingAreas];
161   
162    NSRange rows = [self rowsInRect: [self visibleRect]];
163    if (rows.length == 0)
164        return;
165   
166    NSPoint mouseLocation = [self convertPoint: [[self window] convertScreenToBase: [NSEvent mouseLocation]] fromView: nil];
167   
168    NSUInteger row;
169    for (row = rows.location; row < NSMaxRange(rows); row++)
170    {
171        if (![[self itemAtRow: row] isKindOfClass: [Torrent class]])
172            continue;
173       
174        NSDictionary * userInfo = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: row] forKey: @"Row"];
175        TorrentCell * cell = (TorrentCell *)[self preparedCellAtColumn: 0 row: row];
176        [cell addTrackingAreasForView: self inRect: [self frameOfCellAtColumn: 0 row: row] withUserInfo: userInfo
177                mouseLocation: mouseLocation];
178    }
179}
180
181- (void) removeButtonTrackingAreas
182{
183    fMouseControlRow = -1;
184    fMouseRevealRow = -1;
185    fMouseActionRow = -1;
186   
187    if (![NSApp isOnLeopardOrBetter])
188        return;
189   
190    NSEnumerator * enumerator = [[self trackingAreas] objectEnumerator];
191    NSTrackingArea * area;
192    while ((area = [enumerator nextObject]))
193    {
194        if ([area owner] == self && [[area userInfo] objectForKey: @"Row"])
195            [self removeTrackingArea: area];
196    }
197}
198
199- (void) setControlButtonHover: (int) row
200{
201    fMouseControlRow = row;
202    if (row >= 0)
203        [self setNeedsDisplayInRect: [self rectOfRow: row]];
204}
205
206- (void) setRevealButtonHover: (int) row
207{
208    fMouseRevealRow = row;
209    if (row >= 0)
210        [self setNeedsDisplayInRect: [self rectOfRow: row]];
211}
212
213- (void) setActionButtonHover: (int) row
214{
215    fMouseActionRow = row;
216    if (row >= 0)
217        [self setNeedsDisplayInRect: [self rectOfRow: row]];
218}
219
220- (void) mouseEntered: (NSEvent *) event
221{
222    NSDictionary * dict = (NSDictionary *)[event userData];
223   
224    NSNumber * row;
225    if ((row = [dict objectForKey: @"Row"]))
226    {
227        int rowVal = [row intValue];
228        NSString * type = [dict objectForKey: @"Type"];
229        if ([type isEqualToString: @"Action"])
230            fMouseActionRow = rowVal;
231        else if ([type isEqualToString: @"Control"])
232            fMouseControlRow = rowVal;
233        else
234            fMouseRevealRow = rowVal;
235       
236        [self setNeedsDisplayInRect: [self rectOfRow: rowVal]];
237    }
238}
239
240- (void) mouseExited: (NSEvent *) event
241{
242    NSDictionary * dict = (NSDictionary *)[event userData];
243   
244    NSNumber * row;
245    if ((row = [dict objectForKey: @"Row"]))
246    {
247        NSString * type = [dict objectForKey: @"Type"];
248        if ([type isEqualToString: @"Action"])
249            fMouseActionRow = -1;
250        else if ([type isEqualToString: @"Control"])
251            fMouseControlRow = -1;
252        else
253            fMouseRevealRow = -1;
254       
255        [self setNeedsDisplayInRect: [self rectOfRow: [row intValue]]];
256    }
257}
258
259- (void) outlineViewSelectionIsChanging: (NSNotification *) notification
260{
261    if (fSelectedValues)
262        [self selectValues: fSelectedValues];
263}
264
265- (void) outlineViewItemDidExpand: (NSNotification *) notification
266{
267    int value = [[[[notification userInfo] objectForKey: @"NSObject"] objectForKey: @"Group"] intValue];
268    [fCollapsedGroups removeIndex: value >= 0 ? value : INT_MAX];
269   
270    [[NSNotificationCenter defaultCenter] postNotificationName: @"OutlineExpandCollapse" object: self];
271}
272
273- (void) outlineViewItemDidCollapse: (NSNotification *) notification
274{
275    int value = [[[[notification userInfo] objectForKey: @"NSObject"] objectForKey: @"Group"] intValue];
276    [fCollapsedGroups addIndex: value >= 0 ? value : INT_MAX];
277   
278    [[NSNotificationCenter defaultCenter] postNotificationName: @"OutlineExpandCollapse" object: self];
279}
280
281- (void) mouseDown: (NSEvent *) event
282{
283    NSPoint point = [self convertPoint: [event locationInWindow] fromView: nil];
284   
285    BOOL pushed = [self pointInControlRect: point] || [self pointInRevealRect: point] || [self pointInActionRect: point]
286                    || [self pointInProgressRect: point] || [self pointInMinimalStatusRect: point];
287   
288    //if pushing a button, don't change the selected rows
289    if (pushed)
290        fSelectedValues = [[self selectedValues] retain];
291   
292    [super mouseDown: event];
293   
294    [fSelectedValues release];
295    fSelectedValues = nil;
296   
297    //avoid weird behavior when showing menu by doing this after mouse down
298    if ([self pointInActionRect: point])
299    {
300        int row = [self rowAtPoint: point];
301       
302        fActionPushedRow = row;
303        [self setNeedsDisplayInRect: [self rectOfRow: row]]; //ensure button is pushed down
304       
305        [self displayTorrentMenuForEvent: event];
306       
307        fActionPushedRow = -1;
308        [self setNeedsDisplayInRect: [self rectOfRow: row]];
309    }
310    else if (!pushed && [event clickCount] == 2) //double click
311    {
312        id item = [self itemAtRow: [self rowAtPoint: point]];
313       
314        if ([item isKindOfClass: [Torrent class]])
315            [fController showInfo: nil];
316        else
317        {
318            if ([self isItemExpanded: item])
319                [self collapseItem: item];
320            else
321                [self expandItem: item];
322        }
323    }
324    else;
325}
326
327- (void) selectValues: (NSArray *) values
328{
329    NSMutableIndexSet * indexSet = [NSMutableIndexSet indexSet];
330   
331    NSEnumerator * enumerator = [values objectEnumerator];
332    id item;
333    while ((item = [enumerator nextObject]))
334    {
335        if ([item isKindOfClass: [Torrent class]])
336        {
337            NSUInteger index = [self rowForItem: item];
338            if (index != -1)
339                [indexSet addIndex: index];
340        }
341        else
342        {
343            int group = [[item objectForKey: @"Group"] intValue], i;
344            for (i = 0; i < [self numberOfRows]; i++)
345            {
346                id tableItem = [self itemAtRow: i];
347                if (![tableItem isKindOfClass: [Torrent class]] && [[tableItem objectForKey: @"Group"] intValue] == group)
348                {
349                    [indexSet addIndex: i];
350                    break;
351                }
352            }
353        }
354    }
355   
356    [self selectRowIndexes: indexSet byExtendingSelection: NO];
357}
358
359- (NSArray *) selectedValues
360{
361    NSIndexSet * selectedIndexes = [self selectedRowIndexes];
362    NSMutableArray * values = [NSMutableArray arrayWithCapacity: [selectedIndexes count]];
363   
364    NSUInteger i;
365    for (i = [selectedIndexes firstIndex]; i != NSNotFound; i = [selectedIndexes indexGreaterThanIndex: i])
366        [values addObject: [self itemAtRow: i]];
367   
368    return values;
369}
370
371- (NSArray *) selectedTorrents
372{
373    NSIndexSet * selectedIndexes = [self selectedRowIndexes];
374    NSMutableArray * torrents = [NSMutableArray array];
375   
376    NSUInteger i;
377    for (i = [selectedIndexes firstIndex]; i != NSNotFound; i = [selectedIndexes indexGreaterThanIndex: i])
378    {
379        id item = [self itemAtRow: i];
380        if ([item isKindOfClass: [Torrent class]])
381        {
382            if (![torrents containsObject: item])
383                [torrents addObject: item];
384        }
385        else
386            [torrents addObjectsFromArray: [item objectForKey: @"Torrents"]];
387    }
388   
389    return torrents;
390}
391
392- (NSMenu *) menuForEvent: (NSEvent *) event
393{
394    int row = [self rowAtPoint: [self convertPoint: [event locationInWindow] fromView: nil]];
395    if (row >= 0)
396    {
397        if (![self isRowSelected: row])
398            [self selectRowIndexes: [NSIndexSet indexSetWithIndex: row] byExtendingSelection: NO];
399        return fContextRow;
400    }
401    else
402    {
403        [self deselectAll: self];
404        return fContextNoRow;
405    }
406}
407
408//make sure that the pause buttons become orange when holding down the option key
409- (void) flagsChanged: (NSEvent *) event
410{
411    [self display];
412    [super flagsChanged: event];
413}
414
415- (void) toggleControlForTorrent: (Torrent *) torrent
416{
417    if ([torrent isActive])
418        [fController stopTorrents: [NSArray arrayWithObject: torrent]];
419    else
420    {
421        if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask)
422            [fController resumeTorrentsNoWait: [NSArray arrayWithObject: torrent]];
423        else if ([torrent waitingToStart])
424            [fController stopTorrents: [NSArray arrayWithObject: torrent]];
425        else
426            [fController resumeTorrents: [NSArray arrayWithObject: torrent]];
427    }
428}
429
430- (void) displayTorrentMenuForEvent: (NSEvent *) event
431{
432    int row = [self rowAtPoint: [self convertPoint: [event locationInWindow] fromView: nil]];
433    if (row < 0)
434        return;
435   
436    //get and update file menu
437    fMenuTorrent = [[self itemAtRow: row] retain];
438    NSMenu * fileMenu = [fMenuTorrent fileMenu];
439    [self updateFileMenu: fileMenu forFiles: [fMenuTorrent fileList]];
440   
441    //add file menu items to action menu
442    NSRange range = NSMakeRange(0, [fileMenu numberOfItems]);
443    [fActionMenu appendItemsFromMenu: fileMenu atIndexes: [NSIndexSet indexSetWithIndexesInRange: range] atBottom: YES];
444   
445    //place menu below button
446    NSRect rect = [fTorrentCell iconRectForBounds: [self frameOfCellAtColumn: 0 row: row]];
447    NSPoint location = rect.origin;
448    location.y += rect.size.height + 5.0;
449    location = [self convertPoint: location toView: nil];
450   
451    NSEvent * newEvent = [NSEvent mouseEventWithType: [event type] location: location
452        modifierFlags: [event modifierFlags] timestamp: [event timestamp] windowNumber: [event windowNumber]
453        context: [event context] eventNumber: [event eventNumber] clickCount: [event clickCount] pressure: [event pressure]];
454   
455    [NSMenu popUpContextMenu: fActionMenu withEvent: newEvent forView: self];
456   
457    //move file menu items back to the torrent's file menu
458    range.location = [fActionMenu numberOfItems] - range.length;
459    [fileMenu appendItemsFromMenu: fActionMenu atIndexes: [NSIndexSet indexSetWithIndexesInRange: range] atBottom: YES];
460   
461    [fMenuTorrent release];
462    fMenuTorrent = nil;
463}
464
465- (void) menuNeedsUpdate: (NSMenu *) menu
466{
467    //this method seems to be called when it shouldn't be
468    if (!fMenuTorrent || ![menu supermenu])
469        return;
470   
471    if (menu == fUploadMenu || menu == fDownloadMenu)
472    {
473        NSMenuItem * item;
474        if ([menu numberOfItems] == 4)
475        {
476            const int speedLimitActionValue[] = { 0, 5, 10, 20, 30, 40, 50, 75, 100, 150, 200, 250, 500, 750, -1 };
477           
478            int i;
479            for (i = 0; speedLimitActionValue[i] != -1; i++)
480            {
481                item = [[NSMenuItem alloc] initWithTitle: [NSString stringWithFormat: NSLocalizedString(@"%d KB/s",
482                        "Action menu -> upload/download limit"), speedLimitActionValue[i]] action: @selector(setQuickLimit:)
483                        keyEquivalent: @""];
484                [item setTarget: self];
485                [item setRepresentedObject: [NSNumber numberWithInt: speedLimitActionValue[i]]];
486                [menu addItem: item];
487                [item release];
488            }
489        }
490       
491        BOOL upload = menu == fUploadMenu;
492        int mode = [fMenuTorrent speedMode: upload];
493       
494        item = [menu itemWithTag: ACTION_MENU_LIMIT_TAG];
495        [item setState: mode == TR_SPEEDLIMIT_SINGLE ? NSOnState : NSOffState];
496        [item setTitle: [NSString stringWithFormat: NSLocalizedString(@"Limit (%d KB/s)",
497                            "torrent action menu -> upload/download limit"), [fMenuTorrent speedLimit: upload]]];
498       
499        item = [menu itemWithTag: ACTION_MENU_UNLIMITED_TAG];
500        [item setState: mode == TR_SPEEDLIMIT_UNLIMITED ? NSOnState : NSOffState];
501       
502        item = [menu itemWithTag: ACTION_MENU_GLOBAL_TAG];
503        [item setState: mode == TR_SPEEDLIMIT_GLOBAL ? NSOnState : NSOffState];
504    }
505    else if (menu == fRatioMenu)
506    {
507        NSMenuItem * item;
508        if ([menu numberOfItems] == 4)
509        {
510            const float ratioLimitActionValue[] = { 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, -1.0 };
511           
512            int i;
513            for (i = 0; ratioLimitActionValue[i] != -1.0; i++)
514            {
515                item = [[NSMenuItem alloc] initWithTitle: [NSString stringWithFormat: @"%.2f", ratioLimitActionValue[i]]
516                        action: @selector(setQuickRatio:) keyEquivalent: @""];
517                [item setTarget: self];
518                [item setRepresentedObject: [NSNumber numberWithFloat: ratioLimitActionValue[i]]];
519                [menu addItem: item];
520                [item release];
521            }
522        }
523       
524        int mode = [fMenuTorrent ratioSetting];
525       
526        item = [menu itemWithTag: ACTION_MENU_LIMIT_TAG];
527        [item setState: mode == NSOnState ? NSOnState : NSOffState];
528        [item setTitle: [NSString stringWithFormat: NSLocalizedString(@"Stop at Ratio (%.2f)", "torrent action menu -> ratio stop"),
529                            [fMenuTorrent ratioLimit]]];
530       
531        item = [menu itemWithTag: ACTION_MENU_UNLIMITED_TAG];
532        [item setState: mode == NSOffState ? NSOnState : NSOffState];
533       
534        item = [menu itemWithTag: ACTION_MENU_GLOBAL_TAG];
535        [item setState: mode == NSMixedState ? NSOnState : NSOffState];
536    }
537    else  //assume the menu is part of the file list
538    {
539        NSMenu * supermenu = [menu supermenu];
540        [self updateFileMenu: menu forFiles: [[[supermenu itemAtIndex: [supermenu indexOfItemWithSubmenu: menu]]
541                                                    representedObject] objectForKey: @"Children"]];
542    }
543}
544
545- (void) setQuickLimitMode: (id) sender
546{
547    int mode;
548    switch ([sender tag])
549    {
550        case ACTION_MENU_UNLIMITED_TAG:
551            mode = TR_SPEEDLIMIT_UNLIMITED;
552            break;
553        case ACTION_MENU_LIMIT_TAG:
554            mode = TR_SPEEDLIMIT_SINGLE;
555            break;
556        case ACTION_MENU_GLOBAL_TAG:
557            mode = TR_SPEEDLIMIT_GLOBAL;
558            break;
559        default:
560            return;
561    }
562   
563    [fMenuTorrent setSpeedMode: mode upload: [sender menu] == fUploadMenu];
564   
565    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateOptions" object: nil];
566}
567
568- (void) setQuickLimit: (id) sender
569{
570    BOOL upload = [sender menu] == fUploadMenu;
571    [fMenuTorrent setSpeedMode: TR_SPEEDLIMIT_SINGLE upload: upload];
572    [fMenuTorrent setSpeedLimit: [[sender representedObject] intValue] upload: upload];
573   
574    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateOptions" object: nil];
575}
576
577- (void) setQuickRatioMode: (id) sender
578{
579    int mode;
580    switch ([sender tag])
581    {
582        case ACTION_MENU_UNLIMITED_TAG:
583            mode = NSOffState;
584            break;
585        case ACTION_MENU_LIMIT_TAG:
586            mode = NSOnState;
587            break;
588        case ACTION_MENU_GLOBAL_TAG:
589            mode = NSMixedState;
590            break;
591        default:
592            return;
593    }
594   
595    [fMenuTorrent setRatioSetting: mode];
596   
597    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateOptions" object: nil];
598}
599
600- (void) setQuickRatio: (id) sender
601{
602    [fMenuTorrent setRatioSetting: NSOnState];
603    [fMenuTorrent setRatioLimit: [[sender representedObject] floatValue]];
604   
605    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateOptions" object: nil];
606}
607
608- (void) checkFile: (id) sender
609{
610    NSIndexSet * indexSet = [[sender representedObject] objectForKey: @"Indexes"];
611    [fMenuTorrent setFileCheckState: [sender state] != NSOnState ? NSOnState : NSOffState forIndexes: indexSet];
612   
613    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateStats" object: nil];
614}
615
616- (void) togglePiecesBar
617{
618    [self resizePiecesBarIncrement];
619   
620    if (!fPiecesBarTimer)
621    {
622        fPiecesBarTimer = [NSTimer scheduledTimerWithTimeInterval: PIECE_TIME target: self
623                            selector: @selector(resizePiecesBarIncrement) userInfo: nil repeats: YES];
624        [[NSRunLoop currentRunLoop] addTimer: fPiecesBarTimer forMode: NSModalPanelRunLoopMode];
625        [[NSRunLoop currentRunLoop] addTimer: fPiecesBarTimer forMode: NSEventTrackingRunLoopMode];
626    }
627}
628
629- (float) piecesBarPercent
630{
631    return fPiecesBarPercent;
632}
633
634@end
635
636@implementation TorrentTableView (Private)
637
638- (BOOL) pointInControlRect: (NSPoint) point
639{
640    int row = [self rowAtPoint: point];
641    if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]])
642        return NO;
643   
644    return NSPointInRect(point, [fTorrentCell controlButtonRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
645}
646
647- (BOOL) pointInRevealRect: (NSPoint) point
648{
649    int row = [self rowAtPoint: point];
650    if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]])
651        return NO;
652   
653    return NSPointInRect(point, [fTorrentCell revealButtonRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
654}
655
656- (BOOL) pointInActionRect: (NSPoint) point
657{
658    int row = [self rowAtPoint: point];
659    if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]])
660        return NO;
661   
662    return NSPointInRect(point, [fTorrentCell iconRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
663}
664
665- (BOOL) pointInProgressRect: (NSPoint) point
666{
667    int row = [self rowAtPoint: point];
668    if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]] || [fDefaults boolForKey: @"SmallView"])
669        return NO;
670   
671    TorrentCell * cell;
672    if ([NSApp isOnLeopardOrBetter])
673        cell = (TorrentCell *)[self preparedCellAtColumn: 0 row: row];
674    else
675    {
676        cell = fTorrentCell;
677        [cell setRepresentedObject: [self itemAtRow: row]];
678    }
679    return NSPointInRect(point, [cell progressRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
680}
681
682- (BOOL) pointInMinimalStatusRect: (NSPoint) point
683{
684    int row = [self rowAtPoint: point];
685    if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]] || ![fDefaults boolForKey: @"SmallView"])
686        return NO;
687   
688    TorrentCell * cell;
689    if ([NSApp isOnLeopardOrBetter])
690        cell = (TorrentCell *)[self preparedCellAtColumn: 0 row: row];
691    else
692    {
693        cell = fTorrentCell;
694        [cell setRepresentedObject: [self itemAtRow: row]];
695    }
696    return NSPointInRect(point, [cell minimalStatusRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
697}
698
699- (void) updateFileMenu: (NSMenu *) menu forFiles: (NSArray *) files
700{
701    BOOL create = [menu numberOfItems] <= 0;
702   
703    NSEnumerator * enumerator = [files objectEnumerator];
704    NSDictionary * dict;
705    NSMenuItem * item;
706    while ((dict = [enumerator nextObject]))
707    {
708        NSString * name = [dict objectForKey: @"Name"];
709       
710        if (create)
711        {
712            item = [[NSMenuItem alloc] initWithTitle: name action: @selector(checkFile:) keyEquivalent: @""];
713           
714            NSImage * icon;
715            if (![[dict objectForKey: @"IsFolder"] boolValue])
716                icon = [[NSWorkspace sharedWorkspace] iconForFileType: [name pathExtension]];
717            else
718            {
719                NSMenu * itemMenu = [[NSMenu alloc] initWithTitle: name];
720                [itemMenu setAutoenablesItems: NO];
721                [item setSubmenu: itemMenu];
722                [itemMenu setDelegate: self];
723                [itemMenu release];
724               
725                icon = [[NSWorkspace sharedWorkspace] iconForFileType: NSFileTypeForHFSTypeCode('fldr')];
726            }
727           
728            [item setRepresentedObject: dict];
729           
730            [icon setScalesWhenResized: YES];
731            [icon setSize: NSMakeSize(16.0, 16.0)];
732            [item setImage: icon];
733           
734            [menu addItem: item];
735            [item release];
736        }
737        else
738            item = [menu itemWithTitle: name];
739       
740        NSIndexSet * indexSet = [dict objectForKey: @"Indexes"];
741        [item setState: [fMenuTorrent checkForFiles: indexSet]];
742        [item setEnabled: [fMenuTorrent canChangeDownloadCheckForFiles: indexSet]];
743    }
744}
745
746- (void) resizePiecesBarIncrement
747{
748    BOOL done;
749    if ([fDefaults boolForKey: @"PiecesBar"])
750    {
751        fPiecesBarPercent = MIN(fPiecesBarPercent + PIECE_CHANGE, 1.0);
752        done = fPiecesBarPercent == 1.0;
753    }
754    else
755    {
756        fPiecesBarPercent = MAX(fPiecesBarPercent - PIECE_CHANGE, 0.0);
757        done = fPiecesBarPercent == 0.0;
758    }
759   
760    if (done)
761    {
762        [fPiecesBarTimer invalidate];
763        fPiecesBarTimer = nil;
764    }
765   
766    [self reloadData];
767}
768
769@end
Note: See TracBrowser for help on using the repository browser.