~ubuntu-branches/ubuntu/hardy/transmission/hardy-updates

« back to all changes in this revision

Viewing changes to macosx/TorrentCell.m

  • Committer: Bazaar Package Importer
  • Author(s): Philipp Benner
  • Date: 2008-01-05 09:16:52 UTC
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: james.westby@ubuntu.com-20080105091652-8cf0z4rb3pu8d6jt
Tags: upstream-1.00
ImportĀ upstreamĀ versionĀ 1.00

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 * $Id: TorrentCell.m 4423 2008-01-02 16:55:05Z livings124 $
 
3
 *
 
4
 * Copyright (c) 2006-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 "TorrentCell.h"
 
26
#import "TorrentTableView.h"
 
27
#import "GroupsWindowController.h"
 
28
#import "NSApplicationAdditions.h"
 
29
#import "NSStringAdditions.h"
 
30
#import "NSBezierPathAdditions.h"
 
31
#import "CTGradientAdditions.h"
 
32
 
 
33
#define BAR_HEIGHT 12.0
 
34
 
 
35
#define IMAGE_SIZE_REG 32.0
 
36
#define IMAGE_SIZE_MIN 16.0
 
37
 
 
38
//end up being larger than font height
 
39
#define HEIGHT_TITLE 16.0
 
40
#define HEIGHT_STATUS 12.0
 
41
 
 
42
#define PADDING_HORIZONAL 2.0
 
43
#define PADDING_ABOVE_IMAGE_REG 9.0
 
44
#define PADDING_BETWEEN_IMAGE_AND_TITLE 5.0
 
45
#define PADDING_BETWEEN_IMAGE_AND_BAR 7.0
 
46
#define PADDING_ABOVE_TITLE 3.0
 
47
#define PADDING_ABOVE_MIN_STATUS 4.0
 
48
#define PADDING_BETWEEN_TITLE_AND_MIN_STATUS 2.0
 
49
#define PADDING_BETWEEN_TITLE_AND_PROGRESS 1.0
 
50
#define PADDING_BETWEEN_PROGRESS_AND_BAR 2.0
 
51
#define PADDING_BETWEEN_TITLE_AND_BAR_MIN 3.0
 
52
#define PADDING_BETWEEN_BAR_AND_STATUS 2.0
 
53
 
 
54
#define WIDTH_GROUP 40.0
 
55
#define WIDTH_GROUP_MIN 24.0
 
56
 
 
57
#define MAX_PIECES 324
 
58
 
 
59
@interface TorrentCell (Private)
 
60
 
 
61
- (void) drawBar: (NSRect) barRect;
 
62
- (void) drawRegularBar: (NSRect) barRect;
 
63
- (void) drawPiecesBar: (NSRect) barRect;
 
64
 
 
65
- (NSRect) rectForMinimalStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
 
66
- (NSRect) rectForTitleWithString: (NSAttributedString *) string basedOnMinimalStatusRect: (NSRect) statusRect
 
67
            inBounds: (NSRect) bounds;
 
68
- (NSRect) rectForProgressWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
 
69
- (NSRect) rectForStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
 
70
 
 
71
- (NSAttributedString *) attributedTitleWithColor: (NSColor *) color;
 
72
- (NSAttributedString *) attributedStatusString: (NSString *) string withColor: (NSColor *) color;
 
73
 
 
74
@end
 
75
 
 
76
@implementation TorrentCell
 
77
 
 
78
//only called once, so don't worry about releasing
 
79
- (id) init
 
80
{
 
81
    if ((self = [super init]))
 
82
        {
 
83
        fDefaults = [NSUserDefaults standardUserDefaults];
 
84
        
 
85
        NSMutableParagraphStyle * paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
 
86
        [paragraphStyle setLineBreakMode: NSLineBreakByTruncatingTail];
 
87
    
 
88
        fTitleAttributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
 
89
                                [NSFont messageFontOfSize: 12.0], NSFontAttributeName,
 
90
                                paragraphStyle, NSParagraphStyleAttributeName, nil];
 
91
        fStatusAttributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
 
92
                                [NSFont messageFontOfSize: 9.0], NSFontAttributeName,
 
93
                                paragraphStyle, NSParagraphStyleAttributeName, nil];
 
