Plugins/Displays/Nano/GrowlNanoWindowView.m
author Rudy Richter
Sat Aug 01 20:43:39 2009 -0400 (2009-08-01)
changeset 4259 0e9b6b0b1e25
parent 4246 4f52d1d98978
child 4666 59b81a267426
permissions -rw-r--r--
Plugins: clang warnings
rudy@2886
     1
//
rudy@2886
     2
//  GrowlNanoWindowView.m
rudy@2886
     3
//  Display Plugins
rudy@2886
     4
//
rudy@2886
     5
//  Created by Rudy Richter on 12/12/2005.
ingmarstein@3040
     6
//  Copyright 2005-2006, The Growl Project. All rights reserved.
rudy@2886
     7
//
rudy@2886
     8
rudy@2886
     9
#import "GrowlNanoWindowView.h"
rudy@2886
    10
#import "GrowlNanoPrefs.h"
rudy@2886
    11
#import "GrowlImageAdditions.h"
rudy@2886
    12
rudy@2945
    13
extern CGLayerRef CGLayerCreateWithContext() __attribute__((weak_import));
rudy@2945
    14
Rudy@4246
    15
void addRoundedBottomToPath(CGContextRef context, CGRect rect, CGFloat radius);
Rudy@4246
    16
Rudy@4246
    17
Rudy@4246
    18
void addRoundedBottomToPath(CGContextRef context, CGRect rect, CGFloat radius) {
Rudy@4246
    19
	CGFloat minX = CGRectGetMinX(rect);
Rudy@4246
    20
	CGFloat minY = CGRectGetMinY(rect);
Rudy@4246
    21
	CGFloat maxX = CGRectGetMaxX(rect);
Rudy@4246
    22
	CGFloat maxY = CGRectGetMaxY(rect);
Rudy@4246
    23
	CGFloat midX = CGRectGetMidX(rect);
Rudy@4246
    24
	CGFloat midY = CGRectGetMidY(rect);
rudy@2886
    25
rudy@2886
    26
	CGContextBeginPath(context);
rudy@2886
    27
	CGContextMoveToPoint(context, maxX, midY);
rudy@2886
    28
	CGContextAddLineToPoint(context, maxX, maxY);
rudy@2886
    29
	CGContextAddLineToPoint(context, minX, maxY);
rudy@2886
    30
	CGContextAddLineToPoint(context, minX, midY);
rudy@2886
    31
	CGContextAddArcToPoint(context, minX, minY, midX, minY, radius);
rudy@2886
    32
	CGContextAddArcToPoint(context, maxX, minY, maxX, midY, radius);
rudy@2886
    33
	CGContextClosePath(context);
rudy@2886
    34
}
rudy@2886
    35
rudy@2886
    36
@implementation GrowlNanoWindowView
rudy@2886
    37
rudy@2886
    38
- (id) initWithFrame:(NSRect)frame {
rudy@2886
    39
	if ((self = [super initWithFrame:frame])) {
rudy@2886
    40
		cache = [[NSImage alloc] initWithSize:frame.size];
rudy@2886
    41
		needsDisplay = YES;
rudy@2886
    42
	}
rudy@2886
    43
rudy@2886
    44
	return self;
rudy@2886
    45
}
rudy@2886
    46
rudy@2886
    47
- (void) dealloc {
rudy@2886
    48
	[titleAttributes release];
rudy@2886
    49
	[textAttributes  release];
rudy@2886
    50
	[backgroundColor release];
rudy@2886
    51
	[textColor       release];
rudy@2886
    52
	[icon            release];
rudy@2886
    53
	[title           release];
rudy@2886
    54
	[text            release];
rudy@2886
    55
	[cache           release];
rudy@2886
    56
	if (layer)
rudy@2886
    57
		CGLayerRelease(layer);
rudy@2886
    58
rudy@2886
    59
	[super dealloc];
rudy@2886
    60
}
rudy@2886
    61
rudy@2886
    62
