mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-11 11:07:07 +00:00
Merge remote-tracking branch 'cappuccino/master'
This commit is contained in:
commit
b32499f6ec
20 files changed
+3286
-103
No files matched your search
@@ -103,6 +103,7 @@
|
||||
@import "CPTokenField.j"
|
||||
@import "CPToolbar.j"
|
||||
@import "CPToolbarItem.j"
|
||||
@import "CPTrackingArea.j"
|
||||
@import "CPTreeNode.j"
|
||||
@import "CPUserDefaultsController.j"
|
||||
@import "CPView.j"
|
||||
|
||||
+14
-1
@@ -27,6 +27,7 @@
|
||||
@import "CPShadow.j"
|
||||
@import "CPView.j"
|
||||
@import "CPKeyValueBinding.j"
|
||||
@import "CPTrackingArea.j"
|
||||
|
||||
@global CPApp
|
||||
|
||||
@@ -200,7 +201,6 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Control Size
|
||||
|
||||
@@ -1056,6 +1056,19 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPControl (CPTrackingArea)
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
[self removeAllTrackingAreas];
|
||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPControlActionKey = @"CPControlActionKey",
|
||||
CPControlControlSizeKey = @"CPControlControlSizeKey",
|
||||
CPControlControlStateKey = @"CPControlControlStateKey",
|
||||
|
||||
@@ -123,6 +123,9 @@ var currentCursor = nil,
|
||||
|
||||
- (void)set
|
||||
{
|
||||
if (currentCursor === self)
|
||||
return;
|
||||
|
||||
currentCursor = self;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
@import "CPCompatibility.j"
|
||||
@import "CGGeometry.j"
|
||||
@import "CPText.j"
|
||||
@import "CPTrackingArea.j"
|
||||
|
||||
@class CPTextField
|
||||
@class CPWindow
|
||||
@@ -82,6 +83,8 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
BOOL _suppressCappuccinoCut;
|
||||
BOOL _suppressCappuccinoPaste;
|
||||
#endif
|
||||
|
||||
CPTrackingArea _trackingArea;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -141,6 +144,27 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext eventNumber:anEventNumber clickCount:aClickCount pressure:aPressure];
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new mouse tracking event.
|
||||
|
||||
@param anEventType the event type
|
||||
@param aPoint the location of the cursor in the window specified by \c aWindowNumber
|
||||
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
|
||||
@param aTimestamp the time the event occurred
|
||||
@param aWindowNumber the number of the CPWindow where the event occurred
|
||||
@param aGraphicsContext the graphics context where the event occurred
|
||||
@param anEventNumber a number for this event
|
||||
@param aTrackingArea the tracking area that triggered the event
|
||||
@throws CPInternalInconsistencyException if an invalid event type is provided
|
||||
@return the new mouse event
|
||||
*/
|
||||
+ (id)enterExitEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
|
||||
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
|
||||
eventNumber:(int)anEventNumber trackingArea:(CPTrackingArea)aTrackingArea
|
||||
{
|
||||
return [[self alloc] _initEnterExitEventWithType:anEventType location:aPoint modifierFlags:modifierFlags timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext eventNumber:anEventNumber trackingArea:aTrackingArea];
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new custom event.
|
||||
|
||||
@@ -201,6 +225,28 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
return self;
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (id)_initEnterExitEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
|
||||
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
|
||||
eventNumber:(int)anEventNumber trackingArea:(CPTrackingArea)aTrackingArea
|
||||
{
|
||||
if ((anEventType != CPMouseEntered) && (anEventType != CPMouseExited) && (anEventType != CPCursorUpdate))
|
||||
[CPException raise:CPInternalInconsistencyException reason:"Invalid event type"];
|
||||
|
||||
if (self = [self _initWithType:anEventType])
|
||||
{
|
||||
_location = CGPointCreateCopy(aPoint);
|
||||
_modifierFlags = modifierFlags;
|
||||
_timestamp = aTimestamp;
|
||||
_context = aGraphicsContext;
|
||||
_eventNumber = anEventNumber;
|
||||
_trackingArea = aTrackingArea;
|
||||
_window = [CPApp windowWithWindowNumber:aWindowNumber];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (id)_initKeyEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned int)modifierFlags
|
||||
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
|
||||
@@ -583,6 +629,14 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
}
|
||||
|
||||
- (CPTrackingArea)trackingArea
|
||||
{
|
||||
if ((_type !== CPMouseEntered) && (_type !== CPMouseExited) && (_type !== CPCursorUpdate))
|
||||
[CPException raise:CPInternalInconsistencyException format:@"You can't call trackingArea for events of type %#x", _type]
|
||||
|
||||
return _trackingArea;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
function _CPEventFirePeriodEvent()
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
@import <Foundation/CPObjJRuntime.j>
|
||||
|
||||
@import "CPEvent.j"
|
||||
@import "CPCursor.j"
|
||||
|
||||
@class CPKeyBinding
|
||||
@class CPMenu
|
||||
@@ -200,6 +201,18 @@ CPDeleteForwardKeyCode = 46;
|
||||
[_nextResponder performSelector:_cmd withObject:anEvent];
|
||||
}
|
||||
|
||||
/*!
|
||||
Notifies the receiver that the mouse entered the receiver's area and that it can adapt the cursor.
|
||||
@param anEvent contains information about the exit
|
||||
*/
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
{
|
||||
if (_nextResponder)
|
||||
[_nextResponder performSelector:_cmd withObject:anEvent];
|
||||
else
|
||||
[[CPCursor arrowCursor] set];
|
||||
}
|
||||
|
||||
/*!
|
||||
Notifies the receiver that the mouse scroll wheel has moved.
|
||||
@param anEvent information about the scroll
|
||||
|
||||
+26
-20
@@ -26,6 +26,7 @@
|
||||
@import "CPImage.j"
|
||||
@import "CPView.j"
|
||||
@import "CPCursor.j"
|
||||
@import "CPTrackingArea.j"
|
||||
|
||||
@class CPUserDefaults
|
||||
@global CPApp
|
||||
@@ -562,26 +563,6 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
//[[self window] setAcceptsMouseMovedEvents:YES];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
// Tracking code handles cursor by itself.
|
||||
if (_currentDivider == CPNotFound)
|
||||
[self _updateResizeCursor:anEvent];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(CPEvent)anEvent
|
||||
{
|
||||
if (_currentDivider == CPNotFound)
|
||||
[self _updateResizeCursor:anEvent];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
if (_currentDivider == CPNotFound)
|
||||
// FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow).
|
||||
[[CPCursor arrowCursor] set];
|
||||
}
|
||||
|
||||
- (void)_updateResizeCursor:(CPEvent)anEvent
|
||||
{
|
||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
@@ -1205,6 +1186,29 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPSplitView (CPTrackingArea)
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
[self removeAllTrackingAreas];
|
||||
|
||||
var options = CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow;
|
||||
|
||||
for (var i = 0; i < _subviews.length - 1; i++)
|
||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self effectiveRectOfDividerAtIndex:i]
|
||||
options:options
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
{
|
||||
if (_currentDivider === CPNotFound)
|
||||
[self _updateResizeCursor:anEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPSplitView (CPSplitViewDelegate)
|
||||
|
||||
@@ -1376,6 +1380,8 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
[_delegate splitViewDidResizeSubviews:[[CPNotification alloc] initWithName:CPSplitViewDidResizeSubviewsNotification object:self userInfo:userInfo]];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewDidResizeSubviewsNotification object:self userInfo:userInfo];
|
||||
|
||||
[self updateTrackingAreas];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+23
-31
@@ -24,6 +24,7 @@
|
||||
@import "CPView.j"
|
||||
@import "CPCursor.j"
|
||||
@import "_CPImageAndTextView.j"
|
||||
@import "CPTrackingArea.j"
|
||||
|
||||
@class CPTableView
|
||||
|
||||
@@ -305,7 +306,9 @@ var CPTableHeaderViewResizeZone = 3.0,
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
if (self)
|
||||
{
|
||||
[self _init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -456,34 +459,26 @@ var CPTableHeaderViewResizeZone = 3.0,
|
||||
_activeColumn = -1;
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)theEvent
|
||||
@end
|
||||
|
||||
@implementation CPTableHeaderView (CPTrackingArea)
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
var location = [theEvent globalLocation];
|
||||
|
||||
if (CGPointEqualToPoint(location, _mouseEnterExitLocation))
|
||||
return;
|
||||
|
||||
_mouseEnterExitLocation = location;
|
||||
|
||||
[self _updateResizeCursor:theEvent];
|
||||
[self removeAllTrackingAreas];
|
||||
|
||||
var options = CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow;
|
||||
|
||||
for (var i = 0; i < _tableView._tableColumns.length; i++)
|
||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self _cursorRectForColumn:i]
|
||||
options:options
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(CPEvent)theEvent
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
{
|
||||
[self _updateResizeCursor:theEvent];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)theEvent
|
||||
{
|
||||
var location = [theEvent globalLocation];
|
||||
|
||||
if (CGPointEqualToPoint(location, _mouseEnterExitLocation))
|
||||
return;
|
||||
|
||||
_mouseEnterExitLocation = location;
|
||||
|
||||
// FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow).
|
||||
[[CPCursor arrowCursor] set];
|
||||
[self _updateResizeCursor:anEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -697,6 +692,7 @@ var CPTableHeaderViewResizeZone = 3.0,
|
||||
[[_tableView headerView] setNeedsLayout];
|
||||
|
||||
[[CPCursor arrowCursor] set];
|
||||
[self updateTrackingAreas];
|
||||
}
|
||||
|
||||
- (BOOL)_shouldResizeTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
|
||||
@@ -762,7 +758,10 @@ var CPTableHeaderViewResizeZone = 3.0,
|
||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
|
||||
|
||||
if ([tableColumn width] != _columnOldWidth)
|
||||
{
|
||||
[_tableView _didResizeTableColumn:tableColumn oldWidth:_columnOldWidth];
|
||||
[self updateTrackingAreas];
|
||||
}
|
||||
|
||||
[tableColumn setDisableResizingPosting:NO];
|
||||
[_tableView setDisableAutomaticResizing:NO];
|
||||
@@ -772,13 +771,6 @@ var CPTableHeaderViewResizeZone = 3.0,
|
||||
|
||||
- (void)_updateResizeCursor:(CPEvent)theEvent
|
||||
{
|
||||
// never get stuck in resize cursor mode (FIXME take out when we turn on tracking rects)
|
||||
if (![_tableView allowsColumnResizing] || ([theEvent type] === CPLeftMouseUp && ![[self window] acceptsMouseMovedEvents]))
|
||||
{
|
||||
[[CPCursor arrowCursor] set];
|
||||
return;
|
||||
}
|
||||
|
||||
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
||||
mouseOverLocation = CGPointMake(MAX(mouseLocation.x - CPTableHeaderViewResizeZone, 0.0), mouseLocation.y),
|
||||
overColumn = [self columnAtPoint:mouseOverLocation];
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* CPTrackingArea.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Didier Korthoudt.
|
||||
* Copyright 2015, Cappuccino Project.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
|
||||
@class CPView
|
||||
|
||||
/* @group CPTrackingAreaOptions */
|
||||
@typedef CPTrackingAreaOptions
|
||||
CPTrackingMouseEnteredAndExited = 1 << 1;
|
||||
CPTrackingMouseMoved = 1 << 2;
|
||||
CPTrackingCursorUpdate = 1 << 3;
|
||||
CPTrackingActiveWhenFirstResponder = 1 << 4;
|
||||
CPTrackingActiveInKeyWindow = 1 << 5;
|
||||
CPTrackingActiveInActiveApp = 1 << 6;
|
||||
CPTrackingActiveAlways = 1 << 7;
|
||||
CPTrackingAssumeInside = 1 << 8;
|
||||
CPTrackingInVisibleRect = 1 << 9;
|
||||
CPTrackingEnabledDuringMouseDrag = 1 << 10;
|
||||
|
||||
var CPTrackingAreaViewRectKey = @"CPTrackinkAreaViewRectKey",
|
||||
CPTrackingAreaOptionsKey = @"CPTrackingAreaOptionsKey",
|
||||
CPTrackingAreaOwnerKey = @"CPTrackingAreaOwnerKey",
|
||||
CPTrackingAreaUserInfoKey = @"CPTrackingAreaUserInfoKey",
|
||||
CPTrackingAreaReferencingViewKey = @"CPTrackingAreaReferencingViewKey",
|
||||
CPTrackingAreaWindowRect = @"CPTrackingAreaWindowRect";
|
||||
|
||||
CPTrackingOwnerImplementsMouseEntered = 1 << 1;
|
||||
CPTrackingOwnerImplementsMouseExited = 1 << 2;
|
||||
CPTrackingOwnerImplementsMouseMoved = 1 << 3;
|
||||
CPTrackingOwnerImplementsCursorUpdate = 1 << 4;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
|
||||
A CPTrackingArea defines a region of view that generates mouse-tracking and
|
||||
cursor-update events when the mouse is over that region.
|
||||
*/
|
||||
@implementation CPTrackingArea : CPObject
|
||||
{
|
||||
CGRect _viewRect @accessors(getter=rect);
|
||||
CPTrackingAreaOptions _options @accessors(getter=options);
|
||||
id _owner @accessors(getter=owner);
|
||||
CPDictionary _userInfo @accessors(getter=userInfo);
|
||||
|
||||
CPView _referencingView @accessors(property=view);
|
||||
CGRect _windowRect @accessors(getter=windowRect);
|
||||
|
||||
unsigned _implementedOwnerMethods @accessors(getter=implementedOwnerMethods);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
/*!
|
||||
Initializes and returns an object defining a region of a view to receive mouse-tracking events, mouse-moved events, cursor-update events, or possibly
|
||||
all these events.
|
||||
*/
|
||||
- (CPTrackingArea)initWithRect:(CGRect)aRect options:(CPTrackingAreaOptions)options owner:(id)owner userInfo:(CPDictionary)userInfo
|
||||
{
|
||||
if (owner === nil)
|
||||
[CPException raise:CPInternalInconsistencyException reason:"No owner specified"];
|
||||
|
||||
if (options === 0)
|
||||
[CPException raise:CPInternalInconsistencyException reason:"Invalid CPTrackingArea options"];
|
||||
|
||||
// Check options:
|
||||
// - at least one of CPTrackingMouseEnteredAndExited, CPTrackingMouseMoved, CPTrackingCursorUpdate
|
||||
// - exactly one of CPTrackingActiveWhenFirstResponder, CPTrackingActiveInKeyWindow, CPTrackingActiveInActiveApp, CPTrackingActiveAlways
|
||||
// - no check on CPTrackingAssumeInside, CPTrackingInVisibleRect, CPTrackingEnableDuringMouseDrag
|
||||
|
||||
if (!((options & CPTrackingMouseEnteredAndExited) || (options & CPTrackingMouseMoved) || (options & CPTrackingCursorUpdate)))
|
||||
[CPException raise:CPInternalInconsistencyException reason:"Invalid CPTrackingAreaOptions: must use at least one of [CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingCursorUpdate]"];
|
||||
|
||||
if ((((options & CPTrackingActiveWhenFirstResponder) > 0) + ((options & CPTrackingActiveInKeyWindow) > 0) + ((options & CPTrackingActiveInActiveApp) > 0) + ((options & CPTrackingActiveAlways) > 0)) !== 1)
|
||||
[CPException raise:CPInternalInconsistencyException reason:"Tracking area options may only specify one of [CPTrackingActiveWhenFirstResponder | CPTrackingActiveInKeyWindow | CPTrackingActiveInActiveApp | CPTrackingActiveAlways]."];
|
||||
|
||||
if (self = [super init])
|
||||
{
|
||||
_viewRect = aRect;
|
||||
_options = options;
|
||||
_owner = owner;
|
||||
_userInfo = userInfo;
|
||||
|
||||
// Cache owner implemented methods
|
||||
|
||||
if ([_owner respondsToSelector:@selector(mouseEntered:)])
|
||||
_implementedOwnerMethods |= CPTrackingOwnerImplementsMouseEntered;
|
||||
|
||||
if ([_owner respondsToSelector:@selector(mouseExited:)])
|
||||
_implementedOwnerMethods |= CPTrackingOwnerImplementsMouseExited;
|
||||
|
||||
if ([_owner respondsToSelector:@selector(mouseMoved:)])
|
||||
_implementedOwnerMethods |= CPTrackingOwnerImplementsMouseMoved;
|
||||
|
||||
if ([_owner respondsToSelector:@selector(cursorUpdate:)])
|
||||
_implementedOwnerMethods |= CPTrackingOwnerImplementsCursorUpdate;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Implementation
|
||||
|
||||
- (void)_updateWindowRect
|
||||
{
|
||||
_windowRect = [_referencingView convertRect:((_options & CPTrackingInVisibleRect) ? [_referencingView visibleRect] : _viewRect) toView:[[_referencingView window] _windowView]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark CPCoding
|
||||
|
||||
@implementation CPTrackingArea (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_viewRect = [aCoder decodeObjectForKey:CPTrackingAreaViewRectKey];
|
||||
_options = [aCoder decodeObjectForKey:CPTrackingAreaOptionsKey];
|
||||
_owner = [aCoder decodeObjectForKey:CPTrackingAreaOwnerKey];
|
||||
_userInfo = [aCoder decodeObjectForKey:CPTrackingAreaUserInfoKey];
|
||||
_referencingView = [aCoder decodeObjectForKey:CPTrackingAreaReferencingViewKey];
|
||||
_windowRect = [aCoder decodeObjectForKey:CPTrackingAreaWindowRect];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[aCoder encodeObject:_viewRect forKey:CPTrackingAreaViewRectKey];
|
||||
[aCoder encodeObject:_options forKey:CPTrackingAreaOptionsKey];
|
||||
[aCoder encodeObject:_owner forKey:CPTrackingAreaOwnerKey];
|
||||
[aCoder encodeObject:_userInfo forKey:CPTrackingAreaUserInfoKey];
|
||||
[aCoder encodeObject:_referencingView forKey:CPTrackingAreaReferencingViewKey];
|
||||
[aCoder encodeObject:_windowRect forKey:CPTrackingAreaWindowRect];
|
||||
}
|
||||
|
||||
@end
|
||||
+188
@@ -32,6 +32,7 @@
|
||||
@import "CPGraphicsContext.j"
|
||||
@import "CPResponder.j"
|
||||
@import "CPTheme.j"
|
||||
@import "CPTrackingArea.j"
|
||||
@import "CPWindow_Constants.j"
|
||||
@import "_CPDisplayServer.j"
|
||||
|
||||
@@ -239,6 +240,9 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
BOOL _allowsVibrancy @accessors(property=allowsVibrancy);
|
||||
CPAppearance _appearance @accessors(getter=appearance);
|
||||
CPAppearance _effectiveAppearance;
|
||||
|
||||
CPMutableArray _trackingAreas @accessors(getter=trackingAreas, copy);
|
||||
BOOL _inhibitUpdateTrackingAreas;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -352,6 +356,8 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
_registeredDraggedTypes = [CPSet set];
|
||||
_registeredDraggedTypesArray = [];
|
||||
|
||||
_trackingAreas = [];
|
||||
|
||||
_tag = -1;
|
||||
|
||||
_frame = CGRectMakeCopy(aFrame);
|
||||
@@ -799,8 +805,30 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
[_window _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
|
||||
[aWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes];
|
||||
}
|
||||
|
||||
// View must be removed from the current window viewsWithTrackingAreas
|
||||
if (_window && (_trackingAreas.length > 0))
|
||||
[_window _removeTrackingAreaView:self];
|
||||
|
||||
_window = aWindow;
|
||||
|
||||
if (_window)
|
||||
{
|
||||
var owners;
|
||||
|
||||
if (_trackingAreas.length > 0)
|
||||
{
|
||||
// View must be added to the new window viewsWithTrackingAreas
|
||||
[_window _addTrackingAreaView:self];
|
||||
owners = [self _calcTrackingAreaOwners];
|
||||
}
|
||||
else
|
||||
owners = [self];
|
||||
|
||||
// Notify that view tracking areas should be updated
|
||||
// Cocoa doesn't notify on leaving a window
|
||||
[self _updateTrackingAreasForOwners:owners];
|
||||
}
|
||||
|
||||
var count = [_subviews count];
|
||||
|
||||
@@ -994,6 +1022,9 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
if (_isSuperviewAClipView)
|
||||
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
|
||||
|
||||
if (!_inhibitUpdateTrackingAreas)
|
||||
[self _updateTrackingAreas];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1064,6 +1095,9 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, transform, origin.x, origin.y);
|
||||
#endif
|
||||
|
||||
if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[self _updateTrackingAreas];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1215,6 +1249,9 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
|
||||
|
||||
if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[self _updateTrackingAreas];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1261,6 +1298,9 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
if (_isSuperviewAClipView)
|
||||
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
|
||||
|
||||
if (!_inhibitUpdateTrackingAreas)
|
||||
[self _updateTrackingAreas];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1326,6 +1366,9 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
|
||||
|
||||
if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[self _updateTrackingAreas];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1367,6 +1410,9 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
|
||||
|
||||
if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[self _updateTrackingAreas];
|
||||
}
|
||||
|
||||
|
||||
@@ -3401,6 +3447,141 @@ setBoundsOrigin:
|
||||
*/}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPView (TrackingAreaAdditions)
|
||||
|
||||
- (void)addTrackingArea:(CPTrackingArea)trackingArea
|
||||
{
|
||||
// Consistency check
|
||||
if (!trackingArea || [_trackingAreas containsObjectIdenticalTo:trackingArea])
|
||||
return;
|
||||
|
||||
if ([trackingArea view])
|
||||
[CPException raise:CPInternalInconsistencyException reason:"Tracking area has already been added to another view."];
|
||||
|
||||
[_trackingAreas addObject:trackingArea];
|
||||
[trackingArea setView:self];
|
||||
|
||||
if (_window)
|
||||
[_window _addTrackingArea:trackingArea];
|
||||
|
||||
[trackingArea _updateWindowRect];
|
||||
}
|
||||
|
||||
- (void)removeTrackingArea:(CPTrackingArea)trackingArea
|
||||
{
|
||||
// Consistency check
|
||||
if (!trackingArea)
|
||||
return;
|
||||
|
||||
if (![_trackingAreas containsObjectIdenticalTo:trackingArea])
|
||||
[CPException raise:CPInternalInconsistencyException reason:"Trying to remove unreferenced trackingArea"];
|
||||
|
||||
[self _removeTrackingArea:trackingArea];
|
||||
}
|
||||
|
||||
/*!
|
||||
Invoked automatically when the view’s geometry changes such that its tracking areas need to be recalculated.
|
||||
|
||||
You should override this method to remove out of date tracking areas and add recomputed tracking areas;
|
||||
|
||||
Cocoa calls this on every view, whereas they have tracking area(s) or not.
|
||||
Cappuccino behaves differently :
|
||||
- updateTrackingAreas is called when placing a view in the view hierarchy (that is in a window)
|
||||
- if you have only CPTrackingInVisibleRect tracking areas attached to a view, it will not be called again (until you move the view in the hierarchy)
|
||||
- if you have at least one non-CPTrackingInVisibleRect tracking area attached, it will be called every time the view geometry could be modified
|
||||
You don't have to touch to CPTrackingInVisibleRect tracking areas, they will be automatically updated
|
||||
|
||||
Please note that it is the owner of a tracking area who is called for updateTrackingAreas.
|
||||
But, if a view without any tracking area is inserted in the view hierarchy (that is, in a window), the view is called for updateTrackingAreas.
|
||||
This enables you to use updateTrackingArea to initially attach your tracking areas to the view.
|
||||
*/
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
This utility method is intended for CPView subclasses overriding updateTrackingAreas
|
||||
|
||||
Typical use would be :
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
[self removeAllTrackingAreas];
|
||||
|
||||
... add your specific updated tracking areas ...
|
||||
}
|
||||
|
||||
*/
|
||||
- (void)removeAllTrackingAreas
|
||||
{
|
||||
while (_trackingAreas.length > 0)
|
||||
[self _removeTrackingArea:_trackingAreas[0]];
|
||||
}
|
||||
|
||||
// Internal methods
|
||||
|
||||
- (void)_removeTrackingArea:(CPTrackingArea)trackingArea
|
||||
{
|
||||
if (_window)
|
||||
[_window _removeTrackingArea:trackingArea];
|
||||
|
||||
[trackingArea setView:nil];
|
||||
[_trackingAreas removeObjectIdenticalTo:trackingArea];
|
||||
}
|
||||
|
||||
- (void)_updateTrackingAreas
|
||||
{
|
||||
_inhibitUpdateTrackingAreas = YES;
|
||||
|
||||
[self _recursivelyUpdateTrackingAreas];
|
||||
|
||||
_inhibitUpdateTrackingAreas = NO;
|
||||
}
|
||||
|
||||
- (void)_recursivelyUpdateTrackingAreas
|
||||
{
|
||||
[self _updateTrackingAreasForOwners:[self _calcTrackingAreaOwners]];
|
||||
|
||||
for (var i = 0; i < _subviews.length; i++)
|
||||
[_subviews[i] _recursivelyUpdateTrackingAreas];
|
||||
}
|
||||
|
||||
- (CPArray)_calcTrackingAreaOwners
|
||||
{
|
||||
// First search all owners that must be notified
|
||||
// Remark: 99.99% of time, the only owner will be the view itself
|
||||
// In the same time, update the rects of InVisibleRect tracking areas
|
||||
|
||||
var owners = [];
|
||||
|
||||
for (var i = 0; i < _trackingAreas.length; i++)
|
||||
{
|
||||
var trackingArea = _trackingAreas[i];
|
||||
|
||||
if ([trackingArea options] & CPTrackingInVisibleRect)
|
||||
[trackingArea _updateWindowRect];
|
||||
|
||||
else
|
||||
{
|
||||
var owner = [trackingArea owner];
|
||||
|
||||
if (![owners containsObjectIdenticalTo:owner])
|
||||
[owners addObject:owner];
|
||||
}
|
||||
}
|
||||
|
||||
return owners;
|
||||
}
|
||||
|
||||
- (void)_updateTrackingAreasForOwners:(CPArray)owners
|
||||
{
|
||||
for (var i = 0; i < owners.length; i++)
|
||||
[owners[i] updateTrackingAreas];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
@@ -3423,6 +3604,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
CPViewSizeScaleKey = @"CPViewSizeScaleKey",
|
||||
CPViewIsScaledKey = @"CPViewIsScaledKey",
|
||||
CPViewAppearanceKey = @"CPViewAppearanceKey";
|
||||
CPViewTrackingAreasKey = @"CPViewTrackingAreasKey";
|
||||
|
||||
@implementation CPView (CPCoding)
|
||||
|
||||
@@ -3450,6 +3632,11 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
|
||||
if (self)
|
||||
{
|
||||
_trackingAreas = [aCoder decodeObjectForKey:CPViewTrackingAreasKey];
|
||||
|
||||
if (!_trackingAreas)
|
||||
_trackingAreas = [];
|
||||
|
||||
// We have to manually check because it may be 0, so we can't use ||
|
||||
_tag = [aCoder containsValueForKey:CPViewTagKey] ? [aCoder decodeIntForKey:CPViewTagKey] : -1;
|
||||
_identifier = [aCoder decodeObjectForKey:CPReuseIdentifierKey];
|
||||
@@ -3607,6 +3794,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
[aCoder encodeSize:[self _hierarchyScaleSize] forKey:CPViewSizeScaleKey];
|
||||
[aCoder encodeBool:_isScaled forKey:CPViewIsScaledKey];
|
||||
[aCoder encodeObject:_appearance forKey:CPViewAppearanceKey];
|
||||
[aCoder encodeObject:_trackingAreas forKey:CPViewTrackingAreasKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+404
-51
@@ -36,6 +36,7 @@
|
||||
@import "CPResponder.j"
|
||||
@import "CPScreen.j"
|
||||
@import "CPText.j"
|
||||
@import "CPTrackingArea.j"
|
||||
@import "CPView.j"
|
||||
@import "CPWindow_Constants.j"
|
||||
@import "_CPBorderlessBridgeWindowView.j"
|
||||
@@ -198,6 +199,10 @@ var CPWindowActionMessageKeys = [
|
||||
CPView _toolbarView;
|
||||
|
||||
CPArray _mouseEnteredStack;
|
||||
CPArray _cursorUpdateStack;
|
||||
CPArray _trackingAreaViews;
|
||||
id _activeCursorTrackingArea;
|
||||
CPArray _queuedTrackingEvents;
|
||||
CPView _leftMouseDownView;
|
||||
CPView _rightMouseDownView;
|
||||
|
||||
@@ -335,6 +340,12 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[self setLevel:CPNormalWindowLevel];
|
||||
|
||||
_trackingAreaViews = [];
|
||||
_mouseEnteredStack = [];
|
||||
_cursorUpdateStack = [];
|
||||
_queuedTrackingEvents = [];
|
||||
_activeCursorTrackingArea = nil;
|
||||
|
||||
// Create our border view which is the actual root of our view hierarchy.
|
||||
_windowView = [[windowViewClass alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)) styleMask:aStyleMask];
|
||||
|
||||
@@ -557,6 +568,11 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
}
|
||||
|
||||
- (CPView)_windowView
|
||||
{
|
||||
return _windowView;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the receiver as a full platform window. If you pass YES the CPWindow instance will fill the entire browser content area,
|
||||
otherwise the CPWindow will be a window inside of your browser window which the user can drag around, and resize (if you allow).
|
||||
@@ -1923,6 +1939,9 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
_leftMouseDownView = nil;
|
||||
|
||||
// If mouseUp ends a drag operation, send delayed events for tracking views under the mouse, then flush delayed events
|
||||
[self _flushTrackingEventQueueForMouseAt:point];
|
||||
|
||||
return;
|
||||
|
||||
case CPLeftMouseDown:
|
||||
@@ -1958,6 +1977,11 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
case CPLeftMouseDragged:
|
||||
case CPRightMouseDragged:
|
||||
// First, we search for any tracking area requesting CPTrackingEnabledDuringMouseDrag.
|
||||
// At the same time, we update the entered stack.
|
||||
[self _handleTrackingAreaEvent:anEvent];
|
||||
|
||||
// Normal mouseDragged workflow
|
||||
if (!_leftMouseDownView)
|
||||
return [[_windowView hitTest:point] mouseDragged:anEvent];
|
||||
|
||||
@@ -1976,61 +2000,12 @@ CPTexturedBackgroundWindowMask
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
|
||||
case CPMouseMoved:
|
||||
[_windowView setCursorForLocation:point resizing:NO];
|
||||
|
||||
// Ignore mouse moves for parents of sheets
|
||||
if (!_acceptsMouseMovedEvents || sheet)
|
||||
return;
|
||||
|
||||
if (!_mouseEnteredStack)
|
||||
_mouseEnteredStack = [];
|
||||
|
||||
var hitTestView = [_windowView hitTest:point];
|
||||
|
||||
if ([_mouseEnteredStack count] && [_mouseEnteredStack lastObject] === hitTestView)
|
||||
return [hitTestView mouseMoved:anEvent];
|
||||
|
||||
var view = hitTestView,
|
||||
mouseEnteredStack = [];
|
||||
|
||||
while (view)
|
||||
{
|
||||
mouseEnteredStack.unshift(view);
|
||||
|
||||
view = [view superview];
|
||||
}
|
||||
|
||||
var deviation = MIN(_mouseEnteredStack.length, mouseEnteredStack.length);
|
||||
|
||||
while (deviation--)
|
||||
if (_mouseEnteredStack[deviation] === mouseEnteredStack[deviation])
|
||||
break;
|
||||
|
||||
var index = deviation + 1,
|
||||
count = _mouseEnteredStack.length;
|
||||
|
||||
if (index < count)
|
||||
{
|
||||
var event = [CPEvent mouseEventWithType:CPMouseExited location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
|
||||
|
||||
for (; index < count; ++index)
|
||||
[_mouseEnteredStack[index] mouseExited:event];
|
||||
}
|
||||
|
||||
index = deviation + 1;
|
||||
count = mouseEnteredStack.length;
|
||||
|
||||
if (index < count)
|
||||
{
|
||||
var event = [CPEvent mouseEventWithType:CPMouseEntered location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
|
||||
|
||||
for (; index < count; ++index)
|
||||
[mouseEnteredStack[index] mouseEntered:event];
|
||||
}
|
||||
|
||||
_mouseEnteredStack = mouseEnteredStack;
|
||||
|
||||
[hitTestView mouseMoved:anEvent];
|
||||
|
||||
[self _handleTrackingAreaEvent:anEvent];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3844,6 +3819,384 @@ var interpolate = function(fromValue, toValue, progress)
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPWindow (TrackingAreaAdditions)
|
||||
|
||||
- (void)_addTrackingAreaView:(CPView)aView
|
||||
{
|
||||
var trackingAreas = [aView trackingAreas];
|
||||
|
||||
for (var i = 0; i < trackingAreas.length; i++)
|
||||
[self _addTrackingArea:trackingAreas[i]];
|
||||
}
|
||||
|
||||
- (void)_removeTrackingAreaView:(CPView)aView
|
||||
{
|
||||
var trackingAreas = [aView trackingAreas];
|
||||
|
||||
for (var i = 0; i < trackingAreas.length; i++)
|
||||
[self _removeTrackingArea:trackingAreas[i]];
|
||||
}
|
||||
|
||||
- (void)_addTrackingArea:(CPTrackingArea)trackingArea
|
||||
{
|
||||
var trackingAreaView = [trackingArea view];
|
||||
|
||||
if (![_trackingAreaViews containsObjectIdenticalTo:trackingAreaView])
|
||||
[_trackingAreaViews addObject:trackingAreaView];
|
||||
|
||||
// If CPTrackingAssumeInside option is set, put the tracking area in the _mouseEnteredStack
|
||||
|
||||
if ([trackingArea options] & CPTrackingAssumeInside)
|
||||
[_mouseEnteredStack addObject:trackingArea];
|
||||
}
|
||||
|
||||
- (void)_removeTrackingArea:(CPTrackingArea)trackingArea
|
||||
{
|
||||
// If mouse is in the tracking area, we remove it from the stack to avoid to fire a future mouseExited event
|
||||
|
||||
[_mouseEnteredStack removeObjectIdenticalTo:trackingArea];
|
||||
|
||||
var trackingAreaView = [trackingArea view];
|
||||
|
||||
[_trackingAreaViews removeObjectIdenticalTo:trackingAreaView];
|
||||
}
|
||||
|
||||
- (void)_handleTrackingAreaEvent:(CPEvent)anEvent
|
||||
{
|
||||
var mouseEnteredStack = [],
|
||||
cursorUpdateStack = [],
|
||||
point = [anEvent locationInWindow],
|
||||
dragging = ([anEvent type] !== CPMouseMoved);
|
||||
|
||||
// Handle mouse entering tracking areas (and calc mouseEnteredStack and cursorUpdateStack)
|
||||
|
||||
[self _handleMouseMovedAndEnteredEventsForEvent:anEvent atPoint:point dragging:dragging mouseEnteredStack:mouseEnteredStack cursorUpdateStack:cursorUpdateStack];
|
||||
|
||||
// Handle mouse exiting tracking areas
|
||||
|
||||
[self _handleMouseExitedEventsForEvent:anEvent atPoint:point dragging:dragging mouseEnteredStack:mouseEnteredStack];
|
||||
|
||||
// Cursor update
|
||||
|
||||
if (cursorUpdateStack.length > 0)
|
||||
{
|
||||
[self _handleCursorUpdateEventsForEvent:anEvent atPoint:point dragging:dragging cursorUpdateStack:cursorUpdateStack];
|
||||
}
|
||||
else if (!dragging)
|
||||
{
|
||||
// Here, we are outsite the window content view tracking area, so let _windowView set the cursor (resize cursor, ...)
|
||||
|
||||
[_windowView setCursorForLocation:point resizing:NO];
|
||||
_activeCursorTrackingArea = nil;
|
||||
}
|
||||
|
||||
// Prepare for next call
|
||||
|
||||
_mouseEnteredStack = mouseEnteredStack;
|
||||
_cursorUpdateStack = cursorUpdateStack;
|
||||
}
|
||||
|
||||
- (void)_handleMouseMovedAndEnteredEventsForEvent:(CPEvent)anEvent atPoint:(CGPoint)point dragging:(BOOL)dragging mouseEnteredStack:(CPArray)mouseEnteredStack cursorUpdateStack:(CPArray)cursorUpdateStack
|
||||
{
|
||||
var isKeyWindow = [self isKeyWindow];
|
||||
|
||||
for (var i = 0; i < _trackingAreaViews.length; i++)
|
||||
{
|
||||
var aView = _trackingAreaViews[i],
|
||||
trackingAreas = [aView trackingAreas];
|
||||
|
||||
if ([aView isHidden])
|
||||
continue;
|
||||
|
||||
for (var j = 0; j < trackingAreas.length; j++)
|
||||
{
|
||||
var aTrackingArea = trackingAreas[j],
|
||||
trackingOptions = [aTrackingArea options],
|
||||
trackingImplementedMethods = [aTrackingArea implementedOwnerMethods];
|
||||
|
||||
if (!(((trackingOptions & CPTrackingActiveAlways) ||
|
||||
(trackingOptions & CPTrackingActiveInActiveApp) ||
|
||||
((trackingOptions & CPTrackingActiveInKeyWindow) && isKeyWindow) ||
|
||||
((trackingOptions & CPTrackingActiveWhenFirstResponder) && isKeyWindow && (_firstResponder === aView))) &&
|
||||
(CGRectContainsPoint([aTrackingArea windowRect], point))))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
[mouseEnteredStack addObject:aTrackingArea];
|
||||
|
||||
if ([_mouseEnteredStack containsObjectIdenticalTo:aTrackingArea])
|
||||
{
|
||||
// Mouse was already in this rect so it's a mouseMoved
|
||||
|
||||
if (!dragging && (trackingOptions & CPTrackingMouseMoved) && (trackingImplementedMethods & CPTrackingOwnerImplementsMouseMoved))
|
||||
[[aTrackingArea owner] mouseMoved:anEvent];
|
||||
}
|
||||
else if ((trackingOptions & CPTrackingMouseEnteredAndExited) && (trackingImplementedMethods & CPTrackingOwnerImplementsMouseEntered))
|
||||
{
|
||||
var mouseEnteredEvent = [CPEvent enterExitEventWithType:CPMouseEntered
|
||||
location:point
|
||||
modifierFlags:[anEvent modifierFlags]
|
||||
timestamp:[anEvent timestamp]
|
||||
windowNumber:_windowNumber
|
||||
context:nil
|
||||
eventNumber:-1
|
||||
trackingArea:aTrackingArea];
|
||||
|
||||
if (dragging && !(trackingOptions & CPTrackingEnabledDuringMouseDrag))
|
||||
[self _queueTrackingEvent:mouseEnteredEvent];
|
||||
else
|
||||
[[aTrackingArea owner] mouseEntered:mouseEnteredEvent];
|
||||
}
|
||||
|
||||
if ((trackingOptions & CPTrackingCursorUpdate) && (trackingImplementedMethods & CPTrackingOwnerImplementsCursorUpdate))
|
||||
[cursorUpdateStack addObject:aTrackingArea];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_handleMouseExitedEventsForEvent:(CPEvent)anEvent atPoint:(CGPoint)point dragging:(BOOL)dragging mouseEnteredStack:(CPArray)mouseEnteredStack
|
||||
{
|
||||
// Search for exited views (were in _mouseEnteredStack but no more in mouseEnteredStack)
|
||||
|
||||
for (var i = 0; i < _mouseEnteredStack.length; i++)
|
||||
{
|
||||
var aTrackingArea = _mouseEnteredStack[i],
|
||||
trackingOptions = [aTrackingArea options];
|
||||
|
||||
if ([mouseEnteredStack containsObjectIdenticalTo:aTrackingArea])
|
||||
continue;
|
||||
|
||||
// Mouse is no more in this area so it's a mouseExited
|
||||
|
||||
if ((trackingOptions & CPTrackingMouseEnteredAndExited) && ([aTrackingArea implementedOwnerMethods] & CPTrackingOwnerImplementsMouseExited))
|
||||
{
|
||||
var mouseExitedEvent = [CPEvent enterExitEventWithType:CPMouseExited
|
||||
location:point
|
||||
modifierFlags:[anEvent modifierFlags]
|
||||
timestamp:[anEvent timestamp]
|
||||
windowNumber:_windowNumber
|
||||
context:nil
|
||||
eventNumber:-1
|
||||
trackingArea:aTrackingArea];
|
||||
|
||||
if (dragging && !(trackingOptions & CPTrackingEnabledDuringMouseDrag))
|
||||
[self _queueTrackingEvent:mouseExitedEvent];
|
||||
else
|
||||
[[aTrackingArea owner] mouseExited:mouseExitedEvent];
|
||||
}
|
||||
|
||||
// If this is the active cursor area, we reset _cursorUpdateStack so a new active area will be computed
|
||||
|
||||
if (aTrackingArea === _activeCursorTrackingArea)
|
||||
{
|
||||
_cursorUpdateStack = [];
|
||||
_activeCursorTrackingArea = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_handleCursorUpdateEventsForEvent:(CPEvent)anEvent atPoint:(CGPoint)point dragging:(BOOL)dragging cursorUpdateStack:(CPArray)cursorUpdateStack
|
||||
{
|
||||
var overlappingTrackingAreas = [];
|
||||
|
||||
for (var i = 0; i < cursorUpdateStack.length; i++)
|
||||
{
|
||||
var aTrackingArea = cursorUpdateStack[i];
|
||||
|
||||
if ((![_cursorUpdateStack containsObjectIdenticalTo:aTrackingArea]) || (aTrackingArea === _activeCursorTrackingArea))
|
||||
[overlappingTrackingAreas addObject:aTrackingArea];
|
||||
}
|
||||
|
||||
var nbOverlappingTrackingAreas = overlappingTrackingAreas.length;
|
||||
|
||||
if (nbOverlappingTrackingAreas > 0)
|
||||
{
|
||||
var frontmostTrackingArea = overlappingTrackingAreas[0],
|
||||
frontmostView = [frontmostTrackingArea view];
|
||||
|
||||
for (var i = 1; i < nbOverlappingTrackingAreas; i++)
|
||||
{
|
||||
var aTrackingArea = overlappingTrackingAreas[i],
|
||||
aView = [aTrackingArea view];
|
||||
|
||||
// First, if aView is _windowView, skip to next overlapping tracking area
|
||||
// as _windowView can't be the frontmost view if there's multiple overlapping tracking areas.
|
||||
|
||||
if (aView === _windowView)
|
||||
continue;
|
||||
|
||||
// Then, if frontmostView is _windowView, aView must become frontmostView
|
||||
|
||||
if (frontmostView === _windowView)
|
||||
{
|
||||
frontmostTrackingArea = aTrackingArea;
|
||||
frontmostView = aView;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Next verify if aView is a subview of frontmostView
|
||||
// If so, it's our new frontmost view
|
||||
|
||||
var searchingView = aView;
|
||||
|
||||
while ((searchingView !== _contentView) && ([searchingView superview] !== frontmostView))
|
||||
searchingView = [searchingView superview];
|
||||
|
||||
if (searchingView !== _contentView)
|
||||
{
|
||||
frontmostTrackingArea = aTrackingArea;
|
||||
frontmostView = aView;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// aView is not a subview of frontmostView
|
||||
// Search in view hierarchy which one will be over the other
|
||||
// (this is done by comparing their draw order)
|
||||
|
||||
var firstView = frontmostView,
|
||||
firstSuperview = [firstView superview];
|
||||
|
||||
while (firstView !== _contentView)
|
||||
{
|
||||
var secondView = aView,
|
||||
secondSuperview = [secondView superview];
|
||||
|
||||
while ((secondSuperview !== _contentView) && (firstSuperview !== secondSuperview))
|
||||
{
|
||||
secondView = secondSuperview;
|
||||
secondSuperview = [secondView superview];
|
||||
}
|
||||
|
||||
if (firstSuperview === secondSuperview)
|
||||
break;
|
||||
|
||||
firstView = firstSuperview;
|
||||
firstSuperview = [firstView superview];
|
||||
}
|
||||
|
||||
if (firstSuperview !== secondSuperview)
|
||||
[CPException raise:CPInternalInconsistencyException reason:"Problem with view hierarchy"];
|
||||
|
||||
var firstSuperviewSubviews = [firstSuperview subviews],
|
||||
firstViewIndex = [firstSuperviewSubviews indexOfObject:firstView],
|
||||
secondViewIndex = [firstSuperviewSubviews indexOfObject:secondView];
|
||||
|
||||
if (secondViewIndex > firstViewIndex)
|
||||
{
|
||||
frontmostTrackingArea = aTrackingArea;
|
||||
frontmostView = aView;
|
||||
}
|
||||
}
|
||||
|
||||
if (frontmostTrackingArea !== _activeCursorTrackingArea)
|
||||
{
|
||||
var cursorUpdateEvent = [CPEvent enterExitEventWithType:CPCursorUpdate
|
||||
location:point
|
||||
modifierFlags:[anEvent modifierFlags]
|
||||
timestamp:[anEvent timestamp]
|
||||
windowNumber:_windowNumber
|
||||
context:nil
|
||||
eventNumber:-1
|
||||
trackingArea:frontmostTrackingArea];
|
||||
|
||||
if (dragging)
|
||||
[self _queueTrackingEvent:cursorUpdateEvent];
|
||||
else
|
||||
[[frontmostTrackingArea owner] cursorUpdate:cursorUpdateEvent];
|
||||
|
||||
_activeCursorTrackingArea = frontmostTrackingArea;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_queueTrackingEvent:(CPEvent)anEvent
|
||||
{
|
||||
// This will put a tracking event in the _queuedTrackingEvents queue.
|
||||
//
|
||||
// We optimize this queue with this policy :
|
||||
// - if mouseEntered, search if queue contains a previous mouseExited for the same tracking area. If so, discard both.
|
||||
// - if mouseExited, search if queue contains a previous mouseEntered for the same tracking area. If so, discard both.
|
||||
//
|
||||
// This is not Cocoa way of doing as it would send every event.
|
||||
// But final result should be the same.
|
||||
|
||||
var eventType = [anEvent type],
|
||||
trackingArea = [anEvent trackingArea];
|
||||
|
||||
switch ([anEvent type])
|
||||
{
|
||||
case CPMouseEntered:
|
||||
for (var i = 0; i < _queuedTrackingEvents.length; i++)
|
||||
{
|
||||
var queuedEvent = _queuedTrackingEvents[i];
|
||||
|
||||
if (([queuedEvent trackingArea] === trackingArea) && ([queuedEvent type] === CPMouseExited))
|
||||
{
|
||||
[_queuedTrackingEvents removeObjectAtIndex:i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[_queuedTrackingEvents addObject:anEvent];
|
||||
break;
|
||||
|
||||
case CPMouseExited:
|
||||
for (var i = 0; i < _queuedTrackingEvents.length; i++)
|
||||
{
|
||||
var queuedEvent = _queuedTrackingEvents[i];
|
||||
|
||||
if (([queuedEvent trackingArea] === trackingArea) && ([queuedEvent type] === CPMouseEntered))
|
||||
{
|
||||
[_queuedTrackingEvents removeObjectAtIndex:i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[_queuedTrackingEvents addObject:anEvent];
|
||||
break;
|
||||
|
||||
case CPCursorUpdate:
|
||||
[_queuedTrackingEvents addObject:anEvent];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_flushTrackingEventQueueForMouseAt:(CGPoint)point
|
||||
{
|
||||
for (var i = 0; i < _queuedTrackingEvents.length; i++)
|
||||
{
|
||||
var queuedEvent = _queuedTrackingEvents[i],
|
||||
trackingArea = [queuedEvent trackingArea],
|
||||
trackingOwner = [trackingArea owner];
|
||||
|
||||
switch ([queuedEvent type])
|
||||
{
|
||||
case CPMouseEntered:
|
||||
[trackingOwner mouseEntered:queuedEvent];
|
||||
break;
|
||||
|
||||
case CPMouseExited:
|
||||
[trackingOwner mouseExited:queuedEvent];
|
||||
break;
|
||||
|
||||
case CPCursorUpdate:
|
||||
[trackingOwner updateTrackingAreas];
|
||||
|
||||
if (CGRectContainsPoint([trackingArea windowRect], point))
|
||||
[trackingOwner cursorUpdate:queuedEvent];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_queuedTrackingEvents = [];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
function _CPWindowFullPlatformWindowSessionMake(aWindowView, aContentRect, hasShadow, aLevel)
|
||||
{
|
||||
return { windowView:aWindowView, contentRect:aContentRect, hasShadow:hasShadow, level:aLevel };
|
||||
|
||||
@@ -353,7 +353,9 @@ _CPWindowViewResizeSlop = 3;
|
||||
if ([theWindow isFullPlatformWindow] ||
|
||||
!(_styleMask & CPResizableWindowMask) ||
|
||||
(CPWindowResizeStyle !== CPWindowResizeStyleModern))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var globalPoint = [theWindow convertBaseToGlobal:aPoint],
|
||||
resizeRegion = isResizing ? _resizeRegion : [self resizeRegionForPoint:globalPoint],
|
||||
@@ -969,3 +971,18 @@ _CPWindowViewResizeSlop = 3;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPWindowView (TrackingAreaAdditions)
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
[self removeAllTrackingAreas];
|
||||
|
||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self contentRectForFrameRect:[self frame]]
|
||||
options:CPTrackingCursorUpdate | CPTrackingActiveInActiveApp
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
@import <AppKit/CPApplication.j>
|
||||
|
||||
var methodCalled;
|
||||
var updateTrackingAreasCalls,
|
||||
mouseEnteredCalls,
|
||||
mouseExitedCalls,
|
||||
mouseMovedCalls,
|
||||
cursorUpdateCalls,
|
||||
involvedViewForMouseEntered,
|
||||
involvedViewForMouseExited,
|
||||
involvedViewForCursorUpdate;
|
||||
|
||||
@implementation CPViewTest : OJTestCase
|
||||
{
|
||||
@@ -30,6 +38,7 @@ var methodCalled;
|
||||
[view3 setIdentifier:@"view3"];
|
||||
|
||||
methodCalled = [];
|
||||
updateTrackingAreasCalls = 0;
|
||||
|
||||
[super setUp];
|
||||
}
|
||||
@@ -886,6 +895,581 @@ var methodCalled;
|
||||
[self assert:nil equals:[view effectiveAppearance]];
|
||||
}
|
||||
|
||||
// TrackingAreaAdditions
|
||||
|
||||
- (void)testTrackingAreas
|
||||
{
|
||||
var trackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect owner:self userInfo:nil];
|
||||
|
||||
[self assert:0 equals:[[view trackingAreas] count] message:@"Initially, a view has no tracking area"];
|
||||
|
||||
//
|
||||
|
||||
[view addTrackingArea:trackingArea];
|
||||
[self assert:1 equals:[[view trackingAreas] count] message:@"After adding a tracking area"];
|
||||
[self assert:view equals:[trackingArea view] message:@"Tracking area should be linked to view"];
|
||||
|
||||
//
|
||||
|
||||
[view removeTrackingArea:trackingArea];
|
||||
[self assert:0 equals:[[view trackingAreas] count] message:@"After removing the only tracking area"];
|
||||
[self assert:nil equals:[trackingArea view] message:@"Tracking area should be unlinked"];
|
||||
|
||||
//
|
||||
|
||||
[view addTrackingArea:trackingArea];
|
||||
[view addTrackingArea:trackingArea];
|
||||
[view addTrackingArea:trackingArea];
|
||||
[self assert:1 equals:[[view trackingAreas] count] message:@"Adding the same tracking area multiple times should add it once"];
|
||||
[self assert:view equals:[trackingArea view] message:@"Tracking area should be linked to view"];
|
||||
|
||||
var trackingArea2 = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow owner:self userInfo:nil];
|
||||
|
||||
//
|
||||
|
||||
[view addTrackingArea:trackingArea2];
|
||||
[self assert:2 equals:[[view trackingAreas] count] message:@"After adding a second tracking area"];
|
||||
[self assert:view equals:[trackingArea2 view] message:@"Tracking area should be linked to view"];
|
||||
|
||||
//
|
||||
|
||||
[view removeAllTrackingAreas];
|
||||
[self assert:0 equals:[[view trackingAreas] count] message:@"After removing all tracking areas"];
|
||||
[self assert:nil equals:[trackingArea view] message:@"Tracking area should be unlinked"];
|
||||
[self assert:nil equals:[trackingArea2 view] message:@"Tracking area should be unlinked"];
|
||||
|
||||
//
|
||||
|
||||
[view addTrackingArea:trackingArea];
|
||||
|
||||
var contentView = [window contentView];
|
||||
|
||||
[contentView addSubview:view];
|
||||
[self assert:0 equals:updateTrackingAreasCalls message:@"Putting a view with a CPTrackingAreaInVisibleRect in a window should not call updateTrackingAreas"];
|
||||
|
||||
[view removeFromSuperview];
|
||||
|
||||
//
|
||||
|
||||
[view addTrackingArea:trackingArea2];
|
||||
[contentView addSubview:view];
|
||||
[self assert:1 equals:updateTrackingAreasCalls message:@"Putting a view with a non CPTrackingAreaInVisibleRect in a window should call updateTrackingAreas"];
|
||||
|
||||
[view removeAllTrackingAreas];
|
||||
|
||||
//
|
||||
|
||||
var viewTA = [[CPTrackingAreaView alloc] initWithFrame:CGRectMakeZero()];
|
||||
updateTrackingAreasCalls = 0;
|
||||
|
||||
[contentView addSubview:viewTA];
|
||||
[self assert:1 equals:updateTrackingAreasCalls message:@"Putting a view with no tracking areas in a window should call updateTrackingAreas"];
|
||||
|
||||
//
|
||||
|
||||
updateTrackingAreasCalls = 0;
|
||||
|
||||
[viewTA addTrackingArea:trackingArea];
|
||||
[viewTA setFrame:CGRectMake(10, 10, 10, 10)];
|
||||
[self assert:0 equals:updateTrackingAreasCalls message:@"Changing geometry of a view with a CPTrackingAreaInVisibleRect should not call updateTrackingAreas"];
|
||||
|
||||
//
|
||||
|
||||
updateTrackingAreasCalls = 0;
|
||||
|
||||
[viewTA addTrackingArea:trackingArea2];
|
||||
[viewTA setFrame:CGRectMake(20, 20, 20, 20)];
|
||||
[self assert:1 equals:updateTrackingAreasCalls message:@"Changing geometry of a view with a non CPTrackingAreaInVisibleRect should call updateTrackingAreas"];
|
||||
|
||||
//
|
||||
|
||||
var trackingAreaAll = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingCursorUpdate | CPTrackingActiveInActiveApp | CPTrackingInVisibleRect owner:viewTA userInfo:nil];
|
||||
|
||||
[viewTA removeAllTrackingAreas];
|
||||
[viewTA addTrackingArea:trackingAreaAll];
|
||||
|
||||
// Mouse enters the tracking area
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(21, 21) dragging:NO];
|
||||
|
||||
[self assert:1 equals:mouseEnteredCalls message:@"Mouse entering a tracking area should call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"Mouse entering a tracking area should not call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"Mouse entering a tracking area should not call mouseMoved"];
|
||||
[self assert:1 equals:cursorUpdateCalls message:@"Mouse entering a tracking area should call cursorUpdate"];
|
||||
|
||||
// Mouse moves in the tracking area
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(22, 22) dragging:NO];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"Mouse moving in a tracking area should not call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"Mouse moving in a tracking area should not call mouseExited"];
|
||||
[self assert:1 equals:mouseMovedCalls message:@"Mouse moving in a tracking area should call mouseMoved"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"Mouse moving in a tracking area should not call cursorUpdate"];
|
||||
|
||||
// Mouse exits from the tracking area
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(0, 0) dragging:NO];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"Mouse exiting from a tracking area should not call mouseEntered"];
|
||||
[self assert:1 equals:mouseExitedCalls message:@"Mouse exiting from a tracking area should call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"Mouse exiting from a tracking area should not call mouseMoved"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"Mouse exiting from a tracking area should not call cursorUpdate"];
|
||||
|
||||
// Mouse enters the tracking area while dragging
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(21, 21) dragging:YES];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"While dragging, mouse entering a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"While dragging, mouse entering a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"While dragging, mouse entering a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseMoved"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"While dragging, mouse entering a tracking area without CPTrackingEnabledDuringMouseDrag should not call cursorUpdate"];
|
||||
|
||||
// Mouse moves in the tracking area while dragging
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(22, 22) dragging:YES];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"While dragging, mouse moving in a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"While dragging, mouse moving in a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"While dragging, mouse moving in a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseMoved"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"While dragging, mouse moving in a tracking area without CPTrackingEnabledDuringMouseDrag should not call cursorUpdate"];
|
||||
|
||||
// Mouse exits from the tracking area while dragging
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(0, 0) dragging:YES];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"While dragging, mouse exiting from a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"While dragging, mouse exiting from a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"While dragging, mouse exiting from a tracking area without CPTrackingEnabledDuringMouseDrag should not call mouseMoved"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"While dragging, mouse exiting from a tracking area without CPTrackingEnabledDuringMouseDrag should not call cursorUpdate"];
|
||||
|
||||
//
|
||||
|
||||
var trackingAreaAllWithDrag = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingCursorUpdate | CPTrackingActiveInActiveApp | CPTrackingInVisibleRect | CPTrackingEnabledDuringMouseDrag owner:viewTA userInfo:nil];
|
||||
|
||||
[viewTA removeAllTrackingAreas];
|
||||
[viewTA addTrackingArea:trackingAreaAllWithDrag];
|
||||
|
||||
// Mouse enters the tracking area while dragging (option set)
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(21, 21) dragging:YES];
|
||||
|
||||
[self assert:1 equals:mouseEnteredCalls message:@"While dragging, mouse entering a tracking area with CPTrackingEnabledDuringMouseDrag should call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"While dragging, mouse entering a tracking area with CPTrackingEnabledDuringMouseDrag should not call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"While dragging, mouse entering a tracking area with CPTrackingEnabledDuringMouseDrag should not call mouseMoved"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"While dragging, mouse entering a tracking area with CPTrackingEnabledDuringMouseDrag should not call cursorUpdate"];
|
||||
|
||||
// Mouse moves in the tracking area while dragging (option set)
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(22, 22) dragging:YES];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"While dragging, mouse moving in a tracking area with CPTrackingEnabledDuringMouseDrag should not call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"While dragging, mouse moving in a tracking area with CPTrackingEnabledDuringMouseDrag should not call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"While dragging, mouse moving in a tracking area with CPTrackingEnabledDuringMouseDrag should not call mouseMoved"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"While dragging, mouse moving in a tracking area with CPTrackingEnabledDuringMouseDrag should not call cursorUpdate"];
|
||||
|
||||
// Mouse exits from the tracking area while dragging (option set)
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(0, 0) dragging:YES];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"While dragging, mouse exiting from a tracking area with CPTrackingEnabledDuringMouseDrag should not call mouseEntered"];
|
||||
[self assert:1 equals:mouseExitedCalls message:@"While dragging, mouse exiting from a tracking area with CPTrackingEnabledDuringMouseDrag should call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"While dragging, mouse exiting from a tracking area with CPTrackingEnabledDuringMouseDrag should not call mouseMoved"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"While dragging, mouse exiting from a tracking area with CPTrackingEnabledDuringMouseDrag should not call cursorUpdate"];
|
||||
|
||||
// Nested views
|
||||
|
||||
var innerViewTA = [[CPTrackingAreaView alloc] initWithFrame:CGRectMake(5, 5, 10, 10)];
|
||||
|
||||
[viewTA addSubview:innerViewTA];
|
||||
|
||||
var innerTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingCursorUpdate | CPTrackingActiveInActiveApp | CPTrackingInVisibleRect owner:innerViewTA userInfo:nil];
|
||||
|
||||
[innerViewTA addTrackingArea:innerTrackingArea];
|
||||
|
||||
// Mouse enters outer view
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(21, 21) dragging:NO];
|
||||
|
||||
[self assert:1 equals:mouseEnteredCalls message:@"Mouse entering outer tracking area should call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"Mouse entering outer tracking area should not call mouseExited"];
|
||||
[self assert:0 equals:mouseMovedCalls message:@"Mouse entering outer tracking area should not call mouseMoved"];
|
||||
[self assert:1 equals:cursorUpdateCalls message:@"Mouse entering outer tracking area should call cursorUpdate"];
|
||||
|
||||
// Mouse enters inner view
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(26, 26) dragging:NO];
|
||||
|
||||
[self assert:1 equals:mouseEnteredCalls message:@"Mouse entering inner tracking area should call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"Mouse entering inner tracking area should not call mouseExited"];
|
||||
[self assert:1 equals:mouseMovedCalls message:@"Mouse entering inner tracking area should call mouseMoved"];
|
||||
[self assert:1 equals:cursorUpdateCalls message:@"Mouse entering inner tracking area should call cursorUpdate"];
|
||||
|
||||
// Mouse moves in inner view
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(27, 27) dragging:NO];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"Mouse moving in inner tracking area should not call mouseEntered"];
|
||||
[self assert:0 equals:mouseExitedCalls message:@"Mouse moving in inner tracking area should not call mouseExited"];
|
||||
[self assert:2 equals:mouseMovedCalls message:@"Mouse moving in inner tracking area should call mouseMoved for both views"];
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"Mouse moving in inner tracking area should not call cursorUpdate"];
|
||||
|
||||
// Mouse leaves inner view but remains in outer view
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(36, 36) dragging:NO];
|
||||
|
||||
[self assert:0 equals:mouseEnteredCalls message:@"Mouse moving from inner to outer tracking area should not call mouseEntered"];
|
||||
[self assert:1 equals:mouseExitedCalls message:@"Mouse moving from inner to outer tracking area should call mouseExited (for inner)"];
|
||||
[self assert:1 equals:mouseMovedCalls message:@"Mouse moving from inner to outer tracking area should call mouseMoved (for outer)"];
|
||||
[self assert:1 equals:cursorUpdateCalls message:@"Mouse moving from inner to outer tracking area should call cursorUpdate (for outer)"];
|
||||
|
||||
[self assert:innerViewTA equals:involvedViewForMouseExited message:@"Inner view should receive mouseExited"];
|
||||
[self assert:viewTA equals:involvedViewForCursorUpdate message:@"Outer view should receive cursorUpdate"];
|
||||
|
||||
// Complex test for cursor update frontmost tracking area detection
|
||||
|
||||
var viewA = [[CPTrackingAreaView alloc] initWithFrame:CGRectMake(0, 30, 40, 40)];
|
||||
var viewB = [[CPTrackingAreaView alloc] initWithFrame:CGRectMake(30, 20, 40, 40)];
|
||||
var viewC = [[CPTrackingAreaView alloc] initWithFrame:CGRectMake(10, 0, 40, 40)];
|
||||
|
||||
[contentView setSubviews:[CPArray array]];
|
||||
[contentView addSubview:viewA];
|
||||
[contentView addSubview:viewB];
|
||||
[contentView addSubview:viewC];
|
||||
|
||||
var subviewA = [[CPTrackingAreaView alloc] initWithFrame:CGRectMake(20, 0, 20, 20)];
|
||||
var subviewB = [[CPTrackingAreaView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
|
||||
var subviewC = [[CPTrackingAreaView alloc] initWithFrame:CGRectMake(0, 20, 40, 20)];
|
||||
|
||||
[viewA addSubview:subviewA];
|
||||
[viewB addSubview:subviewB];
|
||||
[viewC addSubview:subviewC];
|
||||
|
||||
var options = CPTrackingCursorUpdate | CPTrackingActiveInActiveApp | CPTrackingInVisibleRect;
|
||||
var options2 = CPTrackingMouseEnteredAndExited | CPTrackingActiveInActiveApp | CPTrackingInVisibleRect;
|
||||
var options3 = CPTrackingCursorUpdate | CPTrackingActiveInActiveApp;
|
||||
|
||||
var viewATrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:options owner:viewA userInfo:nil];
|
||||
var viewBTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:options owner:viewB userInfo:nil];
|
||||
var viewCTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:options2 owner:viewC userInfo:nil];
|
||||
|
||||
var subviewATrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:options owner:subviewA userInfo:nil];
|
||||
var subviewBTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:options owner:subviewB userInfo:nil];
|
||||
var subviewCtrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMake(20, 0, 20, 20) options:options3 owner:subviewC userInfo:nil];
|
||||
|
||||
[viewA addTrackingArea:viewATrackingArea];
|
||||
[viewB addTrackingArea:viewBTrackingArea];
|
||||
[viewC addTrackingArea:viewCTrackingArea];
|
||||
|
||||
[subviewA addTrackingArea:subviewATrackingArea];
|
||||
[subviewB addTrackingArea:subviewBTrackingArea];
|
||||
[subviewC addTrackingArea:subviewCtrackingArea];
|
||||
|
||||
// Step 1
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(5, 25) dragging:NO];
|
||||
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"Step 1 : no cursorUpdate should be called"];
|
||||
[self assert:nil equals:involvedViewForCursorUpdate message:@"Step 1 : no view should be called for cursorUpdate"];
|
||||
|
||||
// Step 2
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(5, 35) dragging:NO];
|
||||
|
||||
[self assert:1 equals:cursorUpdateCalls message:@"Step 2 : 1 cursorUpdate should be called"];
|
||||
[self assert:viewA equals:involvedViewForCursorUpdate message:@"Step 2 : viewA should be called for cursorUpdate"];
|
||||
|
||||
// Step 3
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(15, 35) dragging:NO];
|
||||
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"Step 3 : no cursorUpdate should be called"];
|
||||
[self assert:nil equals:involvedViewForCursorUpdate message:@"Step 3 : no view should be called for cursorUpdate"];
|
||||
|
||||
// Step 4
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(25, 35) dragging:NO];
|
||||
|
||||
[self assert:1 equals:cursorUpdateCalls message:@"Step 4 : 1 cursorUpdate should be called"];
|
||||
[self assert:subviewA equals:involvedViewForCursorUpdate message:@"Step 4 : subviewA should be called for cursorUpdate"];
|
||||
|
||||
// Step 5
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(35, 35) dragging:NO];
|
||||
|
||||
[self assert:1 equals:cursorUpdateCalls message:@"Step 5 : 1 cursorUpdate should be called"];
|
||||
[self assert:subviewC equals:involvedViewForCursorUpdate message:@"Step 5 : subviewC should be called for cursorUpdate"];
|
||||
|
||||
// Step 6
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(45, 35) dragging:NO];
|
||||
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"Step 6 : no cursorUpdate should be called"];
|
||||
[self assert:nil equals:involvedViewForCursorUpdate message:@"Step 6 : no view should be called for cursorUpdate"];
|
||||
|
||||
// Step 7
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(55, 35) dragging:NO];
|
||||
|
||||
[self assert:1 equals:cursorUpdateCalls message:@"Step 7 : 1 cursorUpdate should be called"];
|
||||
[self assert:viewB equals:involvedViewForCursorUpdate message:@"Step 7 : viewB should be called for cursorUpdate"];
|
||||
|
||||
// Step 8
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(75, 35) dragging:NO];
|
||||
|
||||
[self assert:0 equals:cursorUpdateCalls message:@"Step 8 : no cursorUpdate should be called"];
|
||||
[self assert:nil equals:involvedViewForCursorUpdate message:@"Step 8 : no view should be called for cursorUpdate"];
|
||||
|
||||
// Cursor tests
|
||||
|
||||
var viewA = [[CPTrackingAreaViewWithCursorUpdate alloc] initWithFrame:CGRectMake(20, 20, 40, 40)];
|
||||
var viewB = [[CPTrackingAreaView alloc] initWithFrame:CGRectMake(10, 10, 80, 80)];
|
||||
var viewC = [[CPTrackingAreaViewWithoutCursorUpdate alloc] initWithFrame:CGRectMake(10, 10, 80, 80)];
|
||||
|
||||
[contentView setSubviews:[CPArray array]];
|
||||
[contentView addSubview:viewA];
|
||||
|
||||
var options = CPTrackingCursorUpdate | CPTrackingActiveInActiveApp | CPTrackingInVisibleRect;
|
||||
|
||||
var viewATrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:options owner:viewA userInfo:nil];
|
||||
var viewBTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:options owner:viewB userInfo:nil];
|
||||
var viewCTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:options owner:viewC userInfo:nil];
|
||||
|
||||
[viewA addTrackingArea:viewATrackingArea];
|
||||
[viewB addTrackingArea:viewBTrackingArea];
|
||||
[viewC addTrackingArea:viewCTrackingArea];
|
||||
|
||||
// Step 1.1 : outside the view
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(10, 10) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 1.1 : cursor should be an arrow"];
|
||||
|
||||
// Step 1.2 : inside the view
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(30, 30) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor crosshairCursor] equals:[CPCursor currentCursor] message:@"Step 1.2 : cursor should be a crosshair"];
|
||||
|
||||
// Step 1.3 : outside the view
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(70, 70) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 1.3 : cursor should be an arrow"];
|
||||
|
||||
// Step 1.4 : inside the view with dragging
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(30, 30) dragging:YES];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 1.4 : cursor should be an arrow"];
|
||||
|
||||
// Step 1.5 : mouse up (ends dragging)
|
||||
|
||||
[self mouseUpAtPoint:CGPointMake(30, 30)];
|
||||
|
||||
[self assert:[CPCursor crosshairCursor] equals:[CPCursor currentCursor] message:@"Step 1.5 : cursor should be a crosshair"];
|
||||
|
||||
// Step 1.6 : outside the view with dragging
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(10, 10) dragging:YES];
|
||||
|
||||
[self assert:[CPCursor crosshairCursor] equals:[CPCursor currentCursor] message:@"Step 1.6 : cursor should be a crosshair"];
|
||||
|
||||
// Step 1.7 : mouse up (ends dragging)
|
||||
|
||||
[self mouseUpAtPoint:CGPointMake(10, 10)];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 1.7 : cursor should be an arrow"];
|
||||
|
||||
//
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(1, 1) dragging:NO];
|
||||
|
||||
[viewA removeFromSuperview];
|
||||
[contentView addSubview:viewB];
|
||||
[viewB addSubview:viewA];
|
||||
|
||||
// Step 2.1 : outside the superview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 2.1 : cursor should be an arrow"];
|
||||
|
||||
// Step 2.2 : inside the superview / outside the subview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(15, 15) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 2.2 : cursor should be an arrow"];
|
||||
|
||||
// Step 2.3 : inside the subview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(35, 35) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor crosshairCursor] equals:[CPCursor currentCursor] message:@"Step 2.3 : cursor should be a crosshair"];
|
||||
|
||||
// Step 2.4 : outside the subview / inside the superview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(15, 15) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor crosshairCursor] equals:[CPCursor currentCursor] message:@"Step 2.4 : cursor should be a crosshair"];
|
||||
|
||||
// Step 2.5 : outside the superview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 2.5 : cursor should be an arrow"];
|
||||
|
||||
//
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(1, 1) dragging:NO];
|
||||
|
||||
[viewA removeFromSuperview];
|
||||
[viewB removeFromSuperview];
|
||||
[contentView addSubview:viewC];
|
||||
[viewC addSubview:viewA];
|
||||
|
||||
// Step 3.1 : outside the superview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 3.1 : cursor should be an arrow"];
|
||||
|
||||
// Step 3.2 : inside the superview / outside the subview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(15, 15) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 3.2 : cursor should be an arrow"];
|
||||
|
||||
// Step 3.3 : inside the subview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(35, 35) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor crosshairCursor] equals:[CPCursor currentCursor] message:@"Step 3.3 : cursor should be a crosshair"];
|
||||
|
||||
// Step 3.4 : outside the subview / inside the superview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(15, 15) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 3.4 : cursor should be an arrow"];
|
||||
|
||||
// Step 3.5 : outside the superview
|
||||
|
||||
[self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO];
|
||||
|
||||
[self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 3.5 : cursor should be an arrow"];
|
||||
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
updateTrackingAreasCalls++;
|
||||
}
|
||||
|
||||
- (void)resetCounters
|
||||
{
|
||||
mouseEnteredCalls = 0;
|
||||
mouseExitedCalls = 0;
|
||||
mouseMovedCalls = 0;
|
||||
cursorUpdateCalls = 0;
|
||||
|
||||
involvedViewForMouseEntered = nil;
|
||||
involvedViewForMouseExited = nil;
|
||||
involvedViewForCursorUpdate = nil;
|
||||
}
|
||||
|
||||
- (void)moveMouseAtPoint:(CGPoint)aPoint dragging:(BOOL)dragging
|
||||
{
|
||||
var anEvent = [CPEvent mouseEventWithType:(dragging ? CPLeftMouseDragged : CPMouseMoved)
|
||||
location:aPoint
|
||||
modifierFlags:0
|
||||
timestamp:0
|
||||
windowNumber:[window windowNumber]
|
||||
context:nil
|
||||
eventNumber:-1
|
||||
clickCount:0
|
||||
pressure:0];
|
||||
|
||||
[self resetCounters];
|
||||
|
||||
[[CPApplication sharedApplication] sendEvent:anEvent];
|
||||
}
|
||||
|
||||
- (void)mouseUpAtPoint:(CGPoint)aPoint
|
||||
{
|
||||
var anEvent = [CPEvent mouseEventWithType:CPLeftMouseUp
|
||||
location:aPoint
|
||||
modifierFlags:0
|
||||
timestamp:0
|
||||
windowNumber:[window windowNumber]
|
||||
context:nil
|
||||
eventNumber:-1
|
||||
clickCount:0
|
||||
pressure:0];
|
||||
|
||||
[self resetCounters];
|
||||
|
||||
[[CPApplication sharedApplication] sendEvent:anEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPTrackingAreaView : CPView
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
mouseEnteredCalls++;
|
||||
|
||||
involvedViewForMouseEntered = [[anEvent trackingArea] view];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
mouseExitedCalls++;
|
||||
|
||||
involvedViewForMouseExited = [[anEvent trackingArea] view];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(CPEvent)anEvent
|
||||
{
|
||||
mouseMovedCalls++;
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
{
|
||||
cursorUpdateCalls++;
|
||||
|
||||
involvedViewForCursorUpdate = [[anEvent trackingArea] view];
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
updateTrackingAreasCalls++;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPTrackingAreaViewWithCursorUpdate : CPTrackingAreaView
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
{
|
||||
[[CPCursor crosshairCursor] set];
|
||||
|
||||
[super cursorUpdate:anEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPTrackingAreaViewWithoutCursorUpdate : CPView
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPLayoutView : CPView
|
||||
|
||||
@@ -0,0 +1,699 @@
|
||||
/*
|
||||
* AppController.j
|
||||
* TrackingArea
|
||||
*
|
||||
* Created by Didier Korthoudt on November 2, 2015.
|
||||
* Copyright 2015, Your Company All rights reserved.
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
@import <AppKit/CPTrackingArea.j>
|
||||
|
||||
@class SensibleView;
|
||||
@class SensibleViewTA;
|
||||
@class SensibleViewAutoTA;
|
||||
@class SensibleViewWithoutCursorUpdate;
|
||||
|
||||
@implementation AppController : CPObject
|
||||
{
|
||||
@outlet CPWindow theWindow;
|
||||
|
||||
SensibleView v1;
|
||||
SensibleView v2;
|
||||
SensibleView v3;
|
||||
SensibleView v4;
|
||||
SensibleView v5;
|
||||
SensibleView v6;
|
||||
SensibleView v7;
|
||||
SensibleView v8;
|
||||
SensibleView v9;
|
||||
SensibleView v10;
|
||||
SensibleViewWithoutCursorUpdate v11;
|
||||
SensibleView v12;
|
||||
|
||||
SensibleViewTA w2;
|
||||
SensibleView w3;
|
||||
SensibleViewAutoTA w4;
|
||||
SensibleView w5;
|
||||
SensibleView w6;
|
||||
SensibleView w7;
|
||||
|
||||
@outlet SensibleView s1;
|
||||
|
||||
SensibleView cursorCapturingView;
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
|
||||
{
|
||||
// This is called when the application is done loading.
|
||||
|
||||
var message = [[CPAlert alloc] init];
|
||||
|
||||
[message setMessageText:@"CPTrackingArea test application"];
|
||||
[message setInformativeText:@"Play with various cases, try to drag mouse, observe events in the console, ..."];
|
||||
[message setDelegate:self];
|
||||
[message setAlertStyle:CPInformationalAlertStyle];
|
||||
|
||||
[message addButtonWithTitle:@"OK"];
|
||||
|
||||
[message beginSheetModalForWindow:theWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];
|
||||
}
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
// This is called when the cib is done loading.
|
||||
// You can implement this method on any object instantiated from a Cib.
|
||||
// It's a useful hook for setting up current UI values, and other things.
|
||||
|
||||
// In this case, we want the window from Cib to become our full browser window
|
||||
[theWindow setFullPlatformWindow:YES];
|
||||
|
||||
var p = [theWindow contentView];
|
||||
|
||||
// No tracking area
|
||||
|
||||
v1 = [[SensibleView alloc] initWithFrame:CGRectMake(30, 10, 50, 50)];
|
||||
|
||||
[v1 setViewName:@"no_tracking_area"];
|
||||
[v1 setViewColor:[CPColor greenColor]];
|
||||
[v1 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
[p addSubview:v1];
|
||||
|
||||
[self addLabel:@"No tracking area" forView:v1];
|
||||
|
||||
// CPTrackingMouseEnteredAndExited
|
||||
|
||||
v2 = [[SensibleView alloc] initWithFrame:CGRectMake(160, 10, 50, 50)];
|
||||
|
||||
[v2 setViewName:@"CPTrackingMouseEnteredAndExited"];
|
||||
[v2 setViewColor:[CPColor greenColor]];
|
||||
[v2 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v2
|
||||
userInfo:nil];
|
||||
|
||||
[v2 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v2];
|
||||
|
||||
[self addLabel:@"MouseEnteredAndExited\nInVisibleRect" forView:v2];
|
||||
|
||||
// CPTrackingCursorUpdate
|
||||
|
||||
v3 = [[SensibleView alloc] initWithFrame:CGRectMake(290, 10, 50, 50)];
|
||||
|
||||
[v3 setViewName:@"CPTrackingCursorUpdate"];
|
||||
[v3 setViewColor:[CPColor greenColor]];
|
||||
[v3 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v3
|
||||
userInfo:nil];
|
||||
|
||||
[v3 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v3];
|
||||
|
||||
[self addLabel:@"CursorUpdate\nInVisibleRect" forView:v3];
|
||||
|
||||
// CPTrackingMouseMoved
|
||||
|
||||
v4 = [[SensibleView alloc] initWithFrame:CGRectMake(420, 10, 50, 50)];
|
||||
|
||||
[v4 setViewName:@"CPTrackingMouseMoved"];
|
||||
[v4 setViewColor:[CPColor greenColor]];
|
||||
[v4 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseMoved | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v4
|
||||
userInfo:nil];
|
||||
|
||||
[v4 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v4];
|
||||
|
||||
[self addLabel:@"MouseMoved\nInVisibleRect" forView:v4];
|
||||
|
||||
// CPTrackingMouseEnteredAndExited & CPTrackingCursorUpdate
|
||||
|
||||
v5 = [[SensibleView alloc] initWithFrame:CGRectMake(550, 10, 50, 50)];
|
||||
|
||||
[v5 setViewName:@"CPTrackingMouseEnteredAndExited+CPTrackingCursorUpdate"];
|
||||
[v5 setViewColor:[CPColor greenColor]];
|
||||
[v5 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v5
|
||||
userInfo:nil];
|
||||
|
||||
[v5 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v5];
|
||||
|
||||
[self addLabel:@"MouseEnteredAndExited\nCursorUpdate\nInVisibleRect" forView:v5];
|
||||
|
||||
// CPTrackingMouseMoved & CPTrackingCursorUpdate
|
||||
|
||||
v6 = [[SensibleView alloc] initWithFrame:CGRectMake(680, 10, 50, 50)];
|
||||
|
||||
[v6 setViewName:@"CPTrackingMouseMoved+CPTrackingCursorUpdate"];
|
||||
[v6 setViewColor:[CPColor greenColor]];
|
||||
[v6 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseMoved | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v6
|
||||
userInfo:nil];
|
||||
|
||||
[v6 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v6];
|
||||
|
||||
[self addLabel:@"MouseMoved\nCursorUpdate\nInVisibleRect" forView:v6];
|
||||
|
||||
// CPTrackingMouseEnteredAndExited & CPTrackingMouseMoved
|
||||
|
||||
v7 = [[SensibleView alloc] initWithFrame:CGRectMake(810, 10, 50, 50)];
|
||||
|
||||
[v7 setViewName:@"CPTrackingMouseEnteredAndExited+CPTrackingMouseMoved"];
|
||||
[v7 setViewColor:[CPColor greenColor]];
|
||||
[v7 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v7
|
||||
userInfo:nil];
|
||||
|
||||
[v7 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v7];
|
||||
|
||||
[self addLabel:@"MouseEnteredAndExited\nMouseMoved\nInVisibleRect" forView:v7];
|
||||
|
||||
// CPTrackingMouseEnteredAndExited & CPTrackingMouseMoved & CPTrackingCursorUpdate
|
||||
|
||||
v8 = [[SensibleView alloc] initWithFrame:CGRectMake(940, 10, 50, 50)];
|
||||
|
||||
[v8 setViewName:@"CPTrackingMouseEnteredAndExited+CPTrackingMouseMoved+CPTrackingCursorUpdate"];
|
||||
[v8 setViewColor:[CPColor greenColor]];
|
||||
[v8 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v8
|
||||
userInfo:nil];
|
||||
|
||||
[v8 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v8];
|
||||
|
||||
[self addLabel:@"MouseEnteredAndExited\nMouseMoved\nCursorUpdate\nInVisibleRect" forView:v8];
|
||||
|
||||
// nested views, superview implements cursorUpdate but does nothing
|
||||
|
||||
v9 = [[SensibleView alloc] initWithFrame:CGRectMake(1070, 10, 50, 50)];
|
||||
|
||||
[v9 setViewName:@"Superview with cursorUpdate but doing nothing"];
|
||||
[v9 setViewColor:[CPColor greenColor]];
|
||||
[v9 setViewCursor:nil];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v9
|
||||
userInfo:nil];
|
||||
|
||||
[v9 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v9];
|
||||
|
||||
[self addLabel:@"Outer view implements\ncursorUpdate but does nothing.\nInner view implements\ncursorUpdate" forView:v9];
|
||||
|
||||
v10 = [[SensibleView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
|
||||
|
||||
[v10 setViewName:@"Subview with cursorUpdate"];
|
||||
[v10 setViewColor:[CPColor blueColor]];
|
||||
[v10 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v10
|
||||
userInfo:nil];
|
||||
|
||||
[v10 addTrackingArea:t];
|
||||
|
||||
[v9 addSubview:v10];
|
||||
|
||||
// nested views, superview doesn't implement cursorUpdate but requests it
|
||||
|
||||
v11 = [[SensibleViewWithoutCursorUpdate alloc] initWithFrame:CGRectMake(1200, 10, 50, 50)];
|
||||
|
||||
[v11 setViewName:@"Superview without cursorUpdate"];
|
||||
[v11 setViewColor:[CPColor greenColor]];
|
||||
[v11 setViewCursor:[CPCursor pointingHandCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v11
|
||||
userInfo:nil];
|
||||
|
||||
[v11 addTrackingArea:t];
|
||||
|
||||
[p addSubview:v11];
|
||||
|
||||
[self addLabel:@"Outer view doesn't implement\ncursorUpdate but requests it.\nInner view implements\ncursorUpdate" forView:v11];
|
||||
|
||||
v12 = [[SensibleView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
|
||||
|
||||
[v12 setViewName:@"Subview with cursorUpdate"];
|
||||
[v12 setViewColor:[CPColor blueColor]];
|
||||
[v12 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v12
|
||||
userInfo:nil];
|
||||
|
||||
[v12 addTrackingArea:t];
|
||||
|
||||
[v11 addSubview:v12];
|
||||
|
||||
// Not CPTrackingInVisibleRect
|
||||
|
||||
w2 = [[SensibleViewTA alloc] initWithFrame:CGRectMake(160, 110, 50, 50)];
|
||||
|
||||
[w2 setViewName:@"Not CPTrackingInVisibleRect"];
|
||||
[w2 setViewColor:[CPColor greenColor]];
|
||||
[w2 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMake(0, 0, 25, 25)
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow
|
||||
owner:w2
|
||||
userInfo:nil];
|
||||
|
||||
[w2 addTrackingArea:t];
|
||||
|
||||
[p addSubview:w2];
|
||||
|
||||
[self addLabel:@"MouseEnteredAndExited\n(top-left quarter is the active area)" forView:w2];
|
||||
|
||||
// CPTrackingEnabledDuringMouseDrag
|
||||
|
||||
w3 = [[SensibleView alloc] initWithFrame:CGRectMake(290, 110, 50, 50)];
|
||||
|
||||
[w3 setViewName:@"CPTrackingEnabledDuringMouseDrag"];
|
||||
[w3 setViewColor:[CPColor greenColor]];
|
||||
[w3 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect | CPTrackingEnabledDuringMouseDrag
|
||||
owner:w3
|
||||
userInfo:nil];
|
||||
|
||||
[w3 addTrackingArea:t];
|
||||
|
||||
[p addSubview:w3];
|
||||
|
||||
[self addLabel:@"MouseEnteredAndExited\nInVisibleRect\nEnabledDuringMouseDrag" forView:w3];
|
||||
|
||||
// View in CPScrollView
|
||||
|
||||
[s1 setViewName:@"View in CPScrollView"];
|
||||
[s1 setViewColor:[CPColor greenColor]];
|
||||
[s1 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:s1
|
||||
userInfo:nil];
|
||||
|
||||
[s1 addTrackingArea:t];
|
||||
|
||||
// No itinial TA
|
||||
|
||||
w4 = [[SensibleViewAutoTA alloc] initWithFrame:CGRectMake(420, 110, 50, 50)];
|
||||
|
||||
[w4 setViewName:@"No itinial TA"];
|
||||
[w4 setViewColor:[CPColor greenColor]];
|
||||
[w4 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
[p addSubview:w4];
|
||||
|
||||
[self addLabel:@"This one has no initial\ntracking area but\nuses updateTrackingAreas to\nattach one" forView:w4];
|
||||
|
||||
// Two views with tracking areas where the owner is not the view itself
|
||||
|
||||
w5 = [[SensibleView alloc] initWithFrame:CGRectMake(550, 110, 50, 50)];
|
||||
|
||||
[w5 setViewName:@"firstView"];
|
||||
[w5 setViewColor:[CPColor greenColor]];
|
||||
[w5 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
[p addSubview:w5];
|
||||
|
||||
[self addLabel:@"(firstView)\nThis view has a tracking area\nowned by the blue view" forView:w5];
|
||||
|
||||
w6 = [[SensibleView alloc] initWithFrame:CGRectMake(680, 110, 50, 50)];
|
||||
|
||||
[w6 setViewName:@"secondView"];
|
||||
[w6 setViewColor:[CPColor greenColor]];
|
||||
[w6 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
[p addSubview:w6];
|
||||
|
||||
[self addLabel:@"(secondView)\nThis view has a tracking area\nowned by the blue view" forView:w6];
|
||||
|
||||
w7 = [[SensibleView alloc] initWithFrame:CGRectMake(810, 110, 50, 50)];
|
||||
|
||||
[w7 setViewName:@"masterView"];
|
||||
[w7 setViewColor:[CPColor blueColor]];
|
||||
[w7 setViewCursor:[CPCursor crosshairCursor]];
|
||||
|
||||
[p addSubview:w7];
|
||||
|
||||
[self addLabel:@"I'm the owner of the\ntracking areas of\nthe 2 views on my left" forView:w7];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:w7
|
||||
userInfo:@{ @"trigger": @"View 1" } ];
|
||||
|
||||
[w5 addTrackingArea:t];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:w7
|
||||
userInfo:@{ @"trigger": @"View 2" } ];
|
||||
|
||||
[w6 addTrackingArea:t];
|
||||
|
||||
|
||||
// Cursor update complex test
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var v = [[SensibleView alloc] initWithFrame:CGRectMake((i == 0 ? 50 : 20), (i == 0 ? 240 : 20), 400-(i*40), 400-(i*40))];
|
||||
|
||||
[p addSubview:v];
|
||||
p = v;
|
||||
|
||||
[v setViewName:[CPString stringWithFormat:@"v%d",i]];
|
||||
|
||||
var c = [CPColor colorWithHexString:[CPString stringWithFormat:@"%d%d%d%d%d%d",i,i,i,i,i,i]];
|
||||
|
||||
[v setViewColor:c];
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: [v setViewCursor:[CPCursor crosshairCursor]]; break;
|
||||
case 1: [v setViewCursor:[CPCursor pointingHandCursor]]; break;
|
||||
case 2: [v setViewCursor:[CPCursor resizeNorthwestCursor]]; break;
|
||||
case 3: [v setViewCursor:[CPCursor IBeamCursor]]; break;
|
||||
case 4: [v setViewCursor:[CPCursor dragCopyCursor]]; break;
|
||||
case 5: [v setViewCursor:[CPCursor dragLinkCursor]]; break;
|
||||
case 6: [v setViewCursor:[CPCursor contextualMenuCursor]]; break;
|
||||
case 7: [v setViewCursor:[CPCursor openHandCursor]]; break;
|
||||
case 8: [v setViewCursor:[CPCursor closedHandCursor]]; break;
|
||||
case 9: [v setViewCursor:[CPCursor resizeNorthSouthCursor]]; break;
|
||||
}
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect | CPTrackingEnabledDuringMouseDrag
|
||||
owner:v
|
||||
userInfo:nil];
|
||||
[v addTrackingArea:t];
|
||||
}
|
||||
|
||||
|
||||
var p = [theWindow contentView];
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var v = [[SensibleView alloc] initWithFrame:CGRectMake((i == 0 ? 460 : 0), (i == 0 ? 240 : 0), 400-(i*40), 400-(i*40))];
|
||||
|
||||
[p addSubview:v];
|
||||
p = v;
|
||||
|
||||
[v setViewName:[CPString stringWithFormat:@"v%d",i]];
|
||||
|
||||
var c = [CPColor colorWithHexString:[CPString stringWithFormat:@"%d%d%d%d%d%d",i,i,i,i,i,i]];
|
||||
|
||||
[v setViewColor:c];
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: [v setViewCursor:[CPCursor crosshairCursor]]; break;
|
||||
case 1: [v setViewCursor:[CPCursor pointingHandCursor]]; break;
|
||||
case 2: [v setViewCursor:[CPCursor resizeNorthwestCursor]]; break;
|
||||
case 3: [v setViewCursor:[CPCursor IBeamCursor]]; break;
|
||||
case 4: [v setViewCursor:[CPCursor dragCopyCursor]]; break;
|
||||
case 5: [v setViewCursor:[CPCursor dragLinkCursor]]; break;
|
||||
case 6: [v setViewCursor:[CPCursor contextualMenuCursor]]; break;
|
||||
case 7: [v setViewCursor:[CPCursor openHandCursor]]; break;
|
||||
case 8: [v setViewCursor:[CPCursor closedHandCursor]]; break;
|
||||
case 9: [v setViewCursor:[CPCursor resizeNorthSouthCursor]]; break;
|
||||
}
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:v
|
||||
userInfo:nil];
|
||||
[v addTrackingArea:t];
|
||||
}
|
||||
|
||||
var item = [CPButton buttonWithTitle:@"Add a view that catches cursor updates but not mouse entered/exited events"];
|
||||
|
||||
[item setTarget:self];
|
||||
[item setAction:@selector(showHideView:)];
|
||||
[item setCenter:CGPointMake(455, 660)];
|
||||
|
||||
[[theWindow contentView] addSubview:item];
|
||||
}
|
||||
|
||||
- (void)showHideView:(id)aSender
|
||||
{
|
||||
if (!cursorCapturingView)
|
||||
{
|
||||
cursorCapturingView = [[SensibleView alloc] initWithFrame:CGRectMake(250, 440, 410, 200)];
|
||||
|
||||
[cursorCapturingView setViewColor:[CPColor colorWithHexString:@"c8d3b2"]];
|
||||
[cursorCapturingView setViewName:@"cursorCapturingView"];
|
||||
[cursorCapturingView setViewCursor:[CPCursor disappearingItemCursor]];
|
||||
|
||||
[cursorCapturingView setAlphaValue:0.7];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:cursorCapturingView
|
||||
userInfo:nil];
|
||||
[cursorCapturingView addTrackingArea:t];
|
||||
|
||||
|
||||
[[theWindow contentView] addSubview:cursorCapturingView];
|
||||
|
||||
[aSender setTitle:@"Hide the view catching cursor updates but not mouse entered/exited events"];
|
||||
}
|
||||
else if ([cursorCapturingView isHidden])
|
||||
{
|
||||
[cursorCapturingView setHidden:NO];
|
||||
|
||||
[aSender setTitle:@"Hide the view catching cursor updates but not mouse entered/exited events"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cursorCapturingView setHidden:YES];
|
||||
|
||||
[aSender setTitle:@"Add a view that catches cursor updates but not mouse entered/exited events"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addLabel:(CPString)title forView:(CPView)view
|
||||
{
|
||||
var label = [CPTextField labelWithTitle:title],
|
||||
labelSize = [label frameSize],
|
||||
viewFrame = [view frame];
|
||||
|
||||
[label setFrameOrigin:CGPointMake(viewFrame.origin.x + viewFrame.size.width / 2 - labelSize.width / 2, viewFrame.origin.y + viewFrame.size.height + 4)];
|
||||
[label setFont:[CPFont systemFontOfSize:9]];
|
||||
[label setAlignment:CPCenterTextAlignment];
|
||||
[label setVerticalAlignment:CPTopVerticalTextAlignment];
|
||||
|
||||
[[view superview] addSubview:label];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SensibleView : CPView
|
||||
{
|
||||
CPString viewName @accessors;
|
||||
CPCursor viewCursor @accessors;
|
||||
CPColor viewColor;
|
||||
CPTextField coords;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
if (self)
|
||||
{
|
||||
coords = [CPTextField labelWithTitle:@"WWWW,WWWW"];
|
||||
[coords setFont:[CPFont systemFontOfSize:9]];
|
||||
[coords setAlignment:CPCenterTextAlignment];
|
||||
[coords setCenter:CGPointMake(25,25)];
|
||||
[coords setStringValue:@""];
|
||||
|
||||
[self addSubview:coords];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
CPLog.trace("mouseEntered @"+viewName);
|
||||
|
||||
[self setBackgroundColor:[CPColor redColor]];
|
||||
|
||||
var trigger = [[[anEvent trackingArea] userInfo] valueForKey:@"trigger"];
|
||||
|
||||
if (trigger)
|
||||
[coords setStringValue:trigger];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
CPLog.trace("mouseExited @"+viewName);
|
||||
|
||||
[self setBackgroundColor:viewColor];
|
||||
|
||||
[coords setStringValue:@""];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(CPEvent)anEvent
|
||||
{
|
||||
var l = [anEvent locationInWindow];
|
||||
|
||||
[coords setStringValue:[CPString stringWithFormat:@"%d,%d",l.x,l.y]];
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
{
|
||||
CPLog.trace("cursorUpdate @"+viewName);
|
||||
|
||||
if (viewCursor)
|
||||
[viewCursor set];
|
||||
}
|
||||
|
||||
- (void)setViewColor:(CPColor)aColor
|
||||
{
|
||||
viewColor = aColor;
|
||||
[self setBackgroundColor:aColor];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SensibleViewWithoutCursorUpdate : CPView
|
||||
{
|
||||
CPString viewName @accessors;
|
||||
CPCursor viewCursor @accessors;
|
||||
CPColor viewColor;
|
||||
CPTextField coords;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
if (self)
|
||||
{
|
||||
coords = [CPTextField labelWithTitle:@"WWWW,WWWW"];
|
||||
[coords setFont:[CPFont systemFontOfSize:9]];
|
||||
[coords setAlignment:CPCenterTextAlignment];
|
||||
[coords setCenter:CGPointMake(25,25)];
|
||||
[coords setStringValue:@""];
|
||||
|
||||
[self addSubview:coords];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
CPLog.trace("mouseEntered @"+viewName);
|
||||
|
||||
[self setBackgroundColor:[CPColor redColor]];
|
||||
|
||||
var trigger = [[[anEvent trackingArea] userInfo] valueForKey:@"trigger"];
|
||||
|
||||
if (trigger)
|
||||
[coords setStringValue:trigger];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
CPLog.trace("mouseExited @"+viewName);
|
||||
|
||||
[self setBackgroundColor:viewColor];
|
||||
|
||||
[coords setStringValue:@""];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(CPEvent)anEvent
|
||||
{
|
||||
var l = [anEvent locationInWindow];
|
||||
|
||||
[coords setStringValue:[CPString stringWithFormat:@"%d,%d",l.x,l.y]];
|
||||
}
|
||||
|
||||
- (void)setViewColor:(CPColor)aColor
|
||||
{
|
||||
viewColor = aColor;
|
||||
[self setBackgroundColor:aColor];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SensibleViewTA : SensibleView
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
CPLog.trace("updateTrackingAreas @"+viewName);
|
||||
|
||||
[self removeAllTrackingAreas];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMake(0, 0, 25, 25)
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
|
||||
[self addTrackingArea:t];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SensibleViewAutoTA : SensibleView
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
CPLog.trace("updateTrackingAreas @"+viewName);
|
||||
|
||||
[self removeAllTrackingAreas];
|
||||
|
||||
var t = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
|
||||
[self addTrackingArea:t];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Main cib file base name</key>
|
||||
<string>MainMenu.cib</string>
|
||||
<key>CPBundleName</key>
|
||||
<string>TrackingArea</string>
|
||||
<key>CPBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>CPHumanReadableCopyright</key>
|
||||
<string>Copyright © 2015, Your Company All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Jakefile
|
||||
* TrackingArea
|
||||
*
|
||||
* Created by You on November 2, 2015.
|
||||
* Copyright 2015, Your Company All rights reserved.
|
||||
*/
|
||||
|
||||
var ENV = require("system").env,
|
||||
FILE = require("file"),
|
||||
JAKE = require("jake"),
|
||||
task = JAKE.task,
|
||||
FileList = JAKE.FileList,
|
||||
app = require("cappuccino/jake").app,
|
||||
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
|
||||
OS = require("os"),
|
||||
projectName = "TrackingArea";
|
||||
|
||||
app (projectName, function(task)
|
||||
{
|
||||
ENV["OBJJ_INCLUDE_PATHS"] = "Frameworks";
|
||||
|
||||
if (configuration === "Debug")
|
||||
ENV["OBJJ_INCLUDE_PATHS"] = FILE.join(ENV["OBJJ_INCLUDE_PATHS"], configuration);
|
||||
|
||||
task.setBuildIntermediatesPath(FILE.join("Build", "TrackingArea.build", configuration));
|
||||
task.setBuildPath(FILE.join("Build", configuration));
|
||||
|
||||
task.setProductName("TrackingArea");
|
||||
task.setIdentifier("com.yourcompany.TrackingArea");
|
||||
task.setVersion("1.0");
|
||||
task.setAuthor("Your Company");
|
||||
task.setEmail("feedback @nospam@ yourcompany.com");
|
||||
task.setSummary("TrackingArea");
|
||||
task.setSources(new FileList("**/*.j").exclude(FILE.join("Build", "**")).exclude(FILE.join("Frameworks", "Source", "**")));
|
||||
task.setResources(new FileList("Resources/**"));
|
||||
task.setIndexFilePath("index.html");
|
||||
task.setInfoPlistPath("Info.plist");
|
||||
|
||||
if (configuration === "Debug")
|
||||
task.setCompilerFlags("-DDEBUG -g");
|
||||
else
|
||||
task.setCompilerFlags("-O2");
|
||||
});
|
||||
|
||||
task ("default", [projectName], function()
|
||||
{
|
||||
printResults(configuration);
|
||||
});
|
||||
|
||||
task ("build", ["default"], function()
|
||||
{
|
||||
updateApplicationSize();
|
||||
});
|
||||
|
||||
task ("debug", function()
|
||||
{
|
||||
configuration = ENV["CONFIGURATION"] = "Debug";
|
||||
JAKE.subjake(["."], "build", ENV);
|
||||
});
|
||||
|
||||
task ("release", function()
|
||||
{
|
||||
configuration = ENV["CONFIGURATION"] = "Release";
|
||||
JAKE.subjake(["."], "build", ENV);
|
||||
});
|
||||
|
||||
task ("run", ["debug"], function()
|
||||
{
|
||||
OS.system(["open", FILE.join("Build", "Debug", projectName, "index.html")]);
|
||||
});
|
||||
|
||||
task ("run-release", ["release"], function()
|
||||
{
|
||||
OS.system(["open", FILE.join("Build", "Release", projectName, "index.html")]);
|
||||
});
|
||||
|
||||
task ("deploy", ["release"], function()
|
||||
{
|
||||
FILE.mkdirs(FILE.join("Build", "Deployment", projectName));
|
||||
OS.system(["press", "-f", FILE.join("Build", "Release", projectName), FILE.join("Build", "Deployment", projectName)]);
|
||||
printResults("Deployment")
|
||||
});
|
||||
|
||||
task ("desktop", ["release"], function()
|
||||
{
|
||||
FILE.mkdirs(FILE.join("Build", "Desktop", projectName));
|
||||
require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", projectName), FILE.join("Build", "Desktop", projectName, "TrackingArea.app"));
|
||||
printResults("Desktop")
|
||||
});
|
||||
|
||||
task ("run-desktop", ["desktop"], function()
|
||||
{
|
||||
OS.system([FILE.join("Build", "Desktop", projectName, "TrackingArea.app", "Contents", "MacOS", "NativeHost"), "-i"]);
|
||||
});
|
||||
|
||||
function printResults(configuration)
|
||||
{
|
||||
print("----------------------------");
|
||||
print(configuration+" app built at path: "+FILE.join("Build", configuration, projectName));
|
||||
print("----------------------------");
|
||||
}
|
||||
|
||||
function updateApplicationSize()
|
||||
{
|
||||
print("Calculating application file sizes...");
|
||||
|
||||
var contents = FILE.read(FILE.join("Build", configuration, projectName, "Info.plist"), { charset:"UTF-8" }),
|
||||
format = CFPropertyList.sniffedFormatOfString(contents),
|
||||
plist = CFPropertyList.propertyListFromString(contents),
|
||||
totalBytes = {executable:0, data:0, mhtml:0};
|
||||
|
||||
// Get the size of all framework executables and sprite data
|
||||
var frameworksDir = "Frameworks";
|
||||
|
||||
if (configuration === "Debug")
|
||||
frameworksDir = FILE.join(frameworksDir, "Debug");
|
||||
|
||||
var frameworks = FILE.list(frameworksDir);
|
||||
|
||||
frameworks.forEach(function(framework)
|
||||
{
|
||||
if (framework !== "Source")
|
||||
addBundleFileSizes(FILE.join(frameworksDir, framework), totalBytes);
|
||||
});
|
||||
|
||||
// Read in the default theme name, and attempt to get its size
|
||||
var themeName = plist.valueForKey("CPDefaultTheme") || "Aristo2",
|
||||
themePath = nil;
|
||||
|
||||
if (themeName === "Aristo" || themeName === "Aristo2")
|
||||
themePath = FILE.join(frameworksDir, "AppKit", "Resources", themeName + ".blend");
|
||||
else
|
||||
themePath = FILE.join("Frameworks", "Resources", themeName + ".blend");
|
||||
|
||||
if (FILE.isDirectory(themePath))
|
||||
addBundleFileSizes(themePath, totalBytes);
|
||||
|
||||
// Add sizes for the app
|
||||
addBundleFileSizes(FILE.join("Build", configuration, projectName), totalBytes);
|
||||
|
||||
print("Executables: " + totalBytes.executable + ", sprite data: " + totalBytes.data + ", total: " + (totalBytes.executable + totalBytes.data));
|
||||
|
||||
var dict = new CFMutableDictionary();
|
||||
|
||||
dict.setValueForKey("executable", totalBytes.executable);
|
||||
dict.setValueForKey("data", totalBytes.data);
|
||||
dict.setValueForKey("mhtml", totalBytes.mhtml);
|
||||
|
||||
plist.setValueForKey("CPApplicationSize", dict);
|
||||
|
||||
FILE.write(FILE.join("Build", configuration, projectName, "Info.plist"), CFPropertyList.stringFromPropertyList(plist, format), { charset:"UTF-8" });
|
||||
}
|
||||
|
||||
function addBundleFileSizes(bundlePath, totalBytes)
|
||||
{
|
||||
var bundleName = FILE.basename(bundlePath),
|
||||
environment = bundleName === "Foundation" ? "Objj" : "Browser",
|
||||
bundlePath = FILE.join(bundlePath, environment + ".environment");
|
||||
|
||||
if (FILE.isDirectory(bundlePath))
|
||||
{
|
||||
var filename = bundleName + ".sj",
|
||||
filePath = new FILE.Path(FILE.join(bundlePath, filename));
|
||||
|
||||
if (filePath.exists())
|
||||
totalBytes.executable += filePath.size();
|
||||
|
||||
filePath = new FILE.Path(FILE.join(bundlePath, "dataURLs.txt"));
|
||||
|
||||
if (filePath.exists())
|
||||
totalBytes.data += filePath.size();
|
||||
|
||||
filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLData.txt"));
|
||||
|
||||
if (filePath.exists())
|
||||
totalBytes.mhtml += filePath.size();
|
||||
|
||||
filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLPaths.txt"));
|
||||
|
||||
if (filePath.exists())
|
||||
totalBytes.mhtml += filePath.size();
|
||||
}
|
||||
}
|
||||
@@ -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;21E;D;K;6;CP$UIDd;2;22E;D;K;6;CP$UIDd;2;23E;D;K;6;CP$UIDd;2;25E;D;K;6;CP$UIDd;2;26E;D;K;6;CP$UIDd;2;27E;D;K;6;CP$UIDd;2;28E;D;K;6;CP$UIDd;2;29E;D;K;6;CP$UIDd;2;30E;D;K;6;CP$UIDd;2;31E;D;K;6;CP$UIDd;2;32E;D;K;6;CP$UIDd;2;33E;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;35E;D;K;6;CP$UIDd;2;36E;D;K;6;CP$UIDd;2;37E;D;K;6;CP$UIDd;2;38E;D;K;6;CP$UIDd;2;39E;D;K;6;CP$UIDd;2;40E;D;K;6;CP$UIDd;2;41E;D;K;6;CP$UIDd;2;42E;D;K;6;CP$UIDd;2;43E;D;K;6;CP$UIDd;2;44E;D;K;6;CP$UIDd;2;45E;D;K;6;CP$UIDd;2;46E;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;2;51E;D;K;6;CP$UIDd;2;52E;D;K;6;CP$UIDd;2;53E;D;K;6;CP$UIDd;2;54E;D;K;6;CP$UIDd;2;55E;D;K;6;CP$UIDd;2;56E;D;K;6;CP$UIDd;2;57E;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;58E;D;K;6;CP$UIDd;2;60E;D;K;6;CP$UIDd;2;62E;D;K;6;CP$UIDd;2;63E;D;K;6;CP$UIDd;2;64E;D;K;6;CP$UIDd;2;65E;D;K;6;CP$UIDd;2;66E;D;K;6;CP$UIDd;2;67E;D;K;6;CP$UIDd;2;68E;D;K;6;CP$UIDd;2;69E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;71E;D;K;6;CP$UIDd;2;72E;D;K;6;CP$UIDd;2;73E;D;K;6;CP$UIDd;2;74E;D;K;6;CP$UIDd;2;75E;D;K;6;CP$UIDd;2;76E;D;K;6;CP$UIDd;2;77E;D;K;6;CP$UIDd;2;78E;D;K;6;CP$UIDd;2;79E;D;K;6;CP$UIDd;2;80E;D;K;6;CP$UIDd;2;81E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;83E;D;K;6;CP$UIDd;2;84E;D;K;6;CP$UIDd;2;85E;D;K;6;CP$UIDd;2;86E;D;K;6;CP$UIDd;2;87E;D;K;6;CP$UIDd;2;88E;D;K;6;CP$UIDd;2;89E;D;K;6;CP$UIDd;2;90E;D;K;6;CP$UIDd;2;91E;D;K;6;CP$UIDd;2;92E;D;K;6;CP$UIDd;2;93E;D;K;6;CP$UIDd;2;94E;D;K;6;CP$UIDd;2;95E;D;K;6;CP$UIDd;2;96E;D;K;6;CP$UIDd;2;97E;D;K;6;CP$UIDd;2;98E;D;K;6;CP$UIDd;2;99E;D;K;6;CP$UIDd;3;100E;D;K;6;CP$UIDd;3;101E;D;K;6;CP$UIDd;3;102E;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;104E;D;K;6;CP$UIDd;3;105E;D;K;6;CP$UIDd;3;106E;D;K;6;CP$UIDd;3;107E;D;K;6;CP$UIDd;3;108E;D;K;6;CP$UIDd;3;109E;D;K;6;CP$UIDd;3;110E;D;K;6;CP$UIDd;3;111E;D;K;6;CP$UIDd;3;112E;D;K;6;CP$UIDd;3;113E;D;K;6;CP$UIDd;3;114E;D;K;6;CP$UIDd;3;115E;D;K;6;CP$UIDd;3;116E;D;K;6;CP$UIDd;3;117E;D;K;6;CP$UIDd;3;118E;D;K;6;CP$UIDd;3;119E;D;K;6;CP$UIDd;3;120E;D;K;6;CP$UIDd;3;121E;D;K;6;CP$UIDd;3;122E;D;K;6;CP$UIDd;3;123E;D;K;6;CP$UIDd;3;124E;D;K;6;CP$UIDd;3;125E;D;K;6;CP$UIDd;3;126E;D;K;6;CP$UIDd;3;128E;D;K;6;CP$UIDd;3;130E;D;K;6;CP$UIDd;3;132E;D;K;6;CP$UIDd;3;134E;D;K;6;CP$UIDd;3;135E;D;K;6;CP$UIDd;3;136E;D;K;6;CP$UIDd;3;137E;D;K;6;CP$UIDd;3;138E;D;K;6;CP$UIDd;3;139E;D;K;6;CP$UIDd;3;141E;D;K;6;CP$UIDd;3;143E;D;K;6;CP$UIDd;3;144E;D;K;6;CP$UIDd;3;145E;D;K;6;CP$UIDd;3;147E;D;K;6;CP$UIDd;3;148E;D;K;6;CP$UIDd;3;149E;D;K;6;CP$UIDd;3;150E;D;K;6;CP$UIDd;3;152E;D;K;6;CP$UIDd;3;154E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;3;155E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;3;156E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;3;157E;D;K;6;CP$UIDd;3;158E;D;K;6;CP$UIDd;3;160E;D;K;6;CP$UIDd;3;162E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;3;163E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;3;164E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;3;165E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;3;166E;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;60E;D;K;6;CP$UIDd;2;62E;D;K;6;CP$UIDd;2;63E;D;K;6;CP$UIDd;2;63E;D;K;6;CP$UIDd;2;63E;D;K;6;CP$UIDd;2;63E;D;K;6;CP$UIDd;2;63E;D;K;6;CP$UIDd;2;60E;D;K;6;CP$UIDd;2;69E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;73E;D;K;6;CP$UIDd;2;74E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;70E;D;K;6;CP$UIDd;2;60E;D;K;6;CP$UIDd;2;81E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;92E;D;K;6;CP$UIDd;2;93E;D;K;6;CP$UIDd;2;93E;D;K;6;CP$UIDd;2;93E;D;K;6;CP$UIDd;2;93E;D;K;6;CP$UIDd;2;93E;D;K;6;CP$UIDd;2;82E;D;K;6;CP$UIDd;2;99E;D;K;6;CP$UIDd;3;100E;D;K;6;CP$UIDd;3;100E;D;K;6;CP$UIDd;3;100E;D;K;Line truncated
|
||||
@@ -0,0 +1,525 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9060" systemVersion="15C50" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment version="1050" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9060"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="450" id="451"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<menu title="AMainMenu" systemMenu="main" id="29" userLabel="MainMenu">
|
||||
<items>
|
||||
<menuItem title="NewApplication" id="56">
|
||||
<menu key="submenu" title="NewApplication" systemMenu="apple" id="57">
|
||||
<items>
|
||||
<menuItem title="About NewApplication" id="58">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="236">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
|
||||
<menuItem isSeparatorItem="YES" id="143">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Quit NewApplication" keyEquivalent="q" id="136">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-3" id="449"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="83">
|
||||
<menu key="submenu" title="File" id="81">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="82">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="373"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="72">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="374"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="124">
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="126">
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="127"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="79">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Close" keyEquivalent="w" id="73">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="193"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save" keyEquivalent="s" id="75">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="362"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="80">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="-1" id="363"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" id="112">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="217">
|
||||
<menu key="submenu" title="Edit" id="205">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="207">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="223"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="215">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="231"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="206">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="199">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="228"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="197">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="224"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="203">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="226"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="202">
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="235"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="198">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="232"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="214">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Find" id="218">
|
||||
<menu key="submenu" title="Find" id="220">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="241"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208"/>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="210">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="216">
|
||||
<menu key="submenu" title="Spelling and Grammar" id="200">
|
||||
<items>
|
||||
<menuItem title="Show Spelling…" keyEquivalent=":" id="204">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="230"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Spelling" keyEquivalent=";" id="201">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="225"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Spelling While Typing" id="219">
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="346">
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="347"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="348">
|
||||
<menu key="submenu" title="Substitutions" id="349">
|
||||
<items>
|
||||
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="211">
|
||||
<menu key="submenu" title="Speech" id="212">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="196">
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="233"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="195">
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="227"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="295">
|
||||
<menu key="submenu" title="View" id="296">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="297">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="366"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="298">
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="19">
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="24">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="23">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="37"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="239">
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="240"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="92">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Bring All to Front" id="5">
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="39"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="103">
|
||||
<menu key="submenu" title="Help" id="106">
|
||||
<items>
|
||||
<menuItem title="NewApplication Help" keyEquivalent="?" id="111">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="360"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" topStrut="YES"/>
|
||||
<rect key="contentRect" x="119" y="946" width="1374" height="1031"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<view key="contentView" id="372">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1374" height="1031"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<splitView arrangesAllSubviews="NO" dividerStyle="thin" vertical="YES" id="Gf7-bI-H4t">
|
||||
<rect key="frame" x="940" y="811" width="214" height="73"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<customView id="Sze-Eb-8Fx">
|
||||
<rect key="frame" x="0.0" y="0.0" width="59" height="73"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
|
||||
<color key="value" red="0.0" green="0.53140729870000003" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</customView>
|
||||
<customView id="59Y-bY-6NO">
|
||||
<rect key="frame" x="60" y="0.0" width="59" height="73"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
|
||||
<color key="value" red="0.56690436239999997" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</customView>
|
||||
<customView id="e86-da-1nH">
|
||||
<rect key="frame" x="120" y="0.0" width="94" height="73"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<animations/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
|
||||
<color key="value" red="0.57639149440000004" green="0.59769631410000001" blue="0.53293551319999999" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</customView>
|
||||
</subviews>
|
||||
<animations/>
|
||||
<holdingPriorities>
|
||||
<real value="250"/>
|
||||
<real value="250"/>
|
||||
<real value="250"/>
|
||||
</holdingPriorities>
|
||||
</splitView>
|
||||
<splitView arrangesAllSubviews="NO" id="9ty-Ct-bpx">
|
||||
<rect key="frame" x="940" y="698" width="214" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<customView id="Eb6-2a-ijs">
|
||||
<rect key="frame" x="0.0" y="0.0" width="214" height="45"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
|
||||
<color key="value" red="0.0" green="0.2389628775" blue="0.64796560400000003" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</customView>
|
||||
<customView id="sJR-ny-vXH">
|
||||
<rect key="frame" x="0.0" y="54" width="214" height="48"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
|
||||
<color key="value" red="0.4716600252" green="0.3736891779" blue="0.17221581380000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</customView>
|
||||
</subviews>
|
||||
<animations/>
|
||||
<holdingPriorities>
|
||||
<real value="250"/>
|
||||
<real value="250"/>
|
||||
</holdingPriorities>
|
||||
</splitView>
|
||||
<scrollView horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="pZB-1q-EQ1">
|
||||
<rect key="frame" x="940" y="513" width="277" height="163"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" id="Tsy-28-w1p">
|
||||
<rect key="frame" x="1" y="1" width="275" height="161"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view id="35c-jE-A9i">
|
||||
<rect key="frame" x="0.0" y="0.0" width="290" height="346"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<customView id="qhh-BF-uJV" customClass="SensibleView">
|
||||
<rect key="frame" x="56" y="46" width="163" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<animations/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<animations/>
|
||||
</view>
|
||||
</subviews>
|
||||
<animations/>
|
||||
</clipView>
|
||||
<animations/>
|
||||
<scroller key="horizontalScroller" verticalHuggingPriority="750" horizontal="YES" id="haI-QJ-idG">
|
||||
<rect key="frame" x="1" y="146" width="275" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="en7-ag-3l6">
|
||||
<rect key="frame" x="261" y="1" width="15" height="161"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="F6I-OP-yvg">
|
||||
<rect key="frame" x="940" y="377" width="277" height="119"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" id="mCM-Xi-afN">
|
||||
<rect key="frame" x="1" y="23" width="275" height="95"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" headerView="ZTR-Tg-hlW" id="soC-Ts-qCo">
|
||||
<rect key="frame" x="0.0" y="0.0" width="275" height="95"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn width="78.77734375" minWidth="40" maxWidth="1000" id="ce2-Dt-Q9a">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="First">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="Mhu-mt-2hd">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
</tableColumn>
|
||||
<tableColumn width="106.203125" minWidth="40" maxWidth="1000" id="oyN-zb-Aen">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Second">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="POl-Ii-IlH">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
</tableColumn>
|
||||
<tableColumn width="81" minWidth="10" maxWidth="3.4028234663852886e+38" id="4WF-b2-Qjp">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Third">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="6Vv-pe-Az4">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<animations/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<animations/>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="vti-fg-vzI">
|
||||
<rect key="frame" x="1" y="231" width="307" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="EWM-fi-aQY">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
</scroller>
|
||||
<tableHeaderView key="headerView" id="ZTR-Tg-hlW">
|
||||
<rect key="frame" x="0.0" y="0.0" width="275" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
</tableHeaderView>
|
||||
</scrollView>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="USC-6c-rhh">
|
||||
<rect key="frame" x="1223" y="452" width="88" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<animations/>
|
||||
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" title="CPTableHeaderView now using tracking areas for cursor updates" id="yKB-Vw-OTW">
|
||||
<font key="font" metaFont="system" size="9"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="tjU-JO-PMX">
|
||||
<rect key="frame" x="1223" y="621" width="78" height="55"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<animations/>
|
||||
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" title="CPScrollView (scroll down to view and test a view with tracking area)" id="t8v-6H-YXg">
|
||||
<font key="font" metaFont="system" size="9"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="5Zj-ir-6wr">
|
||||
<rect key="frame" x="1160" y="820" width="78" height="55"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<animations/>
|
||||
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" title="CPSplitView with thin vertical dividers, using tracking area for cursor updates" id="sLE-AN-vtO">
|
||||
<font key="font" metaFont="system" size="9"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="NBW-q0-pOz">
|
||||
<rect key="frame" x="1160" y="730" width="78" height="39"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<animations/>
|
||||
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" title="CPSplitView with thick horizontal dividers" id="LoF-bh-fEg">
|
||||
<font key="font" metaFont="system" size="9"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<animations/>
|
||||
</view>
|
||||
<point key="canvasLocation" x="625" y="736.5"/>
|
||||
</window>
|
||||
<customObject id="450" customClass="AppController">
|
||||
<connections>
|
||||
<outlet property="s1" destination="qhh-BF-uJV" id="L8n-I6-kzA"/>
|
||||
<outlet property="theWindow" destination="371" id="459"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -0,0 +1,193 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
index-debug.html
|
||||
TrackingArea
|
||||
|
||||
Created by You on November 2, 2015.
|
||||
Copyright 2015, Your Company All rights reserved.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!--[if lte IE 8]>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1">
|
||||
<![endif]-->
|
||||
<!--[if gte IE 9]>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<![endif]-->
|
||||
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
|
||||
<link rel="apple-touch-icon" href="Resources/icon.png">
|
||||
<link rel="apple-touch-startup-image" href="Resources/default.png">
|
||||
|
||||
<title>TrackingArea</title>
|
||||
|
||||
<!-- Custom javascript goes here -->
|
||||
<!-- End custom javascript -->
|
||||
|
||||
<script type="text/javascript">
|
||||
OBJJ_MAIN_FILE = "main.j";
|
||||
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks"];
|
||||
// Uncomment below to generate debug symbols, type signatures and inline objj_msgSend functions
|
||||
// OBJJ_COMPILER_FLAGS = ["IncludeDebugSymbols", "IncludeTypeSignatures", "InlineMsgSend"];
|
||||
|
||||
var progressBar = null;
|
||||
|
||||
OBJJ_PROGRESS_CALLBACK = function(percent, appSize, path)
|
||||
{
|
||||
percent = percent * 100;
|
||||
|
||||
if (!progressBar)
|
||||
progressBar = document.getElementById("progress-bar");
|
||||
|
||||
if (progressBar)
|
||||
progressBar.style.width = Math.min(percent, 100) + "%";
|
||||
}
|
||||
|
||||
var loadingHTML =
|
||||
'<div id="loading">' +
|
||||
' <div id="loading-text">Loading...</div>' +
|
||||
' <div id="progress-indicator">' +
|
||||
' <span id="progress-bar" style="width:0%"></span>' +
|
||||
' </div>' +
|
||||
'</div>';
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="Frameworks/Debug/Objective-J/Objective-J.js" charset="UTF-8"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
objj_msgSend_reset();
|
||||
|
||||
// DEBUG OPTIONS:
|
||||
|
||||
// Uncomment to enable printing of backtraces on exceptions:
|
||||
//objj_msgSend_decorate(objj_backtrace_decorator);
|
||||
|
||||
// Uncomment to supress exceptions that take place inside a message
|
||||
//objj_msgSend_decorate(objj_supress_exceptions_decorator)
|
||||
|
||||
// Uncomment to enable runtime type checking:
|
||||
//objj_msgSend_decorate(objj_typecheck_decorator);
|
||||
|
||||
// Uncomment (along with both above) to print backtraces on type check errors:
|
||||
//objj_typecheck_prints_backtrace = true;
|
||||
|
||||
// Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
|
||||
//CPLogUnregister(CPLogDefault);
|
||||
|
||||
// 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;
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
html, body, h1, p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* We need a body wrapper because Cappuccino is unhappy if we change the body element */
|
||||
#cappuccino-body {
|
||||
/* Position it absolutely so it will fill the height without content */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
/* Put it at the bottom of the stack so it doesn't interfere with UI */
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#cappuccino-body .container {
|
||||
display: table;
|
||||
margin: 0 auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#cappuccino-body .content {
|
||||
display: table-cell;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position: relative;
|
||||
top: 35%;
|
||||
}
|
||||
|
||||
#loading-text {
|
||||
height: 1.5em;
|
||||
color: #555;
|
||||
font: normal bold 36px/36px Arial, sans-serif;
|
||||
}
|
||||
|
||||
#progress-indicator {
|
||||
padding: 0px;
|
||||
height: 16px;
|
||||
border: 5px solid #555;
|
||||
border-radius: 18px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#progress-bar {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
display: block;
|
||||
height: 18px;
|
||||
|
||||
/* Compensate for moving the bar left 1px to overlap the indicator border */
|
||||
border-right: 1px solid #555;
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
#noscript {
|
||||
position: relative;
|
||||
top: 35%;
|
||||
padding: 1em 1.5em;
|
||||
border: 5px solid #555;
|
||||
border-radius: 16px;
|
||||
background-color: white;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
font: bold 24px Arial, sans-serif;
|
||||
}
|
||||
|
||||
#noscript a {
|
||||
color: #98c0ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="cappuccino-body">
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<script type="text/javascript">
|
||||
document.write(loadingHTML);
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<noscript style="position:absolute; top:0; left:0; width:100%; height:100%">
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<div id="noscript">
|
||||
<p style="font-size:120%; margin-bottom:.75em">JavaScript is required for this site.</p>
|
||||
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,161 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
index.html
|
||||
TrackingArea
|
||||
|
||||
Created by You on November 2, 2015.
|
||||
Copyright 2015, Your Company All rights reserved.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!--[if lte IE 8]>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1">
|
||||
<![endif]-->
|
||||
<!--[if gte IE 9]>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<![endif]-->
|
||||
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
|
||||
<link rel="apple-touch-icon" href="Resources/icon.png">
|
||||
<link rel="apple-touch-startup-image" href="Resources/default.png">
|
||||
|
||||
<title>TrackingArea</title>
|
||||
|
||||
<!-- Custom javascript goes here -->
|
||||
<!-- End custom javascript -->
|
||||
|
||||
<script type="text/javascript">
|
||||
OBJJ_MAIN_FILE = "main.j";
|
||||
|
||||
var progressBar = null;
|
||||
|
||||
OBJJ_PROGRESS_CALLBACK = function(percent, appSize, path)
|
||||
{
|
||||
percent = percent * 100;
|
||||
|
||||
if (!progressBar)
|
||||
progressBar = document.getElementById("progress-bar");
|
||||
|
||||
if (progressBar)
|
||||
progressBar.style.width = Math.min(percent, 100) + "%";
|
||||
}
|
||||
|
||||
var loadingHTML =
|
||||
'<div id="loading">' +
|
||||
' <div id="loading-text">Loading...</div>' +
|
||||
' <div id="progress-indicator">' +
|
||||
' <span id="progress-bar" style="width:0%"></span>' +
|
||||
' </div>' +
|
||||
'</div>';
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
|
||||
|
||||
<style type="text/css">
|
||||
html, body, h1, p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* We need a body wrapper because Cappuccino is unhappy if we change the body element */
|
||||
#cappuccino-body {
|
||||
/* Position it absolutely so it will fill the height without content */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
/* Put it at the bottom of the stack so it doesn't interfere with UI */
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#cappuccino-body .container {
|
||||
display: table;
|
||||
margin: 0 auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#cappuccino-body .content {
|
||||
display: table-cell;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position: relative;
|
||||
top: 35%;
|
||||
}
|
||||
|
||||
#loading-text {
|
||||
height: 1.5em;
|
||||
color: #555;
|
||||
font: normal bold 36px/36px Arial, sans-serif;
|
||||
}
|
||||
|
||||
#progress-indicator {
|
||||
padding: 0px;
|
||||
height: 16px;
|
||||
border: 5px solid #555;
|
||||
border-radius: 18px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#progress-bar {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
display: block;
|
||||
height: 18px;
|
||||
|
||||
/* Compensate for moving the bar left 1px to overlap the indicator border */
|
||||
border-right: 1px solid #555;
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
#noscript {
|
||||
position: relative;
|
||||
top: 35%;
|
||||
padding: 1em 1.5em;
|
||||
border: 5px solid #555;
|
||||
border-radius: 16px;
|
||||
background-color: white;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
font: bold 24px Arial, sans-serif;
|
||||
}
|
||||
|
||||
#noscript a {
|
||||
color: #98c0ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="cappuccino-body">
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<script type="text/javascript">
|
||||
document.write(loadingHTML);
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<noscript style="position:absolute; top:0; left:0; width:100%; height:100%">
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<div id="noscript">
|
||||
<p style="font-size:120%; margin-bottom:.75em">JavaScript is required for this site.</p>
|
||||
<p><a href="http://www.enable-javascript.com" target="_blank">Enable JavaScript</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* AppController.j
|
||||
* TrackingArea
|
||||
*
|
||||
* Created by You on November 2, 2015.
|
||||
* Copyright 2015, Your Company All rights reserved.
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
@import "AppController.j"
|
||||
|
||||
|
||||
function main(args, namedArgs)
|
||||
{
|
||||
CPApplicationMain(args, namedArgs);
|
||||
}
|
||||
Reference in new issue
Block a user