94
        [paragraphStyle release];
 
95
        
 
96
        //store box colors
 
97
        fGrayColor = [[NSColor colorWithCalibratedRed: 0.9 green: 0.9 blue: 0.9 alpha: 1.0] retain];
 
98
        fBlue1Color = [[NSColor colorWithCalibratedRed: 0.8 green: 1.0 blue: 1.0 alpha: 1.0] retain];
 
99
        fBlue2Color = [[NSColor colorWithCalibratedRed: 0.6 green: 1.0 blue: 1.0 alpha: 1.0] retain];
 
100
        fBlue3Color = [[NSColor colorWithCalibratedRed: 0.6 green: 0.8 blue: 1.0 alpha: 1.0] retain];
 
101
        fBlue4Color = [[NSColor colorWithCalibratedRed: 0.4 green: 0.6 blue: 1.0 alpha: 1.0] retain];
 
102
        fBlueColor = [[NSColor colorWithCalibratedRed: 0.0 green: 0.4 blue: 0.8 alpha: 1.0] retain];
 
103
        fOrangeColor = [[NSColor orangeColor] retain];
 
104
        
 
105
        fBarOverlayColor = [[NSColor colorWithDeviceWhite: 0.0 alpha: 0.2] retain];
 
106
    }
 
107
        return self;
 
108
}
 
109
 
 
110
- (id) copyWithZone: (NSZone *) zone
 
111
{
 
112
    TorrentCell * copy = [super copyWithZone: zone];
 
113
    copy->fBitmap = nil;
 
114
    
 
115
    return copy;
 
116
}
 
117
 
 
118
- (void) dealloc
 
119
{
 
120
    [fBitmap release];
 
121
    [super dealloc];
 
122
}
 
123
 
 
124
- (NSRect) iconRectForBounds: (NSRect) bounds
 
125
{
 
126
    NSRect result = bounds;
 
127
    
 
128
    result.origin.x += PADDING_HORIZONAL;
 
129
    
 
130
    float imageSize;
 
131
    if ([fDefaults boolForKey: @"SmallView"])
 
132
    {
 
133
        imageSize = IMAGE_SIZE_MIN;
 
134
        result.origin.y += (result.size.height - imageSize) * 0.5;
 
135
    }
 
136
    else
 
137
    {
 
138
        imageSize = IMAGE_SIZE_REG;
 
139
        result.origin.y += PADDING_ABOVE_IMAGE_REG;
 
140
    }
 
141
    
 
142
    result.size = NSMakeSize(imageSize, imageSize);
 
143
    
 
144
    return result;
 
145
}
 
146
 
 
147
- (NSRect) titleRectForBounds: (NSRect) bounds
 
148
{
 
149
    return [self rectForTitleWithString: [self attributedTitleWithColor: nil]
 
150
            basedOnMinimalStatusRect: [self minimalStatusRectForBounds: bounds] inBounds: bounds];
 
151
}
 
152
 
 
153
- (NSRect) minimalStatusRectForBounds: (NSRect) bounds
 
154
{
 
155
    Torrent * torrent = [self representedObject];
 
156
    NSString * string = [fDefaults boolForKey: @"DisplaySmallStatusRegular"]
 
157
                            ? [torrent shortStatusString] : [torrent remainingTimeString];
 
158
    return [self rectForMinimalStatusWithString: [self attributedStatusString: string withColor: nil] inBounds: bounds];
 
159
}
 
160
 
 
161
- (NSRect) progressRectForBounds: (NSRect) bounds
 
