source: trunk/macosx/TorrentCell.m @ 4191

Last change on this file since 4191 was 4191, checked in by livings124, 14 years ago

fix sizing of group labels with long file names

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