Merge remote-tracking branch 'upstream/master' into CPAnimationContext

Conflicts:
	AppKit/CPView.j
This commit is contained in:
cacaodev
2015-03-14 21:18:18 +01:00
34 changed files with 3669 additions and 62 deletions
-1
View File
@@ -71,7 +71,6 @@ var SharedColorPanel = nil,
*/
@implementation CPColorPanel : CPPanel
{
_CPColorPanelToolbar _toolbar;
_CPColorPanelSwatches _swatchView;
_CPColorPanelPreview _previewView;
-1
View File
@@ -32,7 +32,6 @@
@implementation _CPMenuBarWindow : CPPanel
{
CPMenu _menu;
CPView _highlightView;
CPArray _menuItemViews;
@@ -29,7 +29,6 @@
CGRect _animationTargetRect @accessors(property=_animationTargetRect);
BOOL _selected @accessors(getter=_isSelected, setter=_setSelected:);
BOOL _lastSelected @accessors(getter=_isLastSelected, setter=_setLastSelected:);
CPColor _backgroundColor @accessors(property=backgroundColor);
BOOL _editable @accessors(getter=isEditable, setter=setEditable:);
}
+31 -22
View File
@@ -33,6 +33,15 @@
#define SHOULD_SHOW_CORNER_VIEW() (_scrollerStyle === CPScrollerStyleLegacy && _verticalScroller && ![_verticalScroller isHidden])
@protocol CPScrollViewDelegate <CPObject>
@optional
- (void)scrollViewWillScroll:(CPScrollView)aScrollView;
- (void)scrollViewDidScroll:(CPScrollView)aScrollView;
@end
/*! @ignore */
var _isBrowserUsingOverlayScrollers = function()
{
@@ -98,35 +107,35 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
@implementation CPScrollView : CPView
{
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
CPView _bottomCornerView;
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
CPView _bottomCornerView;
id _delegate;
CPTimer _scrollTimer;
id <CPScrollViewDelegate> _delegate;
CPTimer _scrollTimer;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
CPScroller _verticalScroller;
CPScroller _horizontalScroller;
CPScroller _verticalScroller;
CPScroller _horizontalScroller;
CPInteger _recursionCount;
CPInteger _implementedDelegateMethods;
CPInteger _recursionCount;
CPInteger _implementedDelegateMethods;
float _verticalLineScroll;
float _verticalPageScroll;
float _horizontalLineScroll;
float _horizontalPageScroll;
float _verticalLineScroll;
float _verticalPageScroll;
float _horizontalLineScroll;
float _horizontalPageScroll;
CPBorderType _borderType;
CPBorderType _borderType;
CPTimer _timerScrollersHide;
CPTimer _timerScrollersHide;
int _scrollerStyle;
int _scrollerKnobStyle;
int _scrollerStyle;
int _scrollerKnobStyle;
}
@@ -296,7 +305,7 @@ Notifies the delegate when the scroll view has finished scrolling.
@endcode
*/
- (void)setDelegate:(id)aDelegate
- (void)setDelegate:(id <CPScrollViewDelegate>)aDelegate
{
if (aDelegate === _delegate)
return;
+1 -1
View File
@@ -601,7 +601,7 @@ CPTableColumnUserResizingMask = 1 << 1;
}
/*!
Binds the receiver to an object.
Binds the receiver to an object. Note that unlike Cocoa, this works only *after* the receiver has been added to a \c CPTableView.
@param CPString aBinding - The binding you wish to make. Typically CPValueBinding.
@param id anObject - The object to bind the receiver to.
+17 -6
View File
@@ -4458,6 +4458,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
var row = [self rowAtPoint:aPoint];
_clickedRow = row;
_clickedColumn = [self columnAtPoint:aPoint];
// If the user clicks outside a row then deselect everything.
if (row < 0 && _allowsEmptySelection)
{
@@ -4520,6 +4523,12 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
}
else
[CPApp sendEvent:anEvent];
if ([anEvent type] == CPLeftMouseUp)
{
_clickedRow = CPNotFound;
_clickedColumn = CPNotFound;
}
}
/*
@@ -4529,6 +4538,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
{
var row = [self rowAtPoint:aPoint];
_clickedRow = row;
_clickedColumn = [self columnAtPoint:aPoint];
// begin the drag is the datasource lets us, we've move at least +-3px vertical or horizontal,
// or we're dragging from selected rows and we haven't begun a drag session
if (!_isSelectingSession && [self _dataSourceRespondsToWriteRowsWithIndexesToPasteboard])
@@ -4617,9 +4629,12 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
rowIndex,
shouldEdit = YES;
_clickedRow = [self rowAtPoint:aPoint];
_clickedColumn = [self columnAtPoint:aPoint];
if ([self _dataSourceRespondsToWriteRowsWithIndexesToPasteboard])
{
rowIndex = [self rowAtPoint:aPoint];
rowIndex = _clickedRow;
if (rowIndex !== -1)
{
@@ -4641,7 +4656,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
&& ([self _dataSourceRespondsToSetObjectValueForTableColumnRow]
|| [self infoForBinding:@"content"]))
{
columnIndex = [self columnAtPoint:lastPoint];
columnIndex = _clickedColumn;
if (columnIndex !== -1)
{
@@ -4666,11 +4681,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
//double click actions
if ([[CPApp currentEvent] clickCount] === 2 && _doubleAction)
{
_clickedRow = [self rowAtPoint:aPoint];
_clickedColumn = [self columnAtPoint:lastPoint];
[self sendAction:_doubleAction to:_target];
}
}
/*
+19 -12
View File
@@ -315,13 +315,6 @@ var CPViewHighDPIDrawingEnabled = YES;
_viewClassFlags = CPViewFlags[classUID];
}
- (void)_setupToolTipHandlers
{
_toolTipInstalled = NO;
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; }
_toolTipFunctionOut = function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
}
+ (CPSet)keyPathsForValuesAffectingFrame
{
return [CPSet setWithObjects:@"frameOrigin", @"frameSize"];
@@ -391,9 +384,8 @@ var CPViewHighDPIDrawingEnabled = YES;
#endif
_animator = nil;
_animationsDictionary = [CPDictionary dictionary];
_animationsDictionary = @{};
[self _setupToolTipHandlers];
[self _setupViewFlags];
[self _loadThemeAttributes];
@@ -418,12 +410,16 @@ var CPViewHighDPIDrawingEnabled = YES;
_toolTip = aToolTip;
if (_toolTip)
[self _manageToolTipInstallation];
}
- (void)_manageToolTipInstallation
{
if ([self window] && _toolTip)
[self _installToolTipEventHandlers];
else
[self _uninstallToolTipEventHandlers];
}
/*! @ignore
Install the handlers for the tooltip
@@ -433,6 +429,12 @@ var CPViewHighDPIDrawingEnabled = YES;
if (_toolTipInstalled)
return;
if (!_toolTipFunctionIn)
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; }
if (!_toolTipFunctionOut)
_toolTipFunctionOut = function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
#if PLATFORM(DOM)
if (_DOMElement.addEventListener)
{
@@ -475,6 +477,9 @@ var CPViewHighDPIDrawingEnabled = YES;
}
#endif
_toolTipFunctionIn = nil;
_toolTipFunctionOut = nil;
_toolTipInstalled = NO;
}
@@ -813,6 +818,8 @@ var CPViewHighDPIDrawingEnabled = YES;
[self viewDidMoveToWindow];
[self _manageToolTipInstallation];
[[self window] _dirtyKeyViewLoop];
}
@@ -840,6 +847,7 @@ var CPViewHighDPIDrawingEnabled = YES;
{
// if (_graphicsContext)
[self setNeedsDisplay:YES];
}
/*!
@@ -3561,7 +3569,6 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
_hitTests = ![aCoder containsValueForKey:CPViewHitTestsKey] || [aCoder decodeBoolForKey:CPViewHitTestsKey];
[self _setupToolTipHandlers];
_toolTip = [aCoder decodeObjectForKey:CPViewToolTipKey];
if (_toolTip)
+30
View File
@@ -575,6 +575,9 @@ CPTexturedBackgroundWindowMask
var fullPlatformWindowViewClass = [[self class] _windowViewClassForFullPlatformWindowStyleMask:_styleMask],
windowView = [[fullPlatformWindowViewClass alloc] initWithFrame:CGRectMakeZero() styleMask:_styleMask];
if (_platformWindow != [CPPlatformWindow primaryPlatformWindow] && [_platformWindow _hasInitializeInstanceWithWindow])
[_platformWindow setContentRect:[self frame]];
[self _setWindowView:windowView];
[self setLevel:CPBackgroundWindowLevel];
@@ -759,6 +762,9 @@ CPTexturedBackgroundWindowMask
if (originMoved)
[self _moveChildWindows:delta];
}
if ([_platformWindow _canUpdateContentRect] && _isFullPlatformWindow && _platformWindow != [CPPlatformWindow primaryPlatformWindow])
[_platformWindow setContentRect:aFrame];
}
/*
@@ -909,6 +915,10 @@ CPTexturedBackgroundWindowMask
{
#if PLATFORM(DOM)
if (!_isVisible)
[_platformWindow _setShouldUpdateContentRect:NO];
// -dw- if a sheet is clicked, the parent window should come up too
if (_isSheet)
[_parentView orderFront:self];
@@ -932,6 +942,8 @@ CPTexturedBackgroundWindowMask
if (!CPApp._mainWindow)
[self makeMainWindow];
[_platformWindow _setShouldUpdateContentRect:YES];
}
/*
@@ -947,6 +959,11 @@ CPTexturedBackgroundWindowMask
*/
- (void)_windowWillBeAddedToTheDOM
{
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceivePlatformWindowWillCloseNotification:)
name:_CPPlatformWindowWillCloseNotification
object:_platformWindow];
[[self contentView] _addObservers];
}
@@ -955,6 +972,8 @@ CPTexturedBackgroundWindowMask
*/
- (void)_windowWillBeRemovedFromTheDOM
{
[[CPNotificationCenter defaultCenter] removeObserver:self name:_CPPlatformWindowWillCloseNotification object:nil];
[[self contentView] _removeObservers];
}
@@ -1002,6 +1021,9 @@ CPTexturedBackgroundWindowMask
if ([self _sharesChromeWithPlatformWindow])
[_platformWindow orderOut:self];
if (_isFullPlatformWindow && _platformWindow != [CPPlatformWindow primaryPlatformWindow])
[_platformWindow orderOut:self];
[_platformWindow order:CPWindowOut window:self relativeTo:nil];
#endif
@@ -3353,6 +3375,14 @@ CPTexturedBackgroundWindowMask
[super setValue:aValue forKey:aKey];
}
- (void)_didReceivePlatformWindowWillCloseNotification:(CPNotification)aNotification
{
if ([aNotification object] != _platformWindow)
return;
[self close];
}
@end
var keyViewComparator = function(lhs, rhs, context)
-1
View File
@@ -27,7 +27,6 @@
@implementation _CPHUDWindowView : _CPTitleableWindowView
{
CPView _toolbarView;
CPButton _closeButton;
}
-1
View File
@@ -94,7 +94,6 @@ var _CPStandardWindowViewDividerViewHeight = 1.0;
_CPTexturedWindowHeadView _headView;
CPView _dividerView;
CPView _bodyView;
CPView _toolbarView;
CPButton _closeButton;
CPButton _minimizeButton;
-1
View File
@@ -24,7 +24,6 @@
@implementation CPCibHelpConnector : CPCibConnector
{
id _destination;
id _file;
id _marker;
}
+29
View File
@@ -43,6 +43,8 @@ var PrimaryPlatformWindow = NULL;
BOOL _hasShadow;
unsigned _shadowStyle;
CPString _title;
BOOL _shouldUpdateContentRect;
BOOL _hasInitializeInstanceWithWindow;
#if PLATFORM(DOM)
DOMWindow _DOMWindow;
@@ -119,6 +121,17 @@ var PrimaryPlatformWindow = NULL;
return self;
}
- (id)initWithWindow:(CPWindow)aWindow
{
self = [self initWithContentRect:CGRectMakeCopy([aWindow frame])];
_hasInitializeInstanceWithWindow = YES;
[aWindow setPlatformWindow:self];
[aWindow setFullPlatformWindow:YES];
return self;
}
- (id)init
{
return [self initWithContentRect:CGRectMake(0.0, 0.0, 400.0, 500.0)];
@@ -284,6 +297,22 @@ var PrimaryPlatformWindow = NULL;
return _title;
}
- (BOOL)_canUpdateContentRect
{
// We onyl update the contentRect with the frame of the bridgeless window if we have initialized the platform with the method initWithWindow:
return _shouldUpdateContentRect && _hasInitializeInstanceWithWindow;
}
- (BOOL)_hasInitializeInstanceWithWindow
{
return _hasInitializeInstanceWithWindow;
}
- (void)_setShouldUpdateContentRect:(BOOL)aBoolean
{
_shouldUpdateContentRect = aBoolean;
}
@end
#if PLATFORM(BROWSER)
+19 -4
View File
@@ -203,6 +203,9 @@ var ModifierKeyCodes = [
var resizeTimer = nil;
var PreventScroll = true;
_CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotification";
// When scrolling with an old-style scroll wheel with discete steps ('clicks'), the scroll amount can indicate how many "lines" to
// scroll.
#define SCROLLWHEEL_LINE_PIXELS 6.0
@@ -429,6 +432,9 @@ var PreventScroll = true;
_DOMWindow.addEventListener("unload", function()
{
_DOMWindow.removeEventListener("unload", arguments.callee, NO);
[self _notifyPlatformWindowWillClose];
[self updateFromNativeContentRect];
[self _removeLayers];
@@ -452,8 +458,6 @@ var PreventScroll = true;
_DOMWindow.removeEventListener("wheel", scrollEventCallback, NO);
_DOMWindow.removeEventListener("mousewheel", scrollEventCallback, NO);
//_DOMWindow.removeEventListener("beforeunload", this, NO);
[PlatformWindows removeObject:self];
[_platformPasteboard setDOMWindow:nil];
@@ -483,6 +487,9 @@ var PreventScroll = true;
_DOMWindow.attachEvent("onunload", function()
{
_DOMWindow.detachEvent("unload", arguments.callee);
[self _notifyPlatformWindowWillClose];
[self updateFromNativeContentRect];
[self _removeLayers];
@@ -504,8 +511,6 @@ var PreventScroll = true;
_DOMBodyElement.ondrag = NULL;
_DOMBodyElement.onselectstart = NULL;
//_DOMWindow.removeEvent("beforeunload", this);
[PlatformWindows removeObject:self];
[_platformPasteboard setDOMWindow:nil];
@@ -988,6 +993,7 @@ var PreventScroll = true;
- (void)_actualResizeEvent
{
_shouldUpdateContentRect = NO;
resizeTimer = nil;
// FIXME: This is not the right way to do this.
@@ -1021,6 +1027,8 @@ var PreventScroll = true;
//window.liveResize = NO;
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
_shouldUpdateContentRect = YES;
}
- (void)touchEvent:(DOMEvent)aDOMEvent
@@ -1629,6 +1637,13 @@ var PreventScroll = true;
KeyCodesToPrevent = {};
}
- (void)_notifyPlatformWindowWillClose
{
[[CPNotificationCenter defaultCenter] postNotificationName:_CPPlatformWindowWillCloseNotification
object:self
userInfo:nil];
}
@end
#endif
-1
View File
@@ -63,7 +63,6 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
BOOL _browserAnimates;
BOOL _isObservingFrame;
BOOL _shouldPerformAnimation;
CPInteger _implementedDelegateMethods;
CGRect _targetRect;
CPWindow _targetWindow;
JSObject _orderOutTransitionFunction;
+371
View File
@@ -0,0 +1,371 @@
/*
* CPCache.j
* Foundation
*
* Created by William Mura.
* Copyright 2015, William Mura.
*
* 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 "CPObject.j"
@import "CPDictionary.j"
@import "CPString.j"
@class _CPCacheItem;
/*
* Delegate CPCacheDelegate
*
* - cache:willEvictObject: is called when a object is going to be removed
* When the total cost or the count exceeds the total cost limit or the count limit
* And also when removeObjectForKey or removeAllObjects are called
*/
@protocol CPCacheDelegate <CPObject>
@optional
- (void)cache:(CPCache)cache willEvictObject:(id)obj;
@end
var CPCacheDelegate_cache_willEvictObject_ = 1 << 1;
/*!
@class CPCache
@ingroup foundation
@brief A collection-like container with discardable objects
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSCache_Class/index.html#//apple_ref/occ/instp/NSCache/delegate
A CPCache object is a collection-like container, or cache, that stores key-value pairs,
similar to the CPDictionary class. Developers often incorporate caches to temporarily
store objects with transient data that are expensive to create.
Reusing these objects can provide performance benefits, because their values do not have to be recalculated.
However, the objects are not critical to the application and can be discarded if memory is tight.
If discarded, their values will have to be recomputed again when needed.
*/
@implementation CPCache : CPObject
{
CPDictionary _items;
int _currentPosition;
BOOL _totalCostCache;
unsigned _implementedDelegateMethods;
CPString _name @accessors(property=name);
int _countLimit @accessors(property=countLimit);
int _totalCostLimit @accessors(property=totalCostLimit);
id <CPCacheDelegate> _delegate @accessors(property=delegate);
}
#pragma mark -
#pragma mark Initialization
/*!
Initializes the cache with default values
@return the initialized cache
*/
- (id)init
{
if (self = [super init])
{
_items = [[CPDictionary alloc] init];
_currentPosition = 0;
_totalCostCache = -1;
_implementedDelegateMethods = 0;
_name = @"";
_countLimit = 0;
_totalCostLimit = 0;
_delegate = nil;
}
return self;
}
#pragma mark -
#pragma mark Managing cache
/*!
Returns the object which correspond to the given key
@param aKey the key for the object's entry
@return the object for the entry
*/
- (id)objectForKey:(id)aKey
{
return [[_items objectForKey:aKey] object];
}
/*!
Adds an object with default cost into the cache.
@param anObject the object to add in the cache
@param aKey the object's key
*/
- (void)setObject:(id)anObject forKey:(id)aKey
{
[self setObject:anObject forKey:aKey cost:0];
}
/*!
Adds an object with a cost into the cache.
@param anObject the object to add in the cache
@param aKey the object's key
@param aCost the object's cost
*/
- (void)setObject:(id)anObject forKey:(id)aKey cost:(int)aCost
{
// Check if the key already exist
if ([_items objectForKey:aKey])
[self removeObjectForKey:aKey];
// Add object
[_items setObject:[_CPCacheItem cacheItemWithObject:anObject cost:aCost position:++_currentPosition] forKey:aKey];
// Invalid cost cache
_totalCostCache = -1;
// Clean cache to satisfy condition (< totalCostLimit & < countLimit) if necessary
[self _cleanCache];
}
/*!
Removes the object from the cache for the given key.
@param aKey the key of the object to be removed
*/
- (void)removeObjectForKey:(id)aKey
{
// Call delegate method to warn that the object is going to be removed
[self _sendDelegateWillEvictObjectForKey:aKey];
// Remove object
[_items removeObjectForKey:aKey];
// Invalid cost cache
_totalCostCache = -1;
}
/*!
Removes all the objects from the cache.
*/
- (void)removeAllObjects
{
// Call delegate method to warn that the objects are going to be removed
var enumerator = [_items keyEnumerator],
key;
while (key = [enumerator nextObject])
[self _sendDelegateWillEvictObjectForKey:key]
// Remove all objects
[_items removeAllObjects];
// Invalid cost cache and reset position counter
_totalCostCache = -1;
_currentPosition = 0;
}
#pragma mark -
#pragma mark Setters
/*!
Sets the count limit of the cache.
Remove objects if not enough place to keep all of them
@param aCountLimit the new count limit
*/
- (void)setCountLimit:(int)aCountLimit
{
_countLimit = aCountLimit;
[self _cleanCache];
}
/*!
Sets the total cost limit of the cache.
Remove objects if not enough place to keep all of them
@param aTotalCostLimit the new total cost limit
*/
- (void)setTotalCostLimit:(int)aTotalCostLimit
{
_totalCostLimit = aTotalCostLimit;
[self _cleanCache];
}
/*!
Sets the cache's delegate.
@param aDelegate the new delegate
*/
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(cache:willEvictObject:)])
_implementedDelegateMethods |= CPCacheDelegate_cache_willEvictObject_
}
#pragma mark -
#pragma mark Privates
/*
* This method return the number of objects in the cache
*/
- (int)_count
{
return [_items count];
}
/*
* This method return the total cost (addition of all object's cost in the cache)
*/
- (int)_totalCost
{
if (_totalCostCache >= 0)
return _totalCostCache;
var enumerator = [_items objectEnumerator],
value;
_totalCostCache = 0;
while (value = [enumerator nextObject])
_totalCostCache += [value cost];
return _totalCostCache;
}
/*
* This method resequence the position of objects
* Otherwise the position value could rise until to cause problem
*/
- (void)_resequencePosition
{
_currentPosition = 1;
// Sort keys by position
var sortedKeys = [[_items allKeys] sortedArrayUsingFunction:
function(k1, k2) {
return [[[_items objectForKey:k1] position] compare:[[_items objectForKey:k2] position]]; }];
// Affect new positions
for (var i = 0; i < sortedKeys.length; ++i)
[[_items objectForKey:sortedKeys[i]] setPosition:_currentPosition++];
}
/*
* Check if the totalCostLimit is exceeded
*/
- (BOOL)_isTotalCostLimitExceeded
{
return ([self _totalCost] > _totalCostLimit && _totalCostLimit > 0);
}
/*
* Check if the countLimit is exceeded
*/
- (BOOL)_isCountLimitExceeded
{
return ([self _count] > _countLimit && _countLimit > 0);
}
/*
* This method clean the cache if the totalCost or the count exceeds the totalCostLimit or the countLimit
* until to satisfy condition (totalCost < totalCostLimit and count < countLimit)
*/
- (void)_cleanCache
{
// Check if the condition is satisfied
if (![self _isTotalCostLimitExceeded] && ![self _isCountLimitExceeded])
return;
// Sort keys by position
var sortedKeys = [[_items allKeys] sortedArrayUsingFunction:
function(k1, k2) {
return [[[_items objectForKey:k1] position] compare:[[_items objectForKey:k2] position]]; }];
// Remove oldest objects until to satisfy the break condition
for (var i = 0; i < sortedKeys.length; ++i)
{
if (![self _isTotalCostLimitExceeded] && ![self _isCountLimitExceeded])
break;
// Call delegate method to warn that the object is going to be removed
[self _sendDelegateWillEvictObjectForKey:sortedKeys[i]];
// Remove object
[_items removeObjectForKey: sortedKeys[i]];
// Invalid cost cache
_totalCostCache = -1;
}
// Resequence position of all objects
[self _resequencePosition];
}
@end
@implementation CPCache (CPCacheDelegate)
- (void)_sendDelegateWillEvictObjectForKey:(id)aKey
{
if (_implementedDelegateMethods & CPCacheDelegate_cache_willEvictObject_)
[_delegate cache:self willEvictObject:[[_items objectForKey:aKey] object]];
}
@end
/*
* Class _CPCacheItem
* Represent an item of CPCache
* This class allow to associate a cost and a position to an object
*
* Attributes:
* - object: the stored object
* - cost: represent the cost (of memory) of the object
* - position: represent the insertion order to determine the oldest object
*/
@implementation _CPCacheItem : CPObject
{
CPObject _object @accessors(property=object);
int _cost @accessors(property=cost);
int _position @accessors(property=position);
}
+ (id)cacheItemWithObject:(CPObject)anObject cost:(int)aCost position:(int)aPosition
{
var cacheItem = [[self alloc] init];
if (cacheItem)
{
[cacheItem setObject:anObject];
[cacheItem setCost:aCost];
[cacheItem setPosition:aPosition];
}
return cacheItem;
}
@end
+1
View File
@@ -24,6 +24,7 @@
@import "CPArray.j"
@import "CPBundle.j"
@import "CPByteCountFormatter.j"
@import "CPCache.j"
@import "CPCharacterSet.j"
@import "CPCoder.j"
@import "CPComparisonPredicate.j"
+9 -2
View File
@@ -1754,8 +1754,15 @@ ClassDeclarationStatement: function(node, st, c) {
ivar = {"type": ivarType, "name": ivarName},
accessors = ivarDecl.accessors;
if (ivars[ivarName])
throw compiler.error_message("Instance variable '" + ivarName + "' is already declared for class " + className, ivarDecl.id);
var checkIfIvarIsAlreadyDeclaredAndInSuperClass = function(aClassDef, recursiveFunction) {
if (aClassDef.ivars[ivarName])
throw compiler.error_message("Instance variable '" + ivarName + "' is already declared for class " + className + (aClassDef.name !== className ? " in superclass " + aClassDef.name : ""), ivarDecl.id);
if (aClassDef.superClass)
recursiveFunction(aClassDef.superClass, recursiveFunction);
}
// Check if ivar is already declared in this class or its super classes.
checkIfIvarIsAlreadyDeclaredAndInSuperClass(classDef, checkIfIvarIsAlreadyDeclaredAndInSuperClass);
var isTypeDefined = !ivarTypeIsClass || typeof global[ivarType] !== "undefined" || typeof window[ivarType] !== "undefined"
|| compiler.getClassDef(ivarType) || compiler.getTypeDef(ivarType) || ivarType == classDef.name;
+73 -1
View File
@@ -699,6 +699,78 @@ var methodCalled;
[self assert:expectedRestult equals:methodCalled];
}
- (void)testToolTipInitialEmpty
{
[self assert:nil equals:view._toolTip];
[self assert:nil equals:view._toolTipInstalled];
[self assert:nil equals:view._toolTipFunctionIn];
[self assert:nil equals:view._toolTipFunctionOut];
}
- (void)testToolTipWithToolTipAndNoWindow
{
[view setToolTip:@"tooltip"];
[self assert:@"tooltip" equals:view._toolTip];
[self assert:nil equals:view._toolTipInstalled];
[self assert:nil equals:view._toolTipFunctionIn];
[self assert:nil equals:view._toolTipFunctionOut];
}
- (void)testToolTipWithToolTipAndWindow
{
[view setToolTip:@"tooltip"];
[[window contentView] addSubview:view]
[self assert:@"tooltip" equals:view._toolTip];
[self assertTrue:view._toolTipInstalled];
[self assertTrue:!!view._toolTipFunctionIn];
[self assertTrue:!!view._toolTipFunctionOut];
}
- (void)testToolTipWithToolTipAndWindowThenNoWindow
{
[view setToolTip:@"tooltip"];
[[window contentView] addSubview:view]
[view removeFromSuperview];
[self assert:@"tooltip" equals:view._toolTip];
[self assert:NO equals:view._toolTipInstalled];
[self assert:nil equals:view._toolTipFunctionIn];
[self assert:nil equals:view._toolTipFunctionOut];
}
- (void)testToolTipWithNoToolTipAndWindowThenNoWindowThenToolTip
{
[self assert:nil equals:view._toolTip];
[self assert:nil equals:view._toolTipInstalled];
[self assert:nil equals:view._toolTipFunctionIn];
[self assert:nil equals:view._toolTipFunctionOut];
[[window contentView] addSubview:view];
[self assert:nil equals:view._toolTip];
[self assert:nil equals:view._toolTipInstalled];
[self assert:nil equals:view._toolTipFunctionIn];
[self assert:nil equals:view._toolTipFunctionOut];
[view setToolTip:@"tooltip"];
[self assert:@"tooltip" equals:view._toolTip];
[self assertTrue:view._toolTipInstalled];
[self assertTrue:!!view._toolTipFunctionIn];
[self assertTrue:!!view._toolTipFunctionOut];
[view removeFromSuperview];
[self assert:@"tooltip" equals:view._toolTip];
[self assert:NO equals:view._toolTipInstalled];
[self assert:nil equals:view._toolTipFunctionIn];
[self assert:nil equals:view._toolTipFunctionOut];
}
@end
@implementation CPLayoutView : CPView
@@ -747,4 +819,4 @@ var methodCalled;
return YES;
}
@end
@end
+14
View File
@@ -0,0 +1,14 @@
@import <Foundation/CPCache.j>
@implementation CPCacheItemTest : OJTestCase
- (void)testCacheItemWithObjectCostPosition
{
var cacheItem = [_CPCacheItem cacheItemWithObject:"Hello Cappuccino!" cost:50 position:1];
[self assert:[cacheItem object] equals:"Hello Cappuccino!"];
[self assert:[cacheItem cost] equals:50];
[self assert:[cacheItem position] equals:1];
}
@end
+411
View File
@@ -0,0 +1,411 @@
@import <Foundation/CPCache.j>
/*
* CPCacheTest tests all methods from CPCache
*/
@implementation CPCacheTest : OJTestCase<CPCacheDelegate>
{
// Parameters to check delegate
int _countDelegateExecuted;
CPArray _caches;
CPArray _objects;
}
- (void)setUp
{
// Initialize data to check delegate
_countDelegateExecuted = 0;
_caches = [[CPArray alloc] init];
_objects = [[CPArray alloc] init];
}
/*
* Delegate method, called when an object is evicted
*/
- (void)cache:(CPCache)cache willEvictObject:(id)obj
{
_countDelegateExecuted++;
[_caches addObject:cache];
[_objects addObject:obj];
}
/*
* Tests methods of CPCache
*/
- (void)testInit
{
var cache = [[CPCache alloc] init];
// Private attributes
[self assert:CPCache equals:[cache class]];
[self assert:CPDictionary equals:[cache._items class]];
[self assert:0 equals:cache._currentPosition];
[self assert:-1 equals:cache._totalCostCache];
[self assert:0 equals:cache._implementedDelegateMethods];
// Public attributes
[self assert:@"" equals:[cache name]];
[self assert:0 equals:[cache countLimit]];
[self assert:0 equals:[cache totalCostLimit]];
[self assert:nil equals:[cache delegate]];
}
- (void)testObjectForKey
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setObject:@"Object1" forKey:@"key1"];
// With valid key
[self assert:@"Object1" equals:[cache objectForKey:@"key1"]];
// With invalid key
[self assert:nil equals:[cache objectForKey:@"key666"]];
// With nil key
[self assert:nil equals:[cache objectForKey:nil]];
}
- (void)testSetObjectForKeyDefault
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
// Check result when add key in empty cache
[cache setObject:@"Object1" forKey:@"key1"]
[self assert:@"Object1" equals:[cache objectForKey:@"key1"]];
// Check delegate
[self assert:0 equals:_countDelegateExecuted];
[self assert:0 equals:[_caches count]];
[self assert:0 equals:[_objects count]];
}
- (void)testSetObjectForKeyWithExistingKey
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
[cache setObject:@"Object1" forKey:@"key1"];
[cache setObject:@"Object2" forKey:@"key2"];
// Check result when add object with existing key in cache
[cache setObject:@"Object3" forKey:@"key1"];
[self assert:@"Object3" equals:[cache objectForKey:@"key1"]];
[self assert:@"Object2" equals:[cache objectForKey:@"key2"]];
// Check delegate
[self assert:1 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
}
- (void)testSetObjectForKeyDiscardByCost
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
[cache setTotalCostLimit:100];
[cache setObject:@"Object1" forKey:@"key1" cost:50];
[cache setObject:@"Object2" forKey:@"key2" cost:50];
// Check result when add key in cache with total cost limit
[cache setObject:@"Object3" forKey:@"key3" cost:1];
[self assert:nil equals:[cache objectForKey:@"key1"]];
[self assert:@"Object2" equals:[cache objectForKey:@"key2"]];
[self assert:@"Object3" equals:[cache objectForKey:@"key3"]];
// Check delegate
[self assert:1 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
}
- (void)testSetObjectForKeyDiscardByCount
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
[cache setCountLimit:2];
[cache setObject:@"Object1" forKey:@"key1"];
[cache setObject:@"Object2" forKey:@"key2"];
// Check result when add key in cache with count limit
[cache setObject:@"Object3" forKey:@"key3"];
[self assert:nil equals:[cache objectForKey:@"key1"]];
[self assert:@"Object2" equals:[cache objectForKey:@"key2"]];
[self assert:@"Object3" equals:[cache objectForKey:@"key3"]];
// Check delegate
[self assert:1 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
}
- (void)testRemoveObjectForKey
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
[cache setObject:@"Object1" forKey:@"key1"];
// Remove object
[cache removeObjectForKey:@"key1"];
[self assert:nil equals:[cache objectForKey:@"key1"]];
// Check delegate
[self assert:1 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
}
- (void)testRemoveAllObjects
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
[cache setObject:@"Object1" forKey:@"key1"];
[cache setObject:@"Object2" forKey:@"key2"];
// Remove all objects
[cache removeAllObjects];
[self assert:nil equals:[cache objectForKey:@"key1"]];
[self assert:nil equals:[cache objectForKey:@"key2"]];
// Check delegate
[self assert:2 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
[self assert:cache equals:[_caches objectAtIndex:1]];
[self assert:@"Object2" equals:[_objects objectAtIndex:1]];
}
/*
* Accessors and mutators
*/
- (void)testSetCountLimit
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
[cache setObject:@"Object1" forKey:@"key1"];
[cache setObject:@"Object2" forKey:@"key2"];
[cache setObject:@"Object3" forKey:@"key3"];
// Set count limit
[cache setCountLimit:2];
[self assert:nil equals:[cache objectForKey:@"key1"]];
[self assert:@"Object2" equals:[cache objectForKey:@"key2"]];
[self assert:@"Object3" equals:[cache objectForKey:@"key3"]];
// Check delegate
[self assert:1 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
// Check new count limit
[self assert:2 equals:[cache countLimit]];
}
- (void)testSetTotalCostLimit
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
[cache setObject:@"Object1" forKey:@"key1" cost:50];
[cache setObject:@"Object2" forKey:@"key2" cost:10];
[cache setObject:@"Object3" forKey:@"key3" cost:70];
// Set total cost limit
[cache setTotalCostLimit:100];
[self assert:nil equals:[cache objectForKey:@"key1"]];
[self assert:@"Object2" equals:[cache objectForKey:@"key2"]];
[self assert:@"Object3" equals:[cache objectForKey:@"key3"]];
// Check delegate
[self assert:1 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
// Check total cost limit
[self assert:100 equals:[cache totalCostLimit]];
}
- (void)testSetDelegate
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setDelegate:self];
[self assert:self equals:[cache delegate]];
[self assert:(1 << 1) equals:cache._implementedDelegateMethods]
}
/*
* Test private methods
*/
- (void)testCount
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setObject:@"Object1" forKey:@"key1" cost:50];
[cache setObject:@"Object2" forKey:@"key2" cost:10];
[cache setObject:@"Object3" forKey:@"key3" cost:70];
[self assert:3 equals:[cache _count]];
}
- (void)testTotalCost
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setObject:@"Object1" forKey:@"key1" cost:50];
[cache setObject:@"Object2" forKey:@"key2" cost:10];
[cache setObject:@"Object3" forKey:@"key3" cost:70];
[self assert:130 equals:[cache _totalCost]];
// Hack totalCost then invalidate it to be sure that it is recomputed
cache._totalCostCache = 650;
[self assert:650 equals:[cache _totalCost]];
cache._totalCostCache = -1;
[self assert:130 equals:[cache _totalCost]];
}
- (void)testResequencePosition
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setObject:@"Object1" forKey:@"key1" cost:50]; // 1 - 1
[cache setObject:@"Object2" forKey:@"key2" cost:10];
[cache setObject:@"Object3" forKey:@"key3" cost:70]; // 3 - 2
[cache removeObjectForKey:@"key2"]
[cache setObject:@"Object4" forKey:@"key4" cost:70]; // 4 - 3
// Before resequence
[self assert:1 equals:[[cache._items objectForKey:@"key1"] position]];
[self assert:3 equals:[[cache._items objectForKey:@"key3"] position]];
[self assert:4 equals:[[cache._items objectForKey:@"key4"] position]];
[cache _resequencePosition];
// After resequence
[self assert:1 equals:[[cache._items objectForKey:@"key1"] position]];
[self assert:2 equals:[[cache._items objectForKey:@"key3"] position]];
[self assert:3 equals:[[cache._items objectForKey:@"key4"] position]];
}
- (void)testIsTotalCostLimitExceeded
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setObject:@"Object1" forKey:@"key1" cost:50];
// Not exceed (because of not limit)
[self assert:NO equals:[cache _isTotalCostLimitExceeded]];
// Not exceed (with limit)
[cache setTotalCostLimit:100];
[self assert:NO equals:[cache _isTotalCostLimitExceeded]];
// Exceed (by hacking the cost of object)
[[cache._items objectForKey:@"key1"] setCost: 150];
cache._totalCostCache = -1;
[self assert:YES equals:[cache _isTotalCostLimitExceeded]];
}
- (void)testIsCountLimitExceeded
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setObject:@"Object1" forKey:@"key1"];
// Not exceed (because of not limit)
[self assert:NO equals:[cache _isCountLimitExceeded]];
// Not exceed (with limit)
[cache setCountLimit:1];
[self assert:NO equals:[cache _isCountLimitExceeded]];
// Exceed (by hacking the items)
[cache._items setObject:[_CPCacheItem cacheItemWithObject:@"Object2" cost:0 position:3] forKey:@"key2"];
[self assert:YES equals:[cache _isCountLimitExceeded]];
}
- (void)testCleanCacheWithoutDiscarding
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setTotalCostLimit: 100];
[cache setCountLimit: 2];
[cache setDelegate:self];
[cache setObject:@"Object1" forKey:@"key1" cost:50];
[cache setObject:@"Object2" forKey:@"key2" cost:40];
// Set total cost limit
[cache _cleanCache];
[self assert:@"Object1" equals:[cache objectForKey:@"key1"]];
[self assert:@"Object2" equals:[cache objectForKey:@"key2"]];
// Check delegate
[self assert:0 equals:_countDelegateExecuted];
}
- (void)testCleanCacheWithCostDiscarding
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setTotalCostLimit: 100];
[cache setDelegate:self];
[cache setObject:@"Object1" forKey:@"key1" cost:50];
[cache setObject:@"Object2" forKey:@"key2" cost:40];
// Hack cost of object
[[cache._items objectForKey:@"key2"] setCost:80];
cache._totalCostCache = -1;
// Set total cost limit
[cache _cleanCache];
[self assert:nil equals:[cache objectForKey:@"key1"]];
[self assert:@"Object2" equals:[cache objectForKey:@"key2"]];
// Check delegate
[self assert:1 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
}
- (void)testCleanCacheWithCountDiscarding
{
// Setup cache
var cache = [[CPCache alloc] init];
[cache setCountLimit:2];
[cache setDelegate:self];
[cache setObject:@"Object1" forKey:@"key1"];
[cache setObject:@"Object2" forKey:@"key2"];
// Hack items
[cache._items setObject:[_CPCacheItem cacheItemWithObject:@"Object3" cost:0 position:3] forKey:@"key3"];
// Set total cost limit
[cache _cleanCache];
[self assert:nil equals:[cache objectForKey:@"key1"]];
[self assert:@"Object2" equals:[cache objectForKey:@"key2"]];
[self assert:@"Object3" equals:[cache objectForKey:@"key3"]];
// Check delegate
[self assert:1 equals:_countDelegateExecuted];
[self assert:cache equals:[_caches objectAtIndex:0]];
[self assert:@"Object1" equals:[_objects objectAtIndex:0]];
}
@end
@@ -0,0 +1,104 @@
/*
* AppController.j
* CPPlatformWindow
*
* Created by You on October 30, 2014.
* Copyright 2014, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@implementation AppController : CPObject
{
@outlet CPWindow theWindow;
@outlet CPWindow externalWindow;
CPPlatformWindow platformWindow;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
// This is called when the application is done loading.
[[CPPlatformWindow alloc] initWithWindow:externalWindow];
[externalWindow setDelegate:self];
}
- (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];
}
- (IBAction)showWindow:(id)sender
{
[externalWindow orderFront:sender];
}
- (IBAction)closeWindow:(id)sender
{
[externalWindow orderOut:sender];
}
- (IBAction)changeFrame:(id)sender
{
[externalWindow setFrame:CGRectMake(250, 250, 200, 200)];
}
- (IBAction)showAlert:(id)sender
{
var alert = [CPAlert alertWithMessageText:@"rer" defaultButton:"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:"Multiple login failures may result in blocked access to the system."];
[alert beginSheetModalForWindow:externalWindow];
}
#pragma mark -
#pragma mark Delegate
- (void)windowDidBecomeKey:(CPNotification)aNotification
{
CPLog.debug("windowDidBecomeKey:");
}
- (void)windowDidBecomeMain:(CPNotification)aNotification
{
CPLog.debug("windowDidBecomeMain:");
}
- (void)windowDidEndSheet:(CPNotification)aNotification
{
CPLog.debug("windowDidEndSheet:");
}
- (void)windowDidMove:(CPNotification)aNotification
{
CPLog.debug("windowDidMove:");
}
- (void)windowDidResignKey:(CPNotification)aNotification
{
CPLog.debug("windowDidResignKey:");
}
- (void)windowDidResignMain:(CPNotification)aNotification
{
CPLog.debug("windowDidResignMain:");
}
- (void)windowDidResize:(CPNotification)aNotification
{
CPLog.debug("windowDidResize:");
}
- (void)windowWillClose:(CPWindow)aWindow
{
CPLog.debug("windowWillClose:");
}
@end
+14
View File
@@ -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>CPPlatformWindow</string>
<key>CPBundleVersion</key>
<string>1.0</string>
<key>CPHumanReadableCopyright</key>
<string>Copyright © 2014, Your Company All rights reserved.</string>
</dict>
</plist>
+184
View File
@@ -0,0 +1,184 @@
/*
* Jakefile
* CPPlatformWindow
*
* Created by You on October 30, 2014.
* Copyright 2014, 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 = "CPPlatformWindow";
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", "CPPlatformWindow.build", configuration));
task.setBuildPath(FILE.join("Build", configuration));
task.setProductName("CPPlatformWindow");
task.setIdentifier("com.yourcompany.CPPlatformWindow");
task.setVersion("1.0");
task.setAuthor("Your Company");
task.setEmail("feedback @nospam@ yourcompany.com");
task.setSummary("CPPlatformWindow");
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("-O");
});
task ("default", [projectName], function()
{
printResults(configuration);
});
task ("build", ["default"], function()
{
updateApplicationSize();
});
task ("debug", function()
{
ENV["CONFIGURATION"] = "Debug";
JAKE.subjake(["."], "build", ENV);
});
task ("release", function()
{
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, "CPPlatformWindow.app"));
printResults("Desktop")
});
task ("run-desktop", ["desktop"], function()
{
OS.system([FILE.join("Build", "Desktop", projectName, "CPPlatformWindow.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", ENV["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 (ENV["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", ENV["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", ENV["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();
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="en">
<!--
index-debug.html
CPPlatformWindow
Created by You on October 30, 2014.
Copyright 2014, 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>CPPlatformWindow</title>
<!-- Custom javascript goes here -->
<!-- End custom javascript -->
<script type="text/javascript">
OBJJ_MAIN_FILE = "main.j";
OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks"];
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: -1000;
}
#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>
+161
View File
@@ -0,0 +1,161 @@
<!DOCTYPE html>
<html lang="en">
<!--
index.html
CPPlatformWindow
Created by You on October 30, 2014.
Copyright 2014, 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>CPPlatformWindow</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: -1000;
}
#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>
+18
View File
@@ -0,0 +1,18 @@
/*
* AppController.j
* CPPlatformWindow
*
* Created by You on October 30, 2014.
* Copyright 2014, Your Company All rights reserved.
*/
@import <Foundation/Foundation.j>
@import <AppKit/AppKit.j>
@import "AppController.j"
function main(args, namedArgs)
{
CPApplicationMain(args, namedArgs);
}
@@ -0,0 +1,28 @@
// Expected output: 256
/*
START_EXPECTED
Error on line 10778 of file [unknown]
SyntaxError:
int myIvar;
^
ERROR line 12 in file:[__PATH__]: Instance variable 'myIvar' is already declared for class MySubclass in superclass MySuperclass
END_EXPECTED
*/
@import <Foundation/Foundation.j>
@implementation MySuperclass : CPObject
{
int myIvar;
}
@end
@implementation MySubclass : MySuperclass
{
int myIvar;
}
@end
+1 -1
View File
@@ -7,7 +7,7 @@ Error on line 10001 of file [unknown]
SyntaxError:
@implementation MyType : CPObject
^
ERROR line 5 in file:[__PATH__]: MyType is already declared as type
ERROR line 5 in file:[__PATH__]: MyType is already declared as a type
END_EXPECTED
*/
+1
View File
@@ -55,6 +55,7 @@ def cleanup_output(output):
output = output.replace(" ", "")
output = output.replace("\n", "")
output = output.replace("[0m", "")
output = re.sub('\d*offile\[unknown\]', '', output)
return re.sub('[^\s!-~]', '', output)
@@ -20,11 +20,16 @@
{
var button = [[CPButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 20.0)];
[button setValue:[CPColor blueColor] forThemeAttribute:@"bezel-color"];
[button setValue:[CPColor greenColor] forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted];
var themedButtonValues =
[
[@"text-color", [CPColor redColor]],
[@"text-color", [CPColor yellowColor], CPThemeStateHighlighted],
[button setValue:[CPColor redColor] forThemeAttribute:@"text-color"];
[button setValue:[CPColor yellowColor] forThemeAttribute:@"text-color" inState:CPThemeStateHighlighted];
[@"bezel-color", [CPColor blueColor]],
[@"bezel-color", [CPColor greenColor], CPThemeStateHighlighted],
];
[self registerThemeValues:themedButtonValues forView:button];
[button setTitle:@"Yikes!"];
-1
View File
@@ -409,7 +409,6 @@ var NSButtonIsBorderedMask = 0x00800000,
@implementation NSButtonCell : NSActionCell
{
BOOL _isBordered @accessors(readonly, getter=isBordered);
int _bezelStyle @accessors(readonly, getter=bezelStyle);
CPString _title @accessors(readonly, getter=title);
-1
View File
@@ -177,7 +177,6 @@ var NSDatePickerDefaultSize = 22,
BOOL _drawsBackground @accessors(getter=drawsBackground);
CPDate _minDate @accessors(getter=minDate);
CPDate _maxDate @accessors(getter=maxDate);
CPDateFormatter _formatter @accessors(getter=formatter);
CPInteger _datePickerMode @accessors(getter=datePickerMode);
CPInteger _datePickerElements @accessors(getter=datePickerElements);
CPInteger _datePickerType @accessors(getter=datePickerType);