162
{
 
163
    return [self rectForProgressWithString: [self attributedStatusString: [[self representedObject] progressString] withColor: nil]
 
164
                    inBounds: bounds];
 
165
}
 
166
 
 
167
- (NSRect) barRectForBounds: (NSRect) bounds
 
168
{
 
169
    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
 
170
    
 
171
    NSRect result = bounds;
 
172
    result.size.height = BAR_HEIGHT;
 
173
    result.origin.x = PADDING_HORIZONAL + (minimal ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG) + PADDING_BETWEEN_IMAGE_AND_BAR;
 
174
    
 
175
    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE;
 
176
    if (minimal)
 
177
        result.origin.y += PADDING_BETWEEN_TITLE_AND_BAR_MIN;
 
178
    else
 
179
        result.origin.y += PADDING_BETWEEN_TITLE_AND_PROGRESS + HEIGHT_STATUS + PADDING_BETWEEN_PROGRESS_AND_BAR;
 
180
    
 
181
    result.size.width = round(NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL - BUTTONS_TOTAL_WIDTH);
 
182
    
 
183
    return result;
 
184
}
 
185
 
 
186
- (NSRect) statusRectForBounds: (NSRect) bounds
 
187
{
 
188
    return [self rectForStatusWithString: [self attributedStatusString: [[self representedObject] statusString] withColor: nil]
 
189
                    inBounds: bounds];
 
190
}
 
191
 
 
192
- (NSUInteger) hitTestForEvent: (NSEvent *) event inRect: (NSRect) cellFrame ofView: (NSView *) controlView
 
193
{
 
194
    return NSCellHitContentArea;
 
195
}
 
196
 
 
197
- (void) drawWithFrame: (NSRect) cellFrame inView: (NSView *) controlView
 
