Merge branch 'refs/heads/master' into NEW--CPTextView

This commit is contained in:
Andrew Hankinson
2015-01-14 17:23:50 -05:00
41 changed files with 1098 additions and 341 deletions
-64
View File
@@ -46,75 +46,12 @@
return;
if (_documentView)
{
[self _removeObserverDocumentView:_documentView];
[_documentView removeFromSuperview];
}
_documentView = aView;
if (_documentView)
{
[self addSubview:_documentView];
[self _observeDocumentView];
}
}
- (void)_observeDocumentView
{
var defaultCenter = [CPNotificationCenter defaultCenter];
[_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES];
[defaultCenter
addObserver:self
selector:@selector(viewFrameChanged:)
name:CPViewFrameDidChangeNotification
object:_documentView];
[defaultCenter
addObserver:self
selector:@selector(viewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
object:_documentView];
}
- (void)_removeObserverDocumentView:(CPView)aDocumentView
{
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter
removeObserver:self
name:CPViewFrameDidChangeNotification
object:_documentView];
[defaultCenter
removeObserver:self
name:CPViewBoundsDidChangeNotification
object:_documentView];
}
- (void)_addObservers
{
if (_isObserving)
return;
[super _addObservers];
if (_documentView)
[self _observeDocumentView];
}
- (void)_removeObservers
{
if (!_isObserving)
return;
[super _removeObservers];
if (_documentView)
[self _removeObserverDocumentView:_documentView];
}
/*!
@@ -275,7 +212,6 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView";
// Don't call setDocumentView: here. It calls addSubview:, but it's A) not necessary since the
// view hierarchy is fully encoded and B) dangerous if the subview is not fully decoded.
_documentView = [aCoder decodeObjectForKey:CPClipViewDocumentViewKey];
[self _observeDocumentView];
}
return self;
+106 -65
View File
@@ -53,6 +53,11 @@ CPComboBoxWillPopUpNotification = @"CPComboBoxWillPopUpNotification";
CPComboBoxStateButtonBordered = CPThemeState("button-bordered");
var CPComboBoxDelegate_comboBoxSelectionIsChanging_ = 1 << 0,
CPComboBoxDelegate_comboBoxSelectionDidChange_ = 1 << 1,
CPComboBoxDelegate_comboBoxWillPopUp_ = 1 << 2,
CPComboBoxDelegate_comboBoxWillDismiss_ = 1 << 3;
var CPComboBoxTextSubview = @"text",
CPComboBoxButtonSubview = @"button",
CPComboBoxDefaultNumberOfVisibleItems = 5,
@@ -61,19 +66,20 @@ var CPComboBoxTextSubview = @"text",
@implementation CPComboBox : CPTextField
{
CPArray _items;
_CPPopUpList _listDelegate;
id<CPComboBoxDataSource> _dataSource;
BOOL _usesDataSource;
BOOL _completes;
BOOL _canComplete;
int _numberOfVisibleItems;
BOOL _completes;
BOOL _forceSelection;
BOOL _hasVerticalScroller;
CPString _selectedStringValue;
CGSize _intercellSpacing;
float _itemHeight;
BOOL _popUpButtonCausedResign;
BOOL _usesDataSource;
CGSize _intercellSpacing;
CPArray _items;
id<CPComboBoxDataSource> _dataSource;
CPInteger _implementedDelegateComboBoxMethods;
CPString _selectedStringValue;
float _itemHeight;
int _numberOfVisibleItems;
_CPPopUpList _listDelegate;
}
+ (CPString)defaultThemeClass
@@ -228,41 +234,21 @@ var CPComboBoxTextSubview = @"text",
if (aDelegate === delegate)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (delegate)
{
[defaultCenter removeObserver:delegate name:CPComboBoxSelectionIsChangingNotification object:self];
[defaultCenter removeObserver:delegate name:CPComboBoxSelectionDidChangeNotification object:self];
[defaultCenter removeObserver:delegate name:CPComboBoxWillDismissNotification object:self];
[defaultCenter removeObserver:delegate name:CPComboBoxWillPopUpNotification object:self];
}
_implementedDelegateComboBoxMethods = 0;
if (aDelegate)
{
if ([aDelegate respondsToSelector:@selector(comboBoxSelectionIsChanging:)])
[defaultCenter addObserver:delegate
selector:@selector(comboBoxSelectionIsChanging:)
name:CPComboBoxSelectionIsChangingNotification
object:self];
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionIsChanging_;
if ([aDelegate respondsToSelector:@selector(comboBoxSelectionDidChange:)])
[defaultCenter addObserver:delegate
selector:@selector(comboBoxSelectionDidChange:)
name:CPComboBoxSelectionDidChangeNotification
object:self];
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionDidChange_;
if ([aDelegate respondsToSelector:@selector(comboBoxWillPopUp:)])
[defaultCenter addObserver:delegate
selector:@selector(comboBoxWillPopUp:)
name:CPComboBoxWillPopUpNotification
object:self];
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillPopUp_;
if ([aDelegate respondsToSelector:@selector(comboBoxWillDismiss:)])
[defaultCenter addObserver:delegate
selector:@selector(comboBoxWillDissmis:)
name:CPComboBoxWillDismissNotification
object:self];
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillDismiss_;
}
[super setDelegate:aDelegate];
@@ -412,49 +398,57 @@ var CPComboBoxTextSubview = @"text",
if (_listDelegate === aDelegate)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_listDelegate)
{
[defaultCenter removeObserver:self name:_CPPopUpListWillPopUpNotification object:_listDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListWillDismissNotification object:_listDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListDidDismissNotification object:_listDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListItemWasClickedNotification object:_listDelegate];
var oldTableView = [_listDelegate tableView];
if (oldTableView)
{
[defaultCenter removeObserver:self name:CPTableViewSelectionIsChangingNotification object:oldTableView];
[defaultCenter removeObserver:self name:CPTableViewSelectionDidChangeNotification object:oldTableView];
}
}
[self _removeObserversForListDelegate:_listDelegate];
_listDelegate = aDelegate;
// We only add the observers if the CPComboBox is displayed
if ([self window])
[self _addObserversForListDelegate:_listDelegate]
// Apply our text style to the list
[_listDelegate setFont:[self font]];
[_listDelegate setAlignment:[self alignment]];
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
if (_intercellSpacing)
[[_listDelegate tableView] setIntercellSpacing:_intercellSpacing];
if (_itemHeight)
[[_listDelegate tableView] setRowHeight:_itemHeight];
}
- (void)_addObserversForListDelegate:(_CPPopUpList)aDelegate
{
if (!aDelegate)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter addObserver:self
selector:@selector(comboBoxWillPopUp:)
name:_CPPopUpListWillPopUpNotification
object:_listDelegate];
object:aDelegate];
[defaultCenter addObserver:self
selector:@selector(comboBoxWillDismiss:)
name:_CPPopUpListWillDismissNotification
object:_listDelegate];
object:aDelegate];
[defaultCenter addObserver:self
selector:@selector(listDidDismiss:)
name:_CPPopUpListDidDismissNotification
object:_listDelegate];
object:aDelegate];
[defaultCenter addObserver:self
selector:@selector(itemWasClicked:)
name:_CPPopUpListItemWasClickedNotification
object:_listDelegate];
object:aDelegate];
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
[[aDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
var tableView = [_listDelegate tableView];
var tableView = [aDelegate tableView];
[defaultCenter addObserver:self
selector:@selector(comboBoxSelectionIsChanging:)
@@ -465,13 +459,27 @@ var CPComboBoxTextSubview = @"text",
selector:@selector(comboBoxSelectionDidChange:)
name:CPTableViewSelectionDidChangeNotification
object:tableView];
}
// Apply our text style to the list
[_listDelegate setFont:[self font]];
[_listDelegate setAlignment:[self alignment]];
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
[[_listDelegate tableView] setIntercellSpacing:_intercellSpacing];
[[_listDelegate tableView] setRowHeight:_itemHeight];
- (void)_removeObserversForListDelegate:(_CPPopUpList)aDelegate
{
if (!aDelegate)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter removeObserver:self name:_CPPopUpListWillPopUpNotification object:aDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListWillDismissNotification object:aDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListDidDismissNotification object:aDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListItemWasClickedNotification object:aDelegate];
var oldTableView = [aDelegate tableView];
if (oldTableView)
{
[defaultCenter removeObserver:self name:CPTableViewSelectionIsChangingNotification object:oldTableView];
[defaultCenter removeObserver:self name:CPTableViewSelectionDidChangeNotification object:oldTableView];
}
}
- (int)indexOfItemWithObjectValue:(id)anObject
@@ -516,8 +524,6 @@ var CPComboBoxTextSubview = @"text",
if (!_listDelegate)
[self setListDelegate:[[_CPPopUpList alloc] initWithDataSource:self]];
[self _selectMatchingItem];
// Note the offset here is 1 less than the focus ring width because the outer edge
// of the focus ring is very transparent and it looks better if the list is closer.
if (CPComboBoxFocusRingWidth < 0)
@@ -528,6 +534,7 @@ var CPComboBoxTextSubview = @"text",
}
[_listDelegate popUpRelativeToRect:[self _borderFrame] view:self offset:CPComboBoxFocusRingWidth - 1];
[self _selectMatchingItem];
}
/*! @ignore */
@@ -998,6 +1005,28 @@ var CPComboBoxTextSubview = @"text",
}
}
#pragma mark -
#pragma mark Observers method
- (void)_addObservers
{
if (_isObserving)
return;
[super _addObservers];
[self _addObserversForListDelegate:_listDelegate];
}
- (void)_removeObservers
{
if (!_isObserving)
return;
[super _removeObservers];
[self _removeObserversForListDelegate:_listDelegate];
}
@end
@implementation CPComboBox (CPComboBoxDelegate)
@@ -1005,24 +1034,36 @@ var CPComboBoxTextSubview = @"text",
/*! @ignore */
- (void)comboBoxSelectionIsChanging:(CPNotification)aNotification
{
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxSelectionIsChanging_)
[_delegate comboBoxSelectionIsChanging:[[CPNotification alloc] initWithName:CPComboBoxSelectionIsChangingNotification object:self userInfo:nil]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionIsChangingNotification object:self];
}
/*! @ignore */
- (void)comboBoxSelectionDidChange:(CPNotification)aNotification
{
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxSelectionDidChange_)
[_delegate comboBoxSelectionDidChange:[[CPNotification alloc] initWithName:CPComboBoxSelectionDidChangeNotification object:self userInfo:nil]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionDidChangeNotification object:self];
}
/*! @ignore */
- (void)comboBoxWillPopUp:(CPNotification)aNotification
{
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillPopUp_)
[_delegate comboBoxWillPopUp:[[CPNotification alloc] initWithName:CPComboBoxWillPopUpNotification object:self userInfo:nil]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillPopUpNotification object:self];
}
/*! @ignore */
- (void)comboBoxWillDismiss:(CPNotification)aNotification
{
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillDismiss_)
[_delegate comboBoxWillDismiss:[[CPNotification alloc] initWithName:CPComboBoxWillDismissNotification object:self userInfo:nil]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillDismissNotification object:self];
}
+1
View File
@@ -22,6 +22,7 @@ Cursor support by browser:
*/
@import <Foundation/CPObject.j>
@import "CPImage.j"
@global CPApp
+1
View File
@@ -31,6 +31,7 @@
@class CPTextField
@class CPWindow
@class CPGraphicsContext
@global CPApp
@global CPNewlineCharacter
+31 -5
View File
@@ -264,11 +264,6 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
_delegate = nil;
_scrollTimer = nil;
_implementedDelegateMethods = 0;
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
}
return self;
@@ -1270,6 +1265,37 @@ Notifies the delegate when the scroll view has finished scrolling.
#pragma mark -
#pragma mark Overrides
- (void)_removeObservers
{
if (!_isObserving)
return;
[[CPNotificationCenter defaultCenter] removeObserver:self
name:CPScrollerStyleGlobalChangeNotification
object:nil];
[super _removeObservers];
}
- (void)_addObservers
{
if (_isObserving)
return;
//Make sure to have the last global style for the scroller
[self _didReceiveDefaultStyleChange:nil];
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
[super _addObservers];
}
- (void)drawRect:(CGRect)aRect
{
[super drawRect:aRect];
+1 -16
View File
@@ -28,8 +28,6 @@
@import "CPTextField.j"
@global CPTableViewColumnDidResizeNotification
@class _CPTableColumnHeaderView
@class CPTableView
@@ -186,7 +184,7 @@ CPTableColumnUserResizingMask = 1 << 1;
[tableView tile];
if (!_disableResizingPosting)
[self _postDidResizeNotificationWithOldWidth:oldWidth];
[[self tableView] _didResizeTableColumn:self oldWidth:oldWidth];
}
}
@@ -539,19 +537,6 @@ CPTableColumnUserResizingMask = 1 << 1;
return _headerToolTip;
}
/*!
@ignore
*/
- (void)_postDidResizeNotificationWithOldWidth:(float)oldWidth
{
[[self tableView] _didResizeTableColumn:self];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPTableViewColumnDidResizeNotification
object:[self tableView]
userInfo:@{ @"CPTableColumn": self, @"CPOldWidth": oldWidth }];
}
@end
@implementation CPTableColumnValueBinder : CPBinder
+1 -1
View File
@@ -625,7 +625,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
- (void)stopResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
{
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
[_tableView _didResizeTableColumn:tableColumn oldWidth:_columnOldWidth];
[tableColumn setDisableResizingPosting:NO];
[_tableView setDisableAutomaticResizing:NO];
+91 -90
View File
@@ -81,10 +81,12 @@ var CPTableViewDelegate_selectionShouldChangeInTableView_
CPTableViewDelegate_tableView_typeSelectStringForTableColumn_row_ = 1 << 17,
CPTableViewDelegate_tableView_willDisplayView_forTableColumn_row_ = 1 << 18,
CPTableViewDelegate_tableView_willRemoveView_forTableColumn_row_ = 1 << 19,
CPTableViewDelegate_tableViewSelectionDidChange_ = 1 << 20,
CPTableViewDelegate_tableViewSelectionIsChanging_ = 1 << 21,
CPTableViewDelegate_tableViewMenuForTableColumn_row_ = 1 << 22,
CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_ = 1 << 23;
CPTableViewDelegate_tableViewColumnDidMove_ = 1 << 20,
CPTableViewDelegate_tableViewColumnDidResize_ = 1 << 21,
CPTableViewDelegate_tableViewSelectionDidChange_ = 1 << 22,
CPTableViewDelegate_tableViewSelectionIsChanging_ = 1 << 23,
CPTableViewDelegate_tableViewMenuForTableColumn_row_ = 1 << 24,
CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_ = 1 << 25;
//CPTableViewDraggingDestinationFeedbackStyles
CPTableViewDraggingDestinationFeedbackStyleNone = -1;
@@ -321,6 +323,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
CPTableColumn _draggedColumn;
CPArray _differedColumnDataToRemove;
CPView _observedClipView;
}
/*!
@@ -1167,6 +1171,9 @@ NOT YET IMPLEMENTED
[[CPNotificationCenter defaultCenter] postNotificationName:CPTableViewColumnDidMoveNotification
object:self
userInfo:@{ @"CPOldColumn": fromIndex, @"CPNewColumn": toIndex }];
if (_implementedDelegateMethods & CPTableViewDelegate_tableViewColumnDidMove_)
[_delegate tableViewColumnDidMove:[[CPNotification alloc] initWithName:CPTableViewColumnDidMoveNotification object:self userInfo:@{ @"CPOldColumn": fromIndex, @"CPNewColumn": toIndex }]];
}
/*!
@@ -1245,9 +1252,17 @@ NOT YET IMPLEMENTED
/*!
@ignore
*/
- (void)_didResizeTableColumn:(CPTableColumn)theColumn
- (void)_didResizeTableColumn:(CPTableColumn)theColumn oldWidth:(int)oldWidth
{
[self _autosave];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPTableViewColumnDidResizeNotification
object:self
userInfo:@{ @"CPTableColumn": theColumn, @"CPOldWidth": oldWidth }];
if (_implementedDelegateMethods & CPTableViewDelegate_tableViewColumnDidResize_)
[_delegate tableViewColumnDidResize:[[CPNotification alloc] initWithName:CPTableViewColumnDidResizeNotification object:self userInfo:@{ @"CPTableColumn": theColumn, @"CPOldWidth": oldWidth }]];
}
//Selecting Columns and Rows
@@ -2860,35 +2875,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (_delegate === aDelegate)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_delegate)
{
if ([_delegate respondsToSelector:@selector(tableViewColumnDidMove:)])
[defaultCenter
removeObserver:_delegate
name:CPTableViewColumnDidMoveNotification
object:self];
if ([_delegate respondsToSelector:@selector(tableViewColumnDidResize:)])
[defaultCenter
removeObserver:_delegate
name:CPTableViewColumnDidResizeNotification
object:self];
if ([_delegate respondsToSelector:@selector(tableViewSelectionDidChange:)])
[defaultCenter
removeObserver:_delegate
name:CPTableViewSelectionDidChangeNotification
object:self];
if ([_delegate respondsToSelector:@selector(tableViewSelectionIsChanging:)])
[defaultCenter
removeObserver:_delegate
name:CPTableViewSelectionIsChangingNotification
object:self];
}
_delegate = aDelegate;
_implementedDelegateMethods = 0;
@@ -2963,32 +2949,16 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
_implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_;
if ([_delegate respondsToSelector:@selector(tableViewColumnDidMove:)])
[defaultCenter
addObserver:_delegate
selector:@selector(tableViewColumnDidMove:)
name:CPTableViewColumnDidMoveNotification
object:self];
_implementedDelegateMethods |= CPTableViewDelegate_tableViewColumnDidMove_;
if ([_delegate respondsToSelector:@selector(tableViewColumnDidResize:)])
[defaultCenter
addObserver:_delegate
selector:@selector(tableViewColumnDidResize:)
name:CPTableViewColumnDidResizeNotification
object:self];
_implementedDelegateMethods |= CPTableViewDelegate_tableViewColumnDidResize_;
if ([_delegate respondsToSelector:@selector(tableViewSelectionDidChange:)])
[defaultCenter
addObserver:_delegate
selector:@selector(tableViewSelectionDidChange:)
name:CPTableViewSelectionDidChangeNotification
object:self];
_implementedDelegateMethods |= CPTableViewDelegate_tableViewSelectionDidChange_;
if ([_delegate respondsToSelector:@selector(tableViewSelectionIsChanging:)])
[defaultCenter
addObserver:_delegate
selector:@selector(tableViewSelectionIsChanging:)
name:CPTableViewSelectionIsChangingNotification
object:self];
_implementedDelegateMethods |= CPTableViewDelegate_tableViewSelectionIsChanging_;
}
/*!
@@ -4455,41 +4425,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
*/
- (void)viewWillMoveToSuperview:(CPView)aView
{
[super viewWillMoveToSuperview:aView];
var superview = [self superview],
defaultCenter = [CPNotificationCenter defaultCenter];
if (superview)
{
[defaultCenter
removeObserver:self
name:CPViewFrameDidChangeNotification
object:superview];
[defaultCenter
removeObserver:self
name:CPViewBoundsDidChangeNotification
object:superview];
}
if ([aView isKindOfClass:[CPClipView class]])
_observedClipView = aView;
else
{
[aView setPostsFrameChangedNotifications:YES];
[aView setPostsBoundsChangedNotifications:YES];
[defaultCenter
addObserver:self
selector:@selector(superviewFrameChanged:)
name:CPViewFrameDidChangeNotification
object:aView];
[defaultCenter
addObserver:self
selector:@selector(superviewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
object:aView];
[self _stopObservingClipView];
_observedClipView = nil;
}
[super viewWillMoveToSuperview:aView];
}
/*!
@@ -5071,6 +5015,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
postNotificationName:CPTableViewSelectionIsChangingNotification
object:self
userInfo:nil];
if (_implementedDelegateMethods & CPTableViewDelegate_tableViewSelectionIsChanging_)
[_delegate tableViewSelectionIsChanging:[[CPNotification alloc] initWithName:CPTableViewSelectionIsChangingNotification object:self userInfo:nil]];
}
/*!
@@ -5082,6 +5029,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
postNotificationName:CPTableViewSelectionDidChangeNotification
object:self
userInfo:nil];
if (_implementedDelegateMethods & CPTableViewDelegate_tableViewSelectionDidChange_)
[_delegate tableViewSelectionDidChange:[[CPNotification alloc] initWithName:CPTableViewSelectionDidChangeNotification object:self userInfo:nil]];
}
/*!
@@ -5139,8 +5089,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (!_isObserving)
return;
[self _stopObservingClipView];
[super _removeObservers];
[self _stopObservingFirstResponder];
}
- (void)_addObservers
@@ -5148,13 +5098,64 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if (_isObserving)
return;
[self _startObservingClipView];
[super _addObservers];
[self _startObservingFirstResponder];
}
- (void)_startObservingFirstResponder
/*!
Called when the receiver is about to be moved to a new window.
@param aWindow the window to which the receiver will be moved.
*/
- (void)viewWillMoveToWindow:(CPWindow)aWindow
{
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_firstResponderDidChange:) name:_CPWindowDidChangeFirstResponderNotification object:[self window]];
[super viewWillMoveToWindow:aWindow];
[self _stopObservingFirstResponder];
if (aWindow)
[self _startObservingFirstResponderForWindow:aWindow];
}
- (void)_startObservingClipView
{
if (!_observedClipView)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[_observedClipView setPostsFrameChangedNotifications:YES];
[_observedClipView setPostsBoundsChangedNotifications:YES];
[defaultCenter addObserver:self
selector:@selector(superviewFrameChanged:)
name:CPViewFrameDidChangeNotification
object:_observedClipView];
[defaultCenter addObserver:self
selector:@selector(superviewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
object:_observedClipView];
}
- (void)_stopObservingClipView
{
if (!_observedClipView)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter removeObserver:self
name:CPViewFrameDidChangeNotification
object:_observedClipView];
[defaultCenter removeObserver:self
name:CPViewBoundsDidChangeNotification
object:_observedClipView];
}
- (void)_startObservingFirstResponderForWindow:(CPWindow)aWindow
{
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_firstResponderDidChange:) name:_CPWindowDidChangeFirstResponderNotification object:aWindow];
}
- (void)_stopObservingFirstResponder
+47 -39
View File
@@ -38,8 +38,13 @@
@end
var CPTextFieldDelegate_control_didFailToFormatString_errorDescription_ = 1 << 1,
CPTextFieldDelegate_controlTextDidBeginEditing_ = 1 << 2,
CPTextFieldDelegate_controlTextDidChange_ = 1 << 3,
CPTextFieldDelegate_controlTextDidEndEditing_ = 1 << 4,
CPTextFieldDelegate_controlTextDidFocus_ = 1 << 5,
CPTextFieldDelegate_controlTextDidBlur_ = 1 << 6;
var CPTextFieldDelegate_control_didFailToFormatString_errorDescription_ = 1 << 1;
@typedef CPTextFieldBezelStyle
CPTextFieldSquareBezel = 0; /*! A textfield bezel with squared corners. */
@@ -877,7 +882,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[super _addObservers];
if ([self window] === self)
if ([[self window] firstResponder] === self)
[self _setObserveWindowKeyNotifications:YES];
}
@@ -1147,6 +1152,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
if ([note object] != self)
return;
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBlur_)
[_delegate controlTextDidBlur:note];
[[CPNotificationCenter defaultCenter] postNotification:note];
}
@@ -1156,6 +1164,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
if ([note object] != self)
return;
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidFocus_)
[_delegate controlTextDidFocus:note];
[[CPNotificationCenter defaultCenter] postNotification:note];
}
@@ -1166,9 +1177,36 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
[self _continuouslyReverseSetBinding];
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidChange_)
[_delegate controlTextDidChange:note];
[super textDidChange:note];
}
- (void)textDidBeginEditing:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if ([note object] != self)
return;
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBeginEditing_)
[_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]]
[super textDidBeginEditing:note];
}
- (void)textDidEndEditing:(CPNotification)note
{
//this looks to prevent false propagation of notifications for other objects
if ([note object] != self)
return;
[super textDidEndEditing:note];
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidEndEditing_)
[_delegate controlTextDidEndEditing:note];
}
- (void)_updateCursorForEvent:(CPEvent)anEvent
{
var frame = CGRectMakeCopy([self frame]),
@@ -1713,17 +1751,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
- (void)setDelegate:(id <CPTextFieldDelegate>)aDelegate
{
var defaultCenter = [CPNotificationCenter defaultCenter];
//unsubscribe the existing delegate if it exists
if (_delegate)
{
[defaultCenter removeObserver:_delegate name:CPControlTextDidBeginEditingNotification object:self];
[defaultCenter removeObserver:_delegate name:CPControlTextDidChangeNotification object:self];
[defaultCenter removeObserver:_delegate name:CPControlTextDidEndEditingNotification object:self];
[defaultCenter removeObserver:_delegate name:CPTextFieldDidFocusNotification object:self];
[defaultCenter removeObserver:_delegate name:CPTextFieldDidBlurNotification object:self];
}
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
@@ -1732,40 +1761,19 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
_implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidBeginEditing:)
name:CPControlTextDidBeginEditingNotification
object:self];
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_;
if ([_delegate respondsToSelector:@selector(controlTextDidChange:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidChange:)
name:CPControlTextDidChangeNotification
object:self];
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidChange_;
if ([_delegate respondsToSelector:@selector(controlTextDidEndEditing:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidEndEditing:)
name:CPControlTextDidEndEditingNotification
object:self];
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidEndEditing_;
if ([_delegate respondsToSelector:@selector(controlTextDidFocus:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidFocus:)
name:CPTextFieldDidFocusNotification
object:self];
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidFocus_;
if ([_delegate respondsToSelector:@selector(controlTextDidBlur:)])
[defaultCenter
addObserver:_delegate
selector:@selector(controlTextDidBlur:)
name:CPTextFieldDidBlurNotification
object:self];
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBlur_;
}
- (id)delegate
+21
View File
@@ -175,6 +175,7 @@ var CPViewFlags = { },
BOOL _postsBoundsChangedNotifications;
BOOL _inhibitFrameAndBoundsChangedNotifications;
BOOL _inLiveResize;
BOOL _isSuperviewAClipView;
#if PLATFORM(DOM)
DOMElement _DOMElement;
@@ -824,6 +825,8 @@ var CPViewFlags = { },
*/
- (void)viewWillMoveToSuperview:(CPView)aView
{
_isSuperviewAClipView = [aView isKindOfClass:[CPClipView class]];
[self _removeObservers];
if (aView)
@@ -955,6 +958,9 @@ var CPViewFlags = { },
if (_postsFrameChangedNotifications)
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
if (_isSuperviewAClipView)
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
}
/*!
@@ -1017,6 +1023,9 @@ var CPViewFlags = { },
if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
#if PLATFORM(DOM)
var transform = _superview ? _superview._boundsTransform : NULL;
@@ -1176,6 +1185,9 @@ var CPViewFlags = { },
if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
}
/*!
@@ -1210,6 +1222,9 @@ var CPViewFlags = { },
if (_postsBoundsChangedNotifications)
[CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
if (_isSuperviewAClipView)
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
}
/*!
@@ -1272,6 +1287,9 @@ var CPViewFlags = { },
if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
[CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
}
/*!
@@ -1310,6 +1328,9 @@ var CPViewFlags = { },
if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
[CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
}
+23 -5
View File
@@ -907,18 +907,21 @@ CPTexturedBackgroundWindowMask
- (void)_orderFront
{
[[self contentView] _addObservers];
#if PLATFORM(DOM)
// -dw- if a sheet is clicked, the parent window should come up too
if (_isSheet)
[_parentView orderFront:self];
if (!_isVisible)
[self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
// Save the boolean since it will be updated in the method order:window:relativeTo:
var wasVisible = _isVisible;
[_platformWindow orderFront:self];
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
// setFrame is set after ordering the window as this method can send some notifications
if (!wasVisible)
[self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
#endif
if (!CPApp._keyWindow)
@@ -939,6 +942,23 @@ CPTexturedBackgroundWindowMask
{
}
/*
Called when the window is displayed in the DOM
*/
- (void)_windowWillBeAddedToTheDOM
{
[[self contentView] _addObservers];
}
/*
Called when the window is removed in the DOM
*/
- (void)_windowWillBeRemovedFromTheDOM
{
[[self contentView] _removeObservers];
}
/*
Makes the receiver the last window in the screen ordering.
@param aSender the object that requested this
@@ -968,8 +988,6 @@ CPTexturedBackgroundWindowMask
if (!_isVisible)
return;
[[self contentView] _removeObservers];
if ([self isSheet])
{
// -dw- as in Cocoa, orderOut: detaches the sheet and animates out
@@ -1299,7 +1299,10 @@ var PreventScroll = true;
// When ordering out, ignore otherWindow, simply remove aWindow from its level.
// If layer is nil, this will be a no-op.
if (orderingMode === CPWindowOut)
{
[aWindow _windowWillBeRemovedFromTheDOM];
return [layer removeWindow:aWindow];
}
/*
If aWindow is a child of otherWindow and is not yet visible,
@@ -1345,6 +1348,8 @@ var PreventScroll = true;
if (otherWindow)
insertionIndex = orderingMode === CPWindowAbove ? otherWindow._index + 1 : otherWindow._index;
[aWindow _windowWillBeAddedToTheDOM];
// Place the window at the appropriate index.
[layer insertWindow:aWindow atIndex:insertionIndex];
@@ -1395,6 +1400,9 @@ var PreventScroll = true;
var index = ordering === CPWindowAbove ? parent._index + 1 : parent._index;
if (!childWasVisible)
[child _windowWillBeAddedToTheDOM];
[aLayer insertWindow:child atIndex:index];
if (!childWasVisible)
+28 -14
View File
@@ -96,28 +96,41 @@ var ListColumnIdentifier = @"1";
return [super sendEvent:anEvent];
}
- (void)orderFront:(id)sender
{
[self _trapNextMouseDown];
[super orderFront:sender];
}
- (void)_mouseWasClicked:(CPEvent)anEvent
{
// This is needed, when the user close the list with the key enter
if (![self isVisible])
{
[CPApp sendEvent:anEvent];
return;
}
var mouseWindow = [anEvent window],
rect = [[[self delegate] dataSource] bounds],
rect = CGRectInsetByInset([[[self delegate] dataSource] bounds], [[[self delegate] dataSource] currentValueForThemeAttribute:@"content-inset"]),
point = [[[self delegate] dataSource] convertPoint:[anEvent locationInWindow] fromView:nil];
// If we click somewhere else than the comboBox or the panel we close the panel
if (mouseWindow != self && !CGRectContainsPoint(rect, point))
{
[[self delegate] close];
}
else
[self _trapNextMouseDown];
{
// If we click on the panel, the app will know what to do
if (mouseWindow == self)
[CPApp sendEvent:anEvent];
// If we click on the comboBox field, we will trap the next mouse down
if (CGRectContainsPoint(rect, point))
[self _trapNextMouseDown];
}
}
- (void)_trapNextMouseDown
{
// Don't dequeue the event so clicks in controls will work
[CPApp setTarget:self selector:@selector(_mouseWasClicked:) forNextEventMatchingMask:CPLeftMouseDownMask untilDate:nil inMode:CPDefaultRunLoopMode dequeue:NO];
// Dequeue the event and mouseWasClicked will do what it needs to do
[CPApp setTarget:self selector:@selector(_mouseWasClicked:) forNextEventMatchingMask:CPLeftMouseDownMask untilDate:nil inMode:CPDefaultRunLoopMode dequeue:YES];
}
@end
@@ -323,6 +336,11 @@ var ListColumnIdentifier = @"1";
if ([_panel isVisible])
return;
[self listWillPopUp];
[_panel _trapNextMouseDown];
[[aView window] addChildWindow:_panel ordered:CPWindowAbove];
var rowRect = [_tableView rectOfRow:[self numberOfRowsInTableView:_tableView] - 1],
frame = CGRectMake(0, 0, MAX(_listWidth, CGRectGetWidth(aRect)), CGRectGetMaxY(rowRect));
@@ -333,10 +351,6 @@ var ListColumnIdentifier = @"1";
[_scrollView setFrameSize:CGSizeMakeCopy(frame.size)];
[_tableView setEnabled:[_dataSource numberOfItemsInList:self] > 0];
[self scrollItemAtIndexToTop:[_tableView selectedRow]];
[self listWillPopUp];
[[aView window] addChildWindow:_panel ordered:CPWindowAbove];
}
#pragma mark Setting Display Attributes
+8 -4
View File
@@ -64,6 +64,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
BOOL _isObservingFrame;
BOOL _shouldPerformAnimation;
CPInteger _implementedDelegateMethods;
CGRect _targetRect;
CPWindow _targetWindow;
JSObject _orderOutTransitionFunction;
JSObject _transitionCompleteFunction;
@@ -206,7 +207,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
if (![_targetView window])
return;
var point = [self computeOriginFromRect:[_targetView bounds] ofView:_targetView preferredEdge:[_windowView preferredEdge]];
var point = [self computeOriginFromRect:_targetRect ofView:_targetView preferredEdge:[_windowView preferredEdge]];
[self setFrameOrigin:point];
}
}
@@ -369,6 +370,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
_targetView = positioningView;
}
_targetRect = aRect;
[self makeKeyAndOrderFront:nil];
/*
@@ -417,7 +419,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
if ([self isVisible])
{
var point = [self computeOriginFromRect:[_targetView bounds] ofView:_targetView preferredEdge:[_windowView preferredEdge]];
var point = [self computeOriginFromRect:_targetRect ofView:_targetView preferredEdge:[_windowView preferredEdge]];
[self setFrameOrigin:point];
}
}
@@ -581,10 +583,12 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
- (void)_orderFront
{
if (![self isVisible])
[self _addFrameObserver];
var wasVisible = [self isVisible];
[super _orderFront];
if (!wasVisible)
[self _addFrameObserver];
}
- (void)_parentDidOrderInChild
+1 -1
View File
@@ -53,7 +53,7 @@
@param aType the structure or object type
@param anObject the object to be encoded
*/
- (void)encodeValueOfObjCType:(CPString)aType at:(id)anObject
- (void)encodeValueOfObjJType:(CPString)aType at:(id)anObject
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
+20
View File
@@ -74,24 +74,36 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0));
- (id)initWithTimeIntervalSinceNow:(CPTimeInterval)seconds
{
if (!_isNumberType(seconds))
CPLog.warn(@"The parameter of the method initWithTimeIntervalSinceNow: should be an integer or a float");
self = new Date((new Date()).getTime() + seconds * 1000);
return self;
}
- (id)initWithTimeIntervalSince1970:(CPTimeInterval)seconds
{
if (!_isNumberType(seconds))
CPLog.warn(@"The parameter of the method initWithTimeIntervalSince1970: should be an integer or a float");
self = new Date(seconds * 1000);
return self;
}
- (id)initWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds
{
if (!_isNumberType(seconds))
CPLog.warn(@"The parameter of the method initWithTimeIntervalSinceReferenceDate: should be an integer or a float");
self = [self initWithTimeInterval:seconds sinceDate:CPDateReferenceDate];
return self;
}
- (id)initWithTimeInterval:(CPTimeInterval)seconds sinceDate:(CPDate)refDate
{
if (!_isNumberType(seconds))
CPLog.warn(@"The parameter of the method initWithTimeInterval:sinceDate: should be an integer or a float");
self = new Date(refDate.getTime() + seconds * 1000);
return self;
}
@@ -275,3 +287,11 @@ Date.parseISO8601 = function (date)
};
Date.prototype.isa = CPDate;
function _isNumberType(value)
{
if (typeof value === 'number')
return YES;
else
return NO;
}
+97 -26
View File
@@ -24,31 +24,52 @@
@import "CPObject.j"
@import "CPString.j"
CPCappuccinoErrorDomain = CPCocoaErrorDomain = @"CPCappuccinoErrorDomain";
// CPPOSIXErrorDomain = @"CPPOSIXErrorDomain";
// CPOSStatusErrorDomain = @"CPOSStatusErrorDomain";
CPCappuccinoErrorDomain = kCFErrorDomainCappuccino;
CPCocoaErrorDomain = kCFErrorDomainCappuccino; // compat
CPUnderlyingErrorKey = @"CPUnderlyingErrorKey";
CPUnderlyingErrorKey = kCFErrorUnderlyingErrorKey;
CPLocalizedDescriptionKey = @"CPLocalizedDescriptionKey";
CPLocalizedFailureReasonErrorKey = @"CPLocalizedFailureReasonErrorKey";
CPLocalizedRecoverySuggestionErrorKey = @"CPLocalizedRecoverySuggestionErrorKey";
CPLocalizedDescriptionKey = kCFErrorLocalizedDescriptionKey;
CPLocalizedFailureReasonErrorKey = kCFErrorLocalizedFailureReasonKey;
CPLocalizedRecoverySuggestionErrorKey = kCFErrorLocalizedRecoverySuggestionKey;
CPLocalizedRecoveryOptionsErrorKey = @"CPLocalizedRecoveryOptionsErrorKey";
CPRecoveryAttempterErrorKey = @"CPRecoveryAttempterErrorKey";
CPHelpAnchorErrorKey = @"CPHelpAnchorErrorKey";
CPStringEncodingErrorKey = @"CPStringEncodingErrorKey";
CPURLErrorKey = @"CPURLErrorKey";
CPFilePathErrorKey = @"CPFilePathErrorKey";
CPURLErrorKey = kCFErrorURLKey;
CPFilePathErrorKey = kCFErrorFilePathKey;
/*!
@class CPError
@ingroup foundation
@brief Used for encapsulating, presenting, and recovery from errors.
CPError is toll-free bridged with CFError() methods.
An example of initializing a CPError:
<pre>
var userInfo = @{CPLocalizedDescriptionKey: @"A localized error description",
CPLocalizedFailureReasonErrorKey: @"A localized failure reason",
CPUnderlyingErrorKey: @"An underlying error message"},
err = [CPError errorWithDomain:CPCappuccinoErrorDomain code:-10 userInfo:userInfo];
</pre>
*/
@implementation CPError : CPObject
{
CPInteger _code @accessors(property=code, readonly);
CPString _domain @accessors(property=domain, readonly);
CPDictionary _userInfo @accessors(property=userInfo, readonly);
}
+ (id)alloc
{
var obj = new CFError();
obj.isa = [self class];
return obj;
}
+ (id)errorWithDomain:(CPString)aDomain code:(CPInteger)aCode userInfo:(CPDictionary)aDict
{
return [[CPError alloc] initWithDomain:aDomain code:aCode userInfo:aDict];
@@ -56,44 +77,94 @@ CPFilePathErrorKey = @"CPFilePathErrorKey";
- (id)initWithDomain:(CPString)aDomain code:(CPInteger)aCode userInfo:(CPDictionary)aDict
{
if (self = [super init])
{
_domain = aDomain;
_code = aCode;
_userInfo = aDict;
}
return self;
var result = new CFError(aDomain, aCode, aDict);
result.isa = [self class];
return result;
}
- (CPInteger)code
{
return self.code();
}
- (CPString)userInfo
{
return self.userInfo();
}
- (CPString)domain
{
return self.domain();
}
/*!
By default this method returns the object in the user info dictionary for the key
CPLocalizedDescriptionKey. If the user info dictionary doesnt contain a value for
CPLocalizedDescriptionKey, a default string is constructed from the domain and code.
*/
- (CPString)localizedDescription
{
return [_userInfo objectForKey:CPLocalizedDescriptionKey];
return self.description();
}
- (CPString)localizedFailureReason
{
return [_userInfo objectForKey:CPLocalizedFailureReasonErrorKey];
return self.failureReason();
}
- (CPArray)localizedRecoveryOptions
{
return [_userInfo objectForKey:CPLocalizedRecoveryOptionsErrorKey];
var userInfo = self.userInfo(),
recoveryOptions = userInfo.valueForKey(CPLocalizedRecoveryOptionsErrorKey);
return recoveryOptions;
}
- (CPString)localizedRecoverySuggestion
{
return [_userInfo objectForKey:CPLocalizedRecoverySuggestionErrorKey];
return self.recoverySuggestion();
}
- (id)recoveryAttempter
{
return [_userInfo objectForKey:CPRecoveryAttempterErrorKey];
var userInfo = self.userInfo(),
recoveryAttempter = userInfo.valueForKey(CPRecoveryAttempterErrorKey);
return recoveryAttempter;
}
- (CPString)description
{
return [CPString stringWithFormat:@"Error Domain=%@ Code=%d UserInfo=%p %@", _domain, _code, _userInfo, [self localizedDescription]];
return [CPString stringWithFormat:@"Error Domain=%@ Code=%d \"%@\" UserInfo=%@", self.domain(), self.code(), self.description(), self.userInfo()];
}
@end
var CPErrorCodeKey = @"CPErrorCodeKey",
CPErrorDomainKey = @"CPErrorDomainKey",
CPErrorUserInfoKey = @"CPErrorUserInfoKey";
@implementation CPError (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
var code = [aCoder decodeIntForKey:CPErrorCodeKey],
domain = [aCoder decodeObjectForKey:CPErrorDomainKey],
userInfo = [aCoder decodeObjectForKey:CPErrorUserInfoKey];
return [self initWithDomain:domain
code:code
userInfo:userInfo];
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:self.domain() forKey:CPErrorDomainKey];
[aCoder encodeObject:self.code() forKey:CPErrorCodeKey];
[aCoder encodeObject:self.userInfo() forKey:CPErrorUserInfoKey];
}
@end
CFError.prototype.isa = CPError;
+4 -3
View File
@@ -117,10 +117,11 @@ CPOperationQueuePriorityVeryHigh = 8;
[self willChangeValueForKey:@"isExecuting"];
_executing = NO;
[self didChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
_finished = YES;
[self didChangeValueForKey:@"isFinished"];
}
[self willChangeValueForKey:@"isFinished"];
_finished = YES;
[self didChangeValueForKey:@"isFinished"];
}
/*!
+2 -2
View File
@@ -70,7 +70,7 @@ var cpOperationMainQueue = nil;
for (; i < count; i++)
{
var op = [_operations objectAtIndex:i];
if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting])
if ([op isReady] && ![op isFinished] && ![op isExecuting])
{
[op start];
}
@@ -260,7 +260,7 @@ var cpOperationMainQueue = nil;
for (; i < count; i++)
{
var op = [ops objectAtIndex:i];
if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting])
if ([op isReady] && ![op isFinished] && ![op isExecuting])
{
[op start];
}
+39
View File
@@ -0,0 +1,39 @@
/*
* The CPURL Error Domain
*/
CPURLErrorDomain = @"CPURLErrorDomain";
/*
* CPURL UserInfo Error Keys
*/
CPURLErrorFailingURLErrorKey = @"CPErrorFailingURLKey";
CPURLErrorFailingURLStringErrorKey = @"CPURLErrorFailingURLStringKey";
/*
* CPURL Error Codes
*/
CPURLErrorUnknown = -1;
CPURLErrorCancelled = kCFURLErrorCancelled;
CPURLErrorBadURL = kCFURLErrorBadURL;
CPURLErrorTimedOut = kCFURLErrorTimedOut;
CPURLErrorUnsupportedURL = kCFURLErrorUnsupportedURL;
CPURLErrorCannotFindHost = kCFURLErrorCannotFindHost;
CPURLErrorCannotConnectToHost = kCFURLErrorCannotConnectToHost;
CPURLErrorNetworkConnectionLost = kCFURLErrorNetworkConnectionLost;
CPURLErrorDNSLookupFailed = kCFURLErrorDNSLookupFailed;
CPURLErrorHTTPTooManyRedirects = kCFURLErrorHTTPTooManyRedirects;
CPURLErrorResourceUnavailable = kCFURLErrorResourceUnavailable;
CPURLErrorNotConnectedToInternet = kCFURLErrorNotConnectedToInternet;
CPURLErrorRedirectToNonExistentLocation = kCFURLErrorRedirectToNonExistentLocation;
CPURLErrorBadServerResponse = kCFURLErrorBadServerResponse;
CPURLErrorUserCancelledAuthentication = kCFURLErrorUserCancelledAuthentication;
CPURLErrorUserAuthenticationRequired = kCFURLErrorUserAuthenticationRequired;
CPURLErrorZeroByteResource = kCFURLErrorZeroByteResource;
CPURLErrorCannotDecodeRawData = kCFURLErrorCannotDecodeRawData;
CPURLErrorCannotDecodeContentData = kCFURLErrorCannotDecodeContentData;
CPURLErrorCannotParseResponse = kCFURLErrorCannotParseResponse;
CPURLErrorFileDoesNotExist = kCFURLErrorFileDoesNotExist;
CPURLErrorFileIsDirectory = kCFURLErrorFileIsDirectory;
CPURLErrorNoPermissionsToReadFile = kCFURLErrorNoPermissionsToReadFile;
CPURLErrorDataLengthExceedsMaximum = kCFURLErrorDataLengthExceedsMaximum;
+1
View File
@@ -73,6 +73,7 @@
@import "CPUndoManager.j"
@import "CPURL.j"
@import "CPURLConnection.j"
@import "CPURLError.j"
@import "CPURLRequest.j"
@import "CPURLResponse.j"
@import "CPUserDefaults.j"
+164
View File
@@ -0,0 +1,164 @@
/*
* CFError.js
* Objective-J
*
* Created by Andrew Hankinson.
* Copyright 2014, Andrew Hankinson.
*
* 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
*/
GLOBAL(kCFErrorLocalizedDescriptionKey) = "CPLocalizedDescription";
GLOBAL(kCFErrorLocalizedFailureReasonKey) = "CPLocalizedFailureReason";
GLOBAL(kCFErrorLocalizedRecoverySuggestionKey) = "CPLocalizedRecoverySuggestion";
GLOBAL(kCFErrorDescriptionKey) = "CPDescription";
GLOBAL(kCFErrorUnderlyingErrorKey) = "CPUnderlyingError";
GLOBAL(kCFErrorURLKey) = "CPURL";
GLOBAL(kCFErrorFilePathKey) = "CPFilePath";
// GLOBAL(kCFErrorDomainPOSIX) = "";
// GLOBAL(kCFErrorDomainOSStatus) = "";
// GLOBAL(kCFErrorDomainMach) = "";
GLOBAL(kCFErrorDomainCappuccino) = "CPCappuccinoErrorDomain";
GLOBAL(kCFErrorDomainCocoa) = kCFErrorDomainCappuccino;
GLOBAL(CFError) = function(/* CFString */ domain, /* int */ code, /* CFDictionary */ userInfo)
{
this._domain = domain || NULL;
this._code = code || 0;
this._userInfo = userInfo || new CFDictionary();
this._UID = objj_generateObjectUID();
};
CFError.prototype.domain = function()
{
return this._domain;
};
DISPLAY_NAME(CFError.prototype.domain);
CFError.prototype.code = function()
{
return this._code;
};
DISPLAY_NAME(CFError.prototype.code);
/*
This follows the same logic to generate a description as the "real" CFError.
*/
CFError.prototype.description = function()
{
var localizedDesc = this._userInfo.valueForKey(kCFErrorLocalizedDescriptionKey);
if (localizedDesc)
return localizedDesc;
var reason = this._userInfo.valueForKey(kCFErrorLocalizedFailureReasonKey);
if (reason)
{
var operationFailedStr = "The operation couldn\u2019t be completed. " + reason;
return operationFailedStr;
}
// @TODO Add the bundle localized domain handler.
var result = "",
desc = this._userInfo.valueForKey(kCFErrorDescriptionKey);
if (desc)
{
// we have a description key.
var result = "The operation couldn\u2019t be completed. (error " + this._code + " - " + desc + ")";
}
else
{
// just use error and code;
var result = "The operation couldn\u2019t be completed. (error " + this._code + ")";
}
return result;
};
DISPLAY_NAME(CFError.prototype.description);
CFError.prototype.failureReason = function()
{
return this._userInfo.valueForKey(kCFErrorLocalizedFailureReasonKey);
};
DISPLAY_NAME(CFError.prototype.failureReason);
CFError.prototype.recoverySuggestion = function()
{
return this._userInfo.valueForKey(kCFErrorLocalizedRecoverySuggestionKey);
};
DISPLAY_NAME(CFError.prototype.recoverySuggestion);
CFError.prototype.userInfo = function ()
{
return this._userInfo;
};
DISPLAY_NAME(CFError.prototype.userInfo);
/*
CFError Bridge Functions
The "Create" and "Copy" in the function names do not have any meaning
in Cappuccino; they are bridged here for compatibility reasons only.
*/
GLOBAL(CFErrorCreate) = function(/* String */ domain, /*int */ code, /* CFDictionary */ userInfo)
{
return new CFError(domain, code, userInfo);
};
GLOBAL(CFErrorCreateWithUserInfoKeysAndValues) = function(/* String */ domain, /* int */ code, /* array */ userInfoKeys, /* array */ userInfoValues, /* int */ numUserInfoValues)
{
var userInfo = new CFMutableDictionary();
while (numUserInfoValues--)
userInfo.setValueForKey(userInfoKeys[numUserInfoValues], userInfoValues[numUserInfoValues]);
return new CFError(domain, code, userInfo);
};
GLOBAL(CFErrorGetCode) = function(/* CFError */ err)
{
return err.code();
};
GLOBAL(CFErrorGetDomain) = function(/* CFError */ err)
{
return err.domain();
};
GLOBAL(CFErrorCopyDescription) = function(/* CFError */ err)
{
return err.description();
};
GLOBAL(CFErrorCopyUserInfo) = function(/* CFError */ err)
{
return err.userInfo();
};
GLOBAL(CFErrorCopyFailureReason) = function(/* CFError */ err)
{
return err.failureReason();
};
GLOBAL(CFErrorCopyRecoverySuggestion) = function(/* CFError */err)
{
return err.recoverySuggestion();
};
+25
View File
@@ -0,0 +1,25 @@
GLOBAL(kCFURLErrorUnknown) = -998;
GLOBAL(kCFURLErrorCancelled) = -999;
GLOBAL(kCFURLErrorBadURL) = -1000;
GLOBAL(kCFURLErrorTimedOut) = -1001;
GLOBAL(kCFURLErrorUnsupportedURL) = -1002;
GLOBAL(kCFURLErrorCannotFindHost) = -1003;
GLOBAL(kCFURLErrorCannotConnectToHost) = -1004;
GLOBAL(kCFURLErrorNetworkConnectionLost) = -1005;
GLOBAL(kCFURLErrorDNSLookupFailed) = -1006;
GLOBAL(kCFURLErrorHTTPTooManyRedirects) = -1007;
GLOBAL(kCFURLErrorResourceUnavailable) = -1008;
GLOBAL(kCFURLErrorNotConnectedToInternet) = -1009;
GLOBAL(kCFURLErrorRedirectToNonExistentLocation) = -1010;
GLOBAL(kCFURLErrorBadServerResponse) = -1011;
GLOBAL(kCFURLErrorUserCancelledAuthentication) = -1012;
GLOBAL(kCFURLErrorUserAuthenticationRequired) = -1013;
GLOBAL(kCFURLErrorZeroByteResource) = -1014;
GLOBAL(kCFURLErrorCannotDecodeRawData) = -1015;
GLOBAL(kCFURLErrorCannotDecodeContentData) = -1016;
GLOBAL(kCFURLErrorCannotParseResponse) = -1017;
GLOBAL(kCFURLErrorRequestBodyStreamExhausted) = -1021;
GLOBAL(kCFURLErrorFileDoesNotExist) = -1100;
GLOBAL(kCFURLErrorFileIsDirectory) = -1101;
GLOBAL(kCFURLErrorNoPermissionsToReadFile) = -1102;
GLOBAL(kCFURLErrorDataLengthExceedsMaximum) = -1103;
+2
View File
@@ -38,6 +38,8 @@
#include "CFHTTPRequest.js"
#include "CFPropertyList.js"
#include "CFDictionary.js"
#include "CFError.js"
#include "CFNetworkErrors.js"
#include "CFData.js"
#include "CFURL.js"
#include "MarkedStream.js"
+2 -2
View File
@@ -2381,9 +2381,9 @@ Reference: function(node, st, c) {
buffer.concat(" "); // Add an extra space if it looks something like this: "return(<expression>)". No space between return and expression.
}
buffer.concat("function(__input) { if (arguments.length) return ");
buffer.concat(node.element.name);
c(node.element, st, "Expression");
buffer.concat(" = __input; return ");
buffer.concat(node.element.name);
c(node.element, st, "Expression");
buffer.concat("; }");
if (!generate) compiler.lastPos = node.end;
},
+78
View File
@@ -0,0 +1,78 @@
@import <AppKit/CPComboBox.j>
@import <AppKit/CPApplication.j>
@import <Foundation/Foundation.j>
@import "CPNotificationCenterHelper.j"
[CPApplication sharedApplication];
@implementation CPComboBoxTest : OJTestCase
{
CPComboBox comboBox;
BOOL wasClicked
}
- (void)setUp
{
comboBox = [[CPComboBox alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];
}
- (void)testCanCreate
{
[self assertTrue:!!comboBox];
}
- (void)testPublicAccessors
{
[comboBox setHasVerticalScroller:YES];
[comboBox setIntercellSpacing:CGSizeMakeZero()];
[comboBox setButtonBordered:YES];
[comboBox setItemHeight:30];
[comboBox setNumberOfVisibleItems:10];
}
- (void)testPerformClick
{
[comboBox setTarget:self];
[comboBox setAction:@selector(clickMe:)];
[comboBox performClick:nil];
[self assertTrue:wasClicked];
}
- (void)clickMe:(id)sender
{
wasClicked = YES;
}
- (void)testNotificationsRegistered
{
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:[] message:@"Notications registered for the CPComboBox in the notification center are wrong"];
[comboBox setListDelegate:[[_CPPopUpList alloc] initWithDataSource:comboBox]];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:[] message:@"Notications registered for the CPComboBox in the notification center are wrong"];
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0.0, 0.0, 1024.0, 768.0)
styleMask:CPWindowNotSizable];
[[theWindow contentView] addSubview:comboBox];
var expectedNotifications = [@"_CPPopUpListWillPopUpNotification", @"_CPPopUpListWillDismissNotification", @"_CPPopUpListDidDismissNotification", @"_CPPopUpListItemWasClickedNotification", @"CPTableViewSelectionIsChangingNotification", @"CPTableViewSelectionDidChangeNotification"].sort();
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:expectedNotifications message:@"Notications registered for the CPComboBox in the notification center are wrong"];
[comboBox removeFromSuperview];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:[] message:@"Notications registered for the CPComboBox in the notification center are wrong"];
[[theWindow contentView] addSubview:comboBox];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:expectedNotifications message:@"Notications registered for the CPComboBox in the notification center are wrong"];
[[theWindow contentView] addSubview:comboBox];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:expectedNotifications message:@"Notications registered for the CPComboBox in the notification center are wrong"];
[comboBox setListDelegate:nil];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:[] message:@"Notications registered for the CPComboBox in the notification center are wrong"];
[comboBox setListDelegate:[[_CPPopUpList alloc] initWithDataSource:comboBox]];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:comboBox] equals:expectedNotifications message:@"Notications registered for the CPComboBox in the notification center are wrong"];
}
@end
+39
View File
@@ -0,0 +1,39 @@
@import <Foundation/Foundation.j>
@implementation CPNotificationCenterHelper : CPObject
{
}
+ (void)registeredNotificationsForObserver:(id)anObserver
{
var defaultCenter = [CPNotificationCenter defaultCenter],
names = [defaultCenter._namedRegistries keyEnumerator],
notifications = [],
name;
while ((name = [names nextObject]) !== nil)
{
var notificationRegistry = [defaultCenter._namedRegistries objectForKey:name],
objectObservers = notificationRegistry._objectObservers,
keys = [objectObservers keyEnumerator],
key;
// Iterate through every set of observers
while ((key = [keys nextObject]) !== nil)
{
var observers = [objectObservers objectForKey:key],
observer = nil,
observersEnumerator = [observers objectEnumerator];
while ((observer = [observersEnumerator nextObject]) !== nil)
{
if ([observer observer] == anObserver)
[notifications addObject:name];
}
}
}
return notifications.sort();
}
@end
+22
View File
@@ -1,5 +1,9 @@
@import <AppKit/AppKit.j>
@import "CPNotificationCenterHelper.j"
[CPApplication sharedApplication];
@implementation CPScrollViewTest : OJTestCase
{
}
@@ -256,6 +260,24 @@
[self assertPoint:CGPointMake(0, 0) equals:visibleRect.origin message:@"VisibleRect origin not at top left corner again"];
}
-(void)testNotificationsRegistered
{
var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)],
theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0.0, 0.0, 1024.0, 768.0)
styleMask:CPWindowNotSizable];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[] message:@"Notications registered for the scrollView in the notification center are wrong"];
[[theWindow contentView] addSubview:scrollView];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[@"CPScrollerStyleGlobalChangeNotification"] message:@"Notications registered for the scrollView in the notification center are wrong"];
[[theWindow contentView] addSubview:scrollView];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[@"CPScrollerStyleGlobalChangeNotification"] message:@"Notications registered for the scrollView in the notification center are wrong"];
[scrollView removeFromSuperview];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:scrollView] equals:[] message:@"Notications registered for the scrollView in the notification center are wrong"];
}
- (void)assertPoint:(CGPoint)expected equals:(CGPoint)actual message:(CPString)message
{
[self assert:expected.x equals:actual.x message:@"X: " + message];
+32
View File
@@ -1,5 +1,7 @@
@import <AppKit/AppKit.j>
@import "CPNotificationCenterHelper.j"
[CPApplication sharedApplication];
@implementation CPTableViewTest : OJTestCase
@@ -303,6 +305,36 @@
[self assertTrue:[table bounds].size.width >= 200];
}
-(void)testNotificationsRegistered
{
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[@"_CPWindowDidChangeFirstResponderNotification"] message:@"Notications registered for the tableView in the notification center are wrong"];
[tableView removeFromSuperview];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[] message:@"Notications registered for the tableView in the notification center are wrong"];
[[theWindow contentView] addSubview:tableView];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[@"_CPWindowDidChangeFirstResponderNotification"] message:@"Notications registered for the tableView in the notification center are wrong"];
[[theWindow contentView] addSubview:tableView];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[@"_CPWindowDidChangeFirstResponderNotification"] message:@"Notications registered for the tableView in the notification center are wrong"];
var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, 100.0, 100.0)],
expectedNotifications = [@"_CPWindowDidChangeFirstResponderNotification", @"CPViewFrameDidChangeNotification", @"CPViewBoundsDidChangeNotification"].sort();
[scrollView setDocumentView:tableView];
[[theWindow contentView] addSubview:scrollView];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:expectedNotifications message:@"Notications registered for the tableView in the notification center are wrong"];
[[theWindow contentView] addSubview:scrollView];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:expectedNotifications message:@"Notications registered for the tableView in the notification center are wrong"];
[scrollView removeFromSuperview];
[self assert:[CPNotificationCenterHelper registeredNotificationsForObserver:tableView] equals:[] message:@"Notications registered for the tableView in the notification center are wrong"];
}
@end
@implementation FirstResponderConfigurableTableView : CPTableView
+8
View File
@@ -128,4 +128,12 @@
[self assertTrue:[[[self window] representedURL] class] === [CPURL class]];
}
- (void)testOrderingMethod
{
[_window orderFront:self];
[_window orderBack:self];
[_window orderFront:self];
[_window orderOut:self];
}
@end
+43
View File
@@ -0,0 +1,43 @@
@import <Foundation/CPError.j>
@import <OJUnit/OJTestCase.j>
@implementation CPErrorTest : OJTestCase
{
}
- (void)testInstanceInstantiation
{
var err = [[CPError alloc] initWithDomain:CPCappuccinoErrorDomain
code:-10
userInfo:nil];
[self assertNotNull:err];
}
- (void)testClassInstantiation
{
var err = [CPError errorWithDomain:CPCappuccinoErrorDomain
code:-10
userInfo:nil];
[self assertNotNull:err];
}
- (void)testUserInfoDict
{
var userInfo = @{
CPLocalizedDescriptionKey: @"A localized error description",
CPUnderlyingErrorKey: @"An underlying error",
CPLocalizedFailureReasonErrorKey: @"A localized error reason",
CPLocalizedRecoverySuggestionErrorKey: @"The world is about to explode. You can choose to ignore this.",
CPLocalizedRecoveryOptionsErrorKey: ["Cry", "Ignore"]
},
err = [CPError errorWithDomain:CPCappuccinoErrorDomain
code:-10
userInfo:userInfo];
[self assertNotNull:[err userInfo]];
[self assert:[err localizedDescription] equals:@"A localized error description"];
[self assert:[err localizedRecoveryOptions] equals:["Cry", "Ignore"]];
[self assertNull:[err recoveryAttempter]];
}
@end
+50
View File
@@ -16,6 +16,33 @@ globalResults = [];
@end
@implementation TestCancelOperation : CPOperation
{
BOOL _started @accessors(getter=didStart);
BOOL _mained @accessors(getter=didMain);
}
- (id)init
{
self = [super init];
_started = NO;
_mained = NO;
return self;
}
- (void)main
{
_mained = YES;
}
- (void)start
{
[super start];
_started = YES;
}
@end
@implementation TestObserver : CPObject
{
CPArray changedKeyPaths @accessors;
@@ -167,4 +194,27 @@ globalResults = [];
[self assert:@"name" equals:[[obs changedKeyPaths] objectAtIndex:4]];
}
- (void)testCancelledOperationDoesStart
{
var op = [[TestCancelOperation alloc] init],
queue = [[CPOperationQueue alloc] init];
[self assertFalse:[op isCancelled]];
[self assertFalse:[op isFinished]];
[self assertFalse:[op didMain]];
[self assertFalse:[op didStart]];
[op cancel];
[self assertTrue:[op isCancelled]];
[self assertFalse:[op isFinished]];
[queue addOperations:[op] waitUntilFinished:YES];
[self assertFalse:[op didMain]];
[self assertTrue:[op didStart]];
[self assertTrue:[op isCancelled]];
[self assertTrue:[op isFinished]];
}
@end
+17
View File
@@ -180,4 +180,21 @@
[self assert:@"isCancelled" equals:[[obs changedKeyPaths] objectAtIndex:9]];
}
- (void)testCancelledOperationIsFinished
{
var results = @[],
funcOp = [CPFunctionOperation functionOperationWithFunction:function() {[results addObject:"funcOp"];}];
[funcOp cancel];
[self assertTrue:[funcOp isCancelled]];
[self assertFalse:[funcOp isFinished]];
[funcOp start];
[self assertTrue:[funcOp isCancelled]];
[self assertTrue:[funcOp isFinished]];
[self assertTrue:([results count] == 0)];
}
@end
+60
View File
@@ -0,0 +1,60 @@
@import <OJUnit/OJTestCase.j>
@implementation CFErrorTest : OJTestCase
- (void)testCreate
{
var err = new CFError();
[self assertNotNull:err];
}
- (void)testCreateWithParams
{
var err = new CFError(kCFErrorDomainCappuccino, -1000, nil);
[self assertNotNull:err];
[self assert:-1000 equals:err.code()];
}
- (void)testCreateGlobal
{
var err = CFErrorCreate(kCFErrorDomainCappuccino, -1000, nil);
[self assertNotNull:err];
[self assert:kCFErrorDomainCappuccino equals:err.domain()];
[self assert:-1000 equals:err.code()];
[self assert:@"CPCappuccinoErrorDomain" equals:CFErrorGetDomain(err)];
}
- (void)testCreateWithUserInfoKeysAndValues
{
var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedDescriptionKey, kCFErrorDescriptionKey], [@"A localized description", @"An error description"], 2);
[self assertNotNull:err];
var info = err.userInfo();
[self assert:2 equals:info.count()];
}
- (void)testDescriptionCaseOne
{
// Description case 1: Localized Key set
var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedDescriptionKey], [@"A localized Description Key"], 1);
[self assert:@"A localized Description Key" equals:err.description()];
[self assert:@"A localized Description Key" equals:CFErrorCopyDescription(err)];
}
- (void)testDescriptionCaseTwo
{
// Case 2: Reason set; description generated
var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedFailureReasonKey], [@"A localized reason"], 1);
[self assert:@"The operation couldn\u2019t be completed. A localized reason" equals:err.description()];
}
- (void)testDescriptionCaseThree
{
// Case 3: Final fall-back.
var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorDescriptionKey], [@"A description key"], 1);
[self assert:@"The operation couldn\u2019t be completed. (error -1000 - A description key)" equals:err.description()];
}
@end
@@ -0,0 +1,11 @@
@implementation TC
{
id _control;
}
- (id)a
{
@ref(_control);
}
@end
@@ -0,0 +1,9 @@
{var the_class = objj_allocateClassPair(Nil, "TC"),
meta_class = the_class.isa;class_addIvars(the_class, [new objj_ivar("_control")]);objj_registerClassPair(the_class);
class_addMethods(the_class, [new objj_method(sel_getUid("a"), function $TC__a(self, _cmd)
{
function(__input) { if (arguments.length) return self._control = __input; return self._control; };
}
,["id"])]);
}
@@ -22,6 +22,7 @@ var FILENAMES = [
"Misc/regex-simple-char-classes",
"Misc/empty-loops",
"Misc/empty-statements",
"Misc/ref-self",
];
@implementation OutputTest : OJTestCase
@@ -102,7 +102,7 @@
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: -1000;
z-index: 0;
}
#cappuccino-body .container {
@@ -72,7 +72,7 @@
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: -1000;
z-index: 0;
}
#cappuccino-body .container {
@@ -102,7 +102,7 @@
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: -1000;
z-index: 0;
}
#cappuccino-body .container {
@@ -72,7 +72,7 @@
width: 100%;
/* Put it at the bottom of the stack so it doesn't interfere with UI */
z-index: -1000;
z-index: 0;
}
#cappuccino-body .container {