- (void) drawRect:(NSRect)rect {
rudy@3006
    63
		
rudy@3006
    64
	NSGraphicsContext *context = [NSGraphicsContext currentContext];
rudy@3006
    65
	CGContextRef cgContext = [context graphicsPort];
rudy@3006
    66
	NSRect bounds = [self bounds];
rudy@3006
    67
rudy@3006
    68
	if (needsDisplay) {
rudy@3006
    69
		// rects and sizes
rudy@3006
    70
		int sizePref = 0;
rudy@3006
    71
		READ_GROWL_PREF_INT(Nano_SIZE_PREF, GrowlNanoPrefDomain, &sizePref);
rudy@3006
    72
		NSRect titleRect, textRect;
rudy@3006
    73
		NSRect iconRect;
rudy@3006
    74
rudy@3006
    75
		if (sizePref == Nano_SIZE_HUGE) {
Rudy@4246
    76
			titleRect.origin.x = 10.0;
Rudy@4246
    77
			titleRect.origin.y = NSHeight(bounds) - 28.0;
Rudy@4246
    78
			titleRect.size.width = NSWidth(bounds) - 32.0;
Rudy@4246
    79
			titleRect.size.height = 20.0;
rudy@3006
    80
			
Rudy@4246
    81
			textRect.origin.y = NSHeight(bounds) - 41.0;
Rudy@4246
    82
			textRect.size.height = 15.0;
rudy@3006
    83
			
Rudy@4246
    84
			iconRect.origin.x = 230.0;
Rudy@4246
    85
			iconRect.origin.y = NSHeight(bounds) - 40.0;
Rudy@4246
    86
			iconRect.size.width = 32.0;
Rudy@4246
    87
			iconRect.size.height = 32.0;
rudy@3176
    88
		} else {
Rudy@4246
    89
			titleRect.origin.x = 10.0;
Rudy@4246
    90
			titleRect.origin.y = NSHeight(bounds) - 14.0;
Rudy@4246
    91
			titleRect.size.width = NSWidth(bounds) - 16.0;
Rudy@4246
    92
			titleRect.size.height = 12.0;
rudy@3176
    93
			
Rudy@4246
    94
			textRect.origin.y = NSHeight(bounds) - 22.0;
Rudy@4246
    95
			textRect.size.height = 10.0;
rudy@3176
    96
			
Rudy@4246
    97
			iconRect.origin.x = 160.0;
Rudy@4246
    98
			iconRect.origin.y = NSHeight(bounds) - 20.0;
Rudy@4246
    99
			iconRect.size.width = 16.0;
Rudy@4246
   100
			iconRect.size.height = 16.0;
rudy@3176
   101
		}
rudy@3006
   102
		textRect.origin.x = titleRect.origin.x;
rudy@3006
   103
		textRect.size.width = titleRect.size.width;
rudy@3006
   104
rudy@3006
   105
		//draw to cache
rudy@3006
   106
		/*if (CGLayerCreateWithContext) {
rudy@3006
   107
			if (!layer)
rudy@3006
   108
				layer = CGLayerCreateWithContext(cgContext, CGSizeMake(bounds.size.width, bounds.size.height), NULL);
rudy@3006
   109
			[NSGraphicsContext setCurrentContext:
rudy@3006
   110
				[NSGraphicsContext graphicsContextWithGraphicsPort:CGLayerGetContext(layer) flipped:NO]];
rudy@3006
   111
		} else {
rudy@3006
   112
			[cache lockFocus];
rudy@3006
   113
		}*/
rudy@3006
   114
rudy@3006
   115
		NSRect c = [self bounds];
rudy@3006
   116
		CGRect b = CGRectMake(c.origin.x, c.origin.y, c.size.width, c.size.height);
Rudy@4246
   117
		addRoundedBottomToPath(cgContext, b, 10.0);
Rudy@4246
   118
Rudy@4246
   119
		CGFloat opacityPref = Nano_DEFAULT_OPACITY;
rudy@3006
   120
		READ_GROWL_PREF_FLOAT(Nano_OPACITY_PREF, GrowlNanoPrefDomain, &opacityPref);
Rudy@4246
   121
		CGFloat alpha = opacityPref * 0.01;
rudy@3006
   122
		[[backgroundColor colorWithAlphaComponent:alpha] set];
rudy@3006
   123
		CGContextFillPath(cgContext);
rudy@3006
   124
rudy@3006
   125
		////NSRectFill(bounds);
rudy@3006
   126
		[title drawInRect:titleRect withAttributes:titleAttributes];
rudy@3006
   127
rudy@3006
   128
		[text drawInRect:textRect withAttributes:textAttributes];
rudy@3006
   129
		[icon setFlipped:NO];
Rudy@4246
   130
		[icon drawScaledInRect:iconRect operation:NSCompositeSourceOver fraction:1.0];
rudy@3006
   131
rudy@3006
   132
		/*if (CGLayerCreateWithContext)
rudy@3006
   133
			[NSGraphicsContext setCurrentContext:context];
rudy@3006
   134
		else
rudy@3006
   135
			[cache unlockFocus];
rudy@3006
   136
rudy@3006
   137
		needsDisplay = NO;*/
rudy@3006
   138
	}
rudy@3006
   139
rudy@3006
   140
	// draw background
rudy@3006
   141
	//[[NSColor clearColor] set];
rudy@3006
   142
	//NSRectFill(rect);
rudy@3006
   143
	//CGContextFillPath(cgContext);
rudy@3006
   144
	// draw cache to screen
rudy@3006
   145
	NSRect imageRect = rect;
rudy@3006
   146
	int effect = Nano_EFFECT_SLIDE;
rudy@3006
   147
	READ_GROWL_PREF_BOOL(Nano_EFFECT_PREF, GrowlNanoPrefDomain, &effect);
rudy@3006
   148
	if (effect == Nano_EFFECT_SLIDE) {
rudy@3006
   149
		if (CGLayerCreateWithContext)
Rudy@4246
   150
			imageRect.origin.y = 0.0;
rudy@3006
   151
	} else if (effect == Nano_EFFECT_WIPE) {
rudy@3006
   152
		rect.size.height -= imageRect.origin.y;
rudy@3006
   153
		imageRect.size.height -= imageRect.origin.y;
rudy@3006
   154
		if (!CGLayerCreateWithContext)
Rudy@4246
   155
			imageRect.origin.y = 0.0;
rudy@3006
   156
	}
rudy@3006
   157
rudy@3006
   158
	if (CGLayerCreateWithContext) {
rudy@3006
   159
		CGRect cgRect;
rudy@3006
   160
		cgRect.origin.x = imageRect.origin.x;
rudy@3006
   161
		cgRect.origin.y = imageRect.origin.y;
rudy@3006
   162
		cgRect.size.width = rect.size.width;
rudy@3006
   163
		if (effect == Nano_EFFECT_WIPE) {
rudy@3006
   164
			cgRect.size.height = rect.size.height;
rudy@3006
   165
			CGContextClipToRect(cgContext, cgRect);
rudy@2886
   166
		}
rudy@3006
   167
		cgRect.size.height = bounds.size.height;
rudy@3006
   168
		CGContextDrawLayerInRect(cgContext, cgRect, layer);
rudy@3006
   169
	} else {
Rudy@4246
   170
		[cache drawInRect:rect fromRect:imageRect operation:NSCompositeSourceOver fraction:1.0];
rudy@3006
   171
	}
rudy@2886
   172
}
rudy@2886
   173