198
{
 
199
    [super drawWithFrame: cellFrame inView: controlView];
 
200
    
 
201
    Torrent * torrent = [self representedObject];
 
202
    
 
203
    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
 
204
    
 
205
    //group coloring
 
206
    NSRect iconRect = [self iconRectForBounds: cellFrame];
 
207
    
 
208
    int groupValue = [torrent groupValue];
 
209
    if (groupValue != -1)
 
210
    {
 
211
        NSRect groupRect = NSInsetRect(iconRect, -2.0, -3.0);
 
212
        if (!minimal)
 
213
        {
 
214
            groupRect.size.height--;
 
215
            groupRect.origin.y--;
 
216
        }
 
217
        
 
218
        [[[GroupsWindowController groups] gradientForIndex: groupValue] fillBezierPath:
 
219
            [NSBezierPath bezierPathWithRoundedRect: groupRect radius: 6.0] angle: 90.0];
 
220
    }
 
221
    
 
222
    //error image
 
223
    BOOL error = [torrent isError];
 
224
    if (error && !fErrorImage)
 
225
    {
 
226
        fErrorImage = [[NSImage imageNamed: @"Error.png"] copy];
 
227
        [fErrorImage setFlipped: YES];
 
228
    }
 
229
    
 
230
    //icon
 
231
    NSImage * icon = minimal && error ? fErrorImage : [torrent icon];
 
232
    [icon drawInRect: iconRect fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0];
 
233
    
 
234
    if (error && !minimal)
 
235
    {
 
236
        NSRect errorRect = NSMakeRect(NSMaxX(iconRect) - IMAGE_SIZE_MIN, NSMaxY(iconRect) - IMAGE_SIZE_MIN,
 
237
                                        IMAGE_SIZE_MIN, IMAGE_SIZE_MIN);
 
238
        [fErrorImage drawInRect: errorRect fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0];
 
239
    }
 
240
    
 
241
    //text color
 
242
    NSColor * titleColor, * statusColor;
 
243
    if ([NSApp isOnLeopardOrBetter] ? [self backgroundStyle] == NSBackgroundStyleDark : [self isHighlighted]
 
244
        && [[self highlightColorWithFrame: cellFrame inView: controlView] isEqual: [NSColor alternateSelectedControlColor]])
 
245
    {
 
246
        titleColor = [NSColor whiteColor];
 
247
        statusColor = [NSColor whiteColor];
 
248
    }
 
249
    else
 
250
    {
 
251
        titleColor = [NSColor controlTextColor];
 
252
        statusColor = [NSColor darkGrayColor];
 
253
    }
 
254
    
 
255
    //minimal status
 
256
    NSRect minimalStatusRect;
 
257
    if (minimal)
 
258
    {
 
259
        NSString * string = [fDefaults boolForKey: @"DisplaySmallStatusRegular"]
 
260
                            ? [torrent shortStatusString] : [torrent remainingTimeString];
 
261
        NSAttributedString * minimalString = [self attributedStatusString: string withColor: statusColor];
 
262
        minimalStatusRect = [self rectForMinimalStatusWithString: minimalString inBounds: cellFrame];
 
263
        
 
264
        [minimalString drawInRect: minimalStatusRect];
 
265
    }
 
266
    
 
267
    //title
 
268
    NSAttributedString * titleString = [self attributedTitleWithColor: titleColor];
 
269
    NSRect titleRect = [self rectForTitleWithString: titleString basedOnMinimalStatusRect: minimalStatusRect inBounds: cellFrame];
 
270
    [titleString drawInRect: titleRect];
 
271
    
 
272
    //progress
 
273
    if (!minimal)
 
274
    {
 
275
        NSAttributedString * progressString = [self attributedStatusString: [torrent progressString] withColor: statusColor];
 
276
        NSRect progressRect = [self rectForProgressWithString: progressString inBounds: cellFrame];
 
277
        [progressString drawInRect: progressRect];
 
278
    }
 
279
    
 
280
    //bar
 
281
    [self drawBar: [self barRectForBounds: cellFrame]];
 
282
    
 
283
    //status
 
284
    if (!minimal)
 
285
    {
 
286
        NSAttributedString * statusString = [self attributedStatusString: [torrent statusString] withColor: statusColor];
 
287
        [statusString drawInRect: [self rectForStatusWithString: statusString inBounds: cellFrame]];
 
288
    }
 
289
}
 
290
 
 
291
@end
 
292
 
 
293
@implementation TorrentCell (Private)
 
294
 
 
295
- (void) drawBar: (NSRect) barRect
 
296
{
 
297
    if ([fDefaults boolForKey: @"PiecesBar"])
 
298
    {
 
299
        NSRect regularBarRect = barRect, piecesBarRect = barRect;
 
300
        regularBarRect.size.height /= 2.5;
 
301
        piecesBarRect.origin.y += regularBarRect.size.height;
 
302
        piecesBarRect.size.height -= regularBarRect.size.height;
 
303
        
 
304
        [self drawRegularBar: regularBarRect];
 
305
        [self drawPiecesBar: piecesBarRect];
 
306
    }
 
307
    else
 
308
    {
 
309
        [fBitmap release];
 
310
        fBitmap = nil;
 
311
        [[self representedObject] setPreviousAmountFinished: NULL];
 
312
        
 
313
        [self drawRegularBar: barRect];
 
314
    }
 
315
    
 
316
    [fBarOverlayColor set];
 
317
    [NSBezierPath strokeRect: NSInsetRect(barRect, 0.5, 0.5)];
 
318
}
 
319
 
 
320
- (void) drawRegularBar: (NSRect) barRect
 
