aboutsummaryrefslogtreecommitdiff
path: root/AppKit
diff options
context:
space:
mode:
authorGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2010-03-19 21:33:33 +0000
committerGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2010-03-19 21:33:33 +0000
commitb52866b053b49238bb536324e8a1a1fce859e49e (patch)
tree5e08e371ca00c6c312dea2e8f3f38ee1ba463f77 /AppKit
parent959bac16835a8676f71bf440cea8344a32d6c498 (diff)
[Author: dmaclach]
This may help clean up some code in chrome, and make doing animations on the mac easier in general. Not really sure how to unit test effectively, but I'll try and come up with something this evening. Hopefully you will get a chance to look at it, so Andy can use it for his current CL in flight http://codereview.chromium.org/1118004. R=thomasvl DELTA=908 (908 added, 0 deleted, 0 changed)
Diffstat (limited to 'AppKit')
-rw-r--r--AppKit/GTMNSAnimatablePropertyContainer.h49
-rw-r--r--AppKit/GTMNSAnimatablePropertyContainer.m124
-rw-r--r--AppKit/GTMNSAnimatablePropertyContainerTest.h51
-rw-r--r--AppKit/GTMNSAnimatablePropertyContainerTest.m237
-rw-r--r--AppKit/GTMNSAnimatablePropertyContainerTest.xib426
5 files changed, 887 insertions, 0 deletions
diff --git a/AppKit/GTMNSAnimatablePropertyContainer.h b/AppKit/GTMNSAnimatablePropertyContainer.h
new file mode 100644
index 0000000..c98cabe
--- /dev/null
+++ b/AppKit/GTMNSAnimatablePropertyContainer.h
@@ -0,0 +1,49 @@
+//
+// GTMNSAnimatablePropertyContainer.h
+//
+// Copyright (c) 2010 Google Inc. All rights reserved.
+//
+// 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.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "GTMDefines.h"
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+
+// There is a bug in 10.5 where you cannot stop an animation on a
+// NSAnimatablePropertyContainer by just setting it's duration to 0.0.
+// The work around is rather complex requiring you to NULL out animation
+// dictionary entries temporarily (see the code for details).
+// These categories are to make stopping animations simpler.
+// When you want to stop an animation, you just call it like you would
+// an animator.
+//
+// [[myWindow gtm_animatorStopper] setAlphaValue:0.0];
+//
+// This will stop any current animations that are going on, and will immediately
+// set the alpha value of the window to 0.
+// If there is no animation, it will still set the alpha value to 0.0 for you.
+@interface NSView (GTMNSAnimatablePropertyContainer)
+
+- (id)gtm_animatorStopper;
+
+@end
+
+@interface NSWindow (GTMNSAnimatablePropertyContainer)
+
+- (id)gtm_animatorStopper;
+
+@end
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
diff --git a/AppKit/GTMNSAnimatablePropertyContainer.m b/AppKit/GTMNSAnimatablePropertyContainer.m
new file mode 100644
index 0000000..a47ff65
--- /dev/null
+++ b/AppKit/GTMNSAnimatablePropertyContainer.m
@@ -0,0 +1,124 @@
+//
+// GTMNSAnimatablePropertyContainer.m
+//
+// Copyright (c) 2010 Google Inc. All rights reserved.
+//
+// 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.
+//
+
+#import "GTMNSAnimatablePropertyContainer.h"
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+
+@interface GTMAnimatorStopper : NSObject {
+ @private
+ NSObject<NSAnimatablePropertyContainer> *container_;
+}
+@end
+
+@implementation GTMAnimatorStopper
+- (id)initWithAnimatablePropertyContainer:(NSObject<NSAnimatablePropertyContainer>*) container {
+ if ((self = [super init])) {
+ container_ = [container retain];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [container_ release];
+ [super dealloc];
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
+ return [container_ methodSignatureForSelector:aSelector];
+}
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation {
+ SEL selector = [anInvocation selector];
+ NSString *selectorName = NSStringFromSelector(selector);
+
+ // NSWindow animator handles setFrame:display: which is an odd case
+ // for animator. All other methods take just a key value, so we convert
+ // this to it's equivalent key value.
+ if ([selectorName isEqual:@"setFrame:display:"]) {
+ selectorName = @"setFrame:";
+ }
+
+ // Check to make sure our selector is valid (starts with set and has a
+ // single : at the end.
+ NSRange colonRange = [selectorName rangeOfString:@":"];
+ NSUInteger selectorLength = [selectorName length];
+ if ([selectorName hasPrefix:@"set"]
+ && colonRange.location == selectorLength - 1
+ && selectorLength > 4) {
+ // transform our selector into a keyValue by removing the set
+ // and the colon and converting the first char down to lowercase.
+ NSString *keyValue = [selectorName substringFromIndex:3];
+ NSString *firstChar = [[keyValue substringToIndex:1] lowercaseString];
+ NSRange rest = NSMakeRange(1, [keyValue length] - 2);
+ NSString *restOfKey = [keyValue substringWithRange:rest];
+ keyValue = [firstChar stringByAppendingString:restOfKey];
+
+ // Save a copy of our old animations.
+ NSDictionary *oldAnimations
+ = [[[container_ animations] copy] autorelease];
+
+ // For frame the animator doesn't actually animate the rect but gets
+ // animators for the size and the origin independently. In case this changes
+ // in the future (similar to bounds), we will stop the animations for the
+ // frame as well as the frameSize and frameOrigin.
+ NSDictionary *animations = nil;
+ NSNull *null = [NSNull null];
+ if ([keyValue isEqual:@"frame"]) {
+ animations = [NSDictionary dictionaryWithObjectsAndKeys:
+ null, @"frame",
+ null, @"frameSize",
+ null, @"frameOrigin", nil];
+ } else {
+ animations = [NSDictionary dictionaryWithObject:null forKey:keyValue];
+ }
+
+ // Set our animations to NULL which will force them to stop.
+ [container_ setAnimations:animations];
+ // Call our original invocation on our animator.
+ [anInvocation setTarget:[container_ animator]];
+ [anInvocation invoke];
+
+ // Reset the animations.
+ [container_ setAnimations:oldAnimations];
+ } else {
+ [self doesNotRecognizeSelector:selector];
+ }
+}
+
+@end
+
+@implementation NSView(GTMNSAnimatablePropertyContainer)
+
+- (id)gtm_animatorStopper {
+ return [[[GTMAnimatorStopper alloc] initWithAnimatablePropertyContainer:self]
+ autorelease];
+}
+
+@end
+
+@implementation NSWindow(GTMNSAnimatablePropertyContainer)
+
+- (id)gtm_animatorStopper {
+ return [[[GTMAnimatorStopper alloc] initWithAnimatablePropertyContainer:self]
+ autorelease];
+}
+
+@end
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
diff --git a/AppKit/GTMNSAnimatablePropertyContainerTest.h b/AppKit/GTMNSAnimatablePropertyContainerTest.h
new file mode 100644
index 0000000..ebfd323
--- /dev/null
+++ b/AppKit/GTMNSAnimatablePropertyContainerTest.h
@@ -0,0 +1,51 @@
+//
+// GTMNSAnimatablePropertyContainerTest.h
+//
+// Copyright (c) 2010 Google Inc. All rights reserved.
+//
+// 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.
+//
+
+#import "GTMSenTestCase.h"
+#import <AppKit/AppKit.h>
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+
+@interface GTMNSAnimatablePropertyContainerWindow : NSWindow
+@end
+
+@interface GTMNSAnimatablePropertyContainerWindowBox : NSBox
+
+- (void)set:(NSInteger)value;
+
+@end
+
+@interface GTMNSAnimatablePropertyContainerWindowController : NSWindowController {
+ @private
+ IBOutlet NSBox *nonLayerBox_;
+ IBOutlet NSBox *layerBox_;
+}
+
+@property (readonly, retain, nonatomic) NSBox *nonLayerBox;
+@property (readonly, retain, nonatomic) NSBox *layerBox;
+
+@end
+
+@interface GTMNSAnimatablePropertyContainerTest : GTMTestCase {
+ @private
+ GTMNSAnimatablePropertyContainerWindowController *windowController_;
+ BOOL timerCalled_;
+}
+@end
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
diff --git a/AppKit/GTMNSAnimatablePropertyContainerTest.m b/AppKit/GTMNSAnimatablePropertyContainerTest.m
new file mode 100644
index 0000000..0ce89d2
--- /dev/null
+++ b/AppKit/GTMNSAnimatablePropertyContainerTest.m
@@ -0,0 +1,237 @@
+//
+// GTMNSAnimatablePropertyContainerTest.m
+//
+// Copyright (c) 2010 Google Inc. All rights reserved.
+//
+// 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.
+//
+
+#import "GTMNSAnimatablePropertyContainerTest.h"
+#import "GTMNSAnimatablePropertyContainer.h"
+#import "GTMTypeCasting.h"
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+
+@implementation GTMNSAnimatablePropertyContainerWindow
+
+#if 0
+// Some useful debugging code. Enabled to track animation keys.
+- (id)animationForKey:(NSString *)key {
+ id value = [super animationForKey:key];
+ NSLog(@"Value: %@ Key: %@", value, key);
+ return value;
+}
+#endif
+
+@end
+
+@implementation GTMNSAnimatablePropertyContainerWindowBox
+
+#if 0
+// Some useful debugging code. Enabled to track animation keys.
+- (id)animationForKey:(NSString *)key {
+ id value = [super animationForKey:key];
+ NSLog(@"Value: %@ Key: %@", value, key);
+ return value;
+}
+#endif
+
+- (void)set:(NSInteger)value {
+ value = value;
+}
+
+@end
+
+@implementation GTMNSAnimatablePropertyContainerWindowController
+
+@synthesize nonLayerBox = nonLayerBox_;
+@synthesize layerBox = layerBox_;
+
+- (id)init {
+ return [super initWithWindowNibName:@"GTMNSAnimatablePropertyContainerTest"];
+}
+
+- (void)windowWillClose:(NSNotification *)notification {
+ if (![[notification object] isEqual:[self window]]) {
+ [[NSException exceptionWithName:SenTestFailureException
+ reason:@"Bad window in windowWillClose"
+ userInfo:nil] raise];
+ }
+ [self autorelease];
+}
+
+@end
+
+@implementation GTMNSAnimatablePropertyContainerTest
+
+- (void)setUp {
+ windowController_
+ = [[GTMNSAnimatablePropertyContainerWindowController alloc] init];
+ STAssertNotNil(windowController_, nil);
+ NSWindow *window = [windowController_ window];
+ STAssertNotNil(window, nil);
+}
+
+- (void)tearDown {
+ [windowController_ close];
+ windowController_ = nil;
+}
+
+- (void)windowAlphaValueStopper:(NSTimer *)timer {
+ NSWindow *window = GTM_DYNAMIC_CAST(NSWindow, [timer userInfo]);
+ timerCalled_ = YES;
+ [[window gtm_animatorStopper] setAlphaValue:0.25];
+ STAssertEquals([window alphaValue], (CGFloat)0.25, nil);
+}
+
+- (void)windowFrameStopper:(NSTimer *)timer {
+ NSWindow *window = GTM_DYNAMIC_CAST(NSWindow, [timer userInfo]);
+ timerCalled_ = YES;
+ [[window gtm_animatorStopper] setFrame:NSMakeRect(300, 300, 150, 150)
+ display:YES];
+ STAssertEquals([window frame], NSMakeRect(300, 300, 150, 150), nil);
+}
+
+- (void)nonLayerFrameStopper:(NSTimer *)timer {
+ NSView *view = GTM_DYNAMIC_CAST(NSView, [timer userInfo]);
+ timerCalled_ = YES;
+ [[view gtm_animatorStopper] setFrame:NSMakeRect(200, 200, 200, 200)];
+ STAssertEquals([view frame], NSMakeRect(200, 200, 200, 200), nil);
+}
+
+- (void)layerFrameStopper:(NSTimer *)timer {
+ NSView *view = GTM_DYNAMIC_CAST(NSView, [timer userInfo]);
+ timerCalled_ = YES;
+ [[view gtm_animatorStopper] setFrame:NSMakeRect(200, 200, 200, 200)];
+ STAssertEquals([view frame], NSMakeRect(200, 200, 200, 200), nil);
+}
+
+- (void)testWindowAnimations {
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+
+ // Test Alpha
+ NSWindow *window = [windowController_ window];
+ [window setAlphaValue:1.0];
+ timerCalled_ = NO;
+ [NSAnimationContext beginGrouping];
+ NSAnimationContext *currentContext = [NSAnimationContext currentContext];
+ [currentContext setDuration:2];
+ [[window animator] setAlphaValue:0.5];
+ [NSAnimationContext endGrouping];
+ [NSTimer scheduledTimerWithTimeInterval:0.1
+ target:self
+ selector:@selector(windowAlphaValueStopper:)
+ userInfo:window
+ repeats:NO];
+ [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
+ STAssertTrue(timerCalled_, nil);
+ STAssertEquals([window alphaValue], (CGFloat)0.25, nil);
+
+ // Test Frame
+ [window setFrame:NSMakeRect(100, 100, 100, 100) display:YES];
+ timerCalled_ = NO;
+ [NSAnimationContext beginGrouping];
+ currentContext = [NSAnimationContext currentContext];
+ [currentContext setDuration:2];
+ [[window animator] setFrame:NSMakeRect(200, 200, 200, 200) display:YES];
+ [NSAnimationContext endGrouping];
+ [NSTimer scheduledTimerWithTimeInterval:0.1
+ target:self
+ selector:@selector(windowFrameStopper:)
+ userInfo:window
+ repeats:NO];
+ [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
+ STAssertTrue(timerCalled_, nil);
+ STAssertEquals([window frame], NSMakeRect(300, 300, 150, 150), nil);
+
+ // Test non-animation value
+ [window setTitle:@"Foo"];
+ [[window gtm_animatorStopper] setTitle:@"Bar"];
+ STAssertEquals([window title], @"Bar", nil);
+
+ // Test bad selector
+ STAssertThrows([[window gtm_animatorStopper] testWindowAnimations], nil);
+}
+
+- (void)testNonLayerViewAnimations {
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+
+ NSBox *nonLayerBox = [windowController_ nonLayerBox];
+ STAssertNotNil(nonLayerBox, nil);
+
+ // Test frame
+ [nonLayerBox setFrame:NSMakeRect(50, 50, 50, 50)];
+ timerCalled_ = NO;
+ [NSAnimationContext beginGrouping];
+ NSAnimationContext *currentContext = [NSAnimationContext currentContext];
+ [currentContext setDuration:2];
+ [[nonLayerBox animator] setFrame:NSMakeRect(100, 100, 100, 100)];
+ [NSAnimationContext endGrouping];
+ [NSTimer scheduledTimerWithTimeInterval:0.1
+ target:self
+ selector:@selector(nonLayerFrameStopper:)
+ userInfo:nonLayerBox
+ repeats:NO];
+ [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
+ STAssertTrue(timerCalled_, nil);
+ STAssertEquals([nonLayerBox frame], NSMakeRect(200, 200, 200, 200), nil);
+
+ // Test non-animation value
+ [nonLayerBox setToolTip:@"Foo"];
+ [[nonLayerBox gtm_animatorStopper] setToolTip:@"Bar"];
+ STAssertEquals([nonLayerBox toolTip], @"Bar", nil);
+
+ // Test bad selector
+ STAssertThrows([[nonLayerBox gtm_animatorStopper] testNonLayerViewAnimations],
+ nil);
+}
+
+- (void)testLayerViewAnimations {
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+
+ NSBox *layerBox = [windowController_ layerBox];
+ STAssertNotNil(layerBox, nil);
+
+ // Test frame
+ [layerBox setFrame:NSMakeRect(50, 50, 50, 50)];
+ timerCalled_ = NO;
+ [NSAnimationContext beginGrouping];
+ NSAnimationContext *currentContext = [NSAnimationContext currentContext];
+ [currentContext setDuration:2];
+ [[layerBox animator] setFrame:NSMakeRect(100, 100, 100, 100)];
+ [NSAnimationContext endGrouping];
+ [NSTimer scheduledTimerWithTimeInterval:0.1
+ target:self
+ selector:@selector(layerFrameStopper:)
+ userInfo:layerBox
+ repeats:NO];
+ [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
+ STAssertTrue(timerCalled_, nil);
+ STAssertEquals([layerBox frame], NSMakeRect(200, 200, 200, 200), nil);
+
+ // Test non-animation value
+ [layerBox setToolTip:@"Foo"];
+ [[layerBox gtm_animatorStopper] setToolTip:@"Bar"];
+ STAssertEquals([layerBox toolTip], @"Bar", nil);
+
+ // Test bad selector
+ STAssertThrows([[layerBox gtm_animatorStopper] testLayerViewAnimations],
+ nil);
+
+ // Test Short Selector
+ STAssertThrows([[layerBox gtm_animatorStopper] set:1], nil);
+}
+
+@end
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
diff --git a/AppKit/GTMNSAnimatablePropertyContainerTest.xib b/AppKit/GTMNSAnimatablePropertyContainerTest.xib
new file mode 100644
index 0000000..3065ab5
--- /dev/null
+++ b/AppKit/GTMNSAnimatablePropertyContainerTest.xib
@@ -0,0 +1,426 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">9L31a</string>
+ <string key="IBDocument.InterfaceBuilderVersion">680</string>
+ <string key="IBDocument.AppKitVersion">949.54</string>
+ <string key="IBDocument.HIToolboxVersion">353.00</string>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="2"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilderKit</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="1001">
+ <string key="NSClassName">GTMNSAnimatablePropertyContainerWindowController</string>
+ </object>
+ <object class="NSCustomObject" id="1003">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1004">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSWindowTemplate" id="1005">
+ <int key="NSWindowStyleMask">15</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{196, 240}, {480, 270}}</string>
+ <int key="NSWTFlags">536870912</int>
+ <string key="NSWindowTitle">Window</string>
+ <string key="NSWindowClass">GTMNSAnimatablePropertyContainerWindow</string>
+ <nil key="NSViewClass"/>
+ <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ <object class="NSView" key="NSWindowView" id="1006">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSBox" id="356378161">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">12</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSView" id="518392398">
+ <reference key="NSNextResponder" ref="356378161"/>
+ <int key="NSvFlags">256</int>
+ <string key="NSFrame">{{1, 1}, {120, 113}}</string>
+ <reference key="NSSuperview" ref="356378161"/>
+ </object>
+ </object>
+ <string key="NSFrame">{{36, 135}, {122, 115}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <string key="NSOffsets">{0, 0}</string>
+ <object class="NSTextFieldCell" key="NSTitleCell">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">0</int>
+ <string key="NSContents">NonLayerBox</string>
+ <object class="NSFont" key="NSSupport" id="26">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.100000e+01</double>
+ <int key="NSfFlags">3100</int>
+ </object>
+ <object class="NSColor" key="NSBackgroundColor" id="152657423">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textBackgroundColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes>
+ </object>
+ </object>
+ <reference key="NSContentView" ref="518392398"/>
+ <int key="NSBorderType">1</int>
+ <int key="NSBoxType">4</int>
+ <int key="NSTitlePosition">2</int>
+ <bool key="NSTransparent">NO</bool>
+ <object class="NSColor" key="NSFillColor2">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MCAwIDEAA</bytes>
+ </object>
+ </object>
+ <object class="NSBox" id="852370930">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">12</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSView" id="743292700">
+ <reference key="NSNextResponder" ref="852370930"/>
+ <int key="NSvFlags">256</int>
+ <string key="NSFrame">{{1, 1}, {120, 113}}</string>
+ <reference key="NSSuperview" ref="852370930"/>
+ </object>
+ </object>
+ <string key="NSFrame">{{238, 135}, {122, 115}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <bool key="NSViewIsLayerTreeHost">YES</bool>
+ <string key="NSOffsets">{0, 0}</string>
+ <object class="NSTextFieldCell" key="NSTitleCell">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">0</int>
+ <string key="NSContents">LayerBox</string>
+ <reference key="NSSupport" ref="26"/>
+ <reference key="NSBackgroundColor" ref="152657423"/>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes>
+ </object>
+ </object>
+ <reference key="NSContentView" ref="743292700"/>
+ <int key="NSBorderType">1</int>
+ <int key="NSBoxType">4</int>
+ <int key="NSTitlePosition">2</int>
+ <bool key="NSTransparent">NO</bool>
+ <object class="NSColor" key="NSFillColor2">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAwIDEAA</bytes>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{480, 270}</string>
+ <reference key="NSSuperview"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+ <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">nonLayerBox_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="356378161"/>
+ </object>
+ <int key="connectionID">6</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">layerBox_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="852370930"/>
+ </object>
+ <int key="connectionID">7</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1005"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">8</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">9</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <object class="NSArray" key="object" id="1002">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="1001"/>
+ <reference key="parent" ref="1002"/>
+ <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1003"/>
+ <reference key="parent" ref="1002"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1004"/>
+ <reference key="parent" ref="1002"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="1005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1006"/>
+ </object>
+ <reference key="parent" ref="1002"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="1006"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="356378161"/>
+ <reference ref="852370930"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="356378161"/>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="852370930"/>
+ <reference key="parent" ref="1006"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.IBPluginDependency</string>
+ <string>-2.IBPluginDependency</string>
+ <string>-3.IBPluginDependency</string>
+ <string>1.IBEditorWindowLastContentRect</string>
+ <string>1.IBPluginDependency</string>
+ <string>1.IBWindowTemplateEditedContentRect</string>
+ <string>1.NSWindowTemplate.visibleAtLaunch</string>
+ <string>1.WindowOrigin</string>
+ <string>1.editorWindowContentRectSynchronizationRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.CustomClassName</string>
+ <string>3.IBPluginDependency</string>
+ <string>4.CustomClassName</string>
+ <string>4.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilderKit</string>
+ <string>com.apple.InterfaceBuilderKit</string>
+ <string>{{152, 488}, {480, 270}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{152, 488}, {480, 270}}</string>
+ <integer value="1"/>
+ <string>{196, 240}</string>
+ <string>{{202, 428}, {480, 270}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>GTMNSAnimatablePropertyContainerWindowBox</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>GTMNSAnimatablePropertyContainerWindowBox</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">9</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMNSAnimatablePropertyContainerWindow</string>
+ <string key="superclassName">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="304255356">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">AppKit/GTMNSAnimatablePropertyContainerTest.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMNSAnimatablePropertyContainerWindowBox</string>
+ <string key="superclassName">NSBox</string>
+ <reference key="sourceIdentifier" ref="304255356"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMNSAnimatablePropertyContainerWindowController</string>
+ <string key="superclassName">NSWindowController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>layerBox_</string>
+ <string>nonLayerBox_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSBox</string>
+ <string>NSBox</string>
+ </object>
+ </object>
+ <reference key="sourceIdentifier" ref="304255356"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="712611361">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">UnitTesting/GTMAppKit+UnitTesting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSMenu</string>
+ <reference key="sourceIdentifier" ref="712611361"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">AppKit/GTMCarbonEvent.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">AppKit/GTMDelegatingTableColumn.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Foundation/GTMHTTPServer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Foundation/GTMNSAppleEventDescriptor+Foundation.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Foundation/GTMNSObject+KeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">UnitTesting/GTMCALayer+UnitTesting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">UnitTesting/GTMNSObject+BindingUnitTesting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">UnitTesting/GTMNSObject+UnitTesting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="774965103">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">AppKit/GTMNSAnimatablePropertyContainer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <reference key="sourceIdentifier" ref="712611361"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSWindow</string>
+ <reference key="sourceIdentifier" ref="774965103"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSWindow</string>
+ <reference key="sourceIdentifier" ref="712611361"/>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../GTM.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>