Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/diebuche/ChameleonPrefPane/Sources/RoundedBox.m

1//
2// RoundedBox.m
3// RoundedBox
4//
5// Created by Matt Gemmell on 01/11/2005.
6// Copyright 2006 Matt Gemmell. http://mattgemmell.com/
7//
8// Permission to use this code:
9//
10// Feel free to use this code in your software, either as-is or
11// in a modified form. Either way, please include a credit in
12// your software's "About" box or similar, mentioning at least
13// my name (Matt Gemmell). A link to my site would be nice too.
14//
15// Permission to redistribute this code:
16//
17// You can redistribute this code, as long as you keep these
18// comments. You can also redistribute modified versions of the
19// code, as long as you add comments to say that you've made
20// modifications (keeping these original comments too).
21//
22// If you do use or redistribute this code, an email would be
23// appreciated, just to let me know that people are finding my
24// code useful. You can reach me at matt.gemmell@gmail.com
25//
26
27#import "RoundedBox.h"
28
29
30@implementation RoundedBox
31
32
33- (id)initWithFrame:(NSRect)frame {
34 self = [super initWithFrame:frame];
35 if (self) {
36 [self setDefaults];
37 }
38 return self;
39}
40
41
42- (void)dealloc
43{
44 [borderColor release];
45 [titleColor release];
46 [gradientStartColor release];
47 [gradientEndColor release];
48 [backgroundColor release];
49 [titleAttrs release];
50
51 [super dealloc];
52}
53
54
55- (void)setDefaults
56{
57 borderWidth = 2.0;
58 [self setBorderColor:[NSColor grayColor]];
59 [self setTitleColor:[NSColor whiteColor]];
60 [self setGradientStartColor:[NSColor colorWithCalibratedWhite:0.92 alpha:1.0]];
61 [self setGradientEndColor:[NSColor colorWithCalibratedWhite:0.82 alpha:1.0]];
62 [self setBackgroundColor:[NSColor colorWithCalibratedWhite:0.90 alpha:1.0]];
63 [self setTitleFont:[NSFont boldSystemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
64
65 // Set up text attributes for drawing
66 NSMutableParagraphStyle *paragraphStyle;
67 paragraphStyle = [[NSMutableParagraphStyle alloc] init];
68 [paragraphStyle setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
69 [paragraphStyle setAlignment:NSLeftTextAlignment];
70 [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
71
72 titleAttrs = [[NSMutableDictionary dictionaryWithObjectsAndKeys:
73 [self titleFont], NSFontAttributeName,
74 [self titleColor], NSForegroundColorAttributeName,
75 [paragraphStyle autorelease], NSParagraphStyleAttributeName,
76 nil] retain];
77
78 [self setDrawsFullTitleBar:NO];
79 [self setSelected:NO];
80 [self setDrawsGradientBackground:YES];
81}
82
83
84- (void)awakeFromNib
85{
86 // For when we've been created in a nib file
87 [self setDefaults];
88}
89
90
91- (BOOL)preservesContentDuringLiveResize
92{
93 // NSBox returns YES for this, but doing so would screw up the gradients.
94 return NO;
95}
96
97
98- (void)drawRect:(NSRect)rect {
99
100 // Construct rounded rect path
101 NSRect boxRect = [self bounds];
102 NSRect bgRect = boxRect;
103 bgRect = NSInsetRect(boxRect, borderWidth / 2.0, borderWidth / 2.0);
104 bgRect = NSIntegralRect(bgRect);
105 bgRect.origin.x += 0.5;
106 bgRect.origin.y += 0.5;
107 int minX = NSMinX(bgRect);
108 int midX = NSMidX(bgRect);
109 int maxX = NSMaxX(bgRect);
110 int minY = NSMinY(bgRect);
111 int midY = NSMidY(bgRect);
112 int maxY = NSMaxY(bgRect);
113 float radius = 4.0;
114 NSBezierPath *bgPath = [NSBezierPath bezierPath];
115
116 // Bottom edge and bottom-right curve
117 [bgPath moveToPoint:NSMakePoint(midX, minY)];
118 [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY)
119 toPoint:NSMakePoint(maxX, midY)
120 radius:radius];
121
122 // Right edge and top-right curve
123 [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, maxY)
124 toPoint:NSMakePoint(midX, maxY)
125 radius:radius];
126
127 // Top edge and top-left curve
128 [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY)
129 toPoint:NSMakePoint(minX, midY)
130 radius:radius];
131
132 // Left edge and bottom-left curve
133 [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(minX, minY)
134 toPoint:NSMakePoint(midX, minY)
135 radius:radius];
136 [bgPath closePath];
137
138
139 // Draw background
140
141 if ([self drawsGradientBackground]) {
142 // Draw gradient background
143 NSGraphicsContext *nsContext = [NSGraphicsContext currentContext];
144 [nsContext saveGraphicsState];
145 [bgPath addClip];
146 CTGradient *gradient = [CTGradient gradientWithBeginningColor:[self gradientStartColor] endingColor:[self gradientEndColor]];
147 NSRect gradientRect = [bgPath bounds];
148 [gradient fillRect:gradientRect angle:270.0];
149 [nsContext restoreGraphicsState];
150 } else {
151 // Draw solid color background
152 [backgroundColor set];
153 [bgPath fill];
154 }
155
156
157 // Create drawing rectangle for title
158
159 float titleHInset = borderWidth + 4.0;
160 float titleVInset = borderWidth;
161 NSSize titleSize = [[self title] sizeWithAttributes:titleAttrs];
162 NSRect titleRect = NSMakeRect(boxRect.origin.x + titleHInset,
163 boxRect.origin.y + boxRect.size.height - titleSize.height - (titleVInset * 2.0),
164 titleSize.width + borderWidth,
165 titleSize.height);
166 titleRect.size.width = MIN(titleRect.size.width, boxRect.size.width - (2.0 * titleHInset));
167
168 if ([self selected]) {
169 [[NSColor alternateSelectedControlColor] set];
170 // We use the alternate (darker) selectedControlColor since the regular one is too light.
171 // The alternate one is the highlight color for NSTableView, NSOutlineView, etc.
172 // This mimics how Automator highlights the selected action in a workflow.
173 } else {
174 [borderColor set];
175 }
176
177
178 // Draw title background
179 //NSRectFill(titleRect);
180 [[self titlePathWithinRect:bgRect cornerRadius:radius titleRect:titleRect] fill];
181
182
183 // Draw rounded rect around entire box
184 if (borderWidth > 0.0) {
185 [bgPath setLineWidth:borderWidth];
186 [bgPath stroke];
187 }
188
189
190 // Draw title text
191 [[self title] drawInRect:titleRect withAttributes:titleAttrs];
192 //[[self titleCell] setTextColor:[self titleColor]];
193 //[[self titleCell] drawWithFrame:titleRect inView:self];
194}
195
196
197- (NSBezierPath *)titlePathWithinRect:(NSRect)rect cornerRadius:(float)radius titleRect:(NSRect)titleRect
198{
199 // Construct rounded rect path
200
201 NSRect bgRect = rect;
202 int minX = NSMinX(bgRect);
203 int maxX = minX + titleRect.size.width + ((titleRect.origin.x - rect.origin.x) * 2.0);
204 int maxY = NSMaxY(bgRect);
205 int minY = NSMinY(titleRect) - (maxY - (titleRect.origin.y + titleRect.size.height));
206 float titleExpansionThreshold = 20.0;
207 // i.e. if there's less than 20px space to the right of the short titlebar, just draw the full one.
208
209 NSBezierPath *path = [NSBezierPath bezierPath];
210
211 [path moveToPoint:NSMakePoint(minX, minY)];
212
213 if (bgRect.size.width - titleRect.size.width >= titleExpansionThreshold && ![self drawsFullTitleBar]) {
214 // Draw a short titlebar
215 [path appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY)
216 toPoint:NSMakePoint(maxX, maxY)
217 radius:radius];
218 [path lineToPoint:NSMakePoint(maxX, maxY)];
219 } else {
220 // Draw full titlebar, since we're either set to always do so, or we don't have room for a short one.
221 [path lineToPoint:NSMakePoint(NSMaxX(bgRect), minY)];
222 [path appendBezierPathWithArcFromPoint:NSMakePoint(NSMaxX(bgRect), maxY)
223 toPoint:NSMakePoint(NSMaxX(bgRect) - (bgRect.size.width / 2.0), maxY)
224 radius:radius];
225 }
226
227 [path appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY)
228 toPoint:NSMakePoint(minX, minY)
229 radius:radius];
230
231 [path closePath];
232
233 return path;
234}
235
236
237- (void)setTitle:(NSString *)newTitle
238{
239 [super setTitle:newTitle];
240 [self setNeedsDisplay:YES];
241}
242
243
244- (BOOL)drawsFullTitleBar
245{
246 return drawsFullTitleBar;
247}
248
249
250- (void)setDrawsFullTitleBar:(BOOL)newDrawsFullTitleBar
251{
252 drawsFullTitleBar = newDrawsFullTitleBar;
253 [self setNeedsDisplay:YES];
254}
255
256
257- (BOOL)selected
258{
259 return selected;
260}
261
262
263- (void)setSelected:(BOOL)newSelected
264{
265 selected = newSelected;
266 [self setNeedsDisplay:YES];
267}
268
269
270- (NSColor *)borderColor
271{
272 return borderColor;
273}
274
275
276- (void)setBorderColor:(NSColor *)newBorderColor
277{
278 [newBorderColor retain];
279 [borderColor release];
280 borderColor = newBorderColor;
281 [self setNeedsDisplay:YES];
282}
283
284
285- (NSColor *)titleColor
286{
287 return titleColor;
288}
289
290
291- (void)setTitleColor:(NSColor *)newTitleColor
292{
293 [newTitleColor retain];
294 [titleColor release];
295 titleColor = newTitleColor;
296
297 [titleAttrs setObject:titleColor forKey:NSForegroundColorAttributeName];
298
299 [self setNeedsDisplay:YES];
300}
301
302
303- (NSColor *)gradientStartColor
304{
305 return gradientStartColor;
306}
307
308
309- (void)setGradientStartColor:(NSColor *)newGradientStartColor
310{
311 // Must ensure gradient colors are in NSCalibratedRGBColorSpace, or Core Image gets angry.
312 NSColor *newCalibratedGradientStartColor = [newGradientStartColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
313 [newCalibratedGradientStartColor retain];
314 [gradientStartColor release];
315 gradientStartColor = newCalibratedGradientStartColor;
316 if ([self drawsGradientBackground]) {
317 [self setNeedsDisplay:YES];
318 }
319}
320
321
322- (NSColor *)gradientEndColor
323{
324 return gradientEndColor;
325}
326
327
328- (void)setGradientEndColor:(NSColor *)newGradientEndColor
329{
330 // Must ensure gradient colors are in NSCalibratedRGBColorSpace, or Core Image gets angry.
331 NSColor *newCalibratedGradientEndColor = [newGradientEndColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
332 [newCalibratedGradientEndColor retain];
333 [gradientEndColor release];
334 gradientEndColor = newCalibratedGradientEndColor;
335 if ([self drawsGradientBackground]) {
336 [self setNeedsDisplay:YES];
337 }
338}
339
340
341- (NSColor *)backgroundColor
342{
343 return backgroundColor;
344}
345
346
347- (void)setBackgroundColor:(NSColor *)newBackgroundColor
348{
349 [newBackgroundColor retain];
350 [backgroundColor release];
351 backgroundColor = newBackgroundColor;
352 if (![self drawsGradientBackground]) {
353 [self setNeedsDisplay:YES];
354 }
355}
356
357
358- (BOOL)drawsGradientBackground
359{
360 return drawsGradientBackground;
361}
362
363
364- (void)setDrawsGradientBackground:(BOOL)newDrawsGradientBackground
365{
366 drawsGradientBackground = newDrawsGradientBackground;
367 [self setNeedsDisplay:YES];
368}
369
370
371@end
372

Archive Download this file

Revision: 80