321
{
 
322
    Torrent * torrent = [self representedObject];
 
323
    
 
324
    int leftWidth = barRect.size.width;
 
325
    float progress = [torrent progress];
 
326
    
 
327
    if (progress < 1.0)
 
328
    {
 
329
        float rightProgress = 1.0 - progress, progressLeft = [torrent progressLeft];
 
330
        int rightWidth = leftWidth * rightProgress;
 
331
        leftWidth -= rightWidth;
 
332
        
 
333
        if (progressLeft < rightProgress)
 
334
        {
 
335
            int rightNoIncludeWidth = rightWidth * ((rightProgress - progressLeft) / rightProgress);
 
336
            rightWidth -= rightNoIncludeWidth;
 
337
            
 
338
            NSRect noIncludeRect = barRect;
 
339
            noIncludeRect.origin.x += barRect.size.width - rightNoIncludeWidth;
 
340
            noIncludeRect.size.width = rightNoIncludeWidth;
 
341
            
 
342
            if (!fLightGrayGradient)
 
343
                fLightGrayGradient = [[CTGradient progressLightGrayGradient] retain];
 
344
            [fLightGrayGradient fillRect: noIncludeRect angle: -90];
 
345
        }
 
346
        
 
347
        if (rightWidth > 0)
 
348
        {
 
349
            if ([torrent isActive] && ![torrent allDownloaded] && [fDefaults boolForKey: @"DisplayProgressBarAvailable"])
 
350
            {
 
351
                int notAvailableWidth = MIN(ceil(barRect.size.width * [torrent notAvailableDesired]), rightWidth);
 
352
                rightWidth -= notAvailableWidth;
 
353
                
 
354
                if (notAvailableWidth > 0)
 
355
                {
 
356
                    NSRect notAvailableRect = barRect;
 
357
                    notAvailableRect.origin.x += leftWidth + rightWidth;
 
358
                    notAvailableRect.size.width = notAvailableWidth;
 
359
                    
 
360
                    if (!fRedGradient)
 
361
                        fRedGradient = [[CTGradient progressRedGradient] retain];
 
362
                    [fRedGradient fillRect: notAvailableRect angle: -90];
 
363
                }
 
364
            }
 
365
            
 
366
            if (rightWidth > 0)
 
367
            {
 
368
                NSRect includeRect = barRect;
 
369
                includeRect.origin.x += leftWidth;
 
370
                includeRect.size.width = rightWidth;
 
371
                
 
372
                if (!fWhiteGradient)
 
373
                    fWhiteGradient = [[CTGradient progressWhiteGradient] retain];
 
374
                [fWhiteGradient fillRect: includeRect angle: -90];
 
375
            }
 
376
        }
 
377
    }
 
378
    
 
379
    if (leftWidth > 0)
 
380
    {
 
381
        NSRect completeRect = barRect;
 
382
        completeRect.size.width = leftWidth;
 
383
        
 
384
        if ([torrent isActive])
 
385
        {
 
386
            if ([torrent isChecking])
 
387
            {
 
388
                if (!fYellowGradient)
 
389
                    fYellowGradient = [[CTGradient progressYellowGradient] retain];
 
390
                [fYellowGradient fillRect: completeRect angle: -90];
 
391
            }
 
392
            else if ([torrent isSeeding])
 
393
            {
 
394
                int ratioLeftWidth = leftWidth * (1.0 - [torrent progressStopRatio]);
 
395
                leftWidth -= ratioLeftWidth;
 
396
                
 
397
                if (ratioLeftWidth > 0)
 
398
                {
 
399
                    NSRect ratioLeftRect = barRect;
 
400
                    ratioLeftRect.origin.x += leftWidth;
 
401
                    ratioLeftRect.size.width = ratioLeftWidth;
 
402
                    
 
403
                    if (!fLightGreenGradient)
 
404
                        fLightGreenGradient = [[CTGradient progressLightGreenGradient] retain];
 
405
                    [fLightGreenGradient fillRect: ratioLeftRect angle: -90];
 
406
                }
 
407
                
 
408
                if (leftWidth > 0)
 
409
                {
 
410
                    completeRect.size.width = leftWidth;
 
411
                    
 
412
                    if (!fGreenGradient)
 
413
                        fGreenGradient = [[CTGradient progressGreenGradient] retain];
 
414
                    [fGreenGradient fillRect: completeRect angle: -90];
 
415
                }
 
416
            }
 
417
            else
 
418
            {
 
419
                if (!fBlueGradient)
 
420
                    fBlueGradient = [[CTGradient progressBlueGradient] retain];
 
421
                [fBlueGradient fillRect: completeRect angle: -90];
 
422
            }
 
423
        }
 
424
        else
 
425
        {
 
426
            if ([torrent waitingToStart])
 
427
            {
 
428
                if ([torrent progressLeft] <= 0.0)
 
429
                {
 
430
                    if (!fDarkGreenGradient)
 
431
                        fDarkGreenGradient = [[CTGradient progressDarkGreenGradient] retain];
 
432
                    [fDarkGreenGradient fillRect: completeRect angle: -90];
 
433
                }
 
434
                else
 
435
                {
 
436
                    if (!fDarkBlueGradient)
 
437
                        fDarkBlueGradient = [[CTGradient progressDarkBlueGradient] retain];
 
438
                    [fDarkBlueGradient fillRect: completeRect angle: -90];
 
439
                }
 
440
            }
 
441
            else
 
442
            {
 
443
                if (!fGrayGradient)
 
444
                    fGrayGradient = [[CTGradient progressGrayGradient] retain];
 
445
                [fGrayGradient fillRect: completeRect angle: -90];
 
446
            }
 
447
        }
 
448
    }
 
449
}
 
