transmission: update from 2.13 to 2.22
[tomato.git] / release / src / router / transmission / macosx / TrackerTableView.m
blobaa9c678798793cedb8fe1c222dbc2144225b51a9
1 /******************************************************************************
2  * $Id: TrackerTableView.m 11617 2011-01-01 20:42:14Z 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  *****************************************************************************/
25 #import "TrackerTableView.h"
26 #import "NSApplicationAdditions.h"
27 #import "Torrent.h"
28 #import "TrackerNode.h"
30 @implementation TrackerTableView
32 - (void) mouseDown: (NSEvent *) event
34     [[self window] makeKeyWindow];
35     [super mouseDown: event];
38 - (void) setTorrent: (Torrent *) torrent
40     fTorrent = torrent;
43 - (void) setTrackers: (NSArray *) trackers
45     fTrackers = trackers;
48 - (void) copy: (id) sender
50     NSMutableArray * addresses = [NSMutableArray arrayWithCapacity: [fTrackers count]];
51     NSIndexSet * indexes = [self selectedRowIndexes];
52     for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
53     {
54         id item = [fTrackers objectAtIndex: i];
55         if (![item isKindOfClass: [TrackerNode class]])
56         {
57             for (++i; i < [fTrackers count] && [[fTrackers objectAtIndex: i] isKindOfClass: [TrackerNode class]]; ++i)
58                 [addresses addObject: [(TrackerNode *)[fTrackers objectAtIndex: i] fullAnnounceAddress]];
59             --i;
60         }
61         else
62             [addresses addObject: [(TrackerNode *)item fullAnnounceAddress]];
63     }
64     
65     NSString * text = [addresses componentsJoinedByString: @"\n"];
66     
67     NSPasteboard * pb = [NSPasteboard generalPasteboard];
68     if ([NSApp isOnSnowLeopardOrBetter])
69     {
70         [pb clearContents];
71         [pb writeObjects: [NSArray arrayWithObject: text]];
72     }
73     else
74     {
75         [pb declareTypes: [NSArray arrayWithObject: NSStringPboardType] owner: nil];
76         [pb setString: text forType: NSStringPboardType];
77     }
80 - (void) paste: (id) sender
82     NSAssert(fTorrent != nil, @"no torrent but trying to paste; should not be able to call this method");
83     
84     BOOL added = NO;
85     
86     if ([NSApp isOnSnowLeopardOrBetter])
87     {
88         NSArray * items = [[NSPasteboard generalPasteboard] readObjectsForClasses:
89                             [NSArray arrayWithObject: [NSString class]] options: nil];
90         NSAssert(items != nil, @"no string items to paste; should not be able to call this method");
91         
92         for (NSString * pbItem in items)
93         {
94             for (NSString * item in [pbItem componentsSeparatedByString: @"\n"])
95                 if ([fTorrent addTrackerToNewTier: item])
96                     added = YES;
97         }
98     }
99     else
100     {
101         NSString * pbItem =[[NSPasteboard generalPasteboard] stringForType: NSStringPboardType];
102         NSAssert(pbItem != nil, @"no string items to paste; should not be able to call this method");
103         
104         for (NSString * item in [pbItem componentsSeparatedByString: @"\n"])
105             if ([fTorrent addTrackerToNewTier: item])
106                 added = YES;
107     }
108     
109     //none added
110     if (!added)
111         NSBeep();
114 - (BOOL) validateMenuItem: (NSMenuItem *) menuItem
116     const SEL action = [menuItem action];
117     
118     if (action == @selector(copy:))
119         return [self numberOfSelectedRows] > 0;
120     
121     if (action == @selector(paste:))
122         return fTorrent && ([NSApp isOnSnowLeopardOrBetter]
123                 ? [[NSPasteboard generalPasteboard] canReadObjectForClasses: [NSArray arrayWithObject: [NSString class]] options: nil]
124                 : [[NSPasteboard generalPasteboard] availableTypeFromArray: [NSArray arrayWithObject: NSStringPboardType]] != nil);
125     
126     return YES;
129 //alternating rows - first row after group row is white
130 - (void) highlightSelectionInClipRect: (NSRect) clipRect
132     NSRect visibleRect = clipRect;
133     NSRange rows = [self rowsInRect: visibleRect];
134     BOOL start = YES;
135     
136     const CGFloat totalRowHeight = [self rowHeight] + [self intercellSpacing].height;
137     
138     NSRect gridRects[(NSInteger)(ceil(NSHeight(visibleRect) / totalRowHeight / 2.0)) + 1]; //add one if partial rows at top and bottom
139     NSInteger rectNum = 0;
140     
141     if (rows.length > 0)
142     {
143         //determine what the first row color should be
144         if ([[fTrackers objectAtIndex: rows.location] isKindOfClass: [TrackerNode class]] || [self editedRow] == rows.location)
145         {
146             for (NSInteger i = rows.location-1; i>=0; i--)
147             {
148                 if (![[fTrackers objectAtIndex: i] isKindOfClass: [TrackerNode class]])
149                     break;
150                 start = !start;
151             }
152         }
153         else
154         {
155             rows.location++;
156             rows.length--;
157         }
158         
159         NSInteger i;
160         for (i = rows.location; i < NSMaxRange(rows); i++)
161         {
162             if (![[fTrackers objectAtIndex: i] isKindOfClass: [TrackerNode class]] && [self editedRow] != i)
163             {
164                 start = YES;
165                 continue;
166             }
167             
168             if (!start && ![self isRowSelected: i])
169                 gridRects[rectNum++] = [self rectOfRow: i];
170             
171             start = !start;
172         }
173         
174         const CGFloat newY = NSMaxY([self rectOfRow: i-1]);
175         visibleRect.size.height -= newY - visibleRect.origin.y;
176         visibleRect.origin.y = newY;
177     }
178     
179     const NSInteger numberBlankRows = ceil(visibleRect.size.height / totalRowHeight);
180     
181     //remaining visible rows continue alternating
182     visibleRect.size.height = totalRowHeight;
183     if (start)
184         visibleRect.origin.y += totalRowHeight;
185     
186     for (NSInteger i = start ? 1 : 0; i < numberBlankRows; i += 2)
187     {
188         gridRects[rectNum++] = visibleRect;
189         visibleRect.origin.y += 2.0 * totalRowHeight;
190     }
191     
192     NSAssert([[NSColor controlAlternatingRowBackgroundColors] count] >= 2, @"There should be 2 alternating row colors");
193     
194     [[[NSColor controlAlternatingRowBackgroundColors] objectAtIndex: 1] set];
195     NSRectFillList(gridRects, rectNum);
196     
197     [super highlightSelectionInClipRect: clipRect];
200 @end