source: trunk/macosx/TorrentCell.m @ 3703

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

no reason to retain advanced bar info when it's hidden

  • Property svn:keywords set to Date Rev Author Id
File size: 21.8 KB
Line 
1/******************************************************************************
2 * $Id: TorrentCell.m 3703 2007-11-05 00:04:14Z 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// Used to optimize drawing. They contain packed RGBA pixels for every color needed.
57static uint32_t kBlue   = OSSwapBigToHostConstInt32(0x50A0FFFF), //80, 160, 255
58                kBlue1  = OSSwapBigToHostConstInt32(0x84FFFFFF), //204, 255, 255
59                kBlue2  = OSSwapBigToHostConstInt32(0x6BFFFFFF), //153, 255, 255
60                kBlue3  = OSSwapBigToHostConstInt32(0x6B84FFFF), //153, 204, 255
61                kBlue4  = OSSwapBigToHostConstInt32(0x426BFFFF), //102, 153, 255
62                kGray   = OSSwapBigToHostConstInt32(0xE9E9E9FF); //100, 100, 100
63
64- (void) drawBar: (NSRect) barRect;
65- (void) drawRegularBar: (NSRect) barRect;
66- (void) drawPiecesBar: (NSRect) barRect;
67
68- (NSRect) rectForMinimalStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
69- (NSRect) rectForTitleWithString: (NSAttributedString *) string basedOnMinimalStatusRect: (NSRect) statusRect
70            inBounds: (NSRect) bounds;
71- (NSRect) rectForProgressWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
72- (NSRect) rectForStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds;
73
74- (NSAttributedString *) attributedTitleWithColor: (NSColor *) color;
75- (NSAttributedString *) attributedStatusString: (NSString *) string withColor: (NSColor *) color;
76
77@end
78
79@implementation TorrentCell
80
81//only called one, so don't worry about release
82- (id) init
83{
84    if ((self = [super init]))
85        {
86        fDefaults = [NSUserDefaults standardUserDefaults];
87       
88        NSMutableParagraphStyle * paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
89        [paragraphStyle setLineBreakMode: NSLineBreakByTruncatingTail];
90   
91        fTitleAttributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
92                                [NSFont messageFontOfSize: 12.0], NSFontAttributeName,
93                                paragraphStyle, NSParagraphStyleAttributeName, nil];
94        fStatusAttributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
95                                [NSFont messageFontOfSize: 9.0], NSFontAttributeName,
96                                paragraphStyle, NSParagraphStyleAttributeName, nil];
97        [paragraphStyle release];
98       
99        fBarOverlayColor = [[NSColor colorWithDeviceWhite: 0.0 alpha: 0.2] retain];
100    }
101        return self;
102}
103
104- (id) copyWithZone: (NSZone *) zone
105{
106    TorrentCell * copy = [super copyWithZone: zone];
107   
108    copy->fBitmap = nil;
109    copy->fPieces = NULL;
110   
111    return copy;
112}
113
114- (void) dealloc
115{
116    [fBitmap release];
117    if (fPieces)
118        free(fPieces);
119   
120    [super dealloc];
121}
122
123- (NSRect) iconRectForBounds: (NSRect) bounds
124{
125    NSRect result = bounds;
126   
127    result.origin.x += PADDING_HORIZONAL;
128   
129    float imageSize;
130    if ([fDefaults boolForKey: @"SmallView"])
131    {
132        imageSize = IMAGE_SIZE_MIN;
133        result.origin.y += (result.size.height - imageSize) * 0.5;
134    }
135    else
136    {
137        imageSize = IMAGE_SIZE_REG;
138        result.origin.y += PADDING_ABOVE_IMAGE_REG;
139    }
140   
141    result.size = NSMakeSize(imageSize, imageSize);
142   
143    return result;
144}
145
146- (NSRect) titleRectForBounds: (NSRect) bounds
147{
148    return [self rectForTitleWithString: [self attributedTitleWithColor: nil]
149            basedOnMinimalStatusRect: [self minimalStatusRectForBounds: bounds] inBounds: bounds];
150}
151
152- (NSRect) minimalStatusRectForBounds: (NSRect) bounds
153{
154    Torrent * torrent = [self representedObject];
155    NSString * string = [fDefaults boolForKey: @"DisplaySmallStatusRegular"]
156                            ? [torrent shortStatusString] : [torrent remainingTimeString];
157    return [self rectForMinimalStatusWithString: [self attributedStatusString: string withColor: nil] inBounds: bounds];
158}
159
160- (NSRect) progressRectForBounds: (NSRect) bounds
161{
162    return [self rectForProgressWithString: [self attributedStatusString: [[self representedObject] progressString] withColor: nil]
163                    inBounds: bounds];
164}
165
166- (NSRect) barRectForBounds: (NSRect) bounds
167{
168    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
169   
170    NSRect result = bounds;
171    result.size.height = BAR_HEIGHT;
172    result.origin.x = PADDING_HORIZONAL + (minimal ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG) + PADDING_BETWEEN_IMAGE_AND_BAR;
173   
174    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE;
175    if (minimal)
176        result.origin.y += PADDING_BETWEEN_TITLE_AND_BAR_MIN;
177    else
178        result.origin.y += PADDING_BETWEEN_TITLE_AND_PROGRESS + HEIGHT_STATUS + PADDING_BETWEEN_PROGRESS_AND_BAR;
179   
180    result.size.width = round(NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL - BUTTONS_TOTAL_WIDTH);
181   
182    return result;
183}
184
185- (NSRect) statusRectForBounds: (NSRect) bounds
186{
187    return [self rectForStatusWithString: [self attributedStatusString: [[self representedObject] statusString] withColor: nil]
188                    inBounds: bounds];
189}
190
191- (NSUInteger) hitTestForEvent: (NSEvent *) event inRect: (NSRect) cellFrame ofView: (NSView *) controlView
192{
193    return NSCellHitContentArea;
194}
195
196- (void) drawInteriorWithFrame: (NSRect) cellFrame inView: (NSView *) controlView
197{
198    [super drawInteriorWithFrame: cellFrame inView: controlView];
199   
200    Torrent * torrent = [self representedObject];
201   
202    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
203   
204    //error image
205    BOOL error = [torrent isError];
206    if (error && !fErrorImage)
207    {
208        fErrorImage = [[NSImage imageNamed: @"Error.png"] copy];
209        [fErrorImage setFlipped: YES];
210    }
211   
212    //icon
213    NSImage * icon = minimal && error ? fErrorImage : [torrent icon];
214    NSRect iconRect = [self iconRectForBounds: cellFrame];
215    [icon drawInRect: iconRect fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0];
216   
217    if (error && !minimal)
218    {
219        NSRect errorRect = NSMakeRect(NSMaxX(iconRect) - IMAGE_SIZE_MIN, NSMaxY(iconRect) - IMAGE_SIZE_MIN,
220                                        IMAGE_SIZE_MIN, IMAGE_SIZE_MIN);
221        [fErrorImage drawInRect: errorRect fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0];
222    }
223   
224    //text color
225    NSColor * titleColor, * statusColor;
226    if ([self isHighlighted]
227            && [[self highlightColorWithFrame: cellFrame inView: controlView] isEqual: [NSColor alternateSelectedControlColor]])
228    {
229        titleColor = [NSColor whiteColor];
230        statusColor = [NSColor whiteColor];
231    }
232    else
233    {
234        titleColor = [NSColor controlTextColor];
235        statusColor = [NSColor darkGrayColor];
236    }
237   
238    //minimal status
239    NSRect minimalStatusRect;
240    if (minimal)
241    {
242        NSString * string = [fDefaults boolForKey: @"DisplaySmallStatusRegular"]
243                            ? [torrent shortStatusString] : [torrent remainingTimeString];
244        NSAttributedString * minimalString = [self attributedStatusString: string withColor: statusColor];
245        minimalStatusRect = [self rectForMinimalStatusWithString: minimalString inBounds: cellFrame];
246       
247        [minimalString drawInRect: minimalStatusRect];
248    }
249   
250    //title
251    NSAttributedString * titleString = [self attributedTitleWithColor: titleColor];
252    NSRect titleRect = [self rectForTitleWithString: titleString basedOnMinimalStatusRect: minimalStatusRect inBounds: cellFrame];
253    [titleString drawInRect: titleRect];
254   
255    //progress
256    if (!minimal)
257    {
258        NSAttributedString * progressString = [self attributedStatusString: [torrent progressString] withColor: statusColor];
259        NSRect progressRect = [self rectForProgressWithString: progressString inBounds: cellFrame];
260        [progressString drawInRect: progressRect];
261    }
262   
263    //bar
264    [self drawBar: [self barRectForBounds: cellFrame]];
265   
266    //status
267    if (!minimal)
268    {
269        NSAttributedString * statusString = [self attributedStatusString: [torrent statusString] withColor: statusColor];
270        [statusString drawInRect: [self rectForStatusWithString: statusString inBounds: cellFrame]];
271    }
272}
273
274@end
275
276@implementation TorrentCell (Private)
277
278- (void) drawBar: (NSRect) barRect
279{
280    if ([fDefaults boolForKey: @"PiecesBar"])
281    {
282        NSRect regularBarRect = barRect, piecesBarRect = barRect;
283        regularBarRect.size.height /= 3;
284        piecesBarRect.origin.y += regularBarRect.size.height;
285        piecesBarRect.size.height -= regularBarRect.size.height;
286       
287        [self drawRegularBar: regularBarRect];
288        [self drawPiecesBar: piecesBarRect];
289    }
290    else
291    {
292        if (fPieces)
293        {
294            free(fPieces);
295            fPieces = NULL;
296            [fBitmap release];
297            fBitmap = nil;
298        }
299       
300        [self drawRegularBar: barRect];
301    }
302   
303    [fBarOverlayColor set];
304    [NSBezierPath strokeRect: NSInsetRect(barRect, 0.5, 0.5)];
305}
306
307- (void) drawRegularBar: (NSRect) barRect
308{
309    Torrent * torrent = [self representedObject];
310   
311    int leftWidth = barRect.size.width;
312    float progress = [torrent progress];
313   
314    if (progress < 1.0)
315    {
316        float rightProgress = 1.0 - progress, progressLeft = [torrent progressLeft];
317        int rightWidth = leftWidth * rightProgress;
318        leftWidth -= rightWidth;
319       
320        if (progressLeft < rightProgress)
321        {
322            int rightNoIncludeWidth = rightWidth * ((rightProgress - progressLeft) / rightProgress);
323            rightWidth -= rightNoIncludeWidth;
324           
325            NSRect noIncludeRect = barRect;
326            noIncludeRect.origin.x += barRect.size.width - rightNoIncludeWidth;
327            noIncludeRect.size.width = rightNoIncludeWidth;
328           
329            if (!fLightGrayGradient)
330                fLightGrayGradient = [[CTGradient progressLightGrayGradient] retain];
331            [fLightGrayGradient fillRect: noIncludeRect angle: -90];
332        }
333       
334        if (rightWidth > 0)
335        {
336            int availableWidth = 0;
337            /*if (![fDefaults boolForKey: @"DisplayProgressBarAvailable"])
338            {
339                //NSLog(@"notAvailableWidth %d rightWidth %d", notAvailableWidth, rightWidth);
340                availableWidth = MAX(0, (float)rightWidth - barRect.size.width * [torrent notAvailableDesired]);
341               
342                if (availableWidth > 0)
343                {
344                    rightWidth -= availableWidth;
345                   
346                    NSRect availableRect = barRect;
347                    availableRect.origin.x += leftWidth;
348                    availableRect.size.width = availableWidth;
349                   
350                    if (!fYellowGradient)
351                        fYellowGradient = [[CTGradient progressYellowGradient] retain];
352                    [fYellowGradient fillRect: availableRect angle: -90];
353                }
354            }*/
355           
356            if (rightWidth > 0)
357            {
358                NSRect includeRect = barRect;
359                includeRect.origin.x += leftWidth + availableWidth;
360                includeRect.size.width = rightWidth;
361               
362                if (!fWhiteGradient)
363                    fWhiteGradient = [[CTGradient progressWhiteGradient] retain];
364                [fWhiteGradient fillRect: includeRect angle: -90];
365            }
366        }
367    }
368   
369    if (leftWidth > 0)
370    {
371        NSRect completeRect = barRect;
372        completeRect.size.width = leftWidth;
373       
374        if ([torrent isActive])
375        {
376            if ([torrent isChecking])
377            {
378                if (!fYellowGradient)
379                    fYellowGradient = [[CTGradient progressYellowGradient] retain];
380                [fYellowGradient fillRect: completeRect angle: -90];
381            }
382            else if ([torrent isSeeding])
383            {
384                int ratioLeftWidth = leftWidth * (1.0 - [torrent progressStopRatio]);
385                leftWidth -= ratioLeftWidth;
386               
387                if (ratioLeftWidth > 0)
388                {
389                    NSRect ratioLeftRect = barRect;
390                    ratioLeftRect.origin.x += leftWidth;
391                    ratioLeftRect.size.width = ratioLeftWidth;
392                   
393                    if (!fLightGreenGradient)
394                        fLightGreenGradient = [[CTGradient progressLightGreenGradient] retain];
395                    [fLightGreenGradient fillRect: ratioLeftRect angle: -90];
396                }
397               
398                if (leftWidth > 0)
399                {
400                    completeRect.size.width = leftWidth;
401                   
402                    if (!fGreenGradient)
403                        fGreenGradient = [[CTGradient progressGreenGradient] retain];
404                    [fGreenGradient fillRect: completeRect angle: -90];
405                }
406            }
407            else
408            {
409                if (!fBlueGradient)
410                    fBlueGradient = [[CTGradient progressBlueGradient] retain];
411                [fBlueGradient fillRect: completeRect angle: -90];
412            }
413        }
414        else
415        {
416            if ([torrent waitingToStart])
417            {
418                if ([torrent progressLeft] <= 0.0)
419                {
420                    if (!fDarkGreenGradient)
421                        fDarkGreenGradient = [[CTGradient progressDarkGreenGradient] retain];
422                    [fDarkGreenGradient fillRect: completeRect angle: -90];
423                }
424                else
425                {
426                    if (!fDarkBlueGradient)
427                        fDarkBlueGradient = [[CTGradient progressDarkBlueGradient] retain];
428                    [fDarkBlueGradient fillRect: completeRect angle: -90];
429                }
430            }
431            else
432            {
433                if (!fGrayGradient)
434                    fGrayGradient = [[CTGradient progressGrayGradient] retain];
435                [fGrayGradient fillRect: completeRect angle: -90];
436            }
437        }
438    }
439}
440
441- (void) drawPiecesBar: (NSRect) barRect
442{
443    if (!fBitmap)
444        fBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: nil
445            pixelsWide: MAX_PIECES pixelsHigh: barRect.size.height bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES
446            isPlanar: NO colorSpaceName: NSCalibratedRGBColorSpace bytesPerRow: 0 bitsPerPixel: 0];
447   
448    uint32_t * p;
449    uint8_t * bitmapData = [fBitmap bitmapData];
450    int bytesPerRow = [fBitmap bytesPerRow];
451   
452    if (!fPieces)
453    {
454        fPieces = malloc(MAX_PIECES);
455        int i;
456        for (i = 0; i < MAX_PIECES; i++)
457            fPieces[i] = BLANK_PIECE;
458    }
459   
460    #warning add flashing orange
461   
462    Torrent * torrent = [self representedObject];
463   
464    #warning redo like pieces view
465    int pieceCount = [torrent pieceCount];
466    float * piecePercent = malloc(pieceCount * sizeof(float));
467    [torrent getAmountFinished: piecePercent size: pieceCount];
468   
469    //lines 2 to 14: blue, green, or gray depending on piece availability
470    int i, h, index = 0;
471    float increment = (float)pieceCount / MAX_PIECES, indexValue = 0;
472    uint32_t color;
473    BOOL change;
474    for (i = 0; i < MAX_PIECES; i++)
475    {
476        change = NO;
477        if (piecePercent[index] >= 1.0)
478        {
479            if (fPieces[i] != -1)
480            {
481                color = kBlue;
482                fPieces[i] = -1;
483                change = YES;
484            }
485        }
486        else if (piecePercent[index] <= 0.0)
487        {
488            if (fPieces[i] != 0)
489            {
490                color = kGray;
491                fPieces[i] = 0;
492                change = YES;
493            }
494        }
495        else if (piecePercent[index] <= 0.25)
496        {
497            if (fPieces[i] != 1)
498            {
499                color = kBlue1;
500                fPieces[i] = 1;
501                change = YES;
502            }
503        }
504        else if (piecePercent[index] <= 0.5)
505        {
506            if (fPieces[i] != 2)
507            {
508                color = kBlue2;
509                fPieces[i] = 2;
510                change = YES;
511            }
512        }
513        else if (piecePercent[index] <= 0.75)
514        {
515            if (fPieces[i] != 3)
516            {
517                color = kBlue3;
518                fPieces[i] = 3;
519                change = YES;
520            }
521        }
522        else
523        {
524            if (fPieces[i] != 4)
525            {
526                color = kBlue4;
527                fPieces[i] = 4;
528                change = YES;
529            }
530        }
531       
532        if (change)
533        {
534            //draw vertically
535            p = (uint32_t *)(bitmapData) + i;
536            for (h = 0; h < barRect.size.height; h++)
537            {
538                p[0] = color;
539                p = (uint32_t *)((uint8_t *)p + bytesPerRow);
540            }
541        }
542       
543        indexValue += increment;
544        index = (int)indexValue;
545    }
546   
547    free(piecePercent);
548   
549    //actually draw image
550    NSImage * bar = [[NSImage alloc] initWithSize: [fBitmap size]];
551    [bar setFlipped: YES];
552    [bar addRepresentation: fBitmap];
553   
554    [bar drawInRect: barRect fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0];
555    [bar release];
556   
557    if (!fTransparentGradient)
558        fTransparentGradient = [[CTGradient progressTransparentGradient] retain];
559    [fTransparentGradient fillRect: barRect angle: -90];
560}
561
562- (NSRect) rectForMinimalStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
563{
564    if (![fDefaults boolForKey: @"SmallView"])
565        return NSZeroRect;
566   
567    NSRect result = bounds;
568    result.size = [string size];
569   
570    result.origin.x += bounds.size.width - result.size.width - PADDING_HORIZONAL;
571    result.origin.y += PADDING_ABOVE_MIN_STATUS;
572   
573    return result;
574}
575
576- (NSRect) rectForTitleWithString: (NSAttributedString *) string basedOnMinimalStatusRect: (NSRect) statusRect
577            inBounds: (NSRect) bounds
578{
579    BOOL minimal = [fDefaults boolForKey: @"SmallView"];
580   
581    NSRect result = bounds;
582    result.origin.y += PADDING_ABOVE_TITLE;
583    result.origin.x += PADDING_HORIZONAL + (minimal ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG) + PADDING_BETWEEN_IMAGE_AND_TITLE;
584   
585    result.size = [string size];
586    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL
587                            - (minimal ? PADDING_BETWEEN_TITLE_AND_MIN_STATUS + statusRect.size.width : 0));
588   
589    return result;
590}
591
592- (NSRect) rectForProgressWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
593{
594    if ([fDefaults boolForKey: @"SmallView"])
595        return NSZeroRect;
596   
597    NSRect result = bounds;
598    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE + PADDING_BETWEEN_TITLE_AND_PROGRESS;
599    result.origin.x += PADDING_HORIZONAL + IMAGE_SIZE_REG + PADDING_BETWEEN_IMAGE_AND_TITLE;
600   
601    result.size = [string size];
602    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL);
603   
604    return result;
605}
606
607- (NSRect) rectForStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds
608{
609    if ([fDefaults boolForKey: @"SmallView"])
610        return NSZeroRect;
611   
612    NSRect result = bounds;
613    result.origin.y += PADDING_ABOVE_TITLE + HEIGHT_TITLE + PADDING_BETWEEN_TITLE_AND_PROGRESS + HEIGHT_STATUS
614                        + PADDING_BETWEEN_PROGRESS_AND_BAR + BAR_HEIGHT + PADDING_BETWEEN_BAR_AND_STATUS;
615    result.origin.x += PADDING_HORIZONAL + IMAGE_SIZE_REG + PADDING_BETWEEN_IMAGE_AND_TITLE;
616   
617    result.size = [string size];
618    result.size.width = MIN(result.size.width, NSMaxX(bounds) - result.origin.x - PADDING_HORIZONAL);
619   
620    return result;
621}
622
623- (NSAttributedString *) attributedTitleWithColor: (NSColor *) color
624{
625    if (color)
626        [fTitleAttributes setObject: color forKey: NSForegroundColorAttributeName];
627   
628    NSString * title = [[self representedObject] name];
629    return [[[NSAttributedString alloc] initWithString: title attributes: fTitleAttributes] autorelease];
630}
631
632- (NSAttributedString *) attributedStatusString: (NSString *) string withColor: (NSColor *) color
633{
634    if (color)
635        [fStatusAttributes setObject: color forKey: NSForegroundColorAttributeName];
636   
637    return [[[NSAttributedString alloc] initWithString: string attributes: fStatusAttributes] autorelease];
638}
639
640@end
Note: See TracBrowser for help on using the repository browser.