450
 
 
451
- (void) drawPiecesBar: (NSRect) barRect
 
452
{
 
453
    if (!fBitmap)
 
454
        fBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: nil
 
455
            pixelsWide: MAX_PIECES pixelsHigh: barRect.size.height bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES
 
456
            isPlanar: NO colorSpaceName: NSCalibratedRGBColorSpace bytesPerRow: 0 bitsPerPixel: 0];
 
457
    
 
458
    Torrent * torrent = [self representedObject];
 
459
    
 
460
    int pieceCount = MIN([torrent pieceCount], MAX_PIECES);
 
461
    float * piecePercent = malloc(pieceCount * sizeof(float)),
 
462
        * previousPiecePercent = [torrent getPreviousAmountFinished];
 
463
    [torrent getAmountFinished: piecePercent size: pieceCount];
 
464
    
 
465
    int i, h, index;
 
466
    float increment = (float)pieceCount / MAX_PIECES;
 
467
    NSColor * pieceColor;
 
468
    for (i = 0; i < MAX_PIECES; i++)
 
469
    {
 
470
        index = i * increment;
 
471
        if (piecePercent[index] >= 1.0)
 
472
        {
 
473
            if (previousPiecePercent != NULL && previousPiecePercent[index] < 1.0)
 
474
                pieceColor = fOrangeColor;
 
475
            else
 
476
                pieceColor = fBlueColor;
 
477
        }
 
478
        else if (piecePercent[index] <= 0.0)
 
479
            pieceColor = fGrayColor;
 
480
        else if (piecePercent[index] <= 0.25)
 
481
            pieceColor = fBlue1Color;
 
482
        else if (piecePercent[index] <= 0.5)
 
483
            pieceColor = fBlue2Color;
 
484
        else if (piecePercent[index] <= 0.75)
 
485
            pieceColor = fBlue3Color;
 
486
        else
 
487
            pieceColor = fBlue4Color;
 
488
        
 
489
        if (![pieceColor isEqual: [fBitmap colorAtX: i y: 0]])
 
490
            for (h = 0; h < barRect.size.height; h++)
 
491
                [fBitmap setColor: pieceColor atX: i y: h];
 
492
    }
 
493
    
 
494
    [torrent setPreviousAmountFinished: piecePercent];
 
495
    
 
496
    //actually draw image
 
497
    [fBitmap drawInRect: barRect];
 
