source: trunk/Cocoa/AntiRSI/CTBadge/CTBadge.m@ 447

Last change on this file since 447 was 332, checked in by Nicholas Riley, 17 years ago

version.plist: Not needed.

Info.plist: Updated for 1.4njr2.

AUTHORS: Updated Onne Gorter's email address and added mine.

AntiRSI.[hm]: Added dock badge session timer display and auto-reset options. Updated URLs to point to my Web site; should probably just switch to Sparkle.

CTBadge: Added customized version.

English.lproj/InfoPlist.strings: Updated for 1.4njr2; credit myself and Chad; remove Onne Gorter's URL.

English.lproj/MainMenu.nib: Preference changes; add cmd-R for manual reset.

File size: 8.9 KB
Line 
1//
2// CTBadge.m
3// CTWidgets
4//
5// Created by Chad Weider on 2/14/07.
6// Copyright (c) 2007 Chad Weider.
7// Some rights reserved: <http://creativecommons.org/licenses/by/2.5/>
8//
9// Version: 1.5
10
11#import "CTBadge.h"
12
13const float CTLargeBadgeSize = 46.;
14const float CTSmallBadgeSize = 23.;
15const float CTLargeLabelSize = 24.;
16const float CTSmallLabelSize = 11.;
17
18@interface CTBadge (Private)
19- (NSImage *)badgeMaskOfSize:(float)size length:(unsigned)length; //return a badge with height of <size> to fit <length> characters
20- (NSAttributedString *)labelForString:(NSString *)string size:(unsigned)size; //returns appropriately attributed label string (not autoreleased)
21- (CTGradient *)badgeGradient; //gradient used to fill badge mask
22@end
23
24@implementation CTBadge
25
26- (id)init
27 {
28 self = [super init];
29
30 if (self != nil)
31 {
32 badgeColor = nil;
33 labelColor = nil;
34
35 [self setBadgeColor:[NSColor redColor]];
36 [self setLabelColor:[NSColor whiteColor]];
37 }
38 return self;
39 }
40
41- (void)dealloc
42 {
43 if(badgeColor != nil)
44 [badgeColor release];
45 if(labelColor != nil)
46 [labelColor release];
47
48 [super dealloc];
49 }
50
51+ (CTBadge *)systemBadge
52 {
53 id newInstance = [[[self class] alloc] init];
54
55 return [newInstance autorelease];
56 }
57
58+ (CTBadge *)badgeWithColor:(NSColor *)badgeColor labelColor:(NSColor *)labelColor;
59 {
60 id newInstance = [[[self class] alloc] init];
61
62 [newInstance setBadgeColor:badgeColor];
63 [newInstance setLabelColor:labelColor];
64
65 return [newInstance autorelease];
66 }
67#pragma mark -
68
69
70#pragma mark Appearance
71- (void)setBadgeColor:(NSColor *)theColor;
72 {
73 if(badgeColor != nil)
74 [badgeColor release];
75
76 badgeColor = theColor;
77 [badgeColor retain];
78 }
79- (void)setLabelColor:(NSColor *)theColor;
80 {
81 if(labelColor != nil)
82 [labelColor release];
83
84 labelColor = theColor;
85 [labelColor retain];
86 }
87
88- (NSColor *)badgeColor
89 {
90 return badgeColor;
91 }
92- (NSColor *)labelColor
93 {
94 return labelColor;
95 }
96#pragma mark -
97
98
99#pragma mark Drawing
100- (NSImage *)smallBadgeForValue:(unsigned)value //does drawing in it's own special way
101 {
102 return [self badgeOfSize:CTSmallBadgeSize forValue:value];
103 }
104
105- (NSImage *)smallBadgeForString:(NSString *)string
106 {
107 return [self badgeOfSize:CTSmallBadgeSize forString:string];
108 }
109
110- (NSImage *)largeBadgeForValue:(unsigned)value
111 {
112 return [self badgeOfSize:CTLargeBadgeSize forValue:value];
113 }
114
115- (NSImage *)largeBadgeForString:(NSString *)string
116 {
117 return [self badgeOfSize:CTLargeBadgeSize forString:string];
118 }
119
120- (NSImage *)badgeOfSize:(float)size forValue:(unsigned)value
121 {
122 return [self badgeOfSize:(float)size forString:[NSString stringWithFormat:@"%u", value]];
123 }
124
125- (NSImage *)badgeOfSize:(float)size forString:(NSString *)string
126 {
127 float scaleFactor = 1;
128
129 if(size <= 0)
130 [NSException raise:NSInvalidArgumentException format:@"%@ %@: size (%f) must be positive", [self class], NSStringFromSelector(_cmd), size];
131 else if(size <= CTSmallBadgeSize)
132 scaleFactor = size/CTSmallBadgeSize;
133 else
134 scaleFactor = size/CTLargeBadgeSize;
135
136 //Label stuff -----------------------------------------------
137 NSAttributedString *label;
138 NSSize labelSize;
139
140 if(size <= CTSmallBadgeSize)
141 label = [self labelForString:string size:CTSmallLabelSize*scaleFactor];
142 else
143 label = [self labelForString:string size:CTLargeLabelSize*scaleFactor];
144
145 labelSize = [label size];
146
147 //Badge stuff -----------------------------------------------
148 NSImage *badgeImage; //this the image with the gradient fill
149 NSImage *badgeMask ; //we nock out this mask from the gradient
150
151 CTGradient *badgeGradient = [self badgeGradient];
152
153 float shadowOpacity,
154 shadowOffset,
155 shadowBlurRadius;
156
157 int angle;
158
159 if(size <= CTSmallBadgeSize)
160 {
161 shadowOpacity = .6;
162 shadowOffset = floorf(1*scaleFactor);
163 shadowBlurRadius = ceilf(1*scaleFactor);
164 }
165 else
166 {
167 shadowOpacity = .8;
168 shadowOffset = ceilf(1*scaleFactor);
169 shadowBlurRadius = ceilf(2*scaleFactor);
170 }
171
172 if ([label length] <= 3) //Badges have different gradient angles
173 angle = -45;
174 else
175 angle = -30;
176
177 badgeMask = [self badgeMaskOfSize:size length:[label length]];
178
179 NSSize badgeSize = [badgeMask size];
180 NSPoint origin = NSMakePoint(shadowBlurRadius, shadowBlurRadius+shadowOffset);
181
182 badgeImage = [[NSImage alloc] initWithSize:NSMakeSize(badgeSize.width + 2*shadowBlurRadius, //sometimes it needs more
183 badgeSize.height + 2*shadowBlurRadius - shadowOffset + (size <= CTSmallBadgeSize))]; //space when small
184
185 [badgeImage lockFocus];
186 [badgeGradient fillRect:NSMakeRect(origin.x, origin.y, floorf(badgeSize.width), floorf(badgeSize.height)) angle:angle]; //apply the gradient
187 [badgeMask compositeToPoint:origin operation: NSCompositeDestinationAtop]; //knock out the badge area
188 [label drawInRect:NSMakeRect(origin.x+floorf((badgeSize.width-labelSize.width)/2), origin.y+floorf((badgeSize.height-labelSize.height)/2), badgeSize.width, labelSize.height)]; //draw label in center
189 [badgeImage unlockFocus];
190
191
192 //Final stuff -----------------------------------------------
193 NSImage *image = [[NSImage alloc] initWithSize:[badgeImage size]];
194
195 [image lockFocus];
196 [NSGraphicsContext saveGraphicsState];
197 NSShadow *theShadow = [[NSShadow alloc] init];
198 [theShadow setShadowOffset: NSMakeSize(0,-shadowOffset)];
199 [theShadow setShadowBlurRadius:shadowBlurRadius];
200 [theShadow setShadowColor:[[NSColor blackColor] colorWithAlphaComponent:shadowOpacity]];
201 [theShadow set];
202 [theShadow release];
203 [badgeImage compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver];
204 [NSGraphicsContext restoreGraphicsState];
205 [image unlockFocus];
206
207 [label release];
208 [badgeImage release];
209
210 return [image autorelease];
211 }
212
213
214- (NSImage *)badgeOverlayImageForString:(NSString *)string insetX:(float)dx y:(float)dy;
215 {
216 NSImage *badgeImage = [self largeBadgeForString:string];
217 NSImage *overlayImage = [[NSImage alloc] initWithSize:NSMakeSize(128,128)];
218
219 //draw large icon in the upper right corner of the overlay image
220 [overlayImage lockFocus];
221 NSSize badgeSize = [badgeImage size];
222 [badgeImage compositeToPoint:NSMakePoint(128-dx-badgeSize.width,128-dy-badgeSize.height) operation:NSCompositeSourceOver];
223 [overlayImage unlockFocus];
224
225 return [overlayImage autorelease];
226 }
227
228- (void)badgeApplicationDockIconWithString:(NSString *)string insetX:(float)dx y:(float)dy;
229 {
230 NSImage *appIcon = [NSImage imageNamed:@"NSApplicationIcon"];
231 NSImage *badgeOverlay = [self badgeOverlayImageForString:string insetX:dx y:dy];
232
233 //Put the appIcon underneath the badgeOverlay
234 [badgeOverlay lockFocus];
235 [appIcon compositeToPoint:NSZeroPoint operation:NSCompositeDestinationOver];
236 [badgeOverlay unlockFocus];
237
238 [NSApp setApplicationIconImage:badgeOverlay];
239 }
240
241- (NSImage *)badgeOverlayImageForValue:(unsigned)value insetX:(float)dx y:(float)dy
242 {
243 return [self badgeOverlayImageForString:[NSString stringWithFormat:@"%u", value] insetX:dx y:dy];
244 }
245
246- (void)badgeApplicationDockIconWithValue:(unsigned)value insetX:(float)dx y:(float)dy
247 {
248 [self badgeApplicationDockIconWithString:[NSString stringWithFormat:@"%u", value] insetX:dx y:dy];
249 }
250#pragma mark -
251
252
253#pragma mark Misc.
254- (CTGradient *)badgeGradient
255 {
256 CTGradient *aGradient = [CTGradient gradientWithBeginningColor:[self badgeColor] endingColor:[[self badgeColor] shadowWithLevel:(1./3.)]];
257
258 aGradient = [aGradient addColorStop:[self badgeColor] atPosition:(1./3.)];
259
260 return aGradient;
261 }
262
263- (NSAttributedString *)labelForString:(NSString *)label size:(unsigned)size
264 {
265 //set Attributes to use on String ---------------------------
266 NSFont *labelFont;
267
268 if(size <= CTSmallLabelSize)
269 labelFont = [NSFont boldSystemFontOfSize:size];
270 else
271 labelFont = [NSFont fontWithName:@"Helvetica-Bold" size:size];
272
273 NSMutableParagraphStyle *pStyle = [[NSMutableParagraphStyle alloc] init];[pStyle setAlignment:NSCenterTextAlignment];
274 NSDictionary *attributes = [[NSDictionary alloc] initWithObjectsAndKeys:[self labelColor], NSForegroundColorAttributeName,
275 labelFont , NSFontAttributeName , nil];
276 [pStyle release];
277
278 //Label stuff
279 if([label length] >= 6)
280 label = [NSString stringWithUTF8String:"\xe2\x88\x9e"];
281
282 NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:label attributes:attributes];
283 [attributes release];
284
285 return attributedString;
286 }
287
288- (NSImage *)badgeMaskOfSize:(float)size length:(unsigned)length;
289 {
290 NSImage *badgeMask;
291
292 if(length <=2)
293 badgeMask = [NSImage imageNamed:@"CTBadge_1.pdf"];
294 else if(length <=3)
295 badgeMask = [NSImage imageNamed:@"CTBadge_3.pdf"];
296 else if(length <=4)
297 badgeMask = [NSImage imageNamed:@"CTBadge_4.pdf"];
298 else
299 badgeMask = [NSImage imageNamed:@"CTBadge_5.pdf"];
300
301 if(size > 0 && size != [badgeMask size].height)
302 {
303 [badgeMask setName:nil];
304 [badgeMask setScalesWhenResized:YES];
305 [badgeMask setSize:NSMakeSize([badgeMask size].width*(size/[badgeMask size].height), size)];
306 }
307
308 return badgeMask;
309 }
310
311@end
Note: See TracBrowser for help on using the repository browser.