aboutsummaryrefslogtreecommitdiff
path: root/AppKit
diff options
context:
space:
mode:
authorGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-08-12 17:21:32 +0000
committerGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-08-12 17:21:32 +0000
commit7063d76a007fbf636250d7199d6f24ec487163b1 (patch)
tree5a1f2f0a4b597f62df3e2fe858d76d37b22bbe89 /AppKit
parent43982f07ba6a0a9839e32e774855c9d2068e9d5e (diff)
- Added GTMNSMakeUncollectable for forcing objects to survive in a GC world.
- Added GTMCFAutorelease to make the [GTMNSMakeCollectable(cfFoo) autorelease] simpler and clearer, it's now just GTMCFAutorelease(cfFoo), and works in both GC and non-GC world. - Added GTMIsGarbageCollectionEnabled to GTMGarbageCollection.h. See the note there for it's usage. - Disabled the unittests for things on top of NSAppleScript in a GC world since Apple has bugs and it can crash. See the unittest for a note about it. - GTMStackTrace now can figure out ObjC symbols. Downside it is now ObjC only. - GTMFourCharCode can now be used with NSAppleEventDescriptors easily. typeType, typeKeyword, typeApplSignature, and typeEnumerated all get turned into GTMFourCharCodes. - Fixed up crash in GTMLoggerRingBufferWriter when used with GC on. - Significant updates to GTMNSAppleScript+Handler allowing you to list all handlers and properties (including inherited) and cleans up several errors in how scripting was being handled.
Diffstat (limited to 'AppKit')
-rw-r--r--AppKit/GTMLargeTypeWindow.h9
-rw-r--r--AppKit/GTMLargeTypeWindow.m210
-rw-r--r--AppKit/GTMLargeTypeWindowTest.m100
-rw-r--r--AppKit/GTMLinearRGBShadingTest.m37
-rw-r--r--AppKit/GTMLoginItems.m10
-rw-r--r--AppKit/GTMLoginItemsTest.m46
-rw-r--r--AppKit/GTMNSBezierPath+CGPath.m4
-rw-r--r--AppKit/GTMNSBezierPath+RoundRectTest.m16
-rw-r--r--AppKit/GTMNSBezierPath+ShadingTest.m96
-rw-r--r--AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiffbin8042 -> 10728 bytes
-rw-r--r--AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiffbin8036 -> 10724 bytes
-rw-r--r--AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiffbin8042 -> 10728 bytes
-rw-r--r--AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiffbin19450 -> 45080 bytes
13 files changed, 415 insertions, 113 deletions
diff --git a/AppKit/GTMLargeTypeWindow.h b/AppKit/GTMLargeTypeWindow.h
index 9bb6b85..52316fc 100644
--- a/AppKit/GTMLargeTypeWindow.h
+++ b/AppKit/GTMLargeTypeWindow.h
@@ -28,6 +28,15 @@
// = [[[GTMLargeTypeWindow alloc] initWithString:@"Foo"] autorelease];
// [window makeKeyAndOrderFront:nil];
+// NB This class appears to have a problem with GC on 10.5.4 and below.
+// Radar 6137322 CIFilter crashing when run with GC enabled
+// This appears to be an Apple bug with GC.
+// We do a copy animation that causes things to crash, but only with GC
+// on. Currently I have left this enabled in GTMLargeTypeWindow pending
+// info from Apple on the bug. It's hard to reproduce, and only appears
+// at this time on our test machines.
+// Dual-Core Intel Xeon with ATI Radeon X1300
+
// Amount of time to fade the window in or out
const NSTimeInterval kGTMLargeTypeWindowFadeTime;
diff --git a/AppKit/GTMLargeTypeWindow.m b/AppKit/GTMLargeTypeWindow.m
index d84ce42..709099d 100644
--- a/AppKit/GTMLargeTypeWindow.m
+++ b/AppKit/GTMLargeTypeWindow.m
@@ -16,10 +16,12 @@
// the License.
//
+#import <QuartzCore/QuartzCore.h>
+
#import "GTMLargeTypeWindow.h"
#import "GTMGeometryUtils.h"
#import "GTMNSBezierPath+RoundRect.h"
-
+#import "GTMMethodCheck.h"
// Amount of time to fade the window in or out
const NSTimeInterval kGTMLargeTypeWindowFadeTime = 0.333;
@@ -30,15 +32,23 @@ static const CGFloat kEdgeInset = 16.0;
// Give us an alpha value for our backing window
static const CGFloat kTwoThirdsAlpha = 0.66;
-@interface GTMLargeTypeBackgroundView : NSView
+@interface GTMLargeTypeCopyAnimation : NSAnimation
+@end
+
+@interface GTMLargeTypeBackgroundView : NSView {
+ CIFilter *transition_;
+ GTMLargeTypeCopyAnimation *animation_;
+}
+- (void)animateCopy;
@end
@interface GTMLargeTypeWindow (GTMLargeTypeWindowPrivate)
+ (CGFloat)displayWidth;
-- (void)startFadeInAnimation;
+- (void)animateWithEffect:(NSString*)effect;
@end
@implementation GTMLargeTypeWindow
+
- (id)initWithString:(NSString *)string {
if ([string length] == 0) {
_GTMDevLog(@"GTMLargeTypeWindow got an empty string");
@@ -49,18 +59,44 @@ static const CGFloat kTwoThirdsAlpha = 0.66;
NSMutableAttributedString *attrString
= [[[NSMutableAttributedString alloc] initWithString:string] autorelease];
+ NSRange fullRange = NSMakeRange(0, [string length]);
+ [attrString addAttribute:NSForegroundColorAttributeName
+ value:[NSColor whiteColor]
+ range:fullRange];
+
+ NSMutableParagraphStyle *style
+ = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
+ [style setAlignment:NSCenterTextAlignment];
+ [attrString addAttribute:NSParagraphStyleAttributeName
+ value:style
+ range:fullRange];
+
+ NSShadow *textShadow = [[[NSShadow alloc] init] autorelease];
+ [textShadow setShadowOffset:NSMakeSize( 5, -5 )];
+ [textShadow setShadowBlurRadius:10];
+ [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0
+ alpha:kTwoThirdsAlpha]];
+ [attrString addAttribute:NSShadowAttributeName
+ value:textShadow
+ range:fullRange];
+
// Try and find a size that fits without iterating too many times.
// We start going 50 pixels at a time, then 10, then 1
int size = -26; // start at 24 (-26 + 50)
int offsets[] = { 50, 10, 1 };
+ NSSize bigSize = NSMakeSize(MAXFLOAT, MAXFLOAT);
+ NSStringDrawingOptions options = (NSStringDrawingUsesDeviceMetrics |
+ NSStringDrawingOneShot);
for (size_t i = 0; i < sizeof(offsets) / sizeof(int); ++i) {
for(size = size + offsets[i]; size >= 24 && size < 300; size += offsets[i]) {
- NSFont *textFont = [NSFont boldSystemFontOfSize:size];
- NSDictionary *fontAttr
- = [NSDictionary dictionaryWithObject:textFont
- forKey:NSFontAttributeName];
- NSSize textSize = [string sizeWithAttributes:fontAttr];
- if (textSize.width > displayWidth) {
+ NSFont *font = [NSFont boldSystemFontOfSize:size] ;
+ [attrString addAttribute:NSFontAttributeName
+ value:font
+ range:fullRange];
+ NSRect textSize = [attrString boundingRectWithSize:bigSize
+ options:options];
+ NSSize maxAdvanceSize = [font maximumAdvancement];
+ if (textSize.size.width + maxAdvanceSize.width > displayWidth) {
size = size - offsets[i];
break;
}
@@ -73,30 +109,9 @@ static const CGFloat kTwoThirdsAlpha = 0.66;
} else if (size < 24) {
size = 24;
}
-
- NSRange fullRange = NSMakeRange(0, [string length]);
[attrString addAttribute:NSFontAttributeName
value:[NSFont boldSystemFontOfSize:size]
range:fullRange];
- [attrString addAttribute:NSForegroundColorAttributeName
- value:[NSColor whiteColor]
- range:fullRange];
-
- NSMutableParagraphStyle *style
- = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
- [style setAlignment:NSCenterTextAlignment];
- [attrString addAttribute:NSParagraphStyleAttributeName
- value:style
- range:fullRange];
-
- NSShadow *textShadow = [[[NSShadow alloc] init] autorelease];
- [textShadow setShadowOffset:NSMakeSize( 5, -5 )];
- [textShadow setShadowBlurRadius:10];
- [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0
- alpha:kTwoThirdsAlpha]];
- [attrString addAttribute:NSShadowAttributeName
- value:textShadow
- range:fullRange];
return [self initWithAttributedString:attrString];
}
@@ -186,12 +201,26 @@ static const CGFloat kTwoThirdsAlpha = 0.66;
[pb setString:[[firstResponder textStorage] string]
forType:NSStringPboardType];
}
+
+ // Give the user some feedback that a copy has occurred
+ [(GTMLargeTypeBackgroundView*)[self contentView] animateCopy];
}
- (BOOL)canBecomeKeyWindow {
return YES;
}
+- (BOOL)performKeyEquivalent:(NSEvent *)theEvent {
+ NSString *chars = [theEvent charactersIgnoringModifiers];
+ NSUInteger flags = ([theEvent modifierFlags] &
+ NSDeviceIndependentModifierFlagsMask);
+ BOOL isValid = (flags == NSCommandKeyMask) && [chars isEqualToString:@"c"];
+ if (isValid) {
+ [self copy:self];
+ }
+ return isValid;
+}
+
- (void)keyDown:(NSEvent *)theEvent {
[self close];
}
@@ -204,30 +233,18 @@ static const CGFloat kTwoThirdsAlpha = 0.66;
}
- (void)makeKeyAndOrderFront:(id)sender {
- [self startFadeInAnimation];
[super makeKeyAndOrderFront:sender];
+ [self animateWithEffect:NSViewAnimationFadeInEffect];
}
- (void)orderFront:(id)sender {
- [self startFadeInAnimation];
[super orderFront:sender];
+ [self animateWithEffect:NSViewAnimationFadeInEffect];
}
- (void)orderOut:(id)sender {
- NSDictionary *fadeOut = [NSDictionary dictionaryWithObjectsAndKeys:
- self, NSViewAnimationTargetKey,
- NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey,
- nil];
- NSArray *animation = [NSArray arrayWithObject:fadeOut];
- NSViewAnimation *viewAnim
- = [[[NSViewAnimation alloc] initWithViewAnimations:animation] autorelease];
- [viewAnim setDuration:kGTMLargeTypeWindowFadeTime];
- [viewAnim startAnimation];
- NSDate *fadeOutDate
- = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime];
- // We have a local run loop because if this is called as part of a close
- // our window will be hidden immediately before it has a chance to fade.
- [[NSRunLoop currentRunLoop] runUntilDate:fadeOutDate];
+ [self animateWithEffect:NSViewAnimationFadeOutEffect];
+ [super orderOut:sender];
}
+ (CGFloat)displayWidth {
@@ -237,40 +254,105 @@ static const CGFloat kTwoThirdsAlpha = 0.66;
return NSWidth( screenRect ) * 11.0 / 12.0 - 2.0 * kEdgeInset;
}
-- (void)startFadeInAnimation {
- // If we aren't already fully visible, start fading us in.
- if ([self alphaValue] < 1.0) {
- NSDictionary *fadeIn = [NSDictionary dictionaryWithObjectsAndKeys:
- self, NSViewAnimationTargetKey,
- NSViewAnimationFadeInEffect, NSViewAnimationEffectKey,
- nil];
- NSArray *animation = [NSArray arrayWithObject:fadeIn];
- NSViewAnimation *viewAnim
- = [[[NSViewAnimation alloc] initWithViewAnimations:animation] autorelease];
- [viewAnim setDuration:kGTMLargeTypeWindowFadeTime];
- [viewAnim startAnimation];
- }
+- (void)animateWithEffect:(NSString*)effect {
+ NSDictionary *fadeIn = [NSDictionary dictionaryWithObjectsAndKeys:
+ self, NSViewAnimationTargetKey,
+ effect, NSViewAnimationEffectKey,
+ nil];
+ NSArray *animation = [NSArray arrayWithObject:fadeIn];
+ NSViewAnimation *viewAnim
+ = [[[NSViewAnimation alloc] initWithViewAnimations:animation] autorelease];
+ [viewAnim setDuration:kGTMLargeTypeWindowFadeTime];
+ [viewAnim setAnimationBlockingMode:NSAnimationBlocking];
+ [viewAnim startAnimation];
}
@end
@implementation GTMLargeTypeBackgroundView
+GTM_METHOD_CHECK(NSBezierPath, gtm_appendBezierPathWithRoundRect:cornerRadius:);
- (BOOL)isOpaque {
return NO;
}
- (void)drawRect:(NSRect)rect {
- [[NSColor colorWithDeviceWhite:0 alpha:kTwoThirdsAlpha] set];
rect = [self bounds];
-
NSBezierPath *roundRect = [NSBezierPath bezierPath];
CGFloat minRadius = MIN(NSWidth(rect), NSHeight(rect)) * 0.5f;
[roundRect gtm_appendBezierPathWithRoundRect:rect
cornerRadius:MIN(minRadius, 32)];
- [roundRect addClip];
- NSRectFill(rect);
- [super drawRect:rect];
+ [roundRect addClip];
+ if (transition_) {
+ NSNumber *val = [NSNumber numberWithFloat:[animation_ currentValue]];
+ [transition_ setValue:val forKey:@"inputTime"];
+ CIImage *outputCIImage = [transition_ valueForKey:@"outputImage"];
+ [outputCIImage drawInRect:rect
+ fromRect:rect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+ } else {
+ [[NSColor colorWithDeviceWhite:0 alpha:kTwoThirdsAlpha] set];
+
+ NSRectFill(rect);
+ }
}
+- (void)animateCopy {
+ // This does a photocopy swipe to show folks that their copy has succceeded
+ // Store off a copy of our background
+ NSRect bounds = [self bounds];
+ NSBitmapImageRep *rep = [self bitmapImageRepForCachingDisplayInRect:bounds];
+ NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep];
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:context];
+ [self drawRect:bounds];
+ [NSGraphicsContext restoreGraphicsState];
+ CIVector *extent = [CIVector vectorWithX:bounds.origin.x
+ Y:bounds.origin.y
+ Z:bounds.size.width
+ W:bounds.size.height];
+ CIFilter *transition = [CIFilter filterWithName:@"CICopyMachineTransition"];
+ [transition setDefaults];
+ [transition setValue:extent
+ forKey:@"inputExtent"];
+ CIImage *image = [[CIImage alloc] initWithBitmapImageRep:rep];
+
+ [transition setValue:image forKey:@"inputImage"];
+ [transition setValue:image forKey:@"inputTargetImage"];
+ [transition setValue:[NSNumber numberWithInt:0]
+ forKey:@"inputTime"];
+ [transition valueForKey:@"outputImage"];
+ [image release];
+ transition_ = [transition retain];
+ animation_ = [[GTMLargeTypeCopyAnimation alloc] initWithDuration:0.5
+ animationCurve:NSAnimationLinear];
+ [animation_ setFrameRate:0.0f];
+ [animation_ setDelegate:self];
+ [animation_ setAnimationBlockingMode:NSAnimationBlocking];
+ [animation_ startAnimation];
+}
+
+- (void)animationDidEnd:(NSAnimation*)animation {
+ [animation_ release];
+ animation_ = nil;
+ [transition_ release];
+ transition_ = nil;
+ [self display];
+}
+
+- (float)animation:(NSAnimation*)animation
+ valueForProgress:(NSAnimationProgress)progress {
+ // This gives us half the copy animation, so we don't swing back
+ // Don't want too much gratuitous effect
+ // 0.6 is required by experimentation. 0.5 doesn't do it
+ return progress * 0.6f;
+}
+@end
+
+@implementation GTMLargeTypeCopyAnimation
+- (void)setCurrentProgress:(NSAnimationProgress)progress {
+ [super setCurrentProgress:progress];
+ [[self delegate] display];
+}
@end
diff --git a/AppKit/GTMLargeTypeWindowTest.m b/AppKit/GTMLargeTypeWindowTest.m
index b4a9fe4..d9e56c2 100644
--- a/AppKit/GTMLargeTypeWindowTest.m
+++ b/AppKit/GTMLargeTypeWindowTest.m
@@ -20,6 +20,8 @@
#import "GTMLargeTypeWindow.h"
#import "GTMNSObject+UnitTesting.h"
#import "GTMUnitTestDevLog.h"
+#import "GTMGarbageCollection.h"
+#import "GTMSystemVersion.h"
NSString *const kLongTextBlock =
@"`Twas brillig, and the slithy toves "
@@ -49,11 +51,31 @@ NSString *const kLongTextBlock =
NSString *const kMediumTextBlock = @"For the Snark was a Boojum, you see.";
+NSString *const kShortTextBlock = @"Short";
+
@interface GTMLargeTypeWindowTest : GTMTestCase
@end
@implementation GTMLargeTypeWindowTest
-- (void)testLargeTypeWindow {
+- (BOOL)shouldDoAnimateCopy {
+ // NOTE: Animated copy tests are disabled when GC is on.
+ // See the comment/warning in the GTMLargeTypeWindow.h for more details,
+ // but we disable them to avoid the tests failing (crashing) when it's Apple's
+ // bug. Please bump the system check as appropriate when new systems are
+ // tested. Currently broken on 10.5.4 and below.
+ // Radar 6137322 CIFilter crashing when run with GC enabled
+ long major, minor, bugfix;
+ [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix];
+ if (!(GTMIsGarbageCollectionEnabled()
+ && major <= 10 && minor <= 5 && bugfix <= 4)) {
+ return YES;
+ } else {
+ NSLog(@"--- animated copy not run because of GC incompatibilites ---");
+ return NO;
+ }
+}
+
+- (void)testLargeTypeWindowIllegalInits {
[GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty string"];
GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc]
initWithString:@""] autorelease];
@@ -82,9 +104,11 @@ NSString *const kMediumTextBlock = @"For the Snark was a Boojum, you see.";
[GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty image"];
window = [[[GTMLargeTypeWindow alloc] initWithImage:nil] autorelease];
STAssertNil(window, nil);
-
- window = [[[GTMLargeTypeWindow alloc]
- initWithString:kMediumTextBlock] autorelease];
+}
+
+- (void)testLargeTypeWindowMediumText {
+ GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc]
+ initWithString:kMediumTextBlock] autorelease];
STAssertNotNil(window, nil);
STAssertTrue([window canBecomeKeyWindow], nil);
[window makeKeyAndOrderFront:nil];
@@ -94,52 +118,80 @@ NSString *const kMediumTextBlock = @"For the Snark was a Boojum, you see.";
GTMAssertObjectStateEqualToStateNamed(window,
@"GTMLargeTypeWindowMediumTextTest",
nil);
- [window copy:nil];
- NSPasteboard *pb = [NSPasteboard generalPasteboard];
- NSString *pbString = [pb stringForType:NSStringPboardType];
- STAssertEqualObjects(pbString, kMediumTextBlock, nil);
+ if ([self shouldDoAnimateCopy]) {
+ [window copy:nil];
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+ NSString *pbString = [pb stringForType:NSStringPboardType];
+ STAssertEqualObjects(pbString, kMediumTextBlock, nil);
+ }
[window keyDown:nil];
-
- window = [[[GTMLargeTypeWindow alloc] initWithString:@"Short"] autorelease];
+}
+
+- (void)testLargeTypeWindowShortText {
+ GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc]
+ initWithString:kShortTextBlock] autorelease];
STAssertNotNil(window, nil);
STAssertTrue([window canBecomeKeyWindow], nil);
[window makeKeyAndOrderFront:nil];
- endDate = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime];
+ NSDate *endDate
+ = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime];
[[NSRunLoop currentRunLoop] runUntilDate:endDate];
GTMAssertObjectStateEqualToStateNamed(window,
@"GTMLargeTypeWindowShortTextTest",
nil);
- [window copy:nil];
- pbString = [pb stringForType:NSStringPboardType];
- STAssertEqualObjects(pbString, @"Short", nil);
+ if ([self shouldDoAnimateCopy]) {
+ [window copy:nil];
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+ NSString *pbString = [pb stringForType:NSStringPboardType];
+ STAssertEqualObjects(pbString, kShortTextBlock, nil);
+ }
[window resignKeyWindow];
+}
- window = [[[GTMLargeTypeWindow alloc]
- initWithString:kLongTextBlock] autorelease];
+- (void)testLargeTypeWindowLongText {
+ GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc]
+ initWithString:kLongTextBlock] autorelease];
STAssertNotNil(window, nil);
[window orderFront:nil];
- endDate = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime];
+ NSDate *endDate
+ = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime];
[[NSRunLoop currentRunLoop] runUntilDate:endDate];
// Can't do state for long text as it will wrap differently on different
// sized screens.
GTMAssertObjectStateEqualToStateNamed(window,
@"GTMLargeTypeWindowLongTextTest",
nil);
+ if ([self shouldDoAnimateCopy]) {
+ [window copy:nil];
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+ NSString *pbString = [pb stringForType:NSStringPboardType];
+ STAssertEqualObjects(pbString, kLongTextBlock, nil);
+ }
[window keyDown:nil];
-
+}
+
+- (void)testLargeTypeWindowImageText {
NSImage *image = [NSApp applicationIconImage];
- window = [[[GTMLargeTypeWindow alloc] initWithImage:image] autorelease];
+ GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc]
+ initWithImage:image] autorelease];
STAssertNotNil(window, nil);
[window makeKeyAndOrderFront:nil];
- endDate = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime];
+ NSDate *endDate
+ = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime];
[[NSRunLoop currentRunLoop] runUntilDate:endDate];
GTMAssertObjectStateEqualToStateNamed(window,
@"GTMLargeTypeWindowImageTest",
nil);
- [window copy:nil];
- // Pasteboard should not change for an image
- pbString = [pb stringForType:NSStringPboardType];
- STAssertEqualObjects(pbString, @"Short", nil);
+ NSString *testString = @"TestString";
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+ [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self];
+ [pb setString:testString forType:NSStringPboardType];
+ if ([self shouldDoAnimateCopy]) {
+ [window copy:nil];
+ // Pasteboard should not change for an image
+ NSString *pbString = [pb stringForType:NSStringPboardType];
+ STAssertEqualObjects(pbString, testString, nil);
+ }
[window resignKeyWindow];
}
diff --git a/AppKit/GTMLinearRGBShadingTest.m b/AppKit/GTMLinearRGBShadingTest.m
index cb65572..d70b878 100644
--- a/AppKit/GTMLinearRGBShadingTest.m
+++ b/AppKit/GTMLinearRGBShadingTest.m
@@ -69,6 +69,24 @@
STAssertEqualsWithAccuracy(theColor[2], newValue, 0.001, nil);
STAssertEqualsWithAccuracy(theColor[3], newValue, 0.001, nil);
}
+ // Create a shading with 1 color to test that special handling
+ NSColor *purple = [NSColor purpleColor];
+ NSColor *singleColor[1] = { purple };
+ CGFloat singlePosition[1] = { 0.5 };
+ theShading =
+ [GTMLinearRGBShading shadingWithColors:singleColor
+ fromSpaceNamed:NSCalibratedRGBColorSpace
+ atPositions:singlePosition
+ count:1];
+ // test over a range to make sure we always get the same color
+ for (NSUInteger i = 0; i < kColorCount; i++) {
+ CGFloat newValue = kColorIncrement * i;
+ CGFloat *theColor = (CGFloat*)[theShading valueAtPosition:newValue];
+ STAssertEqualsWithAccuracy(theColor[0], [purple redComponent], 0.001, nil);
+ STAssertEqualsWithAccuracy(theColor[1], [purple greenComponent], 0.001, nil);
+ STAssertEqualsWithAccuracy(theColor[2], [purple blueComponent], 0.001, nil);
+ STAssertEqualsWithAccuracy(theColor[3], [purple alphaComponent], 0.001, nil);
+ }
}
- (void)testShadeFunction {
@@ -83,6 +101,7 @@
}
- (void)testColorSpace {
+ // Calibrated RGB
GTMLinearRGBShading *theShading =
[GTMLinearRGBShading shadingWithColors:nil
fromSpaceNamed:NSCalibratedRGBColorSpace
@@ -91,5 +110,23 @@
CGColorSpaceRef theColorSpace = [theShading colorSpace];
STAssertNotNULL(theColorSpace, nil);
STAssertEquals(CFGetTypeID(theColorSpace), CGColorSpaceGetTypeID(), nil);
+
+ // Device RGB
+ theShading =
+ [GTMLinearRGBShading shadingWithColors:nil
+ fromSpaceNamed:NSDeviceRGBColorSpace
+ atPositions:nil
+ count:0];
+ theColorSpace = [theShading colorSpace];
+ STAssertNotNULL(theColorSpace, nil);
+ STAssertEquals(CFGetTypeID(theColorSpace), CGColorSpaceGetTypeID(), nil);
+
+ // Device CMYK (not supported)
+ theShading =
+ [GTMLinearRGBShading shadingWithColors:nil
+ fromSpaceNamed:NSDeviceCMYKColorSpace
+ atPositions:nil
+ count:0];
+ STAssertNULL(theShading, nil);
}
@end
diff --git a/AppKit/GTMLoginItems.m b/AppKit/GTMLoginItems.m
index 61a2120..1e59e70 100644
--- a/AppKit/GTMLoginItems.m
+++ b/AppKit/GTMLoginItems.m
@@ -57,22 +57,28 @@ NSString * const kGTMLoginItemsHiddenKey = @"Hide";
+ (BOOL)compileAndRunScript:(NSString *)script
withError:(NSError **)errorInfo {
if ([script length] == 0) {
+ // COV_NF_START - no real way to test this
if (errorInfo)
*errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-90 userInfo:nil];
return NO;
+ // COV_NF_END
}
NSAppleScript *query = [[[NSAppleScript alloc] initWithSource:script] autorelease];
NSDictionary *errDict = nil;
if ( ![query compileAndReturnError:&errDict]) {
+ // COV_NF_START - no real way to test this
if (errorInfo)
*errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-91 userInfo:errDict];
return NO;
+ // COV_NF_END
}
NSAppleEventDescriptor *scriptResult = [query executeAndReturnError:&errDict];
if (!scriptResult) {
+ // COV_NF_START - no real way to test this
if (*errorInfo)
*errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-92 userInfo:errDict];
return NO;
+ // COV_NF_END
}
// we don't process the result
return YES;
@@ -90,19 +96,23 @@ NSString * const kGTMLoginItemsHiddenKey = @"Hide";
NSString *querySource = @"tell application \"System Events\" to get properties of login items";
query = [[NSAppleScript alloc] initWithSource:querySource];
if ( ![query compileAndReturnError:&errDict]) {
+ // COV_NF_START - no real way to test this
if (errorInfo)
*errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-1 userInfo:errDict];
[query release];
query = nil;
return nil;
+ // COV_NF_END
}
}
// run the script
NSAppleEventDescriptor *scriptResult = [query executeAndReturnError:&errDict];
if (!scriptResult) {
+ // COV_NF_START - no real way to test this
if (*errorInfo)
*errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-2 userInfo:errDict];
return nil;
+ // COV_NF_END
}
// build our results
NSMutableArray *result = [NSMutableArray array];
diff --git a/AppKit/GTMLoginItemsTest.m b/AppKit/GTMLoginItemsTest.m
index ec08a85..980f772 100644
--- a/AppKit/GTMLoginItemsTest.m
+++ b/AppKit/GTMLoginItemsTest.m
@@ -23,14 +23,12 @@
// we don't really run this test because if someone had it in some automated
// tests, then if something did fail, it could leave things in the login items
// on the computer which could be a nasty surprise.
-#define TESTS_ENABLED 0
+#define MODIFICATION_TESTS_ENABLED 0
@interface GTMLoginItemsTest : GTMTestCase
@end
-#if TESTS_ENABLED
-
static BOOL ItemsListHasPath(NSArray *items, NSString *path) {
NSDictionary *item = nil;
NSEnumerator *itemsEnum = [items objectEnumerator];
@@ -43,14 +41,42 @@ static BOOL ItemsListHasPath(NSArray *items, NSString *path) {
return NO;
}
-#endif // TESTS_ENABLED
-
@implementation GTMLoginItemsTest
-- (void)testGTMLoginItems {
+- (void)testNoModification {
-#if TESTS_ENABLED
+ NSError *error = nil;
+ NSString *bogusAppPath = @"/Applications/AppThatDoesNotExist.app";
+ NSString *bogusAppName = @"AppThatDoesNotExist";
+
+ // fetch the starting values
+ NSArray *initialItems = [GTMLoginItems loginItems:&error];
+ STAssertNotNil(initialItems, @"shouldn't be nil (%@)", error);
+ STAssertFalse(ItemsListHasPath(initialItems, bogusAppPath),
+ @"bogusApp shouldn't be in list to start for test (%@)", initialItems);
+
+ // check by path
+ STAssertFalse([GTMLoginItems pathInLoginItems:bogusAppPath], nil);
+
+ // check by name
+ STAssertFalse([GTMLoginItems itemWithNameInLoginItems:bogusAppName], nil);
+
+ // remove it by path
+ [GTMLoginItems removePathFromLoginItems:bogusAppPath];
+ NSArray *curItems = [GTMLoginItems loginItems:nil];
+ STAssertEqualObjects(initialItems, curItems, nil);
+
+ // remove it by name
+ [GTMLoginItems removeItemWithNameFromLoginItems:bogusAppName];
+ curItems = [GTMLoginItems loginItems:nil];
+ STAssertEqualObjects(initialItems, curItems, nil);
+
+}
+- (void)testModification {
+
+#if MODIFICATION_TESTS_ENABLED
+
NSError *error = nil;
NSString *textEditPath = @"/Applications/TextEdit.app";
NSString *textEditName = @"TextEdit";
@@ -79,7 +105,7 @@ static BOOL ItemsListHasPath(NSArray *items, NSString *path) {
// check by path
STAssertFalse([GTMLoginItems pathInLoginItems:textEditPath], nil);
-
+
// check by name
STAssertFalse([GTMLoginItems itemWithNameInLoginItems:textEditName], nil);
@@ -105,8 +131,8 @@ static BOOL ItemsListHasPath(NSArray *items, NSString *path) {
// check by name
STAssertFalse([GTMLoginItems itemWithNameInLoginItems:textEditName], nil);
-#endif // TESTS_ENABLED
-
+#endif // MODIFICATION_TESTS_ENABLED
+
}
@end
diff --git a/AppKit/GTMNSBezierPath+CGPath.m b/AppKit/GTMNSBezierPath+CGPath.m
index 3bc6de9..656a139 100644
--- a/AppKit/GTMNSBezierPath+CGPath.m
+++ b/AppKit/GTMNSBezierPath+CGPath.m
@@ -58,9 +58,9 @@
case NSClosePathBezierPathElement:
CGPathCloseSubpath(thePath);
break;
- default:
+ default: // COV_NF_START
_GTMDevLog(@"Unknown element at [NSBezierPath (GTMBezierPathCGPathAdditions) cgPath]");
- break;
+ break; // COV_NF_END
};
}
return thePath;
diff --git a/AppKit/GTMNSBezierPath+RoundRectTest.m b/AppKit/GTMNSBezierPath+RoundRectTest.m
index ad64fd4..5bdf3a3 100644
--- a/AppKit/GTMNSBezierPath+RoundRectTest.m
+++ b/AppKit/GTMNSBezierPath+RoundRectTest.m
@@ -1,5 +1,5 @@
//
-// NSBezierPath+RoundRectTest.m
+// GTMNSBezierPath+RoundRectTest.m
//
// Copyright 2006-2008 Google Inc.
//
@@ -28,7 +28,7 @@
@implementation GTMNSBezierPath_RoundRectTest
- (void)testRoundRects {
- GTMAssertDrawingEqualToImageNamed(self, NSMakeSize(330, 430),
+ GTMAssertDrawingEqualToImageNamed(self, NSMakeSize(490, 430),
@"GTMNSBezierPath+RoundRectTest", nil, nil);
}
@@ -39,7 +39,8 @@
NSMakeRect(50.0, 10.0, 30.0, 30.0), //Square Test
NSMakeRect(100.0, 10.0, 1.0, 2.0), //Small Test
NSMakeRect(120.0, 10.0, 15.0, 20.0), //Medium Test
- NSMakeRect(140.0, 10.0, 150.0, 30.0) //Large Test
+ NSMakeRect(140.0, 10.0, 150.0, 30.0), //Large Test
+ NSMakeRect(300.0, 10.0, 150.0, 30.0) //Large Test 2 (for different radius)
};
const NSUInteger theRectCount = sizeof(theRects) / sizeof(NSRect);
@@ -50,8 +51,9 @@
for (i = 0; i < theLineWidthCount; ++i) {
for (j = 0; j < theRectCount; ++j) {
+ CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 20.0 : 0.0 );
NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j]
- cornerRadius:20.0];
+ cornerRadius:cornerRadius];
[roundRect setLineWidth: theLineWidths[i]];
[roundRect stroke];
CGFloat newWidth = 35.0;
@@ -71,8 +73,9 @@
for (i = 0; i < theColorCount; ++i) {
for (j = 0; j < theRectCount; ++j) {
+ CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 10.0 : 0.0 );
NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j]
- cornerRadius:10.0];
+ cornerRadius:cornerRadius];
[theColors[i] setFill];
[roundRect fill];
theRects[j].origin.y += 35.0;
@@ -85,8 +88,9 @@
for (i = 0; i < theFlatnessCount; i++) {
for (j = 0; j < theRectCount; ++j) {
+ CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 6.0 : 0.0 );
NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j]
- cornerRadius:6.0];
+ cornerRadius:cornerRadius];
[roundRect setFlatness:theFlatness[i]];
[roundRect stroke];
theRects[j].origin.y += 35.0;
diff --git a/AppKit/GTMNSBezierPath+ShadingTest.m b/AppKit/GTMNSBezierPath+ShadingTest.m
index 5634cf3..a9dfbef 100644
--- a/AppKit/GTMNSBezierPath+ShadingTest.m
+++ b/AppKit/GTMNSBezierPath+ShadingTest.m
@@ -31,7 +31,7 @@
- (void)testShadings {
GTMAssertDrawingEqualToImageNamed(self,
- NSMakeSize(200, 200),
+ NSMakeSize(310, 410),
@"GTMNSBezierPath+ShadingTest", nil, nil);
}
@@ -50,7 +50,7 @@
count:sizeof(theFloatArray)/sizeof(CGFloat)];
NSBezierPath *shadedPath;
- // axialStrokeRect test
+ // axial stroke rect - diagonal fill
NSRect axialStrokeRect = NSMakeRect(10.0f, 10.0f, 90.0f, 90.0f);
shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect];
[shadedPath setLineWidth: 10.0f];
@@ -59,8 +59,28 @@
NSPoint endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width - 20.0f,
axialStrokeRect.origin.y + axialStrokeRect.size.height - 20.0f);
[shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading];
+
+ // axial stroke rect - v line fill
+ axialStrokeRect = NSMakeRect(110.0f, 10.0f, 90.0f, 90.0f);
+ shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect];
+ [shadedPath setLineWidth: 10.0f];
+ startPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width / 2.0f,
+ axialStrokeRect.origin.y + 20.0f);
+ endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width / 2.0f,
+ axialStrokeRect.origin.y + axialStrokeRect.size.height - 20.0f);
+ [shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading];
+
+ // axial stroke rect - h line fill
+ axialStrokeRect = NSMakeRect(210.0f, 10.0f, 90.0f, 90.0f);
+ shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect];
+ [shadedPath setLineWidth: 10.0f];
+ startPoint = NSMakePoint(axialStrokeRect.origin.x + 20.0f,
+ axialStrokeRect.origin.y + axialStrokeRect.size.height / 2.0f);
+ endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width - 20.0f,
+ axialStrokeRect.origin.y + axialStrokeRect.size.height / 2.0f);
+ [shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading];
- // axial fill
+ // axial fill rect - diagonal fill
NSRect axialFillRect = NSMakeRect(10.0f, 110.0f, 90.0f, 90.0f);
shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect];
startPoint = NSMakePoint(axialFillRect.origin.x + 20.0f,
@@ -69,8 +89,26 @@
axialFillRect.origin.y + axialFillRect.size.height - 20.0f);
[shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading];
- // radial stroke
- NSRect radialStrokeRect = NSMakeRect(110.0f, 110.0f, 90.0f, 90.0f);
+ // axial fill rect - v line fill
+ axialFillRect = NSMakeRect(110.0f, 110.0f, 90.0f, 90.0f);
+ shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect];
+ startPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width / 2.0f,
+ axialFillRect.origin.y + 20.0f);
+ endPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width / 2.0f,
+ axialFillRect.origin.y + axialFillRect.size.height - 20.0f);
+ [shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading];
+
+ // axial fill rect - h line fill
+ axialFillRect = NSMakeRect(210.0f, 110.0f, 90.0f, 90.0f);
+ shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect];
+ startPoint = NSMakePoint(axialFillRect.origin.x + 20.0f,
+ axialFillRect.origin.y + axialFillRect.size.height / 2.0f);
+ endPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width - 20.0f,
+ axialFillRect.origin.y + axialFillRect.size.height / 2.0f);
+ [shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading];
+
+ // radial stroke rect - diagonal fill
+ NSRect radialStrokeRect = NSMakeRect(10.0f, 210.0f, 90.0f, 90.0f);
shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect];
startPoint = NSMakePoint(radialStrokeRect.origin.x + 20.0f,
radialStrokeRect.origin.y + 20.0f);
@@ -80,8 +118,30 @@
to:endPoint toRadius:20.0f
extendingStart:YES extendingEnd:YES shading:shading];
- // radial fill
- NSRect radialFillRect = NSMakeRect(110.0f, 10.0f, 90.0f, 90.0f);
+ // radial stroke rect - v line fill
+ radialStrokeRect = NSMakeRect(110.0f, 210.0f, 90.0f, 90.0f);
+ shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect];
+ startPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width / 2.0f,
+ radialStrokeRect.origin.y + 20.0f);
+ endPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width / 2.0f,
+ radialStrokeRect.origin.y + radialStrokeRect.size.height - 20.0f);
+ [shadedPath gtm_strokeRadiallyFrom:startPoint fromRadius:60.0f
+ to:endPoint toRadius:20.0f
+ extendingStart:YES extendingEnd:YES shading:shading];
+
+ // radial stroke rect - h line fill
+ radialStrokeRect = NSMakeRect(210.0f, 210.0f, 90.0f, 90.0f);
+ shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect];
+ startPoint = NSMakePoint(radialStrokeRect.origin.x + 20.0f,
+ radialStrokeRect.origin.y + radialStrokeRect.size.height / 2.0f);
+ endPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width - 20.0f,
+ radialStrokeRect.origin.y + radialStrokeRect.size.height / 2.0f);
+ [shadedPath gtm_strokeRadiallyFrom:startPoint fromRadius:60.0f
+ to:endPoint toRadius:20.0f
+ extendingStart:YES extendingEnd:YES shading:shading];
+
+ // radial fill rect - diagonal fill
+ NSRect radialFillRect = NSMakeRect(10.0f, 310.0f, 90.0f, 90.0f);
shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect];
startPoint = NSMakePoint(radialFillRect.origin.x + 20.0f,
radialFillRect.origin.y + 20.0f);
@@ -90,6 +150,28 @@
[shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f
to:endPoint toRadius:20.0f
extendingStart:YES extendingEnd:YES shading:shading];
+
+ // radial fill rect - v line fill
+ radialFillRect = NSMakeRect(110.0f, 310.0f, 90.0f, 90.0f);
+ shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect];
+ startPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width / 2.0f,
+ radialFillRect.origin.y + 20.0f);
+ endPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width / 2.0f,
+ radialFillRect.origin.y + radialFillRect.size.height - 20.0f);
+ [shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f
+ to:endPoint toRadius:20.0f
+ extendingStart:YES extendingEnd:YES shading:shading];
+
+ // radial fill rect - h line fill
+ radialFillRect = NSMakeRect(210.0f, 310.0f, 90.0f, 90.0f);
+ shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect];
+ startPoint = NSMakePoint(radialFillRect.origin.x + 20.0f,
+ radialFillRect.origin.y + radialFillRect.size.height / 2.0f);
+ endPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width - 20.0f,
+ radialFillRect.origin.y + radialFillRect.size.height / 2.0f);
+ [shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f
+ to:endPoint toRadius:20.0f
+ extendingStart:YES extendingEnd:YES shading:shading];
}
@end
diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff
index a4df8f8..ef22b6b 100644
--- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff
+++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff
Binary files differ
diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff
index c41ab04..b165acf 100644
--- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff
+++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff
Binary files differ
diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff
index a4df8f8..ef22b6b 100644
--- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff
+++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff
Binary files differ
diff --git a/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff b/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff
index 040cb0d..b44b5bf 100644
--- a/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff
+++ b/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff
Binary files differ