498
    
 
499
    if (!fTransparentGradient)
 
500
        fTransparentGradient = [[CTGradient progressTransparentGradient] retain];
 
501
    [fTransparentGradient fillRect: barRect angle: -90];
 
502
}
 
503
 
 
504
- (NSRect) rectForMinimalStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
 
505
{
 
506
    if (![fDefaults boolForKey: @"SmallView"])
 
507
        return NSZeroRect;
 
508
    
 
509
    NSRect result = bounds;
 
510
    result.size = [string size];
 
511
    
 
512
    result.origin.x += bounds.size.width - result.size.width - PADDING_HORIZONAL;
 
513
    result.origin.y += PADDING_ABOVE_MIN_STATUS;
 
514
    
 
515
    return result;
 
516
}
 
517
 
 
518
- (NSRect) rectForTitleWithString: (NSAttributedString *) string basedOnMinimalStatusRect: (NSRect) statusRect
 
519
            inBounds: (NSRect) bounds
 
520
{
 
521
    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
 
522
    
 
523
    NSRect result = bounds;
 
524
    result.origin.y += PADDING_ABOVE_TITLE;
 
525
    result.origin.x += PADDING_HORIZONAL + (minimal ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG) + PADDING_BETWEEN_IMAGE_AND_TITLE;
 
526
    
 
527
    result.size = [string size];
 
528
    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL
 
529
                            - (minimal ? PADDING_BETWEEN_TITLE_AND_MIN_STATUS + statusRect.size.width : 0));
 
530
    
 
531
    return result;
 
532
}
 
533
 
 
534
- (NSRect) rectForProgressWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
 
535
{
 
536
    if ([fDefaults boolForKey: @"SmallView"])
 
537
        return NSZeroRect;
 
538
    
 
539
    NSRect result = bounds;
 
540
    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE + PADDING_BETWEEN_TITLE_AND_PROGRESS;
 
541
    result.origin.x += PADDING_HORIZONAL + IMAGE_SIZE_REG + PADDING_BETWEEN_IMAGE_AND_TITLE;
 
542
    
 
543
    result.size = [string size];
 
544
    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL);
 
545
    
 
546
    return result;
 
547
}
 
548
 
 
549
- (NSRect) rectForStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
 
550
{
 
551
    if ([fDefaults boolForKey: @"SmallView"])
 
552
        return NSZeroRect;
 
553
    
 
554
    NSRect result = bounds;
 
555
    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE + PADDING_BETWEEN_TITLE_AND_PROGRESS + HEIGHT_STATUS
 
556
                        + PADDING_BETWEEN_PROGRESS_AND_BAR + BAR_HEIGHT + PADDING_BETWEEN_BAR_AND_STATUS;
 
557
    result.origin.x += PADDING_HORIZONAL + IMAGE_SIZE_REG + PADDING_BETWEEN_IMAGE_AND_TITLE;
 
558
    
 
559
    result.size = [string size];
 
560
    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL);
 
561
    
 
562
    return result;
 
563
}
 
564
 
 
565
- (NSAttributedString *) attributedTitleWithColor: (NSColor *) color
 
566
{
 
567
    if (color)
 
568
        [fTitleAttributes setObject: color forKey: NSForegroundColorAttributeName];
 
569
    
 
570
    NSString * title = [[self representedObject] name];
 
571
    return [[[NSAttributedString alloc] initWithString: title attributes: fTitleAttributes] autorelease];
 
572
}
 
573
 
 
574
- (NSAttributedString *) attributedStatusString: (NSString *) string withColor: (NSColor *) color
 
575
{
 
576
    if (color)
 
577
        [fStatusAttributes setObject: color forKey: NSForegroundColorAttributeName];
 
578
    
 
579
    return [[[NSAttributedString alloc] initWithString: string attributes: fStatusAttributes] autorelease];
 
580
}
 
581
 
 
582
@end