mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
Merge remote-tracking branch 'upstream/master' into CPTabView
This commit is contained in:
+3
-1
@@ -26,6 +26,7 @@
|
||||
@import "CPAccordionView.j"
|
||||
@import "CPAlert.j"
|
||||
@import "CPAnimation.j"
|
||||
@import "CPAppearance.j"
|
||||
@import "CPApplication.j"
|
||||
@import "CPArrayController.j"
|
||||
@import "CPBezierPath.j"
|
||||
@@ -106,7 +107,8 @@
|
||||
@import "CPView.j"
|
||||
@import "CPViewAnimation.j"
|
||||
@import "CPViewController.j"
|
||||
@import "CPVisualEffectView.j"
|
||||
@import "CPWebView.j"
|
||||
@import "CPWindow.j"
|
||||
@import "CPWindowController.j"
|
||||
@import "CPWorkspace.j"
|
||||
@import "CPWorkspace.j"
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* CPAppearance.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Antoine Mercadal.
|
||||
* 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>
|
||||
@import "CPTheme.j"
|
||||
|
||||
CPAppearanceNameAqua = @"CPAppearanceNameAqua";
|
||||
CPAppearanceNameLightContent = @"CPAppearanceNameLightContent";
|
||||
CPAppearanceNameVibrantDark = @"CPAppearanceNameVibrantDark";
|
||||
CPAppearanceNameVibrantLight = @"CPAppearanceNameVibrantLight";
|
||||
|
||||
var _CPAppearanceCurrent = nil,
|
||||
_CPAppearancesRegistry = @{};
|
||||
|
||||
|
||||
@protocol CPAppearanceCustomization <CPObject>
|
||||
|
||||
@required
|
||||
- (CPAppearance)appearance;
|
||||
- (void)setAppearance:(CPAppearance)appearance;
|
||||
- (CPAppearance)effectiveAppearance;
|
||||
- (void)setEffectiveAppearance:(CPAppearance)appearance;
|
||||
|
||||
@end
|
||||
|
||||
CPThemeStateAppearanceAqua = CPThemeState("appearance-aqua");
|
||||
CPThemeStateAppearanceLightContent = CPThemeState("appearance-light-content");
|
||||
CPThemeStateAppearanceVibrantLight = CPThemeState("appearance-vibrant-light");
|
||||
CPThemeStateAppearanceVibrantDark = CPThemeState("appearance-vibrant-dark");
|
||||
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
|
||||
A CPAppareance represents the appearance of an to a subset of UI elements.
|
||||
This is a very lightweight implementation of the NSAppearance system, but
|
||||
We are using it for compliance, and especially for the CPVisualEffectView
|
||||
*/
|
||||
@implementation CPAppearance : CPObject
|
||||
{
|
||||
BOOL _allowsVibrancy @accessors(property=allowsVibrancy);
|
||||
|
||||
CPString _name;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Class Methods
|
||||
|
||||
/*! Returns the current default CPAppearance
|
||||
*/
|
||||
+ (CPAppearance)currentAppearance
|
||||
{
|
||||
if (!_CPAppearanceCurrent)
|
||||
_CPAppearanceCurrent = [CPAppearance appearanceNamed:CPAppearanceNameAqua];
|
||||
|
||||
return _CPAppearanceCurrent;
|
||||
}
|
||||
|
||||
/*! Sets the current default CPAppearance
|
||||
@param appearance the new current appearance
|
||||
*/
|
||||
+ (void)setCurrentAppearance:(CPAppearance)anAppearance
|
||||
{
|
||||
_CPAppearanceCurrent = anAppearance;
|
||||
}
|
||||
|
||||
/*! Returns the CPAppearance object with the given name
|
||||
@param name the name of the appearance
|
||||
*/
|
||||
+ (CPAppearance)appearanceNamed:(CPString)aName
|
||||
{
|
||||
if (![_CPAppearancesRegistry containsKey:aName])
|
||||
{
|
||||
[_CPAppearancesRegistry setObject:[[CPAppearance alloc] initWithAppearanceNamed:aName bundle:nil]
|
||||
forKey:aName];
|
||||
}
|
||||
|
||||
return [_CPAppearancesRegistry objectForKey:aName];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
/*! Creates a CPAppearance object initialized to the specified appearance file in the specified bundle
|
||||
This method does actually nothing special. It just creates a default appearance object
|
||||
*/
|
||||
- (id)initWithAppearanceNamed:(CPString)aName bundle:(CPBundle)bundle
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_name = aName;
|
||||
_allowsVibrancy = YES;
|
||||
|
||||
if ([_CPAppearancesRegistry containsKey:aName])
|
||||
[CPException raise:CPInternalInconsistencyException reason:"Appearance with name '" + aName + "' is already declared."];
|
||||
|
||||
[_CPAppearancesRegistry setObject:self forKey:aName];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Implementation
|
||||
|
||||
- (BOOL)isEqual:(id)anObject
|
||||
{
|
||||
if (![anObject isKindOfClass:CPAppearance])
|
||||
return NO;
|
||||
|
||||
return self._name == anObject._name;
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return @"<CPAppearance @" + [self UID] + @" name: " + _name + ">";
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark CPCoding
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_name = [aCoder decodeObjectForKey:@"_name"];
|
||||
_allowsVibrancy = [aCoder decodeBoolForKey:@"_allowsVibrancy"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[aCoder encodeObject:_name forKey:@"_name"];
|
||||
[aCoder encodeBool:_allowsVibrancy forKey:@"_allowsVibrancy"];
|
||||
}
|
||||
|
||||
@end
|
||||
+47
-6
@@ -47,6 +47,8 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
@protocol CPApplicationDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (CPApplicationTerminateReply)applicationShouldTerminate:(CPApplication)sender;
|
||||
- (CPString)applicationShouldTerminateMessage:(CPApplication)sender;
|
||||
- (void)applicationDidBecomeActive:(CPNotification)aNotification;
|
||||
- (void)applicationDidChangeScreenParameters:(CPNotification)aNotification;
|
||||
- (void)applicationDidFinishLaunching:(CPNotification)aNotification;
|
||||
@@ -58,6 +60,9 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
|
||||
@end
|
||||
|
||||
var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
|
||||
CPApplicationDelegate_applicationShouldTerminateMessage_ = 1 << 1;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPApplication
|
||||
@@ -103,6 +108,8 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
|
||||
//
|
||||
id <CPApplicationDelegate> _delegate;
|
||||
CPInteger _implementedDelegateMethods;
|
||||
|
||||
BOOL _finishedLaunching;
|
||||
BOOL _isActive;
|
||||
|
||||
@@ -165,6 +172,8 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
if (_delegate == aDelegate)
|
||||
return;
|
||||
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter],
|
||||
delegateNotifications =
|
||||
[
|
||||
@@ -205,6 +214,12 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
if ([_delegate respondsToSelector:selector])
|
||||
[defaultCenter addObserver:_delegate selector:selector name:notificationName object:self];
|
||||
}
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
|
||||
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminate_
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationShouldTerminateMessage:)])
|
||||
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminateMessage_
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -426,12 +441,7 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
{
|
||||
// callback method for terminate:
|
||||
if (didCloseAll)
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
|
||||
[self replyToApplicationShouldTerminate:[_delegate applicationShouldTerminate:self]];
|
||||
else
|
||||
[self replyToApplicationShouldTerminate:YES];
|
||||
}
|
||||
[self replyToApplicationShouldTerminate:[self _sendDelegateApplicationShouldTerminate]];
|
||||
}
|
||||
|
||||
- (void)replyToApplicationShouldTerminate:(BOOL)terminate
|
||||
@@ -445,6 +455,9 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
|
||||
- (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps
|
||||
{
|
||||
if (_isActive)
|
||||
return;
|
||||
|
||||
[self _willBecomeActive];
|
||||
|
||||
[CPPlatform activateIgnoringOtherApps:shouldIgnoreOtherApps];
|
||||
@@ -455,6 +468,9 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
|
||||
- (void)deactivate
|
||||
{
|
||||
if (!_isActive)
|
||||
return;
|
||||
|
||||
[self _willResignActive];
|
||||
|
||||
[CPPlatform deactivate];
|
||||
@@ -480,6 +496,15 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
- (void)run
|
||||
{
|
||||
[self finishLaunching];
|
||||
[self sendEvent:[CPEvent otherEventWithType:CPAppKitDefined
|
||||
location:CGPointMakeZero()
|
||||
modifierFlags:0
|
||||
timestamp:[CPEvent currentTimestamp]
|
||||
windowNumber:[_keyWindow windowNumber]
|
||||
context:nil
|
||||
subtype:nil
|
||||
data1:nil
|
||||
data2:nil]];
|
||||
}
|
||||
|
||||
// Managing the Event Loop
|
||||
@@ -1195,6 +1220,22 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateApplicationShouldTerminate
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPApplicationDelegate_applicationShouldTerminate_))
|
||||
return YES;
|
||||
|
||||
return [_delegate applicationShouldTerminate:self];
|
||||
}
|
||||
|
||||
- (CPString)_sendDelegateApplicationShouldTerminateMessage
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPApplicationDelegate_applicationShouldTerminateMessage_))
|
||||
return @"You have attempted to leave this page. Are you sure you want to exit this page?";
|
||||
|
||||
return [_delegate applicationShouldTerminateMessage:self];
|
||||
}
|
||||
|
||||
- (void)_didResignActive
|
||||
{
|
||||
if (self._activeMenu)
|
||||
|
||||
@@ -31,6 +31,7 @@ CPApplicationWillResignActiveNotification = @"CPApplicationWillResignA
|
||||
CPApplicationDidResignActiveNotification = @"CPApplicationDidResignActiveNotification";
|
||||
CPApplicationDidChangeScreenParametersNotification = @"CPApplicationDidChangeScreenParametersNotification";
|
||||
|
||||
@typedef CPApplicationTerminateReply
|
||||
CPTerminateNow = YES;
|
||||
CPTerminateCancel = NO;
|
||||
CPTerminateLater = -1; // not currently supported
|
||||
|
||||
+2
-2
@@ -665,10 +665,10 @@ CPButtonImageOffset = 3.0;
|
||||
*/
|
||||
- (void)sizeToFit
|
||||
{
|
||||
[self setFrameSize:[self _minimumFrameSize]];
|
||||
|
||||
[self layoutSubviews];
|
||||
|
||||
[self setFrameSize:[self _minimumFrameSize]];
|
||||
|
||||
if ([self ephemeralSubviewNamed:@"content-view"])
|
||||
[self layoutSubviews];
|
||||
}
|
||||
|
||||
@@ -112,6 +112,8 @@
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
[super awakeFromCib];
|
||||
|
||||
var view = [self superview],
|
||||
subview = self;
|
||||
|
||||
|
||||
+1
-1
@@ -195,7 +195,7 @@
|
||||
|
||||
- (CGRect)documentVisibleRect
|
||||
{
|
||||
return [self convertRect:[self bounds] fromView:_documentView];
|
||||
return [_documentView visibleRect];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -60,6 +60,8 @@ var CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_
|
||||
|
||||
@end
|
||||
|
||||
var HORIZONTAL_MARGIN = 2;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPCollectionView
|
||||
@@ -88,9 +90,6 @@ var CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_
|
||||
@param indices the indices to obtain drag types
|
||||
@return an array of drag types (CPString)
|
||||
*/
|
||||
|
||||
var HORIZONTAL_MARGIN = 2;
|
||||
|
||||
@implementation CPCollectionView : CPView
|
||||
{
|
||||
CPArray _content;
|
||||
|
||||
+11
-2
@@ -74,7 +74,7 @@ var CPComboBoxTextSubview = @"text",
|
||||
BOOL _usesDataSource;
|
||||
CGSize _intercellSpacing;
|
||||
CPArray _items;
|
||||
id<CPComboBoxDataSource> _dataSource;
|
||||
id <CPComboBoxDataSource> _dataSource;
|
||||
CPInteger _implementedDelegateComboBoxMethods;
|
||||
CPString _selectedStringValue;
|
||||
float _itemHeight;
|
||||
@@ -843,7 +843,16 @@ var CPComboBoxTextSubview = @"text",
|
||||
// In FireFox this needs to be done in setTimeout, otherwise there is no caret
|
||||
// We have to save the input element now, when we lose focus it will change.
|
||||
var element = [self _inputElement];
|
||||
window.setTimeout(function() { element.focus(); }, 0);
|
||||
window.setTimeout(function() {
|
||||
|
||||
// This will prevent to jump to the focused element
|
||||
var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
|
||||
|
||||
element.focus();
|
||||
|
||||
[self _restorePreviousScrollingOrigin:previousScrollingOrigin];
|
||||
|
||||
}, 0);
|
||||
#endif
|
||||
|
||||
return NO;
|
||||
|
||||
+52
-8
@@ -42,13 +42,6 @@
|
||||
|
||||
@end
|
||||
|
||||
@typedef CPTextAlignment
|
||||
CPLeftTextAlignment = 0;
|
||||
CPRightTextAlignment = 1;
|
||||
CPCenterTextAlignment = 2;
|
||||
CPJustifiedTextAlignment = 3;
|
||||
CPNaturalTextAlignment = 4;
|
||||
|
||||
@typedef CPControlSize
|
||||
CPRegularControlSize = 0;
|
||||
CPSmallControlSize = 1;
|
||||
@@ -126,6 +119,8 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
CGPoint _previousTrackingLocation;
|
||||
|
||||
CPControlSize _controlSize;
|
||||
|
||||
CPWritingDirection _baseWritingDirection @accessors(property=baseWritingDirection);
|
||||
}
|
||||
|
||||
+ (CPDictionary)themeAttributes
|
||||
@@ -240,7 +235,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
*/
|
||||
- (ThemeState)_controlSizeThemeState
|
||||
{
|
||||
switch(_controlSize)
|
||||
switch (_controlSize)
|
||||
{
|
||||
case CPSmallControlSize:
|
||||
return CPThemeStateControlSizeSmall;
|
||||
@@ -1016,6 +1011,49 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
return [self hasThemeState:CPThemeStateHighlighted];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Base writing direction
|
||||
|
||||
/*!
|
||||
Sets the initial writing direction of the receiver
|
||||
@param writingDirection - It could be CPWritingDirectionNatural, CPWritingDirectionLeftToRight, CPWritingDirectionRightToLeft
|
||||
*/
|
||||
- (void)setBaseWritingDirection:(CPWritingDirection)writingDirection
|
||||
{
|
||||
if (writingDirection == _baseWritingDirection)
|
||||
return;
|
||||
|
||||
[self willChangeValueForKey:@"baseWritingDirection"];
|
||||
_baseWritingDirection = writingDirection;
|
||||
[self didChangeValueForKey:@"baseWritingDirection"];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var style;
|
||||
|
||||
switch (_baseWritingDirection)
|
||||
{
|
||||
case CPWritingDirectionNatural:
|
||||
style = "initial";
|
||||
break;
|
||||
|
||||
case CPWritingDirectionLeftToRight:
|
||||
style = "ltr";
|
||||
break;
|
||||
|
||||
case CPWritingDirectionRightToLeft:
|
||||
style = "rtl";
|
||||
break;
|
||||
|
||||
default:
|
||||
style = "initial";
|
||||
}
|
||||
|
||||
_DOMElement.style.direction = style;
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPControlActionKey = @"CPControlActionKey",
|
||||
@@ -1027,6 +1065,7 @@ var CPControlActionKey = @"CPControlActionKey",
|
||||
CPControlSendsActionOnEndEditingKey = @"CPControlSendsActionOnEndEditingKey",
|
||||
CPControlTargetKey = @"CPControlTargetKey",
|
||||
CPControlValueKey = @"CPControlValueKey",
|
||||
CPControlBaseWrittingDirectionKey = @"CPControlBaseWrittingDirectionKey";
|
||||
|
||||
__Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
|
||||
|
||||
@@ -1055,6 +1094,8 @@ var CPControlActionKey = @"CPControlActionKey",
|
||||
[self setFormatter:[aCoder decodeObjectForKey:CPControlFormatterKey]];
|
||||
|
||||
[self setControlSize:[aCoder decodeIntForKey:CPControlControlSizeKey]];
|
||||
|
||||
[self setBaseWritingDirection:[aCoder decodeIntForKey:CPControlBaseWrittingDirectionKey]];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -1089,6 +1130,9 @@ var CPControlActionKey = @"CPControlActionKey",
|
||||
[aCoder encodeObject:_formatter forKey:CPControlFormatterKey];
|
||||
|
||||
[aCoder encodeInt:_controlSize forKey:CPControlControlSizeKey];
|
||||
|
||||
[aCoder encodeInt:_baseWritingDirection forKey:CPControlBaseWrittingDirectionKey];
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -630,14 +630,6 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
return [[_locale objectForKey:CPLocaleCountryCode] isEqualToString:@"US"];
|
||||
}
|
||||
|
||||
/*! Check if we are in the english format or not. Depending on the locale
|
||||
*/
|
||||
- (BOOL)_isEnglishFormat
|
||||
{
|
||||
return [[_locale objectForKey:CPLocaleLanguageCode] isEqualToString:@"en"];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Key event
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ var RADIANS = Math.PI / 180;
|
||||
[_minuteHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"minute-hand-image"]];
|
||||
[_secondHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"second-hand-image"]];
|
||||
|
||||
if ([_datePicker _isEnglishFormat])
|
||||
if ([_datePicker _isAmericanFormat])
|
||||
{
|
||||
if (dateValue.getHours() > 11)
|
||||
[_PMAMTextField setStringValue:@"PM"]
|
||||
|
||||
@@ -198,7 +198,6 @@ var CPZeroKeyCode = 48,
|
||||
else
|
||||
[self _selectTextField:_firstTextField];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*! Select a textField
|
||||
@@ -277,74 +276,99 @@ var CPZeroKeyCode = 48,
|
||||
}
|
||||
}
|
||||
|
||||
/*! performKeyEquivalent event
|
||||
Used for moving in the textField
|
||||
/*!
|
||||
PerformKeyEquivalent event
|
||||
We need to override that to handle the tab key
|
||||
*/
|
||||
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
|
||||
{
|
||||
if (![self isEnabled] || !_currentTextField || [[self window] firstResponder] != _datePicker)
|
||||
return NO;
|
||||
|
||||
var key = [anEvent charactersIgnoringModifiers];
|
||||
|
||||
if (key == CPUpArrowFunctionKey)
|
||||
if ([anEvent charactersIgnoringModifiers] === CPTabCharacter)
|
||||
{
|
||||
[_currentTextField _invalidTimer];
|
||||
[_stepper setDoubleValue:[_currentTextField intValue]];
|
||||
[_stepper performClickUp:self];
|
||||
if ([anEvent modifierFlags] & CPShiftKeyMask)
|
||||
[self insertBacktab:self];
|
||||
else
|
||||
[self insertTab:self];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (key == CPDownArrowFunctionKey)
|
||||
else if ([anEvent charactersIgnoringModifiers] === CPBackTabCharacter)
|
||||
{
|
||||
[_currentTextField _invalidTimer];
|
||||
[_stepper setDoubleValue:[_currentTextField intValue]];
|
||||
[_stepper performClickDown:self];
|
||||
[self insertBacktab:self];
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (key == CPLeftArrowFunctionKey || [anEvent keyCode] == CPTabKeyCode && [anEvent modifierFlags] & CPShiftKeyMask)
|
||||
{
|
||||
if (_currentTextField == _firstTextField && [anEvent keyCode] == CPTabKeyCode)
|
||||
{
|
||||
var previousValidKeyView = [_datePicker previousValidKeyView];
|
||||
|
||||
if (previousValidKeyView)
|
||||
[[self window] makeFirstResponder:previousValidKeyView];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
[self _selectTextField:[_currentTextField previousTextField]];
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (key == CPRightArrowFunctionKey || [anEvent keyCode] == CPTabKeyCode)
|
||||
{
|
||||
if (_currentTextField == _lastTextField && [anEvent keyCode] == CPTabKeyCode)
|
||||
{
|
||||
var nextValidKeyView = [_datePicker nextValidKeyView];
|
||||
|
||||
if (nextValidKeyView)
|
||||
[[self window] makeFirstResponder:nextValidKeyView];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
[self _selectTextField:[_currentTextField nextTextField]];
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([anEvent keyCode] == CPReturnKeyCode)
|
||||
{
|
||||
[_currentTextField _endEditing];
|
||||
|
||||
return [super performKeyEquivalent:anEvent];
|
||||
}
|
||||
|
||||
return [super performKeyEquivalent:anEvent];
|
||||
}
|
||||
|
||||
- (void)insertTab:(id)sender
|
||||
{
|
||||
if (!_currentTextField)
|
||||
return;
|
||||
|
||||
if (_currentTextField == _lastTextField)
|
||||
[[self window] selectNextKeyView:self];
|
||||
else
|
||||
[self moveRight:sender];
|
||||
}
|
||||
|
||||
- (void)moveRight:(id)sender
|
||||
{
|
||||
if (!_currentTextField)
|
||||
return;
|
||||
|
||||
[self _selectTextField:[_currentTextField nextTextField]];
|
||||
}
|
||||
|
||||
- (void)insertBacktab:(id)sender
|
||||
{
|
||||
if (!_currentTextField)
|
||||
return;
|
||||
|
||||
if (_currentTextField == _firstTextField)
|
||||
[[self window] selectPreviousKeyView:self];
|
||||
else
|
||||
[self moveLeft:sender];
|
||||
}
|
||||
|
||||
- (void)moveLeft:(id)sender
|
||||
{
|
||||
if (!_currentTextField)
|
||||
return;
|
||||
|
||||
[self _selectTextField:[_currentTextField previousTextField]];
|
||||
}
|
||||
|
||||
- (void)moveDown:(id)sender
|
||||
{
|
||||
if (!_currentTextField)
|
||||
return;
|
||||
|
||||
[_currentTextField _invalidTimer];
|
||||
[_stepper setDoubleValue:[_currentTextField intValue]];
|
||||
[_stepper performClickDown:self];
|
||||
}
|
||||
|
||||
- (void)moveUp:(id)sender
|
||||
{
|
||||
if (!_currentTextField)
|
||||
return;
|
||||
|
||||
[_currentTextField _invalidTimer];
|
||||
[_stepper setDoubleValue:[_currentTextField intValue]];
|
||||
[_stepper performClickUp:self];
|
||||
}
|
||||
|
||||
- (void)insertNewline:(id)sender
|
||||
{
|
||||
if (!_currentTextField)
|
||||
return;
|
||||
|
||||
[_currentTextField _endEditing];
|
||||
}
|
||||
|
||||
/*! KeyDown event
|
||||
We just care care about the event A/P and every numbers
|
||||
*/
|
||||
@@ -353,7 +377,9 @@ var CPZeroKeyCode = 48,
|
||||
if (![self isEnabled])
|
||||
return;
|
||||
|
||||
if ([_datePicker _isEnglishFormat] && [_currentTextField dateType] == CPAMPMDateType && ([anEvent keyCode] == CPAKeyCode || [anEvent keyCode] == CPPKeyCode || [anEvent keyCode] == CPMajAKeyCode || [anEvent keyCode] == CPMajPKeyCode))
|
||||
[self interpretKeyEvents:[anEvent]];
|
||||
|
||||
if ([_datePicker _isAmericanFormat] && [_currentTextField dateType] == CPAMPMDateType && ([anEvent keyCode] == CPAKeyCode || [anEvent keyCode] == CPPKeyCode || [anEvent keyCode] == CPMajAKeyCode || [anEvent keyCode] == CPMajPKeyCode))
|
||||
{
|
||||
if ([anEvent keyCode] == CPAKeyCode || [anEvent keyCode] == CPMajAKeyCode)
|
||||
[_currentTextField setStringValue:@"AM"];
|
||||
@@ -368,6 +394,7 @@ var CPZeroKeyCode = 48,
|
||||
[_currentTextField setValueForKeyEvent:anEvent];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Layout methods
|
||||
|
||||
@@ -725,7 +752,7 @@ var CPZeroKeyCode = 48,
|
||||
|
||||
if (hour != currentHour)
|
||||
{
|
||||
if (([_datePicker _isEnglishFormat] || [_datePicker _isAmericanFormat]))
|
||||
if ([_datePicker _isAmericanFormat])
|
||||
{
|
||||
if (![self _isAMHour])
|
||||
{
|
||||
@@ -1050,7 +1077,7 @@ var CPZeroKeyCode = 48,
|
||||
- (void)_updateHiddenTextFields
|
||||
{
|
||||
var datePickerElements = [_datePicker datePickerElements],
|
||||
isEnglishFormat = [_datePicker _isEnglishFormat];
|
||||
isAmericanFormat = [_datePicker _isAmericanFormat];
|
||||
|
||||
if (datePickerElements & CPYearMonthDatePickerElementFlag)
|
||||
{
|
||||
@@ -1083,7 +1110,7 @@ var CPZeroKeyCode = 48,
|
||||
[_textFieldSeparatorThree setHidden:NO];
|
||||
[_textFieldSeparatorFour setHidden:YES];
|
||||
|
||||
if (isEnglishFormat)
|
||||
if (isAmericanFormat)
|
||||
[_textFieldPMAM setHidden:NO];
|
||||
else
|
||||
[_textFieldPMAM setHidden:YES];
|
||||
@@ -1115,9 +1142,9 @@ var CPZeroKeyCode = 48,
|
||||
verticalInset = contentInset.top - contentInset.bottom,
|
||||
firstTexField = _textFieldMonth,
|
||||
secondTextField = _textFieldDay,
|
||||
isEnglishFormat = [_datePicker _isEnglishFormat];
|
||||
isAmericanFormat = [_datePicker _isAmericanFormat];
|
||||
|
||||
if (!isEnglishFormat)
|
||||
if (!isAmericanFormat)
|
||||
{
|
||||
firstTexField = _textFieldDay;
|
||||
secondTextField = _textFieldMonth;
|
||||
@@ -1131,7 +1158,7 @@ var CPZeroKeyCode = 48,
|
||||
else
|
||||
[secondTextField setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldSeparatorOne frame]) + separatorContentInset.right, verticalInset)];
|
||||
|
||||
if (isEnglishFormat && [secondTextField isHidden])
|
||||
if (isAmericanFormat && [secondTextField isHidden])
|
||||
[_textFieldSeparatorTwo setFrameOrigin:CGPointMake(CGRectGetMaxX([firstTexField frame]) + separatorContentInset.left, verticalInset)];
|
||||
else
|
||||
[_textFieldSeparatorTwo setFrameOrigin:CGPointMake(CGRectGetMaxX([secondTextField frame]) + separatorContentInset.left, verticalInset)];
|
||||
@@ -1206,7 +1233,7 @@ var CPZeroKeyCode = 48,
|
||||
{
|
||||
var datePickerElements = [_datePicker datePickerElements];
|
||||
|
||||
if ([_datePicker _isEnglishFormat])
|
||||
if ([_datePicker _isAmericanFormat])
|
||||
{
|
||||
if (datePickerElements & CPYearMonthDayDatePickerElementFlag || datePickerElements & CPYearMonthDatePickerElementFlag)
|
||||
[[self superview] setFirstTextField:_textFieldMonth];
|
||||
@@ -1249,9 +1276,9 @@ var CPZeroKeyCode = 48,
|
||||
var datePickerElements = [_datePicker datePickerElements],
|
||||
firstTexField = _textFieldMonth,
|
||||
secondTextField = _textFieldDay,
|
||||
isEnglishFormat = [_datePicker _isEnglishFormat];
|
||||
isAmericanFormat = [_datePicker _isAmericanFormat];
|
||||
|
||||
if (!isEnglishFormat)
|
||||
if (!isAmericanFormat)
|
||||
{
|
||||
firstTexField = _textFieldDay;
|
||||
secondTextField = _textFieldMonth;
|
||||
@@ -1266,7 +1293,7 @@ var CPZeroKeyCode = 48,
|
||||
|
||||
if (datePickerElements & CPHourMinuteSecondDatePickerElementFlag || datePickerElements & CPHourMinuteDatePickerElementFlag)
|
||||
[_textFieldYear setNextTextField:_textFieldHour];
|
||||
else if (isEnglishFormat || (datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag)
|
||||
else if (isAmericanFormat || (datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag)
|
||||
[_textFieldYear setNextTextField:firstTexField];
|
||||
else
|
||||
[_textFieldYear setNextTextField:secondTextField];
|
||||
@@ -1275,7 +1302,7 @@ var CPZeroKeyCode = 48,
|
||||
|
||||
if ((datePickerElements & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag)
|
||||
[_textFieldMinute setNextTextField:_textFieldSecond];
|
||||
else if (isEnglishFormat)
|
||||
else if (isAmericanFormat)
|
||||
[_textFieldMinute setNextTextField:_textFieldPMAM];
|
||||
else if ((datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag)
|
||||
[_textFieldMinute setNextTextField:firstTexField];
|
||||
@@ -1284,7 +1311,7 @@ var CPZeroKeyCode = 48,
|
||||
else
|
||||
[_textFieldMinute setNextTextField:_textFieldHour];
|
||||
|
||||
if (isEnglishFormat)
|
||||
if (isAmericanFormat)
|
||||
[_textFieldSecond setNextTextField:_textFieldPMAM];
|
||||
else if ((datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag)
|
||||
[_textFieldSecond setNextTextField:firstTexField];
|
||||
@@ -1304,9 +1331,9 @@ var CPZeroKeyCode = 48,
|
||||
var datePickerElements = [_datePicker datePickerElements],
|
||||
firstTexField = _textFieldMonth,
|
||||
secondTextField = _textFieldDay,
|
||||
isEnglishFormat = [_datePicker _isEnglishFormat];
|
||||
isAmericanFormat = [_datePicker _isAmericanFormat];
|
||||
|
||||
if (!isEnglishFormat)
|
||||
if (!isAmericanFormat)
|
||||
{
|
||||
firstTexField = _textFieldDay;
|
||||
secondTextField = _textFieldMonth;
|
||||
@@ -1322,14 +1349,14 @@ var CPZeroKeyCode = 48,
|
||||
|
||||
if (datePickerElements & CPYearMonthDatePickerElementFlag)
|
||||
[_textFieldHour setPreviousTextField:_textFieldYear];
|
||||
else if (isEnglishFormat)
|
||||
else if (isAmericanFormat)
|
||||
[_textFieldHour setPreviousTextField:_textFieldPMAM];
|
||||
else if ((datePickerElements & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag)
|
||||
[_textFieldHour setPreviousTextField:_textFieldSecond];
|
||||
else
|
||||
[_textFieldHour setPreviousTextField:_textFieldMinute];
|
||||
|
||||
if (!isEnglishFormat)
|
||||
if (!isAmericanFormat)
|
||||
[_textFieldYear setPreviousTextField:_textFieldMonth];
|
||||
else if ((datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag)
|
||||
[_textFieldYear setPreviousTextField:_textFieldDay];
|
||||
@@ -1338,7 +1365,7 @@ var CPZeroKeyCode = 48,
|
||||
|
||||
[secondTextField setPreviousTextField:firstTexField];
|
||||
|
||||
if (isEnglishFormat && datePickerElements & CPHourMinuteDatePickerElementFlag)
|
||||
if (isAmericanFormat && datePickerElements & CPHourMinuteDatePickerElementFlag)
|
||||
[firstTexField setPreviousTextField:_textFieldPMAM];
|
||||
else if ((datePickerElements & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag)
|
||||
[firstTexField setPreviousTextField:_textFieldSecond];
|
||||
@@ -1530,7 +1557,7 @@ var CPMonthDateType = 0,
|
||||
}
|
||||
}
|
||||
|
||||
if (parseInt(newValue) > [self _maxNumberWithMaxDate] || ([_datePicker _isEnglishFormat] && _dateType == CPHourDateType && parseInt(newValue) > 12))
|
||||
if (parseInt(newValue) > [self _maxNumberWithMaxDate] || ([_datePicker _isAmericanFormat] && _dateType == CPHourDateType && parseInt(newValue) > 12))
|
||||
return;
|
||||
|
||||
_firstEvent = NO;
|
||||
@@ -1549,7 +1576,7 @@ var CPMonthDateType = 0,
|
||||
|
||||
if ([stringValue length])
|
||||
{
|
||||
if ([_datePicker _isEnglishFormat] && [self dateType] == CPHourDateType)
|
||||
if ([_datePicker _isAmericanFormat] && [self dateType] == CPHourDateType)
|
||||
{
|
||||
var isAMHour = [[self superview] _isAMHour];
|
||||
|
||||
@@ -1593,7 +1620,7 @@ var CPMonthDateType = 0,
|
||||
if (![objectValue length])
|
||||
objectValue = [self objectValue];
|
||||
|
||||
if ([_datePicker _isEnglishFormat] && [self dateType] == CPHourDateType)
|
||||
if ([_datePicker _isAmericanFormat] && [self dateType] == CPHourDateType)
|
||||
{
|
||||
var isAMHour = [[self superview] _isAMHour];
|
||||
|
||||
@@ -1621,7 +1648,7 @@ var CPMonthDateType = 0,
|
||||
}
|
||||
else if (_dateType != CPAMPMDateType)
|
||||
{
|
||||
if (_dateType == CPHourDateType && [_datePicker _isEnglishFormat])
|
||||
if (_dateType == CPHourDateType && [_datePicker _isAmericanFormat])
|
||||
{
|
||||
var value = parseInt(aStringValue);
|
||||
|
||||
|
||||
@@ -236,6 +236,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
_subtype = aSubtype;
|
||||
_data1 = aData1;
|
||||
_data2 = aData2;
|
||||
_windowNumber = aWindowNumber;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -182,7 +182,7 @@ var CPBindingOperationAnd = 0,
|
||||
allBindings = [bindingsForObject allKeys],
|
||||
count = [allBindings count];
|
||||
|
||||
while(count--)
|
||||
while (count--)
|
||||
{
|
||||
if ([[anObject class] isBindingExclusive:allBindings[count]])
|
||||
return NO;
|
||||
|
||||
+2
-2
@@ -26,6 +26,8 @@
|
||||
CPOKButton = 1;
|
||||
CPCancelButton = 0;
|
||||
|
||||
CPDocModalWindowMask = 1 << 6;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPPanel
|
||||
@@ -51,8 +53,6 @@ CPCancelButton = 0;
|
||||
@global
|
||||
@class CPWindow
|
||||
*/
|
||||
CPDocModalWindowMask = 1 << 6;
|
||||
|
||||
@implementation CPPanel : CPWindow
|
||||
{
|
||||
BOOL _becomesKeyOnlyIfNeeded;
|
||||
|
||||
@@ -86,6 +86,9 @@ var CPProgressIndicatorSpinningStyleColors = [];
|
||||
@"spinning-mini-gif": [CPNull null],
|
||||
@"spinning-small-gif": [CPNull null],
|
||||
@"spinning-regular-gif": [CPNull null],
|
||||
@"circular-border-color": [CPNull null],
|
||||
@"circular-border-size": 1,
|
||||
@"circular-color": [CPNull null]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -368,6 +371,7 @@ var CPProgressIndicatorSpinningStyleColors = [];
|
||||
- (void)drawBar
|
||||
{
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (CPView)createEphemeralSubviewNamed:(CPString)aName
|
||||
@@ -413,6 +417,9 @@ var CPProgressIndicatorSpinningStyleColors = [];
|
||||
{
|
||||
if (_style == CPProgressIndicatorSpinningStyle)
|
||||
{
|
||||
if (!_indeterminate)
|
||||
return;
|
||||
|
||||
// This will cause the bar view to go away due to having a nil rect when _style == CPProgressIndicatorSpinningStyle.
|
||||
[self layoutEphemeralSubviewNamed:"bar-view"
|
||||
positioned:CPWindowBelow
|
||||
@@ -438,6 +445,54 @@ var CPProgressIndicatorSpinningStyleColors = [];
|
||||
[self setBackgroundColor:nil];
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)aRect
|
||||
{
|
||||
if (_style == CPProgressIndicatorSpinningStyle && !_indeterminate)
|
||||
{
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
||||
rect = CGRectMakeCopy(aRect),
|
||||
borderSize = [self currentValueForThemeAttribute:@"circular-border-size"];
|
||||
|
||||
rect.origin.x += borderSize;
|
||||
rect.origin.y += borderSize;
|
||||
rect.size.width = rect.size.width - borderSize * 2;
|
||||
rect.size.height = rect.size.height - borderSize * 2;
|
||||
|
||||
if ([self doubleValue] > [self minValue] && [self doubleValue] < [self maxValue])
|
||||
{
|
||||
var midX = CGRectGetMidX(rect),
|
||||
midY = CGRectGetMidY(rect),
|
||||
endAngle = Math.PI * 2 * (([self doubleValue] - [self minValue]) / ([self maxValue] - [self minValue])) - Math.PI / 2,
|
||||
radius = MIN(rect.size.width / 2, rect.size.height / 2)
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetLineWidth(context, borderSize);
|
||||
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
|
||||
CGContextMoveToPoint(context, midX, midY);
|
||||
CGContextAddArc(context, midX, midY, radius, 3 * Math.PI / 2, endAngle, YES)
|
||||
CGContextAddLineToPoint(context, midX, midY);
|
||||
CGContextClosePath(context);
|
||||
CGContextFillPath(context);
|
||||
CGContextStrokePath(context);
|
||||
}
|
||||
else if ([self doubleValue] == [self maxValue])
|
||||
{
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
|
||||
CGContextAddEllipseInRect(context, rect);
|
||||
CGContextClosePath(context);
|
||||
CGContextFillPath(context);
|
||||
}
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetStrokeColor(context , [self currentValueForThemeAttribute:@"circular-border-color"]);
|
||||
CGContextSetLineWidth(context, borderSize);
|
||||
CGContextAddEllipseInRect(context, rect);
|
||||
CGContextClosePath(context);
|
||||
CGContextStrokePath(context);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
+4
-6
@@ -29,6 +29,7 @@
|
||||
|
||||
@global CPApp
|
||||
|
||||
CPRadioImageOffset = 4.0;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@@ -67,9 +68,6 @@
|
||||
option.
|
||||
|
||||
*/
|
||||
|
||||
CPRadioImageOffset = 4.0;
|
||||
|
||||
@implementation CPRadio : CPButton
|
||||
{
|
||||
CPRadioGroup _radioGroup;
|
||||
@@ -269,9 +267,9 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
|
||||
- (BOOL)selectRadioWithTag:(int)tag
|
||||
{
|
||||
var index = [_radios indexOfObjectPassingTest:function(radio)
|
||||
{
|
||||
return [radio tag] === tag;
|
||||
}];
|
||||
{
|
||||
return [radio tag] === tag;
|
||||
}];
|
||||
|
||||
if (index !== CPNotFound)
|
||||
{
|
||||
|
||||
@@ -487,9 +487,9 @@ CPTransformableAttributeType = 1800;
|
||||
|
||||
- (id)copy
|
||||
{
|
||||
var views = [CPArray array];
|
||||
var views = [CPArray array],
|
||||
copy = [[[self class] alloc] init];
|
||||
|
||||
var copy = [[[self class] alloc] init];
|
||||
[copy _setTemplateType:_templateType];
|
||||
[copy _setOptions:_predicateOptions];
|
||||
[copy _setModifier:_predicateModifier];
|
||||
|
||||
@@ -86,15 +86,6 @@ var _isBrowserUsingOverlayScrollers = function()
|
||||
#endif
|
||||
};
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPScrollView
|
||||
|
||||
Used to display views that are too large for the viewing area. the CPScrollView
|
||||
places scroll bars on the side of the view to allow the user to scroll and see the entire
|
||||
contents of the view.
|
||||
*/
|
||||
|
||||
var TIMER_INTERVAL = 0.2,
|
||||
CPScrollViewDelegate_scrollViewWillScroll_ = 1 << 0,
|
||||
CPScrollViewDelegate_scrollViewDidScroll_ = 1 << 1,
|
||||
@@ -104,7 +95,14 @@ var TIMER_INTERVAL = 0.2,
|
||||
var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
|
||||
CPScrollerStyleGlobalChangeNotification = @"CPScrollerStyleGlobalChangeNotification";
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPScrollView
|
||||
|
||||
Used to display views that are too large for the viewing area. the CPScrollView
|
||||
places scroll bars on the side of the view to allow the user to scroll and see the entire
|
||||
contents of the view.
|
||||
*/
|
||||
@implementation CPScrollView : CPView
|
||||
{
|
||||
CPClipView _contentView;
|
||||
@@ -1584,6 +1582,8 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
|
||||
*/
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
[super awakeFromCib];
|
||||
|
||||
[self _updateScrollerStyle];
|
||||
[self _updateCornerAndHeaderView];
|
||||
}
|
||||
|
||||
+5
-5
@@ -50,11 +50,6 @@ CPNoScrollerParts = 0;
|
||||
CPOnlyScrollerArrows = 1;
|
||||
CPAllScrollerParts = 2;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPScroller
|
||||
*/
|
||||
|
||||
var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob],
|
||||
NAMES_FOR_PARTS = {},
|
||||
PARTS_FOR_NAMES = {};
|
||||
@@ -78,6 +73,11 @@ CPThemeStateScrollViewLegacy = CPThemeState("scroller-style-legacy");
|
||||
CPThemeStateScrollerKnobLight = CPThemeState("scroller-knob-light");
|
||||
CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPScroller
|
||||
*/
|
||||
|
||||
@implementation CPScroller : CPControl
|
||||
{
|
||||
CPUsableScrollerParts _usableParts;
|
||||
|
||||
+10
-9
@@ -34,9 +34,8 @@ CPSearchFieldRecentsMenuItemTag = 1001;
|
||||
CPSearchFieldClearRecentsMenuItemTag = 1002;
|
||||
CPSearchFieldNoRecentsMenuItemTag = 1003;
|
||||
|
||||
var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotification";
|
||||
|
||||
var RECENT_SEARCH_PREFIX = @" ";
|
||||
var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotification",
|
||||
RECENT_SEARCH_PREFIX = @" ";
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@@ -74,8 +73,8 @@ var RECENT_SEARCH_PREFIX = @" ";
|
||||
@"image-find": [CPNull null],
|
||||
@"image-cancel": [CPNull null],
|
||||
@"image-cancel-pressed": [CPNull null],
|
||||
@"image-search-left-margin" : 0,
|
||||
@"image-cancel-right-margin" : 0
|
||||
@"image-search-inset" : CGInsetMake(0, 0, 0, 5),
|
||||
@"image-cancel-inset" : CGInsetMake(0, 5, 0, 0)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -268,9 +267,10 @@ var RECENT_SEARCH_PREFIX = @" ";
|
||||
*/
|
||||
- (CGRect)searchButtonRectForBounds:(CGRect)rect
|
||||
{
|
||||
var size = [[self currentValueForThemeAttribute:@"image-search"] size] || CGSizeMakeZero();
|
||||
var size = [[self currentValueForThemeAttribute:@"image-search"] size] || CGSizeMakeZero(),
|
||||
inset = [self currentValueForThemeAttribute:@"image-search-inset"];
|
||||
|
||||
return CGRectMake([self currentValueForThemeAttribute:@"image-search-left-margin"], (CGRectGetHeight(rect) - size.height) / 2, size.width, size.height);
|
||||
return CGRectMake(inset.left - inset.right, inset.top - inset.bottom + (CGRectGetHeight(rect) - size.height) / 2, size.width, size.height);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -280,9 +280,10 @@ var RECENT_SEARCH_PREFIX = @" ";
|
||||
*/
|
||||
- (CGRect)cancelButtonRectForBounds:(CGRect)rect
|
||||
{
|
||||
var size = [[self currentValueForThemeAttribute:@"image-cancel"] size] || CGSizeMakeZero();
|
||||
var size = [[self currentValueForThemeAttribute:@"image-cancel"] size] || CGSizeMakeZero(),
|
||||
inset = [self currentValueForThemeAttribute:@"image-cancel-inset"];
|
||||
|
||||
return CGRectMake(CGRectGetWidth(rect) - size.width - [self currentValueForThemeAttribute:@"image-cancel-right-margin"], (CGRectGetHeight(rect) - size.width) / 2, size.height, size.height);
|
||||
return CGRectMake(CGRectGetWidth(rect) - size.width + inset.left - inset.right, inset.top - inset.bottom + (CGRectGetHeight(rect) - size.width) / 2, size.height, size.height);
|
||||
}
|
||||
|
||||
// Managing Menu Templates
|
||||
|
||||
+18
-18
@@ -516,7 +516,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
*/
|
||||
- (void)drawSegmentBezel:(int)aSegment highlight:(BOOL)shouldHighlight
|
||||
{
|
||||
if(aSegment < _themeStates.length)
|
||||
if (aSegment < _themeStates.length)
|
||||
{
|
||||
if (shouldHighlight)
|
||||
_themeStates[aSegment] = _themeStates[aSegment].and(CPThemeStateHighlighted);
|
||||
@@ -745,29 +745,23 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
if (aSegment < 0 || (segmentCount > 0 && aSegment >= segmentCount))
|
||||
return;
|
||||
|
||||
// Invalidate frames for segments on the right. They will be lazily computed by -frameForSegment:.
|
||||
for (var i = aSegment; i < segmentCount; i++)
|
||||
[_segments[i] setFrame:CGRectMakeZero()];
|
||||
var width = 0;
|
||||
|
||||
[self setFrameSize:[self intrinsicContentSize]];
|
||||
if (segmentCount > 0)
|
||||
{
|
||||
// Invalidate frames for segments on the right. They will be lazily computed by -frameForSegment:.
|
||||
for (var i = aSegment; i < segmentCount; i++)
|
||||
[_segments[i] setFrame:CGRectMakeZero()];
|
||||
|
||||
width = CGRectGetMaxX([self frameForSegment:(segmentCount - 1)]);
|
||||
}
|
||||
|
||||
[self setFrameSize:CGSizeMake(width, CGRectGetHeight([self frame]))];
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (CGSize)intrinsicContentSize
|
||||
{
|
||||
// frameForSegment is recursively called backwards. All previously invalidated frames will be recomputed.
|
||||
var segmentCount = [self segmentCount],
|
||||
width = 0;
|
||||
|
||||
if (segmentCount > 0)
|
||||
width = CGRectGetMaxX([self frameForSegment:(segmentCount - 1)]);
|
||||
|
||||
return CGSizeMake(width, [self valueForThemeAttribute:@"min-size"].height);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the bounding rectangle for the specified segment.
|
||||
@param aSegment the segment to get the rectangle for
|
||||
@@ -819,6 +813,12 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
return CGRectMake(left + contentInset.left, contentInset.top, width - contentInset.left - contentInset.right, height - contentInset.top - contentInset.bottom);
|
||||
}
|
||||
|
||||
- (CGSize)_minimumFrameSize
|
||||
{
|
||||
// The current width is always the minimum width.
|
||||
return CGSizeMake(CGRectGetWidth([self frame]), [self currentValueForThemeAttribute:@"min-size"].height);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the segment that is hit by the specified point.
|
||||
@param aPoint the point to test for a segment hit
|
||||
|
||||
+44
-35
@@ -55,7 +55,9 @@ var CPSplitViewDelegate_splitView_canCollapseSubview_
|
||||
CPSplitViewDelegate_splitView_constrainMaxCoordinate_ofSubviewAt_ = 1 << 5,
|
||||
CPSplitViewDelegate_splitView_constrainMinCoordinate_ofSubviewAt_ = 1 << 6,
|
||||
CPSplitViewDelegate_splitView_constrainSplitPosition_ofSubviewAt_ = 1 << 7,
|
||||
CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_ = 1 << 8;
|
||||
CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_ = 1 << 8,
|
||||
CPSplitViewDelegate_splitViewDidResizeSubviews_ = 1 << 9,
|
||||
CPSplitViewDelegate_splitViewWillResizeSubviews_ = 1 << 10;
|
||||
|
||||
#define SPLIT_VIEW_MAYBE_POST_WILL_RESIZE() \
|
||||
if ((_suppressResizeNotificationsMask & DidPostWillResizeNotification) === 0) \
|
||||
@@ -967,26 +969,14 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewDidResizeSubviewsNotification object:self];
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewWillResizeSubviewsNotification object:self];
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitViewWillResizeSubviews_;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] addObserver:_delegate
|
||||
selector:@selector(splitViewDidResizeSubviews:)
|
||||
name:CPSplitViewDidResizeSubviewsNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] addObserver:_delegate
|
||||
selector:@selector(splitViewWillResizeSubviews:)
|
||||
name:CPSplitViewWillResizeSubviewsNotification
|
||||
object:self];
|
||||
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitViewDidResizeSubviews_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_canCollapseSubview_;
|
||||
@@ -1064,27 +1054,12 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
|
||||
- (void)_postNotificationWillResize
|
||||
{
|
||||
var userInfo = nil;
|
||||
|
||||
if (_currentDivider !== CPNotFound)
|
||||
userInfo = @{ @"CPSplitViewDividerIndex": _currentDivider };
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification
|
||||
object:self
|
||||
userInfo:userInfo];
|
||||
[self _sendDelegateSplitViewWillResizeSubviews];
|
||||
}
|
||||
|
||||
- (void)_postNotificationDidResize
|
||||
{
|
||||
var userInfo = nil;
|
||||
|
||||
if (_currentDivider !== CPNotFound)
|
||||
userInfo = @{ @"CPSplitViewDividerIndex": _currentDivider };
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewDidResizeSubviewsNotification
|
||||
object:self
|
||||
userInfo:userInfo];
|
||||
|
||||
[self _sendDelegateSplitViewDidResizeSubviews];
|
||||
|
||||
// TODO Cocoa always autosaves on "viewDidEndLiveResize". If Cappuccino adds support for this we
|
||||
// should do the same.
|
||||
@@ -1369,6 +1344,40 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
[_delegate splitView:self resizeSubviewsWithOldSize:oldSize];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitViewWillResizeSubviews:
|
||||
*/
|
||||
- (void)_sendDelegateSplitViewWillResizeSubviews
|
||||
{
|
||||
var userInfo = nil;
|
||||
|
||||
if (_currentDivider !== CPNotFound)
|
||||
userInfo = @{ @"CPSplitViewDividerIndex": _currentDivider };
|
||||
|
||||
if (_implementedDelegateMethods & CPSplitViewDelegate_splitViewWillResizeSubviews_)
|
||||
[_delegate splitViewWillResizeSubviews:[[CPNotification alloc] initWithName:CPSplitViewWillResizeSubviewsNotification object:self userInfo:userInfo]];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification object:self userInfo:userInfo];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitViewDidResizeSubviews:
|
||||
*/
|
||||
- (void)_sendDelegateSplitViewDidResizeSubviews
|
||||
{
|
||||
var userInfo = nil;
|
||||
|
||||
if (_currentDivider !== CPNotFound)
|
||||
userInfo = @{ @"CPSplitViewDividerIndex": _currentDivider };
|
||||
|
||||
if (_implementedDelegateMethods & CPSplitViewDelegate_splitViewDidResizeSubviews_)
|
||||
[_delegate splitViewDidResizeSubviews:[[CPNotification alloc] initWithName:CPSplitViewDidResizeSubviewsNotification object:self userInfo:userInfo]];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewDidResizeSubviewsNotification object:self userInfo:userInfo];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -765,6 +765,8 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
[super awakeFromCib];
|
||||
|
||||
// This cannot be run in initWithCoder because it might call selectTabViewItem:, which is
|
||||
// not safe to call before the views of the tab views items are fully decoded.
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
_textField = [[_CPImageAndTextView alloc] initWithFrame:
|
||||
CGRectMake(5.0, 0.0, CGRectGetWidth([self bounds]) - 10.0, CGRectGetHeight([self bounds]))];
|
||||
|
||||
[_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
||||
[_textField setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
|
||||
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
[_textField setTextColor:[CPColor colorWithRed:51.0 / 255.0 green:51.0 / 255.0 blue:51.0 / 255.0 alpha:1.0]];
|
||||
@@ -196,7 +196,7 @@
|
||||
maxX = CGRectGetMaxX(bounds) - 0.5;
|
||||
|
||||
CGContextSetLineWidth(context, 1);
|
||||
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0/255.0 alpha:1.0]);
|
||||
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
|
||||
|
||||
CGContextBeginPath(context);
|
||||
|
||||
|
||||
+20
-16
@@ -2100,26 +2100,26 @@ NOT YET IMPLEMENTED
|
||||
found = NO,
|
||||
max_rec = 100;
|
||||
|
||||
while (max_rec--)
|
||||
while (max_rec--)
|
||||
{
|
||||
if (!cellView || cellView === contentView)
|
||||
{
|
||||
if (!cellView || cellView === contentView)
|
||||
found = NO;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
var superview = [cellView superview];
|
||||
|
||||
if ([superview isKindOfClass:[CPTableView class]])
|
||||
{
|
||||
found = NO;
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
var superview = [cellView superview];
|
||||
|
||||
if ([superview isKindOfClass:[CPTableView class]])
|
||||
{
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
|
||||
cellView = superview;
|
||||
}
|
||||
cellView = superview;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
@@ -3593,6 +3593,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
if (!_isViewBased)
|
||||
[self _setEditingState:NO forView:dataView];
|
||||
|
||||
[self _sendDelegateWillDisplayView:dataView forTableColumn:tableColumn row:row];
|
||||
|
||||
return dataView;
|
||||
@@ -5091,7 +5094,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
_editingColumn = column;
|
||||
_editingRow = row;
|
||||
|
||||
[aView addObserver:self forKeyPath:@"objectValue" options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew context:"editing"];
|
||||
[aView addObserver:self forKeyPath:@"objectValue" options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:"editing"];
|
||||
}
|
||||
|
||||
return aView;
|
||||
@@ -5196,7 +5199,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
[self _notifyViewDidBecomeFirstResponder];
|
||||
|
||||
// This is for cell-based tables only. In view-based mode, we do not change the textfield apprearence during an edit.
|
||||
if (!_isViewBased && _editingRow !== CPNotFound && [responder isKindOfClass:[CPTextField class]] && [responder isEditable])
|
||||
if (!_isViewBased && _editingRow !== CPNotFound && [responder isKindOfClass:[CPTextField class]] && [responder isEditable] && [responder superview] == self)
|
||||
{
|
||||
[responder setBezeled:YES];
|
||||
[self _registerForEndEditingNote:responder];
|
||||
@@ -6391,6 +6394,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
[super awakeFromCib];
|
||||
[self setThemeState:CPThemeStateTableDataView];
|
||||
}
|
||||
|
||||
|
||||
+13
-1
@@ -38,4 +38,16 @@ CPLeftTextMovement = 19;
|
||||
CPRightTextMovement = 20;
|
||||
CPUpTextMovement = 21;
|
||||
CPDownTextMovement = 22;
|
||||
CPCancelTextMovement = 23;
|
||||
CPCancelTextMovement = 23;
|
||||
|
||||
@typedef CPWritingDirection
|
||||
CPWritingDirectionNatural = -1;
|
||||
CPWritingDirectionLeftToRight = 0;
|
||||
CPWritingDirectionRightToLeft = 1;
|
||||
|
||||
@typedef CPTextAlignment
|
||||
CPLeftTextAlignment = 0;
|
||||
CPRightTextAlignment = 1;
|
||||
CPCenterTextAlignment = 2;
|
||||
CPJustifiedTextAlignment = 3;
|
||||
CPNaturalTextAlignment = 4;
|
||||
+92
-6
@@ -28,12 +28,12 @@
|
||||
@import "_CPImageAndTextView.j"
|
||||
|
||||
@class CPPasteboard
|
||||
@class CPScrollView
|
||||
|
||||
@global CPApp
|
||||
@global CPStringPboardType
|
||||
@global CPCursor
|
||||
|
||||
|
||||
@protocol CPTextFieldDelegate <CPControlTextEditingDelegate>
|
||||
|
||||
@end
|
||||
@@ -65,7 +65,8 @@ var CPTextFieldDOMCurrentElement = nil,
|
||||
CPTextFieldCachedSelectStartFunction = nil,
|
||||
CPTextFieldCachedDragFunction = nil,
|
||||
CPTextFieldBlurHandler = nil,
|
||||
CPTextFieldInputFunction = nil;
|
||||
CPTextFieldInputFunction = nil,
|
||||
CPTexFieldCurrentCSSSelectableField = nil;
|
||||
|
||||
var CPSecureTextFieldCharacter = "\u2022";
|
||||
|
||||
@@ -88,7 +89,12 @@ function CPTextFieldBlurFunction(anEvent, owner, domElement, inputElement, resig
|
||||
{
|
||||
window.setTimeout(function()
|
||||
{
|
||||
// This will prevent to jump to the focused element
|
||||
var previousScrollingOrigin = [owner _scrollToVisibleRectAndReturnPreviousOrigin];
|
||||
|
||||
inputElement.focus();
|
||||
|
||||
[owner _restorePreviousScrollingOrigin:previousScrollingOrigin];
|
||||
}, 0.0);
|
||||
}
|
||||
}
|
||||
@@ -370,7 +376,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
_sendActionOn = CPKeyUpMask | CPKeyDownMask;
|
||||
|
||||
[self setValue:CPLeftTextAlignment forThemeAttribute:@"alignment"];
|
||||
[self setValue:CPNaturalTextAlignment forThemeAttribute:@"alignment"];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -643,6 +649,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
_stringValue = [self stringValue];
|
||||
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
[self _setCSSStyleForInputElement];
|
||||
@@ -672,8 +679,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (CPTextFieldInputOwner !== self)
|
||||
return;
|
||||
|
||||
// This will prevent to jump to the focused element
|
||||
var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
|
||||
|
||||
element.focus();
|
||||
|
||||
[self _restorePreviousScrollingOrigin:previousScrollingOrigin];
|
||||
|
||||
// Select the text if the textfield became first responder through keyboard interaction
|
||||
if (!_willBecomeFirstResponderByClick)
|
||||
[self _selectText:self immediately:YES];
|
||||
@@ -688,6 +700,21 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the selection css style for the DOM element of the textField
|
||||
@ignore
|
||||
*/
|
||||
- (void)_setEnableCSSSelection:(BOOL)shouldEnable
|
||||
{
|
||||
#if PLATFORM (DOM)
|
||||
if (CPTexFieldCurrentCSSSelectableField)
|
||||
CPTexFieldCurrentCSSSelectableField._DOMElement.style[CPBrowserStyleProperty(@"user-select")] = @"none";
|
||||
|
||||
CPTexFieldCurrentCSSSelectableField = self;
|
||||
_DOMElement.style[CPBrowserStyleProperty(@"user-select")] = shouldEnable ? @"text" : @"none";
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the css style for the input element of the textField
|
||||
@ignore
|
||||
@@ -741,6 +768,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
element.style.textAlign = "right";
|
||||
break;
|
||||
|
||||
case CPNaturalTextAlignment:
|
||||
element.style.textAlign = "";
|
||||
break;
|
||||
|
||||
default:
|
||||
element.style.textAlign = "left";
|
||||
}
|
||||
@@ -783,7 +814,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
// even if the value has not changed.
|
||||
if ([self _valueIsValid:newValue] === NO)
|
||||
{
|
||||
// This will prevent to jump to the focused element
|
||||
var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
|
||||
|
||||
element.focus();
|
||||
|
||||
[self _restorePreviousScrollingOrigin:previousScrollingOrigin];
|
||||
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
@@ -792,7 +829,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
// When we are no longer the first responder we don't worry about the key status of our window anymore.
|
||||
[self _setObserveWindowKeyNotifications:NO];
|
||||
|
||||
[self _resignFirstKeyResponder];
|
||||
if ([[self window] isKeyWindow])
|
||||
[self _resignFirstKeyResponder];
|
||||
|
||||
_isEditing = NO;
|
||||
if ([self isEditable])
|
||||
@@ -970,6 +1008,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
}
|
||||
else if ([self isSelectable])
|
||||
{
|
||||
[self _setEnableCSSSelection:YES];
|
||||
if (document.attachEvent)
|
||||
{
|
||||
CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
|
||||
@@ -1011,6 +1050,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rightMouseDown:(CPEvent)anEvent
|
||||
{
|
||||
if ([self menuForEvent:anEvent] || [[self nextResponder] isKindOfClass:CPView])
|
||||
[super rightMouseDown:anEvent];
|
||||
else
|
||||
[[[anEvent window] platformWindow] _propagateContextMenuDOMEvent:YES];
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(CPEvent)anEvent
|
||||
{
|
||||
if (![self isEnabled] || !([self isSelectable] || [self isEditable]))
|
||||
@@ -1950,17 +1997,55 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (!wind)
|
||||
return NO;
|
||||
|
||||
var scrollView = [self enclosingScrollView],
|
||||
previousContentViewBoundsOrigin;
|
||||
|
||||
// Here we scroll to the textField, otherwise the textField could not be in the usable platformRect
|
||||
var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
|
||||
|
||||
var frame = [self convertRectToBase:[self contentRectForBounds:[self bounds]]],
|
||||
usableRect = [[wind platformWindow] usableContentFrame];
|
||||
|
||||
frame.origin = [wind convertBaseToGlobal:frame.origin];
|
||||
|
||||
// Here we restore the the previous scrolling posiition
|
||||
[self _restorePreviousScrollingOrigin:previousScrollingOrigin];
|
||||
|
||||
return (CGRectGetMinX(frame) >= CGRectGetMinX(usableRect) &&
|
||||
CGRectGetMaxX(frame) <= CGRectGetMaxX(usableRect) &&
|
||||
CGRectGetMinY(frame) >= CGRectGetMinY(usableRect) &&
|
||||
CGRectGetMaxY(frame) <= CGRectGetMaxY(usableRect));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (CGPoint)_scrollToVisibleRectAndReturnPreviousOrigin
|
||||
{
|
||||
var scrollView = [self enclosingScrollView],
|
||||
previousContentViewBoundsOrigin;
|
||||
|
||||
// Here we scroll to the textField, otherwise the textField could not be in the usable platformRect
|
||||
if ([scrollView isKindOfClass:[CPScrollView class]])
|
||||
{
|
||||
previousContentViewBoundsOrigin = CGPointMakeCopy([[scrollView contentView] boundsOrigin]);
|
||||
|
||||
if (![[self superview] scrollRectToVisible:[self frame]])
|
||||
previousContentViewBoundsOrigin = nil;
|
||||
}
|
||||
|
||||
return previousContentViewBoundsOrigin;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_restorePreviousScrollingOrigin:(CGPoint)scrollingOrigin
|
||||
{
|
||||
if (scrollingOrigin)
|
||||
[[[self enclosingScrollView] contentView] setBoundsOrigin:scrollingOrigin];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var secureStringForString = function(aString)
|
||||
@@ -2082,7 +2167,8 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
newValue = [self valueForBinding:aBinding],
|
||||
value = [destination valueForKeyPath:keyPath];
|
||||
|
||||
if (CPIsControllerMarker(value) && newValue === nil) return;
|
||||
if (CPIsControllerMarker(value) && newValue === nil)
|
||||
return;
|
||||
|
||||
newValue = [self reverseTransformValue:newValue withOptions:options];
|
||||
|
||||
@@ -2109,4 +2195,4 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
[_source setObjectValue:aValue];
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
||||
@@ -457,7 +457,13 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
|
||||
window.setTimeout(function()
|
||||
{
|
||||
// This will prevent to jump to the focused element
|
||||
var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
|
||||
|
||||
element.focus();
|
||||
|
||||
[self _restorePreviousScrollingOrigin:previousScrollingOrigin];
|
||||
|
||||
CPTokenFieldInputOwner = self;
|
||||
}, 0.0);
|
||||
|
||||
|
||||
+137
-14
@@ -26,6 +26,7 @@
|
||||
|
||||
@import "CGAffineTransform.j"
|
||||
@import "CGGeometry.j"
|
||||
@import "CPAppearance.j"
|
||||
@import "CPColor.j"
|
||||
@import "CPGraphicsContext.j"
|
||||
@import "CPResponder.j"
|
||||
@@ -131,7 +132,6 @@ var CPViewFlags = { },
|
||||
|
||||
var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPView
|
||||
@@ -240,6 +240,10 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
BOOL _toolTipInstalled;
|
||||
|
||||
BOOL _isObserving;
|
||||
|
||||
BOOL _allowsVibrancy @accessors(property=allowsVibrancy);
|
||||
CPAppearance _appearance @accessors(getter=appearance);
|
||||
CPAppearance _effectiveAppearance;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -327,6 +331,13 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
[super awakeFromCib];
|
||||
|
||||
[self _recomputeAppearance];
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
return [self initWithFrame:CGRectMakeZero()];
|
||||
@@ -839,9 +850,9 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
*/
|
||||
- (void)viewDidMoveToSuperview
|
||||
{
|
||||
// if (_graphicsContext)
|
||||
[self setNeedsDisplay:YES];
|
||||
[self _recomputeAppearance];
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1820,7 +1831,7 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
else if ([[self nextResponder] isKindOfClass:CPView])
|
||||
[super rightMouseDown:anEvent];
|
||||
else
|
||||
[[[anEvent window] platformWindow] _propagateContextMenuDOMEvent:YES];
|
||||
[[[anEvent window] platformWindow] _propagateContextMenuDOMEvent:NO];
|
||||
}
|
||||
|
||||
- (CPMenu)menuForEvent:(CPEvent)anEvent
|
||||
@@ -2731,18 +2742,47 @@ setBoundsOrigin:
|
||||
if (CGRectContainsRect(documentViewVisibleRect, rectInDocumentView))
|
||||
return NO;
|
||||
|
||||
var scrollPoint = CGPointMakeCopy(documentViewVisibleRect.origin);
|
||||
var currentScrollPoint = documentViewVisibleRect.origin,
|
||||
scrollPoint = CGPointMakeCopy(currentScrollPoint),
|
||||
rectInDocumentViewMinX = CGRectGetMinX(rectInDocumentView),
|
||||
documentViewVisibleRectMinX = CGRectGetMinX(documentViewVisibleRect),
|
||||
doesItFitForWidth = documentViewVisibleRect.size.width >= rectInDocumentView.size.width;
|
||||
|
||||
// One of the following has to be true since our current visible rect didn't contain aRect.
|
||||
if (CGRectGetMinX(rectInDocumentView) < CGRectGetMinX(documentViewVisibleRect))
|
||||
scrollPoint.x = CGRectGetMinX(rectInDocumentView);
|
||||
else if (CGRectGetMaxX(rectInDocumentView) > CGRectGetMaxX(documentViewVisibleRect))
|
||||
scrollPoint.x += CGRectGetMaxX(rectInDocumentView) - CGRectGetMaxX(documentViewVisibleRect);
|
||||
if (rectInDocumentViewMinX < documentViewVisibleRectMinX && doesItFitForWidth)
|
||||
// Scroll to left edge of aRect as it is to the left of the visible rect and it fit inside
|
||||
scrollPoint.x = rectInDocumentViewMinX;
|
||||
else if (CGRectGetMaxX(rectInDocumentView) > CGRectGetMaxX(documentViewVisibleRect) && doesItFitForWidth)
|
||||
// Scroll to right edge of aRect as it is to the right of the visible rect and it fit inside
|
||||
scrollPoint.x = CGRectGetMaxX(rectInDocumentView) - documentViewVisibleRect.size.width;
|
||||
else if (rectInDocumentViewMinX > documentViewVisibleRectMinX)
|
||||
// Scroll to left edge of aRect as it is to the right of the visible rect and it doesn't fit inside
|
||||
scrollPoint.x = rectInDocumentViewMinX;
|
||||
else if (CGRectGetMaxX(rectInDocumentView) < CGRectGetMaxX(documentViewVisibleRect))
|
||||
// Scroll to right edge of aRect as it is to the left of the visible rect and it doesn't fit inside
|
||||
scrollPoint.x = CGRectGetMaxX(rectInDocumentView) - documentViewVisibleRect.size.width;
|
||||
|
||||
if (CGRectGetMinY(rectInDocumentView) < CGRectGetMinY(documentViewVisibleRect))
|
||||
scrollPoint.y = CGRectGetMinY(rectInDocumentView);
|
||||
else if (CGRectGetMaxY(rectInDocumentView) > CGRectGetMaxY(documentViewVisibleRect))
|
||||
scrollPoint.y += CGRectGetMaxY(rectInDocumentView) - CGRectGetMaxY(documentViewVisibleRect);
|
||||
var rectInDocumentViewMinY = CGRectGetMinY(rectInDocumentView),
|
||||
documentViewVisibleRectMinY = CGRectGetMinY(documentViewVisibleRect),
|
||||
doesItFitForHeight = documentViewVisibleRect.size.height >= rectInDocumentView.size.height;
|
||||
|
||||
if (rectInDocumentViewMinY < documentViewVisibleRectMinY && doesItFitForHeight)
|
||||
// Scroll to top edge of aRect as it is above the visible rect and it fit inside
|
||||
scrollPoint.y = rectInDocumentViewMinY;
|
||||
else if (CGRectGetMaxY(rectInDocumentView) > CGRectGetMaxY(documentViewVisibleRect) && doesItFitForHeight)
|
||||
// Scroll to bottom edge of aRect as it is below the visible rect and it fit inside
|
||||
scrollPoint.y = CGRectGetMaxY(rectInDocumentView) - documentViewVisibleRect.size.height;
|
||||
else if (rectInDocumentViewMinY > documentViewVisibleRectMinY)
|
||||
// Scroll to top edge of aRect as it is below the visible rect and it doesn't fit inside
|
||||
scrollPoint.y = rectInDocumentViewMinY;
|
||||
else if (CGRectGetMaxY(rectInDocumentView) < CGRectGetMaxY(documentViewVisibleRect))
|
||||
// Scroll to bottom edge of aRect as it is above the visible rect and it doesn't fit inside
|
||||
scrollPoint.y = CGRectGetMaxY(rectInDocumentView) - documentViewVisibleRect.size.height;
|
||||
|
||||
// Don't scroll if aRect contains the whole visible rect as it is already as visible as possible.
|
||||
// We check this by comparing to new scrollPoint to the current.
|
||||
if (CGPointEqualToPoint(scrollPoint, currentScrollPoint))
|
||||
return NO;
|
||||
|
||||
[enclosingClipView scrollToPoint:scrollPoint];
|
||||
|
||||
@@ -3480,6 +3520,85 @@ setBoundsOrigin:
|
||||
return (_ephemeralSubviewsForNames[aViewName] || nil);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPView (Appearance)
|
||||
|
||||
/*! Returns the receiver's appearance if any, or ask the superview and returns it.
|
||||
*/
|
||||
- (CPAppearance)effectiveAppearance
|
||||
{
|
||||
if (_appearance)
|
||||
return _appearance;
|
||||
|
||||
return [_superview effectiveAppearance];
|
||||
}
|
||||
|
||||
- (void)setAppearance:(CPAppearance)anAppearance
|
||||
{
|
||||
if ([_appearance isEqual:anAppearance])
|
||||
return;
|
||||
|
||||
[self willChangeValueForKey:@"appearance"];
|
||||
_appearance = anAppearance;
|
||||
[self didChangeValueForKey:@"appearance"];
|
||||
|
||||
[self _recomputeAppearance];
|
||||
}
|
||||
|
||||
/*! @ignore
|
||||
*/
|
||||
- (void)_recomputeAppearance
|
||||
{
|
||||
// if we don't have a themeState, it means
|
||||
// the view is not decoding from a cib, so we just return.
|
||||
// this method will be called again in awakeFromCib
|
||||
if (!_themeState)
|
||||
return;
|
||||
|
||||
var effectiveAppearance = [self effectiveAppearance];
|
||||
|
||||
if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameAqua]])
|
||||
{
|
||||
[self setThemeState:CPThemeStateAppearanceAqua];
|
||||
[self unsetThemeState:CPThemeStateAppearanceLightContent];
|
||||
[self unsetThemeState:CPThemeStateAppearanceVibrantLight];
|
||||
[self unsetThemeState:CPThemeStateAppearanceVibrantDark];
|
||||
}
|
||||
else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameLightContent]])
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateAppearanceAqua];
|
||||
[self setThemeState:CPThemeStateAppearanceLightContent];
|
||||
[self unsetThemeState:CPThemeStateAppearanceVibrantLight];
|
||||
[self unsetThemeState:CPThemeStateAppearanceVibrantDark];
|
||||
}
|
||||
else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]])
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateAppearanceAqua];
|
||||
[self unsetThemeState:CPThemeStateAppearanceLightContent];
|
||||
[self setThemeState:CPThemeStateAppearanceVibrantLight];
|
||||
[self unsetThemeState:CPThemeStateAppearanceVibrantDark];
|
||||
}
|
||||
else if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]])
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateAppearanceAqua];
|
||||
[self unsetThemeState:CPThemeStateAppearanceLightContent];
|
||||
[self unsetThemeState:CPThemeStateAppearanceVibrantLight];
|
||||
[self setThemeState:CPThemeStateAppearanceVibrantDark];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateAppearanceAqua];
|
||||
[self unsetThemeState:CPThemeStateAppearanceLightContent];
|
||||
[self unsetThemeState:CPThemeStateAppearanceVibrantLight];
|
||||
[self unsetThemeState:CPThemeStateAppearanceVibrantDark];
|
||||
}
|
||||
|
||||
[_subviews makeObjectsPerformSelector:@selector(_recomputeAppearance)];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
@@ -3502,7 +3621,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
CPReuseIdentifierKey = @"CPReuseIdentifierKey",
|
||||
CPViewScaleKey = @"CPViewScaleKey",
|
||||
CPViewSizeScaleKey = @"CPViewSizeScaleKey",
|
||||
CPViewIsScaledKey = @"CPViewIsScaledKey";
|
||||
CPViewIsScaledKey = @"CPViewIsScaledKey",
|
||||
CPViewAppearanceKey = @"CPViewAppearanceKey";
|
||||
|
||||
@implementation CPView (CPCoding)
|
||||
|
||||
@@ -3617,6 +3737,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
_themeAttributes[attributeName] = CPThemeAttributeDecode(aCoder, attributeName, attributes[count], _theme, themeClass);
|
||||
}
|
||||
|
||||
[self setAppearance:[aCoder decodeObjectForKey:CPViewAppearanceKey]];
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
@@ -3705,6 +3827,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
[aCoder encodeSize:[self scaleSize] forKey:CPViewScaleKey];
|
||||
[aCoder encodeSize:[self _hierarchyScaleSize] forKey:CPViewSizeScaleKey];
|
||||
[aCoder encodeBool:_isScaled forKey:CPViewIsScaledKey];
|
||||
[aCoder encodeObject:_appearance forKey:CPViewAppearanceKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* CPVisualEffectView.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Antoine Mercadal.
|
||||
* Copyright 2015, 280 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>
|
||||
@import "CPAppearance.j"
|
||||
@import "CPView.j"
|
||||
|
||||
@typedef CPVisualEffectMaterial
|
||||
CPVisualEffectMaterialAppearanceBased = 0;
|
||||
CPVisualEffectMaterialLight = 1;
|
||||
CPVisualEffectMaterialDark = 2;
|
||||
CPVisualEffectMaterialTitlebar = 3;
|
||||
|
||||
@typedef CPVisualEffectBlendingMode
|
||||
CPVisualEffectBlendingModeBehindWindow = 0;
|
||||
CPVisualEffectBlendingModeWithinWindow = 1;
|
||||
|
||||
@typedef CPVisualEffectState
|
||||
CPVisualEffectStateFollowsWindowActiveState = 0;
|
||||
CPVisualEffectStateActive = 1;
|
||||
CPVisualEffectStateInactive = 2;
|
||||
|
||||
|
||||
/*! @ingroup appkit
|
||||
|
||||
Very naive implementation of CPVisualEffectView. This view allows
|
||||
to use vibrancy effect. This is only working with Safari 9+ and the
|
||||
support in Chrome/ium should come quite soon.
|
||||
Using this class with a browser that doesn't support backdrop-filter
|
||||
While still work, but you will not get the blurry effect.
|
||||
*/
|
||||
@implementation CPVisualEffectView : CPView
|
||||
{
|
||||
CPImage _maskImage @accessors(property=maskImage);
|
||||
CPVisualEffectBlendingMode _blendingMode @accessors(property=blendingMode);
|
||||
CPVisualEffectMaterial _material @accessors(property=material);
|
||||
CPVisualEffectState _state @accessors(property=state);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
_material = CPVisualEffectMaterialAppearanceBased;
|
||||
_blendingMode = CPVisualEffectBlendingModeWithinWindow;
|
||||
_state = CPVisualEffectStateFollowsWindowActiveState;
|
||||
_appearance = [CPAppearance appearanceNamed:CPAppearanceNameVibrantDark];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark CPVisualEffectView API
|
||||
|
||||
/*! Sets the appearance of the CPVisualEffectView.
|
||||
|
||||
Only CPAppearance named CPAppearanceNameVibrantDark or CPAppearanceNameVibrantLight are valid
|
||||
|
||||
@param anAppearance the CPAppearance.
|
||||
*/
|
||||
- (void)setAppearance:(CPAppearance)anAppearance
|
||||
{
|
||||
if (![self _validAppearance:anAppearance])
|
||||
[CPException raise:CPInvalidArgumentException reason:"Appearance can only be CPAppearanceNameVibrantDark or CPAppearanceNameVibrantLight in CPVisualEffectView, but is " + anAppearance];
|
||||
|
||||
[super setAppearance:anAppearance];
|
||||
[self _applyVibrancyState];
|
||||
}
|
||||
|
||||
/*! Sets the received effect state.
|
||||
Possible values:
|
||||
<pre>
|
||||
CPVisualEffectStateFollowsWindowActiveState (default)
|
||||
CPVisualEffectStateActive
|
||||
CPVisualEffectStateInactive
|
||||
</pre>
|
||||
*/
|
||||
- (void)setState:(CPVisualEffectState)aState
|
||||
{
|
||||
if (_state == aState)
|
||||
return;
|
||||
|
||||
[self willChangeValueForKey:"state"];
|
||||
_state = aState;
|
||||
[self didChangeValueForKey:"state"];
|
||||
|
||||
[self _applyVibrancyState];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Utilities
|
||||
|
||||
- (void)_setEffectEnabled:(BOOL)shouldEnable
|
||||
{
|
||||
var dark = [[self appearance] isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]],
|
||||
prop = CPBrowserStyleProperty("backdrop-filter"),
|
||||
color = (dark ? [CPColor colorWithHexString:@"1e1e1e"] : [CPColor whiteColor]),
|
||||
finalColor = shouldEnable ? [color colorWithAlphaComponent:0.6] : color;
|
||||
|
||||
[self setBackgroundColor:finalColor];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
self._DOMElement.style[prop] = shouldEnable ? "blur(30px)" : nil;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
- (void)_applyVibrancyState
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
case CPVisualEffectStateFollowsWindowActiveState:
|
||||
[self _setEffectEnabled:[self hasThemeState:CPThemeStateKeyWindow]];
|
||||
break;
|
||||
|
||||
case CPVisualEffectStateActive:
|
||||
[self _setEffectEnabled:YES];
|
||||
break;
|
||||
|
||||
case CPVisualEffectStateInactive:
|
||||
[self _setEffectEnabled:NO];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)_validAppearance:(CPAppearance)anAppearance
|
||||
{
|
||||
return [anAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]] || [anAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Overrides
|
||||
|
||||
- (BOOL)setThemeState:(ThemeState)aState
|
||||
{
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
var r = [super setThemeState:aState];
|
||||
|
||||
if (r)
|
||||
[self _applyVibrancyState];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
- (BOOL)unsetThemeState:(ThemeState)aState
|
||||
{
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
var r = [super unsetThemeState:aState];
|
||||
|
||||
if (r)
|
||||
[self _applyVibrancyState];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToSuperview
|
||||
{
|
||||
[super viewDidMoveToSuperview];
|
||||
|
||||
if (_superview)
|
||||
[self _applyVibrancyState];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
[super viewDidMoveToWindow];
|
||||
|
||||
if (_window)
|
||||
[self _applyVibrancyState];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark CPCoding
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
if (self = [super initWithCoder:aCoder])
|
||||
{
|
||||
_blendingMode = [aCoder decodeIntForKey:@"_blendingMode"] || CPVisualEffectBlendingModeWithinWindow;
|
||||
_maskImage = [aCoder decodeObjectForKey:@"_maskImage"];
|
||||
_material = [aCoder decodeIntForKey:@"_material"] || CPVisualEffectMaterialAppearanceBased;
|
||||
_state = [aCoder decodeIntForKey:@"_state"] || CPVisualEffectStateFollowsWindowActiveState;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeObject:_maskImage forKey:@"_maskImage"];
|
||||
[aCoder encodeInt:_blendingMode forKey:@"_blendingMode"];
|
||||
[aCoder encodeInt:_material forKey:@"_material"];
|
||||
[aCoder encodeInt:_state forKey:@"_state"];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -63,22 +63,28 @@
|
||||
|
||||
@optional
|
||||
- (BOOL)windowShouldClose:(CPWindow)aWindow;
|
||||
- (CGSize)windowWillResize:(CPWindow)sender toSize:(CGSize)aSize;
|
||||
- (CPUndoManager)windowWillReturnUndoManager:(CPWindow)window;
|
||||
- (void)windowDidBecomeKey:(CPNotification)aNotification;
|
||||
- (void)windowDidBecomeMain:(CPNotification)aNotification;
|
||||
- (void)windowDidDeminiaturize:(CPNotification)notification;
|
||||
- (void)windowDidEndSheet:(CPNotification)aNotification;
|
||||
- (void)windowDidMiniaturize:(CPNotification)notification;
|
||||
- (void)windowDidMove:(CPNotification)aNotification;
|
||||
- (void)windowDidResignKey:(CPNotification)aNotification;
|
||||
- (void)windowDidResignMain:(CPNotification)aNotification;
|
||||
- (void)windowDidResize:(CPNotification)aNotification;
|
||||
- (void)windowWillMiniaturize:(CPNotification)notification;
|
||||
- (void)windowWillBeginSheet:(CPNotification)aNotification;
|
||||
- (void)windowWillClose:(CPWindow)aWindow;
|
||||
|
||||
@end
|
||||
|
||||
var CPWindowDelegate_windowShouldClose_ = 1 << 1
|
||||
var CPWindowDelegate_windowShouldClose_ = 1 << 1,
|
||||
CPWindowDelegate_windowWillReturnUndoManager_ = 1 << 2,
|
||||
CPWindowDelegate_windowWillClose_ = 1 << 3;
|
||||
CPWindowDelegate_windowWillClose_ = 1 << 3,
|
||||
CPWindowDelegate_windowWillResize_toSize_ = 1 << 4;
|
||||
|
||||
|
||||
var CPWindowSaveImage = nil,
|
||||
|
||||
@@ -747,6 +753,9 @@ CPTexturedBackgroundWindowMask
|
||||
size.width = newSize.width;
|
||||
size.height = newSize.height;
|
||||
|
||||
if (!_isAnimating)
|
||||
size = [self _sendDelegateWindowWillResizeToSize:size];
|
||||
|
||||
[_windowView setFrameSize:size];
|
||||
|
||||
if (_hasShadow)
|
||||
@@ -975,6 +984,7 @@ CPTexturedBackgroundWindowMask
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:_CPPlatformWindowWillCloseNotification object:nil];
|
||||
|
||||
[[self contentView] _removeObservers];
|
||||
_hasBecomeKeyWindow = NO;
|
||||
}
|
||||
|
||||
|
||||
@@ -1429,6 +1439,9 @@ CPTexturedBackgroundWindowMask
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidResizeNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowWillBeginSheetNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidEndSheetNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidMiniaturizeNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidDeminiaturizeNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowWillMiniaturizeNotification object:self];
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
@@ -1442,6 +1455,9 @@ CPTexturedBackgroundWindowMask
|
||||
if ([_delegate respondsToSelector:@selector(windowWillClose:)])
|
||||
_implementedDelegateMethods |= CPWindowDelegate_windowWillClose_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowWillResize:toSize:)])
|
||||
_implementedDelegateMethods |= CPWindowDelegate_windowWillResize_toSize_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowDidResignKey:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
@@ -1497,6 +1513,27 @@ CPTexturedBackgroundWindowMask
|
||||
selector:@selector(windowDidEndSheet:)
|
||||
name:CPWindowDidEndSheetNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowDidMiniaturize:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(windowDidMiniaturize:)
|
||||
name:CPWindowDidMiniaturizeNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowWillMiniaturize:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(windowWillMiniaturize:)
|
||||
name:CPWindowWillMiniaturizeNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowDidDeminiaturize:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(windowDidDeminiaturize:)
|
||||
name:CPWindowDidDeminiaturizeNotification
|
||||
object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1809,6 +1846,9 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CPAppKitDefined:
|
||||
return [CPApp activateIgnoringOtherApps:YES];
|
||||
|
||||
case CPFlagsChanged:
|
||||
return [[self firstResponder] flagsChanged:anEvent];
|
||||
|
||||
@@ -2023,6 +2063,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[self _setupFirstResponder];
|
||||
_hasBecomeKeyWindow = YES;
|
||||
_platformWindow._currentKeyWindow = self;
|
||||
|
||||
[_windowView noteKeyWindowStateChanged];
|
||||
[_contentView _notifyWindowDidBecomeKey];
|
||||
@@ -2093,6 +2134,7 @@ CPTexturedBackgroundWindowMask
|
||||
if (CPApp._keyWindow === self)
|
||||
CPApp._keyWindow = nil;
|
||||
|
||||
_platformWindow._currentKeyWindow = nil;
|
||||
[_windowView noteKeyWindowStateChanged];
|
||||
[_contentView _notifyWindowDidResignKey];
|
||||
|
||||
@@ -2476,6 +2518,7 @@ CPTexturedBackgroundWindowMask
|
||||
- (void)becomeMainWindow
|
||||
{
|
||||
CPApp._mainWindow = self;
|
||||
_platformWindow._currentMainWindow = self;
|
||||
|
||||
[self _synchronizeSaveMenuWithDocumentSaving];
|
||||
|
||||
@@ -2498,6 +2541,7 @@ CPTexturedBackgroundWindowMask
|
||||
if (CPApp._mainWindow === self)
|
||||
CPApp._mainWindow = nil;
|
||||
|
||||
_platformWindow._currentMainWindow = nil;
|
||||
[_windowView noteMainWindowStateChanged];
|
||||
}
|
||||
|
||||
@@ -2736,7 +2780,7 @@ CPTexturedBackgroundWindowMask
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidEndSheetNotification object:self];
|
||||
|
||||
var sheet = _sheetContext[@"nextSheet"],
|
||||
modalDelegate =_sheetContext[@"nextModalDelegate"],
|
||||
modalDelegate = _sheetContext[@"nextModalDelegate"],
|
||||
endSelector = _sheetContext[@"nextEndSelector"],
|
||||
contextInfo = _sheetContext[@"nextContextInfo"];
|
||||
|
||||
@@ -3473,6 +3517,18 @@ var keyViewComparator = function(lhs, rhs, context)
|
||||
[_delegate windowWillClose:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate windowWillResize:toSize:
|
||||
*/
|
||||
- (CGSize)_sendDelegateWindowWillResizeToSize:(CGSize)aSize
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPWindowDelegate_windowWillResize_toSize_))
|
||||
return aSize;
|
||||
|
||||
return [_delegate windowWillResize:self toSize:aSize];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
@import "CGGradient.j"
|
||||
@import "_CPWindowView.j"
|
||||
|
||||
@global CPPopoverAppearanceMinimal
|
||||
|
||||
var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10);
|
||||
|
||||
@@ -39,7 +38,6 @@ var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10);
|
||||
{
|
||||
float _arrowOffsetX @accessors(property=arrowOffsetX);
|
||||
float _arrowOffsetY @accessors(property=arrowOffsetY);
|
||||
int _appearance @accessors(property=appearance);
|
||||
unsigned _preferredEdge @accessors(property=preferredEdge);
|
||||
|
||||
CGSize _cursorSize;
|
||||
@@ -123,7 +121,7 @@ var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10);
|
||||
{
|
||||
_arrowOffsetX = 0.0;
|
||||
_arrowOffsetY = 0.0;
|
||||
_appearance = CPPopoverAppearanceMinimal;
|
||||
_appearance = [CPAppearance appearanceNamed:CPAppearanceNameVibrantLight];
|
||||
_cursorSize = CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize);
|
||||
}
|
||||
|
||||
@@ -168,7 +166,7 @@ var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10);
|
||||
gradient,
|
||||
frame = [self bounds];
|
||||
|
||||
if (_appearance == CPPopoverAppearanceMinimal)
|
||||
if ([_appearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]])
|
||||
{
|
||||
gradient = [self valueForThemeAttribute:@"background-gradient"];
|
||||
strokeColor = [self valueForThemeAttribute:@"stroke-color"];
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
|
||||
@import "CGContext.j"
|
||||
@import "CGGeometry.j"
|
||||
|
||||
@import "CPColor.j"
|
||||
@import "CPView.j"
|
||||
|
||||
#define DOM(aLayer) aLayer._DOMElement
|
||||
|
||||
@@ -494,11 +495,11 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
*/
|
||||
- (void)display
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
if (!_context)
|
||||
{
|
||||
_context = CGBitmapGraphicsContextCreate();
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMContentsElement = _context.DOMElement;
|
||||
|
||||
_DOMContentsElement.style.zIndex = -100;
|
||||
@@ -516,7 +517,6 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
_DOMContentsElement.style.height = ROUND(CGRectGetHeight(_backingStoreFrame)) + "px";
|
||||
|
||||
_DOMElement.appendChild(_DOMContentsElement);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (USE_BUFFER)
|
||||
@@ -534,6 +534,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
|
||||
[self drawInContext:CABackingStoreGetContext(_contents)];
|
||||
}
|
||||
#endif
|
||||
|
||||
[self composite];
|
||||
}
|
||||
@@ -796,7 +797,6 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
|
||||
if (mask & CALayerDisplayUpdateMask)
|
||||
[layer display];
|
||||
|
||||
else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask)
|
||||
[layer composite];
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
|
||||
require("../common.jake");
|
||||
|
||||
checkUlimit();
|
||||
|
||||
var framework = require("objective-j/jake").framework,
|
||||
BundleTask = require("objective-j/jake").BundleTask;
|
||||
|
||||
|
||||
@@ -75,6 +75,12 @@ var PrimaryPlatformWindow = NULL;
|
||||
CPPlatformPasteboard _platformPasteboard;
|
||||
|
||||
CPString _overriddenEventType;
|
||||
|
||||
CPWindow _currentKeyWindow;
|
||||
CPWindow _previousKeyWindow;
|
||||
|
||||
CPWindow _currentMainWindow;
|
||||
CPWindow _previousMainWindow;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -48,10 +48,21 @@ var screenNeedsInitialization = NO,
|
||||
document.documentElement.style.overflow = "hidden";
|
||||
|
||||
if ([CPPlatform isBrowser])
|
||||
{
|
||||
// This differ from cocoa, where shouldTerminate is called in the method terminate of CPApp
|
||||
// Cappuccino acts like this because we can not close a window openend by the user with a script (so not possible in terminate), and we can only prevent the action in the method onbeforeunload in js.
|
||||
window.onbeforeunload = function()
|
||||
{
|
||||
if ([CPApp _sendDelegateApplicationShouldTerminate] != CPTerminateNow)
|
||||
return [CPApp _sendDelegateApplicationShouldTerminateMessage];
|
||||
};
|
||||
|
||||
window.onunload = function()
|
||||
{
|
||||
[self closeAllPlatformWindows];
|
||||
[CPApp terminate:nil];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)isBrowser
|
||||
@@ -138,4 +149,18 @@ var screenNeedsInitialization = NO,
|
||||
object:self];
|
||||
}
|
||||
|
||||
+ (void)closeAllPlatformWindows
|
||||
{
|
||||
var platformWindows = [CPPlatformWindow visiblePlatformWindows],
|
||||
primaryPlatformWindow = [CPPlatformWindow primaryPlatformWindow],
|
||||
platformWindowEnumerator = [platformWindows objectEnumerator],
|
||||
platformWindow = nil;
|
||||
|
||||
while ((platformWindow = [platformWindowEnumerator nextObject]) !== nil)
|
||||
{
|
||||
if (platformWindow != primaryPlatformWindow)
|
||||
[platformWindow orderOut:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -127,6 +127,7 @@
|
||||
@import "CPText.j"
|
||||
@import "CPWindow_Constants.j"
|
||||
|
||||
@class CPApplication
|
||||
@class CPDragServer
|
||||
@class _CPToolTip
|
||||
|
||||
@@ -202,6 +203,7 @@ var ModifierKeyCodes = [
|
||||
|
||||
var resizeTimer = nil;
|
||||
var PreventScroll = true;
|
||||
var blurTimer = nil;
|
||||
|
||||
_CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotification";
|
||||
|
||||
@@ -363,6 +365,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
_DOMBodyElement.style["-khtml-user-select"] = "none";
|
||||
|
||||
_DOMBodyElement.webkitTouchCallout = "none";
|
||||
_DOMBodyElement.style[CPBrowserStyleProperty(@"user-select")] = @"none";
|
||||
|
||||
[self createDOMElements];
|
||||
[self _addLayers];
|
||||
@@ -396,7 +399,15 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
|
||||
touchEventSelector = @selector(touchEvent:),
|
||||
touchEventImplementation = class_getMethodImplementation(theClass, touchEventSelector),
|
||||
touchEventCallback = function (anEvent) { touchEventImplementation(self, nil, anEvent); };
|
||||
touchEventCallback = function (anEvent) { touchEventImplementation(self, nil, anEvent); },
|
||||
|
||||
onFocusEventSelector = @selector(focusEvent:),
|
||||
onFocusEventImplementation = class_getMethodImplementation(theClass, onFocusEventSelector),
|
||||
onFocusEventCallback = function (anEvent) { onFocusEventImplementation(self, nil, anEvent); },
|
||||
|
||||
onBlurEventSelector = @selector(blurEvent:),
|
||||
onBlurEventImplementation = class_getMethodImplementation(theClass, onBlurEventSelector),
|
||||
onBlurEventCallback = function (anEvent) { onBlurEventImplementation(self, nil, anEvent); };
|
||||
|
||||
if (theDocument.addEventListener)
|
||||
{
|
||||
@@ -430,10 +441,14 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
|
||||
_DOMWindow.addEventListener("resize", resizeEventCallback, NO);
|
||||
|
||||
_DOMWindow.addEventListener("blur", onBlurEventCallback, NO);
|
||||
_DOMWindow.addEventListener("focus", onFocusEventCallback, NO);
|
||||
|
||||
_DOMWindow.addEventListener("unload", function()
|
||||
{
|
||||
_DOMWindow.removeEventListener("unload", arguments.callee, NO);
|
||||
|
||||
[self blurEvent:nil];
|
||||
[self _notifyPlatformWindowWillClose];
|
||||
[self updateFromNativeContentRect];
|
||||
[self _removeLayers];
|
||||
@@ -453,6 +468,9 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
|
||||
_DOMWindow.removeEventListener("resize", resizeEventCallback, NO);
|
||||
|
||||
_DOMWindow.removeEventListener("blur", onBlurEventCallback, NO);
|
||||
_DOMWindow.removeEventListener("focus", onFocusEventCallback, NO);
|
||||
|
||||
//FIXME: does firefox really need a different value?
|
||||
_DOMWindow.removeEventListener("DOMMouseScroll", scrollEventCallback, NO);
|
||||
_DOMWindow.removeEventListener("wheel", scrollEventCallback, NO);
|
||||
@@ -479,6 +497,9 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
|
||||
_DOMWindow.attachEvent("onresize", resizeEventCallback);
|
||||
|
||||
_DOMWindow.attachEvent("onfocus", onFocusEventCallback);
|
||||
_DOMWindow.attachEvent("onblur", onBlurEventCallback);
|
||||
|
||||
_DOMWindow.onmousewheel = scrollEventCallback;
|
||||
theDocument.onmousewheel = scrollEventCallback;
|
||||
|
||||
@@ -489,6 +510,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
{
|
||||
_DOMWindow.detachEvent("unload", arguments.callee);
|
||||
|
||||
[self blurEvent:nil];
|
||||
[self _notifyPlatformWindowWillClose];
|
||||
[self updateFromNativeContentRect];
|
||||
[self _removeLayers];
|
||||
@@ -505,7 +527,11 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
|
||||
_DOMWindow.detachEvent("onresize", resizeEventCallback);
|
||||
|
||||
_DOMWindow.detachEvent("onfocus", onBlurEventCallback);
|
||||
_DOMWindow.detachEvent("onblur", onFocusEventCallback);
|
||||
|
||||
_DOMWindow.onmousewheel = NULL;
|
||||
|
||||
theDocument.onmousewheel = NULL;
|
||||
|
||||
_DOMBodyElement.ondrag = NULL;
|
||||
@@ -545,7 +571,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
[PlatformWindows addObject:self];
|
||||
|
||||
// FIXME: cpSetFrame?
|
||||
_DOMWindow.document.write('<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body style="background-color:transparent;"></body></html>');
|
||||
_DOMWindow.document.write('<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body style="background-color:transparent; overflow:hidden"></body></html>');
|
||||
_DOMWindow.document.close();
|
||||
|
||||
if (self != [CPPlatformWindow primaryPlatformWindow])
|
||||
@@ -1031,6 +1057,96 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
_shouldUpdateContentRect = YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)blurEvent:(DOMEvent)aDOMEvent
|
||||
{
|
||||
if ([CPApp keyWindow] == _currentKeyWindow)
|
||||
[_currentKeyWindow resignKeyWindow];
|
||||
|
||||
if ([CPApp mainWindow] == _currentMainWindow)
|
||||
[_currentMainWindow resignMainWindow];
|
||||
|
||||
_previousKeyWindow = aDOMEvent ? _currentKeyWindow : nil;
|
||||
_previousMainWindow = aDOMEvent ? _currentMainWindow : nil;
|
||||
|
||||
[blurTimer invalidate];
|
||||
blurTimer = [CPTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(_blurEventTimer:) userInfo:nil repeats:NO];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_blurEventTimer:(CPTimer)aTimer
|
||||
{
|
||||
if (![CPApp mainWindow])
|
||||
[[CPApplication sharedApplication] deactivate];
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)focusEvent:(DOMEvent)aDOMEvent
|
||||
{
|
||||
[blurTimer invalidate];
|
||||
[CPApp activateIgnoringOtherApps:YES];
|
||||
|
||||
var keyWindow = _previousKeyWindow;
|
||||
|
||||
if (!keyWindow)
|
||||
keyWindow = [[[_windowLayers objectForKey:[_windowLevels firstObject]] orderedWindows] firstObject];
|
||||
|
||||
if (!keyWindow)
|
||||
return;
|
||||
|
||||
[self _makeKeyWindow:keyWindow];
|
||||
|
||||
if ([keyWindow isKeyWindow] && ([keyWindow firstResponder] === keyWindow || ![keyWindow firstResponder]))
|
||||
[keyWindow makeFirstResponder:[keyWindow initialFirstResponder]];
|
||||
|
||||
[self _makeMainWindow:keyWindow];
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
|
||||
_previousKeyWindow = nil;
|
||||
_previousMainWindow = nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_makeKeyWindow:(CPWindow)aWindow
|
||||
{
|
||||
if ([CPApp keyWindow] === aWindow || ![aWindow canBecomeKeyWindow])
|
||||
return;
|
||||
|
||||
[[CPApp keyWindow] resignKeyWindow];
|
||||
[aWindow becomeKeyWindow];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_makeMainWindow:(CPWindow)aWindow
|
||||
{
|
||||
// Sheets cannot be main. Their parent window becomes main.
|
||||
if (aWindow._isSheet)
|
||||
{
|
||||
[self _makeMainWindow:aWindow._parentView];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([CPApp mainWindow] === aWindow || ![aWindow canBecomeMainWindow])
|
||||
return;
|
||||
|
||||
[[CPApp mainWindow] resignMainWindow];
|
||||
[aWindow becomeMainWindow];
|
||||
}
|
||||
|
||||
|
||||
- (void)touchEvent:(DOMEvent)aDOMEvent
|
||||
{
|
||||
if (aDOMEvent.touches && (aDOMEvent.touches.length == 1 || (aDOMEvent.touches.length == 0 && aDOMEvent.changedTouches.length == 1)))
|
||||
|
||||
@@ -1243,8 +1243,8 @@ var themedButtonValues = nil,
|
||||
|
||||
overrides =
|
||||
[
|
||||
[@"image-search-left-margin", 5],
|
||||
[@"image-cancel-right-margin", 5],
|
||||
[@"image-search-inset", CGInsetMake(0, 0, 0, 5)],
|
||||
[@"image-cancel-inset", CGInsetMake(0, 5, 0, 0)],
|
||||
|
||||
[@"image-search", imageSearch],
|
||||
[@"image-find", imageFind],
|
||||
@@ -1255,15 +1255,15 @@ var themedButtonValues = nil,
|
||||
[@"image-find", smallImageFind, CPThemeStateControlSizeSmall],
|
||||
[@"image-cancel", smallImageCancel, CPThemeStateControlSizeSmall],
|
||||
[@"image-cancel-pressed", smallImageCancelPressed, CPThemeStateControlSizeSmall],
|
||||
[@"image-search-left-margin", 8, CPThemeStateControlSizeSmall],
|
||||
[@"image-cancel-right-margin", 8, CPThemeStateControlSizeSmall],
|
||||
[@"image-search-inset", CGInsetMake(0, 0, 0, 8), CPThemeStateControlSizeSmall],
|
||||
[@"image-cancel-inset", CGInsetMake(0, 8, 0, 0), CPThemeStateControlSizeSmall],
|
||||
|
||||
[@"image-search", miniImageSearch, CPThemeStateControlSizeMini],
|
||||
[@"image-find", miniImageFind, CPThemeStateControlSizeMini],
|
||||
[@"image-cancel", miniImageCancel, CPThemeStateControlSizeMini],
|
||||
[@"image-cancel-pressed", miniImageCancelPressed, CPThemeStateControlSizeMini],
|
||||
[@"image-search-left-margin", 8, CPThemeStateControlSizeMini],
|
||||
[@"image-cancel-right-margin", 8, CPThemeStateControlSizeMini],
|
||||
[@"image-search-inset", CGInsetMake(0, 0, 0, 8), CPThemeStateControlSizeMini],
|
||||
[@"image-cancel-inset", CGInsetMake(0, 8, 0, 0), CPThemeStateControlSizeMini],
|
||||
];
|
||||
|
||||
[self registerThemeValues:overrides forView:searchField inherit:themedRoundedTextFieldValues];
|
||||
@@ -2999,6 +2999,24 @@ var themedButtonValues = nil,
|
||||
return progressBar;
|
||||
}
|
||||
|
||||
+ (CPProgressIndicator)themedCircularProgressIndicator
|
||||
{
|
||||
var progressBar = [[CPProgressIndicator alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
|
||||
[progressBar setStyle:CPProgressIndicatorSpinningStyle];
|
||||
[progressBar setIndeterminate:NO];
|
||||
|
||||
var themeValues =
|
||||
[
|
||||
[@"circular-border-color", [CPColor colorWithHexString:@"C7C7C7"]],
|
||||
[@"circular-border-size", 1],
|
||||
[@"circular-color", [CPColor colorWithHexString:@"89B5CD"]]
|
||||
];
|
||||
|
||||
[self registerThemeValues:themeValues forView:progressBar];
|
||||
|
||||
return progressBar;
|
||||
}
|
||||
|
||||
+ (CPBox)themedBox
|
||||
{
|
||||
var box = [[CPBox alloc] initWithFrame:CGRectMake(0,0,100,100)],
|
||||
|
||||
@@ -688,7 +688,8 @@ var themedButtonValues = nil,
|
||||
[@"text-color", [CPColor blackColor], [CPThemeStateTableDataView, CPThemeStateSelectedDataView, CPThemeStateEditable, CPThemeStateFirstResponder, CPThemeStateKeyWindow]],
|
||||
[@"content-inset", CGInsetMake(7.0, 7.0, 5.0, 10.0), [CPThemeStateTableDataView, CPThemeStateEditable]],
|
||||
[@"font", [CPFont systemFontOfSize:CPFontCurrentSystemSize], [CPThemeStateTableDataView, CPThemeStateEditing]],
|
||||
[@"bezel-inset", CGInsetMake(-2.0, -2.0, -2.0, -2.0), [CPThemeStateTableDataView, CPThemeStateEditing]],
|
||||
[@"bezel-inset", CGInsetMake(-2.0, -2.0, -2.0, -2.0), [CPThemeStateTableDataView, CPThemeStateEditable, CPThemeStateEditing]],
|
||||
[@"bezel-inset", CGInsetMake(1.0, 1.0, 1.0, 1.0), [CPThemeStateTableDataView, CPThemeStateEditable]],
|
||||
|
||||
[@"text-color", [CPColor colorWithCalibratedWhite:125.0 / 255.0 alpha:1.0], [CPThemeStateTableDataView, CPThemeStateGroupRow]],
|
||||
[@"text-color", [CPColor whiteColor], [CPThemeStateTableDataView, CPThemeStateGroupRow, CPThemeStateSelectedDataView, CPThemeStateFirstResponder, CPThemeStateKeyWindow]],
|
||||
@@ -824,8 +825,8 @@ var themedButtonValues = nil,
|
||||
|
||||
overrides =
|
||||
[
|
||||
[@"image-search-left-margin", 5],
|
||||
[@"image-cancel-right-margin", 5],
|
||||
[@"image-search-inset", CGInsetMake(0, 0, 0, 5)],
|
||||
[@"image-cancel-inset", CGInsetMake(0, 5, 0, 0)],
|
||||
|
||||
[@"image-search", imageSearch],
|
||||
[@"image-find", imageFind],
|
||||
@@ -2499,6 +2500,24 @@ var themedButtonValues = nil,
|
||||
return progressBar;
|
||||
}
|
||||
|
||||
+ (CPProgressIndicator)themedCircularProgressIndicator
|
||||
{
|
||||
var progressBar = [[CPProgressIndicator alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
|
||||
[progressBar setStyle:CPProgressIndicatorSpinningStyle];
|
||||
[progressBar setIndeterminate:NO];
|
||||
|
||||
var themeValues =
|
||||
[
|
||||
[@"circular-border-color", [CPColor colorWithHexString:@"A0A0A0"]],
|
||||
[@"circular-border-size", 1],
|
||||
[@"circular-color", [CPColor colorWithHexString:@"5982DA"]]
|
||||
];
|
||||
|
||||
[self registerThemeValues:themeValues forView:progressBar];
|
||||
|
||||
return progressBar;
|
||||
}
|
||||
|
||||
+ (CPBox)themedBox
|
||||
{
|
||||
var box = [[CPBox alloc] initWithFrame:CGRectMake(0, 0, 100, 100)],
|
||||
|
||||
+39
-16
@@ -141,7 +141,12 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
|
||||
if (_appearance === anAppearance)
|
||||
return;
|
||||
|
||||
[_windowView setAppearance:anAppearance];
|
||||
_appearance = anAppearance;
|
||||
|
||||
var appearanceName = _appearance == CPPopoverAppearanceMinimal ? CPAppearanceNameVibrantLight : CPAppearanceNameVibrantDark,
|
||||
viewAppearance = [CPAppearance appearanceNamed:appearanceName];
|
||||
|
||||
[_windowView setAppearance:viewAppearance];
|
||||
}
|
||||
|
||||
- (void)setStyleMask:(unsigned)aStyleMask
|
||||
@@ -548,29 +553,36 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
|
||||
|
||||
// Now set up the pop-in to normal size transition.
|
||||
// Because we are watching the -webkit-transform, it will occur now.
|
||||
[self setCSS3Property:@"Transform" value:@"scale(1)"];
|
||||
[self setCSS3Property:@"Transition" value:CPBrowserCSSProperty('transform') + @" 50ms linear"];
|
||||
|
||||
_transitionCompleteFunction = function()
|
||||
window.setTimeout(function()
|
||||
{
|
||||
[self setCSS3Property:@"Transform" value:@"scale(1)"];
|
||||
[self setCSS3Property:@"Transition" value:CPBrowserCSSProperty('transform') + @" 50ms linear"];
|
||||
|
||||
_transitionCompleteFunction = function()
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.removeEventListener(CPBrowserStyleProperty('transitionend'), _transitionCompleteFunction, YES);
|
||||
_DOMElement.removeEventListener(CPBrowserStyleProperty('transitionend'), _transitionCompleteFunction, YES);
|
||||
|
||||
// Make sure to clear these properties when the animation is done. Without this,
|
||||
// the window becomes blurry in Chrome, presumably because the browser composits
|
||||
// a layer with a transform differently even when it's an identity transform.
|
||||
[self setCSS3Property:@"Transform" value:nil];
|
||||
[self setCSS3Property:@"TransformOrigin" value:nil];
|
||||
[self setCSS3Property:@"Transition" value:nil];
|
||||
// Make sure to clear these properties when the animation is done. Without this,
|
||||
// the window becomes blurry in Chrome, presumably because the browser composits
|
||||
// a layer with a transform differently even when it's an identity transform.
|
||||
[self setCSS3Property:@"Transform" value:nil];
|
||||
[self setCSS3Property:@"TransformOrigin" value:nil];
|
||||
[self setCSS3Property:@"Transition" value:nil];
|
||||
#endif
|
||||
_isOpening = NO;
|
||||
_isOpening = NO;
|
||||
|
||||
[_delegate _popoverWindowDidShow];
|
||||
}
|
||||
[_delegate _popoverWindowDidShow];
|
||||
}
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), _transitionCompleteFunction, YES);
|
||||
_DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), _transitionCompleteFunction, YES);
|
||||
#endif
|
||||
}, 0); // There are some weird random conditions happening in Chrome 44. If we don't put a timeout to 0 for the end of
|
||||
// the transition, the popover is blinking. It happens on Opera as well...
|
||||
// When the condition is met, the popover will lag a bit when opening...nothing crazy ;)
|
||||
// An issue has been opened here : https://code.google.com/p/chromium/issues/detail?id=523044&thanks=523044&ts=1440095724
|
||||
};
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
@@ -668,6 +680,17 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
|
||||
[_delegate _popoverWindowDidClose];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Needed to be ignored to close a popover when a platform is closed.
|
||||
Because the animation, the popover is not properly closed.
|
||||
*/
|
||||
- (void)_didReceivePlatformWindowWillCloseNotification:(CPNotification)aNotification
|
||||
{
|
||||
[super _didReceivePlatformWindowWillCloseNotification:aNotification];
|
||||
[self _orderOutRecursively:YES];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Private
|
||||
@@ -715,7 +738,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
|
||||
|
||||
// Consider clicks in child windows to be "inside". This keeps a transient popover from
|
||||
// closing if e.g. the window containing the menu of a token field is clicked.
|
||||
if (mouseWindow === self || [mouseWindow _hasAncestorWindow:self] || ![self _hasOnlyTransientChild:self])
|
||||
if (mouseWindow === self || [mouseWindow _hasAncestorWindow:self] || ![self _hasOnlyTransientChild:self] || [mouseWindow platformWindow] != [self platformWindow])
|
||||
{
|
||||
[self _trapNextMouseDown];
|
||||
}
|
||||
|
||||
+25
-10
@@ -366,23 +366,38 @@ function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
return {executable:includedBytes, data:dataBytes, mhtml:mhtmlBytes};
|
||||
}
|
||||
|
||||
function pngcrushDirectory(directory) {
|
||||
var directoryPath = FILE.path(directory);
|
||||
var pngs = directoryPath.glob("**/*.png");
|
||||
function pngcrushDirectory(directory)
|
||||
{
|
||||
var directoryPath = FILE.path(directory),
|
||||
pngs = directoryPath.glob("**/*.png");
|
||||
|
||||
system.stderr.print("Running pngcrush on " + pngs.length + " pngs:");
|
||||
pngs.forEach(function(dstPath) {
|
||||
pngs.forEach(function(dstPath)
|
||||
{
|
||||
var tmpPath = FILE.path(dstPath+".tmp");
|
||||
|
||||
var p = OS.popen(["pngcrush", "-rem", "alla", "-reduce", /*"-brute",*/ dstPath, tmpPath]);
|
||||
if (p.wait()) {
|
||||
CPLog.warn("pngcrush failed. Ensure it's installed and on your PATH.");
|
||||
try
|
||||
{
|
||||
var p = OS.popen(["pngcrush", "-rem", "alla", "-reduce", /*"-brute",*/ dstPath, tmpPath]);
|
||||
|
||||
if (p.wait())
|
||||
{
|
||||
CPLog.warn("pngcrush failed. Ensure it's installed and on your PATH.");
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE.move(tmpPath, dstPath);
|
||||
system.stderr.write(".").flush();
|
||||
}
|
||||
}
|
||||
else {
|
||||
FILE.move(tmpPath, dstPath);
|
||||
system.stderr.write(".").flush();
|
||||
finally
|
||||
{
|
||||
p.stdin.close();
|
||||
p.stdout.close();
|
||||
p.stderr.close();
|
||||
}
|
||||
});
|
||||
|
||||
system.stderr.print("");
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,20 @@ var OS = require("os");
|
||||
|
||||
exports.fontinfo = function(name, size)
|
||||
{
|
||||
var p = OS.popen(["fontinfo", "-n", name, size || 12]);
|
||||
var result;
|
||||
|
||||
if (p.wait() === 0)
|
||||
return JSON.parse(p.stdout.read());
|
||||
else
|
||||
return null;
|
||||
try
|
||||
{
|
||||
var p = OS.popen(["fontinfo", "-n", name, size || 12]);
|
||||
if (p.wait() === 0)
|
||||
result = p.stdout.read();
|
||||
}
|
||||
finally
|
||||
{
|
||||
p.stdin.close();
|
||||
p.stdout.close();
|
||||
p.stderr.close();
|
||||
}
|
||||
|
||||
return result ? JSON.parse(result) : null;
|
||||
};
|
||||
|
||||
@@ -3,10 +3,20 @@ var OS = require("os");
|
||||
|
||||
exports.imagesize = function(path)
|
||||
{
|
||||
var p = OS.popen(["imagesize", "-n", path]);
|
||||
var result;
|
||||
|
||||
if (p.wait() === 0)
|
||||
return JSON.parse(p.stdout.read());
|
||||
else
|
||||
return null;
|
||||
try
|
||||
{
|
||||
var p = OS.popen(["imagesize", "-n", path]);
|
||||
if (p.wait() === 0)
|
||||
result = p.stdout.read();
|
||||
}
|
||||
finally
|
||||
{
|
||||
p.stdin.close();
|
||||
p.stdout.close();
|
||||
p.stderr.close();
|
||||
}
|
||||
|
||||
return result ? JSON.parse(result) : null;
|
||||
};
|
||||
|
||||
@@ -208,6 +208,14 @@ var concat = Array.prototype.concat,
|
||||
_CPRaiseInvalidAbstractInvocation(self, _cmd);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a hash for the object. Unlike Cocoa, the hash value does not take content into account, so two arrays with the same content (\c isEqual: === YES) will not generate the same hash.
|
||||
*/
|
||||
- (unsigned)hash
|
||||
{
|
||||
return [self UID];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the first object in the array. If the array is empty, returns \c nil
|
||||
*/
|
||||
|
||||
@@ -196,7 +196,8 @@ var concat = Array.prototype.concat,
|
||||
}
|
||||
|
||||
else
|
||||
for (; index < count; ++index) {
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var receiver = self[index];
|
||||
receiver == nil ? nil : receiver.isa.objj_msgSend0(receiver, aSelector);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
@import "CPString.j"
|
||||
|
||||
// The default global behavior class, created lazily
|
||||
var CPDefaultDcmHandler = nil;
|
||||
var CPDefaultDcmHandler = nil,
|
||||
CPDecimalNumberUIDs = new CFMutableDictionary();
|
||||
|
||||
/*!
|
||||
@class CPDecimalNumberHandler
|
||||
@@ -531,6 +532,20 @@ var CPDecimalNumberHandlerRoundingModeKey = @"CPDecimalNumberHandlerRoundi
|
||||
}
|
||||
|
||||
// instance methods
|
||||
|
||||
- (CPString)UID
|
||||
{
|
||||
var UID = CPDecimalNumberUIDs.valueForKey(self);
|
||||
|
||||
if (!UID)
|
||||
{
|
||||
UID = objj_generateObjectUID();
|
||||
CPDecimalNumberUIDs.setValueForKey(self, UID);
|
||||
}
|
||||
|
||||
return UID + "";
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a new CPDecimalNumber object with the result of the summation of
|
||||
the receiver object and \c decimalNumber. If overflow occurs then the
|
||||
|
||||
@@ -26,10 +26,7 @@
|
||||
@import "CPNull.j"
|
||||
@import "CPObject.j"
|
||||
|
||||
//FIXME: After release of 0.9.7 remove below variable
|
||||
var CPDictionaryShowNilDeprecationMessage = YES,
|
||||
|
||||
CPDictionaryMaxDescriptionRecursion = 10;
|
||||
var CPDictionaryMaxDescriptionRecursion = 10;
|
||||
|
||||
/*!
|
||||
@class CPDictionary
|
||||
@@ -238,28 +235,10 @@ var CPDictionaryShowNilDeprecationMessage = YES,
|
||||
key = keyArray[i];
|
||||
|
||||
if (value === nil)
|
||||
{
|
||||
CPDictionaryShowNilDeprecationMessage = NO;
|
||||
CPLog.warn([CPString stringWithFormat:@"[%s %s] DEPRECATED: Attempt to insert nil object from objects[%d]", [self className], _cmd, i]);
|
||||
|
||||
if (typeof(objj_backtrace_print) === "function")
|
||||
objj_backtrace_print(CPLog.warn);
|
||||
|
||||
// FIXME: After release of 0.9.7 change this block to:
|
||||
// [CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil object from objects[" + i + @"]"];
|
||||
}
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil object from objects[" + i + @"]"];
|
||||
|
||||
if (key === nil)
|
||||
{
|
||||
CPDictionaryShowNilDeprecationMessage = NO;
|
||||
CPLog.warn([CPString stringWithFormat:@"[%s %s] DEPRECATED: Attempt to insert nil key from keys[%d]", [self className], _cmd, i]);
|
||||
|
||||
if (typeof(objj_backtrace_print) === "function")
|
||||
objj_backtrace_print(CPLog.warn);
|
||||
|
||||
// FIXME: After release of 0.9.7 change this block to:
|
||||
// [CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil key from keys[" + i + @"]"];
|
||||
}
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil key from keys[" + i + @"]"];
|
||||
|
||||
[self setObject:value forKey:key];
|
||||
}
|
||||
@@ -302,28 +281,10 @@ var CPDictionaryShowNilDeprecationMessage = YES,
|
||||
key = arguments[index + 1];
|
||||
|
||||
if (value === nil)
|
||||
{
|
||||
CPDictionaryShowNilDeprecationMessage = NO;
|
||||
CPLog.warn([CPString stringWithFormat:@"[%s %s] DEPRECATED: Attempt to insert nil object from objects[%d]", [self className], _cmd, (index / 2) - 1]);
|
||||
|
||||
if (typeof(objj_backtrace_print) === "function")
|
||||
objj_backtrace_print(CPLog.warn);
|
||||
|
||||
// FIXME: After release of 0.9.7 change 3 lines above to this:
|
||||
// [CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil object from objects[" + ((index / 2) - 1) + @"]"];
|
||||
}
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil object from objects[" + ((index / 2) - 1) + @"]"];
|
||||
|
||||
if (key === nil)
|
||||
{
|
||||
CPDictionaryShowNilDeprecationMessage = NO;
|
||||
CPLog.warn([CPString stringWithFormat:@"[%s %s] DEPRECATED: Attempt to insert nil key from keys[%d]", [self className], _cmd, (index / 2) - 1]);
|
||||
|
||||
if (typeof(objj_backtrace_print) === "function")
|
||||
objj_backtrace_print(CPLog.warn);
|
||||
|
||||
// FIXME: After release of 0.9.7 change 3 lines above to this:
|
||||
// [CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil key from keys[" + ((index / 2) - 1) + @"]"];
|
||||
}
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Attempt to insert nil key from keys[" + ((index / 2) - 1) + @"]"];
|
||||
|
||||
[self setObject:value forKey:key];
|
||||
}
|
||||
@@ -634,34 +595,11 @@ var CPDictionaryShowNilDeprecationMessage = YES,
|
||||
*/
|
||||
- (void)setObject:(id)anObject forKey:(id)aKey
|
||||
{
|
||||
// FIXME: After release of 0.9.7, remove this test and leave the contents of its block
|
||||
if (CPDictionaryShowNilDeprecationMessage)
|
||||
{
|
||||
if (aKey === nil)
|
||||
{
|
||||
CPLog.warn([CPString stringWithFormat:@"[%s %s] DEPRECATED: key cannot be nil", [self className], _cmd]);
|
||||
if (aKey === nil)
|
||||
[CPException raise:CPInvalidArgumentException reason:@"key cannot be nil"];
|
||||
|
||||
if (typeof(objj_backtrace_print) === "function")
|
||||
objj_backtrace_print(CPLog.warn);
|
||||
|
||||
// FIXME: After release of 0.9.7 change this block to:
|
||||
// [CPException raise:CPInvalidArgumentException reason:@"key cannot be nil"];
|
||||
}
|
||||
|
||||
if (anObject === nil)
|
||||
{
|
||||
CPLog.warn([CPString stringWithFormat:@"[%s %s] DEPRECATED: object cannot be nil (key: %s)", [self className], _cmd, aKey]);
|
||||
|
||||
if (typeof(objj_backtrace_print) === "function")
|
||||
objj_backtrace_print(CPLog.warn);
|
||||
|
||||
// FIXME: After release of 0.9.7 change this block to:
|
||||
// [CPException raise:CPInvalidArgumentException reason:@"object cannot be nil (key: " + aKey + @")"];
|
||||
}
|
||||
}
|
||||
// FIXME: After release of 0.9.7 remove 2 lines below.
|
||||
else
|
||||
CPDictionaryShowNilDeprecationMessage = YES;
|
||||
if (anObject === nil)
|
||||
[CPException raise:CPInvalidArgumentException reason:@"object cannot be nil (key: " + aKey + @")"];
|
||||
|
||||
self.setValueForKey(aKey, anObject);
|
||||
}
|
||||
|
||||
@@ -605,11 +605,11 @@
|
||||
}
|
||||
if ([self scanPredicateKeyword:@"TRUE"] || [self scanPredicateKeyword:@"YES"])
|
||||
{
|
||||
return [CPExpression expressionForConstantValue:[CPNumber numberWithBool:YES]];
|
||||
return [CPExpression expressionForConstantValue:YES];
|
||||
}
|
||||
if ([self scanPredicateKeyword:@"FALSE"] || [self scanPredicateKeyword:@"NO"])
|
||||
{
|
||||
return [CPExpression expressionForConstantValue:[CPNumber numberWithBool:NO]];
|
||||
return [CPExpression expressionForConstantValue:NO];
|
||||
}
|
||||
if ([self scanPredicateKeyword:@"SELF"])
|
||||
{
|
||||
|
||||
@@ -266,7 +266,7 @@ var abbreviationDictionary,
|
||||
@"MST" : [@"Mountain Standard Time", @"MST", @"Mountain Daylight Time", @"MDT", @"Mountain Time", @"MT"],
|
||||
@"PHT" : [@"Philippine Standard Time", @"GMT+08:00", @"Philippine Summer Time", @"GMT+08:00", @"Philippine Standard Time", @"Philippines Time"],
|
||||
@"WET" : [@"Western European Standard Time", @"GMT", @"Western European Summer Time", @"GMT+01:00", @"Western European Time", @"Portugal Time (Lisbon)"]
|
||||
};
|
||||
};
|
||||
|
||||
var date = [CPDate date],
|
||||
abbreviation = String(String(date).split("(")[1]).split(")")[0];
|
||||
|
||||
@@ -26,6 +26,16 @@
|
||||
@import "CPURLRequest.j"
|
||||
@import "CPURLResponse.j"
|
||||
|
||||
@protocol CPURLConnectionDelegate <CPObject>
|
||||
|
||||
- (void)connection:(CPURLConnection)anURLConnection didFailWithError:(CPException)anError;
|
||||
- (void)connection:(CPURLConnection)anURLConnection didReceiveData:(CPString)aData;
|
||||
- (void)connection:(CPURLConnection)anURLConnection didReceiveResponse:(CPString)aResponse;
|
||||
- (void)connectionDidFinishLoading:(CPURLConnection)anURLConnection;
|
||||
- (void)connectionDidReceiveAuthenticationChallenge:(CPURLConnection)anURLConnection;
|
||||
|
||||
@end
|
||||
|
||||
@typedef HTTPRequest
|
||||
|
||||
var CPURLConnectionDelegate = nil;
|
||||
@@ -76,16 +86,16 @@ var CPURLConnectionDelegate = nil;
|
||||
*/
|
||||
@implementation CPURLConnection : CPObject
|
||||
{
|
||||
CPURLRequest _originalRequest @accessors(readonly, getter=originalRequest);
|
||||
CPURLRequest _request @accessors(readonly, getter=currentRequest);
|
||||
id _delegate;
|
||||
BOOL _isCanceled;
|
||||
BOOL _isLocalFileConnection;
|
||||
CPURLRequest _originalRequest @accessors(readonly, getter=originalRequest);
|
||||
CPURLRequest _request @accessors(readonly, getter=currentRequest);
|
||||
id <CPURLConnectionDelegate> _delegate;
|
||||
BOOL _isCanceled;
|
||||
BOOL _isLocalFileConnection;
|
||||
|
||||
HTTPRequest _HTTPRequest;
|
||||
HTTPRequest _HTTPRequest;
|
||||
}
|
||||
|
||||
+ (void)setClassDelegate:(id)delegate
|
||||
+ (void)setClassDelegate:(id <CPURLConnectionDelegate>)delegate
|
||||
{
|
||||
CPURLConnectionDelegate = delegate;
|
||||
}
|
||||
@@ -145,7 +155,7 @@ var CPURLConnectionDelegate = nil;
|
||||
@param shouldStartImmediately whether the \c -start method should be called from here
|
||||
@return the initialized url connection
|
||||
*/
|
||||
- (id)initWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate startImmediately:(BOOL)shouldStartImmediately
|
||||
- (id)initWithRequest:(CPURLRequest)aRequest delegate:(id <CPURLConnectionDelegate>)aDelegate startImmediately:(BOOL)shouldStartImmediately
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
@@ -166,6 +176,7 @@ var CPURLConnectionDelegate = nil;
|
||||
(window.location.protocol === "file:" || window.location.protocol === "app:"));
|
||||
|
||||
_HTTPRequest = new CFHTTPRequest();
|
||||
_HTTPRequest.setTimeout([aRequest timeoutInterval] * 1000);
|
||||
_HTTPRequest.setWithCredentials([aRequest withCredentials]);
|
||||
|
||||
if (shouldStartImmediately)
|
||||
@@ -175,7 +186,7 @@ var CPURLConnectionDelegate = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate
|
||||
- (id)initWithRequest:(CPURLRequest)aRequest delegate:(id <CPURLConnectionDelegate>)aDelegate
|
||||
{
|
||||
return [self initWithRequest:aRequest delegate:aDelegate startImmediately:YES];
|
||||
}
|
||||
@@ -200,6 +211,7 @@ var CPURLConnectionDelegate = nil;
|
||||
_HTTPRequest.open([_request HTTPMethod], [[_request URL] absoluteString], YES);
|
||||
|
||||
_HTTPRequest.onreadystatechange = function() { [self _readyStateDidChange]; };
|
||||
_HTTPRequest.ontimeout = function() { [self _didTimeout]; };
|
||||
|
||||
var fields = [_request allHTTPHeaderFields],
|
||||
key = nil,
|
||||
@@ -212,11 +224,16 @@ var CPURLConnectionDelegate = nil;
|
||||
}
|
||||
catch (anException)
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(connection:didFailWithError:)])
|
||||
[_delegate connection:self didFailWithError:anException];
|
||||
[self _sendDelegateDidFailWithError:anException];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_sendDelegateDidFailWithError:(CPException)anException
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(connection:didFailWithError:)])
|
||||
[_delegate connection:self didFailWithError:anException];
|
||||
}
|
||||
|
||||
/*
|
||||
Cancels the current request.
|
||||
*/
|
||||
@@ -239,10 +256,22 @@ var CPURLConnectionDelegate = nil;
|
||||
return _isLocalFileConnection;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_didTimeout
|
||||
{
|
||||
var exception = [CPException exceptionWithName:@"Timeout exception"
|
||||
reason:"The request timed out."
|
||||
userInfo:@{}];
|
||||
|
||||
[self _sendDelegateDidFailWithError:exception];
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (void)_readyStateDidChange
|
||||
{
|
||||
if (_HTTPRequest.readyState() === CFHTTPRequest.CompleteState)
|
||||
if (_HTTPRequest.readyState() === CFHTTPRequest.CompleteState && !_HTTPRequest.isTimeoutRequest())
|
||||
{
|
||||
var statusCode = _HTTPRequest.status(),
|
||||
URL = [_request URL];
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
@import "CPString.j"
|
||||
@import "CPURL.j"
|
||||
|
||||
@typedef CPURLRequestCachePolicy
|
||||
CPURLRequestUseProtocolCachePolicy = 0;
|
||||
CPURLRequestReloadIgnoringLocalCacheData = 1;
|
||||
CPURLRequestReturnCacheDataElseLoad = 2;
|
||||
CPURLRequestReturnCacheDataDontLoad = 3;
|
||||
|
||||
/*!
|
||||
@class CPURLRequest
|
||||
@ingroup foundation
|
||||
@@ -35,14 +41,16 @@
|
||||
*/
|
||||
@implementation CPURLRequest : CPObject
|
||||
{
|
||||
CPURL _URL @accessors(property=URL);
|
||||
CPURL _URL @accessors(property=URL);
|
||||
|
||||
// FIXME: this should be CPData
|
||||
CPString _HTTPBody @accessors(property=HTTPBody);
|
||||
CPString _HTTPMethod @accessors(property=HTTPMethod);
|
||||
BOOL _withCredentials @accessors(property=withCredentials);
|
||||
CPString _HTTPBody @accessors(property=HTTPBody);
|
||||
CPString _HTTPMethod @accessors(property=HTTPMethod);
|
||||
BOOL _withCredentials @accessors(property=withCredentials);
|
||||
|
||||
CPDictionary _HTTPHeaderFields @accessors(readonly, getter=allHTTPHeaderFields);
|
||||
CPDictionary _HTTPHeaderFields @accessors(readonly, getter=allHTTPHeaderFields);
|
||||
CPTimeInterval _timeoutInterval @accessors(readonly, getter=timeoutInterval);
|
||||
CPURLRequestCachePolicy _cachePolicy @accessors(readonly, getter=cachePolicy);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -55,6 +63,18 @@
|
||||
return [[CPURLRequest alloc] initWithURL:aURL];
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a request with a specified URL, cachePolicy and timeoutInterval
|
||||
@param aURL the URL of the request
|
||||
@param aCachePolicy the cache policy of the request
|
||||
@param aTimeoutInterval the timeoutInterval of the request
|
||||
@return a CPURLRequest
|
||||
*/
|
||||
+ (id)requestWithURL:(CPURL)anURL cachePolicy:(CPURLRequestCachePolicy)aCachePolicy timeoutInterval:(CPTimeInterval)aTimeoutInterval
|
||||
{
|
||||
return [[CPURLRequest alloc] initWithURL:anURL cachePolicy:aCachePolicy timeoutInterval:aTimeoutInterval];
|
||||
}
|
||||
|
||||
/*!
|
||||
Equal to `[receiver initWithURL:nil]`.
|
||||
*/
|
||||
@@ -63,6 +83,25 @@
|
||||
return [self initWithURL:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Initializes the request with a URL. This is the designated initializer.
|
||||
|
||||
@param aURL the url to set
|
||||
@param aCachePolicy the cache policy of the request
|
||||
@param aTimeoutInterval the timeoutInterval of the request
|
||||
@return the initialized CPURLRequest
|
||||
*/
|
||||
- (id)initWithURL:(CPURL)anURL cachePolicy:(CPURLRequestCachePolicy)aCachePolicy timeoutInterval:(CPTimeInterval)aTimeoutInterval
|
||||
{
|
||||
if (self = [self initWithURL:anURL])
|
||||
{
|
||||
_cachePolicy = aCachePolicy;
|
||||
_timeoutInterval = aTimeoutInterval;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
Initializes the request with a URL. This is the designated initializer.
|
||||
|
||||
@@ -71,9 +110,7 @@
|
||||
*/
|
||||
- (id)initWithURL:(CPURL)aURL
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
if (self = [super init])
|
||||
{
|
||||
[self setURL:aURL];
|
||||
|
||||
@@ -81,9 +118,34 @@
|
||||
_HTTPMethod = @"GET";
|
||||
_HTTPHeaderFields = @{};
|
||||
_withCredentials = NO;
|
||||
_timeoutInterval = 60.0;
|
||||
_cachePolicy = CPURLRequestUseProtocolCachePolicy;
|
||||
|
||||
[self setValue:"Thu, 01 Jan 1970 00:00:00 GMT" forHTTPHeaderField:"If-Modified-Since"];
|
||||
[self setValue:"no-cache" forHTTPHeaderField:"Cache-Control"];
|
||||
|
||||
switch (_cachePolicy)
|
||||
{
|
||||
case CPURLRequestUseProtocolCachePolicy:
|
||||
// TODO: implement everything about cache...
|
||||
[self setValue:"no-cache" forHTTPHeaderField:"Cache-Control"];
|
||||
break;
|
||||
|
||||
case CPURLRequestReturnCacheDataElseLoad:
|
||||
[self setValue:"max-stale=31536000" forHTTPHeaderField:"Cache-Control"];
|
||||
break;
|
||||
|
||||
case CPURLRequestReturnCacheDataDontLoad:
|
||||
[self setValue:"only-if-cached" forHTTPHeaderField:"Cache-Control"];
|
||||
break;
|
||||
|
||||
case CPURLRequestReloadIgnoringLocalCacheData:
|
||||
[self setValue:"no-cache" forHTTPHeaderField:"Cache-Control"];
|
||||
break;
|
||||
|
||||
default:
|
||||
[self setValue:"no-cache" forHTTPHeaderField:"Cache-Control"];
|
||||
}
|
||||
|
||||
[self setValue:"XMLHttpRequest" forHTTPHeaderField:"X-Requested-With"];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* CPUserNotification.j
|
||||
* Foundation
|
||||
*
|
||||
* Created by Alexandre Wilhelm.
|
||||
* Copyright 2015, 280 North, Inc.
|
||||
*
|
||||
* 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 "CPAttributedString.j"
|
||||
@import "CPArray.j"
|
||||
@import "CPDate.j"
|
||||
@import "CPDictionary.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPTimeZone.j"
|
||||
|
||||
// We need something from the AppKit in Foundation ???
|
||||
@class CPImage
|
||||
|
||||
@typedef CPUserNotificationAction
|
||||
@typedef CPUserNotificationActivationType
|
||||
|
||||
/*!
|
||||
@global CPUserNotificationActivationType
|
||||
@group CPUserNotificationActivationType
|
||||
The user did not interact with the notification alert.
|
||||
*/
|
||||
CPUserNotificationActivationTypeNone = 0;
|
||||
|
||||
/*!
|
||||
@global CPUserNotificationActivationType
|
||||
@group CPUserNotificationActivationType
|
||||
The user clicked on the contents of the notification alert.
|
||||
*/
|
||||
CPUserNotificationActivationTypeContentsClicked = 1;
|
||||
|
||||
/*!
|
||||
@global CPUserNotificationActivationType
|
||||
@group CPUserNotificationActivationType
|
||||
The user clicked on the action button of the notification alert.
|
||||
*/
|
||||
CPUserNotificationActivationTypeActionButtonClicked = 2;
|
||||
|
||||
/*!
|
||||
@global CPUserNotificationActivationType
|
||||
@group CPUserNotificationActivationType
|
||||
The user replied to the notification.
|
||||
*/
|
||||
CPUserNotificationActivationTypeReplied = 3,
|
||||
|
||||
/*!
|
||||
@global CPUserNotificationActivationType
|
||||
@group CPUserNotificationActivationType
|
||||
The user clicked on the additional action button of the notification alert.
|
||||
*/
|
||||
CPUserNotificationActivationTypeAdditionalActionClicked = 4;
|
||||
|
||||
/*!
|
||||
@class CPUserNotification
|
||||
@ingroup foundation
|
||||
|
||||
@brief The CPUserNotification class is used to configure a notification that is scheduled for display by the UserNotificationCenter class.
|
||||
*/
|
||||
@implementation CPUserNotification : CPObject
|
||||
{
|
||||
BOOL _presented @accessors(getter=isPresented);
|
||||
BOOL _remote @accessors(getter=isRemote);
|
||||
CPDate _actualDeliveryDate @accessors(getter=actualDeliveryDate);
|
||||
CPDate _deliveryDate @accessors(property=deliveryDate);
|
||||
CPDictionary _userInfo @accessors(property=userInfo);
|
||||
CPImage _contentImage @accessors(property=contentImage);
|
||||
CPString _identifier @accessors(property=identifier);
|
||||
CPString _informativeText @accessors(property=informativeText);
|
||||
CPString _title @accessors(property=title);
|
||||
CPTimeInterval _deliveryRepeatInterval @accessors(property=deliveryRepeatInterval);
|
||||
CPTimeZone _deliveryTimeZone @accessors(property=deliveryTimeZone);
|
||||
CPUserNotificationActivationType _activationType @accessors(getter=activationType);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Creating an user notification
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_identifier = [self UID];
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* CPUserNotificationCenter.j
|
||||
* Foundation
|
||||
*
|
||||
* Created by Alexandre Wilhelm.
|
||||
* Copyright 2015, 280 North, Inc.
|
||||
*
|
||||
* 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 "CPArray.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPTimer.j"
|
||||
@import "CPUserNotification.j"
|
||||
|
||||
@protocol CPUserNotificationCenterDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)userNotificationCenter:(CPUserNotificationCenter)center shouldPresentNotification:(CPUserNotification)notification;
|
||||
- (void)userNotificationCenter:(CPUserNotificationCenter)center didDeliverNotification:(CPUserNotification)notification;
|
||||
- (void)userNotificationCenter:(CPUserNotificationCenter)center didActivateNotification:(CPUserNotification)notification;
|
||||
|
||||
@end
|
||||
|
||||
// Remove compiling warnings
|
||||
@class Notification
|
||||
|
||||
@global CPApp
|
||||
|
||||
var CPUserNotificationCenterDelegate_userNotificationCenter_shouldPresentNotification_ = 1 << 0,
|
||||
CPUserNotificationCenterDelegate_userNotificationCenter_didDeliverNotification_ = 1 << 1,
|
||||
CPUserNotificationCenterDelegate_userNotificationCenter_didActivateNotification_ = 1 << 2;
|
||||
|
||||
var CPUserNotificationDefaultCenter = nil;
|
||||
|
||||
/*!
|
||||
@class CPUserNotificationCenter
|
||||
@ingroup foundation
|
||||
|
||||
@brief The CPUserNotificationCenter class delivers user notifications to the user from applications or helper applications.
|
||||
*/
|
||||
@implementation CPUserNotificationCenter : CPObject
|
||||
{
|
||||
CPArray _deliveredNotifications @accessors(property=deliveredNotifications);
|
||||
CPArray _scheduledNotifications @accessors(property=scheduledNotifications);
|
||||
id <CPUserNotificationCenterDelegate> _delegate;
|
||||
|
||||
CPInteger _implementedDelegateMethods;
|
||||
CPMutableDictionary _timersForUserNotification;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Creating Default User Notification Center
|
||||
|
||||
/*!
|
||||
Returns the user's notification center
|
||||
*/
|
||||
+ (CPNotificationCenter)defaultUserNotificationCenter
|
||||
{
|
||||
if (!CPUserNotificationDefaultCenter)
|
||||
CPUserNotificationDefaultCenter = [[CPUserNotificationCenter alloc] init];
|
||||
|
||||
return CPUserNotificationDefaultCenter;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_deliveredNotifications = [];
|
||||
_scheduledNotifications = [];
|
||||
_timersForUserNotification = @{};
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Getting and Setting the Delegate
|
||||
|
||||
- (void)setDelegate:(id <CPUserNotificationCenterDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(userNotificationCenter:shouldPresentNotification:)])
|
||||
_implementedDelegateMethods |= CPUserNotificationCenterDelegate_userNotificationCenter_shouldPresentNotification_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(userNotificationCenter:didDeliverNotification:)])
|
||||
_implementedDelegateMethods |= CPUserNotificationCenterDelegate_userNotificationCenter_didDeliverNotification_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(userNotificationCenter:didActivateNotification:)])
|
||||
_implementedDelegateMethods |= CPUserNotificationCenterDelegate_userNotificationCenter_didActivateNotification_;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Managing the Scheduled Notification Queue
|
||||
|
||||
/*!
|
||||
Schedules the given user notification
|
||||
@param anUserNotification the user notification
|
||||
*/
|
||||
- (void)scheduleNotification:(CPUserNotification)anUserNotification
|
||||
{
|
||||
var scheduledDate = [[anUserNotification deliveryDate] copy];
|
||||
[scheduledDate _dateWithTimeZone:[anUserNotification deliveryTimeZone]];
|
||||
|
||||
var timer = [[CPTimer alloc] initWithFireDate:scheduledDate
|
||||
interval:[anUserNotification deliveryRepeatInterval]
|
||||
target:self
|
||||
selector:@selector(_scheduledUserNotificationTimerDidFire:)
|
||||
userInfo:anUserNotification
|
||||
repeats:([anUserNotification deliveryRepeatInterval] ? YES : NO)];
|
||||
|
||||
[_scheduledNotifications addObject:anUserNotification];
|
||||
_timersForUserNotification[[anUserNotification UID]] = timer;
|
||||
|
||||
[[CPRunLoop currentRunLoop] addTimer:timer forMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
- (void)_scheduledUserNotificationTimerDidFire:(CPTimer)aTimer
|
||||
{
|
||||
[self deliverNotification:[aTimer userInfo]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes the given user notification for the scheduled notifications.
|
||||
@param anUserNotification the user notification
|
||||
*/
|
||||
- (void)removeScheduledNotification:(CPUserNotification)anUserNotification
|
||||
{
|
||||
if ([_scheduledNotifications indexOfObject:anUserNotification] != CPNotFound)
|
||||
{
|
||||
[_scheduledNotifications removeObject:anUserNotification];
|
||||
[_timersForUserNotification[[anUserNotification UID]] invalidate];
|
||||
delete _timersForUserNotification[[anUserNotification UID]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Managing the Delivered Notifications
|
||||
|
||||
/*!
|
||||
Deliver the given user notification
|
||||
@param aNotification the user notification
|
||||
*/
|
||||
- (void)deliverNotification:(CPUserNotification)aNotification
|
||||
{
|
||||
[self _launchUserNotification:aNotification];
|
||||
}
|
||||
|
||||
/*!
|
||||
Remove a delivered user notification from the user notification center.
|
||||
@param aNotification the user notification
|
||||
*/
|
||||
- (void)removeDeliveredNotification:(CPUserNotification)aNotification
|
||||
{
|
||||
[_deliveredNotifications removeObject:aNotification];
|
||||
}
|
||||
|
||||
/*!
|
||||
Remove all delivered user notifications from the user notification center.
|
||||
*/
|
||||
- (void)removeAllDeliveredNotifications
|
||||
{
|
||||
[_deliveredNotifications removeAllObjects];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Permission Utilities
|
||||
|
||||
- (void)_askPermissionForUserNotification:(CPUserNotification)anUserNotification
|
||||
{
|
||||
Notification.requestPermission(function (permission) {
|
||||
if (permission == "granted")
|
||||
// We need to relaunch the notification if the permission are granted
|
||||
[self _launchUserNotification:anUserNotification];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Notification Utilities
|
||||
|
||||
- (void)_launchUserNotification:(CPUserNotification)anUserNotification
|
||||
{
|
||||
// If the browser version is unsupported, remain silent.
|
||||
if (!window || !'Notification' in window)
|
||||
return;
|
||||
|
||||
if (Notification.permission === 'default')
|
||||
[self _askPermissionForUserNotification:anUserNotification];
|
||||
|
||||
if (Notification.permission === 'granted')
|
||||
{
|
||||
if (([self _delegateRespondsToShouldPresentNotification] && [self _sendDelegateShouldPresentNotification:anUserNotification])
|
||||
|| ![CPApp isActive])
|
||||
{
|
||||
var notification = new Notification(
|
||||
[anUserNotification title],
|
||||
{
|
||||
'body': [anUserNotification informativeText],
|
||||
'icon': [[anUserNotification contentImage] filename],
|
||||
// ...prevent duplicate notifications
|
||||
'tag' : [anUserNotification identifier]
|
||||
}
|
||||
);
|
||||
|
||||
anUserNotification._presented = YES;
|
||||
|
||||
notification.onclick = function () {
|
||||
anUserNotification._activationType = CPUserNotificationActivationTypeContentsClicked;
|
||||
[self _sendDelegateDidActivateNotification:anUserNotification];
|
||||
|
||||
// Remove the notification from Notification Center when clicked.
|
||||
this.close();
|
||||
};
|
||||
|
||||
// Callback function when the notification is closed.
|
||||
notification.onclose = function () {
|
||||
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
anUserNotification._presented = NO;
|
||||
}
|
||||
|
||||
anUserNotification._activationType = CPUserNotificationActivationTypeNone;
|
||||
anUserNotification._actualDeliveryDate = [CPDate date];
|
||||
[_deliveredNotifications addObject:anUserNotification];
|
||||
|
||||
if (![anUserNotification deliveryRepeatInterval])
|
||||
[self removeScheduledNotification:anUserNotification];
|
||||
|
||||
[self _sendDelegateDidDeliverNotification:anUserNotification];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPUserNotificationCenter (CPUserNotificationCenterDelegate)
|
||||
|
||||
- (BOOL)_delegateRespondsToShouldPresentNotification
|
||||
{
|
||||
return _implementedDelegateMethods & CPUserNotificationCenterDelegate_userNotificationCenter_shouldPresentNotification_;
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateShouldPresentNotification:(CPUserNotification)aNotification
|
||||
{
|
||||
return [_delegate userNotificationCenter:self shouldPresentNotification:aNotification];
|
||||
}
|
||||
|
||||
- (void)_sendDelegateDidActivateNotification:(CPUserNotification)aNotification
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPUserNotificationCenterDelegate_userNotificationCenter_didActivateNotification_))
|
||||
return;
|
||||
|
||||
[_delegate userNotificationCenter:self didActivateNotification:aNotification];
|
||||
}
|
||||
|
||||
- (void)_sendDelegateDidDeliverNotification:(CPUserNotification)aNotification
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPUserNotificationCenterDelegate_userNotificationCenter_didDeliverNotification_))
|
||||
return;
|
||||
|
||||
[_delegate userNotificationCenter:self didDeliverNotification:aNotification];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -78,6 +78,8 @@
|
||||
@import "CPURLRequest.j"
|
||||
@import "CPURLResponse.j"
|
||||
@import "CPUserDefaults.j"
|
||||
@import "CPUserNotification.j"
|
||||
@import "CPUserNotificationCenter.j"
|
||||
@import "CPUserSessionManager.j"
|
||||
@import "CPValue.j"
|
||||
@import "CPValueTransformer.j"
|
||||
|
||||
@@ -128,12 +128,21 @@ function generateDocs(/* boolean */ noFrame)
|
||||
// If the Doxygen application is installed on Mac OS X, use that
|
||||
if (!doxygen && executableExists("mdfind"))
|
||||
{
|
||||
var p = OS.popen(["mdfind", "kMDItemContentType == 'com.apple.application-bundle' && kMDItemCFBundleIdentifier == 'org.doxygen'"]);
|
||||
if (p.wait() === 0)
|
||||
try
|
||||
{
|
||||
var doxygenApps = p.stdout.read().split("\n");
|
||||
if (doxygenApps[0])
|
||||
doxygen = FILE.join(doxygenApps[0], "Contents/Resources/doxygen");
|
||||
var p = OS.popen(["mdfind", "kMDItemContentType == 'com.apple.application-bundle' && kMDItemCFBundleIdentifier == 'org.doxygen'"]);
|
||||
if (p.wait() === 0)
|
||||
{
|
||||
var doxygenApps = p.stdout.read().split("\n");
|
||||
if (doxygenApps[0])
|
||||
doxygen = FILE.join(doxygenApps[0], "Contents/Resources/doxygen");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
p.stdin.close();
|
||||
p.stdout.close();
|
||||
p.stderr.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,13 @@ GLOBAL(CFHTTPRequest) = function()
|
||||
determineAndDispatchHTTPRequestEvents(self);
|
||||
};
|
||||
|
||||
this._timeoutHandler = function()
|
||||
{
|
||||
dispatchTimeoutHTTPRequestEvents(self);
|
||||
};
|
||||
|
||||
this._nativeRequest.onreadystatechange = this._stateChangeHandler;
|
||||
this._nativeRequest.ontimeout = this._timeoutHandler;
|
||||
|
||||
if (CFHTTPRequest.AuthenticationDelegate !== nil)
|
||||
this._eventDispatcher.addEventListener("HTTP403", function()
|
||||
@@ -209,6 +215,16 @@ CFHTTPRequest.prototype.getResponseHeader = function(/*String*/ aHeader)
|
||||
return this._nativeRequest.getResponseHeader(aHeader);
|
||||
};
|
||||
|
||||
CFHTTPRequest.prototype.setTimeout = function(/*int*/ aTimeout)
|
||||
{
|
||||
this._nativeRequest.timeout = aTimeout;
|
||||
};
|
||||
|
||||
CFHTTPRequest.prototype.getTimeout = function(/*int*/ aTimeout)
|
||||
{
|
||||
return this._nativeRequest.timeout;
|
||||
};
|
||||
|
||||
CFHTTPRequest.prototype.getAllResponseHeaders = function()
|
||||
{
|
||||
return this._nativeRequest.getAllResponseHeaders();
|
||||
@@ -235,7 +251,10 @@ CFHTTPRequest.prototype.send = function(/*Object*/ aBody)
|
||||
if (!this._isOpen)
|
||||
{
|
||||
delete this._nativeRequest.onreadystatechange;
|
||||
delete this._nativeRequest.ontimeout;
|
||||
|
||||
this._nativeRequest.open(this._method, this._URL, this._async, this._user, this._password);
|
||||
this._nativeRequest.ontimeout = this._timeoutHandler;
|
||||
this._nativeRequest.onreadystatechange = this._stateChangeHandler;
|
||||
}
|
||||
|
||||
@@ -277,25 +296,35 @@ CFHTTPRequest.prototype.removeEventListener = function(/*String*/ anEventName, /
|
||||
this._eventDispatcher.removeEventListener(anEventName, anEventListener);
|
||||
};
|
||||
|
||||
CFHTTPRequest.prototype.setWithCredentials = function(/*Boolean*/ willSendWithCredentials)
|
||||
CFHTTPRequest.prototype.setWithCredentials = function(/*Boolean*/ willSendWithCredentials)
|
||||
{
|
||||
this._nativeRequest.withCredentials = willSendWithCredentials;
|
||||
};
|
||||
|
||||
CFHTTPRequest.prototype.withCredentials = function()
|
||||
CFHTTPRequest.prototype.withCredentials = function()
|
||||
{
|
||||
return this._nativeRequest.withCredentials;
|
||||
};
|
||||
|
||||
CFHTTPRequest.prototype.isTimeoutRequest = function()
|
||||
{
|
||||
// Can we consider that as a timeout ?
|
||||
return !this.success() && !this._nativeRequest.response && !this._nativeRequest.responseText && !this._nativeRequest.responseType && !this._nativeRequest.responseURL && !this._nativeRequest.responseXML;
|
||||
};
|
||||
|
||||
function dispatchTimeoutHTTPRequestEvents(/*CFHTTPRequest*/ aRequest)
|
||||
{
|
||||
aRequest._eventDispatcher.dispatchEvent({ type:"timeout", request:aRequest});
|
||||
}
|
||||
|
||||
function determineAndDispatchHTTPRequestEvents(/*CFHTTPRequest*/ aRequest)
|
||||
{
|
||||
var eventDispatcher = aRequest._eventDispatcher;
|
||||
var eventDispatcher = aRequest._eventDispatcher,
|
||||
nativeRequest = aRequest._nativeRequest,
|
||||
readyStates = ["uninitialized", "loading", "loaded", "interactive", "complete"];
|
||||
|
||||
eventDispatcher.dispatchEvent({ type:"readystatechange", request:aRequest});
|
||||
|
||||
var nativeRequest = aRequest._nativeRequest,
|
||||
readyStates = ["uninitialized", "loading", "loaded", "interactive", "complete"];
|
||||
|
||||
if (readyStates[aRequest.readyState()] === "complete")
|
||||
{
|
||||
var status = "HTTP" + aRequest.status();
|
||||
@@ -323,12 +352,21 @@ function FileRequest(/*CFURL*/ aURL, onsuccess, onfailure, onprogress)
|
||||
var aFilePath = aURL.toString().substring(5),
|
||||
OS = require("os"),
|
||||
gccFlags = require("objective-j").currentCompilerFlags(),
|
||||
gcc = OS.popen("gcc -E -x c -P " + (gccFlags ? gccFlags : "") + " " + OS.enquote(aFilePath), { charset:"UTF-8" }),
|
||||
chunk,
|
||||
fileContents = "";
|
||||
|
||||
while (chunk = gcc.stdout.read())
|
||||
fileContents += chunk;
|
||||
try
|
||||
{
|
||||
var gcc = OS.popen("gcc -E -x c -P " + (gccFlags ? gccFlags : "") + " " + OS.enquote(aFilePath), { charset:"UTF-8" });
|
||||
while (chunk = gcc.stdout.read())
|
||||
fileContents += chunk;
|
||||
}
|
||||
finally
|
||||
{
|
||||
gcc.stdin.close();
|
||||
gcc.stdout.close();
|
||||
gcc.stderr.close();
|
||||
}
|
||||
|
||||
if (fileContents.length > 0)
|
||||
{
|
||||
|
||||
@@ -94,6 +94,7 @@ exports.run = function(args)
|
||||
print(" -I, --objj-include-paths include a specific framework paths")
|
||||
print(" -h, --help print this help");
|
||||
print(" -m, --multifiles launch objj on several files")
|
||||
print(" -x, --xml specify the output format in xml.")
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -101,45 +102,57 @@ exports.run = function(args)
|
||||
{
|
||||
switch (argv[0])
|
||||
{
|
||||
case "--objj-include-paths":
|
||||
case "-I":
|
||||
argv.shift();
|
||||
OBJJ_INCLUDE_PATHS.unshift.apply(OBJJ_INCLUDE_PATHS, argv.shift().split(":"));
|
||||
break;
|
||||
|
||||
case "--multifiles":
|
||||
case "-m":
|
||||
argv.shift();
|
||||
multipleFiles = true;
|
||||
break
|
||||
|
||||
case "-x":
|
||||
case "--xml":
|
||||
argv.shift();
|
||||
exports.outputFormatInXML = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argv && argv.length > 0)
|
||||
{
|
||||
var endCommand = false;
|
||||
var endCommand = false,
|
||||
errors = [];
|
||||
|
||||
while (argv.length > 0)
|
||||
{
|
||||
var arg0 = argv.shift();
|
||||
var mainFilePath = FILE.canonical(arg0);
|
||||
var arg0 = argv.shift(),
|
||||
mainFilePath = FILE.canonical(arg0);
|
||||
|
||||
if (multipleFiles)
|
||||
{
|
||||
// This is needed to process every files passed in args
|
||||
// Otherwise it would stop when an error is raised or we would like to objj the other given files
|
||||
try
|
||||
{
|
||||
exports.make_narwhal_factory(mainFilePath)(require, { }, module, system, print);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
print("\n" + e);
|
||||
}
|
||||
}
|
||||
else
|
||||
try
|
||||
{
|
||||
exports.make_narwhal_factory(mainFilePath)(require, { }, module, system, print);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
if (exports.outputFormatInXML)
|
||||
{
|
||||
var dict = new CFMutableDictionary();
|
||||
dict.addValueForKey('line', e.line ? e.line : 0);
|
||||
dict.addValueForKey('sourcePath', e.path ? e.path : mainFilePath);
|
||||
dict.addValueForKey('message', e.message);
|
||||
|
||||
errors.push(dict);
|
||||
}
|
||||
else
|
||||
{
|
||||
errors.push("\n" + e);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof main === "function")
|
||||
{
|
||||
@@ -157,6 +170,14 @@ exports.run = function(args)
|
||||
ObjectiveJ.FileExecutable.resetFileExecutables();
|
||||
objj_resetRegisterClasses();
|
||||
}
|
||||
|
||||
if (errors.length)
|
||||
{
|
||||
if (exports.outputFormatInXML)
|
||||
throw CFPropertyListCreateXMLData(errors, kCFPropertyListXMLFormat_v1_0).rawString();
|
||||
else
|
||||
throw errors;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -229,6 +250,7 @@ function getPackage() {
|
||||
exports.version = function() { return getPackage()["version"]; }
|
||||
exports.revision = function() { return getPackage()["cappuccino-revision"]; }
|
||||
exports.timestamp = function() { return new Date(getPackage()["cappuccino-timestamp"]); }
|
||||
exports.outputFormatInXML = false;
|
||||
|
||||
exports.fullVersionString = function() {
|
||||
return sprintf("objective-j %s (%04d-%02d-%02d %s)",
|
||||
|
||||
@@ -46,18 +46,39 @@ function compileWithResolvedFlags(aFilePath, objjcFlags, gccFlags, asPlainJavasc
|
||||
|
||||
if (!shouldObjjPreprocess)
|
||||
{
|
||||
if (OS.popen("which gcc").stdout.read().length === 0)
|
||||
fileContents = FILE.read(aFilePath, { charset:"UTF-8" });
|
||||
else
|
||||
try
|
||||
{
|
||||
// GCC preprocess the file.
|
||||
var gcc = OS.popen("gcc -E -x c -P " + (gccFlags ? gccFlags.join(" ") : "") + " " + OS.enquote(aFilePath), { charset:"UTF-8" }),
|
||||
chunk = "";
|
||||
var p = OS.popen("which gcc");
|
||||
|
||||
while (chunk = gcc.stdout.read())
|
||||
fileContents += chunk;
|
||||
if (p.stdout.read().length === 0)
|
||||
{
|
||||
fileContents = FILE.read(aFilePath, { charset:"UTF-8" });
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var gcc = OS.popen("gcc -E -x c -P " + (gccFlags ? gccFlags.join(" ") : "") + " " + OS.enquote(aFilePath), { charset:"UTF-8" }),
|
||||
chunk = "";
|
||||
|
||||
while (chunk = gcc.stdout.read())
|
||||
fileContents += chunk;
|
||||
}
|
||||
finally
|
||||
{
|
||||
gcc.stdin.close();
|
||||
gcc.stdout.close();
|
||||
gcc.stderr.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
p.stdin.close();
|
||||
p.stdout.close();
|
||||
p.stderr.close();
|
||||
}
|
||||
|
||||
return fileContents;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
var FILE = require("file");
|
||||
|
||||
|
||||
var BUNDLE_TASK = require("objective-j/jake/bundletask");
|
||||
|
||||
exports.BundleTask = BUNDLE_TASK.BundleTask;
|
||||
|
||||
+15
-6
@@ -40,8 +40,8 @@ $BROWSER_FILES = new FileList($BROWSER_FILE).include($OBJECTIVEJ_FILES);
|
||||
|
||||
filedir($BUILD_BROWSER_FILE, $BROWSER_FILES, function(aTask)
|
||||
{
|
||||
gcc($BROWSER_FILE,
|
||||
$BUILD_BROWSER_FILE,
|
||||
gcc($BROWSER_FILE,
|
||||
$BUILD_BROWSER_FILE,
|
||||
environmentFlags("Browser", "ObjJ").concat($INCLUDE_FLAGS, $DEBUG_FLAGS), $CONFIGURATION !== "Debug");
|
||||
});
|
||||
|
||||
@@ -119,11 +119,20 @@ function gcc(inputFilePath, outputFilePath, flags, compress)
|
||||
stream.print("Building... \0green(" + outputFilePath +"\0)");
|
||||
|
||||
// GCC preprocess the file.
|
||||
var cmd = ["gcc", "-E", "-x", "c", "-P"].concat(flags, inputFilePath).join(" ");
|
||||
var gcc = OS.popen(cmd, { charset:"UTF-8" });
|
||||
var cmd = ["gcc", "-E", "-x", "c", "-P"].concat(flags, inputFilePath).join(" "),
|
||||
contents = FILE.read("header.txt", { charset : "UTF-8" });
|
||||
|
||||
var contents = FILE.read("header.txt", { charset : "UTF-8" });
|
||||
contents += gcc.stdout.read();
|
||||
try
|
||||
{
|
||||
var gcc = OS.popen(cmd, { charset:"UTF-8" });
|
||||
contents += gcc.stdout.read();
|
||||
}
|
||||
finally
|
||||
{
|
||||
gcc.stdin.close();
|
||||
gcc.stdout.close();
|
||||
gcc.stderr.close();
|
||||
}
|
||||
|
||||
if (FILE.extension(inputFilePath) === ".js" && compress)
|
||||
contents = compressor(contents);
|
||||
|
||||
@@ -394,9 +394,22 @@ var ObjJAcornCompiler = function(/*String*/ aString, /*CFURL*/ aURL, /*unsigned*
|
||||
#ifdef BROWSER
|
||||
console.log(message);
|
||||
#else
|
||||
print(message);
|
||||
if (exports.outputFormatInXML)
|
||||
{
|
||||
var dict = new CFMutableDictionary();
|
||||
dict.addValueForKey('line', e.line);
|
||||
dict.addValueForKey('sourcePath', this.URL.path());
|
||||
dict.addValueForKey('message', message);
|
||||
|
||||
print(CFPropertyListCreateXMLData([dict], kCFPropertyListXMLFormat_v1_0).rawString());
|
||||
}
|
||||
else
|
||||
{
|
||||
print(message);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -434,6 +447,8 @@ exports.ObjJAcornCompiler.compileFileDependencies = function(/*String*/ aString,
|
||||
|
||||
ObjJAcornCompiler.prototype.compilePass2 = function()
|
||||
{
|
||||
var warnings = [];
|
||||
|
||||
ObjJAcornCompiler.currentCompileFile = this.URL;
|
||||
this.pass = 2;
|
||||
this.jsBuffer = new StringBuffer();
|
||||
@@ -442,14 +457,32 @@ ObjJAcornCompiler.prototype.compilePass2 = function()
|
||||
compile(this.tokens, new Scope(null ,{ compiler: this }), pass2);
|
||||
for (var i = 0; i < this.warnings.length; i++)
|
||||
{
|
||||
var message = this.prettifyMessage(this.warnings[i], "WARNING");
|
||||
var warning = this.warnings[i],
|
||||
type = "WARNING";
|
||||
|
||||
var message = this.prettifyMessage(warning, type);
|
||||
#ifdef BROWSER
|
||||
console.log(message);
|
||||
#else
|
||||
print(message);
|
||||
if (exports.outputFormatInXML)
|
||||
{
|
||||
var dict = new CFMutableDictionary();
|
||||
dict.addValueForKey('line', warning.line)
|
||||
dict.addValueForKey('sourcePath', this.URL.path())
|
||||
dict.addValueForKey('message', message)
|
||||
|
||||
warnings.push(dict);
|
||||
}
|
||||
else
|
||||
{
|
||||
print(message);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (warnings.length && exports.outputFormatInXML)
|
||||
print(CFPropertyListCreateXMLData(warnings, kCFPropertyListXMLFormat_v1_0).rawString());
|
||||
|
||||
//print(this.URL + ": " + this.jsBuffer.toString());
|
||||
return this.jsBuffer.toString();
|
||||
}
|
||||
@@ -660,9 +693,13 @@ ObjJAcornCompiler.prototype.prettifyMessage = function(/* Message */ aMessage, /
|
||||
ObjJAcornCompiler.prototype.error_message = function(errorMessage, node)
|
||||
{
|
||||
var pos = exports.acorn.getLineInfo(this.source, node.start),
|
||||
syntaxError = {message: errorMessage, line: pos.line, column: pos.column, lineStart: pos.lineStart, lineEnd: pos.lineEnd};
|
||||
syntaxErrorData = {message: errorMessage, line: pos.line, column: pos.column, lineStart: pos.lineStart, lineEnd: pos.lineEnd},
|
||||
syntaxError = new SyntaxError(this.prettifyMessage(syntaxErrorData, "ERROR"));
|
||||
|
||||
return new SyntaxError(this.prettifyMessage(syntaxError, "ERROR"));
|
||||
syntaxError.line = pos.line;
|
||||
syntaxError.path = this.URL.path();
|
||||
|
||||
return syntaxError;
|
||||
}
|
||||
|
||||
ObjJAcornCompiler.prototype.pushImport = function(url)
|
||||
|
||||
+4
-2
@@ -1,3 +1,5 @@
|
||||
[](https://travis-ci.org/cappuccino/cappuccino)
|
||||
|
||||
Welcome to Cappuccino!
|
||||
======================
|
||||
|
||||
@@ -33,7 +35,7 @@ Getting Started
|
||||
---------------
|
||||
To get started, download and install the current release version of Cappuccino:
|
||||
|
||||
$ curl https://raw.githubusercontent.com/cappuccino/cappuccino/v0.9.7-1/bootstrap.sh >/tmp/cappuccino_bootstrap.sh && bash /tmp/cappuccino_bootstrap.sh
|
||||
$ curl https://raw.githubusercontent.com/cappuccino/cappuccino/v0.9.8/bootstrap.sh >/tmp/cappuccino_bootstrap.sh && bash /tmp/cappuccino_bootstrap.sh
|
||||
|
||||
If you'd just like to get started using Cappuccino for your web apps, you are done.
|
||||
|
||||
@@ -71,7 +73,7 @@ If you need help with Cappuccino, you can get help from the following sources:
|
||||
- Mailing Lists:
|
||||
- [Objective-J](http://groups.google.com/group/objectivej)
|
||||
- [Objective-J Developers](http://groups.google.com/group/objectivej-dev)
|
||||
- IRC: irc://irc.freenode.net#cappuccino
|
||||
- [Gitter] (https://gitter.im/cappuccino/cappuccino)
|
||||
|
||||
If you discover any bugs, please file a ticket at:
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
@import <AppKit/CPApplication.j>
|
||||
@import <AppKit/CPAnimation.j>
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
@implementation CPAnimation (TestMethods)
|
||||
{
|
||||
}
|
||||
@@ -18,11 +16,17 @@
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
- (void)testScheduleTimerWithIntervalBasedOnDefaultFrameRate
|
||||
{
|
||||
var animation = [[CPAnimation alloc] initWithDuration:0.1 animationCurve:CPAnimationLinear];
|
||||
[animation startAnimation];
|
||||
|
||||
|
||||
[self assert:1.0/60.0 equals:[[animation timer] timeInterval]];
|
||||
}
|
||||
|
||||
@@ -31,7 +35,7 @@
|
||||
var animation = [[CPAnimation alloc] initWithDuration:0.1 animationCurve:CPAnimationLinear];
|
||||
[animation setFrameRate:30];
|
||||
[animation startAnimation];
|
||||
|
||||
|
||||
[self assert:1.0/30.0 equals:[[animation timer] timeInterval]];
|
||||
}
|
||||
|
||||
@@ -40,7 +44,7 @@
|
||||
var animation = [[CPAnimation alloc] initWithDuration:0.1 animationCurve:CPAnimationLinear];
|
||||
[animation setFrameRate:0];
|
||||
[animation startAnimation];
|
||||
|
||||
|
||||
[self assert:0.0001 equals:[[animation timer] timeInterval]];
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ var globalResults = [];
|
||||
{
|
||||
// This sets up the CPApp convenience variable, the unit tests fails
|
||||
// if this is not done, because the framework internally uses CPApp.
|
||||
app = [CPApplication sharedApplication];
|
||||
app = [[CPApplication alloc] init];
|
||||
|
||||
// fake the window.location.hash
|
||||
window.location = {hash: "#var1=1/var2=2"};
|
||||
|
||||
@@ -6,6 +6,15 @@ var ELEMENTS = 200,
|
||||
REPEATS = 25;
|
||||
|
||||
@implementation CPArrayControllerPerformance : OJTestCase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
- (CPArrayController)setupWithElements:(int)aCount
|
||||
{
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
_contentArray = [self makeTestArray];
|
||||
[self initControllerWithSimpleArray]
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
|
||||
@implementation CPAutosizePerformance : OJTestCase
|
||||
{
|
||||
CPInteger NUMBER_OF_VIEWS;
|
||||
@@ -12,6 +9,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
NUMBER_OF_VIEWS = 50;
|
||||
RESIZES_COUNT = 250;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
@class CPBrowserDelegate
|
||||
|
||||
|
||||
@implementation CPBrowserTest : OJTestCase
|
||||
{
|
||||
CPBrowser browser;
|
||||
@@ -11,6 +10,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
browser = [[CPBrowser alloc] initWithFrame:CGRectMake(0, 0, 500, 300)];
|
||||
delegate = [CPBrowserDelegate new];
|
||||
[delegate setEntries:[".1", ".1.1", ".1.2", ".1.2.1", ".1.2.2", ".2", ".3", ".3.1"]];
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
|
||||
@import <AppKit/CPButton.j>
|
||||
@import <AppKit/CPApplication.j>
|
||||
@import <AppKit/CPText.j>
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
@implementation CPButtonTest : OJTestCase
|
||||
{
|
||||
CPButton button;
|
||||
@@ -13,6 +10,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
button = [CPButton buttonWithTitle:"hello world"];
|
||||
wasClicked = NO;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
@import <AppKit/CPCheckBox.j>
|
||||
|
||||
[CPApplication sharedApplication]
|
||||
|
||||
@implementation CPCheckBoxTest : OJTestCase
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
/*!
|
||||
Verify that CPCheckBox placeholders work, both explicit and default ones.
|
||||
*/
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
_collectionView = [[CPCollectionView alloc] initWithFrame:CGRectMakeZero()];
|
||||
_globalResults = nil;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
- (void)testHexStringConversion
|
||||
{
|
||||
var colors = ['000000', '0099CC', '7E8EAB', 'FFFFFF'];
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
@import <AppKit/CPColorWell.j>
|
||||
@import <AppKit/CPApplication.j>
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
@implementation CPColorWellTest : OJTestCase
|
||||
{
|
||||
CPColorWell colorWell;
|
||||
@@ -10,6 +8,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
colorWell = [[CPColorWell alloc] initWithFrame:CGRectMakeZero()];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
@import "CPNotificationCenterHelper.j"
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
@implementation CPComboBoxTest : OJTestCase
|
||||
{
|
||||
CPComboBox comboBox;
|
||||
@@ -14,6 +12,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
comboBox = [[CPComboBox alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
// set up a dummy DOM element.
|
||||
DOMElement = {
|
||||
style: {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
@import <OJUnit/OJTestCase.j>
|
||||
|
||||
@import <AppKit/CPDatePicker.j>
|
||||
@import <AppKit/CPApplication.j>
|
||||
@import <Foundation/Foundation.j>
|
||||
|
||||
|
||||
@implementation CPDatePickerTest : OJTestCase
|
||||
{
|
||||
CPDatePicker datePicker;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
datePicker = [[CPDatePicker alloc] initWithFrame:CGRectMake(200, 28, 0, 0)];
|
||||
}
|
||||
|
||||
- (void)testCanCreate
|
||||
{
|
||||
[self assertTrue:!!datePicker];
|
||||
}
|
||||
|
||||
- (void)testLayoutSubviews
|
||||
{
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// CPApplication must be initialised for some event handling to work.
|
||||
[CPApplication sharedApplication];
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
anEvent = [CPEvent otherEventWithType:CPApplicationDefined location:CGPointMakeZero() modifierFlags:0 timestamp:500.5 windowNumber:2 context:nil subtype:5 data1:15 data2:25];
|
||||
|
||||
[self assert:@"CPEvent: type=15 loc={0, 0} time=500.5 flags=0x0 win=null winNum=0 ctxt=null subtype=5 data1=15 data2=25" equals:[anEvent description]];
|
||||
[self assert:@"CPEvent: type=15 loc={0, 0} time=500.5 flags=0x0 win=null winNum=2 ctxt=null subtype=5 data1=15 data2=25" equals:[anEvent description]];
|
||||
}
|
||||
|
||||
- (void)testModifierFlags
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
@implementation CPFontManagerTest : OJTestCase
|
||||
{
|
||||
CPFont fontA;
|
||||
@@ -14,6 +12,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
fontA = [CPFont systemFontOfSize:8.0];
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
_systemFont = [CPFont systemFontOfSize:15];
|
||||
_boldSystemFont = [CPFont boldSystemFontOfSize:15];
|
||||
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
- (void)testInitWithContentsOfFile_nil
|
||||
{
|
||||
var image = [[CPImage alloc] initWithContentsOfFile:nil];
|
||||
|
||||
@@ -3,9 +3,16 @@
|
||||
@import <AppKit/CPEvent.j>
|
||||
@import <AppKit/CPButton.j>
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
@implementation CPKeyEquivalentPerformance : OJTestCase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
- (void)testKeyEquivalentSpeed
|
||||
{
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// CPApp must be initialised or action sending will not work.
|
||||
[CPApplication sharedApplication];
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
track = [Track new];
|
||||
[track setVolume:5.0];
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
CPArrayController arrayController @accessors;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
- (void)testExposingBindings
|
||||
{
|
||||
[BindingTester exposeBinding:@"foo"];
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
+ (CPLevelIndicator)indicatorWithLowWarning
|
||||
{
|
||||
var levelIndicator = [[CPLevelIndicator alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||
@@ -44,7 +50,7 @@
|
||||
|
||||
[levelIndicator setObjectValue:4];
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
|
||||
|
||||
[self assert:[CPColor yellowColor] equals:[GET_LEVEL_INDICATOR_SEGMENT(levelIndicator, 0) backgroundColor]];
|
||||
}
|
||||
|
||||
@@ -54,7 +60,7 @@
|
||||
|
||||
[levelIndicator setObjectValue:2];
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
|
||||
|
||||
[self assert:[CPColor redColor] equals:[GET_LEVEL_INDICATOR_SEGMENT(levelIndicator, 0) backgroundColor]];
|
||||
}
|
||||
|
||||
@@ -74,7 +80,7 @@
|
||||
|
||||
[levelIndicator setObjectValue:6];
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
|
||||
|
||||
[self assert:[CPColor yellowColor] equals:[GET_LEVEL_INDICATOR_SEGMENT(levelIndicator, 0) backgroundColor]];
|
||||
}
|
||||
|
||||
@@ -84,7 +90,7 @@
|
||||
|
||||
[levelIndicator setObjectValue:8];
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
|
||||
|
||||
[self assert:[CPColor redColor] equals:[GET_LEVEL_INDICATOR_SEGMENT(levelIndicator, 0) backgroundColor]];
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
|
||||
@import <AppKit/CPMenu.j>
|
||||
@import <AppKit/CPMenuItem.j>
|
||||
@import <AppKit/CPApplication.j>
|
||||
@import <AppKit/CPText.j>
|
||||
|
||||
[CPApplication sharedApplication]
|
||||
|
||||
@implementation CPMenuTest : OJTestCase
|
||||
{
|
||||
@@ -21,6 +19,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
// Set up a fairly complete menu to have something to work with.
|
||||
menu = [[CPMenu alloc] initWithTitle:@"MainMenu"];
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ var CPMenuValidatedUserInterfaceItemTestValidatedItems = [];
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
_menuTarget = [[MenuTarget alloc] init];
|
||||
[[CPApplication sharedApplication] setDelegate:_menuTarget];
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
@class TestOutlineDataSource
|
||||
|
||||
|
||||
@implementation CPOutlineViewTest : OJTestCase
|
||||
{
|
||||
CPOutlineView outlineView;
|
||||
@@ -12,6 +11,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
outlineView = [[CPOutlineView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||
|
||||
tableColumn = [[CPTableColumn alloc] initWithIdentifier:@"Foo"];
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
- (void)testSetString_forType_
|
||||
{
|
||||
var pboard = [CPPasteboard generalPasteboard];
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
button = [CPPopUpButton new];
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
_editor = [[CPPredicateEditor alloc] initWithFrame:CGRectMakeZero()];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
@import <AppKit/CPPlatformWindow+DOMKeys.j>
|
||||
|
||||
[CPApplication sharedApplication]
|
||||
|
||||
@implementation CPResponderTest : OJTestCase
|
||||
{
|
||||
CPWindow theWindow;
|
||||
@@ -14,6 +12,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
responder = [TestResponder new];
|
||||
responder.doCommandCalls = [];
|
||||
}
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
|
||||
@import "CPNotificationCenterHelper.j"
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
@implementation CPScrollViewTest : OJTestCase
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
/*!
|
||||
Test that scroll views don't generate bad layouts when very small.
|
||||
*/
|
||||
@@ -229,7 +234,7 @@
|
||||
|
||||
[scrollView setDocumentView:documentView];
|
||||
|
||||
[textField1 setFrameOrigin:CGPointMake(0, 0)];
|
||||
[textField1 setFrameOrigin:CGPointMake(10, 10)];
|
||||
[textField2 setFrameOrigin:CGPointMake(500, 500)];
|
||||
|
||||
[documentView addSubview:textField1];
|
||||
@@ -242,9 +247,11 @@
|
||||
[self assertPoint:CGPointMake(0, 0) equals:visibleRect.origin message:@"VisibleRect origin not at top left corner"];
|
||||
|
||||
// Make the second text field visible
|
||||
[textField2 scrollRectToVisible:[textField2 bounds]];
|
||||
var hasScrolled = [textField2 scrollRectToVisible:[textField2 bounds]];
|
||||
|
||||
var visibleRectOriginShouldBeAt = CGPointMake(500 - originalVisibleSize.width + textField2Size.width, 500 -originalVisibleSize.height + textField2Size.height);
|
||||
[self assertTrue:hasScrolled];
|
||||
|
||||
var visibleRectOriginShouldBeAt = CGPointMake(500 - originalVisibleSize.width + textField2Size.width, 500 - originalVisibleSize.height + textField2Size.height);
|
||||
|
||||
visibleRect = [documentView visibleRect];
|
||||
|
||||
@@ -252,12 +259,66 @@
|
||||
[self assertPoint:visibleRectOriginShouldBeAt equals:visibleRect.origin message:@"Second text field not at lower right corner in visible rect"];
|
||||
|
||||
// Make the first text field visible again
|
||||
[textField1 scrollRectToVisible:[textField2 bounds]];
|
||||
hasScrolled = [textField1 scrollRectToVisible:[textField1 bounds]];
|
||||
[self assertTrue:hasScrolled];
|
||||
|
||||
visibleRect = [documentView visibleRect];
|
||||
|
||||
// We should now be back at top left corner
|
||||
[self assertPoint:CGPointMake(0, 0) equals:visibleRect.origin message:@"VisibleRect origin not at top left corner again"];
|
||||
[self assertPoint:CGPointMake(10, 10) equals:visibleRect.origin message:@"VisibleRect origin not at top left corner again"];
|
||||
|
||||
// Try to scroll again and it should not scroll
|
||||
hasScrolled = [textField1 scrollRectToVisible:[textField1 bounds]];
|
||||
[self assertFalse:hasScrolled];
|
||||
}
|
||||
|
||||
- (void)testScrollRectToVisibleWithLargeRect
|
||||
{
|
||||
var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)],
|
||||
documentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 1000, 1000)],
|
||||
view1 = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)],
|
||||
view2 = [[CPView alloc] initWithFrame:CGRectMake(500, 500, 200, 200)],
|
||||
view1Size = CGSizeMakeCopy([view1 bounds].size),
|
||||
view2Size = CGSizeMakeCopy([view2 bounds].size);
|
||||
|
||||
[scrollView setDocumentView:documentView];
|
||||
|
||||
[view1 setFrameOrigin:CGPointMake(0, 0)];
|
||||
[view2 setFrameOrigin:CGPointMake(500, 500)];
|
||||
|
||||
[documentView addSubview:view1];
|
||||
[documentView addSubview:view2];
|
||||
|
||||
var visibleRect = [documentView visibleRect],
|
||||
originalVisibleSize = CGSizeMakeCopy(visibleRect.size);
|
||||
|
||||
// Make sure we are at the top left corner
|
||||
[self assertPoint:CGPointMake(0, 0) equals:visibleRect.origin message:@"VisibleRect origin not at top left corner"];
|
||||
|
||||
// Make the second view visible
|
||||
var hasScrolled = [view2 scrollRectToVisible:[view2 bounds]];
|
||||
|
||||
[self assertTrue:hasScrolled];
|
||||
|
||||
visibleRect = [documentView visibleRect];
|
||||
|
||||
// We should now have the origin of view2 in the upper left corner
|
||||
[self assertPoint:CGPointMake(500, 500) equals:visibleRect.origin message:@"Origin of second view not at upper left corner in visible rect"];
|
||||
|
||||
// Make the first view visible again
|
||||
hasScrolled = [view1 scrollRectToVisible:[view1 bounds]];
|
||||
[self assertTrue:hasScrolled];
|
||||
|
||||
visibleRect = [documentView visibleRect];
|
||||
|
||||
var visibleRectOriginShouldBeAt = CGPointMake(200 - visibleRect.size.width, 200 - visibleRect.size.height);
|
||||
|
||||
// We should now be back almost at top left corner except that the lower right corner of the rect should be at the lower right corner of the visible rect.
|
||||
[self assertPoint:visibleRectOriginShouldBeAt equals:visibleRect.origin message:@"VisibleRect origin not at top left corner again"];
|
||||
|
||||
// Try to scroll again and it should not scroll even as some parts are outside the visible rect
|
||||
hasScrolled = [view1 scrollRectToVisible:[view1 bounds]];
|
||||
[self assertFalse:hasScrolled];
|
||||
}
|
||||
|
||||
-(void)testNotificationsRegistered
|
||||
@@ -278,11 +339,49 @@
|
||||
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[] message:@"Notications registered for the scrollView in the notification center are wrong"];
|
||||
}
|
||||
|
||||
- (void)testDocumentVisibleRect
|
||||
{
|
||||
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0.0, 0.0, 1024.0, 768.0)
|
||||
styleMask:CPWindowNotSizable],
|
||||
windowView = [theWindow contentView],
|
||||
aScrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)],
|
||||
aDocumentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
|
||||
|
||||
[CPScrollView setGlobalScrollerStyle:CPScrollerStyleOverlay];
|
||||
|
||||
[aScrollView setDocumentView:aDocumentView];
|
||||
[windowView addSubview:aScrollView];
|
||||
|
||||
[self assertRect:CGRectMake(0, 0, 100, 100) equals:[aScrollView documentVisibleRect] message:@"documentVisibleRect is wrong in CPScrollView"];
|
||||
|
||||
[aDocumentView setScaleSize:CGSizeMake(0.5, 0.5)];
|
||||
[self assertRect:CGRectMake(0, 0, 200, 200) equals:[aScrollView documentVisibleRect] message:@"documentVisibleRect is wrong in CPScrollView after scaling"];
|
||||
|
||||
[aDocumentView setScaleSize:CGSizeMake(1, 1)];
|
||||
[aDocumentView scrollRectToVisible:CGRectMake(120, 120, 20, 20)];
|
||||
[self assertRect:CGRectMake(40, 40, 100, 100) equals:[aScrollView documentVisibleRect] message:@"documentVisibleRect is wrong in CPScrollView"];
|
||||
|
||||
[aDocumentView setScaleSize:CGSizeMake(0.5, 0.5)];
|
||||
[self assertRect:CGRectMake(80, 80, 200, 200) equals:[aScrollView documentVisibleRect] message:@"documentVisibleRect is wrong in CPScrollView"];
|
||||
}
|
||||
|
||||
- (void)assertPoint:(CGPoint)expected equals:(CGPoint)actual message:(CPString)message
|
||||
{
|
||||
[self assert:expected.x equals:actual.x message:@"X: " + message];
|
||||
[self assert:expected.y equals:actual.y message:@"Y: " + message];
|
||||
}
|
||||
|
||||
- (void)assertSize:(CGSize)expected equals:(CGSize)actual message:(CPString)message
|
||||
{
|
||||
[self assert:expected.width equals:actual.width message:@"Width: " + message];
|
||||
[self assert:expected.height equals:actual.height message:@"Height: " + message];
|
||||
}
|
||||
|
||||
- (void)assertRect:(CGRect)expected equals:(CGRect)actual message:(CPString)message
|
||||
{
|
||||
[self assertPoint:expected.origin equals:actual.origin message:message]
|
||||
[self assertSize:expected.size equals:actual.size message:message]
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
_searchField = [[CPSearchField alloc] initWithFrame:CGRectMakeZero()];
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
_segmentedControl = [[CPSegmentedControl alloc] initWithFrame:CGRectMakeZero()];
|
||||
[_segmentedControl setSegmentCount:3];
|
||||
}
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
}
|
||||
|
||||
- (void)testIsContinuous
|
||||
{
|
||||
// While normally testing simple instance variables is a waste of time,
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
|
||||
@import <AppKit/CPApplication.j>
|
||||
@import <AppKit/CPSplitView.j>
|
||||
|
||||
[CPApplication sharedApplication];
|
||||
|
||||
@implementation CPSplitViewTest : OJTestCase
|
||||
{
|
||||
CPSplitView splitView;
|
||||
@@ -13,6 +10,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
splitView = [[CPSplitView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||
viewA = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
|
||||
viewB = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
@import <AppKit/CPStepper.j>
|
||||
@import <AppKit/CPApplication.j>
|
||||
|
||||
[CPApplication sharedApplication]
|
||||
|
||||
@implementation CPStepperTest : OJTestCase
|
||||
{
|
||||
CPStepper stepper;
|
||||
@@ -10,6 +8,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
stepper = [CPStepper stepper];
|
||||
[stepper setValueWraps:NO];
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
@import <Foundation/Foundation.j>
|
||||
@import <AppKit/AppKit.j>
|
||||
|
||||
|
||||
|
||||
@implementation CPTabView (TEST)
|
||||
|
||||
- (CPSegmentedControl)tabs
|
||||
@@ -27,6 +25,9 @@
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
// This will init the global var CPApp which are used internally in the AppKit
|
||||
[[CPApplication alloc] init];
|
||||
|
||||
_tabView = [[CPTabView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)];
|
||||
|
||||
_tabItem1 = [[CPTabViewItem alloc] initWithIdentifier:@"id1"];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user