source: trunk/macosx/TorrentCell.m @ 3195

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

remove some leftovers from the advanced bar

  • Property svn:keywords set to Date Rev Author Id
File size: 16.1 KB
Line 
1/******************************************************************************
2 * $Id: TorrentCell.m 3195 2007-09-27 02:29:32Z livings124 $
3 *
4 * Copyright (c) 2006-2007 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 "TorrentCell.h"
26#import "TorrentTableView.h"
27#import "NSStringAdditions.h"
28#import "CTGradientAdditions.h"
29
30#define BAR_HEIGHT 12.0
31
32#define IMAGE_SIZE_REG 32.0
33#define IMAGE_SIZE_MIN 16.0
34
35//end up being larger than font height
36#define HEIGHT_TITLE 16.0
37#define HEIGHT_STATUS 12.0
38
39#define PADDING_HORIZONAL 2.0
40#define PADDING_ABOVE_IMAGE_REG 9.0
41#define PADDING_BETWEEN_IMAGE_AND_TITLE 5.0
42#define PADDING_BETWEEN_IMAGE_AND_BAR 7.0
43#define PADDING_ABOVE_TITLE 3.0
44#define PADDING_ABOVE_MIN_STATUS 4.0
45#define PADDING_BETWEEN_TITLE_AND_MIN_STATUS 2.0
46#define PADDING_BETWEEN_TITLE_AND_PROGRESS 1.0
47#define PADDING_BETWEEN_PROGRESS_AND_BAR 2.0
48#define PADDING_BETWEEN_TITLE_AND_BAR_MIN 3.0
49#define PADDING_BETWEEN_BAR_AND_STATUS 2.0
50
51#define MAX_PIECES 324
52#define BLANK_PIECE -99
53
54@interface TorrentCell (Private)
55
56- (void) drawBar: (NSRect) barRect;
57
58- (NSRect) rectForMinimalStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
59- (NSRect) rectForTitleWithString: (NSAttributedString *) string basedOnMinimalStatusRect: (NSRect) statusRect
60            inBounds: (NSRect) bounds;
61- (NSRect) rectForProgressWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
62- (NSRect) rectForStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
63
64- (NSAttributedString *) attributedTitleWithColor: (NSColor *) color;
65- (NSAttributedString *) attributedStatusString: (NSString *) string withColor: (NSColor *) color;
66
67@end
68
69@implementation TorrentCell
70
71//only called one, so don't worry about release
72- (id) init
73{
74    if ((self = [super init]))
75        {
76        fDefaults = [NSUserDefaults standardUserDefaults];
77       
78        NSMutableParagraphStyle * paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
79        [paragraphStyle setLineBreakMode: NSLineBreakByTruncatingTail];
80   
81        fTitleAttributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
82                                [NSFont messageFontOfSize: 12.0], NSFontAttributeName,
83                                paragraphStyle, NSParagraphStyleAttributeName, nil];
84        fStatusAttributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
85                                [NSFont messageFontOfSize: 9.0], NSFontAttributeName,
86                                paragraphStyle, NSParagraphStyleAttributeName, nil];
87        [paragraphStyle release];
88       
89        fBarOverlayColor = [[NSColor colorWithDeviceWhite: 0.0 alpha: 0.2] retain];
90    }
91        return self;
92}
93
94- (NSRect) iconRectForBounds: (NSRect) bounds
95{
96    NSRect result = bounds;
97   
98    result.origin.x += PADDING_HORIZONAL;
99   
100    float imageSize;
101    if ([fDefaults boolForKey: @"SmallView"])
102    {
103        imageSize = IMAGE_SIZE_MIN;
104        result.origin.y += (result.size.height - imageSize) * 0.5;
105    }
106    else
107    {
108        imageSize = IMAGE_SIZE_REG;
109        result.origin.y += PADDING_ABOVE_IMAGE_REG;
110    }
111   
112    result.size = NSMakeSize(imageSize, imageSize);
113   
114    return result;
115}
116
117- (NSRect) titleRectForBounds: (NSRect) bounds
118{
119    return [self rectForTitleWithString: [self attributedTitleWithColor: nil]
120            basedOnMinimalStatusRect: [self minimalStatusRectForBounds: bounds] inBounds: bounds];
121}
122
123- (NSRect) minimalStatusRectForBounds: (NSRect) bounds
124{
125    Torrent * torrent = [self representedObject];
126    NSString * string = [torrent isActive] && ![fDefaults boolForKey: @"DisplaySmallStatusRegular"]
127                            ? [torrent remainingTimeString] : [torrent shortStatusString];
128    return [self rectForMinimalStatusWithString: [self attributedStatusString: string withColor: nil] inBounds: bounds];
129}
130
131- (NSRect) progressRectForBounds: (NSRect) bounds
132{
133    return [self rectForProgressWithString: [self attributedStatusString: [[self representedObject] progressString] withColor: nil]
134                    inBounds: bounds];
135}
136
137- (NSRect) barRectForBounds: (NSRect) bounds
138{
139    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
140   
141    NSRect result = bounds;
142    result.size.height = BAR_HEIGHT;
143    result.origin.x = PADDING_HORIZONAL + (minimal ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG) + PADDING_BETWEEN_IMAGE_AND_BAR;
144   
145    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE;
146    if (minimal)
147        result.origin.y += PADDING_BETWEEN_TITLE_AND_BAR_MIN;
148    else
149        result.origin.y += PADDING_BETWEEN_TITLE_AND_PROGRESS + HEIGHT_STATUS + PADDING_BETWEEN_PROGRESS_AND_BAR;
150   
151    result.size.width = round(NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL - BUTTONS_TOTAL_WIDTH);
152   
153    return result;
154}
155
156- (NSRect) statusRectForBounds: (NSRect) bounds
157{
158    return [self rectForStatusWithString: [self attributedStatusString: [[self representedObject] statusString] withColor: nil]
159                    inBounds: bounds];
160}
161
162- (void) drawInteriorWithFrame: (NSRect) cellFrame inView: (NSView *) controlView
163{
164    [super drawInteriorWithFrame: cellFrame inView: controlView];
165   
166    Torrent * torrent = [self representedObject];
167   
168    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
169   
170    //error image
171    BOOL error = [torrent isError];
172    if (error && !fErrorImage)
173    {
174        fErrorImage = [[NSImage imageNamed: @"Error.png"] copy];
175        [fErrorImage setFlipped: YES];
176    }
177   
178    //icon
179    NSImage * icon = minimal && error ? fErrorImage : [torrent icon];
180    NSRect iconRect = [self iconRectForBounds: cellFrame];
181    [icon drawInRect: iconRect fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0];
182   
183    if (error && !minimal)
184    {
185        NSRect errorRect = NSMakeRect(NSMaxX(iconRect) - IMAGE_SIZE_MIN, NSMaxY(iconRect) - IMAGE_SIZE_MIN,
186                                        IMAGE_SIZE_MIN, IMAGE_SIZE_MIN);
187        [fErrorImage drawInRect: errorRect fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0];
188    }
189   
190    //text color
191    BOOL highlighted = [self isHighlighted] && [[self highlightColorWithFrame: cellFrame inView: controlView]
192                                                isEqual: [NSColor alternateSelectedControlColor]];
193    NSColor * titleColor, * statusColor;
194    if ([self isHighlighted]
195            && [[self highlightColorWithFrame: cellFrame inView: controlView] isEqual: [NSColor alternateSelectedControlColor]])
196    {
197        titleColor = [NSColor whiteColor];
198        statusColor = [NSColor whiteColor];
199    }
200    else
201    {
202        titleColor = [NSColor controlTextColor];
203        statusColor = [NSColor darkGrayColor];
204    }
205   
206    //minimal status
207    NSRect minimalStatusRect;
208    if (minimal)
209    {
210        NSString * string = [torrent isActive] && ![fDefaults boolForKey: @"DisplaySmallStatusRegular"]
211                                ? [torrent remainingTimeString] : [torrent shortStatusString];
212        NSAttributedString * minimalString = [self attributedStatusString: string withColor: statusColor];
213        minimalStatusRect = [self rectForMinimalStatusWithString: minimalString inBounds: cellFrame];
214       
215        [minimalString drawInRect: minimalStatusRect];
216    }
217   
218    //title
219    NSAttributedString * titleString = [self attributedTitleWithColor: titleColor];
220    NSRect titleRect = [self rectForTitleWithString: titleString basedOnMinimalStatusRect: minimalStatusRect inBounds: cellFrame];
221    [titleString drawInRect: titleRect];
222   
223    //progress
224    if (!minimal)
225    {
226        NSAttributedString * progressString = [self attributedStatusString: [torrent progressString] withColor: statusColor];
227        NSRect progressRect = [self rectForProgressWithString: progressString inBounds: cellFrame];
228        [progressString drawInRect: progressRect];
229    }
230   
231    //bar
232    NSRect barRect = [self barRectForBounds: cellFrame];
233    [self drawBar: barRect];
234   
235    //status
236    if (!minimal)
237    {
238        NSAttributedString * statusString = [self attributedStatusString: [torrent statusString] withColor: statusColor];
239        [statusString drawInRect: [self rectForStatusWithString: statusString inBounds: cellFrame]];
240    }
241}
242
243@end
244
245@implementation TorrentCell (Private)
246
247- (void) drawBar: (NSRect) barRect
248{
249    Torrent * torrent = [self representedObject];
250   
251    int leftWidth = barRect.size.width;
252    float progress = [torrent progress];
253   
254    if (progress < 1.0)
255    {
256        float rightProgress = 1.0 - progress, progressLeft = [torrent progressLeft];
257        int rightWidth = leftWidth * rightProgress;
258        leftWidth -= rightWidth;
259       
260        if (progressLeft < rightProgress)
261        {
262            int rightNoIncludeWidth = rightWidth * ((rightProgress - progressLeft) / rightProgress);
263            rightWidth -= rightNoIncludeWidth;
264           
265            NSRect noIncludeRect = barRect;
266            noIncludeRect.origin.x += barRect.size.width - rightNoIncludeWidth;
267            noIncludeRect.size.width = rightNoIncludeWidth;
268           
269            if (!fLightGrayGradient)
270                fLightGrayGradient = [[CTGradient progressLightGrayGradient] retain];
271            [fLightGrayGradient fillRect: noIncludeRect angle: -90];
272        }
273       
274        if (rightWidth > 0)
275        {
276            NSRect includeRect = barRect;
277            includeRect.origin.x += leftWidth;
278            includeRect.size.width = rightWidth;
279           
280            if (!fWhiteGradient)
281                fWhiteGradient = [[CTGradient progressWhiteGradient] retain];
282            [fWhiteGradient fillRect: includeRect angle: -90];
283        }
284    }
285   
286    if (leftWidth > 0)
287    {
288        NSRect completeRect = barRect;
289        completeRect.size.width = leftWidth;
290       
291        if ([torrent isActive])
292        {
293            if ([torrent isChecking])
294            {
295                if (!fYellowGradient)
296                    fYellowGradient = [[CTGradient progressYellowGradient] retain];
297                [fYellowGradient fillRect: completeRect angle: -90];
298            }
299            else if ([torrent isSeeding])
300            {
301                int ratioLeftWidth = leftWidth * (1.0 - [torrent progressStopRatio]);
302                leftWidth -= ratioLeftWidth;
303               
304                if (ratioLeftWidth > 0)
305                {
306                    NSRect ratioLeftRect = barRect;
307                    ratioLeftRect.origin.x += leftWidth;
308                    ratioLeftRect.size.width = ratioLeftWidth;
309                   
310                    if (!fLightGreenGradient)
311                        fLightGreenGradient = [[CTGradient progressLightGreenGradient] retain];
312                    [fLightGreenGradient fillRect: ratioLeftRect angle: -90];
313                }
314               
315                if (leftWidth > 0)
316                {
317                    completeRect.size.width = leftWidth;
318                   
319                    if (!fGreenGradient)
320                        fGreenGradient = [[CTGradient progressGreenGradient] retain];
321                    [fGreenGradient fillRect: completeRect angle: -90];
322                }
323            }
324            else
325            {
326                if (!fBlueGradient)
327                    fBlueGradient = [[CTGradient progressBlueGradient] retain];
328                [fBlueGradient fillRect: completeRect angle: -90];
329            }
330        }
331        else
332        {
333            if ([torrent waitingToStart])
334            {
335                if ([torrent progressLeft] <= 0.0)
336                {
337                    if (!fDarkGreenGradient)
338                        fDarkGreenGradient = [[CTGradient progressDarkGreenGradient] retain];
339                    [fDarkGreenGradient fillRect: completeRect angle: -90];
340                }
341                else
342                {
343                    if (!fDarkBlueGradient)
344                        fDarkBlueGradient = [[CTGradient progressDarkBlueGradient] retain];
345                    [fDarkBlueGradient fillRect: completeRect angle: -90];
346                }
347            }
348            else
349            {
350                if (!fGrayGradient)
351                    fGrayGradient = [[CTGradient progressGrayGradient] retain];
352                [fGrayGradient fillRect: completeRect angle: -90];
353            }
354        }
355    }
356   
357    [fBarOverlayColor set];
358    [NSBezierPath strokeRect: NSInsetRect(barRect, 0.5, 0.5)];
359}
360
361- (NSRect) rectForMinimalStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
362{
363    if (![fDefaults boolForKey: @"SmallView"])
364        return NSZeroRect;
365   
366    NSRect result = bounds;
367    result.size = [string size];
368   
369    result.origin.x += bounds.size.width - result.size.width - PADDING_HORIZONAL;
370    result.origin.y += PADDING_ABOVE_MIN_STATUS;
371   
372    return result;
373}
374
375- (NSRect) rectForTitleWithString: (NSAttributedString *) string basedOnMinimalStatusRect: (NSRect) statusRect
376            inBounds: (NSRect) bounds
377{
378    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
379   
380    NSRect result = bounds;
381    result.origin.y += PADDING_ABOVE_TITLE;
382    result.origin.x += PADDING_HORIZONAL + (minimal ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG) + PADDING_BETWEEN_IMAGE_AND_TITLE;
383   
384    result.size = [string size];
385    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL
386                            - (minimal ? PADDING_BETWEEN_TITLE_AND_MIN_STATUS + statusRect.size.width : 0));
387   
388    return result;
389}
390
391- (NSRect) rectForProgressWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
392{
393    if ([fDefaults boolForKey: @"SmallView"])
394        return NSZeroRect;
395   
396    NSRect result = bounds;
397    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE + PADDING_BETWEEN_TITLE_AND_PROGRESS;
398    result.origin.x += PADDING_HORIZONAL + IMAGE_SIZE_REG + PADDING_BETWEEN_IMAGE_AND_TITLE;
399   
400    result.size = [string size];
401    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL);
402   
403    return result;
404}
405
406- (NSRect) rectForStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
407{
408    if ([fDefaults boolForKey: @"SmallView"])
409        return NSZeroRect;
410   
411    NSRect result = bounds;
412    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE + PADDING_BETWEEN_TITLE_AND_PROGRESS + HEIGHT_STATUS
413                        + PADDING_BETWEEN_PROGRESS_AND_BAR + BAR_HEIGHT + PADDING_BETWEEN_BAR_AND_STATUS;
414    result.origin.x += PADDING_HORIZONAL + IMAGE_SIZE_REG + PADDING_BETWEEN_IMAGE_AND_TITLE;
415   
416    result.size = [string size];
417    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL);
418   
419    return result;
420}
421
422- (NSAttributedString *) attributedTitleWithColor: (NSColor *) color
423{
424    if (color)
425        [fTitleAttributes setObject: color forKey: NSForegroundColorAttributeName];
426   
427    NSString * title = [[self representedObject] name];
428    return [[[NSAttributedString alloc] initWithString: title attributes: fTitleAttributes] autorelease];
429}
430
431- (NSAttributedString *) attributedStatusString: (NSString *) string withColor: (NSColor *) color
432{
433    if (color)
434        [fStatusAttributes setObject: color forKey: NSForegroundColorAttributeName];
435   
436    return [[[NSAttributedString alloc] initWithString: string attributes: fStatusAttributes] autorelease];
437}
438
439@end
Note: See TracBrowser for help on using the repository browser.