diff --git a/AppKit/CPPopover.j b/AppKit/CPPopover.j
index 3629b7603..3c7483760 100644
--- a/AppKit/CPPopover.j
+++ b/AppKit/CPPopover.j
@@ -68,7 +68,6 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
int _behavior @accessors(getter=behavior);
_CPAttachedWindow _attachedWindow;
- BOOL _needsNewAttachedWindow;
int _implementedDelegateMethods;
}
@@ -79,16 +78,15 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Initialize the CPPopover witn default values
- @returns anInitialized CPPopover
+ @returns an initialized CPPopover
*/
- (CPPopover)init
{
if (self = [super init])
{
- _animates = YES;
- _appearance = CPPopoverAppearanceMinimal;
- _behavior = CPPopoverBehaviorApplicationDefined;
- _needsNewAttachedWindow = YES;
+ _animates = YES;
+ _appearance = CPPopoverAppearanceMinimal;
+ _behavior = CPPopoverBehaviorApplicationDefined;
}
return self;
@@ -106,7 +104,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
- (CGRect)positioningRect
{
if (![_attachedWindow isVisible])
- return nil;
+ return CGRectMakeZero();
return [_attachedWindow frame];
}
@@ -128,7 +126,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
- (CGSize)contentSize
{
if (![_attachedWindow isVisible])
- return nil;
+ return CGRectMakeZero();
return [[_contentViewController view] frameSize];
}
@@ -147,7 +145,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
@returns \c YES if visible
*/
-- (BOOL)shown
+- (BOOL)isShown
{
return [_attachedWindow isVisible];
}
@@ -166,7 +164,7 @@ Set the behaviour of the CPPopover. It can be:
return;
_behavior = aBehaviour;
- _needsNewAttachedWindow = YES;
+ [_attachedWindow setStyleMask:[self styleMaskForBehavior]];
}
- (void)setDelegate:(id)aDelegate
@@ -205,17 +203,27 @@ Set the behaviour of the CPPopover. It can be:
*/
- (void)showRelativeToRect:(CGRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge
{
+ if (!positioningView)
+ [CPException raise:CPInvalidArgumentException reason:"positionView must not be nil"];
+
if (!_contentViewController)
- [CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
+ [CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
+
+ // If the popover is currently closing, do nothing. That is what Cocoa does.
+ if ([_attachedWindow isClosing])
+ return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_)
[_delegate popoverWillShow:self];
- if (!_attachedWindow || _needsNewAttachedWindow || [_attachedWindow isVisible])
+ if (!_attachedWindow)
{
- var styleMask = (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : nil;
- _attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:styleMask];
- _needsNewAttachedWindow = NO;
+ _attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self styleMaskForBehavior]];
+
+ var parentWindow = [positioningView window];
+
+ if (![parentWindow isKindOfClass:_CPAttachedWindow])
+ [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(parentWindowWillClose:) name:CPWindowWillCloseNotification object:parentWindow];
}
[_attachedWindow setAppearance:_appearance];
@@ -224,26 +232,32 @@ Set the behaviour of the CPPopover. It can be:
[_attachedWindow setMovableByWindowBackground:NO];
[_attachedWindow setFrame:[_attachedWindow frameRectForContentRect:[[_contentViewController view] frame]]];
[_attachedWindow setContentView:[_contentViewController view]];
-
- if (positioningRect)
- [_attachedWindow positionRelativeToRect:positioningRect preferredEdge:preferredEdge];
- else if (positioningView)
- [_attachedWindow positionRelativeToView:positioningView preferredEdge:preferredEdge];
- else
- [CPException raise:CPInvalidArgumentException reason:@"a value must be passed for positioningRect or positioningView"];
+ [_attachedWindow positionRelativeToRect:positioningRect ofView:positioningView preferredEdge:preferredEdge];
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
[_delegate popoverDidShow:self];
}
+- (unsigned)styleMaskForBehavior
+{
+ return (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : 0;
+}
+
/*!
Closes the popover
*/
- (void)close
{
- if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
- if (![_delegate popoverShouldClose:self])
- return;
+ [self _close];
+}
+
+/*!
+ Closes the popover
+*/
+- (void)_close
+{
+ if ([_attachedWindow isClosing] || ![self isShown])
+ return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_)
[_delegate popoverWillClose:self];
@@ -261,11 +275,18 @@ Set the behaviour of the CPPopover. It can be:
/*!
Close the popover
- @param aSender the sender of the action
+ @param sender the sender of the action
*/
-- (IBAction)performClose:(id)aSender
+- (IBAction)performClose:(id)sender
{
- [self close];
+ if ([_attachedWindow isClosing])
+ return;
+
+ if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
+ if (![_delegate popoverShouldClose:self])
+ return;
+
+ [self _close];
}
@@ -290,6 +311,22 @@ Set the behaviour of the CPPopover. It can be:
[_delegate popoverDidClose:self];
}
+
+#pragma mark -
+#pragma mark Notifications
+
+/*!
+ @ignore
+
+ This method is called only when a non-popover parent window
+ is closing. In that case popovers should order out.
+*/
+- (void)parentWindowWillClose:(CPNotification)aNotification
+{
+ [_attachedWindow orderOut:nil];
+ [self performClose:nil];
+}
+
@end
var CPPopoverNeedsNewAttachedWindowKey = @"CPPopoverNeedsNewAttachedWindowKey",
@@ -307,7 +344,6 @@ var CPPopoverNeedsNewAttachedWindowKey = @"CPPopoverNeedsNewAttachedWindowKey",
if (self)
{
- _needsNewAttachedWindow = [aCoder decodeBoolForKey:CPPopoverNeedsNewAttachedWindowKey];
_appearance = [aCoder decodeIntForKey:CPPopoverAppearanceKey];
_animates = [aCoder decodeBoolForKey:CPPopoverAnimatesKey];
_contentViewController = [aCoder decodeObjectForKey:CPPopoverContentViewControllerKey];
@@ -321,7 +357,6 @@ var CPPopoverNeedsNewAttachedWindowKey = @"CPPopoverNeedsNewAttachedWindowKey",
{
[super encodeWithCoder:aCoder];
- [aCoder encodeBool:_needsNewAttachedWindow forKey:CPPopoverNeedsNewAttachedWindowKey];
[aCoder encodeInt:_appearance forKey:CPPopoverAppearanceKey];
[aCoder encodeBool:_animates forKey:CPPopoverAnimatesKey];
[aCoder encodeObject:_contentViewController forKey:CPPopoverContentViewControllerKey];
diff --git a/AppKit/CPWindow/_CPAttachedWindowView.j b/AppKit/CPWindow/_CPAttachedWindowView.j
index fcf179645..315c5ef96 100644
--- a/AppKit/CPWindow/_CPAttachedWindowView.j
+++ b/AppKit/CPWindow/_CPAttachedWindowView.j
@@ -25,7 +25,11 @@
#define ALIGN_STROKE(point) (FLOOR(point) === (point) ? (point) + halfStrokeWidth : (point))
#define ALIGN_COORD(point) (FLOOR(point))
-var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10);
+var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10),
+ _CPAttachedWindowViewRadius = 5.0,
+ _CPAttachedWindowViewStrokeWidth = 1.0,
+ _CPAttachedWindowViewShadowSize = CGSizeMake(0, 6),
+ _CPAttachedWindowViewShadowBlur = 15.0;
/*!
@ignore
@@ -34,13 +38,12 @@ var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10);
*/
@implementation _CPAttachedWindowView : _CPWindowView
{
- BOOL _mouseDownPressed @accessors(getter=isMouseDownPressed, setter=setMouseDownPressed:);
- float _arrowOffsetX @accessors(property=arrowOffsetX);
- float _arrowOffsetY @accessors(property=arrowOffsetY);
- int _appearance @accessors(property=appearance);
- unsigned _preferredEdge @accessors(property=preferredEdge);
+ float _arrowOffsetX @accessors(property=arrowOffsetX);
+ float _arrowOffsetY @accessors(property=arrowOffsetY);
+ int _appearance @accessors(property=appearance);
+ unsigned _preferredEdge @accessors(property=preferredEdge);
- CGSize _cursorSize;
+ CGSize _cursorSize;
}
/*!
@@ -91,8 +94,6 @@ var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10);
{
_arrowOffsetX = 0.0;
_arrowOffsetY = 0.0;
-
- // @TODO: make this themable
_appearance = CPPopoverAppearanceMinimal;
_cursorSize = CGSizeMakeCopy(_CPAttachedWindowViewDefaultCursorSize);
}
@@ -116,7 +117,6 @@ var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10);
{
_cursorSize = CGSizeMakeCopy(_CPAttachedWindowViewDefaultCursorSize);
[self setNeedsDisplay:YES];
- _mouseDownPressed = NO;
}
/*!
@@ -127,28 +127,41 @@ var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10);
[super drawRect:aRect];
var context = [[CPGraphicsContext currentContext] graphicsPort],
- radius = 5,
+ radius = _CPAttachedWindowViewRadius,
arrowWidth = _cursorSize.width,
arrowHeight = _cursorSize.height,
- strokeWidth = 1,
+ strokeWidth = _CPAttachedWindowViewStrokeWidth,
halfStrokeWidth = strokeWidth / 2.0,
strokeColor,
shadowColor = [[CPColor blackColor] colorWithAlphaComponent:.2],
- shadowSize = CGSizeMake(0, 6),
- shadowBlur = 15,
+ shadowSize = _CPAttachedWindowViewShadowSize,
+ shadowBlur = _CPAttachedWindowViewShadowBlur,
gradient,
frame = [self bounds];
if (_appearance == CPPopoverAppearanceMinimal)
{
- gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [(254.0 / 255), (254.0 / 255), (254.0 / 255), 0.93,
- (231.0 / 255), (231.0 / 255), (231.0 / 255), 0.93], [0,1], 2);
+ gradient = CGGradientCreateWithColorComponents(
+ CGColorSpaceCreateDeviceRGB(),
+ [
+ (254.0 / 255), (254.0 / 255), (254.0 / 255), 0.93,
+ (231.0 / 255), (231.0 / 255), (231.0 / 255), 0.93
+ ],
+ [0, 1],
+ 2
+ );
strokeColor = [CPColor colorWithHexString:@"B8B8B8"];
}
else
{
- gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [(38.0 / 255), (38.0 / 255), (38.0 / 255), 0.93,
- (18.0 / 255), (18.0 / 255), (18.0 / 255), 0.93], [0,1], 2);
+ gradient = CGGradientCreateWithColorComponents(
+ CGColorSpaceCreateDeviceRGB(),
+ [
+ (38.0 / 255), (38.0 / 255), (38.0 / 255), 0.93,
+ (18.0 / 255), (18.0 / 255), (18.0 / 255), 0.93
+ ],
+ [0, 1],
+ 2);
strokeColor = [CPColor colorWithHexString:@"222222"];
}
@@ -367,22 +380,8 @@ var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10);
}
CGContextClosePath(context);
-
- //Draw it
CGContextStrokePath(context);
CGContextFillPath(context);
}
-- (void)mouseDown:(CPEvent)anEvent
-{
- _mouseDownPressed = YES;
- [super mouseDown:anEvent];
-}
-
-- (void)mouseUp:(CPEvent)anEvent
-{
- _mouseDownPressed = NO;
- [super mouseUp:anEvent];
-}
-
@end
diff --git a/AppKit/_CPAttachedWindow.j b/AppKit/_CPAttachedWindow.j
index 2ed4247b0..1eb175b4e 100644
--- a/AppKit/_CPAttachedWindow.j
+++ b/AppKit/_CPAttachedWindow.j
@@ -45,12 +45,11 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
BOOL _animates @accessors(property=animates);
id _targetView @accessors(property=targetView);
int _appearance @accessors(getter=appearance);
+ BOOL _isClosing @accessors(property=isClosing);
BOOL _closeOnBlur;
- BOOL _isClosing;
BOOL _browserAnimates;
BOOL _shouldPerformAnimation;
- CPButton _closeButton;
CPInteger _implementedDelegateMethods;
}
@@ -82,7 +81,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
*/
+ (id)attachedWindowWithSize:(CGSize)aSize forView:(CPView)aView
{
- return [_CPAttachedWindow attachedWindowWithSize:aSize forView:aView styleMask:nil];
+ return [_CPAttachedWindow attachedWindowWithSize:aSize forView:aView styleMask:0];
}
/*!
@@ -95,7 +94,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
*/
+ (id)attachedWindowWithSize:(CGSize)aSize forView:(CPView)aView styleMask:(int)aMask
{
- var attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CGRectMake(0.0, 0.0, aSize.width, aSize.height) styleMask:aMask];
+ var attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:_CGRectMake(0.0, 0.0, aSize.width, aSize.height) styleMask:aMask];
[attachedWindow attachToView:aView];
@@ -110,12 +109,12 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
*/
- (id)initWithContentRect:(CGRect)aFrame
{
- self = [self initWithContentRect:aFrame styleMask:nil];
+ self = [self initWithContentRect:aFrame styleMask:0];
return self;
}
/*!
- Create and init a _CPAttachedWindow with the given frame and style mask.
+ Designated initializer. Create and init a _CPAttachedWindow with the given frame and style mask.
@param aFrame the frame of the attached window
@param styleMask the window style mask (combine CPClosableWindowMask and CPClosableOnBlurWindowMask)
@@ -154,6 +153,11 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
[_windowView setAppearance:anAppearance];
}
+- (void)setStyleMask:(unsigned)aStyleMask
+{
+ _closeOnBlur = (aStyleMask & CPClosableOnBlurWindowMask);
+}
+
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
@@ -180,25 +184,9 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
if ([aPath isEqual:@"frame"])
{
// TODO: don't recompute everything, just compute the move offset
- var g = [_windowView preferredEdge];
+ var edge = [_windowView preferredEdge];
- [self positionRelativeToView:_targetView preferredEdge:g];
- }
-}
-
-
-#pragma mark -
-#pragma mark Notification handlers
-
-- (void)_attachedWindowDidMove:(CPNotification)aNotification
-{
- if ([_windowView isMouseDownPressed])
- {
- [_targetView removeObserver:self forKeyPath:@"frame"];
- [_windowView hideCursor];
- [self setLevel:CPNormalWindowLevel];
- [_closeButton setFrameOrigin:CGPointMake(1.0, 1.0)];
- [[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidMoveNotification object:self];
+ [self positionRelativeToView:_targetView preferredEdge:edge];
}
}
@@ -206,58 +194,34 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
#pragma mark -
#pragma mark Utilities
-- (CGPoint)computeOrigin:(CPView)aView preferredEdge:(int)anEdge
+- (CGPoint)computeOriginFromRect:(CGRect)aRect ofView:(CPView)positioningView preferredEdge:(int)anEdge
{
- var frameView = [aView frame],
- currentView = aView,
- origin = [aView frameOrigin],
- lastView;
-
- // FIXME: make this work with the conversion function of CPView
- while (currentView = [currentView superview])
- {
- origin.x += [currentView frameOrigin].x;
- origin.y += [currentView frameOrigin].y;
- lastView = currentView;
- }
-
- origin.x += [[lastView window] frame].origin.x;
- origin.y += [[lastView window] frame].origin.y;
-
- // take care of the scrolling point
- if ([aView enclosingScrollView])
- {
- var offsetPoint = [[[aView enclosingScrollView] contentView] boundsOrigin];
- origin.x -= offsetPoint.x;
- origin.y -= offsetPoint.y;
- }
-
- return [self computeOriginFromRect:CGRectMake(origin.x, origin.y, CGRectGetWidth(frameView), CGRectGetHeight(frameView)) preferredEdge:anEdge];
-}
-
-- (CGPoint)computeOriginFromRect:(CGRect)aRect preferredEdge:(int)anEdge
-{
- var nativeRect = [[[CPApp mainWindow] platformWindow] nativeContentRect],
- originLeft = CGPointCreateCopy(aRect.origin),
- originRight = CGPointCreateCopy(aRect.origin),
- originTop = CGPointCreateCopy(aRect.origin),
- originBottom = CGPointCreateCopy(aRect.origin),
+ var mainWindow = [CPApp mainWindow],
+ platformWindow = [mainWindow platformWindow],
+ nativeRect = [platformWindow nativeContentRect],
+ baseOrigin = [positioningView convertPointToBase:aRect.origin],
+ platformOrigin = [mainWindow convertBaseToPlatformWindow:baseOrigin],
+ platformRect = _CGRectMake(platformOrigin.x, platformOrigin.y, aRect.size.width, aRect.size.height),
+ originLeft = _CGPointCreateCopy(platformOrigin),
+ originRight = _CGPointCreateCopy(platformOrigin),
+ originTop = _CGPointCreateCopy(platformOrigin),
+ originBottom = _CGPointCreateCopy(platformOrigin),
frameSize = [self frame].size;
// CPMaxXEdge
- originRight.x += aRect.size.width;
- originRight.y += (aRect.size.height / 2.0) - (frameSize.height / 2.0);
+ originRight.x += platformRect.size.width;
+ originRight.y += (platformRect.size.height / 2.0) - (frameSize.height / 2.0);
// CPMinXEdge
originLeft.x -= frameSize.width;
- originLeft.y += (aRect.size.height / 2.0) - (frameSize.height / 2.0);
+ originLeft.y += (platformRect.size.height / 2.0) - (frameSize.height / 2.0);
// CPMaxYEdge
- originBottom.x += aRect.size.width / 2.0 - frameSize.width / 2.0;
- originBottom.y += aRect.size.height;
+ originBottom.x += platformRect.size.width / 2.0 - frameSize.width / 2.0;
+ originBottom.y += platformRect.size.height;
// CPMinYEdge
- originTop.x += aRect.size.width / 2.0 - frameSize.width / 2.0;
+ originTop.x += platformRect.size.width / 2.0 - frameSize.width / 2.0;
originTop.y -= frameSize.height;
var requestedEdge = (anEdge !== nil) ? anEdge : CPMaxXEdge,
@@ -284,51 +248,57 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
for (var i = 0; i < origins.length; i++)
{
- var o = origins[i],
- g = edges[i];
+ var origin = origins[i],
+ edge = edges[i];
[_windowView setArrowOffsetX:0];
[_windowView setArrowOffsetY:0];
- [_windowView setPreferredEdge:g];
+ [_windowView setPreferredEdge:edge];
- if (o.x < 0)
+ if (origin.x < 0)
{
- [_windowView setArrowOffsetX:o.x];
- o.x = 0;
- }
- if (o.x + frameSize.width > nativeRect.size.width)
- {
- [_windowView setArrowOffsetX:(o.x + frameSize.width - nativeRect.size.width)];
- o.x = nativeRect.size.width - frameSize.width;
- }
- if (o.y < 0)
- {
- [_windowView setArrowOffsetY:o.y];
- o.y = 0;
- }
- if (o.y + frameSize.height > nativeRect.size.height)
- {
- [_windowView setArrowOffsetY:(frameSize.height + o.y - nativeRect.size.height)];
- o.y = nativeRect.size.height - frameSize.height;
+ [_windowView setArrowOffsetX:origin.x];
+ origin.x = 0;
}
- switch (g)
+ if (origin.x + frameSize.width > nativeRect.size.width)
+ {
+ [_windowView setArrowOffsetX:(origin.x + frameSize.width - nativeRect.size.width)];
+ origin.x = nativeRect.size.width - frameSize.width;
+ }
+
+ if (origin.y < 0)
+ {
+ [_windowView setArrowOffsetY:origin.y];
+ origin.y = 0;
+ }
+
+ if (origin.y + frameSize.height > nativeRect.size.height)
+ {
+ [_windowView setArrowOffsetY:(frameSize.height + origin.y - nativeRect.size.height)];
+ origin.y = nativeRect.size.height - frameSize.height;
+ }
+
+ switch (edge)
{
case CPMaxXEdge:
- if (o.x >= (aRect.origin.x + aRect.size.width))
- return o;
+ if (origin.x >= _CGRectGetMaxX(platformRect))
+ return origin;
break;
+
case CPMinXEdge:
- if ((o.x + frameSize.width) <= aRect.origin.x)
- return o;
+ if ((origin.x + frameSize.width) <= platformRect.origin.x)
+ return origin;
break;
+
case CPMaxYEdge:
- if (o.y >= (aRect.origin.y + aRect.size.height))
- return o;
+ if (origin.y >= _CGRectGetMaxY(platformRect))
+ return origin;
break;
+
case CPMinYEdge:
- if ((o.y + frameSize.height) <= aRect.origin.y)
- return o;
+ if ((origin.y + frameSize.height) <= platformRect.origin.y)
+ return origin;
break;
}
}
@@ -345,58 +315,35 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
*/
- (void)positionRelativeToView:(CPView)aView
{
- [self positionRelativeToView:aView preferredEdge:nil];
-}
-
-/*!
- Compute the frame needed to be placed to the given view
- and position the attached window according to this view
-
- @param aView the view where _CPAttachedWindow must be attached
- @param anEdge the preferd edge to use
-*/
-- (void)positionRelativeToView:(CPView)aView preferredEdge:(int)anEdge
-{
- var point = [self computeOrigin:aView preferredEdge:anEdge];
-
- [self setFrameOrigin:point];
- [_windowView showCursor];
- [self setLevel:CPStatusWindowLevel];
- [_closeButton setFrameOrigin:CGPointMake(1.0, 1.0)];
- [_windowView setNeedsDisplay:YES];
- [self makeKeyAndOrderFront:nil];
-
- _targetView = aView;
- [_targetView addObserver:self forKeyPath:@"frame" options:nil context:nil];
-}
-
-/*!
- Position the _CPAttachedWindow relative to a given rect,
- automatically calculating the edge.
-
- @param aPoint the point where the _CPAttachedWindow will be attached
-*/
-- (void)positionRelativeToRect:(CGRect)aRect
-{
- [self positionRelativeToRect:aRect preferredEdge:nil];
+ [self positionRelativeToRect:nil ofView:aView preferredEdge:nil];
}
/*!
Position the _CPAttachedWindow relative to a given rect's edge.
- @param aPoint the point where the _CPAttachedWindow will be attached
+ @param aRect the rect relative to which the attached window will be positioned
+ @param positioningView the view to which the attached window is attached
@param anEdge the prefered edge
*/
-- (void)positionRelativeToRect:(CGRect)aRect preferredEdge:(int)anEdge
+- (void)positionRelativeToRect:(CGRect)aRect ofView:(CPView)positioningView preferredEdge:(int)anEdge
{
- var point = [self computeOriginFromRect:aRect preferredEdge:anEdge];
+ if (!aRect || _CGRectIsEmpty(aRect))
+ aRect = [positioningView bounds];
+
+ var point = [self computeOriginFromRect:aRect ofView:positioningView preferredEdge:anEdge];
[self setFrameOrigin:point];
[_windowView showCursor];
[self setLevel:CPStatusWindowLevel];
- [_closeButton setFrameOrigin:CGPointMake(1.0, 1.0)];
[_windowView setNeedsDisplay:YES];
[self makeKeyAndOrderFront:nil];
+
+ if (positioningView !== _targetView)
+ {
+ [_targetView removeObserver:self forKeyPath:@"frame"];
+ _targetView = positioningView;
+ [_targetView addObserver:self forKeyPath:@"frame" options:0 context:nil];
+ }
}
/*! @ignore */
@@ -440,15 +387,17 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
/*!
Called when the window is losing focus.
- Close the window if CPClosableOnBlurWindowMask is set.
*/
- (void)resignMainWindow
{
if (_closeOnBlur && !_isClosing)
{
- if (!_delegate || ((_implementedDelegateMethods & _CPAttachedWindow_attachedWindowShouldClose_)
- && [_delegate attachedWindowShouldClose:self]))
- [self close];
+ if (!_delegate ||
+ ((_implementedDelegateMethods & _CPAttachedWindow_attachedWindowShouldClose_) &&
+ [_delegate attachedWindowShouldClose:self]))
+ {
+ [self close];
+ }
}
}
@@ -460,66 +409,67 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
*/
- (IBAction)orderFront:(is)aSender
{
- [super orderFront:aSender];
-
- if (_animates && _browserAnimates && _shouldPerformAnimation)
+ if (![self isMainWindow])
{
- var transformOrigin = "50% 100%",
- frame = [self frame],
- preferredEdge = [_windowView preferredEdge],
- posX;
+ [super orderFront:aSender];
- switch (preferredEdge)
+ if (_animates && _browserAnimates && _shouldPerformAnimation)
{
- case CPMaxYEdge:
- case CPMinYEdge:
- posX = 50 + (([_windowView arrowOffsetX] * 100) / frame.size.width);
- transformOrigin = posX + "% " + (preferredEdge === CPMaxYEdge ? "0%" : "100%");
- break;
+ var transformOrigin = "50% 100%",
+ frame = [self frame],
+ preferredEdge = [_windowView preferredEdge],
+ posX;
- case CPMinXEdge:
- case CPMaxXEdge:
- posY = 50 + (([_windowView arrowOffsetY] * 100) / frame.size.height);
- transformOrigin = (preferredEdge === CPMaxXEdge ? "0% " : "100% ") + posY + "%";
- break;
- }
-
- // This is the initial transform. We start scaled to zero and watch for opacity changes.
- [self setCSS3Property:@"Transform" value:@"scale(0)"];
- [self setCSS3Property:@"TransformOrigin" value:transformOrigin];
- [self setCSS3Property:@"Transition" value:"opacity 0 linear"];
-
- window.setTimeout(function()
- {
- // We are watching opacity, so this triggers the next transition
- _DOMElement.style.opacity = 1;
- _DOMElement.style.height = frame.size.height + @"px";
- _DOMElement.style.width = frame.size.width + @"px";
-
- // Set up the pop-out transition
- [self setCSS3Property:@"Transform" value:@"scale(1.1)"];
- [self setCSS3Property:@"Transition" value:@"-webkit-transform 200ms ease-in"];
-
- var transitionEndFunction = function()
+ switch (preferredEdge)
{
- _DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES);
+ case CPMaxYEdge:
+ case CPMinYEdge:
+ posX = 50 + (([_windowView arrowOffsetX] * 100) / frame.size.width);
+ transformOrigin = posX + "% " + (preferredEdge === CPMaxYEdge ? "0%" : "100%");
+ break;
- // Now set up the pop-in to normal size transition.
- // Because we are watching the -webkit-transform, it will occur now.
- [self setCSS3Property:@"Transform" value:@"scale(1)"];
- [self setCSS3Property:@"Transition" value:@"-webkit-transform 50ms linear"];
- };
+ case CPMinXEdge:
+ case CPMaxXEdge:
+ posY = 50 + (([_windowView arrowOffsetY] * 100) / frame.size.height);
+ transformOrigin = (preferredEdge === CPMaxXEdge ? "0% " : "100% ") + posY + "%";
+ break;
+ }
- _DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES);
- }, 0);
+ // This is the initial transform. We start scaled to zero and watch for opacity changes.
+ [self setCSS3Property:@"Transform" value:@"scale(0)"];
+ [self setCSS3Property:@"TransformOrigin" value:transformOrigin];
+ [self setCSS3Property:@"Transition" value:"opacity 0 linear"];
+
+ window.setTimeout(function()
+ {
+ // We are watching opacity, so this triggers the next transition
+ _DOMElement.style.opacity = 1;
+ _DOMElement.style.height = frame.size.height + @"px";
+ _DOMElement.style.width = frame.size.width + @"px";
+
+ // Set up the pop-out transition
+ [self setCSS3Property:@"Transform" value:@"scale(1.1)"];
+ [self setCSS3Property:@"Transition" value:@"-webkit-transform 200ms ease-in"];
+
+ var transitionEndFunction = function()
+ {
+ _DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES);
+
+ // Now set up the pop-in to normal size transition.
+ // Because we are watching the -webkit-transform, it will occur now.
+ [self setCSS3Property:@"Transform" value:@"scale(1)"];
+ [self setCSS3Property:@"Transition" value:@"-webkit-transform 50ms linear"];
+ };
+
+ _DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES);
+ }, 0);
+ }
+ else
+ {
+ [self setCSS3Property:@"Transition" value:@""];
+ _DOMElement.style.opacity = 1;
+ }
}
- else
- {
- [self setCSS3Property:@"Transition" value:@""];
- _DOMElement.style.opacity = 1;
- }
-
- [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_attachedWindowDidMove:) name:CPWindowDidMoveNotification object:self];
_shouldPerformAnimation = NO;
_isClosing = NO;
@@ -530,6 +480,9 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
*/
- (void)close
{
+ if (![self isVisible])
+ return;
+
// set a flag to avoid an infinite loop in resignMainWindow
_isClosing = YES;
@@ -559,6 +512,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
[_targetView removeObserver:self forKeyPath:@"frame"];
_shouldPerformAnimation = YES;
+ _isClosing = NO;
if (_implementedDelegateMethods & _CPAttachedWindow_attachedWindowDidClose_)
[_delegate attachedWindowDidClose:self];
diff --git a/Tests/Manual/CPPopover/AppController.j b/Tests/Manual/CPPopover/AppController.j
index b4b894667..10277ca8a 100644
--- a/Tests/Manual/CPPopover/AppController.j
+++ b/Tests/Manual/CPPopover/AppController.j
@@ -12,12 +12,15 @@
@implementation AppController : CPObject
{
- CPPopUpButton buttonEdge;
- CPPopUpButton buttonStyle;
- CPPopUpButton buttonAnimation;
- CPPopUpButton buttonBehaviour;
- CPPopover popover;
- CPTextField appearanceLabel;
+ CPPopUpButton buttonEdge;
+ CPPopUpButton buttonStyle;
+ CPPopUpButton buttonAnimation;
+ CPPopUpButton buttonBehaviour;
+ CPButton lastButton;
+ int lastPreferredEdge;
+ @outlet CPPopover popover;
+ @outlet CPPopover windowPopover;
+ @outlet CPWindow popoverWindow;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
@@ -41,52 +44,59 @@
button = [CPButton buttonWithTitle:@"click"];
[button setTarget:self];
[button setAction:@selector(open:)];
- [button setAutoresizingMask:CPViewMinXMargin]
+ [button setAutoresizingMask:CPViewMinXMargin];
[button setFrameOrigin:CGPointMake(contentViewSize.width - CGRectGetWidth([button frame]) - 1, 1)];
[contentView addSubview:button];
button = [CPButton buttonWithTitle:@"click"];
[button setTarget:self];
[button setAction:@selector(open:)];
- [button setAutoresizingMask:CPViewMinXMargin]
+ [button setAutoresizingMask:CPViewMinXMargin];
[button setFrameOrigin:CGPointMake(contentViewSize.width - CGRectGetWidth([button frame]) - 1, 100)];
[contentView addSubview:button];
button = [CPButton buttonWithTitle:@"click"];
[button setTarget:self];
[button setAction:@selector(open:)];
- [button setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin]
+ [button setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin];
[button setFrameOrigin:CGPointMake(contentViewSize.width - CGRectGetWidth([button frame])- 1, contentViewSize.height - CGRectGetHeight([button frame]) - 1)];
[contentView addSubview:button];
button = [CPButton buttonWithTitle:@"click"];
[button setTarget:self];
[button setAction:@selector(open:)];
- [button setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin]
+ [button setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin];
[button setFrameOrigin:CGPointMake(contentViewSize.width - CGRectGetWidth([button frame])- 1, contentViewSize.height - 100)];
[contentView addSubview:button];
button = [CPButton buttonWithTitle:@"click"];
[button setTarget:self];
[button setAction:@selector(open:)];
- [button setAutoresizingMask:CPViewMaxXMargin | CPViewMinYMargin]
+ [button setAutoresizingMask:CPViewMaxXMargin | CPViewMinYMargin];
[button setFrameOrigin:CGPointMake(1, contentViewSize.height - CGRectGetHeight([button frame]) - 1)];
[contentView addSubview:button];
button = [CPButton buttonWithTitle:@"click"];
[button setTarget:self];
[button setAction:@selector(open:)];
- [button setAutoresizingMask:CPViewMaxXMargin | CPViewMinYMargin]
+ [button setAutoresizingMask:CPViewMaxXMargin | CPViewMinYMargin];
[button setFrameOrigin:CGPointMake(1, contentViewSize.height - 100)];
[contentView addSubview:button];
button = [CPButton buttonWithTitle:@"click"];
[button setTarget:self];
[button setAction:@selector(open:)];
- [button setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin]
+ [button setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin];
[button setCenter:[contentView center]];
[contentView addSubview:button];
+ button = [CPButton buttonWithTitle:@"Open window"];
+ [button setTarget:self];
+ [button setAction:@selector(openWindow:)];
+ [button setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
+ [button setCenter:[contentView center]];
+ [button setFrameOrigin:CGPointMake(CGRectGetMinX([button frame]), 70)];
+ [contentView addSubview:button];
buttonEdge = [[CPPopUpButton alloc] initWithFrame:CGRectMake(150, 10, 130, 24)];
[buttonEdge addItemWithTitle:"Automatic"];
@@ -114,30 +124,29 @@
[theWindow orderFront:self];
}
-- (IBAction)open:(id)sender
+- (int)popoverEdge
{
- var edge;
-
switch ([buttonEdge title])
{
case "Automatic":
- edge = nil;
- break;
+ return nil;
case "Bottom":
- edge = CPMaxYEdge;
- break;
+ return CPMaxYEdge;
case "Top":
- edge = CPMinYEdge;
- break;
+ return CPMinYEdge;
case "Left":
- edge = CPMinXEdge;
- break;
+ return CPMinXEdge;
case "Right":
- edge = CPMaxXEdge;
- break;
+ return CPMaxXEdge;
+ default:
+ return nil;
}
+}
- var appearance;
+- (IBAction)open:(id)sender
+{
+ var edge = [self popoverEdge],
+ appearance;
switch ([buttonStyle title])
{
@@ -149,45 +158,36 @@
break;
}
- var pop = [self popoverWithAppearance:appearance];
-
- [pop showRelativeToRect:nil ofView:sender preferredEdge:edge];
-
- CPLog.info("content size - w:" + [pop contentSize].width + " h:" + [pop contentSize].width);
- CPLog.info("positioning rect - x: " + [pop positioningRect].origin.x + " y: " + [pop positioningRect].origin.x
- + " w:" + [pop positioningRect].size.width + " h:" + [pop positioningRect].size.width);
+ [self initPopover:popover withAppearance:appearance];
+ lastButton = sender;
+ lastPreferredEdge = edge;
+ [popover showRelativeToRect:nil ofView:sender preferredEdge:edge];
}
-- (CPPopover)popoverWithAppearance:(int)appearance
+- (void)openWindow:(id)sender
{
- if (!popover || [buttonBehaviour title] === @"Not managed")
- {
- popover = [CPPopover new];
+ [popoverWindow orderFront:nil];
+}
- var controller = [[CPViewController alloc] init],
- view = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320, 300)];
+- (IBAction)openWindowPopover:(id)sender
+{
+ [windowPopover showRelativeToRect:nil ofView:sender preferredEdge:[self popoverEdge]];
+}
- appearanceLabel = [CPTextField labelWithTitle:[buttonEdge title]];
- [appearanceLabel setFont:[CPFont boldSystemFontOfSize:30.0]];
- [appearanceLabel setFrameOrigin:CGPointMake(0, 70)];
- [appearanceLabel setValue:CGSizeMake(0.0, 1.0) forThemeAttribute:@"text-shadow-offset"];
- [appearanceLabel setFrameSize:CPSizeMake([view frame].size.width, 50)];
- [appearanceLabel setAlignment:CPCenterTextAlignment];
- [view addSubview:appearanceLabel];
+- (IBAction)movePopover:(id)sender
+{
+ if (++lastPreferredEdge > CPMaxYEdge)
+ lastPreferredEdge = CPMinXEdge;
- [controller setView:view];
- [popover setContentViewController:controller];
- [popover setDelegate:self];
- }
+ [popover showRelativeToRect:CGRectMakeZero() ofView:lastButton preferredEdge:lastPreferredEdge];
+}
- [appearanceLabel setTextColor:(appearance === CPPopoverAppearanceHUD) ? [CPColor whiteColor] : [CPColor colorWithHexString:@"444"]];
- [appearanceLabel setValue:(appearance === CPPopoverAppearanceHUD) ? [CPColor colorWithHexString:@"333"] : [CPColor colorWithHexString:@"fff"] forThemeAttribute:@"text-shadow-color"];
- [appearanceLabel setStringValue:[buttonEdge title]];
- [popover setAnimates:([buttonAnimation title] === @"With animation")];
- [popover setBehaviour:([buttonBehaviour title] === @"Transient") ? CPPopoverBehaviorTransient : CPPopoverBehaviorApplicationDefined];
- [popover setAppearance:appearance];
-
- return popover;
+- (void)initPopover:(CPPopover)aPopover withAppearance:(int)appearance
+{
+ [aPopover setDelegate:self];
+ [aPopover setAnimates:([buttonAnimation title] === @"With animation")];
+ [aPopover setBehaviour:([buttonBehaviour title] === @"Transient") ? CPPopoverBehaviorTransient : CPPopoverBehaviorApplicationDefined];
+ [aPopover setAppearance:appearance];
}
#pragma mark -
@@ -203,6 +203,12 @@
CPLog.info("popover " + aPopover + " did show");
}
+- (BOOL)popoverShouldClose:(CPPopover)aPopover
+{
+ CPLog.info("popover " + aPopover + " should close");
+ return YES;
+}
+
- (void)popoverWillClose:(CPPopover)aPopover
{
diff --git a/Tests/Manual/CPPopover/Info.plist b/Tests/Manual/CPPopover/Info.plist
index 3eb7a23af..5e8c2cda3 100644
--- a/Tests/Manual/CPPopover/Info.plist
+++ b/Tests/Manual/CPPopover/Info.plist
@@ -2,11 +2,9 @@
- CPApplicationDelegateClass
- AppController
+ Main cib file base name
+ MainMenu.cib
CPBundleName
- test
- CPPrincipalClass
- CPApplication
+ CPPopover
diff --git a/Tests/Manual/CPPopover/Jakefile b/Tests/Manual/CPPopover/Jakefile
index 07be3fd32..c6c685238 100644
--- a/Tests/Manual/CPPopover/Jakefile
+++ b/Tests/Manual/CPPopover/Jakefile
@@ -1,9 +1,9 @@
/*
* Jakefile
- * test
+ * CPPopover
*
- * Created by You on July 6, 2011.
- * Copyright 2011, Your Company All rights reserved.
+ * Created by You on March 29, 2012.
+ * Copyright 2012, Your Company All rights reserved.
*/
var ENV = require("system").env,
@@ -15,21 +15,22 @@ var ENV = require("system").env,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
OS = require("os");
-app ("test", function(task)
+app ("CPPopover", function(task)
{
- task.setBuildIntermediatesPath(FILE.join("Build", "test.build", configuration));
+ task.setBuildIntermediatesPath(FILE.join("Build", "CPPopover.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
- task.setProductName("test");
- task.setIdentifier("com.yourcompany.test");
+ task.setProductName("CPPopover");
+ task.setIdentifier("com.yourcompany.CPPopover");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
- task.setSummary("test");
+ task.setSummary("CPPopover");
task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
task.setResources(new FileList("Resources/**"));
task.setIndexFilePath("index.html");
task.setInfoPlistPath("Info.plist");
+ task.setNib2CibFlags("-R Resources/");
if (configuration === "Debug")
task.setCompilerFlags("-DDEBUG -g");
@@ -37,7 +38,7 @@ app ("test", function(task)
task.setCompilerFlags("-O");
});
-task ("default", ["test"], function()
+task ("default", ["CPPopover"], function()
{
printResults(configuration);
});
@@ -58,36 +59,36 @@ task ("release", function()
task ("run", ["debug"], function()
{
- OS.system(["open", FILE.join("Build", "Debug", "test", "index.html")]);
+ OS.system(["open", FILE.join("Build", "Debug", "CPPopover", "index.html")]);
});
task ("run-release", ["release"], function()
{
- OS.system(["open", FILE.join("Build", "Release", "test", "index.html")]);
+ OS.system(["open", FILE.join("Build", "Release", "CPPopover", "index.html")]);
});
task ("deploy", ["release"], function()
{
- FILE.mkdirs(FILE.join("Build", "Deployment", "test"));
- OS.system(["press", "-f", FILE.join("Build", "Release", "test"), FILE.join("Build", "Deployment", "test")]);
+ FILE.mkdirs(FILE.join("Build", "Deployment", "CPPopover"));
+ OS.system(["press", "-f", FILE.join("Build", "Release", "CPPopover"), FILE.join("Build", "Deployment", "CPPopover")]);
printResults("Deployment")
});
task ("desktop", ["release"], function()
{
- FILE.mkdirs(FILE.join("Build", "Desktop", "test"));
- require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "test"), FILE.join("Build", "Desktop", "test", "test.app"));
+ FILE.mkdirs(FILE.join("Build", "Desktop", "CPPopover"));
+ require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "CPPopover"), FILE.join("Build", "Desktop", "CPPopover", "CPPopover.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
- OS.system([FILE.join("Build", "Desktop", "test", "test.app", "Contents", "MacOS", "NativeHost"), "-i"]);
+ OS.system([FILE.join("Build", "Desktop", "CPPopover", "CPPopover.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});
function printResults(configuration)
{
print("----------------------------");
- print(configuration+" app built at path: "+FILE.join("Build", configuration, "test"));
+ print(configuration+" app built at path: "+FILE.join("Build", configuration, "CPPopover"));
print("----------------------------");
}
diff --git a/Tests/Manual/CPPopover/Resources/MainMenu.cib b/Tests/Manual/CPPopover/Resources/MainMenu.cib
new file mode 100644
index 000000000..5e479a9d1
--- /dev/null
+++ b/Tests/Manual/CPPopover/Resources/MainMenu.cib
@@ -0,0 +1 @@
+280NPLIST;1.0;D;K;4;$topD;K;18;CPCibObjectDataKeyD;K;6;CP$UIDd;1;2E;E;K;8;$objectsA;S;5;$nullD;K;10;$classnameS;16;_CPCibObjectDataK;8;$classesA;S;16;_CPCibObjectDataS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;1E;K;28;_CPCibObjectDataNamesKeysKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataNamesValuesKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataClassesKeysKeyD;K;6;CP$UIDd;1;0E;K;32;_CPCibObjectDataClassesValuesKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataConnectionsKeyD;K;6;CP$UIDd;1;4E;K;28;_CPCibObjectDataFrameworkKeyD;K;6;CP$UIDd;1;0E;K;26;_CPCibObjectDataNextOidKeyD;K;6;CP$UIDd;1;5E;K;30;_CPCibObjectDataObjectsKeysKeyD;K;6;CP$UIDd;1;6E;K;32;_CPCibObjectDataObjectsValuesKeyD;K;6;CP$UIDd;1;7E;K;26;_CPCibObjectDataOidKeysKeyD;K;6;CP$UIDd;1;8E;K;28;_CPCibObjectDataOidValuesKeyD;K;6;CP$UIDd;1;9E;K;28;_CPCibObjectDataFileOwnerKeyD;K;6;CP$UIDd;2;11E;K;33;_CPCibObjectDataVisibleWindowsKeyD;K;6;CP$UIDd;2;13E;E;D;K;10;$classnameS;7;CPArrayK;8;$classesA;S;7;CPArrayS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;15E;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;17E;D;K;6;CP$UIDd;2;18E;D;K;6;CP$UIDd;2;19E;D;K;6;CP$UIDd;2;20E;D;K;6;CP$UIDd;2;21E;D;K;6;CP$UIDd;2;22E;D;K;6;CP$UIDd;2;24E;D;K;6;CP$UIDd;2;25E;D;K;6;CP$UIDd;2;26E;D;K;6;CP$UIDd;2;27E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;28E;D;K;6;CP$UIDd;2;29E;D;K;6;CP$UIDd;2;31E;D;K;6;CP$UIDd;2;33E;D;K;6;CP$UIDd;2;35E;D;K;6;CP$UIDd;2;37E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;38E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;40E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;41E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;43E;D;K;6;CP$UIDd;2;45E;D;K;6;CP$UIDd;2;46E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;47E;D;K;6;CP$UIDd;2;48E;D;K;6;CP$UIDd;2;49E;D;K;6;CP$UIDd;2;50E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;51E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;52E;D;K;6;CP$UIDd;1;0E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;35E;D;K;6;CP$UIDd;2;37E;D;K;6;CP$UIDd;2;35E;D;K;6;CP$UIDd;2;38E;D;K;6;CP$UIDd;2;35E;D;K;6;CP$UIDd;2;40E;D;K;6;CP$UIDd;2;35E;D;K;6;CP$UIDd;2;41E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;43E;D;K;6;CP$UIDd;2;45E;D;K;6;CP$UIDd;2;46E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;49E;D;K;6;CP$UIDd;2;50E;D;K;6;CP$UIDd;2;49E;D;K;6;CP$UIDd;2;51E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;52E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;10;$classnameS;18;_CPCibCustomObjectK;8;$classesA;S;18;_CPCibCustomObjectS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;53E;E;D;K;10;$classnameS;5;CPSetK;8;$classesA;S;5;CPSetS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;12E;K;15;CPSetObjectsKeyD;K;6;CP$UIDd;2;54E;E;D;K;10;$classnameS;20;CPCibOutletConnectorK;8;$classesA;S;20;CPCibOutletConnectorS;14;CPCibConnectorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;11E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;29E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;55E;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;29E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;33E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;56E;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;29E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;43E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;57E;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;29E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;48E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;58E;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;31E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;35E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;59E;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;33E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;31E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;60E;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;47E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;49E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;59E;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;48E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;47E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;60E;E;D;K;10;$classnameS;21;CPCibControlConnectorK;8;$classesA;S;21;CPCibControlConnectorS;14;CPCibConnectorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;23E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;40E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;33E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;61E;E;D;K;6;$classD;K;6;CP$UIDd;2;23E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;41E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;29E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;62E;E;D;K;6;$classD;K;6;CP$UIDd;2;23E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;46E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;29E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;63E;E;D;K;6;$classD;K;6;CP$UIDd;2;23E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;51E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;48E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;61E;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;53E;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;64E;E;D;K;10;$classnameS;16;CPViewControllerK;8;$classesA;S;16;CPViewControllerS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;30E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;23;CPViewControllerViewKeyD;K;6;CP$UIDd;1;0E;K;24;CPViewControllerTitleKeyD;K;6;CP$UIDd;1;0E;K;26;CPViewControllerCibNameKeyD;K;6;CP$UIDd;1;0E;K;25;CPViewControllerBundleKeyD;K;6;CP$UIDd;1;0E;E;D;K;10;$classnameS;9;CPPopoverK;8;$classesA;S;9;CPPopoverS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;32E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;22;CPPopoverAppearanceKeyD;K;6;CP$UIDd;2;65E;K;20;CPPopoverAnimatesKeyD;K;6;CP$UIDd;2;66E;K;33;CPPopoverContentViewControllerKeyD;K;6;CP$UIDd;1;0E;K;20;CPPopoverDelegateKeyD;K;6;CP$UIDd;1;0E;K;20;CPPopoverBehaviorKeyD;K;6;CP$UIDd;2;67E;E;D;K;10;$classnameS;16;_CPCibCustomViewK;8;$classesA;S;16;_CPCibCustomViewS;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;34E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;68E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;68E;K;17;CPViewSubviewsKeyD;K;6;CP$UIDd;2;69E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;70E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;1;0E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;71E;K;28;_CPCibCustomViewClassNameKeyD;K;6;CP$UIDd;2;72E;E;D;K;10;$classnameS;11;CPTextFieldK;8;$classesA;S;11;CPTextFieldS;9;CPControlS;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;36E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;35E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;73E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;74E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;35E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;75E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;77E;K;6;$afontD;K;6;CP$UIDd;2;79E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;80E;K;11;$aalignmentD;K;6;CP$UIDd;2;81E;K;35;CPControlSendsActionOnEndEditingKeyD;K;6;CP$UIDd;2;66E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;82E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;83E;K;24;CPTextFieldIsEditableKeyD;K;6;CP$UIDd;2;66E;K;26;CPTextFieldIsSelectableKeyD;K;6;CP$UIDd;2;66E;K;29;CPTextFieldDrawsBackgroundKeyD;K;6;CP$UIDd;2;66E;K;29;CPTextFieldBackgroundColorKeyD;K;6;CP$UIDd;2;85E;K;27;CPTextFieldLineBreakModeKeyD;K;6;CP$UIDd;2;80E;K;23;CPTextFieldAlignmentKeyD;K;6;CP$UIDd;2;81E;K;31;CPTextFieldPlaceholderStringKeyD;K;6;CP$UIDd;2;86E;E;D;K;6;$classD;K;6;CP$UIDd;2;36E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;35E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;87E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;88E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;35E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;89E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;71E;K;6;$afontD;K;6;CP$UIDd;2;90E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;67E;K;11;$aalignmentD;K;6;CP$UIDd;2;80E;K;35;CPControlSendsActionOnEndEditingKeyD;K;6;CP$UIDd;2;66E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;91E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;83E;K;24;CPTextFieldIsEditableKeyD;K;6;CP$UIDd;2;92E;K;26;CPTextFieldIsSelectableKeyD;K;6;CP$UIDd;2;92E;K;29;CPTextFieldDrawsBackgroundKeyD;K;6;CP$UIDd;2;92E;K;29;CPTextFieldBackgroundColorKeyD;K;6;CP$UIDd;1;0E;K;27;CPTextFieldLineBreakModeKeyD;K;6;CP$UIDd;2;67E;K;23;CPTextFieldAlignmentKeyD;K;6;CP$UIDd;2;80E;K;31;CPTextFieldPlaceholderStringKeyD;K;6;CP$UIDd;1;0E;E;D;K;10;$classnameS;8;CPButtonK;8;$classesA;S;8;CPButtonS;9;CPControlS;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;39E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;35E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;93E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;94E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;35E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;95E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;96E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;97E;K;6;$afontD;K;6;CP$UIDd;2;98E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;65E;K;11;$aalignmentD;K;6;CP$UIDd;2;80E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;65E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;81E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;2;99E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;92E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;80E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;65E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;39E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;35E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;100E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;101E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;35E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;95E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;96E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;97E;K;6;$afontD;K;6;CP$UIDd;2;98E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;65E;K;11;$aalignmentD;K;6;CP$UIDd;2;80E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;65E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;81E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;3;102E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;92E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;80E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;65E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;10;$classnameS;20;_CPCibWindowTemplateK;8;$classesA;S;20;_CPCibWindowTemplateS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;42E;K;30;_CPCibWindowTemplateMaxSizeKeyD;K;6;CP$UIDd;3;103E;K;32;_CPCibWindowTemplateViewClassKeyD;K;6;CP$UIDd;1;0E;K;34;_CPCibWindowTemplateWindowClassKeyD;K;6;CP$UIDd;3;104E;K;33;_CPCibWindowTemplateWindowRectKeyD;K;6;CP$UIDd;3;105E;K;30;_CPCibWindowTempatStyleMaskKeyD;K;6;CP$UIDd;3;106E;K;34;_CPCibWindowTemplateWindowTitleKeyD;K;6;CP$UIDd;3;107E;K;33;_CPCibWindowTemplateWindowViewKeyD;K;6;CP$UIDd;2;45E;E;D;K;10;$classnameS;6;CPViewK;8;$classesA;S;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;44E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;108E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;108E;K;17;CPViewSubviewsKeyD;K;6;CP$UIDd;3;109E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;1;0E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;71E;E;D;K;6;$classD;K;6;CP$UIDd;2;39E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;45E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;110E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;111E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;45E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;75E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;96E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;97E;K;6;$afontD;K;6;CP$UIDd;2;98E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;65E;K;11;$aalignmentD;K;6;CP$UIDd;2;80E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;65E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;81E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;3;112E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;92E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;80E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;65E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;30E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;23;CPViewControllerViewKeyD;K;6;CP$UIDd;1;0E;K;24;CPViewControllerTitleKeyD;K;6;CP$UIDd;1;0E;K;26;CPViewControllerCibNameKeyD;K;6;CP$UIDd;1;0E;K;25;CPViewControllerBundleKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;32E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;22;CPPopoverAppearanceKeyD;K;6;CP$UIDd;2;65E;K;20;CPPopoverAnimatesKeyD;K;6;CP$UIDd;2;66E;K;33;CPPopoverContentViewControllerKeyD;K;6;CP$UIDd;1;0E;K;20;CPPopoverDelegateKeyD;K;6;CP$UIDd;1;0E;K;20;CPPopoverBehaviorKeyD;K;6;CP$UIDd;2;65E;E;D;K;6;$classD;K;6;CP$UIDd;2;34E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;113E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;113E;K;17;CPViewSubviewsKeyD;K;6;CP$UIDd;3;114E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;70E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;1;0E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;71E;K;28;_CPCibCustomViewClassNameKeyD;K;6;CP$UIDd;2;72E;E;D;K;6;$classD;K;6;CP$UIDd;2;36E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;49E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;115E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;116E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;49E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;3;117E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;71E;K;6;$afontD;K;6;CP$UIDd;2;79E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;80E;K;11;$aalignmentD;K;6;CP$UIDd;2;80E;K;35;CPControlSendsActionOnEndEditingKeyD;K;6;CP$UIDd;2;66E;K;17;CPControlValueKeyD;K;6;CP$UIDd;3;118E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;83E;K;24;CPTextFieldIsEditableKeyD;K;6;CP$UIDd;2;92E;K;26;CPTextFieldIsSelectableKeyD;K;6;CP$UIDd;2;92E;K;29;CPTextFieldDrawsBackgroundKeyD;K;6;CP$UIDd;2;92E;K;29;CPTextFieldBackgroundColorKeyD;K;6;CP$UIDd;1;0E;K;27;CPTextFieldLineBreakModeKeyD;K;6;CP$UIDd;2;80E;K;23;CPTextFieldAlignmentKeyD;K;6;CP$UIDd;2;80E;K;31;CPTextFieldPlaceholderStringKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;39E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;49E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;119E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;94E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;49E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;95E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;96E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;97E;K;6;$afontD;K;6;CP$UIDd;2;98E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;65E;K;11;$aalignmentD;K;6;CP$UIDd;2;80E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;65E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;81E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;2;99E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;92E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;80E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;65E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;36E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;65E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;120E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;120E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;70E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;71E;K;6;$afontD;K;6;CP$UIDd;2;79E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;80E;K;11;$aalignmentD;K;6;CP$UIDd;2;81E;K;35;CPControlSendsActionOnEndEditingKeyD;K;6;CP$UIDd;2;66E;K;17;CPControlValueKeyD;K;6;CP$UIDd;3;121E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;83E;K;24;CPTextFieldIsEditableKeyD;K;6;CP$UIDd;2;92E;K;26;CPTextFieldIsSelectableKeyD;K;6;CP$UIDd;2;92E;K;29;CPTextFieldDrawsBackgroundKeyD;K;6;CP$UIDd;2;92E;K;29;CPTextFieldBackgroundColorKeyD;K;6;CP$UIDd;1;0E;K;27;CPTextFieldLineBreakModeKeyD;K;6;CP$UIDd;2;80E;K;23;CPTextFieldAlignmentKeyD;K;6;CP$UIDd;2;81E;K;31;CPTextFieldPlaceholderStringKeyD;K;6;CP$UIDd;1;0E;E;S;13;CPApplicationD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;S;8;delegateS;7;popoverS;13;popoverWindowS;13;windowPopoverS;4;viewS;21;contentViewControllerS;13;performClose:S;12;movePopover:S;18;openWindowPopover:S;13;AppControllerd;1;0T;d;1;1S;20;{{0, 0}, {301, 217}}D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;37E;D;K;6;CP$UIDd;2;41E;D;K;6;CP$UIDd;2;40E;D;K;6;CP$UIDd;2;38E;E;E;d;2;12S;6;normalS;6;CPViewS;21;{{25, 94}, {247, 29}}S;19;{{0, 0}, {247, 29}}d;2;45S;9;textfieldS;19;bezeled+placeholderD;K;10;$classnameS;6;CPFontK;8;$classesA;S;6;CPFontS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;78E;K;13;CPFontNameKeyD;K;6;CP$UIDd;3;122E;K;13;CPFontSizeKeyD;K;6;CP$UIDd;2;70E;K;15;CPFontIsBoldKeyD;K;6;CP$UIDd;2;92E;K;17;CPFontIsItalicKeyD;K;6;CP$UIDd;2;92E;E;d;1;2d;1;4S;0;d;4;3072D;K;10;$classnameS;7;CPColorK;8;$classesA;S;7;CPColorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;84E;K;20;CPColorComponentsKeyD;K;6;CP$UIDd;3;123E;E;S;15;Write somethingS;21;{{28, 43}, {245, 34}}S;19;{{0, 0}, {245, 34}}d;2;37D;K;6;$classD;K;6;CP$UIDd;2;78E;K;13;CPFontNameKeyD;K;6;CP$UIDd;3;122E;K;13;CPFontSizeKeyD;K;6;CP$UIDd;3;124E;K;15;CPFontIsBoldKeyD;K;6;CP$UIDd;2;66E;K;17;CPFontIsItalicKeyD;K;6;CP$UIDd;2;92E;E;S;14;I’m a popover!F;S;22;{{38, 153}, {114, 24}}S;19;{{0, 0}, {114, 24}}d;2;13S;6;buttonS;8;borderedD;K;6;$classD;K;6;CP$UIDd;2;78E;K;13;CPFontNameKeyD;K;6;CP$UIDd;3;122E;K;13;CPFontSizeKeyD;K;6;CP$UIDd;2;70E;K;15;CPFontIsBoldKeyD;K;6;CP$UIDd;2;66E;K;17;CPFontIsItalicKeyD;K;6;CP$UIDd;2;92E;E;S;12;performCloseS;22;{{197, 153}, {62, 24}}S;18;{{0, 0}, {62, 24}}S;4;MoveS;32;{10000000000000, 10000000000000}S;8;CPWindowS;24;{{344, 245}, {212, 112}}d;2;15S;6;WindowS;20;{{0, 0}, {212, 112}}D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;46E;E;E;S;20;{{60, 43}, {87, 24}}S;18;{{0, 0}, {87, 24}}S;9;Click me!S;19;{{0, 0}, {163, 96}}D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;51E;D;K;6;CP$UIDd;2;50E;E;E;S;20;{{37, 20}, {89, 17}}S;18;{{0, 0}, {89, 17}}d;2;36S;11;From windowS;21;{{22, 54}, {114, 24}}S;18;{{0, 0}, {38, 17}}S;5;LabelS;17;Arial, sans-serifD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;67E;D;K;6;CP$UIDd;2;67E;D;K;6;CP$UIDd;2;67E;D;K;6;CP$UIDd;2;67E;E;E;d;2;20E;K;9;$archiverS;15;CPKeyedArchiverK;8;$versionS;6;100000E;
\ No newline at end of file
diff --git a/Tests/Manual/CPPopover/Resources/MainMenu.xib b/Tests/Manual/CPPopover/Resources/MainMenu.xib
new file mode 100644
index 000000000..b05caa61a
--- /dev/null
+++ b/Tests/Manual/CPPopover/Resources/MainMenu.xib
@@ -0,0 +1,832 @@
+
+
+
+ 1050
+ 11D50
+ 2182
+ 1138.32
+ 568.00
+
+
+
+
+
+
+
+ YES
+
+
+ delegate
+
+
+
+ 451
+
+
+
+ popover
+
+
+
+ 473
+
+
+
+ windowPopover
+
+
+
+ 519
+
+
+
+ openWindowPopover:
+
+
+
+ 521
+
+
+
+ movePopover:
+
+
+
+ 550
+
+
+
+ popoverWindow
+
+
+
+ 555
+
+
+
+ view
+
+
+
+ 468
+
+
+
+ contentViewController
+
+
+
+ 462
+
+
+
+ performClose:
+
+
+
+ 484
+
+
+
+ view
+
+
+
+ 529
+
+
+
+ contentViewController
+
+
+
+ 508
+
+
+
+ performClose:
+
+
+
+ 554
+
+
+
+
+ YES
+
+ 0
+
+ YES
+
+
+
+
+
+ -2
+
+
+ File's Owner
+
+
+ -1
+
+
+ First Responder
+
+
+ -3
+
+
+ Application
+
+
+ 450
+
+
+
+
+ 460
+
+
+ Popover View Controller
+
+
+ 461
+
+
+
+
+ 463
+
+
+ YES
+
+
+
+
+
+
+
+
+ 464
+
+
+ YES
+
+
+
+
+
+ 465
+
+
+
+
+ 466
+
+
+ YES
+
+
+
+
+
+ 467
+
+
+
+
+ 476
+
+
+ YES
+
+
+
+
+
+ 477
+
+
+
+
+ 488
+
+
+ YES
+
+
+
+
+
+ 489
+
+
+
+
+ 502
+
+
+ YES
+
+
+
+
+
+ 503
+
+
+ YES
+
+
+
+
+
+ 504
+
+
+ YES
+
+
+
+
+
+ 505
+
+
+
+
+ 506
+
+
+ Window Popover View Controller
+
+
+ 507
+
+
+ Window Popover
+
+
+ 510
+
+
+ YES
+
+
+
+
+ Parent View
+
+
+ 511
+
+
+ YES
+
+
+
+
+
+ 512
+
+
+
+
+ 535
+
+
+ YES
+
+
+
+
+
+ 536
+
+
+
+
+ 551
+
+
+ YES
+
+
+
+
+
+ 552
+
+
+
+
+
+
+ YES
+
+ YES
+ -1.IBPluginDependency
+ -2.IBPluginDependency
+ -3.IBPluginDependency
+ 450.IBPluginDependency
+ 460.IBPluginDependency
+ 461.IBPluginDependency
+ 463.IBPluginDependency
+ 464.IBPluginDependency
+ 465.IBPluginDependency
+ 466.IBPluginDependency
+ 467.IBPluginDependency
+ 476.IBPluginDependency
+ 477.IBPluginDependency
+ 488.IBPluginDependency
+ 489.IBPluginDependency
+ 502.IBNSWindowAutoPositionCentersHorizontal
+ 502.IBNSWindowAutoPositionCentersVertical
+ 502.IBPluginDependency
+ 502.NSWindowTemplate.visibleAtLaunch
+ 503.IBPluginDependency
+ 504.IBPluginDependency
+ 505.IBPluginDependency
+ 506.IBPluginDependency
+ 507.IBPluginDependency
+ 510.IBPluginDependency
+ 511.IBPluginDependency
+ 512.IBPluginDependency
+ 535.IBPluginDependency
+ 536.IBPluginDependency
+ 551.IBPluginDependency
+ 552.IBPluginDependency
+
+
+ YES
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+
+
+ YES
+
+
+
+
+
+ YES
+
+
+
+
+ 555
+
+
+
+ YES
+
+ AppController
+ NSObject
+
+ YES
+
+ YES
+ movePopover:
+ open:
+ openWindowPopover:
+
+
+ YES
+ id
+ id
+ id
+
+
+
+ YES
+
+ YES
+ movePopover:
+ open:
+ openWindowPopover:
+
+
+ YES
+
+ movePopover:
+ id
+
+
+ open:
+ id
+
+
+ openWindowPopover:
+ id
+
+
+
+
+ YES
+
+ YES
+ popover
+ popoverWindow
+ windowPopover
+
+
+ YES
+ NSPopover
+ NSWindow
+ NSPopover
+
+
+
+ YES
+
+ YES
+ popover
+ popoverWindow
+ windowPopover
+
+
+ YES
+
+ popover
+ NSPopover
+
+
+ popoverWindow
+ NSWindow
+
+
+ windowPopover
+ NSPopover
+
+
+
+
+ IBProjectSource
+ ./Classes/AppController.h
+
+
+
+
+ 0
+ IBCocoaFramework
+
+ com.apple.InterfaceBuilder.CocoaPlugin.macosx
+
+
+
+ com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3
+
+
+ YES
+ 3
+
+
diff --git a/Tests/Manual/CPPopover/index-debug.html b/Tests/Manual/CPPopover/index-debug.html
index 631a52ca1..2f7ed22a6 100644
--- a/Tests/Manual/CPPopover/index-debug.html
+++ b/Tests/Manual/CPPopover/index-debug.html
@@ -52,6 +52,10 @@
// Uncomment to enable a specific logger:
//CPLogRegister(CPLogConsole);
//CPLogRegister(CPLogPopup);
+
+ // Tag view DOM elements with a "data-cappuccino-view" attribute that contains
+ // the class name of the view that created them. Comment this or set to false to disable.
+ appkit_tag_dom_elements = true;