rudy@2886
   174
- (void) setIcon:(NSImage *)anIcon {
rudy@2886
   175
	[icon autorelease];
rudy@2886
   176
	icon = [anIcon retain];
rudy@2886
   177
	[self setNeedsDisplay:(needsDisplay = YES)];
rudy@2886
   178
}
rudy@2886
   179
rudy@2886
   180
- (void) setTitle:(NSString *)aTitle {
rudy@2886
   181
	[title autorelease];
rudy@2886
   182
	title = [aTitle copy];
rudy@2886
   183
	[self setNeedsDisplay:(needsDisplay = YES)];
rudy@2886
   184
}
rudy@2886
   185
rudy@2886
   186
- (void) setText:(NSString *)aText {
rudy@2886
   187
	[text autorelease];
rudy@2886
   188
	text = [aText copy];
rudy@2886
   189
	[self setNeedsDisplay:(needsDisplay = YES)];
rudy@2886
   190
}
rudy@2886
   191
rudy@2886
   192
- (void) setPriority:(int)priority {
rudy@2886
   193
	NSString *key;
rudy@2886
   194
	NSString *textKey;
rudy@2886
   195
	switch (priority) {
rudy@2886
   196
		case -2:
rudy@2886
   197
			key = GrowlNanoVeryLowBackgroundColor;
rudy@2886
   198
			textKey = GrowlNanoVeryLowTextColor;
rudy@2886
   199
			break;
rudy@2886
   200
		case -1:
rudy@2886
   201
			key = GrowlNanoModerateBackgroundColor;
rudy@2886
   202
			textKey = GrowlNanoModerateTextColor;
rudy@2886
   203
			break;
rudy@2886
   204
		case 1:
rudy@2886
   205
			key = GrowlNanoHighBackgroundColor;
rudy@2886
   206
			textKey = GrowlNanoHighTextColor;
rudy@2886
   207
			break;
rudy@2886
   208
		case 2:
rudy@2886
   209
			key = GrowlNanoEmergencyBackgroundColor;
rudy@2886
   210
			textKey = GrowlNanoEmergencyTextColor;
rudy@2886
   211
			break;
rudy@2886
   212
		case 0:
rudy@2886
   213
		default:
rudy@2886
   214
			key = GrowlNanoNormalBackgroundColor;
rudy@2886
   215
			textKey = GrowlNanoNormalTextColor;
rudy@2886
   216
			break;
rudy@2886
   217
	}
rudy@2886
   218
rudy@2886
   219
	[backgroundColor release];
rudy@2886
   220
Rudy@4246
   221
	CGFloat opacityPref = Nano_DEFAULT_OPACITY;
rudy@2886
   222
	READ_GROWL_PREF_FLOAT(Nano_OPACITY_PREF, GrowlNanoPrefDomain, &opacityPref);
Rudy@4246
   223
	CGFloat alpha = opacityPref * 0.01;
rudy@2886
   224
rudy@2886
   225
	Class NSDataClass = [NSData class];
rudy@2886
   226
	NSData *data = nil;
rudy@2886
   227
rudy@2886
   228
	READ_GROWL_PREF_VALUE(key, GrowlNanoPrefDomain, NSData *, &data);
Rudy@4259
   229
	if(data)
Rudy@4259
   230
		CFMakeCollectable(data);		
rudy@2886
   231
	if (data && [data isKindOfClass:NSDataClass])
rudy@2886
   232
		backgroundColor = [NSUnarchiver unarchiveObjectWithData:data];
rudy@2886
   233
	else
rudy@2886
   234
		backgroundColor = [NSColor blackColor];
rudy@2886
   235
	backgroundColor = [[backgroundColor colorWithAlphaComponent:alpha] retain];
rudy@2886
   236
	[data release];
rudy@2886
   237
	data = nil;
rudy@2886
   238
rudy@2886
   239
	[textColor release];
rudy@2886
   240
	READ_GROWL_PREF_VALUE(textKey, GrowlNanoPrefDomain, NSData *, &data);
Rudy@4259
   241
	if(data)
Rudy@4259
   242
		CFMakeCollectable(data);		
rudy@2886
   243
	if (data && [data isKindOfClass:NSDataClass])
rudy@2886
   244
		textColor = [NSUnarchiver unarchiveObjectWithData:data];
rudy@2886
   245
	else
rudy@2886
   246
		textColor = [NSColor whiteColor];
rudy@2886
   247
	[textColor retain];
rudy@2886
   248
	[data release];
rudy@2886
   249
Rudy@4246
   250
	CGFloat titleFontSize;
Rudy@4246
   251
	CGFloat textFontSize;
rudy@2886
   252
	int sizePref = 0;
rudy@2886
   253
	READ_GROWL_PREF_INT(Nano_SIZE_PREF, GrowlNanoPrefDomain, &sizePref);
rudy@2886
   254
rudy@2886
   255
	if (sizePref == Nano_SIZE_HUGE) {
Rudy@4246
   256
		titleFontSize = 14.0;
Rudy@4246
   257
		textFontSize = 12.0;
rudy@2886
   258
	} else {
Rudy@4246
   259
		titleFontSize = 10.0;
Rudy@4246
   260
		textFontSize = 8.0;
rudy@2886
   261
	}
rudy@2886
   262
rudy@2886
   263
	NSShadow *textShadow = [[NSShadow alloc] init];
rudy@2886
   264
Rudy@4246
   265
	NSSize shadowSize = {0.0, -2.0};
rudy@2886
   266
	[textShadow setShadowOffset:shadowSize];
Rudy@4246
   267
	[textShadow setShadowBlurRadius:3.0];
rudy@2886
   268
	[textShadow setShadowColor:[NSColor blackColor]];
rudy@2886
   269
rudy@2886
   270
	NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
rudy@2886
   271
	[paragraphStyle setAlignment:NSLeftTextAlignment];
rudy@2886
   272
	[paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
rudy@2886
   273
	[titleAttributes release];
rudy@2886
   274
	titleAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
rudy@2886
   275
		textColor,                                   NSForegroundColorAttributeName,
rudy@2886
   276
		paragraphStyle,                              NSParagraphStyleAttributeName,
rudy@2886
   277
		[NSFont boldSystemFontOfSize:titleFontSize], NSFontAttributeName,
rudy@2886
   278
		textShadow,                                  NSShadowAttributeName,
rudy@2886
   279
		nil];
rudy@2886
   280
	[paragraphStyle release];
rudy@2886
   281
rudy@2886
   282
	paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
rudy@2886
   283
	[paragraphStyle setAlignment:NSLeftTextAlignment];
rudy@2886
   284
	[textAttributes release];
rudy@2886
   285
	textAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
rudy@2886
   286
		textColor,                               NSForegroundColorAttributeName,
rudy@2886
   287
		paragraphStyle,                          NSParagraphStyleAttributeName,
rudy@2886
   288
		[NSFont messageFontOfSize:textFontSize], NSFontAttributeName,
rudy@2886
   289
		textShadow,                              NSShadowAttributeName,
rudy@2886
   290
		nil];
rudy@2886
   291
	[paragraphStyle release];
rudy@2886
   292
	[textShadow release];
rudy@2886
   293
}
rudy@2886
   294
rudy@2886
   295
- (id) target {
rudy@2886
   296
	return target;
rudy@2886
   297
}
rudy@2886
   298
rudy@2886
   299
- (void) setTarget:(id) object {
rudy@2886
   300
	target = object;
rudy@2886
   301
}
rudy@2886
   302
rudy@2886
   303
#pragma mark -
rudy@2886
   304
rudy@2886
   305
- (SEL) action {
rudy@2886
   306
	return action;
rudy@2886
   307
}
rudy@2886
   308
rudy@2886
   309
- (void) setAction:(SEL) selector {
rudy@2886
   310
	action = selector;
rudy@2886
   311
}
rudy@2886
   312
rudy@2886
   313
#pragma mark -
rudy@2886
   314
rudy@2886
   315
- (BOOL) needsDisplay {
rudy@2886
   316
	return needsDisplay && [super needsDisplay];
rudy@2886
   317
}
rudy@2886
   318
rudy@2886
   319
@end