aboutsummaryrefslogtreecommitdiff
path: root/AppKit
diff options
context:
space:
mode:
authorGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-10-22 19:16:19 +0000
committerGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-10-22 19:16:19 +0000
commit11938e47355bfbf3b81f1ff5b15f1222b83d4f47 (patch)
tree3794c78559472e4b2efe5eabc0e094d7c14a9743 /AppKit
parent90eba8f973c0b77f36dc7084163ff0d43675a1a8 (diff)
- GTM_INLINE will make sure a function gets inlined, and provides a consistent
way for all GTM code to do it. - Added GTMDebugThreadValidation to allow you to enforce the fact that your code must run in the main thread in DEBUG builds. - Updated some internals of the iPhone unittesting so it doesn't double print the test descriptions, file names, or lines numbers of a test failure line. Also includes the test names in the error output. - Changed the xcconfigs so that know it's easier to set different settings at the different levels and not accidentally overwrite settings set at lower levels in the "settings collapse". Also tightened up warnings significantly. - Changed how gtm_unitTestExposedBindingsTestValues works. If you have an implementation of gtm_unitTestExposedBindingsTestValues in your own code you will need to update to the new way of calling. See implementations in GTMNSObject+BindingUnitTesting.m for details. - Added support for grabbing the build number for a particular OS in GTMSystemVersion and easily comparing it to known build numbers, and switched some types from in GTMSystemVersion from "int" to SInt32 to make 64 bit work better. - Added support for SnowLeopard (10A96). We build cleanly with the 10.6 SDKs and all radar checks were updated accordingly. Build All script was also updated to build on SnowLeopard if you have the SDK available. - Turned off building ppc64 GTM because the SnowLeopard SDK currently doesn't have ppc64 support, so SenTestCase isn't defined. This makes it impossible to build the ppc64 10.5 config on SnowLeopard. We have left the setting in the xcconfig for those of you who need it, but have disabled it in the GTM project settings. - Turned on stack smashing protection on the debug builds for all Leopard and above. - Added ability to easily do leak checking by defining the GTM_ENABLE_LEAKS environment variable. It isn't on by default because several of Apple's frameworks leak. You can work around these false positives by using the GTM_LEAKS_SYMBOLS_TO_IGNORE environment variable. Also if you turn on leaks make sure to turn off zombies by defining the GTM_DISABLE_ZOMBIES variable, otherwise every memory allocation you do will look like a leak.
Diffstat (limited to 'AppKit')
-rw-r--r--AppKit/GTMGetURLHandler.m284
-rw-r--r--AppKit/GTMLargeTypeWindowTest.m2
-rw-r--r--AppKit/GTMLinearRGBShading.m2
-rw-r--r--AppKit/GTMLinearRGBShadingTest.m2
-rw-r--r--AppKit/GTMNSBezierPath+Shading.m2
-rw-r--r--AppKit/GTMNSImage+Scaling.h4
-rw-r--r--AppKit/GTMNSImage+Scaling.m17
-rw-r--r--AppKit/GTMNSImage+ScalingTest.m21
-rw-r--r--AppKit/TestData/GTMNSBezierPath+ShadingTest.tiff (renamed from AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff)bin45080 -> 45080 bytes
9 files changed, 325 insertions, 9 deletions
diff --git a/AppKit/GTMGetURLHandler.m b/AppKit/GTMGetURLHandler.m
new file mode 100644
index 0000000..a35dd95
--- /dev/null
+++ b/AppKit/GTMGetURLHandler.m
@@ -0,0 +1,284 @@
+//
+// GTMGetURLHandler.m
+//
+// Copyright 2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+// Add this class to your app to have get URL handled almost automatically for
+// you. For each entry in your CFBundleURLTypes dictionaries, add a new
+// key/object pair of GTMBundleURLClass/the name of the class you want
+// to have handle the scheme(s).
+// Then have that class respond to the class method:
+// + (BOOL)gtm_openURL:(NSURL*)url
+// and voila, it will just work.
+// Note that in Debug mode we will do extensive testing to make sure that this
+// is all hooked up correctly, and will spew out to the console if we
+// find anything amiss.
+//
+// Example plist entry
+// ...
+//
+// <key>CFBundleURLTypes</key>
+// <array>
+// <dict>
+// <key>CFBundleURLName</key>
+// <string>Google Suggestion URL</string>
+// <key>GTMBundleURLClass</key>
+// <string>GoogleSuggestURLHandler</string>
+// <key>CFBundleURLSchemes</key>
+// <array>
+// <string>googlesuggest</string>
+// <string>googlesuggestextreme</string>
+// </array>
+// </dict>
+// </array>
+//
+//
+// Example implementation
+// @interface GoogleSuggestURLHandler
+// @end
+// @implementation GoogleSuggestURLHandler
+// + (BOOL)gtm_openURL:(NSURL*)url {
+// NSLog(@"%@", url);
+// }
+// @end
+
+#import <AppKit/AppKit.h>
+#import "GTMGarbageCollection.h"
+#import "GTMNSAppleEventDescriptor+Foundation.h"
+#import "GTMMethodCheck.h"
+
+static NSString *const kGTMBundleURLClassKey = @"GTMBundleURLClass";
+// A variety of constants Apple really should have defined somewhere to
+// allow the compiler to find your typos.
+static NSString *const kGTMCFBundleURLSchemesKey = @"CFBundleURLSchemes";
+static NSString *const kGTMCFBundleURLNameKey = @"CFBundleURLName";
+static NSString *const kGTMCFBundleTypeRoleKey = @"CFBundleTypeRole";
+static NSString *const kGTMCFBundleURLTypesKey = @"CFBundleURLTypes";
+static NSString *const kGTMCFBundleViewerRole = @"Viewer";
+static NSString *const kGTMCFBundleEditorRole = @"Editor";
+
+// Set this macro elsewhere is you want to force the
+// bundle checks on/off. They are nice for debugging
+// problems, but shouldn't be required in a release version
+// unless you are paranoid about your users messing with your
+// Info.plist
+#ifndef GTM_CHECK_BUNDLE_URL_CLASSES
+#define GTM_CHECK_BUNDLE_URL_CLASSES DEBUG
+#endif // GTM_CHECK_BUNDLE_URL_CLASSES
+
+@protocol GTMGetURLHandlerProtocol
++ (BOOL)gtm_openURL:(NSURL*)url;
+@end
+
+@interface GTMGetURLHandler : NSObject {
+ NSArray *urlTypes_;
+}
+- (id)initWithTypes:(NSArray*)urlTypes;
+- (void)getUrl:(NSAppleEventDescriptor *)event
+withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
+- (void)addError:(OSStatus)error
+ withDescription:(NSString*)string
+ toDescriptor:(NSAppleEventDescriptor *)desc;
++ (id)handlerForBundle:(NSBundle *)bundle;
++ (void)appFinishedLaunchingHandler:(NSNotification*)notification;
+@end
+
+@implementation GTMGetURLHandler
+GTM_METHOD_CHECK(NSNumber, gtm_appleEventDescriptor);
+GTM_METHOD_CHECK(NSString, gtm_appleEventDescriptor);
+
++ (void)load {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc addObserver:self
+ selector:@selector(appFinishedLaunchingHandler:)
+ name:NSApplicationDidFinishLaunchingNotification
+ object:nil];
+ [pool release];
+}
+
++ (void)appFinishedLaunchingHandler:(NSNotification*)notification {
+ NSBundle *bundle = [NSBundle mainBundle];
+ GTMGetURLHandler *handler = [GTMGetURLHandler handlerForBundle:bundle];
+ if (handler) {
+ [handler retain];
+ GTMNSMakeUncollectable(handler);
+ NSAppleEventManager *man = [NSAppleEventManager sharedAppleEventManager];
+ [man setEventHandler:handler
+ andSelector:@selector(getUrl:withReplyEvent:)
+ forEventClass:kInternetEventClass
+ andEventID:kAEGetURL];
+ }
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+ [nc removeObserver:self
+ name:NSApplicationDidFinishLaunchingNotification
+ object:nil];
+}
+
++ (id)handlerForBundle:(NSBundle *)bundle {
+ GTMGetURLHandler *handler = nil;
+ NSArray *urlTypes
+ = [bundle objectForInfoDictionaryKey:kGTMCFBundleURLTypesKey];
+ if (urlTypes) {
+ handler = [[[GTMGetURLHandler alloc] initWithTypes:urlTypes] autorelease];
+ } else {
+ _GTMDevLog(@"If you don't have CFBundleURLTypes in your plist, you may want"
+ @" to remove GTMGetURLHandler.m from your project");
+ }
+ return handler;
+}
+
+- (id)initWithTypes:(NSArray*)urlTypes {
+ if ((self = [super init])) {
+ urlTypes_ = [urlTypes retain];
+#if GTM_CHECK_BUNDLE_URL_CLASSES
+ // Some debug handling to check to make sure we can handle the
+ // classes properly.
+ NSEnumerator *enumerator = [urlTypes_ objectEnumerator];
+ NSDictionary *urlType;
+ while ((urlType = [enumerator nextObject])) {
+ NSString *className = [urlType objectForKey:kGTMBundleURLClassKey];
+ if ([className length]) {
+ Class cls = NSClassFromString(className);
+ if (cls) {
+ if (![cls respondsToSelector:@selector(gtm_openURL:)]) {
+ _GTMDevLog(@"Class %@ for URL handler %@ "
+ "(URL schemes: %@) doesn't respond to openURL:",
+ className,
+ [urlType objectForKey:kGTMCFBundleURLNameKey],
+ [urlType objectForKey:kGTMCFBundleURLSchemesKey]);
+ }
+ } else {
+ _GTMDevLog(@"Unable to get class %@ for URL handler %@ "
+ "(URL schemes: %@)",
+ className,
+ [urlType objectForKey:kGTMCFBundleURLNameKey],
+ [urlType objectForKey:kGTMCFBundleURLSchemesKey]);
+ }
+ } else {
+ NSString *role = [urlType objectForKey:kGTMCFBundleTypeRoleKey];
+ if ([role caseInsensitiveCompare:kGTMCFBundleViewerRole] == NSOrderedSame ||
+ [role caseInsensitiveCompare:kGTMCFBundleEditorRole] == NSOrderedSame) {
+ _GTMDevLog(@"Missing %@ for URL handler %@ "
+ "(URL schemes: %@)",
+ kGTMBundleURLClassKey,
+ [urlType objectForKey:kGTMCFBundleURLNameKey],
+ [urlType objectForKey:kGTMCFBundleURLSchemesKey]);
+ }
+ }
+ }
+#endif // GTM_CHECK_BUNDLE_URL_CLASSES
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [urlTypes_ release];
+ [super dealloc];
+}
+
+- (NSURL*)extractURLFromEvent:(NSAppleEventDescriptor*)event
+ withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
+ NSAppleEventDescriptor *desc
+ = [event paramDescriptorForKeyword:keyDirectObject];
+ NSString *urlstring = [desc stringValue];
+ NSURL *url = [NSURL URLWithString:urlstring];
+ if (!url) {
+ [self addError:errAECoercionFail
+ withDescription:@"Unable to extract url from key direct object."
+ toDescriptor:replyEvent];
+ }
+ return url;
+}
+
+- (Class)getClassForScheme:(NSString *)scheme
+ withReplyEvent:(NSAppleEventDescriptor*)replyEvent {
+ NSEnumerator *typeEnumerator = [urlTypes_ objectEnumerator];
+ NSDictionary *urlType;
+ Class cls = nil;
+ NSString *typeScheme = nil;
+ while (!typeScheme && (urlType = [typeEnumerator nextObject])) {
+ NSArray *schemes = [urlType objectForKey:kGTMCFBundleURLSchemesKey];
+ NSEnumerator *schemeEnumerator = [schemes objectEnumerator];
+ while ((typeScheme = [schemeEnumerator nextObject])) {
+ if ([typeScheme caseInsensitiveCompare:scheme] == NSOrderedSame) {
+ break;
+ }
+ }
+ }
+ if (typeScheme) {
+ NSString *class = [urlType objectForKey:kGTMBundleURLClassKey];
+ if (class) {
+ cls = NSClassFromString(class);
+ }
+ if (!cls) {
+ NSString *errorString
+ = [NSString stringWithFormat:@"Unable to instantiate class for "
+ "%@:%@ for scheme:%@.",
+ kGTMBundleURLClassKey, class, typeScheme];
+ [self addError:errAECorruptData
+ withDescription:errorString
+ toDescriptor:replyEvent];
+ }
+ } else {
+ NSString *errorString
+ = [NSString stringWithFormat:@"Unable to find handler for scheme %@.",
+ scheme];
+ [self addError:errAECorruptData
+ withDescription:errorString
+ toDescriptor:replyEvent];
+ }
+ return cls;
+}
+
+- (void)getUrl:(NSAppleEventDescriptor *)event
+withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
+ NSURL *url = [self extractURLFromEvent:event withReplyEvent:replyEvent];
+ if (!url) {
+ return;
+ }
+ NSString *scheme = [url scheme];
+ Class cls = [self getClassForScheme:scheme withReplyEvent:replyEvent];
+ if (!cls) {
+ return;
+ }
+ BOOL wasGood = [cls gtm_openURL:url];
+ if (!wasGood) {
+ NSString *errorString
+ = [NSString stringWithFormat:@"[%@ gtm_openURL:] failed to handle %@",
+ NSStringFromClass(cls), url];
+ [self addError:errAEEventNotHandled
+ withDescription:errorString
+ toDescriptor:replyEvent];
+ }
+}
+
+- (void)addError:(OSStatus)error
+ withDescription:(NSString*)string
+ toDescriptor:(NSAppleEventDescriptor *)desc {
+ NSAppleEventDescriptor *errorDesc = nil;
+ if (error != noErr) {
+ NSNumber *errNum = [NSNumber numberWithLong:error];
+ errorDesc = [errNum gtm_appleEventDescriptor];
+ [desc setParamDescriptor:errorDesc forKeyword:keyErrorNumber];
+ }
+ if (string) {
+ errorDesc = [string gtm_appleEventDescriptor];
+ [desc setParamDescriptor:errorDesc forKeyword:keyErrorString];
+ }
+}
+@end
+
diff --git a/AppKit/GTMLargeTypeWindowTest.m b/AppKit/GTMLargeTypeWindowTest.m
index 36e60c3..6e0577a 100644
--- a/AppKit/GTMLargeTypeWindowTest.m
+++ b/AppKit/GTMLargeTypeWindowTest.m
@@ -64,7 +64,7 @@ NSString *const kShortTextBlock = @"Short";
// bug. Please bump the system check as appropriate when new systems are
// tested. Currently broken on 10.5.5 and below.
// Radar 6137322 CIFilter crashing when run with GC enabled
- long major, minor, bugfix;
+ SInt32 major, minor, bugfix;
[GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix];
if (!(GTMIsGarbageCollectionEnabled()
&& major <= 10 && minor <= 5 && bugfix <= 5)) {
diff --git a/AppKit/GTMLinearRGBShading.m b/AppKit/GTMLinearRGBShading.m
index ef13986..f0216bf 100644
--- a/AppKit/GTMLinearRGBShading.m
+++ b/AppKit/GTMLinearRGBShading.m
@@ -193,7 +193,7 @@ static void cShadeFunction(void *info, const CGFloat *inPos, CGFloat *outVals) {
// lazily create the colorspace as necessary
if (nil == colorSpace_) {
if (isCalibrated_) {
- colorSpace_ = CGColorSpaceCreateWithName(kCGColorSpaceUserRGB);
+ colorSpace_ = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
} else {
colorSpace_ = CGColorSpaceCreateDeviceRGB();
}
diff --git a/AppKit/GTMLinearRGBShadingTest.m b/AppKit/GTMLinearRGBShadingTest.m
index d70b878..38802e6 100644
--- a/AppKit/GTMLinearRGBShadingTest.m
+++ b/AppKit/GTMLinearRGBShadingTest.m
@@ -44,7 +44,7 @@
- (void)testShadingWith {
// Create a shading with kColorCount colors and make sure all the values are there.
- const NSUInteger kColorCount = 100;
+ enum { kColorCount = 100 };
NSColor *theColors[kColorCount];
CGFloat thePositions[kColorCount];
const CGFloat kColorIncrement = 1.0 / kColorCount;
diff --git a/AppKit/GTMNSBezierPath+Shading.m b/AppKit/GTMNSBezierPath+Shading.m
index eff8dfb..f75876f 100644
--- a/AppKit/GTMNSBezierPath+Shading.m
+++ b/AppKit/GTMNSBezierPath+Shading.m
@@ -154,7 +154,7 @@
@implementation NSBezierPath (GTMBezierPathShadingAdditions)
-GTM_METHOD_CHECK(NSBezierPath, gtm_createCGPath); // COV_NF_LINE
+GTM_METHOD_CHECK(NSBezierPath, gtm_createCGPath);
- (void)gtm_strokeAxiallyFrom:(NSPoint)fromPoint to:(NSPoint)toPoint
extendingStart:(BOOL)extendingStart extendingEnd:(BOOL)extendingEnd
diff --git a/AppKit/GTMNSImage+Scaling.h b/AppKit/GTMNSImage+Scaling.h
index 297d18c..6bf2dd5 100644
--- a/AppKit/GTMNSImage+Scaling.h
+++ b/AppKit/GTMNSImage+Scaling.h
@@ -26,8 +26,12 @@
// Return an existing representation of a size
- (NSImageRep *)gtm_representationOfSize:(NSSize)size;
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
// Return the exact or next largest representation for a size
+// If you are on SnowLeopard use
+// -[NSImage bestRepresentationForRect:context:hints:]
- (NSImageRep *)gtm_bestRepresentationForSize:(NSSize)size;
+#endif
// Create a new represetation for a given size
- (BOOL)gtm_createRepresentationOfSize:(NSSize)size;
diff --git a/AppKit/GTMNSImage+Scaling.m b/AppKit/GTMNSImage+Scaling.m
index 57687fd..5f31190 100644
--- a/AppKit/GTMNSImage+Scaling.m
+++ b/AppKit/GTMNSImage+Scaling.m
@@ -23,6 +23,9 @@
@implementation NSImage (GTMNSImageScaling)
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+// If you are on SnowLeopard use
+// -[NSImage bestRepresentationForRect:context:hints:]
- (NSImageRep *)gtm_bestRepresentationForSize:(NSSize)size {
NSImageRep *bestRep = [self gtm_representationOfSize:size];
if (bestRep) {
@@ -37,7 +40,7 @@
while ((thisRep = [repEnum nextObject])) {
CGFloat thisDistance;
thisDistance = MIN(size.width - [thisRep size].width,
- size.height-[thisRep size].height);
+ size.height - [thisRep size].height);
if (repDistance < 0 && thisDistance > 0) continue;
if (ABS(thisDistance) < ABS(repDistance)
@@ -53,6 +56,7 @@
return bestRep;
}
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
- (NSImageRep *)gtm_representationOfSize:(NSSize)size {
NSArray *reps = [self representations];
@@ -80,8 +84,15 @@
return NO;
}
- NSBitmapImageRep *bestRep =
- (NSBitmapImageRep *)[self gtm_bestRepresentationForSize:size];
+ NSBitmapImageRep *bestRep;
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+ bestRep = (NSBitmapImageRep *)[self gtm_bestRepresentationForSize:size];
+#else
+ bestRep
+ = (NSBitmapImageRep *)[self bestRepresentationForRect:GTMNSRectOfSize(size)
+ context:nil
+ hints:nil];
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
NSRect drawRect = GTMNSScaleRectToRect(GTMNSRectOfSize([bestRep size]),
GTMNSRectOfSize(size),
diff --git a/AppKit/GTMNSImage+ScalingTest.m b/AppKit/GTMNSImage+ScalingTest.m
index ec17cc5..5679b7c 100644
--- a/AppKit/GTMNSImage+ScalingTest.m
+++ b/AppKit/GTMNSImage+ScalingTest.m
@@ -21,6 +21,7 @@
#import "GTMSenTestCase.h"
#import "GTMNSImage+Scaling.h"
+#import "GTMGeometryUtils.h"
@interface GTMNSImage_ScalingTest : GTMTestCase
@end
@@ -31,7 +32,16 @@
NSImage *testImage = [NSImage imageNamed:@"NSApplicationIcon"];
NSImageRep *rep = nil;
- rep = [testImage gtm_bestRepresentationForSize:NSMakeSize(99, 99)];
+ NSRect bestRepRect = NSMakeRect(0, 0, 99, 99);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+ rep = [testImage bestRepresentationForRect:bestRepRect
+ context:nil
+ hints:nil];
+#else
+ rep = [testImage gtm_bestRepresentationForSize:bestRepRect.size];
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+
STAssertTrue(NSEqualSizes([rep size], NSMakeSize(128, 128)), nil);
[testImage gtm_createIconRepresentations];
@@ -39,7 +49,14 @@
STAssertNotNil([testImage gtm_representationOfSize:NSMakeSize(32, 32)], nil);
NSImage *duplicate = [testImage gtm_duplicateOfSize: NSMakeSize(48, 48)];
- rep = [duplicate gtm_bestRepresentationForSize:NSMakeSize(50, 50)];
+ bestRepRect = NSMakeRect(0, 0, 50, 50);
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+ rep = [duplicate bestRepresentationForRect:bestRepRect
+ context:nil
+ hints:nil];
+#else
+ rep = [duplicate gtm_bestRepresentationForSize:bestRepRect.size];
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
STAssertTrue(NSEqualSizes([rep size], NSMakeSize(48, 48)), nil);
}
diff --git a/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff b/AppKit/TestData/GTMNSBezierPath+ShadingTest.tiff
index b44b5bf..b44b5bf 100644
--- a/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff
+++ b/AppKit/TestData/GTMNSBezierPath+ShadingTest.tiff
Binary files differ