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

Conflicts:
	AppKit/CPRuleEditor/CPRuleEditor.j
This commit is contained in:
cacaodev committed 2012-04-26 15:38:30 +02:00
commit 3ab2ebf71f
367 files changed
+29845 -3410

No files matched your search

+7
View File
@@ -21,6 +21,7 @@
*/
@import "CALayer.j"
@import "CPAccordionView.j"
@import "CPAlert.j"
@import "CPAnimation.j"
@import "CPApplication.j"
@@ -37,14 +38,18 @@
@import "CPCibControlConnector.j"
@import "CPCibLoading.j"
@import "CPCibOutletConnector.j"
@import "CPCibRuntimeAttributesConnector.j"
@import "CPCibHelpConnector.j"
@import "CPClipView.j"
@import "CPCollectionView.j"
@import "CPCollectionViewItem.j"
@import "CPColor.j"
@import "CPColorPanel.j"
@import "CPColorSpace.j"
@import "CPColorWell.j"
@import "CPCompatibility.j"
@import "CPControl.j"
@import "CPController.j"
@import "CPCookie.j"
@import "CPCursor.j"
@import "CPDocument.j"
@@ -55,6 +60,7 @@
@import "CPFont.j"
@import "CPFontManager.j"
@import "CPGeometry.j"
@import "CPGradient.j"
@import "CPGraphics.j"
@import "CPImage.j"
@import "CPImageView.j"
@@ -99,5 +105,6 @@
@import "CPViewAnimation.j"
@import "CPViewController.j"
@import "CPWebView.j"
@import "CPWorkspace.j"
@import "CPWindow.j"
@import "CPWindowController.j"
+11 -11
View File
@@ -117,21 +117,21 @@ CPCriticalAlertStyle = 2;
*/
+ (CPAlert)alertWithMessageText:(CPString)aMessage defaultButton:(CPString)defaultButtonTitle alternateButton:(CPString)alternateButtonTitle otherButton:(CPString)otherButtonTitle informativeTextWithFormat:(CPString)informativeText
{
var alert = [[self alloc] init];
var newAlert = [[self alloc] init];
[alert setMessageText:aMessage];
[alert addButtonWithTitle:defaultButtonTitle];
[newAlert setMessageText:aMessage];
[newAlert addButtonWithTitle:defaultButtonTitle];
if (alternateButtonTitle)
[alert addButtonWithTitle:alternateButtonTitle];
[newAlert addButtonWithTitle:alternateButtonTitle];
if (otherButtonTitle)
[alert addButtonWithTitle:otherButtonTitle];
[newAlert addButtonWithTitle:otherButtonTitle];
if (informativeText)
[alert setInformativeText:informativeText];
[newAlert setInformativeText:informativeText];
return alert;
return newAlert;
}
/*!
@@ -142,12 +142,12 @@ CPCriticalAlertStyle = 2;
*/
+ (CPAlert)alertWithError:(CPString)anErrorMessage
{
var alert = [[self alloc] init];
var newAlert = [[self alloc] init];
[alert setMessageText:anErrorMessage];
[alert setAlertStyle:CPCriticalAlertStyle];
[newAlert setMessageText:anErrorMessage];
[newAlert setAlertStyle:CPCriticalAlertStyle];
return alert;
return newAlert;
}
/*!
+1
View File
@@ -122,6 +122,7 @@ ACTUAL_FRAME_RATE = 0;
*/
- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve
{
var timingFunctionName;
switch (anAnimationCurve)
{
case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut;
+42 -9
View File
@@ -564,7 +564,7 @@
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
{
[self _selectionWillChange]
var r = [self __setSelectionIndexes:indexes];
var r = [self __setSelectionIndexes:indexes avoidEmpty:NO];
[self _selectionDidChange];
return r;
}
@@ -583,6 +583,11 @@
@ignore
*/
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes
{
[self __setSelectionIndexes:indexes avoidEmpty:_avoidsEmptySelection];
}
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes avoidEmpty:(BOOL)avoidEmpty
{
var newIndexes = indexes;
@@ -591,7 +596,7 @@
if (![newIndexes count])
{
if (_avoidsEmptySelection && [[self arrangedObjects] count])
if (avoidEmpty && [[self arrangedObjects] count])
newIndexes = [CPIndexSet indexSetWithIndex:0];
}
else
@@ -606,7 +611,7 @@
// Remove out of bounds indexes.
[newIndexes removeIndexesInRange:CPMakeRange(objectsCount, [newIndexes lastIndex] + 1)];
// When avoiding empty selection and the deleted selection was at the bottom, select the last item.
if (![newIndexes count] && _avoidsEmptySelection && objectsCount)
if (![newIndexes count] && avoidEmpty && objectsCount)
newIndexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
}
@@ -647,7 +652,7 @@
[self willChangeValueForKey:@"selectionIndexes"];
[self _selectionWillChange];
var r = [self __setSelectedObjects:objects];
var r = [self __setSelectedObjects:objects avoidEmpty:NO];
[self didChangeValueForKey:@"selectionIndexes"];
[self _selectionDidChange];
@@ -659,6 +664,11 @@
@ignore
*/
- (BOOL)__setSelectedObjects:(CPArray)objects
{
[self __setSelectedObjects:objects avoidEmpty:_avoidsEmptySelection];
}
- (BOOL)__setSelectedObjects:(CPArray)objects avoidEmpty:(BOOL)avoidEmpty
{
var set = [CPIndexSet indexSet],
count = [objects count],
@@ -672,7 +682,7 @@
[set addIndex:index];
}
[self __setSelectionIndexes:set];
[self __setSelectionIndexes:set avoidEmpty:avoidEmpty];
return YES;
}
@@ -1066,22 +1076,45 @@
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
isCompound = [self handlesContentAsCompoundValue];
isCompound = [self handlesContentAsCompoundValue],
dotIndex = keyPath.lastIndexOf("."),
firstPart = dotIndex !== CPNotFound ? keyPath.substring(0, dotIndex) : nil,
isSelectionProxy = firstPart && [[destination valueForKeyPath:firstPart] isKindOfClass:CPControllerSelectionProxy];
if (!isCompound)
if (!isCompound && !isSelectionProxy)
{
newValue = [destination mutableArrayValueForKeyPath:keyPath];
}
else
{
// handlesContentAsCompoundValue == YES so we cannot just set up a proxy.
// 1. If handlesContentAsCompoundValue we cannot just set up a proxy.
// Every read and every write must go through transformValue and
// reverseTransformValue, and the resulting object cannot be described by
// a key path.
// 2. If isSelectionProxy, we don't want to proxy a proxy - that's bad
// for performance and won't work with markers.
newValue = [destination valueForKeyPath:keyPath];
}
newValue = [self transformValue:newValue withOptions:options];
var isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
if (newValue === CPNotApplicableMarker && [options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
{
[CPException raise:CPGenericException
reason:@"can't transform non applicable key on: " + _source + " value: " + newValue];
}
newValue = [self _placeholderForMarker:newValue];
// This seems to be what Cocoa does.
if (!newValue)
newValue = [CPMutableArray array];
}
else
newValue = [self transformValue:newValue withOptions:options];
if (isCompound)
{
+1 -2
View File
@@ -20,7 +20,6 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright 2009 280 North, Inc.
*/
@import <Foundation/CPObject.j>
@@ -276,7 +275,7 @@ var DefaultLineWidth = 1.0;
/*!
Append the contents of a CPBezierPath object.
*/
- (void)appendBezierPath:(NSBezierPath *)other
- (void)appendBezierPath:(CPBezierPath)other
{
CGPathAddPath(_path, nil, other._path);
}
+129 -7
View File
@@ -35,6 +35,16 @@ CPLineBorder = 1;
CPBezelBorder = 2;
CPGrooveBorder = 3;
// CPTitlePosition
CPNoTitle = 0;
CPAboveTop = 1;
CPAtTop = 2;
CPBelowTop = 3;
CPAboveBottom = 4;
CPAtBottom = 5;
CPBelowBottom = 6;
/*!
@ingroup appkit
@class CPBox
@@ -54,6 +64,10 @@ CPGrooveBorder = 3;
CPSize _contentMargin;
CPView _contentView;
CPString _title @accessors(getter=title);
int _titlePosition @accessors(getter=titlePosition);
CPTextField _titleView;
}
+ (id)boxEnclosingView:(CPView)aView
@@ -61,7 +75,7 @@ CPGrooveBorder = 3;
var box = [[self alloc] initWithFrame:CGRectMakeZero()],
enclosingView = [aView superview];
[box setAutoresizingMask:[aView autoresizingMask]];
[box setAutoresizingMask:[aView autoresizingMask]];
[box setFrameFromContentFrame:[aView frame]];
[enclosingView replaceSubview:aView with:box];
@@ -84,6 +98,9 @@ CPGrooveBorder = 3;
_borderWidth = 1.0;
_contentMargin = CGSizeMake(0.0, 0.0);
_titlePosition = CPNoTitle;
_titleView = [CPTextField labelWithTitle:@""];
_contentView = [[CPView alloc] initWithFrame:[self bounds]];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
@@ -278,18 +295,100 @@ CPGrooveBorder = 3;
- (void)setFrameFromContentFrame:(CPRect)aRect
{
[self setFrame:CGRectInset(aRect, -(_contentMargin.width + _borderWidth), -(_contentMargin.height + _borderWidth))];
var offset = [self _titleHeightOffset];
[self setFrame:CGRectInset(aRect, -(_contentMargin.width + _borderWidth), -(_contentMargin.height + offset[0] + _borderWidth))];
[self setNeedsDisplay:YES];
}
- (void)setTitle:(CPString)aTitle
{
if (aTitle == _title)
return;
_title = aTitle;
[self _manageTitlePositioning];
}
- (void)setTitlePosition:(int)aTitlePotisition
{
if (aTitlePotisition == _titlePosition)
return;
_titlePosition = aTitlePotisition;
[self _manageTitlePositioning];
}
- (void)_manageTitlePositioning
{
if (_titlePosition == CPNoTitle)
{
[_titleView removeFromSuperview];
[self setNeedsDisplay:YES];
return;
}
[_titleView setStringValue:_title];
[_titleView sizeToFit];
[self addSubview:_titleView];
switch (_titlePosition)
{
case CPAtTop:
case CPAboveTop:
case CPBelowTop:
[_titleView setFrameOrigin:CPPointMake(5.0, 0.0)];
[_titleView setAutoresizingMask:CPViewNotSizable];
break;
case CPAboveBottom:
case CPAtBottom:
case CPBelowBottom:
var h = [_titleView frameSize].height;
[_titleView setFrameOrigin:CPPointMake(5.0, [self frameSize].height - h)];
[_titleView setAutoresizingMask:CPViewMinYMargin];
break;
}
[self sizeToFit];
[self setNeedsDisplay:YES];
}
- (void)sizeToFit
{
var contentFrame = [_contentView frame];
var contentFrame = [_contentView frame],
offset = [self _titleHeightOffset];
if (!contentFrame)
return;
[_contentView setAutoresizingMask:CPViewNotSizable];
[self setFrameSize:CGSizeMake(contentFrame.size.width + _contentMargin.width * 2,
contentFrame.size.height + _contentMargin.height * 2)];
contentFrame.size.height + _contentMargin.height * 2 + offset[0])];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height)];
[_contentView setFrameOrigin:CGPointMake(_contentMargin.width, _contentMargin.height + offset[1])];
}
- (float)_titleHeightOffset
{
if (_titlePosition == CPNoTitle)
return [0.0, 0.0];
switch (_titlePosition)
{
case CPAtTop:
return [[_titleView frameSize].height, [_titleView frameSize].height];
case CPAtBottom:
return [[_titleView frameSize].height, 0.0];
default:
return [0.0, 0.0];
}
}
- (void)drawRect:(CPRect)rect
@@ -297,7 +396,7 @@ CPGrooveBorder = 3;
if (_borderType === CPNoBorder)
return;
var bounds = [self bounds];
var bounds = CGRectMakeCopy([self bounds]);
switch (_boxType)
{
@@ -312,6 +411,16 @@ CPGrooveBorder = 3;
break;
}
if (_titlePosition == CPAtTop)
{
bounds.origin.y += [_titleView frameSize].height;
bounds.size.height -= [_titleView frameSize].height;
}
if (_titlePosition == CPAtBottom)
{
bounds.size.height -= [_titleView frameSize].height;
}
switch (_borderType)
{
case CPBezelBorder:
@@ -386,7 +495,10 @@ var CPBoxTypeKey = @"CPBoxTypeKey",
CPBoxFillColorKey = @"CPBoxFillColorKey",
CPBoxCornerRadiusKey = @"CPBoxCornerRadiusKey",
CPBoxBorderWidthKey = @"CPBoxBorderWidthKey",
CPBoxContentMarginKey = @"CPBoxContentMarginKey";
CPBoxContentMarginKey = @"CPBoxContentMarginKey",
CPBoxTitle = @"CPBoxTitle",
CPBoxTitlePosition = @"CPBoxTitlePosition",
CPBoxTitleView = @"CPBoxTitleView";
@implementation CPBox (CPCoding)
@@ -407,10 +519,16 @@ var CPBoxTypeKey = @"CPBoxTypeKey",
_contentMargin = [aCoder decodeSizeForKey:CPBoxContentMarginKey];
_title = [aCoder decodeObjectForKey:CPBoxTitle];
_titlePosition = [aCoder decodeIntForKey:CPBoxTitlePosition];
_titleView = [aCoder decodeObjectForKey:CPBoxTitleView] || [CPTextField labelWithTitle:_title];
_contentView = [self subviews][0];
[self setAutoresizesSubviews:YES];
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[self _manageTitlePositioning];
}
return self;
@@ -429,6 +547,10 @@ var CPBoxTypeKey = @"CPBoxTypeKey",
[aCoder encodeFloat:_cornerRadius forKey:CPBoxCornerRadiusKey];
[aCoder encodeFloat:_borderWidth forKey:CPBoxBorderWidthKey];
[aCoder encodeObject:_title forKey:CPBoxTitle];
[aCoder encodeInt:_titlePosition forKey:CPBoxTitlePosition];
[aCoder encodeObject:_titleView forKey:CPBoxTitleView];
[aCoder encodeSize:_contentMargin forKey:CPBoxContentMarginKey];
}
+2 -2
View File
@@ -258,7 +258,7 @@
var column = [[CPTableColumn alloc] initWithIdentifier:@"Image"],
view = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
[view setImageScaling:CPScaleProportionally];
[view setImageScaling:CPImageScaleProportionallyDown];
[column setDataView:view];
[column setResizingMask:CPTableColumnNoResizing];
@@ -988,7 +988,7 @@ var _CPBrowserResizeControlBackgroundImage = nil;
isHighlighted = [self themeState] & CPThemeStateSelectedDataView;
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
[imageView setImageScaling:CPScaleNone];
[imageView setImageScaling:CPImageScaleNone];
}
- (void)encodeWithCoder:(CPCoder)aCoder
+19 -21
View File
@@ -141,9 +141,9 @@ CPButtonImageOffset = 3.0;
}
/*!
Initializes and returns a newly allocated CPButton object with a specified frame rectangle.
@param aFrame The frame rectangle for the created button object.
@return An initialized CPView object or nil if the object couldn't be created.
Initializes and returns a newly allocated CPButton object with a specified frame rectangle.
@param aFrame The frame rectangle for the created button object.
@return An initialized CPView object or nil if the object couldn't be created.
*/
- (id)initWithFrame:(CGRect)aFrame
{
@@ -155,7 +155,7 @@ CPButtonImageOffset = 3.0;
[self setValue:CPCenterTextAlignment forThemeAttribute:@"alignment"];
[self setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
[self setValue:CPScaleNone forThemeAttribute:@"image-scaling"];
[self setValue:CPImageScaleNone forThemeAttribute:@"image-scaling"];
[self setBezelStyle:CPRoundRectBezelStyle];
[self setBordered:YES];
@@ -180,7 +180,7 @@ CPButtonImageOffset = 3.0;
// Setting the state
/*!
Returns a Boolean value indicating whether the button allows a mixed state.
Returns a Boolean value indicating whether the button allows a mixed state.
@return \c YES if the button has a 'mixed' state in addition to on and off.
*/
- (BOOL)allowsMixedState
@@ -206,8 +206,8 @@ CPButtonImageOffset = 3.0;
}
/*!
Sets the value of the button using an Objective-J object.
@param anObjectValue The value of the button interpreted as an Objective-J object.
Sets the value of the button using an Objective-J object.
@param anObjectValue The value of the button interpreted as an Objective-J object.
*/
- (void)setObjectValue:(id)anObjectValue
{
@@ -244,11 +244,11 @@ CPButtonImageOffset = 3.0;
}
/*!
Returns the button's next state.
@return The button's state. A button can have two or three states.
If it has two, this value is either \c CPOffState (the normal or unpressed state)
or \c CPOnState (the alternate or pressed state).
If it has three, this value can be \c CPOnState (the feature is in effect everywhere), \c CPOffState (the feature is in effect nowhere), or \c CPMixedState (the feature is in effect somewhere).
Returns the button's next state.
@return The button's state. A button can have two or three states.
If it has two, this value is either \c CPOffState (the normal or unpressed state)
or \c CPOnState (the alternate or pressed state).
If it has three, this value can be \c CPOnState (the feature is in effect everywhere), \c CPOffState (the feature is in effect nowhere), or \c CPMixedState (the feature is in effect somewhere).
*/
- (CPInteger)nextState
{
@@ -294,9 +294,9 @@ CPButtonImageOffset = 3.0;
}
/*!
Sets the title displayed by the button when in its normal state.
@param aTitle The string to set as the button's title. This title is always shown on buttons
that don’t use their alternate contents when highlighting or displaying their alternate state.
Sets the title displayed by the button when in its normal state.
@param aTitle The string to set as the button's title. This title is always shown on buttons
that don’t use their alternate contents when highlighting or displaying their alternate state.
*/
- (void)setTitle:(CPString)aTitle
{
@@ -310,9 +310,9 @@ CPButtonImageOffset = 3.0;
}
/*!
Returns the title displayed on the button when it’s in its normal state.
@return The title displayed on the receiver when it’s in its normal state
or the empty string if the button doesn’t display a title.
Returns the title displayed on the button when it’s in its normal state.
@return The title displayed on the receiver when it’s in its normal state
or the empty string if the button doesn’t display a title.
*/
- (CPString)title
{
@@ -802,9 +802,7 @@ var CPButtonImageKey = @"CPButtonImageKey",
_title = [aCoder decodeObjectForKey:CPButtonTitleKey];
_alternateTitle = [aCoder decodeObjectForKey:CPButtonAlternateTitleKey];
if ([aCoder containsValueForKey:CPButtonAllowsMixedStateKey])
_allowsMixedState = [aCoder decodeBoolForKey:CPButtonAllowsMixedStateKey];
_allowsMixedState = [aCoder decodeBoolForKey:CPButtonAllowsMixedStateKey];
[self setImageDimsWhenDisabled:[aCoder decodeObjectForKey:CPButtonImageDimsWhenDisabledKey]];
+15 -38
View File
@@ -100,48 +100,25 @@ CPCheckBoxImageOffset = 4.0;
{
}
- (void)setValueFor:(CPString)theBinding
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
[super _updatePlaceholdersWithOptions:options];
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = CPMixedState;
break;
[self _setPlaceholder:CPMixedState forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:CPOffState forMarker:CPNoSelectionMarker isDefault:YES];
[self _setPlaceholder:CPOffState forMarker:CPNotApplicableMarker isDefault:YES];
[self _setPlaceholder:CPOffState forMarker:CPNullMarker isDefault:YES];
}
case CPNoSelectionMarker:
newValue = CPOffState;
break;
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setAllowsMixedState:(aValue === CPMixedState)];
[_source setState:aValue];
}
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = CPOffState;
break;
}
if (newValue === CPMixedState)
{
[_source setAllowsMixedState:YES];
}
else
{
// Cocoa will always set allowsMixedState to NO
// This behavior will be fine for Cappuccino as well if we (like Cocoa)
// default the CPConditionallySetsEnabledBindingOption to YES
[_source setAllowsMixedState:NO];
}
}
[_source setState:newValue];
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source setState:aValue];
}
@end
+27 -15
View File
@@ -40,23 +40,23 @@
@par Delegate Methods
@delegate -(void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
@delegate - (void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
Called when the selection in the collection view has changed.
@param collectionView the collection view who's selection changed
@delegate -(void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
@delegate - (void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
Called when the user double-clicks on an item in the collection view.
@param collectionView the collection view that received the double-click
@param index the index of the item that received the double-click
@delegate -(CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
@delegate - (CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
Invoked to obtain data for a set of indices.
@param collectionView the collection view to obtain data for
@param indices the indices to return data for
@param aType the data type
@return a data object containing the index items
@delegate -(CPArray)collectionView:(CPCollectionView)collectionView dragTypesForItemsAtIndexes:(CPIndexSet)indices;
@delegate - (CPArray)collectionView:(CPCollectionView)collectionView dragTypesForItemsAtIndexes:(CPIndexSet)indices;
Invoked to obtain the data types supported by the specified indices for placement on the pasteboard.
@param collectionView the collection view the items reside in
@param indices the indices to obtain drag types
@@ -340,19 +340,21 @@
*/
- (void)setSelectionIndexes:(CPIndexSet)anIndexSet
{
if ([_selectionIndexes isEqual:anIndexSet] || !_isSelectable)
if (!anIndexSet)
anIndexSet = [CPIndexSet indexSet];
if (!_isSelectable || [_selectionIndexes isEqual:anIndexSet])
return;
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) !== CPNotFound)
[_items[index] setSelected:NO];
_selectionIndexes = anIndexSet;
var index = CPNotFound;
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) !== CPNotFound)
[_items[index] setSelected:YES];
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
@@ -473,7 +475,7 @@
}
var superview = [self superview],
proposedHeight = y + itemSize.height + _verticalMargin;
proposedHeight = y + itemSize.height + _verticalMargin;
if ([superview isKindOfClass:[CPClipView class]])
{
@@ -559,6 +561,8 @@
*/
- (void)setMinItemSize:(CGSize)aSize
{
if (aSize === nil || aSize === undefined)
[CPException raise:CPInvalidArgumentException reason:"Invalid value provided for minimum size"];
if (CGSizeEqualToSize(_minItemSize, aSize))
return;
@@ -665,6 +669,13 @@
indexes = [CPIndexSet indexSetWithIndex:index];
[self setSelectionIndexes:indexes];
// TODO Is it allowable for collection view items to become the first responder? In that case they
// may have become that at this point by virtue of CPWindow's sendEvent: mouse down handling, and
// the following line will rudely snatch it away from them. For most cases though, clicking on an
// item should naturally make the collection view the first responder so that keyboard navigation
// is enabled.
[[self window] makeFirstResponder:self];
}
else if (_allowsEmptySelection)
[self setSelectionIndexes:[CPIndexSet indexSet]];
@@ -965,14 +976,15 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
{
[super awakeFromCib];
if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()) || CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
var prototypeView = [_itemPrototype view];
if (prototypeView && (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()) || CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero())))
{
var item = _itemPrototype;
if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
_minItemSize = [[item view] frameSize];
_minItemSize = [prototypeView frameSize];
else if (CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
_maxItemSize = [[item view] frameSize];
_maxItemSize = [prototypeView frameSize];
}
}
@@ -989,11 +1001,11 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
_itemSize = CGSizeMakeZero();
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey];
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey];
_maxNumberOfRows = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfRowsKey] || 0;
_maxNumberOfColumns = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfColumnsKey] || 0;
_maxNumberOfRows = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfRowsKey];
_maxNumberOfColumns = [aCoder decodeIntForKey:CPCollectionViewMaxNumberOfColumnsKey];
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
+20 -9
View File
@@ -133,7 +133,7 @@ function CPColorWithImages()
}
/*!
Creates a color in the RGB color space, with an alpha value.
Creates a color in the RGB colorspace, with an alpha value.
Each component should be between the range of 0.0 to 1.0. For
the alpha component, a value of 1.0 is opaque, and 0.0 means
completely transparent.
@@ -147,13 +147,13 @@ function CPColorWithImages()
*/
+ (CPColor)colorWithRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
{
return [[CPColor alloc] _initWithRGBA:[red, green, blue, alpha]];
return [[CPColor alloc] _initWithRGBA:[MAX(0.0, MIN(1.0, red)), MAX(0.0, MIN(1.0, green)), MAX(0.0, MIN(1.0, blue)), MAX(0.0, MIN(1.0, alpha))]];
}
/*!
@deprecated in favor of colorWithRed:green:blue:alpha:
Creates a color in the RGB color space, with an alpha value.
Creates a color in the RGB colorspace, with an alpha value.
Each component should be between the range of 0.0 to 1.0. For
the alpha component, a value of 1.0 is opaque, and 0.0 means
completely transparent.
@@ -228,12 +228,12 @@ function CPColorWithImages()
switch (FLOOR(hue / 60))
{
case 0: return [CPColor colorWithCalibratedRed: b green: t blue: p alpha: alpha];
case 1: return [CPColor colorWithCalibratedRed: q green: b blue: p alpha: alpha];
case 2: return [CPColor colorWithCalibratedRed: p green: b blue: t alpha: alpha];
case 3: return [CPColor colorWithCalibratedRed: p green: q blue: b alpha: alpha];
case 4: return [CPColor colorWithCalibratedRed: t green: p blue: b alpha: alpha];
case 5: return [CPColor colorWithCalibratedRed: b green: p blue: q alpha: alpha];
case 0: return [CPColor colorWithCalibratedRed:b green:t blue:p alpha:alpha];
case 1: return [CPColor colorWithCalibratedRed:q green:b blue:p alpha:alpha];
case 2: return [CPColor colorWithCalibratedRed:p green:b blue:t alpha:alpha];
case 3: return [CPColor colorWithCalibratedRed:p green:q blue:b alpha:alpha];
case 4: return [CPColor colorWithCalibratedRed:t green:p blue:b alpha:alpha];
case 5: return [CPColor colorWithCalibratedRed:b green:p blue:q alpha:alpha];
}
}
@@ -253,6 +253,17 @@ function CPColorWithImages()
return rgba ? [[CPColor alloc] _initWithRGBA: rgba] : null;
}
/*!
Creates a color in the sRGB colorspace with the given components and alpha values.
Values below 0.0 are treated as 0.0 and values above 1.0 are treated as 1.0.
*/
+ (CPColor)colorWithSRGBRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
{
// TODO If Cappuccino is ported to a colorspace aware platform, this color should be in
// sRGBColorSpace.
return [self colorWithRed:red green:green blue:blue alpha:alpha];
}
/*!
Returns a black color object. (RGBA=[0.0, 0.0, 0.0, 1.0])
*/
+62
View File
@@ -0,0 +1,62 @@
/*
* CPColorSpace.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2012, SlevenBits Ltd.
*
* 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
*/
var sRGBColorSpace = nil;
/*!
Represent color spaces.
*/
@implementation CPColorSpace : CPObject
{
CGColorSpace _cgColorSpace;
}
/*!
Return an object representing the standard sRGB color space.
*/
+ (CPColorSpace)sRGBColorSpace
{
if (!sRGBColorSpace)
sRGBColorSpace = [[self alloc] initWithCGColorSpace:CGColorSpaceCreateDeviceRGB()];
return sRGBColorSpace;
}
- (id)initWithCGColorSpace:(CGColorSpace)cgColorSpace
{
if (self = [super init])
{
_cgColorSpace = cgColorSpace;
}
return self;
}
/*!
Return a Core Graphics color space representing the receiver.
*/
- (CGColorSpace)CGColorSpace
{
return _cgColorSpace;
}
@end
+58
View File
@@ -46,6 +46,22 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
CPView _wellView;
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding == CPValueBinding)
return [CPColorWellValueBinder class];
return [super _binderClassForBinding:theBinding];
}
- (void)_reverseSetBinding
{
var binderClass = [[self class] _binderClassForBinding:CPValueBinding],
theBinding = [binderClass getBinding:CPValueBinding forObject:self];
[theBinding reverseSetValueFor:@"color"];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -262,6 +278,48 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
@end
@implementation CPColorWellValueBinder : CPBinder
{
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
var placeholderColor = [CPColor blueColor];
[self _setPlaceholder:placeholderColor forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:placeholderColor forMarker:CPNoSelectionMarker isDefault:YES];
[self _setPlaceholder:placeholderColor forMarker:CPNotApplicableMarker isDefault:YES];
[self _setPlaceholder:placeholderColor forMarker:CPNullMarker isDefault:YES];
}
- (void)setValueFor:(CPString)theBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
if (isPlaceholder)
{
if (newValue === CPNotApplicableMarker && [options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
{
[CPException raise:CPGenericException
reason:@"can't transform non applicable key on: " + _source + " value: " + newValue];
}
newValue = [self _placeholderForMarker:newValue];
}
else
{
newValue = [self transformValue:newValue withOptions:options];
}
[_source setColor:newValue];
}
@end
var CPColorWellColorKey = "CPColorWellColorKey",
CPColorWellBorderedKey = "CPColorWellBorderedKey";
+40 -33
View File
@@ -28,42 +28,48 @@
@import "CPView.j"
@import "CPKeyValueBinding.j"
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
CPJustifiedTextAlignment = 3;
CPNaturalTextAlignment = 4;
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
CPJustifiedTextAlignment = 3;
CPNaturalTextAlignment = 4;
CPRegularControlSize = 0;
CPSmallControlSize = 1;
CPMiniControlSize = 2;
CPRegularControlSize = 0;
CPSmallControlSize = 1;
CPMiniControlSize = 2;
CPLineBreakByWordWrapping = 0;
CPLineBreakByCharWrapping = 1;
CPLineBreakByClipping = 2;
CPLineBreakByTruncatingHead = 3;
CPLineBreakByTruncatingTail = 4;
CPLineBreakByTruncatingMiddle = 5;
CPLineBreakByWordWrapping = 0;
CPLineBreakByCharWrapping = 1;
CPLineBreakByClipping = 2;
CPLineBreakByTruncatingHead = 3;
CPLineBreakByTruncatingTail = 4;
CPLineBreakByTruncatingMiddle = 5;
CPTopVerticalTextAlignment = 1;
CPCenterVerticalTextAlignment = 2;
CPBottomVerticalTextAlignment = 3;
CPTopVerticalTextAlignment = 1;
CPCenterVerticalTextAlignment = 2;
CPBottomVerticalTextAlignment = 3;
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
// Deprecated for use with images, use the CPImageScale constants
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
CPImageScaleProportionallyDown = 0;
CPImageScaleAxesIndependently = 1;
CPImageScaleNone = 2;
CPImageScaleProportionallyUpOrDown = 3;
CPOnState = 1;
CPOffState = 0;
CPMixedState = -1;
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
CPImageRight = 3;
CPImageBelow = 4;
CPImageAbove = 5;
CPImageOverlaps = 6;
CPOnState = 1;
CPOffState = 0;
CPMixedState = -1;
CPControlNormalBackgroundColor = "CPControlNormalBackgroundColor";
CPControlSelectedBackgroundColor = "CPControlSelectedBackgroundColor";
@@ -784,9 +790,10 @@ var CPControlBlackColor = [CPColor blackColor];
Sets the image scaling of the control.
<pre>
CPScaleProportionally
CPScaleToFit
CPScaleNone
CPImageScaleProportionallyDown
CPImageScaleAxesIndependently
CPImageScaleNone
CPImageScaleProportionallyUpOrDown
</pre>
*/
- (void)setImageScaling:(CPImageScaling)scaling
+11 -2
View File
@@ -179,7 +179,8 @@ CPDOMEventTouchCancel = "touchcancel";
var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil,
_CPEventUpperCaseRegex = new RegExp("[A-Z]");
_CPEventUpperCaseRegex = new RegExp("[A-Z]"),
_CPEventStartupMilliseconds = new Date().getTime();
/*!
@ingroup appkit
@@ -209,6 +210,14 @@ var _CPEventPeriodicEventPeriod = 0,
float _deltaZ;
}
/*!
Returns the current time in fractional seconds since startup.
*/
+ (CPTimeInterval)currentTimestamp
{
return (new Date().getTime() - _CPEventStartupMilliseconds) / 1000;
}
/*!
Creates a new keyboard event.
@@ -389,7 +398,7 @@ var _CPEventPeriodicEventPeriod = 0,
}
/*!
Returns the time the event occurred.
Returns the time the event occurred in seconds since startup.
*/
- (CPTimeInterval)timestamp
{
+5 -5
View File
@@ -104,10 +104,10 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
- (void)setFlashVars:(CPDictionary)aDictionary
{
var varString = @"",
enumerator = [aDictionary keyEnumerator];
enumerator = [aDictionary keyEnumerator],
key;
var key;
while (key = [enumerator nextObject])
while ((key = [enumerator nextObject]) !== nil)
varString = [varString stringByAppendingFormat:@"&%@=%@", key, [aDictionary objectForKey:key]];
if (!_params)
@@ -146,7 +146,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
var enumerator = [_params keyEnumerator],
key;
while (_DOMObjectElement && (key = [enumerator nextObject]))
while (_DOMObjectElement && (key = [enumerator nextObject]) !== nil)
{
var param = document.createElement(@"param");
param.name = key;
@@ -178,7 +178,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
paramEnumerator = [_params keyEnumerator],
key;
while (key = [paramEnumerator nextObject])
while ((key = [paramEnumerator nextObject]) !== nil)
paramString = [paramString stringByAppendingFormat:@"<param name='%@' value='%@' />", key, [_params objectForKey:key]];
_DOMObjectElement = document.createElement(@"object");
+8 -8
View File
@@ -142,7 +142,7 @@ var _CPFonts = {},
*/
+ (CPFont)fontWithName:(CPString)aName size:(float)aSize
{
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:NO];
return [CPFont fontWithName:aName size:aSize bold:NO italic:NO];
}
/*!
@@ -154,7 +154,7 @@ var _CPFonts = {},
*/
+ (CPFont)fontWithName:(CPString)aName size:(float)aSize italic:(BOOL)italic
{
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:italic];
return [CPFont fontWithName:aName size:aSize bold:NO italic:italic];
}
/*!
@@ -165,7 +165,7 @@ var _CPFonts = {},
*/
+ (CPFont)boldFontWithName:(CPString)aName size:(float)aSize
{
return _CPCachedFont(aName, aSize, YES, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:NO];
return [CPFont fontWithName:aName size:aSize bold:YES italic:NO];
}
/*!
@@ -177,7 +177,7 @@ var _CPFonts = {},
*/
+ (CPFont)boldFontWithName:(CPString)aName size:(float)aSize italic:(BOOL)italic
{
return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:italic];
return [CPFont fontWithName:aName size:aSize bold:YES italic:italic];
}
/*!
@@ -187,7 +187,7 @@ var _CPFonts = {},
*/
+ (CPFont)systemFontOfSize:(CPSize)aSize
{
return _CPCachedFont(_CPFontSystemFontFace, aSize, NO, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:NO italic:NO];
return [CPFont fontWithName:_CPFontSystemFontFace size:aSize bold:NO italic:NO];
}
/*!
@@ -197,15 +197,15 @@ var _CPFonts = {},
*/
+ (CPFont)boldSystemFontOfSize:(CPSize)aSize
{
return _CPCachedFont(_CPFontSystemFontFace, aSize, YES, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:YES italic:NO];
return [CPFont fontWithName:_CPFontSystemFontFace size:aSize bold:YES italic:NO];
}
/* FIXME Font Descriptor
@ignore
*/
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold
+ (CPFont)fontWithName:(CPString)aName size:(float)aSize bold:(BOOL)bold italic:(BOOL)italic
{
return [self _initWithName:aName size:aSize bold:isBold italic:NO];
return _CPCachedFont(aName, aSize, bold, italic) || [[CPFont alloc] _initWithName:aName size:aSize bold:bold italic:italic];
}
- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold italic:(BOOL)isItalic
+123
View File
@@ -0,0 +1,123 @@
/*
* CPGradient.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2012, SlevenBits Ltd.
*
* 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
*/
CPGradientDrawsBeforeStartingLocation = kCGGradientDrawsBeforeStartLocation;
CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation;
/*!
A class for drawing linear and radial gradients with a convenient API.
*/
@implementation CPGradient : CPObject
{
CGGradient _gradient;
}
- (id)initWithColors:(CPArray)someColors
{
var count = [someColors count];
if (count < 2)
[CPException raise:CPInvalidArgumentException reason:@"at least 2 colors required"];
var distance = 1.0 / (count - 1),
locations = [CPMutableArray array],
location = 0.0;
for (var i = 0; i < count; i++)
{
[locations addObject:location];
location += distance;
}
return [self initWithColors:someColors atLocations:locations colorSpace:nil];
}
- (id)initWithColors:(CPArray)someColors atLocations:(CPArray)someLocations colorSpace:(CPColorSpace)aColorSpace
{
if (self = [super init])
{
var cgColors = [],
count = [someColors count],
colorSpace = [aColorSpace CGColorSpace] || CGColorSpaceCreateDeviceRGB;
for (var i = 0; i < count; i++)
cgColors.push(CGColorCreate(colorSpace, [someColors[i] components]));
_gradient = CGGradientCreateWithColors(colorSpace, cgColors, someLocations);
}
return self;
}
- (void)drawInRect:(CGRect)rect angle:(float)angle
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(ctx);
CGContextClipToRect(ctx, rect);
CGContextAddRect(ctx, rect);
var startPoint,
endPoint;
// Modulo of negative values doesn't work as expected in JS.
angle = ((angle % 360.0) + 360.0) % 360.0;
if (angle < 90.0)
startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMinY(rect));
else if (angle < 180.0)
startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMinY(rect));
else if (angle < 270.0)
startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMaxY(rect));
else
startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMaxY(rect));
// A line segment comes out of the starting point at the given angle, with the first colour
// at the starting point and the last at the end. To do what drawInRect: is supposed to do
// we want the opposite corner of the starting corner to just reach the final colour stop.
// So when the angle isn't a right angle, the segment has to extend beyond the edge of the
// rectangle just far enough. This is hard to describe without a picture but if we place
// another line through the opposite corner at -90 degrees, it'll help form some triangles
// from which we can derive this formula:
//
// length = cos(angle) * (rectWidth + rectHeight * tan(angle))
//
// This simplifies down to (in the first quadrant) rectWidth * cos(a) + rectHeight * sin(a).
var radians = PI * angle / 180.0,
length = ABS(_CGRectGetWidth(rect) * COS(radians)) + ABS(_CGRectGetHeight(rect) * SIN(radians));
endPoint = _CGPointMake(startPoint.x + length * COS(radians),
startPoint.y + length * SIN(radians));
[self drawFromPoint:startPoint toPoint:endPoint options:CPGradientDrawsBeforeStartingLocation | CPGradientDrawsAfterEndingLocation];
CGContextRestoreGState(ctx);
}
- (void)drawFromPoint:(NSPoint)startingPoint toPoint:(NSPoint)endingPoint options:(NSGradientDrawingOptions)options
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
// TODO kCGGradientDrawsBeforeStartLocation and kCGGradientDrawsAfterEndLocation are not actually supported
// by CGContextDrawLinearGradient yet.
CGContextDrawLinearGradient(ctx, _gradient, startingPoint, endingPoint, options);
}
@end
+13
View File
@@ -86,4 +86,17 @@ var CPGraphicsContextCurrent = nil;
return _graphicsPort;
}
/*!
(Not implemented. Always returns Cappuccino's default, `YES`.)
Return `isFlipped` of the receiver's focused view, unless no view is focused in which case the receiver's
`flipped` flag, as set by `graphicsContextWithGraphicsPort:flipped:`, is returned.
Note: Cappuccino is flipped by default.
*/
- (BOOL)isFlipped
{
return YES;
}
@end
+71 -51
View File
@@ -26,11 +26,6 @@
@import "CPImage.j"
@import "CPShadowView.j"
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
CPImageAlignCenter = 0;
CPImageAlignTop = 1;
CPImageAlignTopLeft = 2;
@@ -41,15 +36,7 @@ CPImageAlignBottomLeft = 6;
CPImageAlignBottomRight = 7;
CPImageAlignRight = 8;
var CPImageViewShadowBackgroundColor = nil,
CPImageViewEmptyPlaceholderImage = nil;
var LEFT_SHADOW_INSET = 3.0,
RIGHT_SHADOW_INSET = 3.0,
TOP_SHADOW_INSET = 3.0,
BOTTOM_SHADOW_INSET = 5.0,
VERTICAL_SHADOW_INSET = TOP_SHADOW_INSET + BOTTOM_SHADOW_INSET,
HORIZONTAL_SHADOW_INSET = LEFT_SHADOW_INSET + RIGHT_SHADOW_INSET;
var CPImageViewEmptyPlaceholderImage = nil;
/*!
@ingroup appkit
@@ -77,6 +64,14 @@ var LEFT_SHADOW_INSET = 3.0,
CPImageViewEmptyPlaceholderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"empty.png"]];
}
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding === CPValueBinding || theBinding === CPValueURLBinding || theBinding === CPValuePathBinding)
return [CPImageViewValueBinder class];
return [super _binderClassForBinding:theBinding];
}
- (id)initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
@@ -240,7 +235,7 @@ var LEFT_SHADOW_INSET = 3.0,
[super setImageScaling:anImageScaling];
#if PLATFORM(DOM)
if ([self currentValueForThemeAttribute:@"image-scaling"] === CPScaleToFit)
if ([self currentValueForThemeAttribute:@"image-scaling"] === CPImageScaleAxesIndependently)
{
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, 0.0, 0.0);
}
@@ -297,19 +292,19 @@ var LEFT_SHADOW_INSET = 3.0,
imageScaling = [self currentValueForThemeAttribute:@"image-scaling"],
x = 0.0,
y = 0.0,
insetWidth = (_hasShadow ? HORIZONTAL_SHADOW_INSET : 0.0),
insetHeight = (_hasShadow ? VERTICAL_SHADOW_INSET : 0.0),
insetWidth = (_hasShadow ? [_shadowView horizontalInset] : 0.0),
insetHeight = (_hasShadow ? [_shadowView verticalInset] : 0.0),
boundsWidth = _CGRectGetWidth(bounds),
boundsHeight = _CGRectGetHeight(bounds),
width = boundsWidth - insetWidth,
height = boundsHeight - insetHeight;
if (imageScaling === CPScaleToFit)
if (imageScaling === CPImageScaleAxesIndependently)
{
#if PLATFORM(DOM)
_DOMImageElement.width = ROUND(width);
_DOMImageElement.height = ROUND(height);
#endif
#if PLATFORM(DOM)
_DOMImageElement.width = ROUND(width);
_DOMImageElement.height = ROUND(height);
#endif
}
else
{
@@ -318,17 +313,19 @@ var LEFT_SHADOW_INSET = 3.0,
if (size.width == -1 && size.height == -1)
return;
if (imageScaling === CPScaleProportionally)
switch (imageScaling)
{
// The max size it can be is size.width x size.height, so only
// only proportion otherwise.
if (width >= size.width && height >= size.height)
{
width = size.width;
height = size.height;
}
else
{
case CPImageScaleProportionallyDown:
if (width >= size.width && height >= size.height)
{
width = size.width;
height = size.height;
break;
}
// intentionally fall through to the next case
case CPImageScaleProportionallyUpOrDown:
var imageRatio = size.width / size.height,
viewRatio = width / height;
@@ -336,26 +333,19 @@ var LEFT_SHADOW_INSET = 3.0,
width = height * imageRatio;
else
height = width / imageRatio;
}
break;
#if PLATFORM(DOM)
case CPImageScaleAxesIndependently:
case CPImageScaleNone:
width = size.width;
height = size.height;
break;
}
#if PLATFORM(DOM)
_DOMImageElement.width = ROUND(width);
_DOMImageElement.height = ROUND(height);
#endif
}
else
{
width = size.width;
height = size.height;
}
if (imageScaling == CPScaleNone)
{
#if PLATFORM(DOM)
_DOMImageElement.width = ROUND(size.width);
_DOMImageElement.height = ROUND(size.height);
#endif
}
#endif
var x,
y;
@@ -406,7 +396,7 @@ var LEFT_SHADOW_INSET = 3.0,
_imageRect = _CGRectMake(x, y, width, height);
if (_hasShadow)
[_shadowView setFrame:_CGRectMake(x - LEFT_SHADOW_INSET, y - TOP_SHADOW_INSET, width + insetWidth, height + insetHeight)];
[_shadowView setFrame:_CGRectMake(x - [_shadowView leftInset], y - [_shadowView topInset], width + insetWidth, height + insetHeight)];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -457,6 +447,33 @@ var LEFT_SHADOW_INSET = 3.0,
@end
@implementation CPImageViewValueBinder : CPBinder
{
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
[self _setPlaceholder:nil forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:nil forMarker:CPNoSelectionMarker isDefault:YES];
[self _setPlaceholder:nil forMarker:CPNotApplicableMarker isDefault:YES];
[self _setPlaceholder:nil forMarker:CPNullMarker isDefault:YES];
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setImage:nil];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
if (aBinding === CPValueURLBinding || aBinding === CPValuePathBinding)
aValue = [[CPImage alloc] initWithContentsOfFile:aValue];
[_source setImage:aValue];
}
@end
var CPImageViewImageKey = @"CPImageViewImageKey",
CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
CPImageViewImageAlignmentKey = @"CPImageViewImageAlignmentKey",
@@ -483,6 +500,9 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
if (typeof(appkit_tag_dom_elements) !== "undefined" && !!appkit_tag_dom_elements)
_DOMImageElement.setAttribute("data-cappuccino-view", [self className]);
#endif
self = [super initWithCoder:aCoder];
@@ -496,7 +516,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
[self setImageAlignment:[aCoder decodeIntForKey:CPImageViewImageAlignmentKey]];
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey])
[self setEditable:YES];
[self setNeedsLayout];
+82 -8
View File
@@ -41,6 +41,7 @@ var CPBindingOperationAnd = 0,
id _source;
JSObject _suppressedNotifications;
JSObject _placeholderForMarker;
}
+ (void)exposeBinding:(CPString)aBinding forClass:(Class)aClass
@@ -125,10 +126,13 @@ var CPBindingOperationAnd = 0,
_source = aSource;
_info = [CPDictionary dictionaryWithObjects:[aDestination, aKeyPath] forKeys:[CPObservedObjectKey, CPObservedKeyPathKey]];
_suppressedNotifications = {};
_placeholderForMarker = {};
if (options)
[_info setObject:options forKey:CPOptionsKey];
[self _updatePlaceholdersWithOptions:options];
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
var bindings = [bindingsMap objectForKey:[_source UID]];
@@ -145,15 +149,40 @@ var CPBindingOperationAnd = 0,
return self;
}
- (void)setValueFor:(CPString)aBinding
- (void)setValueFor:(CPString)theBinding
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath];
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
newValue = [self transformValue:newValue withOptions:options];
[_source setValue:newValue forKey:aBinding];
if (isPlaceholder)
{
if (newValue === CPNotApplicableMarker && [options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
{
[CPException raise:CPGenericException
reason:@"Cannot transform non-applicable key on: " + _source + " key path: " + keyPath + " value: " + newValue];
}
var value = [self _placeholderForMarker:newValue];
[self setPlaceholderValue:value withMarker:newValue forBinding:theBinding];
}
else
{
var value = [self transformValue:newValue withOptions:options];
[self setValue:value forBinding:theBinding];
}
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setValue:aValue forKey:aBinding];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source setValue:aValue forKey:aBinding];
}
- (void)reverseSetValueFor:(CPString)aBinding
@@ -164,7 +193,10 @@ var CPBindingOperationAnd = 0,
newValue = [_source valueForKeyPath:aBinding];
newValue = [self reverseTransformValue:newValue withOptions:options];
[self suppressSpecificNotificationFromObject:destination keyPath:keyPath];
[destination setValue:newValue forKeyPath:keyPath];
[self unsuppressSpecificNotificationFromObject:destination keyPath:keyPath];
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)context
@@ -204,14 +236,13 @@ var CPBindingOperationAnd = 0,
if (valueTransformer)
aValue = [valueTransformer transformedValue:aValue];
if (aValue === undefined || aValue === nil || aValue === [CPNull null])
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
return aValue;
}
- (id)reverseTransformValue:(id)aValue withOptions: (CPDictionary)options
- (id)reverseTransformValue:(id)aValue withOptions:(CPDictionary)options
{
var valueTransformerName = [options objectForKey:CPValueTransformerNameBindingOption],
valueTransformer;
@@ -271,6 +302,42 @@ var CPBindingOperationAnd = 0,
delete objectSuppressions[aKeyPath];
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
var count = [CPBinderPlaceholderMarkers count];
while (count--)
{
var marker = CPBinderPlaceholderMarkers[count],
optionName = CPBinderPlaceholderOptions[count],
isExplicit = [options containsKey:optionName],
placeholder = isExplicit ? [options objectForKey:optionName] : nil;
[self _setPlaceholder:placeholder forMarker:marker isDefault:!isExplicit];
}
}
- (void)_placeholderForMarker:aMarker
{
var placeholder = _placeholderForMarker[aMarker];
if (placeholder)
return placeholder['value'];
return nil;
}
- (void)_setPlaceholder:(id)aPlaceholder forMarker:(id)aMarker isDefault:(BOOL)isDefault
{
if (isDefault)
{
var existingPlaceholder = _placeholderForMarker[aMarker];
// Don't overwrite an explicitly set placeholder with a default.
if (existingPlaceholder && !existingPlaceholder['isDefault'])
return;
}
_placeholderForMarker[aMarker] = { 'isDefault': isDefault, 'value': aPlaceholder };
}
@end
@implementation CPObject (KeyValueBindingCreation)
@@ -404,7 +471,7 @@ var CPBindingOperationAnd = 0,
@end
var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
var resolveMultipleValues = function(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)
{
var bindingName = key,
theBinding,
@@ -428,7 +495,7 @@ var resolveMultipleValues = function resolveMultipleValues(/*CPString*/key, /*CP
return !operation;
};
var invokeAction = function invokeAction(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
var invokeAction = function(/*CPString*/targetKey, /*CPString*/argumentKey, /*CPDictionary*/bindings)
{
var theBinding = [bindings objectForKey:targetKey],
infoDictionary = theBinding._info,
@@ -488,6 +555,9 @@ CPSelectedIndexBinding = @"selectedIndex";
CPTextColorBinding = @"textColor";
CPToolTipBinding = @"toolTip";
CPValueBinding = @"value";
CPValueURLBinding = @"valueURL";
CPValuePathBinding = @"valuePath";
CPDataBinding = @"data";
//Binding options constants
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelection";
@@ -519,3 +589,7 @@ CPIsControllerMarker = function(/*id*/anObject)
{
return anObject === CPMultipleValuesMarker || anObject === CPNoSelectionMarker || anObject === CPNotApplicableMarker || anObject === CPNullMarker;
};
var CPBinderPlaceholderMarkers = [CPMultipleValuesMarker, CPNoSelectionMarker, CPNotApplicableMarker, CPNullMarker],
CPBinderPlaceholderOptions = [CPMultipleValuesPlaceholderBindingOption, CPNoSelectionPlaceholderBindingOption, CPNotApplicablePlaceholderBindingOption, CPNullPlaceholderBindingOption];
+40 -19
View File
@@ -5,13 +5,13 @@ _CPMenuManagerScrollingStateUp = -1;
_CPMenuManagerScrollingStateDown = 1;
_CPMenuManagerScrollingStateNone = 0;
var STICKY_TIME_INTERVAL = 500,
var STICKY_TIME_INTERVAL = 0.5,
SharedMenuManager = nil;
@implementation _CPMenuManager: CPObject
{
CPTimeInterval _startTime;
BOOL _hasMouseGoneUpAfterStartedTracking;
BOOL _mouseWasDragged;
int _scrollingState;
CGPoint _lastGlobalLocation;
@@ -66,7 +66,7 @@ var STICKY_TIME_INTERVAL = 500,
CPApp._activeMenu = menu;
_startTime = [anEvent timestamp];//new Date();
_startTime = [anEvent timestamp];
_scrollingState = _CPMenuManagerScrollingStateNone;
_constraintRect = aRect;
@@ -91,7 +91,7 @@ var STICKY_TIME_INTERVAL = 500,
return [self trackMenuBarButtonEvent:anEvent];
}
_hasMouseGoneUpAfterStartedTracking = NO;
_mouseWasDragged = NO;
[self trackEvent:anEvent];
}
@@ -127,7 +127,7 @@ var STICKY_TIME_INTERVAL = 500,
if (_keyBuffer)
{
if (([CPDate date] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2))
if (([anEvent timestamp] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2))
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:YES];
if (type === CPPeriodic)
@@ -189,7 +189,7 @@ var STICKY_TIME_INTERVAL = 500,
var menuContainerWindow = activeMenuContainer;
if (![menuContainerWindow isKindOfClass:[CPWindow class]])
if (![menuContainerWindow isKindOfClass:CPWindow])
menuContainerWindow = [menuContainerWindow window];
[menuContainerWindow
@@ -215,6 +215,9 @@ var STICKY_TIME_INTERVAL = 500,
if (type === CPMouseMoved || type === CPLeftMouseDragged || type === CPLeftMouseDown || type === CPPeriodic)
{
if (type === CPLeftMouseDragged)
_mouseWasDragged = YES;
var oldScrollingState = _scrollingState;
_scrollingState = [activeMenuContainer scrollingStateForPoint:globalLocation];
@@ -229,17 +232,35 @@ var STICKY_TIME_INTERVAL = 500,
}
else if (type === CPLeftMouseUp || type === CPRightMouseUp)
{
if (_hasMouseGoneUpAfterStartedTracking)
{
// Don't close the menu if the current item has a submenu
// and did not override it's default action
if ([activeItem action] === @selector(submenuAction:))
return;
/*
There are a few possibilites:
[trackingMenu cancelTracking];
1. The user clicks and releases without dragging within the sticky time.
This is considered a regular mouse click and not a drag. In this case
we allow the user to track the menu by moving the mouse. The next
mouse up will end tracking.
2. The user clicks and releases without dragging after the sticky time.
This is considered a drag and release and tracking ends.
3. The user clicks, drags and then releases. Tracking ends.
*/
if (_mouseWasDragged || ([anEvent timestamp] - _startTime > STICKY_TIME_INTERVAL))
{
/*
Close the menu if:
1. The mouse was dragged.
2. The mouse is released in the menubar.
3. The current item has a submenu with a custom action.
*/
if (_mouseWasDragged ||
[activeMenuContainer isMenuBar] ||
[activeItem action] !== @selector(submenuAction:))
{
[trackingMenu cancelTracking];
}
}
else
_hasMouseGoneUpAfterStartedTracking = YES;
}
}
@@ -252,7 +273,7 @@ var STICKY_TIME_INTERVAL = 500,
}
// If the item has a submenu, show it.
if ([activeItem hasSubmenu])// && [activeItem action] === @selector(submenuAction:))
if ([activeItem hasSubmenu]) // && [activeItem action] === @selector(submenuAction:))
{
var activeItemRect = [activeMenuContainer rectForItemAtIndex:activeItemIndex],
newMenuOrigin;
@@ -406,7 +427,7 @@ var STICKY_TIME_INTERVAL = 500,
break;
// If this menu is already being shown, unhighlight and return.
if (menu === newMenu)//&& [menu supermenu] === baseMenu)
if (menu === newMenu) //&& [menu supermenu] === baseMenu)
return [newMenu _highlightItemAtIndex:CPNotFound];
[menuContainer orderOut:self];
@@ -452,7 +473,7 @@ var STICKY_TIME_INTERVAL = 500,
var iter = [selectorNames objectEnumerator],
obj;
while (obj = [iter nextObject])
while ((obj = [iter nextObject]) !== nil)
{
var aSelector = CPSelectorFromString(obj);
@@ -483,7 +504,7 @@ var STICKY_TIME_INTERVAL = 500,
var iter = [[menu itemArray] objectEnumerator],
obj;
while (obj = [iter nextObject])
while ((obj = [iter nextObject]) !== nil)
{
if ([obj isHidden] || ![obj isEnabled])
continue;
+11 -12
View File
@@ -932,34 +932,33 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
_action = [aCoder decodeObjectForKey:CPMenuItemActionKey];
_isEnabled = DEFAULT_VALUE(CPMenuItemIsEnabledKey, YES);
_isHidden = DEFAULT_VALUE(CPMenuItemIsHiddenKey, NO);
_tag = DEFAULT_VALUE(CPMenuItemTagKey, 0);
_state = DEFAULT_VALUE(CPMenuItemStateKey, CPOffState);
_isHidden = [aCoder decodeBoolForKey:CPMenuItemIsHiddenKey];
_tag = [aCoder decodeIntForKey:CPMenuItemTagKey];
_state = [aCoder decodeIntForKey:CPMenuItemStateKey];
_image = DEFAULT_VALUE(CPMenuItemImageKey, nil);
_alternateImage = DEFAULT_VALUE(CPMenuItemAlternateImageKey, nil);
_image = [aCoder decodeObjectForKey:CPMenuItemImageKey];
_alternateImage = [aCoder decodeObjectForKey:CPMenuItemAlternateImageKey];
// CPImage _onStateImage;
// CPImage _offStateImage;
// CPImage _mixedStateImage;
// This order matters because setSubmenu: needs _menu to be around.
_menu = DEFAULT_VALUE(CPMenuItemMenuKey, nil);
[self setSubmenu:DEFAULT_VALUE(CPMenuItemSubmenuKey, nil)];
_menu = [aCoder decodeObjectForKey:CPMenuItemMenuKey];
[self setSubmenu:[aCoder decodeObjectForKey:CPMenuItemSubmenuKey]];
_keyEquivalent = [aCoder decodeObjectForKey:CPMenuItemKeyEquivalentKey] || @"";
_keyEquivalentModifierMask = [aCoder decodeObjectForKey:CPMenuItemKeyEquivalentModifierMaskKey] || 0;
_keyEquivalentModifierMask = [aCoder decodeIntForKey:CPMenuItemKeyEquivalentModifierMaskKey];
// int _mnemonicLocation;
// BOOL _isAlternate;
// Default is 0.
[self setIndentationLevel:[aCoder decodeIntForKey:CPMenuItemIndentationLevelKey] || 0];
[self setIndentationLevel:[aCoder decodeIntForKey:CPMenuItemIndentationLevelKey]];
// CPString _toolTip;
_representedObject = DEFAULT_VALUE(CPMenuItemRepresentedObjectKey, nil);
_view = DEFAULT_VALUE(CPMenuItemViewKey, nil);
_representedObject = [aCoder decodeObjectForKey:CPMenuItemRepresentedObjectKey];
_view = [aCoder decodeObjectForKey:CPMenuItemViewKey];
}
return self;
+1 -3
View File
@@ -148,10 +148,8 @@ var SelectionColor = nil,
[_submenuIndicatorView setFrame:submenuViewFrame];
}
_minSize = CGSizeMake(x + HORIZONTAL_MARGIN, height);
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setFrameSize:CGSizeMake(x + HORIZONTAL_MARGIN, height)];
[self setAutoresizesSubviews:YES];
}
+14 -14
View File
@@ -6,14 +6,14 @@ var LEFT_MARGIN = 3.0,
STATE_COLUMN_WIDTH = 14.0,
INDENTATION_WIDTH = 17.0,
VERTICAL_MARGIN = 4.0,
RIGHT_COLUMNS_MARGIN = 30.0,
KEY_EQUIVALENT_MARGIN = 10.0;
var SUBMENU_INDICATOR_COLOR = nil,
_CPMenuItemSelectionColor = nil,
_CPMenuItemTextShadowColor = nil,
_CPMenuItemDefaultStateImages = [],
_CPMenuItemDefaultStateHighlightedImages = [];
@@ -43,9 +43,9 @@ var SUBMENU_INDICATOR_COLOR = nil,
_CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:95.0 / 255.0 green:131.0 / 255.0 blue:185.0 / 255.0 alpha:1.0];
_CPMenuItemTextShadowColor = [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0];
var bundle = [CPBundle bundleForClass:self];
_CPMenuItemDefaultStateImages[CPOffState] = nil;
_CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil;
@@ -74,7 +74,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
{
_stateView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[_stateView setImageScaling:CPScaleNone];
[_stateView setImageScaling:CPImageScaleNone];
[self addSubview:_stateView];
@@ -175,7 +175,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
[_keyEquivalentView setTextShadowOffset:CGSizeMake(0, 1)];
[_keyEquivalentView setFrameOrigin:CGPointMake(x, VERTICAL_MARGIN)];
[_keyEquivalentView sizeToFit];
var keyEquivalentViewFrame = [_keyEquivalentView frame];
keyEquivalentViewFrame.origin.x = x;
@@ -215,7 +215,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
keyEquivalentViewFrame.origin.y = FLOOR((height - CGRectGetHeight(keyEquivalentViewFrame)) / 2.0);
[_keyEquivalentView setFrame:keyEquivalentViewFrame];
}
if (hasSubmenu)
{
submenuViewFrame.origin.y = FLOOR((height - CGRectGetHeight(submenuViewFrame)) / 2.0);
@@ -223,7 +223,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
}
_minSize = CGSizeMake(x + RIGHT_MARGIN, height);
[self setAutoresizesSubviews:NO];
[self setFrameSize:_minSize];
[self setAutoresizesSubviews:YES];
@@ -233,7 +233,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
{
// FIXME: This should probably be even throw.
if (![_menuItem isEnabled])
return;
return;
if (shouldHighlight)
{
@@ -259,7 +259,7 @@ var SUBMENU_INDICATOR_COLOR = nil,
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_keyEquivalentView setTextShadowColor:[self textShadowColor]];
}
if ([[_menuItem menu] showsStateColumn])
{
if (shouldHighlight)
@@ -290,15 +290,15 @@ var SUBMENU_INDICATOR_COLOR = nil,
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds];
CGContextBeginPath(context);
CGContextMoveToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMidY(bounds));
CGContextAddLineToPoint(context, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
CGContextClosePath(context);
CGContextSetFillColor(context, _color);
CGContextFillPath(context);
}
+10 -8
View File
@@ -371,7 +371,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[self setObjectClass:objectClass || [CPMutableDictionary class]];
[self setEditable:[aCoder decodeBoolForKey:CPObjectControllerIsEditableKey]];
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey] || NO];
[self setAutomaticallyPreparesContent:[aCoder decodeBoolForKey:CPObjectControllerAutomaticallyPreparesContentKey]];
[self setContent:[aCoder decodeObjectForKey:CPObjectControllerContentKey]];
_observedKeys = [[CPCountedSet alloc] init];
@@ -579,6 +579,8 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (void)removeObjectAtIndex:(unsigned)anIndex
{
var currentObject = [self objectAtIndex:anIndex];
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
var proxy = [_observationProxies objectAtIndex:i],
@@ -588,7 +590,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
if (operator)
[self willChangeValueForKey:keyPath];
[anObject removeObserver:proxy forKeyPath:keyPath];
[currentObject removeObserver:proxy forKeyPath:keyPath];
if (operator)
[self didChangeValueForKey:keyPath];
@@ -663,7 +665,8 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (id)_controllerMarkerForValues:(CPArray)theValues
{
var count = [theValues count];
var count = [theValues count],
value;
if (!count)
value = CPNoSelectionMarker;
@@ -677,7 +680,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
{
value = [theValues objectAtIndex:0];
for (var i = 0, count= [theValues count]; i < count && value != CPMultipleValuesMarker; i++)
for (var i = 0, count = [theValues count]; i < count && value != CPMultipleValuesMarker; i++)
{
if (![value isEqual:[theValues objectAtIndex:i]])
value = CPMultipleValuesMarker;
@@ -693,8 +696,8 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (id)valueForKeyPath:(CPString)theKeyPath
{
var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath];
value = [self _controllerMarkerForValues:values];
var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath],
value = [self _controllerMarkerForValues:values];
[_cachedValues setObject:value forKey:theKeyPath];
@@ -776,8 +779,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[proxy setNotifyObject:YES];
[_observationProxies addObject:proxy];
// We keep are reference to the observed objects
// because the removeObserver: will be called after the selection changes
// We keep a reference to the observed objects because removeObserver: will be called after the selection changes.
var observedObjects = [_controller selectedObjects];
_observedObjectsByKeyPath[aKeyPath] = observedObjects;
[observedObjects addObserver:proxy forKeyPath:aKeyPath options:options context:context];
+75 -37
View File
@@ -62,7 +62,7 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ = 1 << 12,
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 13,
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ = 1 << 14,
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ = 1 << 15,
CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_ = 1 << 15,
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ = 1 << 16,
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ = 1 << 17,
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ = 1 << 18,
@@ -80,6 +80,10 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
CPOutlineViewCoalesceSelectionNotificationStateOn = 1,
CPOutlineViewCoalesceSelectionNotificationStateDid = 2;
#define SELECTION_SHOULD_CHANGE(anOutlineView) (!((anOutlineView)._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_selectionShouldChangeInOutlineView_) || [(anOutlineView)._outlineViewDelegate selectionShouldChangeInOutlineView:(anOutlineView)])
#define SHOULD_SELECT_ITEM(anOutlineView, anItem) (!((anOutlineView)._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_) || [(anOutlineView)._outlineViewDelegate outlineView:(anOutlineView) shouldSelectItem:(anItem)])
/*!
@ingroup appkit
@class CPOutlineView
@@ -136,7 +140,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
_selectionHighlightStyle = CPTableViewSelectionHighlightStyleSourceList;
// The root item has weight "0", thus represents the weight solely of its descendants.
_rootItemInfo = { isExpanded:YES, isExpandable:NO, level:-1, row:-1, children:[], weight:0 };
_rootItemInfo = { isExpanded:YES, isExpandable:NO, shouldShowOutlineDisclosureControl:NO, level:-1, row:-1, children:[], weight:0 };
_itemsForRows = [];
_itemInfosForItems = { };
@@ -147,7 +151,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
_retargedChildIndex = nil;
_shouldRetargetChildIndex = NO;
_startHoverTime = nil;
[self setIndentationPerLevel:16.0];
[self setIndentationMarkerFollowsDataView:YES];
@@ -294,6 +297,19 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
return itemInfo.isExpandable;
}
- (BOOL)_shouldShowOutlineDisclosureControlForItem:(id)anItem
{
if (!anItem)
return YES;
var itemInfo = _itemInfosForItems[[anItem UID]];
if (!itemInfo)
return YES;
return itemInfo.shouldShowOutlineDisclosureControl;
}
/*!
Used to find if an item is already expanded.
@@ -690,7 +706,8 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
*/
- (CGRect)frameOfOutlineDisclosureControlAtRow:(CPInteger)aRow
{
if (![self isExpandable:[self itemAtRow:aRow]])
var theItem = [self itemAtRow:aRow];
if (![self isExpandable:theItem] || ![self _shouldShowOutlineDisclosureControlForItem:theItem])
return _CGRectMakeZero();
var dataViewFrame = [self _frameOfOutlineDataViewAtRow:aRow],
@@ -822,29 +839,24 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
name:CPOutlineViewSelectionIsChangingNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillExpand:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemWillExpandNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemDidExpand:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemDidExpandNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillCollapse:)])
[defaultCenter
removeObserver:_outlineViewDelegate
name:CPOutlineViewItemWillCollapseNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemDidCollapse:)])
[defaultCenter
removeObserver:_outlineViewDelegate
@@ -870,7 +882,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ , @selector(outlineView:shouldReorderColumn:toColumn:),
CPOutlineViewDelegate_outlineView_shouldSelectItem_ , @selector(outlineView:shouldSelectItem:),
CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ , @selector(outlineView:shouldSelectTableColumn:),
CPOutlineViewDelegate_outlineView_shouldShowOutlineViewForItem_ , @selector(outlineView:shouldShowOutlineViewForItem:),
CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_ , @selector(outlineView:shouldShowOutlineDisclosureControlForItem:),
CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ , @selector(outlineView:shouldShowViewExpansionForTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ , @selector(outlineView:shouldTrackView:forTableColumn:item:),
CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ , @selector(outlineView:shouldTypeSelectForEvent:withCurrentSearchString:),
@@ -921,7 +933,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
name:CPOutlineViewSelectionIsChangingNotification
object:self];
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewItemWillExpand:)])
[defaultCenter
addObserver:_outlineViewDelegate
@@ -984,7 +995,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
_disclosureControlData = nil;
_disclosureControlQueue = [];
// fIXME: really?
// FIXME: really?
[self reloadData];
}
@@ -1285,7 +1296,12 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
item = _itemsForRows[row],
isExpandable = [self isExpandable:item];
if (!isExpandable)
if (!isExpandable)
continue;
var disclosureControlFrame = [self frameOfOutlineDisclosureControlAtRow:row];
if (_CGRectIsEmpty(disclosureControlFrame))
continue;
var control = [self _dequeueDisclosureControl];
@@ -1295,7 +1311,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
[control setState:[self isItemExpanded:item] ? CPOnState : CPOffState];
var selector = [self isRowSelected:row] ? @"setThemeState:" : @"unsetThemeState:";
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
[control setFrame:[self frameOfOutlineDisclosureControlAtRow:row]];
[control setFrame:disclosureControlFrame];
[self addSubview:control];
}
@@ -1348,7 +1364,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
[self collapseItem:item];
else
[self expandItem:item];
[self expandItem:item expandChildren:([[CPApp currentEvent] modifierFlags] & CPAlternateKeyMask)];
}
/*!
@@ -1459,7 +1475,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
userInfo:[CPDictionary dictionaryWithObject:item forKey:"CPObject"]];
}
- (void)keyDown:(CPEvent)anEvent
{
var character = [anEvent charactersIgnoringModifiers],
@@ -1483,7 +1498,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
for (; i < c; i++)
items.push([self itemAtRow:indexes[i]]);
if (character === CPRightArrowFunctionKey)
{
for (var i = 0; i < c; i++)
@@ -1491,12 +1505,32 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
}
else if (character === CPLeftArrowFunctionKey)
{
// When a single, collapsed item is selected and the left arrow key is pressed, the parent
// should be selected if possible.
if (c == 1)
{
var theItem = items[0];
if (![self isItemExpanded:theItem])
{
var parent = [self parentForItem:theItem],
shouldSelect = parent && SELECTION_SHOULD_CHANGE(self) && SHOULD_SELECT_ITEM(self, parent);
if (shouldSelect)
{
var rowIndex = [self rowForItem:parent];
[self selectRowIndexes:[CPIndexSet indexSetWithIndex:rowIndex] byExtendingSelection:NO];
[self scrollRowToVisible:rowIndex];
return;
}
}
}
for (var i = 0; i < c; i++)
[self collapseItem:items[i]];
}
[super keyDown:anEvent];
}
@end
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
@@ -1535,6 +1569,7 @@ var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
itemInfo.shouldShowOutlineDisclosureControl = !(_implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_) || [_outlineViewDelegate outlineView:self shouldShowOutlineDisclosureControlForItem:newItem];
}
};
@@ -1560,6 +1595,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
return [];
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
itemInfo.shouldShowOutlineDisclosureControl = !(_implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_) || [_outlineViewDelegate outlineView:self shouldShowOutlineDisclosureControlForItem:anItem];
// If we were previously expanded, but now no longer expandable, "de-expand".
// NOTE: we are *not* collapsing, thus no notification is posted.
@@ -1590,7 +1626,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
if (!childItemInfo)
{
childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 };
childItemInfo = { isExpanded:NO, isExpandable:NO, shouldShowOutlineDisclosureControl:YES, children:[], weight:1 };
itemInfosForItems[[childItem UID]] = childItemInfo;
}
@@ -1793,9 +1829,9 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
var dataView = nil;
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_))
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
dataViewForTableColumn:theTableColumn
item:[_outlineView itemAtRow:theRow]];
dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
dataViewForTableColumn:theTableColumn
item:[_outlineView itemAtRow:theRow]];
if (!dataView)
dataView = [theTableColumn dataViewForRow:theRow];
@@ -1805,10 +1841,12 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
- (BOOL)tableView:(CPTableView)theTableView shouldSelectRow:(int)theRow
{
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_))
return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]];
return SHOULD_SELECT_ITEM(_outlineView, [_outlineView itemAtRow:theRow]);
}
return YES;
- (BOOL)selectionShouldChangeInTableView:(CPTableView)theTableView
{
return SELECTION_SHOULD_CHANGE(_outlineView);
}
- (BOOL)tableView:(CPTableView)aTableView shouldEditTableColumn:(CPTableColumn)aColumn row:(int)aRow
@@ -1886,16 +1924,22 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
- (void)drawRect:(CGRect)aRect
{
var bounds = [self bounds],
context = [[CPGraphicsContext currentContext] graphicsPort];
context = [[CPGraphicsContext currentContext] graphicsPort],
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
CGContextBeginPath(context);
CGContextTranslateCTM(context, _CGRectGetWidth(bounds) / 2.0, _CGRectGetHeight(bounds) / 2.0);
CGContextRotateCTM(context, _angle);
CGContextTranslateCTM(context, -_CGRectGetWidth(bounds) / 2.0, -_CGRectGetHeight(bounds) / 2.0);
if (_angle)
{
var centre = _CGPointMake(FLOOR(width / 2.0), FLOOR(height / 2.0));
CGContextTranslateCTM(context, centre.x, centre.y);
CGContextRotateCTM(context, _angle);
CGContextTranslateCTM(context, -centre.x, -centre.y);
}
// Center, but crisp.
CGContextTranslateCTM(context, FLOOR((_CGRectGetWidth(bounds) - 9.0) / 2.0), FLOOR((_CGRectGetHeight(bounds) - 8.0) / 2.0));
CGContextTranslateCTM(context, FLOOR((width - 9.0) / 2.0), FLOOR((height - 8.0) / 2.0));
CGContextMoveToPoint(context, 0.0, 0.0);
CGContextAddLineToPoint(context, 9.0, 0.0);
@@ -1908,20 +1952,14 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
[self hasThemeState:CPThemeStateHighlighted]));
CGContextFillPath(context);
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0.0, 0.0);
CGContextAddLineToPoint(context, 4.5, 8.0);
if (_angle === 0.0)
{
CGContextAddLineToPoint(context, 4.5, 8.0);
CGContextAddLineToPoint(context, 9.0, 0.0);
}
else
CGContextAddLineToPoint(context, 4.5, 8.0);
CGContextSetStrokeColor(context, [CPColor colorWithCalibratedWhite:1.0 alpha: 0.8]);
CGContextSetStrokeColor(context, [CPColor colorWithCalibratedWhite:1.0 alpha: 0.7]);
CGContextStrokePath(context);
}
+1 -1
View File
@@ -249,7 +249,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
@ignore
*/
- (int)selectedTag
- (int)_selectedTag
{
return [[self selectedItem] tag];
}
+105 -63
View File
@@ -35,7 +35,6 @@ CPPopoverBehaviorApplicationDefined = 0;
CPPopoverBehaviorTransient = 1;
CPPopoverBehaviorSemitransient = 2;
var CPPopoverDelegate_popover_willShow_ = 1 << 0,
CPPopoverDelegate_popover_didShow_ = 1 << 1,
CPPopoverDelegate_popover_shouldClose_ = 1 << 2,
@@ -50,11 +49,14 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
view relative to another one.
Delegate can implement:
– popoverShouldClose:(CPPopover)aPopOver
– popoverWillShow:(CPPopover)aPopOver
– popoverDidShow:(CPPopover)aPopOver
– popoverWillClose:(CPPopover)aPopOver
– popoverDidClose:(CPPopover)aPopOver
@code
– popoverShouldClose:(CPPopover)aPopOver
– popoverWillShow:(CPPopover)aPopOver
– popoverDidShow:(CPPopover)aPopOver
– popoverWillClose:(CPPopover)aPopOver
– popoverDidClose:(CPPopover)aPopOver
@endcode
*/
@implementation CPPopover : CPResponder
{
@@ -62,11 +64,9 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
@outlet id _delegate @accessors(getter=delegate);
BOOL _animates @accessors(property=animates);
BOOL _shown @accessors(getter=shown);
int _appearance @accessors(property=appearance);
int _behavior @accessors(getter=behavior);
BOOL _needsCompute;
_CPAttachedWindow _attachedWindow;
int _implementedDelegateMethods;
}
@@ -78,17 +78,15 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Initialize the CPPopover witn default values
@returns anInitialized CPPopover
@returns an initialized CPPopover
*/
- (CPPopover)init
{
if (self = [super init])
{
_animates = YES;
_appearance = CPPopoverAppearanceMinimal;
_behavior = CPPopoverBehaviorApplicationDefined;
_needsCompute = YES;
_shown = NO;
_animates = YES;
_appearance = CPPopoverAppearanceMinimal;
_behavior = CPPopoverBehaviorApplicationDefined;
}
return self;
@@ -101,21 +99,21 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Returns the current rect of the popover
@return CPRect represeting the frame of the popover
@return CGRect representing the frame of the popover
*/
- (CPRect)positioningRect
- (CGRect)positioningRect
{
if (!_attachedWindow || ![_attachedWindow isVisible])
return nil;
if (![_attachedWindow isVisible])
return CGRectMakeZero();
return [_attachedWindow frame];
}
/*! Sets the frame of the popover
@param aRect the desired frame
*/
- (void)setPositioningRect:(CPRect)aRect
- (void)setPositioningRect:(CGRect)aRect
{
if (!_attachedWindow || ![_attachedWindow isVisible])
if (![_attachedWindow isVisible])
return;
[_attachedWindow setFrame:aRect];
}
@@ -123,12 +121,12 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Returns the size of the popover's view
@return CPSize represeting the size of the popover's view
@return CGSize representing the size of the popover's view
*/
- (CPRect)contentSize
- (CGSize)contentSize
{
if (!_attachedWindow || ![_attachedWindow isVisible])
return nil;
if (![_attachedWindow isVisible])
return CGRectMakeZero();
return [[_contentViewController view] frameSize];
}
@@ -145,21 +143,20 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Indicates if CPPopover is visible
@returns YES if visible
@returns \c YES if visible
*/
- (BOOL)shown
- (BOOL)isShown
{
if (!_attachedWindow)
return NO;
return [_attachedWindow isVisible];
}
/*!
Set the behaviour of the CPPopover. It can be
- CPPopoverBehaviorTransient: the popover will be close if another control outside the popover become the responder
- CPPopoverBehaviorApplicationDefined: (DEFAULT) the application is responsible for closing the popover
Set the behaviour of the CPPopover. It can be:
@param aBehaviour the desired behaviour
- \c CPPopoverBehaviorTransient: the popover will close if another control outside the popover becomes the responder
- \c CPPopoverBehaviorApplicationDefined: (DEFAULT) the application is responsible for closing the popover
@param aBehaviour the desired behaviour
*/
- (void)setBehaviour:(int)aBehaviour
{
@@ -167,10 +164,9 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
return;
_behavior = aBehaviour;
_needsCompute = YES;
[_attachedWindow setStyleMask:[self styleMaskForBehavior]];
}
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
@@ -203,20 +199,31 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
@param positioningRect if set, the popover will be positionned to a random rect relative to the window
@param positioningView if set, the popover will be positioned relative to this view
@param preferredEdge: CPRectEdge representing the preferred positioning.
@param preferredEdge: \c CPRectEdge representing the preferred positioning.
*/
- (void)showRelativeToRect:(CPRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge
- (void)showRelativeToRect:(CGRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge
{
if (!positioningView)
[CPException raise:CPInvalidArgumentException reason:"positionView must not be nil"];
if (!_contentViewController)
[CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
// If the popover is currently closing, do nothing. That is what Cocoa does.
if ([_attachedWindow isClosing])
return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_)
[_delegate popoverWillShow:self];
if (!_contentViewController)
[CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
if (_needsCompute || !_attachedWindow)
if (!_attachedWindow)
{
var styleMask = (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : nil;
_attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:styleMask];
_attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self styleMaskForBehavior]];
var parentWindow = [positioningView window];
if (![parentWindow isKindOfClass:_CPAttachedWindow])
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(parentWindowWillClose:) name:CPWindowWillCloseNotification object:parentWindow];
}
[_attachedWindow setAppearance:_appearance];
@@ -225,34 +232,40 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
[_attachedWindow setMovableByWindowBackground:NO];
[_attachedWindow setFrame:[_attachedWindow frameRectForContentRect:[[_contentViewController view] frame]]];
[_attachedWindow setContentView:[_contentViewController view]];
if (positioningRect)
[_attachedWindow positionRelativeToRect:positioningRect preferredEdge:preferredEdge];
else if (positioningView)
[_attachedWindow positionRelativeToView:positioningView preferredEdge:preferredEdge];
else
[CPException raise:CPInvalidArgumentException reason:@"a value must be passed for positioningRect or positioningView"];
[_attachedWindow positionRelativeToRect:positioningRect ofView:positioningView preferredEdge:preferredEdge];
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
[_delegate popoverDidShow:self];
}
- (unsigned)styleMaskForBehavior
{
return (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : 0;
}
/*!
Closes the popover
*/
- (void)close
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
if (![_delegate popoverShouldClose:self])
return;
[self _close];
}
/*!
Closes the popover
*/
- (void)_close
{
if ([_attachedWindow isClosing] || ![self isShown])
return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_)
[_delegate popoverWillClose:self];
[_attachedWindow close];
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didClose_)
[_delegate popoverDidClose:self];
// popoverDidClose will be sent from attachedWindowDidClose, since
// the attached window will close asynchronously when animating.
}
@@ -262,11 +275,18 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
/*!
Close the popover
@param aSender the sender of the action
@param sender the sender of the action
*/
- (IBAction)performClose:(id)aSender
- (IBAction)performClose:(id)sender
{
[self close];
if ([_attachedWindow isClosing])
return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
if (![_delegate popoverShouldClose:self])
return;
[self _close];
}
@@ -278,14 +298,38 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
{
[self close];
// we return NO, because we want the CPPopover to compute
// if the attached can be close in order to send delegate messages
// We return NO, because we want the CPPopover to determine
// if the attached window can be closed and to give us a chance
// to send delegate messages.
return NO;
}
/*! @ignore */
- (void)attachedWindowDidClose:(_CPAttachedWindow)anAttachedWindow
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didClose_)
[_delegate popoverDidClose:self];
}
#pragma mark -
#pragma mark Notifications
/*!
@ignore
This method is called only when a non-popover parent window
is closing. In that case popovers should order out.
*/
- (void)parentWindowWillClose:(CPNotification)aNotification
{
[_attachedWindow orderOut:nil];
[self performClose:nil];
}
@end
var CPPopoverNeedsComputeKey = @"CPPopoverNeedsComputeKey",
var CPPopoverNeedsNewAttachedWindowKey = @"CPPopoverNeedsNewAttachedWindowKey",
CPPopoverAppearanceKey = @"CPPopoverAppearanceKey",
CPPopoverAnimatesKey = @"CPPopoverAnimatesKey",
CPPopoverContentViewControllerKey = @"CPPopoverContentViewControllerKey",
@@ -300,7 +344,6 @@ var CPPopoverNeedsComputeKey = @"CPPopoverNeedsComputeKey",
if (self)
{
_needsCompute = [aCoder decodeIntForKey:CPPopoverNeedsComputeKey];
_appearance = [aCoder decodeIntForKey:CPPopoverAppearanceKey];
_animates = [aCoder decodeBoolForKey:CPPopoverAnimatesKey];
_contentViewController = [aCoder decodeObjectForKey:CPPopoverContentViewControllerKey];
@@ -314,9 +357,8 @@ var CPPopoverNeedsComputeKey = @"CPPopoverNeedsComputeKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeBool:_needsCompute forKey:CPPopoverNeedsComputeKey];
[aCoder encodeInt:_appearance forKey:CPPopoverAppearanceKey];
[aCoder encodeObject:_animates forKey:CPPopoverAnimatesKey];
[aCoder encodeBool:_animates forKey:CPPopoverAnimatesKey];
[aCoder encodeObject:_contentViewController forKey:CPPopoverContentViewControllerKey];
[aCoder encodeObject:_delegate forKey:CPPopoverDelegateKey];
[aCoder encodeInt:_behavior forKey:CPPopoverBehaviorKey];
+4 -4
View File
@@ -88,9 +88,9 @@ var CPProgressIndicatorSpinningStyleColors = nil,
CPProgressIndicatorSpinningStyleColors = [];
CPProgressIndicatorSpinningStyleColors[CPMiniControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]];
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleMini.gif"] size:CGSizeMake(16.0, 16.0)]];
CPProgressIndicatorSpinningStyleColors[CPSmallControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]];
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleSmall.gif"] size:CGSizeMake(32.0, 32.0)]];
CPProgressIndicatorSpinningStyleColors[CPRegularControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:
[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]];
@@ -477,7 +477,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
_doubleValue = [aCoder decodeObjectForKey:@"_doubleValue"];
_controlSize = [aCoder decodeObjectForKey:@"_controlSize"];
_isIndeterminate = [aCoder decodeObjectForKey:@"_isIndeterminate"];
_style = [aCoder decodeObjectForKey:@"_style"];
_style = [aCoder decodeIntForKey:@"_style"];
_isAnimating = [aCoder decodeObjectForKey:@"_isAnimating"];
_isDisplayedWhenStoppedSet = [aCoder decodeObjectForKey:@"_isDisplayedWhenStoppedSet"];
_isDisplayedWhenStopped = [aCoder decodeObjectForKey:@"_isDisplayedWhenStopped"];
@@ -495,7 +495,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
[aCoder encodeObject:_doubleValue forKey:@"_doubleValue"];
[aCoder encodeObject:_controlSize forKey:@"_controlSize"];
[aCoder encodeObject:_isIndeterminate forKey:@"_isIndeterminate"];
[aCoder encodeObject:_style forKey:@"_style"];
[aCoder encodeInt:_style forKey:@"_style"];
[aCoder encodeObject:_isAnimating forKey:@"_isAnimating"];
[aCoder encodeObject:_isDisplayedWhenStoppedSet forKey:@"_isDisplayedWhenStoppedSet"];
[aCoder encodeObject:_isDisplayedWhenStopped forKey:@"_isDisplayedWhenStopped"];
+8 -4
View File
@@ -377,7 +377,8 @@
{
var rootRowsArray = [super _rootRowsArray],
subpredicates = [CPMutableArray array],
count = count2 = [rootRowsArray count],
count,
count2 = count = [rootRowsArray count],
predicate;
while (count--)
@@ -405,12 +406,13 @@
if (rowType == CPRuleEditorRowTypeCompound)
{
var subrows = [rowItem valueForKey:_subrowsArrayKeyPath],
count = [subrows count];
count = [subrows count];
for (var i = 0; i < count; i++)
{
var subrow = [subrows objectAtIndex:i];
var predicate = [self _predicateFromRowItem:subrow];
var subrow = [subrows objectAtIndex:i],
predicate = [self _predicateFromRowItem:subrow];
[subpredicates addObject:predicate];
}
}
@@ -514,9 +516,11 @@ var CPPredicateTemplatesKey = @"CPPredicateTemplates";
- (id)initWithCoder:(id)aCoder
{
self = [super initWithCoder:aCoder];
if (self != nil)
{
var nibTemplates = [aCoder decodeObjectForKey:CPPredicateTemplatesKey];
if (nibTemplates != nil)
[self setRowTemplates:nibTemplates];
}
+136 -115
View File
@@ -141,7 +141,7 @@ var itemsContext = "items",
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
if (self !== nil)
{
_slices = [[CPMutableArray alloc] init];
@@ -150,7 +150,7 @@ var itemsContext = "items",
_editable = YES;
_allowsEmptyCompoundRows = NO;
_disallowEmpty = NO;
[self setFormattingStringsFilename:nil];
[self setCriteriaKeyPath:@"criteria"];
[self setSubrowsKeyPath:@"subrows"];
@@ -190,7 +190,7 @@ var itemsContext = "items",
[_slicesHolder addSubview:_dropLineView];
[self registerForDraggedTypes:[CPArray arrayWithObjects:CPRuleEditorItemPBoardType,nil]];
[_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew context:boundArrayContext];
[_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
}
/*! @endcond */
@@ -247,7 +247,7 @@ var itemsContext = "items",
*/
- (void)setEditable:(BOOL)editable
{
if (editable == _editable)
if (editable === _editable)
return;
_editable = editable;
@@ -277,7 +277,7 @@ var itemsContext = "items",
*/
- (void)setNestingMode:(CPRuleEditorNestingMode)mode
{
if (mode != _nestingMode)
if (mode !== _nestingMode)
{
_nestingMode = mode;
if ([self numberOfRows] > 0)
@@ -344,7 +344,7 @@ var itemsContext = "items",
*/
- (void)setRowHeight:(float)height
{
if (height == _sliceHeight)
if (height === _sliceHeight)
return;
_sliceHeight = MAX([self _minimumFrameHeight], height);
@@ -398,10 +398,10 @@ var itemsContext = "items",
*/
- (void)setFormattingStringsFilename:(CPString)stringsFilename
{
if (_standardLocalizer == nil)
if (_standardLocalizer === nil)
_standardLocalizer = [_CPRuleEditorLocalizer new];
if (_stringsFilename != stringsFilename)
if (_stringsFilename !== stringsFilename)
{
_stringsFilename = stringsFilename;
@@ -410,7 +410,7 @@ var itemsContext = "items",
if (![stringsFilename hasSuffix:@".strings"])
stringsFilename = stringsFilename + @".strings";
var path = [[CPBundle mainBundle] pathForResource:stringsFilename];
if (path !=nil)
if (path !== nil)
[_standardLocalizer loadContentOfURL:[CPURL URLWithString:path]];
}
}
@@ -441,7 +441,7 @@ var itemsContext = "items",
*/
- (void)setCriteria:(CPArray)criteria andDisplayValues:(CPArray)values forRowAtIndex:(int)rowIndex
{
if (criteria == nil || values == nil)
if (criteria === nil || values === nil)
[CPException raise:CPInvalidArgumentException reason:_cmd + @". criteria and values parameters must not be nil."];
if (rowIndex < 0 || rowIndex >= [self numberOfRows])
@@ -511,12 +511,12 @@ var itemsContext = "items",
for (var current_index = 0; current_index < rowIndex; current_index++)
{
if ([self rowTypeForRow:current_index] == CPRuleEditorRowTypeCompound)
if ([self rowTypeForRow:current_index] === CPRuleEditorRowTypeCompound)
{
var candidate = [[self _rowCacheForIndex:current_index] rowObject],
subObjects = [[self _subrowObjectsOfObject:candidate] _representedObject];
if ([subObjects indexOfObjectIdenticalTo:targetObject] != CPNotFound)
if ([subObjects indexOfObjectIdenticalTo:targetObject] !== CPNotFound)
return current_index;
}
}
@@ -567,7 +567,8 @@ TODO: implement
- (CPIndexSet)subrowIndexesForRow:(int)rowIndex
{
var object;
if (rowIndex == -1)
if (rowIndex === -1)
object = _boundArrayOwner;
else
object = [[self _rowCacheForIndex:rowIndex] rowObject];
@@ -582,16 +583,16 @@ TODO: implement
var candidate = [[self _rowCacheForIndex:i] rowObject],
indexInSubrows = [[subobjects _representedObject] indexOfObjectIdenticalTo:candidate];
if (indexInSubrows != CPNotFound)
if (indexInSubrows !== CPNotFound)
{
[indexes addIndex:i];
objectsCount --;
if ([self rowTypeForRow:i] == CPRuleEditorRowTypeCompound)
if ([self rowTypeForRow:i] === CPRuleEditorRowTypeCompound)
i += [[self subrowIndexesForRow:i] count];
}
if (objectsCount == 0)
if (objectsCount === 0)
break;
}
@@ -627,12 +628,12 @@ TODO: implement
{
var slice = _slices[count],
rowIndex = [slice rowIndex],
contains = [indexes containsIndex:rowIndex];
contains = [indexes containsIndex:rowIndex],
shouldSelect = (contains && !(extend && [slice _isSelected]));
if (contains)
[slice _setSelected:shouldSelect];
[slice _setLastSelected:(rowIndex == lastSelected)];
[slice _setLastSelected:(rowIndex === lastSelected)];
[slice setNeedsDisplay:YES];
}
}
@@ -674,7 +675,7 @@ TODO: implement
break;
default:
[CPException raise:CPInvalidArgumentException reason:@"Not supported CPRuleEditorNestingMode " + nestingMode];
// Compound mode: parentRowIndex=(lastRowType == CPRuleEditorRowTypeCompound)?lastRow :[self parentRowForRow:lastRow]; break;
// Compound mode: parentRowIndex=(lastRowType === CPRuleEditorRowTypeCompound)?lastRow :[self parentRowForRow:lastRow]; break;
}
[self insertRowAtIndex:numberOfRows withType:rowtype asSubrowOfRow:parentRowIndex animate:YES];
@@ -696,7 +697,7 @@ TODO: implement
*/
var newObject = [self _insertNewRowAtIndex:rowIndex ofType:rowType withParentRow:parentRow];
if (rowType == CPRuleEditorRowTypeCompound && !_allowsEmptyCompoundRows)
if (rowType === CPRuleEditorRowTypeCompound && !_allowsEmptyCompoundRows)
{
var subrow = [self _insertNewRowAtIndex:(rowIndex + 1) ofType:CPRuleEditorRowTypeSimple withParentRow:rowIndex];
}
@@ -727,7 +728,7 @@ TODO: implement
*/
- (void)removeRowsAtIndexes:(CPIndexSet)rowIndexes includeSubrows:(BOOL)includeSubrows
{
if ([rowIndexes count] == 0)
if ([rowIndexes count] === 0)
return;
if ([rowIndexes lastIndex] >= [self numberOfRows])
@@ -738,7 +739,7 @@ TODO: implement
childsIndexes = [CPMutableIndexSet indexSet],
subrows;
if (parentRowIndex == -1)
if (parentRowIndex === -1)
subrows = [self _rootRowsArray];
else
{
@@ -746,15 +747,15 @@ TODO: implement
subrows = [self _subrowObjectsOfObject:parentRowObject];
}
while (current_index != CPNotFound)
while (current_index !== CPNotFound)
{
var rowObject = [[self _rowCacheForIndex:current_index] rowObject],
relativeChildIndex = [[subrows _representedObject] indexOfObjectIdenticalTo:rowObject];
if (relativeChildIndex != CPNotFound)
if (relativeChildIndex !== CPNotFound)
[childsIndexes addIndex:relativeChildIndex];
if (includeSubrows && [self rowTypeForRow:current_index] == CPRuleEditorRowTypeCompound)
if (includeSubrows && [self rowTypeForRow:current_index] === CPRuleEditorRowTypeCompound)
{
var more_childs = [self subrowIndexesForRow:current_index];
[self removeRowsAtIndexes:more_childs includeSubrows:includeSubrows];
@@ -814,20 +815,20 @@ TODO: implement
[predicateParts addEntriesFromDictionary:predpart];
}
if ([self rowTypeForRow:aRow] == CPRuleEditorRowTypeCompound)
if ([self rowTypeForRow:aRow] === CPRuleEditorRowTypeCompound)
{
var compoundPredicate,
subpredicates = [CPMutableArray array],
subrowsIndexes = [self subrowIndexesForRow:aRow];
if ([subrowsIndexes count] == 0)
if ([subrowsIndexes count] === 0)
return nil;
var current_index = [subrowsIndexes firstIndex];
while (current_index != CPNotFound)
while (current_index !== CPNotFound)
{
var subpredicate = [self predicateForRow:current_index];
if (subpredicate != nil)
if (subpredicate !== nil)
[subpredicates addObject:subpredicate];
current_index = [subrowsIndexes indexGreaterThanIndex:current_index];
@@ -835,7 +836,7 @@ TODO: implement
var compoundType = [predicateParts objectForKey:CPRuleEditorPredicateCompoundType];
if ([subpredicates count] == 0)
if ([subpredicates count] === 0)
return nil;
else
{
@@ -863,16 +864,33 @@ TODO: implement
modifier = [predicateParts objectForKey:CPRuleEditorPredicateComparisonModifier],
selector = CPSelectorFromString([predicateParts objectForKey:CPRuleEditorPredicateCustomSelector]);
if (lhs == nil){ CPLogConsole(@"missing left expression in predicate parts dictionary"); return NULL;}
if (rhs == nil){ CPLogConsole(@"missing right expression in predicate parts dictionary"); return NULL;}
if (selector == nil && operator == nil){ CPLogConsole(@"missing operator and selector in predicate parts dictionary"); return NULL;}
if (lhs === nil)
{
CPLogConsole(@"missing left expression in predicate parts dictionary");
return NULL;
}
if (modifier == nil) CPLogConsole(@"missing modifier in predicate parts dictionary. Setting default: CPDirectPredicateModifier");
if (options == nil) CPLogConsole(@"missing options in predicate parts dictionary. Setting default: CPCaseInsensitivePredicateOption");
if (rhs === nil)
{
CPLogConsole(@"missing right expression in predicate parts dictionary");
return NULL;
}
if (selector === nil && operator === nil)
{
CPLogConsole(@"missing operator and selector in predicate parts dictionary");
return NULL;
}
if (modifier === nil)
CPLogConsole(@"missing modifier in predicate parts dictionary. Setting default: CPDirectPredicateModifier");
if (options === nil)
CPLogConsole(@"missing options in predicate parts dictionary. Setting default: CPCaseInsensitivePredicateOption");
try
{
if (selector != nil)
if (selector !== nil)
predicate = [CPComparisonPredicate
predicateWithLeftExpression:lhs
rightExpression:rhs
@@ -919,7 +937,7 @@ TODO: implement
*/
- (void)setRowClass:(Class)rowClass
{
if (rowClass == [CPMutableDictionary class])
if (rowClass === [CPMutableDictionary class])
rowClass = [_CPRuleEditorRowObject class];
_rowClass = rowClass;
@@ -1095,7 +1113,7 @@ TODO: implement
- (void)keyDown:(CPEvent)event
{
if (!_suppressKeyDownHandling && [self _applicableNestingMode] == CPRuleEditorNestingModeCompound && !_isKeyDown && ([event modifierFlags] & CPAlternateKeyMask))
if (!_suppressKeyDownHandling && [self _applicableNestingMode] === CPRuleEditorNestingModeCompound && !_isKeyDown && ([event modifierFlags] & CPAlternateKeyMask))
{
[_slices makeObjectsPerformSelector:@selector(_configurePlusButtonByRowType:) withObject:CPRuleEditorRowTypeCompound];
}
@@ -1127,7 +1145,7 @@ TODO: implement
- (BOOL)_wantsRowAnimations
{
return (_currentAnimation != nil);
return (_currentAnimation !== nil);
}
- (void)_updateButtonVisibilities
@@ -1150,10 +1168,10 @@ TODO: implement
if (!_nestingModeDidChange)
return _nestingMode;
var a = (_nestingMode == CPRuleEditorNestingModeCompound || _nestingMode == CPRuleEditorNestingModeSimple);
var b = ([self rowTypeForRow:0] == CPRuleEditorRowTypeCompound);
var a = (_nestingMode === CPRuleEditorNestingModeCompound || _nestingMode === CPRuleEditorNestingModeSimple),
b = ([self rowTypeForRow:0] === CPRuleEditorRowTypeCompound);
if (a == b)
if (a === b)
return _nestingMode;
return a ? CPRuleEditorNestingModeList : CPRuleEditorNestingModeSimple;
@@ -1161,7 +1179,7 @@ TODO: implement
- (BOOL)_shouldHideAddButtonForSlice:(id)slice
{
return (!_editable || [self _applicableNestingMode] == CPRuleEditorNestingModeSingle);
return (!_editable || [self _applicableNestingMode] === CPRuleEditorNestingModeSingle);
}
- (BOOL)_shouldHideSubtractButtonForSlice:(id)slice
@@ -1181,9 +1199,9 @@ TODO: implement
switch (nestingMode)
{
case CPRuleEditorNestingModeCompound:
case CPRuleEditorNestingModeSimple: shouldHide = ([subrowsIndexes count] == 1 && !_allowsEmptyCompoundRows) || parentIndex == -1;
case CPRuleEditorNestingModeSimple: shouldHide = ([subrowsIndexes count] === 1 && !_allowsEmptyCompoundRows) || parentIndex === -1;
break;
case CPRuleEditorNestingModeList: shouldHide = ([self numberOfRows] == 1);
case CPRuleEditorNestingModeList: shouldHide = ([self numberOfRows] === 1);
break;
case CPRuleEditorNestingModeSingle: shouldHide = YES;
break;
@@ -1217,7 +1235,7 @@ TODO: implement
- (int)_rowIndexForRowObject:(id)rowobject
{
if (rowobject == _boundArrayOwner)
if (rowobject === _boundArrayOwner)
return -1;
return [[self _searchCacheForRowObject:rowobject] rowIndex]; // Pas bon car le rowIndex du row cache n'est pas synchro avec la position dans _rowCache.
@@ -1236,14 +1254,14 @@ TODO: implement
var childlessParents = [CPIndexSet indexSet],
current_index = [indexes firstIndex];
while (current_index != CPNotFound)
while (current_index !== CPNotFound)
{
var parentIndex = [self parentRowForRow:current_index];
var parentIndex = [self parentRowForRow:current_index],
subrowsIndexes = [self subrowIndexesForRow:parentIndex];
var subrowsIndexes = [self subrowIndexesForRow:parentIndex];
if ([subrowsIndexes count]==1)
if ([subrowsIndexes count] === 1)
{
if (parentIndex != -1)
if (parentIndex !== -1)
return [CPIndexSet indexSetWithIndex:0];
var childlessGranPa = [self _childlessParentsIfSlicesWereDeletedAtIndexes:[CPIndexSet indexSetWithIndex:parentIndex]];
@@ -1262,7 +1280,7 @@ TODO: implement
var subindexes = [indexes copy],
current_index = [indexes firstIndex];
while (current_index != CPNotFound)
while (current_index !== CPNotFound)
{
var sub = [self subrowIndexesForRow:current_index];
[subindexes addIndexes:[self _includeSubslicesForSlicesAtIndexes:sub]];
@@ -1302,7 +1320,7 @@ TODO: implement
childrenCount = [self _queryNumberOfChildrenOfItem:parentItem withRowType:type],
foundIndex = CPNotFound;
if (childrenCount == 0)
if (childrenCount === 0)
return NO;
var current_criterions = [CPMutableArray array],
@@ -1314,34 +1332,34 @@ TODO: implement
var aCriteria = [self criteriaForRow:row],
itemIndex = [items count];
if ([self rowTypeForRow:row] == type && itemIndex < [aCriteria count])
if ([self rowTypeForRow:row] === type && itemIndex < [aCriteria count])
{
var crit = [aCriteria objectAtIndex:itemIndex];
[current_criterions addObject:crit];
}
}
while (foundIndex == CPNotFound)
while (foundIndex === CPNotFound)
{
var buffer = [CPMutableArray arrayWithArray:current_criterions],
i;
for (i = 0; i < childrenCount; i++)
{
var child = [self _queryChild:i ofItem:parentItem withRowType:type];
if ([current_criterions indexOfObject:child] == CPNotFound)
if ([current_criterions indexOfObject:child] === CPNotFound)
{
foundIndex = i;
break;
}
}
if (foundIndex == CPNotFound)
if (foundIndex === CPNotFound)
{
for (var k = 0; k < childrenCount; k++)
{
var anobject = [self _queryChild:k ofItem:parentItem withRowType:type],
index = [buffer indexOfObject:anobject];
if (index != CPNotFound)
if (index !== CPNotFound)
[buffer removeObjectAtIndex:index];
}
@@ -1394,7 +1412,7 @@ TODO: implement
rowTypeEvent = [self rowTypeForRow:rowIndexEvent],
insertIndex = rowIndexEvent + 1;
var parentRowIndex = (rowTypeEvent == CPRuleEditorRowTypeCompound) ? rowIndexEvent:[self parentRowForRow:rowIndexEvent];
var parentRowIndex = (rowTypeEvent === CPRuleEditorRowTypeCompound) ? rowIndexEvent:[self parentRowForRow:rowIndexEvent];
[self insertRowAtIndex:insertIndex withType:type asSubrowOfRow:parentRowIndex animate:YES];
}
@@ -1413,7 +1431,7 @@ TODO: implement
[row setValue:[CPMutableArray array] forKey:_subrowsArrayKeyPath];
var subrowsObjects;
if (parentRowIndex == -1 || [self _applicableNestingMode] == CPRuleEditorNestingModeList)
if (parentRowIndex === -1 || [self _applicableNestingMode] === CPRuleEditorNestingModeList)
subrowsObjects = [self _rootRowsArray];
else
{
@@ -1436,7 +1454,7 @@ TODO: implement
- (void)_startObservingRowObjectsRecursively:(CPArray)rowObjects
{
[_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew context:boundArrayContext];
[_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
var count = [rowObjects count];
@@ -1444,9 +1462,9 @@ TODO: implement
{
var rowObject = [rowObjects objectAtIndex:i];
[rowObject addObserver:self forKeyPath:_itemsKeyPath options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew context:itemsContext];
[rowObject addObserver:self forKeyPath:_valuesKeyPath options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew context:valuesContext];
[rowObject addObserver:self forKeyPath:_subrowsArrayKeyPath options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew context:subrowsContext];
[rowObject addObserver:self forKeyPath:_itemsKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:itemsContext];
[rowObject addObserver:self forKeyPath:_valuesKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:valuesContext];
[rowObject addObserver:self forKeyPath:_subrowsArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:subrowsContext];
var subrows = [self _subrowObjectsOfObject:rowObject];
if ([subrows count] > 0)
@@ -1482,21 +1500,21 @@ TODO: implement
newRows,
oldRows;
if (context == boundArrayContext || context == subrowsContext)
if (context === boundArrayContext || context === subrowsContext)
{
if (changeKind == CPKeyValueChangeSetting)
if (changeKind === CPKeyValueChangeSetting)
{
newRows = changeNewValue;
oldRows = changeOldValue;
}
else if (changeKind == CPKeyValueChangeInsertion)
else if (changeKind === CPKeyValueChangeInsertion)
{
newRows = [self _subrowObjectsOfObject:object];
oldRows = [CPArray arrayWithArray:newRows];
[oldRows removeObjectsInArray:changeNewValue];
}
else if (changeKind == CPKeyValueChangeRemoval)
else if (changeKind === CPKeyValueChangeRemoval)
{
newRows = [self _subrowObjectsOfObject:object];
oldRows = [CPArray arrayWithArray:newRows];
@@ -1507,10 +1525,10 @@ TODO: implement
[self _changedRowArray:newRows withOldRowArray:oldRows forParent:object];
[self _reconfigureSubviewsAnimate:[self _wantsRowAnimations]];
}
else if (context == itemsContext)
else if (context === itemsContext)
{
}
else if (context == valuesContext)
else if (context === valuesContext)
{
}
}
@@ -1574,7 +1592,7 @@ TODO: implement
//var gindexes = [self _globalIndexesForSubrowIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0,oldRowCount)] ofParentObject:parentRowObject];
if (parentCacheIndex == -1)
if (parentCacheIndex === -1)
parentCacheIndentation = -1;
else
parentCacheIndentation = [[self _rowCacheForIndex:parentCacheIndex] indentation];
@@ -1603,17 +1621,18 @@ TODO: implement
var oldrow = [oldRows objectAtIndex:changeStartIndex],
newrow = [newRows objectAtIndex:changeStartIndex];
if (newrow != oldrow)
if (newrow !== oldrow)
break;
}
var replaceCount = (deltaCount == 0) ? maxCount : maxCount - minusCount;
var startIndex = parentCacheIndex + changeStartIndex + 1;
var replaceCount = (deltaCount === 0) ? maxCount : maxCount - minusCount,
startIndex = parentCacheIndex + changeStartIndex + 1;
if (deltaCount <= 0)
{
var removeIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(startIndex, replaceCount)];
var removeSlices = [_slices objectsAtIndexes:removeIndexes];
var removeIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(startIndex, replaceCount)],
removeSlices = [_slices objectsAtIndexes:removeIndexes];
[removeSlices makeObjectsPerformSelector:@selector(removeFromSuperview)];
[_slices removeObjectsAtIndexes:removeIndexes];
}
@@ -1694,7 +1713,7 @@ TODO: implement
//var boundRows = [_boundArrayOwner valueForKey:_boundArrayKeyPath];
[_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld|CPKeyValueObservingOptionNew context:boundArrayContext];
[_boundArrayOwner addObserver:self forKeyPath:_boundArrayKeyPath options:CPKeyValueObservingOptionOld | CPKeyValueObservingOptionNew context:boundArrayContext];
//if ([boundRows isKindOfClass:[CPArray class]] && [boundRows count] > 0)
// [_boundArrayOwner setValue:boundRows forKey:_boundArrayKeyPath];
@@ -1721,11 +1740,11 @@ TODO: implement
subindexes = [self subrowIndexesForRow:-1],
current_index = [subindexes firstIndex];
while (current_index != CPNotFound)
while (current_index !== CPNotFound)
{
var subpredicate = [self predicateForRow:current_index];
if (subpredicate != nil)
if (subpredicate !== nil)
[subpredicates addObject:subpredicate];
current_index = [subindexes indexGreaterThanIndex:current_index];
@@ -1767,7 +1786,7 @@ TODO: implement
startRect = [aslice frame],
startIndex = [aslice rowIndex] - 1;
if ([aslice superview] == nil)
if ([aslice superview] === nil)
{
startRect = CGRectMake(0, startIndex * _sliceHeight, CGRectGetWidth(startRect), _sliceHeight);
[aslice _reconfigureSubviews];
@@ -1799,7 +1818,7 @@ TODO: implement
_lastRow = [self numberOfRows] - 1;
if (_lastRow == -1)
if (_lastRow === -1)
_nestingModeDidChange = NO;
[self setNeedsDisplay:YES];
@@ -1893,7 +1912,7 @@ TODO: implement
{
var current_index = [indexes firstIndex];
while (current_index !=CPNotFound)
while (current_index !== CPNotFound)
{
var subindexes = [self subrowIndexesForRow:index];
[self _updateSliceIndentationAtIndex:current_index toIndentation:indentation + 1 withIndexSet:subindexes];
@@ -1937,7 +1956,7 @@ TODO: implement
- (void)_mouseUpOnSlice:(id)slice withEvent:(CPEvent)event
{
if ([slice _rowType] != CPRuleEditorRowTypeSimple)
if ([slice _rowType] !== CPRuleEditorRowTypeSimple)
return;
var modifierFlags = [event modifierFlags],
@@ -2045,7 +2064,7 @@ TODO: implement
{
[self setNeedsDisplay:YES];
if (CGRectGetWidth([self frame]) != size.width)
if (CGRectGetWidth([self frame]) !== size.width)
[_slices makeObjectsPerformSelector:@selector(setNeedsLayout)];
[super setFrameSize:size];
@@ -2081,7 +2100,7 @@ TODO: implement
- (BOOL)_dragShouldBeginFromMouseDown:(CPView)view
{
return (([self nestingMode] == CPRuleEditorNestingModeList || [view rowIndex] != 0) && _editable && [view isKindOfClass:[_CPRuleEditorViewSliceRow class]] && _draggingRows == nil);
return (([self nestingMode] === CPRuleEditorNestingModeList || [view rowIndex] !== 0) && _editable && [view isKindOfClass:[_CPRuleEditorViewSliceRow class]] && _draggingRows === nil);
}
- (BOOL)_performDragForSlice:(id)slice withEvent:(CPEvent)event
@@ -2124,7 +2143,7 @@ TODO: implement
- (CPDragOperation)draggingEntered:(id < CPDraggingInfo >)sender
{
if ([sender draggingSource] == self)
if ([sender draggingSource] === self)
{
[self _clearDropLine];
return CPDragOperationMove;
@@ -2143,7 +2162,7 @@ TODO: implement
{
[_dropLineView setAlphaValue:0];
if (_subviewIndexOfDropLine != CPNotFound && _subviewIndexOfDropLine < _lastRow)
if (_subviewIndexOfDropLine !== CPNotFound && _subviewIndexOfDropLine < _lastRow)
{
var previousBelowSlice = [_slices objectAtIndex:_subviewIndexOfDropLine];
[previousBelowSlice setFrameOrigin:CGPointMake(0, [previousBelowSlice rowIndex] * _sliceHeight)];
@@ -2155,20 +2174,20 @@ TODO: implement
- (CPDragOperation)draggingUpdated:(id <CPDraggingInfo>)sender
{
var point = [self convertPoint:[sender draggingLocation] fromView:nil],
y = point.y + _sliceHeight /2,
y = point.y + _sliceHeight / 2,
indexOfDropLine = FLOOR(y / _sliceHeight),
numberOfRows = [self numberOfRows];
if (indexOfDropLine < 0 || indexOfDropLine > numberOfRows || (indexOfDropLine >= [_draggingRows firstIndex] && indexOfDropLine <= [_draggingRows lastIndex] + 1))
{
if (_subviewIndexOfDropLine != CPNotFound && indexOfDropLine != _subviewIndexOfDropLine)
if (_subviewIndexOfDropLine !== CPNotFound && indexOfDropLine !== _subviewIndexOfDropLine)
[self _clearDropLine];
return CPDragOperationNone;
}
if (_subviewIndexOfDropLine != indexOfDropLine)
if (_subviewIndexOfDropLine !== indexOfDropLine)
{
if (_subviewIndexOfDropLine != CPNotFound && _subviewIndexOfDropLine < numberOfRows)
if (_subviewIndexOfDropLine !== CPNotFound && _subviewIndexOfDropLine < numberOfRows)
{
var previousBelowSlice = [_slices objectAtIndex:_subviewIndexOfDropLine];
[previousBelowSlice setFrameOrigin:CPMakePoint(0, [previousBelowSlice rowIndex] * _sliceHeight)];
@@ -2191,7 +2210,7 @@ TODO: implement
- (BOOL)prepareForDragOperation:(id < CPDraggingInfo >)sender
{
return (_subviewIndexOfDropLine != CPNotFound);
return (_subviewIndexOfDropLine !== CPNotFound);
}
- (BOOL)performDragOperation:(id < CPDraggingInfo >)info
@@ -2203,11 +2222,11 @@ TODO: implement
var rowObjects = [_rowCache valueForKey:@"rowObject"],
index = [_draggingRows lastIndex];
var parentRowIndex = [self parentRowForRow:index]; // first index of draggingrows
var parentRowObject = (parentRowIndex == -1) ? _boundArrayOwner : [[self _rowCacheForIndex:parentRowIndex] rowObject];
var insertIndex = _subviewIndexOfDropLine;
var parentRowIndex = [self parentRowForRow:index], // first index of draggingrows
parentRowObject = (parentRowIndex === -1) ? _boundArrayOwner : [[self _rowCacheForIndex:parentRowIndex] rowObject],
insertIndex = _subviewIndexOfDropLine;
while (index != CPNotFound)
while (index !== CPNotFound)
{
if (index >= insertIndex)
{
@@ -2286,12 +2305,12 @@ TODO: implement
current_index = [indexes firstIndex],
numberOfChildrenOfPreviousBrother = 0;
while (current_index != CPNotFound)
while (current_index !== CPNotFound)
{
var globalChildIndex = current_index + parentRowIndex + 1 + numberOfChildrenOfPreviousBrother;
[globalIndexes addIndex:globalChildIndex];
if ([self rowTypeForRow:globalChildIndex] == CPRuleEditorRowTypeCompound)
if ([self rowTypeForRow:globalChildIndex] === CPRuleEditorRowTypeCompound)
{
var rowObject = [[self _rowCacheForIndex:current_index] rowObject],
subrows = [self _subrowObjectsOfObject:rowObject];
@@ -2338,8 +2357,8 @@ TODO: implement
var criteria = [self criteriaForRow:aRow];
indexofCriterion = [criteria indexOfObject:criterion];
if (parentItem != nil
&& indexofCriterion != CPNotFound
if (parentItem !== nil
&& indexofCriterion !== CPNotFound
&& indexofCriterion < [criteria count] - 1)
{
var next = indexofCriterion + 1;
@@ -2355,10 +2374,10 @@ TODO: implement
var availChild = aChild,
availValue = value;
if ( criterion != aChild )
if (criterion !== aChild)
availValue = [self _queryValueForItem:aChild inRow:aRow];
if ( !availValue )
if (!availValue)
availValue = [self _queryValueForItem:availChild inRow:aRow];
[availItems addObject:availChild];
@@ -2394,7 +2413,7 @@ var CPRuleEditorAlignmentGridWidthKey = @"CPRuleEditorAlignmentGridWidth",
- (id)initWithCoder:(CPCoder)coder
{
self = [super initWithCoder:coder];
if (self != nil)
if (self !== nil)
{
[self setFormattingStringsFilename:[coder decodeObjectForKey:CPRuleEditorStringsFilenameKey]];
_alignmentGridWidth = [coder decodeFloatForKey:CPRuleEditorAlignmentGridWidthKey];
@@ -2478,7 +2497,7 @@ var CriteriaKey = @"criteria",
- (id)initWithCoder:(id)coder
{
self = [super init];
if (self != nil)
if (self !== nil)
{
subrows = [coder decodeObjectForKey:SubrowsKey];
criteria = [coder decodeObjectForKey:CriteriaKey];
@@ -2508,7 +2527,7 @@ var CriteriaKey = @"criteria",
- (CPString)description
{
return [CPString stringWithFormat:@"<%d object:%d rowIndex:%d indentation:%d>",[self hash], [rowObject hash], rowIndex, indentation];
return [CPString stringWithFormat:@"<%d object:%d rowIndex:%d indentation:%d>", [self hash], [rowObject hash], rowIndex, indentation];
}
@end
@@ -2574,21 +2593,23 @@ var dropSeparatorColor = [CPColor colorWithHexString:@"4886ca"];
- (int)valueType
{
var result = 0;
var result = 0,
isString = [self isKindOfClass:CPString];
var isString = [self isKindOfClass:[CPString class]];
if ( !isString )
if (!isString)
{
var isView = [self isKindOfClass:[CPView class]];
var isView = [self isKindOfClass:CPView];
result = 1;
if ( !isView )
if (!isView)
{
var ismenuItem = [self isKindOfClass:[CPMenuItem class]];
var ismenuItem = [self isKindOfClass:CPMenuItem];
result = 2;
if ( !ismenuItem )
if (!ismenuItem)
{
[CPException raise:CPGenericException reason:@"Unknown Type For " + self];
result = -1;
[CPException raise:CPGenericException reason:@"Unknown type for " + self];
result = -1;
}
}
}
@@ -2597,4 +2618,4 @@ var dropSeparatorColor = [CPColor colorWithHexString:@"4886ca"];
}
@end
/*! @endcond */
/*! @endcond */
@@ -28,11 +28,10 @@
node.tree = aTree;
var template = [aTree template],
uuid = [template UID];
uuid = [template UID],
cachedNode = templateTable[uuid];
var cachedNode = templateTable[uuid];
if (cachedNode == nil)
if (cachedNode === nil)
{
views = [CPMutableArray array];
copiedContainer = [CPMutableArray array];
@@ -67,6 +66,7 @@
- (BOOL)applyTemplate:(id)template withViews:(id)views forOriginalTemplate:(id)originalTemplate
{
var t = [tree template];
if (t !== template)
{
[templateViews setArray:views];
@@ -75,6 +75,7 @@
}
var count = [children count];
for (var i; i < count; i++)
[children[i] applyTemplate:template withViews:views forOriginalTemplate:originalTemplate];
}
@@ -89,7 +90,7 @@
- (void)copyTemplateIfNecessary
{
if ([copiedTemplateContainer count] == 0)
if ([copiedTemplateContainer count] === 0)
{
var copy = [[tree template] copy];
[copiedTemplateContainer addObject:copy];
@@ -117,7 +118,8 @@
- (id)displayValue
{
var title = [self title];
if (title != nil)
if (title !== nil)
return title;
return [self templateView];
@@ -128,4 +130,4 @@
return [CPString stringWithFormat:@"<%@ %@ %@ tree:%@ tviews:%@", [self className],[self UID], [self title], [tree UID], [templateViews description]];
}
@end
@end
+120 -78
View File
@@ -30,38 +30,40 @@
@import "CPScroller.j"
@import "CPView.j"
#define SHOULD_SHOW_CORNER_VIEW() (_scrollerStyle === CPScrollerStyleLegacy && _verticalScroller && ![_verticalScroller isHidden])
/*! @ignore */
var _isSystemUsingOverlayScrollers = function()
{
#if PLATFORM(DOM)
var inner = document.createElement('p'),
outer = document.createElement('div');
var inner = document.createElement('p'),
outer = document.createElement('div');
inner.style.width = "100%";
inner.style.height = "200px";
inner.style.width = "100%";
inner.style.height = "200px";
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2)
w2 = outer.clientWidth;
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2)
w2 = outer.clientWidth;
document.body.removeChild (outer);
document.body.removeChild (outer);
return (w1 - w2 == 0);
return (w1 - w2 == 0);
#else
return NO;
return NO;
#endif
};
@@ -272,7 +274,19 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
}
/*!
Set the delegate of the scroll view
Sets the delegate of the scroll view.
Possible delegate methods to implement are listed below.
Notifies the delegate when the scroll view is about to scroll.
@code
- (void)scrollViewWillScroll:(CPScrollView)aScrollView
@endcode
Notifies the delegate when the scroll view has finished scrolling.
@code
- (void)scrollViewDidScroll:(CPScrollView)aScrollView
@endcode
*/
- (void)setDelegate:(id)aDelegate
{
@@ -737,35 +751,42 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
{
[_horizontalScroller setStyle:_scrollerStyle];
[_horizontalScroller unsetThemeState:CPThemeStateSelected];
switch (_scrollerKnobStyle)
{
case CPScrollerKnobStyleLight:
[_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
[_horizontalScroller setThemeState:CPThemeStateScrollerKnobLight];
break;
case CPScrollerKnobStyleDark:
[_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
[_horizontalScroller setThemeState:CPThemeStateScrollerKnobDark];
break;
default:
[_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
[_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
}
}
if (_hasVerticalScroller)
{
[_verticalScroller setStyle:_scrollerStyle];
[_verticalScroller unsetThemeState:CPThemeStateSelected];
switch (_scrollerKnobStyle)
{
case CPScrollerKnobStyleLight:
[_verticalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
[_verticalScroller setThemeState:CPThemeStateScrollerKnobLight];
break;
case CPScrollerKnobStyleDark:
[_verticalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
[_verticalScroller setThemeState:CPThemeStateScrollerKnobDark];
break;
default:
[_verticalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
[_verticalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
@@ -776,6 +797,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
{
if (_timerScrollersHide)
[_timerScrollersHide invalidate];
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
[[self bottomCornerView] setHidden:YES];
}
@@ -813,10 +835,15 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
_cornerView = documentCornerView;
if (_cornerView)
{
[_cornerView setHidden:!SHOULD_SHOW_CORNER_VIEW()];
[self addSubview:_cornerView];
}
}
[self reflectScrolledClipView:_contentView];
[documentHeaderView setNeedsLayout];
[documentHeaderView setNeedsDisplay:YES];
}
/* @ignore */
@@ -851,7 +878,9 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
var frame = [self _insetBounds];
frame.size.height = _CGRectGetHeight([headerView frame]);
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
if (SHOULD_SHOW_CORNER_VIEW())
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
return frame;
}
@@ -1138,8 +1167,9 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
if (_scrollerStyle === CPScrollerStyleOverlay && hasHorizontalScroll)
verticalScrollerHeight -= horizontalScrollerHeight;
var documentHeight = _CGRectGetHeight(documentFrame);
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
[_verticalScroller setKnobProportion:_CGRectGetHeight(contentFrame) / _CGRectGetHeight(documentFrame)];
[_verticalScroller setKnobProportion:documentHeight > 0 ? _CGRectGetHeight(contentFrame) / documentHeight : 1.0];
[_verticalScroller setFrame:_CGRectMake(_CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)];
}
else if (wasShowingVerticalScroller)
@@ -1155,8 +1185,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
if (_scrollerStyle === CPScrollerStyleOverlay && hasVerticalScroll)
horizontalScrollerWidth -= verticalScrollerWidth;
var documentWidth = _CGRectGetWidth(documentFrame);
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
[_horizontalScroller setKnobProportion:_CGRectGetWidth(contentFrame) / _CGRectGetWidth(documentFrame)];
[_horizontalScroller setKnobProportion:documentWidth > 0 ? _CGRectGetWidth(contentFrame) / documentWidth : 1.0];
[_horizontalScroller setFrame:_CGRectMake(_CGRectGetMinX(contentFrame), _CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)];
}
else if (wasShowingHorizontalScroller)
@@ -1166,9 +1198,15 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
}
[_contentView setFrame:contentFrame];
[_headerClipView setFrame:headerClipViewFrame];
[_headerClipView setFrame:[self _headerClipViewFrame]];
[[_headerClipView documentView] setNeedsDisplay:YES];
[_cornerView setFrame:[self _cornerViewFrame]];
if (SHOULD_SHOW_CORNER_VIEW())
{
[_cornerView setFrame:[self _cornerViewFrame]];
[_cornerView setHidden:NO];
}
else
[_cornerView setHidden:YES];
if (_scrollerStyle === CPScrollerStyleLegacy)
{
@@ -1201,6 +1239,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
if (_timerScrollersHide)
[_timerScrollersHide invalidate]
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
}
@@ -1248,70 +1287,67 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
- (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect
{
CGContextBeginPath(context);
var minX = _CGRectGetMinX(aRect),
maxX = _CGRectGetMaxX(aRect),
minY = _CGRectGetMinY(aRect),
maxY = _CGRectGetMaxY(aRect),
y = minY + 0.5;
// Slightly darker line on top.
CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]);
var y = _CGRectGetMinY(aRect) + 0.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 1.0, y);
CGContextBeginPath(context);
CGContextMoveToPoint(context, minX, y);
CGContextAddLineToPoint(context, maxX, y);
CGContextStrokePath(context);
CGContextBeginPath(context);
// The rest of the border.
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextStrokePath(context);
var x = maxX - 0.5;
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]);
CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y);
CGContextStrokePath(context);
CGContextMoveToPoint(context, x, minY + 1.0);
CGContextAddLineToPoint(context, x, maxY);
CGContextMoveToPoint(context, x - 0.5, maxY - 0.5);
CGContextAddLineToPoint(context, minX, maxY - 0.5);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:190.0 / 255.0 alpha:1.0]);
x = minX + 0.5;
var x = _CGRectGetMaxX(aRect) - 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 1.0);
CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextMoveToPoint(context, x - 0.5, _CGRectGetMaxY(aRect) - 0.5);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect), _CGRectGetMaxY(aRect) - 0.5);
x = _CGRectGetMinX(aRect) + 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect) + 1.0);
CGContextMoveToPoint(context, x, maxY);
CGContextAddLineToPoint(context, x, minY + 1.0);
CGContextStrokePath(context);
}
- (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect
{
var minX = _CGRectGetMinX(aRect),
maxX = _CGRectGetMaxX(aRect),
minY = _CGRectGetMinY(aRect),
maxY = _CGRectGetMaxY(aRect);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:159.0 / 255.0 alpha:1.0]);
var y = _CGRectGetMinY(aRect) + 0.5;
var y = minY + 0.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y);
CGContextMoveToPoint(context, minX, y);
CGContextAddLineToPoint(context, maxX, y);
var x = _CGRectGetMaxX(aRect) - 1.5;
var x = maxX - 1.5;
CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 2.0);
CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect) - 1.0);
CGContextMoveToPoint(context, x, minY + 2.0);
CGContextAddLineToPoint(context, x, maxY - 1.0);
y = _CGRectGetMaxY(aRect) - 1.5;
y = maxY - 1.5;
CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y);
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 2.0, y);
CGContextMoveToPoint(context, maxX - 1.0, y);
CGContextAddLineToPoint(context, minX + 2.0, y);
x = _CGRectGetMinX(aRect) + 0.5;
x = minX + 0.5;
CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect));
CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect));
CGContextMoveToPoint(context, x, maxY);
CGContextAddLineToPoint(context, x, minY);
CGContextStrokePath(context);
@@ -1327,10 +1363,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
y = _CGRectGetMinY(aRect) + 2.5;
y = minY + 2.5;
CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 2.0, y);
CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 2.0, y);
CGContextMoveToPoint(context, minX + 2.0, y);
CGContextAddLineToPoint(context, maxX - 2.0, y);
CGContextStrokePath(context);
}
@@ -1470,21 +1506,27 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
_scrollTimer = nil;
_implementedDelegateMethods = 0;
// Due to the anything goes nature of decoding, our subviews may not exist yet, so layout at the end of the run loop when we're sure everything is in a correct state.
[[CPRunLoop currentRunLoop] performSelector:@selector(_updateCornerAndHeaderView) target:self argument:_contentView order:0 modes:[CPDefaultRunLoopMode]];
[self setScrollerStyle:[aCoder decodeIntForKey:CPScrollViewScrollerStyleKey] || CPScrollerStyleGlobal];
[self setScrollerKnobStyle:[aCoder decodeIntForKey:CPScrollViewScrollerKnobStyleKey] || CPScrollerKnobStyleDefault];
_scrollerStyle = [aCoder decodeObjectForKey:CPScrollViewScrollerStyleKey] || CPScrollerStyleGlobal;
_scrollerKnobStyle = [aCoder decodeObjectForKey:CPScrollViewScrollerKnobStyleKey] || CPScrollerKnobStyleDefault;
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
}
return self;
}
/*!
Do final init that can only be done when we are sure all subviews have been initialized.
*/
- (void)awakeFromCib
{
[self _updateScrollerStyle];
[self _updateCornerAndHeaderView];
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
+12 -2
View File
@@ -23,6 +23,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../Foundation/Foundation.h"
@import "CPControl.j"
// CPScroller Constants
@@ -260,6 +262,9 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
*/
- (void)setKnobProportion:(float)aProportion
{
if (!_IS_NUMERIC(aProportion))
[CPException raise:CPInvalidArgumentException reason:"aProportion must be numeric"];
_knobProportion = MIN(1.0, MAX(0.0001, aProportion));
[self setNeedsDisplay:YES];
@@ -766,6 +771,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
if (_timerFadeOut)
[_timerFadeOut invalidate];
_timerFadeOut = [CPTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(_performFadeOut:) userInfo:nil repeats:NO];
}
@@ -791,10 +797,12 @@ var CPScrollerControlSizeKey = @"CPScrollerControlSize",
if (self = [super initWithCoder:aCoder])
{
_controlSize = CPRegularControlSize;
if ([aCoder containsValueForKey:CPScrollerControlSizeKey])
_controlSize = [aCoder decodeIntForKey:CPScrollerControlSizeKey];
_knobProportion = 1.0;
if ([aCoder containsValueForKey:CPScrollerKnobProportionKey])
_knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
@@ -804,8 +812,10 @@ var CPScrollerControlSizeKey = @"CPScrollerControlSize",
_allowFadingOut = YES;
_isMouseOver = NO;
var paramAnimFadeOut = [CPDictionary dictionaryWithObjects:[self, CPViewAnimationFadeOutEffect]
forKeys:[CPViewAnimationTargetKey, CPViewAnimationEffectKey]];
var paramAnimFadeOut = [CPDictionary dictionaryWithObjects:[self, CPViewAnimationFadeOutEffect]
forKeys:[CPViewAnimationTargetKey, CPViewAnimationEffectKey]];
_animationScroller = [[CPViewAnimation alloc] initWithDuration:0.2 animationCurve:CPAnimationEaseInOut];
[_animationScroller setViewAnimations:[paramAnimFadeOut]];
[_animationScroller setDelegate:self];
+2 -2
View File
@@ -173,7 +173,7 @@ var RECENT_SEARCH_PREFIX = @" ";
searchButtonImage = (_searchMenuTemplate === nil) ? CPSearchFieldSearchImage : CPSearchFieldFindImage;
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImageScaling:CPImageScaleAxesIndependently];
[button setImage:searchButtonImage];
[button setAutoresizingMask:CPViewMaxXMargin];
}
@@ -215,7 +215,7 @@ var RECENT_SEARCH_PREFIX = @" ";
{
var button = [self cancelButton];
[button setBordered:NO];
[button setImageScaling:CPScaleToFit];
[button setImageScaling:CPImageScaleAxesIndependently];
[button setImage:CPSearchFieldCancelImage];
[button setAlternateImage:CPSearchFieldCancelPressedImage];
[button setAutoresizingMask:CPViewMinXMargin];
+1 -1
View File
@@ -55,7 +55,7 @@ CPSegmentSwitchTrackingMomentary = 2;
+ (id)themeAttributes
{
return [CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPScaleNone, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null], 1.0, 24.0]
return [CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPImageScaleNone, _CGInsetMakeZero(), _CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null], 1.0, 24.0]
forKeys:[@"alignment", @"vertical-alignment", @"image-position", @"image-scaling", @"bezel-inset", @"content-inset", @"left-segment-bezel-color", @"right-segment-bezel-color", @"center-segment-bezel-color", @"divider-bezel-color", @"divider-thickness", @"default-height"]];
}
+38 -37
View File
@@ -47,7 +47,6 @@ var LIGHT_LEFT_INSET = 3.0,
/*!
@ingroup appkit
*/
@implementation CPShadowView : CPView
{
CPShadowWeight _weight;
@@ -60,35 +59,33 @@ var LIGHT_LEFT_INSET = 3.0,
var bundle = [CPBundle bundleForClass:[self class]];
CPShadowViewLightBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopLeft.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTop.png"] size:CGSizeMake(1.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopRight.png"] size:CGSizeMake(9.0, 9.0)],
CPShadowViewLightBackgroundColor = CPColorWithImages([
[@"CPShadowView/CPShadowViewLightTopLeft.png", 9.0, 9.0, bundle],
[@"CPShadowView/CPShadowViewLightTop.png", 1.0, 9.0, bundle],
[@"CPShadowView/CPShadowViewLightTopRight.png", 9.0, 9.0, bundle],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightLeft.png"] size:CGSizeMake(9.0, 1.0)],
nil,
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightRight.png"] size:CGSizeMake(9.0, 1.0)],
[@"CPShadowView/CPShadowViewLightLeft.png", 9.0, 1.0, bundle],
nil,
[@"CPShadowView/CPShadowViewLightRight.png", 9.0, 1.0, bundle],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomLeft.png"] size:CGSizeMake(9.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottom.png"] size:CGSizeMake(1.0, 9.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomRight.png"] size:CGSizeMake(9.0, 9.0)]
]]];
[@"CPShadowView/CPShadowViewLightBottomLeft.png", 9.0, 9.0, bundle],
[@"CPShadowView/CPShadowViewLightBottom.png", 1.0, 9.0, bundle],
[@"CPShadowView/CPShadowViewLightBottomRight.png", 9.0, 9.0, bundle]
]);
CPShadowViewHeavyBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
[
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopLeft.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTop.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopRight.png"] size:CGSizeMake(17.0, 17.0)],
CPShadowViewHeavyBackgroundColor = CPColorWithImages([
[@"CPShadowView/CPShadowViewHeavyTopLeft.png", 17.0, 17.0, bundle],
[@"CPShadowView/CPShadowViewHeavyTop.png", 1.0, 17.0, bundle],
[@"CPShadowView/CPShadowViewHeavyTopRight.png", 17.0, 17.0, bundle],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyLeft.png"] size:CGSizeMake(17.0, 1.0)],
nil,
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyRight.png"] size:CGSizeMake(17.0, 1.0)],
[@"CPShadowView/CPShadowViewHeavyLeft.png", 17.0, 1.0, bundle],
nil,
[@"CPShadowView/CPShadowViewHeavyRight.png", 17.0, 1.0, bundle],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomLeft.png"] size:CGSizeMake(17.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottom.png"] size:CGSizeMake(1.0, 17.0)],
[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomRight.png"] size:CGSizeMake(17.0, 17.0)]
]]];
[@"CPShadowView/CPShadowViewHeavyBottomLeft.png", 17.0, 17.0, bundle],
[@"CPShadowView/CPShadowViewHeavyBottom.png", 1.0, 17.0, bundle],
[@"CPShadowView/CPShadowViewHeavyBottomRight.png", 17.0, 17.0, bundle]
]);
}
+ (id)shadowViewEnclosingView:(CPView)aView
@@ -98,20 +95,24 @@ var LIGHT_LEFT_INSET = 3.0,
+ (id)shadowViewEnclosingView:(CPView)aView withWeight:(CPShadowWeight)aWeight
{
var shadowView = [[CPShadowView alloc] initWithFrame:[aView frame]];
[shadowView setWeight:aWeight];
var shadowView = [[self alloc] initWithFrame:[aView frame]];
var size = [shadowView frame].size,
width = size.width - [shadowView leftInset] - [shadowView rightInset],
height = size.height - [shadowView topInset] - [shadowView bottomInset],
enclosingView = [aView superview];
if (shadowView)
{
[shadowView setWeight:aWeight];
[shadowView setHitTests:[aView hitTests]];
[shadowView setAutoresizingMask:[aView autoresizingMask]];
[aView removeFromSuperview];
[shadowView addSubview:aView];
[aView setFrame:CGRectMake([shadowView leftInset], [shadowView topInset], width, height)]
[enclosingView addSubview:shadowView];
var size = [shadowView frame].size,
width = size.width - [shadowView leftInset] - [shadowView rightInset],
height = size.height - [shadowView topInset] - [shadowView bottomInset],
enclosingView = [aView superview];
[shadowView setHitTests:[aView hitTests]];
[shadowView setAutoresizingMask:[aView autoresizingMask]];
[aView removeFromSuperview];
[shadowView addSubview:aView];
[aView setFrame:CGRectMake([shadowView leftInset], [shadowView topInset], width, height)]
[enclosingView addSubview:shadowView];
}
return shadowView;
}
+125 -53
View File
@@ -117,8 +117,9 @@ var CPSplitViewHorizontalImage = nil,
return;
var bundle = [CPBundle bundleForClass:self];
CPSplitViewHorizontalImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSplitView/CPSplitViewHorizontal.png"] size:CPSizeMake(5.0, 10.0)];
CPSplitViewVerticalImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSplitView/CPSplitViewVertical.png"] size:CPSizeMake(10.0, 5.0)];
CPSplitViewHorizontalImage = CPImageInBundle("CPSplitView/CPSplitViewHorizontal.png", CGSizeMake(5.0, 10.0), bundle);
CPSplitViewVerticalImage = CPImageInBundle("CPSplitView/CPSplitViewVertical.png", CGSizeMake(10.0, 5.0), bundle);
}
- (id)initWithFrame:(CGRect)aFrame
@@ -178,14 +179,17 @@ var CPSplitViewHorizontalImage = nil,
count = _subviews.length;
if ([self isVertical])
{
for (; index < count; ++index)
[_subviews[index] setFrame:CGRectMake(ROUND((eachSize + dividerThickness) * index), 0, eachSize, frame.size.height)];
}
else
{
for (; index < count; ++index)
[_subviews[index] setFrame:CGRectMake(0, ROUND((eachSize + dividerThickness) * index), frame.size.width, eachSize)];
}
[self setNeedsDisplay:YES];
[self _postNotificationDidResize];
}
@@ -261,7 +265,6 @@ var CPSplitViewHorizontalImage = nil,
rect = CGRectMakeZero();
rect.size = [self frame].size;
rect.size[_sizeComponent] = [self dividerThickness];
rect.origin[_originComponent] = frame.origin[_originComponent] + frame.size[_sizeComponent];
@@ -370,28 +373,33 @@ var CPSplitViewHorizontalImage = nil,
_needsResizeSubviews = NO;
[self resizeSubviewsWithOldSize:[self _calculateSize]];
}
- (CGSize)_calculateSize
{
var subviews = [self subviews],
count = subviews.length,
oldSize = CGSizeMakeZero();
size = CGSizeMakeZero();
if ([self isVertical])
{
oldSize.width += [self dividerThickness] * (count - 1);
oldSize.height = CGRectGetHeight([self frame]);
size.width += [self dividerThickness] * (count - 1);
size.height = CGRectGetHeight([self frame]);
}
else
{
oldSize.width = CGRectGetWidth([self frame]);
oldSize.height += [self dividerThickness] * (count - 1);
size.width = CGRectGetWidth([self frame]);
size.height += [self dividerThickness] * (count - 1);
}
while (count--)
oldSize[_sizeComponent] += [subviews[count] frame].size[_sizeComponent];
size[_sizeComponent] += [subviews[count] frame].size[_sizeComponent];
[self resizeSubviewsWithOldSize:oldSize];
return size;
}
- (BOOL)cursorAtPoint:(CPPoint)aPoint hitDividerAtIndex:(int)anIndex
- (BOOL)cursorAtPoint:(CGPoint)aPoint hitDividerAtIndex:(int)anIndex
{
var frame = [_subviews[anIndex] frame],
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent],
@@ -455,10 +463,11 @@ var CPSplitViewHorizontalImage = nil,
if (type == CPLeftMouseDown)
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
count = [_subviews count] - 1;
_currentDivider = CPNotFound;
var count = [_subviews count] - 1;
for (var i = 0; i < count; i++)
{
var frame = [_subviews[i] frame],
@@ -574,9 +583,11 @@ var CPSplitViewHorizontalImage = nil,
if (sizeA === 0)
canGrow = YES; // Subview is collapsed.
else if (!canShrink &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i]])
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i]])
{
canShrink = YES; // Subview is collapsible.
}
if (sizeB === 0)
{
@@ -586,9 +597,11 @@ var CPSplitViewHorizontalImage = nil,
canShrink = YES;
}
else if (!canGrow &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i + 1]])
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i + 1]])
{
canGrow = YES; // Right/lower subview is collapsible.
}
if (_isVertical && canShrink && canGrow)
cursor = [CPCursor resizeLeftRightCursor];
@@ -665,6 +678,7 @@ var CPSplitViewHorizontalImage = nil,
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
{
var proposedActualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
if (_IS_NUMERIC(proposedActualMin))
actualMin = proposedActualMin;
}
@@ -672,6 +686,7 @@ var CPSplitViewHorizontalImage = nil,
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
{
var proposedActualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
if (_IS_NUMERIC(proposedActualMax))
actualMax = proposedActualMax;
}
@@ -685,6 +700,7 @@ var CPSplitViewHorizontalImage = nil,
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
if ([_delegate splitView:self canCollapseSubview:viewA])
realPosition = proposedMin;
// We can also collapse to the right.
if (position > proposedMax - (proposedMax - actualMax) / 2)
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
@@ -704,18 +720,19 @@ var CPSplitViewHorizontalImage = nil,
SPLIT_VIEW_SUPPRESS_RESIZE_NOTIFICATIONS(YES);
[self _adjustSubviewsWithCalculatedSize];
var realPosition = [self _realPositionForPosition:position ofDividerAtIndex:dividerIndex];
var viewA = _subviews[dividerIndex],
var realPosition = [self _realPositionForPosition:position ofDividerAtIndex:dividerIndex],
viewA = _subviews[dividerIndex],
frameA = [viewA frame],
viewB = _subviews[dividerIndex + 1],
frameB = [viewB frame],
_preCollapsePosition = 0;
_preCollapsePosition = 0,
preSize = frameA.size[_sizeComponent];
var preSize = frameA.size[_sizeComponent];
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
if (preSize !== 0 && frameA.size[_sizeComponent] === 0)
_preCollapsePosition = preSize;
if (preSize !== frameA.size[_sizeComponent])
{
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
@@ -724,11 +741,15 @@ var CPSplitViewHorizontalImage = nil,
}
preSize = frameB.size[_sizeComponent];
var preOrigin = frameB.origin[_originComponent];
frameB.size[_sizeComponent] = frameB.origin[_originComponent] + frameB.size[_sizeComponent] - realPosition - [self dividerThickness];
if (preSize !== 0 && frameB.size[_sizeComponent] === 0)
_preCollapsePosition = frameB.origin[_originComponent];
frameB.origin[_originComponent] = realPosition + [self dividerThickness];
if (preSize !== frameB.size[_sizeComponent] || preOrigin !== frameB.origin[_originComponent])
{
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
@@ -743,6 +764,7 @@ var CPSplitViewHorizontalImage = nil,
if (SPLIT_VIEW_DID_SUPPRESS_RESIZE_NOTIFICATION())
[self _postNotificationDidResize];
SPLIT_VIEW_SUPPRESS_RESIZE_NOTIFICATIONS(NO);
}
@@ -773,66 +795,101 @@ var CPSplitViewHorizontalImage = nil,
return;
}
[self adjustSubviews];
}
- (void)adjustSubviews
{
var count = [_subviews count];
if (!count)
return;
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
[self _postNotificationWillResize];
var index = 0,
count = [_subviews count],
bounds = [self bounds],
boundsSize = bounds.size[_sizeComponent],
oldSize = [self _calculateSize],
dividerThickness = [self dividerThickness],
totalDividers = count - 1,
totalSizableSpace = 0,
nonSizableSpace = 0,
lastSizableIndex = -1,
oldFlexibleSpace = 0,
totalSizablePanes = 0,
isVertical = [self isVertical];
isSizableMap = {},
viewSizes = [],
delegateRespondsToShouldAdjust = [_delegate respondsToSelector:@selector(splitView:shouldAdjustSizeOfSubview:)];
// What we want to do is to preserve non resizable sizes first, and then to preserve the ratio of size to available
// non fixed space for every other subview. E.g. assume fixed space was 20 pixels initially, view 1 was 20 and
// view 2 was 30 pixels, for a total of 70 pixels. Then the new total size becomes 140 pixels. Now we want the fixed
// space to still be 20 pixels, view 1 to be 48 pixels and view 2 to be 72 pixels. This way the relative size of
// view 1 to view 2 remains the same - view 1 was 66% of view 2 initially and after the resize view 1 is still
// 66% of view 2's size.
//
// For this calculation, we can consider the dividers themselves to also be fixed size areas - they should remain
// the same size before and after.
// How much flexible size do we have in pre-resize pixels?
for (index = 0; index < count; ++index)
{
var view = _subviews[index],
isSizable = isVertical ? [view autoresizingMask] & CPViewWidthSizable : [view autoresizingMask] & CPViewHeightSizable;
isSizable = !delegateRespondsToShouldAdjust || [_delegate splitView:self shouldAdjustSizeOfSubview:view],
size = [view frame].size[_sizeComponent];
isSizableMap[index] = isSizable;
viewSizes.push(size);
if (isSizable)
{
totalSizableSpace += [view frame].size[_sizeComponent];
lastSizableIndex = index;
oldFlexibleSpace += size;
totalSizablePanes++;
}
}
if (totalSizablePanes === count)
totalSizableSpace = 0;
// nonSizableSpace is the number of fixed pixels in pre-resize terms and the desired number post-resize.
var nonSizableSpace = oldSize[_sizeComponent] - oldFlexibleSpace,
newFlexibleSpace = boundsSize - nonSizableSpace,
remainingFixedPixelsToRemove = 0;
var nonSizableSpace = totalSizableSpace ? bounds.size[_sizeComponent] - totalSizableSpace : 0,
remainingFlexibleSpace = bounds.size[_sizeComponent] - oldSize[_sizeComponent],
oldDimension = (oldSize[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace),
ratio = oldDimension <= 0 ? 0 : (bounds.size[_sizeComponent] - totalDividers * dividerThickness - nonSizableSpace) / oldDimension;
if (newFlexibleSpace < 0)
{
remainingFixedPixelsToRemove = -newFlexibleSpace;
newFlexibleSpace = 0;
}
var remainingFixedPanes = count - totalSizablePanes;
for (index = 0; index < count; ++index)
{
var view = _subviews[index],
viewFrame = CGRectMakeCopy(bounds),
isSizable = isVertical ? [view autoresizingMask] & CPViewWidthSizable : [view autoresizingMask] & CPViewHeightSizable;
isSizable = isSizableMap[index],
targetSize = 0;
// The last area must take up exactly the remaining space, fixed or not.
if (index + 1 === count)
viewFrame.size[_sizeComponent] = bounds.size[_sizeComponent] - viewFrame.origin[_originComponent];
else if (totalSizableSpace && isSizable && lastSizableIndex === index)
viewFrame.size[_sizeComponent] = MAX(0, ROUND([view frame].size[_sizeComponent] + remainingFlexibleSpace))
else if (isSizable || !totalSizableSpace)
targetSize = boundsSize - viewFrame.origin[_originComponent];
// Try to keep fixed size areas the same size.
else if (!isSizable)
{
viewFrame.size[_sizeComponent] = MAX(0, ROUND(ratio * [view frame].size[_sizeComponent]));
remainingFlexibleSpace -= (viewFrame.size[_sizeComponent] - [view frame].size[_sizeComponent]);
var removedFixedPixels = MIN(remainingFixedPixelsToRemove / remainingFixedPanes, viewSizes[index]);
targetSize = viewSizes[index] - removedFixedPixels;
remainingFixedPixelsToRemove -= removedFixedPixels;
remainingFixedPanes--;
}
// (new size / flexible size available) == (old size / old flexible size available)
else if (oldFlexibleSpace > 0)
targetSize = newFlexibleSpace * viewSizes[index] / oldFlexibleSpace;
// oldFlexibleSpace <= 0 so all flexible areas were crushed. When we get space, allocate it evenly.
// totalSizablePanes cannot be 0 since isSizable.
else
targetSize = newFlexibleSpace / totalSizablePanes;
else if (totalSizableSpace && !isSizable)
viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent];
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
targetSize = MAX(0, ROUND(targetSize));
viewFrame.size[_sizeComponent] = targetSize;
[view setFrame:viewFrame];
bounds.origin[_originComponent] += targetSize + dividerThickness;
}
SPLIT_VIEW_MAYBE_POST_DID_RESIZE();
@@ -852,6 +909,11 @@ Notifies the delegate when the subviews will be resized.
- (void)splitViewWillResizeSubviews:(CPNotification)aNotification;
@endcode
Allows the delegate to specify which of the CPSplitView's subviews should adjust if the window is resized.
@code
- (BOOL)splitView:(CPSplitView)aSplitView shouldAdjustSizeOfSubview:(CPView)aSubView
@endcode
Lets the delegate specify a different rect for which the user can drag the splitView divider.
@code
- (CGRect)splitView:(CPSplitView)aSplitView effectiveRect:(CGRect)aRect forDrawnRect:(CGRect)aDrawnRect ofDividerAtIndex:(int)aDividerIndex;
@@ -984,6 +1046,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
{
if (_autosaveName == autosaveName)
return;
_autosaveName = autosaveName;
}
@@ -1002,7 +1065,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
*/
- (void)_autosave
{
if (!_shouldAutosave)
if (!_shouldAutosave || !autosaveName)
return;
var userDefaults = [CPUserDefaults standardUserDefaults],
@@ -1043,6 +1106,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
position = 0;
_shouldAutosave = NO;
for (var i = 0, count = [frames count] - 1; i < count; i++)
{
var frame = CPRectFromString(frames[i]);
@@ -1052,12 +1116,14 @@ The sum of the views and the sum of the dividers should be equal to the size of
position += dividerThickness;
}
_shouldAutosave = YES;
}
if (preCollapseArray)
{
_preCollapsePositions = [CPMutableDictionary new];
for (var i = 0, count = [preCollapseArray count]; i < count; i++)
[_preCollapsePositions setObject:preCollapseArray[i] forKey:i + ""];
}
@@ -1068,6 +1134,9 @@ The sum of the views and the sum of the dividers should be equal to the size of
*/
- (CPString)_framesKeyForAutosaveName:(CPString)theAutosaveName
{
if (!theAutosaveName)
return nil;
return @"CPSplitView Subview Frames " + theAutosaveName;
}
@@ -1076,6 +1145,9 @@ The sum of the views and the sum of the dividers should be equal to the size of
*/
- (CPString)_precollapseKeyForAutosaveName:(CPString)theAutosaveName
{
if (!theAutosaveName)
return nil;
return @"CPSplitView Subview Precollapse Positions " + theAutosaveName;
}
+57 -29
View File
@@ -34,6 +34,7 @@
@implementation CPStepper: CPControl
{
BOOL _valueWraps @accessors(property=valueWraps);
BOOL _autorepeat @accessors(getter=autorepeat);
int _increment @accessors(property=increment);
int _maxValue @accessors(property=maxValue);
int _minValue @accessors(property=minValue);
@@ -88,29 +89,38 @@
_minValue = 0.0;
_increment = 1.0;
_valueWraps = YES;
_autorepeat = YES;
[self setDoubleValue:0.0];
_buttonUp = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonUp setContinuous:YES];
[_buttonUp setTarget:self];
[_buttonUp setAction:@selector(_buttonDidClick:)];
[_buttonUp setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonUp];
_buttonDown = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonDown setContinuous:YES];
[_buttonDown setTarget:self];
[_buttonDown setAction:@selector(_buttonDidClick:)];
[_buttonDown setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonDown];
[self setNeedsLayout];
[self _init];
}
return self;
}
/*! @ignore */
- (void)_init
{
_buttonUp = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonUp setContinuous:_autorepeat];
[_buttonUp setTarget:self];
[_buttonUp setAction:@selector(_buttonDidClick:)];
[_buttonUp setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonUp];
_buttonDown = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonDown setContinuous:_autorepeat];
[_buttonDown setTarget:self];
[_buttonDown setAction:@selector(_buttonDidClick:)];
[_buttonDown setAutoresizingMask:CPViewNotSizable];
[self setContinuous:_autorepeat];
[self addSubview:_buttonDown];
[self setNeedsLayout];
}
#pragma mark -
#pragma mark Superclass overrides
@@ -164,8 +174,13 @@
*/
- (void)setAutorepeat:(BOOL)shouldAutoRepeat
{
[_buttonUp setContinuous:shouldAutoRepeat];
[_buttonDown setContinuous:shouldAutoRepeat];
if (shouldAutoRepeat !== _autorepeat)
{
[_buttonUp setContinuous:shouldAutoRepeat];
[_buttonDown setContinuous:shouldAutoRepeat];
}
[self setContinuous:shouldAutoRepeat];
}
/*!
@@ -235,19 +250,27 @@
@end
var CPStepperMinValue = @"CPStepperMinValue",
CPStepperMaxValue = @"CPStepperMaxValue",
CPStepperValueWraps = @"CPStepperValueWraps",
CPStepperAutorepeat = @"CPStepperAutorepeat",
CPStepperIncrement = @"CPStepperIncrement";
@implementation CPStepper (CPCodingCompliance)
@implementation CPStepper (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_maxValue = [aCoder decodeObjectForKey:@"_maxValue"];
_minValue = [aCoder decodeObjectForKey:@"_minValue"];
_increment = [aCoder decodeObjectForKey:@"_increment"];
_buttonUp = [aCoder decodeObjectForKey:@"_buttonUp"];
_buttonDown = [aCoder decodeObjectForKey:@"_buttonDown"];
_increment = [aCoder decodeIntForKey:CPStepperIncrement];
_minValue = [aCoder decodeIntForKey:CPStepperMinValue];
_maxValue = [aCoder decodeIntForKey:CPStepperMaxValue];
_valueWraps = [aCoder decodeBoolForKey:CPStepperValueWraps];
_autorepeat = [aCoder decodeBoolForKey:CPStepperAutorepeat];
[self _init];
}
return self;
}
@@ -255,11 +278,16 @@
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_maxValue forKey:@"_maxValue"];
[aCoder encodeObject:_minValue forKey:@"_minValue"];
[aCoder encodeObject:_increment forKey:@"_increment"];
[aCoder encodeObject:_buttonUp forKey:@"_buttonUp"];
[aCoder encodeObject:_buttonDown forKey:@"_buttonDown"];
[aCoder encodeInt:_increment forKey:CPStepperIncrement];
if (_minValue)
[aCoder encodeInt:_minValue forKey:CPStepperMinValue];
if (_maxValue)
[aCoder encodeInt:_maxValue forKey:CPStepperMaxValue];
if (_valueWraps)
[aCoder encodeBool:_valueWraps forKey:CPStepperValueWraps];
if (_autorepeat)
[aCoder encodeBool:_autorepeat forKey:CPStepperAutorepeat];
}
@end
+45 -15
View File
@@ -1,3 +1,25 @@
/*
* CPTabView.j
* AppKit
*
* Created by Derek Hammer.
* Copyright 2010, Derek Hammer.
*
* 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 "CPBox.j"
@import "CPSegmentedControl.j"
@import "CPTabViewItem.j"
@@ -45,7 +67,6 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
if (self = [super initWithFrame:aFrame])
{
_items = [CPArray array];
_selectedIndex = CPNotFound;
[self _init];
[self setTabViewType:CPTopTabsBezelBorder];
@@ -56,6 +77,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
- (void)_init
{
_selectedIndex = CPNotFound;
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[_tabs setHitTests:NO];
@@ -250,17 +273,15 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
Selects the item at the specified index.
@param anIndex the index of the item to display.
*/
- (void)selectTabViewItemAtIndex:(unsigned)anIndex
- (BOOL)selectTabViewItemAtIndex:(unsigned)anIndex
{
var aTabViewItem = [_items objectAtIndex:anIndex];
if (anIndex === _selectedIndex)
return;
var aTabViewItem = [self tabViewItemAtIndex:anIndex];
if ((_delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![_delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
return;
return NO;
if (_delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[_delegate tabView:self willSelectTabViewItem:aTabViewItem];
@@ -270,6 +291,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
if (_delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[_delegate tabView:self didSelectTabViewItem:aTabViewItem];
return YES;
}
/*!
@@ -278,7 +301,10 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
*/
- (CPTabViewItem)selectedTabViewItem
{
return [_items objectAtIndex:_selectedIndex];
if (_selectedIndex != CPNotFound)
return [_items objectAtIndex:_selectedIndex];
return nil;
}
// Modifying the font
@@ -407,11 +433,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
{
var segmentIndex = [_tabs testSegment:[_tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
if (segmentIndex != CPNotFound)
{
[self selectTabViewItemAtIndex:segmentIndex];
if (segmentIndex != CPNotFound && [self selectTabViewItemAtIndex:segmentIndex])
[_tabs trackSegment:anEvent];
}
}
- (void)_repositionTabs
@@ -428,8 +451,12 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
- (void)_setSelectedIndex:(CPNumber)index
{
_selectedIndex = index;
[self _setContentViewForItem:[_items objectAtIndex:_selectedIndex]];
}
[_box setContentView:[[_items objectAtIndex:_selectedIndex] view]];
- (void)_setContentViewForItem:(CPTabViewItem)anItem
{
[_box setContentView:[anItem view]];
}
- (void)_updateItems
@@ -469,17 +496,17 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
[_tabs setFont:_font];
_items = [aCoder decodeObjectForKey:CPTabViewItemsKey];
[_items makeObjectsPerformSelector:@selector(_setTabView:) withObject:self];
[self _updateItems];
[self _repositionTabs];
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
if (selected)
[self selectTabViewItem:selected];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
[self setTabViewType:[aCoder decodeIntForKey:CPTabViewTypeKey]];
}
@@ -491,7 +518,10 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_items forKey:CPTabViewItemsKey];
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey];
var selected = [self selectedTabViewItem];
if (selected)
[aCoder encodeObject:selected forKey:CPTabViewSelectedItemKey];
[aCoder encodeInt:_type forKey:CPTabViewTypeKey];
[aCoder encodeObject:_font forKey:CPTabViewFontKey];
+6
View File
@@ -132,7 +132,13 @@ CPPressedTab = 2;
*/
- (void)setView:(CPView)aView
{
if (_view == aView)
return;
_view = aView;
if ([_tabView selectedTabViewItem] == self)
[_tabView _setContentViewForItem:self];
}
/*!
+3 -6
View File
@@ -678,8 +678,11 @@ CPTableColumnUserResizingMask = 1 << 1;
bindingInfo = binding._info,
destination = [bindingInfo objectForKey:CPObservedObjectKey],
keyPath = [bindingInfo objectForKey:CPObservedKeyPathKey],
options = [bindingInfo objectForKey:CPOptionsKey],
dotIndex = keyPath.lastIndexOf(".");
newValue = [binding reverseTransformValue:newValue withOptions:options];
if (dotIndex === CPNotFound)
[[destination valueForKeyPath:keyPath] replaceObjectAtIndex:aRow withObject:newValue];
else
@@ -696,11 +699,6 @@ CPTableColumnUserResizingMask = 1 << 1;
}
}
//- (void)objectValue
//{
// return nil;
//}
@end
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
@@ -734,7 +732,6 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
[self setIdentifier:[aCoder decodeObjectForKey:CPTableColumnIdentifierKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
[self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
[self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
_resizingMask = [aCoder decodeIntForKey:CPTableColumnResizingMaskKey];
_isHidden = [aCoder decodeBoolForKey:CPTableColumnIsHiddenKey];
+1 -1
View File
@@ -643,7 +643,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
columnMaxX = _CGRectGetMaxX(columnToStroke);
CGContextMoveToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMinY(columnToStroke)));
CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMaxY(columnToStroke)));
CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMaxY(columnToStroke)) - 1.0);
}
CGContextClosePath(context);
CGContextStrokePath(context);
+54 -36
View File
@@ -87,9 +87,9 @@ CPTableViewSelectionHighlightStyleNone = -1;
CPTableViewSelectionHighlightStyleRegular = 0;
CPTableViewSelectionHighlightStyleSourceList = 1;
CPTableViewGridNone = 0;
CPTableViewSolidVerticalGridLineMask = 1 << 0;
CPTableViewSolidHorizontalGridLineMask = 1 << 1;
CPTableViewGridNone = 0;
CPTableViewSolidVerticalGridLineMask = 1 << 0;
CPTableViewSolidHorizontalGridLineMask = 1 << 1;
CPTableViewNoColumnAutoresizing = 0;
CPTableViewUniformColumnAutoresizingStyle = 1; // FIX ME: This is FUBAR
@@ -321,7 +321,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
*/
- (void)_init
{
_tableViewFlags = 0;
_lastSelectedRow = -1;
_selectedColumnIndexes = [CPIndexSet indexSet];
@@ -335,15 +334,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
if (!_alternatingRowBackgroundColors)
_alternatingRowBackgroundColors = [[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"]];
_selectionHighlightColor = [CPColor colorWithHexString:@"5f83b9"];
_tableColumnRanges = [];
_dirtyTableColumnRangeIndex = 0;
_numberOfHiddenColumns = 0;
_objectValues = { };
_dataViewsForTableColumns = { };
_dataViews = [];
_numberOfRows = 0;
_exposedRows = [CPIndexSet indexSet];
_exposedColumns = [CPIndexSet indexSet];
@@ -683,7 +679,8 @@ NOT YET IMPLEMENTED
*/
- (void)setRowHeight:(unsigned)aRowHeight
{
aRowHeight = aRowHeight;
// Accept row heights such as "0".
aRowHeight = +aRowHeight;
if (_rowHeight === aRowHeight)
return;
@@ -954,8 +951,9 @@ NOT YET IMPLEMENTED
*/
- (void)_moveColumn:(unsigned)fromIndex toColumn:(unsigned)toIndex
{
fromIndex = fromIndex;
toIndex = toIndex;
// Convert parameters such as "0" to 0.
fromIndex = +fromIndex;
toIndex = +toIndex;
if (fromIndex === toIndex)
return;
@@ -1511,6 +1509,8 @@ NOT YET IMPLEMENTED
if ([scrollView isKindOfClass:[CPScrollView class]] && [scrollView documentView] === self)
[scrollView _updateCornerAndHeaderView];
[self setNeedsLayout];
}
// Complexity:
@@ -1562,7 +1562,8 @@ NOT YET IMPLEMENTED
*/
- (CGRect)rectOfColumn:(CPInteger)aColumnIndex
{
aColumnIndex = aColumnIndex;
// Convert e.g. "0" to 0.
aColumnIndex = +aColumnIndex;
if (aColumnIndex < 0 || aColumnIndex >= NUMBER_OF_COLUMNS())
return _CGRectMakeZero();
@@ -2684,7 +2685,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
oldMainSortDescriptor = [[self sortDescriptors] objectAtIndex: 0];
// Remove every main descriptor equivalents (normally only one)
while ((descriptor = [e nextObject]) != nil)
while ((descriptor = [e nextObject]) !== nil)
{
if ([[descriptor key] isEqual: [newMainSortDescriptor key]])
[outdatedDescriptors addObject:descriptor];
@@ -3045,7 +3046,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
return _sortDescriptors;
}
/*!
@ignore
*/
@@ -3369,6 +3369,14 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
*/
- (void)_commitDataViewObjectValue:(id)sender
{
/*
makeFirstResponder at the end of this method causes the dataview to resign.
If the dataview resigning triggers the action (as CPTextField does), we come right
back here and start an infinite loop. So we have to check this flag first.
*/
if (_editingCellIndex === nil)
return;
_editingCellIndex = nil;
if (_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_)
@@ -3426,7 +3434,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
[aTableColumn setDataView:dataView];
}
return [aTableColumn _newDataViewForRow:aRow];
}
@@ -3498,8 +3505,20 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
{
[super setNeedsDisplay:aFlag];
[_tableDrawView setNeedsDisplay:aFlag];
[[self headerView] setNeedsDisplay:YES];
}
/*!
@ignore
*/
- (void)setNeedsLayout
{
[super setNeedsLayout];
[[self headerView] setNeedsLayout];
}
/*!
@ignore
*/
@@ -3681,7 +3700,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
[_selectedColumnIndexes getIndexes:indexes maxCount:-1 inIndexRange:exposedRange];
}
var count = count2 = [indexes count];
var count,
count2 = count = [indexes count];
if (!count)
return;
@@ -3706,7 +3726,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
{
var topGroupLineColor = [CPColor colorWithCalibratedWhite:212.0 / 255.0 alpha:1.0],
bottomGroupLineColor = [CPColor colorWithCalibratedWhite:185.0 / 255.0 alpha:1.0],
gradientGroupColor = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [212.0 / 255.0, 212.0 / 255.0, 212.0 / 255.0,1.0, 197.0 / 255.0, 197.0 / 255.0, 197.0 / 255.0,1.0], [0,1], 2);
gradientGroupColor = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [212.0 / 255.0, 212.0 / 255.0, 212.0 / 255.0, 1.0, 197.0 / 255.0, 197.0 / 255.0, 197.0 / 255.0, 1.0], [0, 1], 2);
}
while (count--)
@@ -3824,8 +3844,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
var gradientCache = [self selectionGradientColors],
topLineColor = [CPColor colorWithHexString:"d3d3d3"],
bottomLineColor = [CPColor colorWithHexString:"bebebd"],
gradientColor = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [220.0 / 255.0, 220.0 / 255.0, 220.0 / 255.0,1.0,
199.0 / 255.0, 199.0 / 255.0, 199.0 / 255.0,1.0], [0,1], 2),
gradientColor = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [220.0 / 255.0, 220.0 / 255.0, 220.0 / 255.0, 1.0,
199.0 / 255.0, 199.0 / 255.0, 199.0 / 255.0, 1.0], [0, 1], 2),
drawGradient = YES;
while (i--)
@@ -3973,7 +3993,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
{
var row = [self rowAtPoint:aPoint];
//if the user clicks outside a row then deselect everything
// If the user clicks outside a row then deselect everything.
if (row < 0 && _allowsEmptySelection)
[self selectRowIndexes:[CPIndexSet indexSet] byExtendingSelection:NO];
@@ -4638,19 +4658,19 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
while (![_delegate tableView:self shouldSelectRow:i] && (i < [self numberOfRows] || i > 0))
shouldGoUpward ? i-- : i++; //check to see if the row can be selected if it can't be then see if the next row can be selected
//if the index still can be selected after the loop then just return
if (![_delegate tableView:self shouldSelectRow:i])
return;
// If the index still can be selected after the loop then just return.
if (![_delegate tableView:self shouldSelectRow:i])
return;
}
// if we go upward and see that this row is already selected we should deselect the row below
if ([selectedIndexes containsIndex:i] && extend)
// If we go upward and see that this row is already selected we should deselect the row below.
if (extend && [selectedIndexes containsIndex:i])
{
// the row we're on is the last to be selected
// The row we're on is the last to be selected.
var differedLastSelectedRow = i;
// no remove the one before/after it
shouldGoUpward ? i++ : i--;
shouldGoUpward ? i++ : i--;
[selectedIndexes removeIndex:i];
@@ -4662,7 +4682,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
if ([selectedIndexes containsIndex:i])
{
i = shouldGoUpward ? [selectedIndexes firstIndex] -1 : [selectedIndexes lastIndex] + 1;
i = MIN(MAX(i,0), [self numberOfRows] - 1);
i = MIN(MAX(i, 0), [self numberOfRows] - 1);
}
[selectedIndexes addIndex:i];
@@ -4762,15 +4782,14 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
_tableColumns = [aCoder decodeObjectForKey:CPTableViewTableColumnsKey] || [];
[_tableColumns makeObjectsPerformSelector:@selector(setTableView:) withObject:self];
if ([aCoder containsValueForKey:CPTableViewRowHeightKey])
_rowHeight = [aCoder decodeFloatForKey:CPTableViewRowHeightKey];
else
_rowHeight = 23.0;
_rowHeight = [aCoder decodeFloatForKey:CPTableViewRowHeightKey] || 23.0;
_intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey];
_intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey] || _CGSizeMake(3.0, 2.0);
if (_CGSizeEqualToSize(_intercellSpacing, _CGSizeMakeZero()))
_intercellSpacing = _CGSizeMake(3.0, 2.0);
[self setGridColor:[aCoder decodeObjectForKey:CPTableViewGridColorKey]];
_gridStyleMask = [aCoder decodeIntForKey:CPTableViewGridStyleMaskKey] || CPTableViewGridNone;
_gridStyleMask = [aCoder decodeIntForKey:CPTableViewGridStyleMaskKey];
_usesAlternatingRowBackgroundColors = [aCoder decodeObjectForKey:CPTableViewUsesAlternatingBackgroundKey];
[self setAlternatingRowBackgroundColors:[aCoder decodeObjectForKey:CPTableViewAlternatingRowColorsKey]];
@@ -4837,9 +4856,8 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
while (index != CPNotFound)
{
var indexSet = (switchFlag) ? otherSet : self;
otherIndex = [indexSet indexGreaterThanOrEqualToIndex:index];
var indexSet = (switchFlag) ? otherSet : self,
otherIndex = [indexSet indexGreaterThanOrEqualToIndex:index];
if (otherIndex == index)
{
+39 -53
View File
@@ -540,7 +540,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
// Select the text if the textfield became first responder through keyboard interaction
if (!_willBecomeFirstResponderByClick)
[self selectText:self];
[self _selectText:self immediately:YES];
_willBecomeFirstResponderByClick = NO;
@@ -630,15 +630,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
#endif
// post CPControlTextDidEndEditingNotification
if (_isEditing)
{
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
}
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
@@ -1075,24 +1071,36 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
*/
- (void)selectText:(id)sender
{
// FIXME Should this really make the text field the first responder?
[self _selectText:sender immediately:NO];
}
- (void)_selectText:(id)sender immediately:(BOOL)immediately
{
// Selecting the text in a field makes it the first responder
if (([self isEditable] || [self isSelectable]))
{
var wind = [self window];
#if PLATFORM(DOM)
var element = [self _inputElement];
if ([[self window] firstResponder] === self)
window.setTimeout(function() { element.select(); }, 0);
else if ([self window] !== nil && [[self window] makeFirstResponder:self])
window.setTimeout(function() {[self selectText:sender];}, 0);
if ([wind firstResponder] === self)
{
if (immediately)
element.select();
else
window.setTimeout(function() { element.select(); }, 0);
}
else if (wind !== nil && [wind makeFirstResponder:self])
[self _selectText:sender immediately:immediately];
#else
// Even if we can't actually select the text we need to preserve the first
// responder side effect.
if ([self window] !== nil && [[self window] firstResponder] !== self)
[[self window] makeFirstResponder:self];
if (wind !== nil && [wind firstResponder] !== self)
[wind makeFirstResponder:self];
#endif
}
}
- (void)copy:(id)sender
@@ -1503,47 +1511,25 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
{
}
- (void)setValueFor:(CPString)theBinding
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
var destination = [_info objectForKey:CPObservedObjectKey],
keyPath = [_info objectForKey:CPObservedKeyPathKey],
options = [_info objectForKey:CPOptionsKey],
newValue = [destination valueForKeyPath:keyPath],
isPlaceholder = CPIsControllerMarker(newValue);
[super _updatePlaceholdersWithOptions:options];
if (isPlaceholder)
{
switch (newValue)
{
case CPMultipleValuesMarker:
newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || @"Multiple Values";
break;
[self _setPlaceholder:@"Multiple Values" forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:@"No Selection" forMarker:CPNoSelectionMarker isDefault:YES];
[self _setPlaceholder:@"Not Applicable" forMarker:CPNotApplicableMarker isDefault:YES];
[self _setPlaceholder:@"" forMarker:CPNullMarker isDefault:YES];
}
case CPNoSelectionMarker:
newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || @"No Selection";
break;
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setPlaceholderString:aValue];
[_source setObjectValue:nil];
}
case CPNotApplicableMarker:
if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
[CPException raise:CPGenericException
reason:@"can't transform non applicable key on: "+_source+" value: "+newValue];
newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || @"Not Applicable";
break;
case CPNullMarker:
newValue = [options objectForKey:CPNullPlaceholderBindingOption] || @"";
break;
}
[_source setPlaceholderString:newValue];
[_source setObjectValue:nil];
}
else
{
newValue = [self transformValue:newValue withOptions:options];
[_source setObjectValue:newValue];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source setObjectValue:aValue];
}
@end
+1 -1
View File
@@ -255,7 +255,7 @@ var CPThemesByName = { },
attributeNames = [attributes keyEnumerator],
objectThemeClass = [anObject themeClass];
while (attributeName = [attributeNames nextObject])
while ((attributeName = [attributeNames nextObject]) !== nil)
[self _recordAttribute:[attributes objectForKey:attributeName] forClass:objectThemeClass];
}
+32 -4
View File
@@ -50,9 +50,17 @@ CPToolbarDisplayModeIconOnly = 2;
*/
CPToolbarDisplayModeLabelOnly = 3;
CPToolbarSizeModeDefault = 0;
CPToolbarSizeModeRegular = 1;
CPToolbarSizeModeSmall = 2;
var CPToolbarsByIdentifier = nil,
CPToolbarConfigurationsByIdentifier = nil;
var TOOLBAR_REGULAR_HEIGHT = 59.0,
TOOLBAR_SMALL_HEIGHT = 46.0;
/*!
@ingroup appkit
@class CPToolbar
@@ -87,6 +95,7 @@ var CPToolbarsByIdentifier = nil,
BOOL _showsBaselineSeparator;
BOOL _allowsUserCustomization;
BOOL _isVisible;
int _sizeMode @accessors(property=sizeMode);
id _delegate;
@@ -148,6 +157,7 @@ var CPToolbarsByIdentifier = nil,
_identifier = anIdentifier;
_isVisible = YES;
_sizeMode = CPToolbarSizeModeDefault;
[CPToolbar _addToolbar:self forIdentifier:_identifier];
}
@@ -202,6 +212,16 @@ var CPToolbarsByIdentifier = nil,
[_window _noteToolbarChanged];
}
- (void)setSizeMode:(CPToolbarSizeMode)aSize
{
if (aSize === _sizeMode)
return;
_sizeMode = aSize;
[[self _toolbarView] setFrame:[self _toolbarViewFrame]];
[_window _noteToolbarChanged];
}
- (CPWindow)_window
{
return _window;
@@ -232,12 +252,17 @@ var CPToolbarsByIdentifier = nil,
}
- (CGRect)_toolbarViewFrame
{
return CPRectMake(0.0, 0.0, 1200.0, _sizeMode != CPToolbarSizeModeSmall ? TOOLBAR_REGULAR_HEIGHT : TOOLBAR_SMALL_HEIGHT);
}
/* @ignore */
- (CPView)_toolbarView
{
if (!_toolbarView)
{
_toolbarView = [[_CPToolbarView alloc] initWithFrame:CPRectMake(0.0, 0.0, 1200.0, 59.0)];
_toolbarView = [[_CPToolbarView alloc] initWithFrame:[self _toolbarViewFrame]];
[_toolbarView setToolbar:self];
[_toolbarView setAutoresizingMask:CPViewWidthSizable];
@@ -427,7 +452,8 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
CPToolbarIdentifiedItemsKey = @"CPToolbarIdentifiedItemsKey",
CPToolbarDefaultItemsKey = @"CPToolbarDefaultItemsKey",
CPToolbarAllowedItemsKey = @"CPToolbarAllowedItemsKey",
CPToolbarSelectableItemsKey = @"CPToolbarSelectableItemsKey";
CPToolbarSelectableItemsKey = @"CPToolbarSelectableItemsKey",
CPToolbarSizeModeKey = @"CPToolbarSizeModeKey";
@implementation CPToolbar (CPCoding)
@@ -446,6 +472,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
_showsBaselineSeparator = [aCoder decodeBoolForKey:CPToolbarShowsBaselineSeparatorKey];
_allowsUserCustomization = [aCoder decodeBoolForKey:CPToolbarAllowsUserCustomizationKey];
_isVisible = [aCoder decodeBoolForKey:CPToolbarIsVisibleKey];
_sizeMode = [aCoder decodeIntForKey:CPToolbarSizeModeKey];
_identifiedItems = [aCoder decodeObjectForKey:CPToolbarIdentifiedItemsKey];
_defaultItems = [aCoder decodeObjectForKey:CPToolbarDefaultItemsKey];
@@ -492,6 +519,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
[aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
[aCoder encodeBool:_allowsUserCustomization forKey:CPToolbarAllowsUserCustomizationKey];
[aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
[aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey]
[aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
[aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
@@ -547,7 +575,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
var bundle = [CPBundle bundleForClass:self];
_CPToolbarViewExtraItemsImage = [[CPImage alloc] initWithContentsOfFile: [bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsImage.png"] size: CPSizeMake(10.0, 15.0)];
_CPToolbarViewExtraItemsImage = [[CPImage alloc] initWithContentsOfFile: [bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsImage.png"] size:CPSizeMake(10.0, 15.0)];
_CPToolbarViewExtraItemsAlternateImage = [[CPImage alloc] initWithContentsOfFile: [bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsAlternateImage.png"] size:CGSizeMake(10.0, 15.0)];
}
@@ -996,7 +1024,7 @@ var TOP_MARGIN = 5.0,
{
_imageView = [[CPImageView alloc] initWithFrame:[self bounds]];
[_imageView setImageScaling:CPScaleProportionally];
[_imageView setImageScaling:CPImageScaleProportionallyDown];
[self addSubview:_imageView];
}
+5 -5
View File
@@ -180,7 +180,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
var keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount];
[self willChangeValueForKey:key];
@@ -194,7 +194,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
var keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount];
[[_controller defaults] setObject:[_cachedValues objectForKey:key] forKey:key];
@@ -207,7 +207,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount];
[self willChangeValueForKey:key];
@@ -229,7 +229,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount],
value = [_cachedValues objectForKey:key],
@@ -250,7 +250,7 @@ var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
keys = [_cachedValues allKeys],
keysCount = [keys count];
while(keysCount--)
while (keysCount--)
{
var key = keys[keysCount],
value = [_cachedValues objectForKey:key],
+245 -11
View File
@@ -98,6 +98,10 @@ var CPViewFlags = { },
CPViewHasCustomDrawRect = 1 << 0,
CPViewHasCustomLayoutSubviews = 1 << 1;
var CPCurrentToolTip,
CPCurrentToolTipTimer,
CPToolTipDelay = 1.0;
/*!
@ingroup appkit
@class CPView
@@ -141,6 +145,7 @@ var CPViewFlags = { },
BOOL _postsFrameChangedNotifications;
BOOL _postsBoundsChangedNotifications;
BOOL _inhibitFrameAndBoundsChangedNotifications;
BOOL _inLiveResize;
#if PLATFORM(DOM)
DOMElement _DOMElement;
@@ -188,7 +193,10 @@ var CPViewFlags = { },
unsigned _viewClassFlags;
// ToolTips
CPString _toolTip @accessors(property=toolTip);
CPString _toolTip @accessors(getter=toolTip);
Function _toolTipFunctionIn;
Function _toolTipFunctionOut;
BOOL _toolTipInstalled;
}
/*
@@ -214,7 +222,7 @@ var CPViewFlags = { },
CachedNotificationCenter = [CPNotificationCenter defaultCenter];
}
- (void)setupViewFlags
- (void)_setupViewFlags
{
var theClass = [self class],
classUID = [theClass UID];
@@ -235,6 +243,13 @@ var CPViewFlags = { },
_viewClassFlags = CPViewFlags[classUID];
}
- (void)_setupToolTipHandlers
{
_toolTipInstalled = NO;
_toolTipFunctionIn = function(e){[self _fireToolTip];}
_toolTipFunctionOut = function(e){[self _invalidateToolTip];};
}
+ (CPSet)keyPathsForValuesAffectingFrame
{
return [CPSet setWithObjects:@"frameOrigin", @"frameSize"];
@@ -291,6 +306,9 @@ var CPViewFlags = { },
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(aFrame), _CGRectGetMinY(aFrame));
CPDOMDisplayServerSetStyleSize(_DOMElement, width, height);
if (typeof(appkit_tag_dom_elements) !== "undefined" && !!appkit_tag_dom_elements)
_DOMElement.setAttribute("data-cappuccino-view", [self className]);
_DOMImageParts = [];
_DOMImageSizes = [];
#endif
@@ -298,7 +316,8 @@ var CPViewFlags = { },
_theme = [CPTheme defaultTheme];
_themeState = CPThemeStateNormal;
[self setupViewFlags];
[self _setupToolTipHandlers];
[self _setupViewFlags];
[self _loadThemeAttributes];
}
@@ -306,6 +325,118 @@ var CPViewFlags = { },
return self;
}
/*!
Sets the tooltip for the receiver.
@param aToolTip the tooltip
*/
- (void)setToolTip:(CPString)aToolTip
{
if (_toolTip == aToolTip)
return;
_toolTip = aToolTip;
if (_toolTip)
[self _installToolTipEventHandlers];
else
[self _uninstallToolTipEventHandlers];
}
/*! @ignore
Install the handlers for the tooltip
*/
- (void)_installToolTipEventHandlers
{
if (_toolTipInstalled)
return;
if (_DOMElement.addEventListener)
{
_DOMElement.addEventListener("mouseover", _toolTipFunctionIn, NO);
_DOMElement.addEventListener("keypress", _toolTipFunctionOut, NO);
_DOMElement.addEventListener("mouseout", _toolTipFunctionOut, NO);
}
else if (_DOMElement.attachEvent)
{
_DOMElement.attachEvent("onmouseover", _toolTipFunctionIn);
_DOMElement.attachEvent("onkeypress", _toolTipFunctionOut);
_DOMElement.attachEvent("onmouseout", _toolTipFunctionOut);
}
_toolTipInstalled = YES;
}
/*! @ignore
Uninstall the handlers for the tooltip
*/
- (void)_uninstallToolTipEventHandlers
{
if (!_toolTipInstalled)
return;
if (_DOMElement.removeEventListener)
{
_DOMElement.removeEventListener("mouseover", _toolTipFunctionIn, NO);
_DOMElement.removeEventListener("keypress", _toolTipFunctionOut, NO);
_DOMElement.removeEventListener("mouseout", _toolTipFunctionOut, NO);
}
else if (_DOMElement.detachEvent)
{
_DOMElement.detachEvent("onmouseover", _toolTipFunctionIn);
_DOMElement.detachEvent("onkeypress", _toolTipFunctionOut);
_DOMElement.detachEvent("onmouseout", _toolTipFunctionOut);
}
_toolTipInstalled = NO;
}
/*! @ignore
Starts the tooltip timer.
*/
- (void)_fireToolTip
{
if (CPCurrentToolTipTimer)
{
[CPCurrentToolTipTimer invalidate];
if (CPCurrentToolTip)
[CPCurrentToolTip close];
CPCurrentToolTip = nil;
}
if (_toolTip)
CPCurrentToolTipTimer = [CPTimer scheduledTimerWithTimeInterval:CPToolTipDelay target:self selector:@selector(_showToolTip:) userInfo:nil repeats:NO];
}
/*! @ignore
Stop the tooltip timer if any
*/
- (void)_invalidateToolTip
{
if (CPCurrentToolTipTimer)
{
[CPCurrentToolTipTimer invalidate];
CPCurrentToolTipTimer = nil;
}
if (CPCurrentToolTip)
{
[CPCurrentToolTip close];
CPCurrentToolTip = nil;
}
}
/*! @ignore
Actually shows the tooltip if any
*/
- (void)_showToolTip:(CPTimer)aTimer
{
if (CPCurrentToolTip)
[CPCurrentToolTip close];
CPCurrentToolTip = [_CPToolTip toolTipWithString:_toolTip];
}
/*!
Returns the container view of the receiver
@return the receiver's containing view
@@ -365,6 +496,9 @@ var CPViewFlags = { },
/* @ignore */
- (void)_insertSubview:(CPView)aSubview atIndex:(int)anIndex
{
if (aSubview === self)
[CPException raise:CPInvalidArgumentException reason:"can't add a view as a subview of itself"];
// We will have to adjust the z-index of all views starting at this index.
var count = _subviews.length;
@@ -527,7 +661,7 @@ var CPViewFlags = { },
var addedSubview = nil,
addedSubviewEnumerator = [addedSubviews objectEnumerator];
while (addedSubview = [addedSubviewEnumerator nextObject])
while ((addedSubview = [addedSubviewEnumerator nextObject]) !== nil)
[self addSubview:addedSubview];
// If the order is fine, no need to reorder.
@@ -848,11 +982,17 @@ var CPViewFlags = { },
if (_backgroundType === BackgroundVerticalThreePartImage)
{
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width, size.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], size.width, _DOMImageSizes[2].height);
}
else if (_backgroundType === BackgroundHorizontalThreePartImage)
{
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], _DOMImageSizes[0].width, size.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, size.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], _DOMImageSizes[2].width, size.height);
}
else if (_backgroundType === BackgroundNinePartImage)
{
@@ -1539,7 +1679,10 @@ var CPViewFlags = { },
}
else if (_backgroundType == BackgroundVerticalThreePartImage)
{
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], frameSize.width, _DOMImageSizes[0].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width, frameSize.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], frameSize.width, _DOMImageSizes[2].height);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, 0.0, _DOMImageSizes[0].height);
@@ -1547,7 +1690,10 @@ var CPViewFlags = { },
}
else if (_backgroundType == BackgroundHorizontalThreePartImage)
{
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], _DOMImageSizes[0].width, frameSize.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, frameSize.height);
CPDOMDisplayServerSetStyleSize(_DOMImageParts[2], _DOMImageSizes[2].width, frameSize.height);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, _DOMImageSizes[0].width, 0.0);
@@ -2128,6 +2274,43 @@ setBoundsOrigin:
{
}
/*!
Return yes if the receiver is in a live-resize operation.
*/
- (BOOL)inLiveResize
{
return _inLiveResize;
}
/*!
Not implemented.
A view will be sent this message before a window begins a resize operation. The
receiver might choose to simplify its drawing operations during a live resize
for speed.
Subclasses should call super.
*/
- (void)viewWillStartLiveResize
{
_inLiveResize = YES;
}
/*!
Not implemented.
A view will be sent this message after a window finishes a resize operation. The
receiver which simplified its drawing operations in viewWillStartLiveResize might
stop doing so now. Note the view might no longer be in a window, so use
[self setNeedsDisplay:YES] if a final non-simplified redraw is required.
Subclasses should call super.
*/
- (void)viewDidEndLiveResize
{
_inLiveResize = NO;
}
@end
@implementation CPView (KeyView)
@@ -2543,6 +2726,50 @@ setBoundsOrigin:
return (_themeAttributes && _themeAttributes[aName] !== undefined);
}
/*!
Registers theme values encoded in an array at runtime. The format of the data in the array
is the same as that used by ThemeDescriptors.j, with the exception that you need to use
CPColorWithImages() in place of PatternColor(). For more information see the comments
at the top of ThemeDescriptors.j.
@param themeValues array of theme values
*/
- (void)registerThemeValues:(CPArray)themeValues
{
for (var i = 0; i < themeValues.length; ++i)
{
var attributeValueState = themeValues[i],
attribute = attributeValueState[0],
value = attributeValueState[1],
state = attributeValueState[2];
if (state)
[self setValue:value forThemeAttribute:attribute inState:state];
else
[self setValue:value forThemeAttribute:attribute];
}
}
/*!
Registers theme values encoded in an array at runtime. The format of the data in the array
is the same as that used by ThemeDescriptors.j, with the exception that you need to use
CPColorWithImages() in place of PatternColor(). The values in \c inheritedValues are
registered first, then those in \c themeValues override/augment the inherited values.
For more information see the comments at the top of ThemeDescriptors.j.
@param themeValues array of base theme values
@param inheritedValues array of overridden/additional theme values
*/
- (void)registerThemeValues:(CPArray)themeValues inherit:(CPArray)inheritedValues
{
// Register inherited values first, then override those with the subtheme values.
if (inheritedValues)
[self registerThemeValues:inheritedValues];
if (themeValues)
[self registerThemeValues:themeValues];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aViewName
{
return nil;
@@ -2607,6 +2834,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
CPViewBoundsKey = @"CPViewBoundsKey",
CPViewFrameKey = @"CPViewFrameKey",
CPViewHitTestsKey = @"CPViewHitTestsKey",
CPViewToolTipKey = @"CPViewToolTipKey",
CPViewIsHiddenKey = @"CPViewIsHiddenKey",
CPViewOpacityKey = @"CPViewOpacityKey",
CPViewSubviewsKey = @"CPViewSubviewsKey",
@@ -2661,7 +2889,12 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
_autoresizesSubviews = ![aCoder containsValueForKey:CPViewAutoresizesSubviewsKey] || [aCoder decodeBoolForKey:CPViewAutoresizesSubviewsKey];
_hitTests = ![aCoder containsValueForKey:CPViewHitTestsKey] || [aCoder decodeObjectForKey:CPViewHitTestsKey];
_hitTests = ![aCoder containsValueForKey:CPViewHitTestsKey] || [aCoder decodeBoolForKey:CPViewHitTestsKey];
[self _setupToolTipHandlers];
_toolTip = [aCoder decodeObjectForKey:CPViewToolTipKey];
if (_toolTip)
[self _installToolTipEventHandlers];
// DOM SETUP
#if PLATFORM(DOM)
@@ -2681,10 +2914,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
}
#endif
if ([aCoder containsValueForKey:CPViewIsHiddenKey])
[self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]];
else
_isHidden = NO;
[self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]];
if ([aCoder containsValueForKey:CPViewOpacityKey])
[self setAlphaValue:[aCoder decodeIntForKey:CPViewOpacityKey]];
@@ -2692,8 +2922,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
_opacity = 1.0;
[self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]];
[self setupViewFlags];
[self _setupViewFlags];
_theme = [CPTheme defaultTheme];
_themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey];
@@ -2774,6 +3003,9 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
if (_isHidden)
[aCoder encodeBool:_isHidden forKey:CPViewIsHiddenKey];
if (_toolTip)
[aCoder encodeObject:_toolTip forKey:CPViewToolTipKey];
var nextKeyView = [self nextKeyView];
if (nextKeyView !== nil && ![nextKeyView isEqual:self])
@@ -2897,3 +3129,5 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView)
return transform;
};
+30 -23
View File
@@ -66,6 +66,7 @@ var CPViewControllerCachedCibs;
{
CPView _view @accessors(property=view);
BOOL _isLoading;
BOOL _isLazy;
id _representedObject @accessors(property=representedObject);
CPString _title @accessors(property=title);
@@ -124,6 +125,7 @@ var CPViewControllerCachedCibs;
_cibExternalNameTable = anExternalNameTable || [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
_isLoading = NO;
_isLazy = NO;
}
return self;
@@ -136,12 +138,12 @@ var CPViewControllerCachedCibs;
If you create your views manually, you must override this method and use
it to create your view and assign it to the view property. The default
implementation for programmatic views is to create a plain view. You can
invoke super to utilize this view.
implementation for programmatic views is to create a plain, zero width & height
view. You can invoke super to utilize this view.
If you use Interface Builder to create your views, you initialize the view
using the initWithCibName:bundle: method then you must not override this
method. The consequences risk shattering the space-time continuum.
If you use Interface Builder to create your views, and you initialize the
controller using the initWithCibName:bundle: methods, then you MUST NOT override
this method. The consequences risk shattering the space-time continuum.
Note: The cib loading system is currently synchronous.
*/
@@ -150,17 +152,22 @@ var CPViewControllerCachedCibs;
if (_view)
return;
// check if a cib is already cached for the current _cibName
var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
if (!cib)
if (_cibName)
{
// if the cib isn't cached yet : fetch it and cache it
cib = [[CPCib alloc] initWithContentsOfURL:[_cibBundle pathForResource:_cibName + @".cib"]];
[CPViewControllerCachedCibs setObject:cib forKey:_cibName];
}
// check if a cib is already cached for the current _cibName
var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
[cib instantiateCibWithExternalNameTable:_cibExternalNameTable];
if (!cib)
{
// if the cib isn't cached yet : fetch it and cache it
cib = [[CPCib alloc] initWithCibNamed:_cibName bundle:_cibBundle];
[CPViewControllerCachedCibs setObject:cib forKey:_cibName];
}
[cib instantiateCibWithExternalNameTable:_cibExternalNameTable];
}
else
_view = [CPView new];
}
/*!
@@ -199,6 +206,11 @@ var CPViewControllerCachedCibs;
_isLoading = NO;
[self viewDidLoad];
}
else if (_isLazy)
{
_isLazy = NO;
[self viewDidLoad];
}
return _view;
}
@@ -208,9 +220,9 @@ var CPViewControllerCachedCibs;
This method is called after the view controller has loaded its associated views into memory.
This method is called regardless of whether the views were stored in a nib
file or created programmatically in the loadView method. This method is
most commonly used to perform additional initialization steps on views
that are loaded from cib files.
file or created programmatically in the loadView method, but NOT when setView
is invoked. This method is most commonly used to perform additional initialization
steps on views that are loaded from cib files.
*/
- (void)viewDidLoad
{
@@ -228,13 +240,7 @@ var CPViewControllerCachedCibs;
*/
- (void)setView:(CPView)aView
{
var viewWasLoaded = !_view;
_view = aView;
// Make sure the viewDidLoad method is called if the view is set directly
if (!_isLoading && viewWasLoaded)
[self viewDidLoad];
}
@end
@@ -266,6 +272,7 @@ var CPViewControllerViewKey = @"CPViewControllerViewKey",
_cibBundle = bundlePath ? [CPBundle bundleWithPath:bundlePath] : [CPBundle mainBundle];
_cibExternalNameTable = [CPDictionary dictionaryWithObject:self forKey:CPCibOwner];
_isLazy = YES;
}
return self;
+43 -13
View File
@@ -455,6 +455,7 @@ CPTexturedBackgroundWindowMask
if (aStyleMask & CPBorderlessBridgeWindowMask)
[self setFullPlatformWindow:YES];
_autorecalculatesKeyViewLoop = NO;
_defaultButtonEnabled = YES;
_keyViewLoopIsDirty = YES;
@@ -515,6 +516,11 @@ CPTexturedBackgroundWindowMask
- (void)awakeFromCib
{
_keyViewLoopIsDirty = ![self _hasKeyViewLoop];
// If no key view loop has been specified by hand, and we are not intending to auto recalculate,
// set up a default key view loop.
if (_keyViewLoopIsDirty && ![self autorecalculatesKeyViewLoop])
[self recalculateKeyViewLoop];
}
- (void)_setWindowView:(CPView)aWindowView
@@ -1296,6 +1302,34 @@ CPTexturedBackgroundWindowMask
_initialFirstResponder = aView;
}
- (void)_setupFirstResponder
{
/*
If:
- The key loop is dirty
- The key loop does not auto-recalculate
- The first responder is the window
- The initial first responder is the content view
Then calculate the key view loop and set the first responder
to the first view in the loop, since we should
always have an initial first responder and a key loop by default.
*/
if (_keyViewLoopIsDirty &&
!_autorecalculatesKeyViewLoop &&
_firstResponder === self &&
_initialFirstResponder === [self contentView])
{
[self recalculateKeyViewLoop];
// Make the first key view of the content view the first responder
var firstKeyView = [[self contentView] nextValidKeyView];
[self makeFirstResponder:firstKeyView];
}
}
/*!
Attempts to make the \c aResponder the first responder. Before trying
to make it the first responder, the receiver will ask the current first responder
@@ -1650,6 +1684,8 @@ CPTexturedBackgroundWindowMask
if (_firstResponder !== self && [_firstResponder respondsToSelector:@selector(becomeKeyWindow)])
[_firstResponder becomeKeyWindow];
[self _setupFirstResponder];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPWindowDidBecomeKeyNotification
object:self];
@@ -2015,7 +2051,7 @@ CPTexturedBackgroundWindowMask
*/
- (BOOL)isMainWindow
{
return [CPApp mainWindow] == self;
return [CPApp mainWindow] === self;
}
/*!
@@ -2484,10 +2520,7 @@ CPTexturedBackgroundWindowMask
[views sortUsingFunction:keyViewComparator context:nil];
var index = 0,
count = [views count];
for (; index < count; ++index)
for (var index = 0, count = [views count]; index < count; ++index)
[views[index] setNextKeyView:views[(index + 1) % count]];
_keyViewLoopIsDirty = NO;
@@ -2500,9 +2533,7 @@ CPTexturedBackgroundWindowMask
_autorecalculatesKeyViewLoop = shouldRecalculate;
if (_keyViewLoopIsDirty)
[self recalculateKeyViewLoop];
else if (_autorecalculatesKeyViewLoop)
if (_autorecalculatesKeyViewLoop)
[self _dirtyKeyViewLoop];
}
@@ -2668,8 +2699,7 @@ var allViews = function(aWindow)
[views addObjectsFromArray:[[aWindow contentView] subviews]];
var index = 0;
for (; index < views.length; ++index)
for (var index = 0; index < views.length; ++index)
views = views.concat([views[index] subviews]);
return views;
@@ -2790,7 +2820,7 @@ var keyViewComparator = function(lhs, rhs, context)
- (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint
{
if ([self _sharesChromeWithPlatformWindow])
return aPoint;
return _CGPointMakeCopy(aPoint);
var origin = [self frame].origin;
@@ -2798,12 +2828,12 @@ var keyViewComparator = function(lhs, rhs, context)
}
/*!
Converts aPoint from the parent platform window coordinate system to the windows coordinate system.
Converts aPoint from the parent platform window coordinate system to the window's coordinate system.
*/
- (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint
{
if ([self _sharesChromeWithPlatformWindow])
return aPoint;
return _CGPointMakeCopy(aPoint);
var origin = [self frame].origin;
+215 -128
View File
@@ -22,21 +22,28 @@
@import "_CPWindowView.j"
#define ALIGN_STROKE(point) (FLOOR(point) === (point) ? (point) + halfStrokeWidth : (point))
#define ALIGN_COORD(point) (FLOOR(point))
var _CPAttachedWindowViewDefaultCursorSize = CGSizeMake(16, 10),
_CPAttachedWindowViewRadius = 5.0,
_CPAttachedWindowViewStrokeWidth = 1.0,
_CPAttachedWindowViewShadowSize = CGSizeMake(0, 6),
_CPAttachedWindowViewShadowBlur = 15.0;
/*!
@ignore
A custom CPWindowView that manage border and cursor
A custom CPWindowView that manages a border and cursor
*/
@implementation _CPAttachedWindowView : _CPWindowView
{
BOOL _mouseDownPressed @accessors(getter=isMouseDownPressed, setter=setMouseDownPressed:);
float _arrowOffsetX @accessors(property=arrowOffsetX);
float _arrowOffsetY @accessors(property=arrowOffsetY);
int _appearance @accessors(property=appearance);
unsigned _preferredEdge @accessors(property=preferredEdge);
float _arrowOffsetX @accessors(property=arrowOffsetX);
float _arrowOffsetY @accessors(property=arrowOffsetY);
int _appearance @accessors(property=appearance);
unsigned _preferredEdge @accessors(property=preferredEdge);
CPSize _cursorSize;
CGSize _cursorSize;
}
/*!
@@ -81,18 +88,14 @@
/*!
Initialize the _CPWindowView
*/
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
- (id)initWithFrame:(CGRect)aFrame styleMask:(unsigned)aStyleMask
{
if (self = [super initWithFrame:aFrame styleMask:aStyleMask])
{
var bundle = [CPBundle bundleForClass:[self class]];
_arrowOffsetX = 0.0;
_arrowOffsetY = 0.0;
// @TODO: make this themable
_useGlowingEffect = YES;
_appearance = CPPopoverAppearanceMinimal;
_cursorSize = CPSizeMake(15, 10);
_cursorSize = CGSizeMakeCopy(_CPAttachedWindowViewDefaultCursorSize);
}
return self;
@@ -103,7 +106,7 @@
*/
- (void)hideCursor
{
_cursorSize = CPSizeMakeZero();
_cursorSize = CGSizeMakeZero();
[self setNeedsDisplay:YES];
}
@@ -112,9 +115,8 @@
*/
- (void)showCursor
{
_cursorSize = CPSizeMake(15, 10);
_cursorSize = CGSizeMakeCopy(_CPAttachedWindowViewDefaultCursorSize);
[self setNeedsDisplay:YES];
_mouseDownPressed = NO;
}
/*!
@@ -125,176 +127,261 @@
[super drawRect:aRect];
var context = [[CPGraphicsContext currentContext] graphicsPort],
radius = 5,
radius = _CPAttachedWindowViewRadius,
arrowWidth = _cursorSize.width,
arrowHeight = _cursorSize.height,
strokeWidth = 1,
strokeWidth = _CPAttachedWindowViewStrokeWidth,
halfStrokeWidth = strokeWidth / 2.0,
strokeColor,
shadowColor = [[CPColor blackColor] colorWithAlphaComponent:.2],
shadowSize = CGSizeMake(0, 7),
shadowBlur = 15,
gradient;
shadowSize = _CPAttachedWindowViewShadowSize,
shadowBlur = _CPAttachedWindowViewShadowBlur,
gradient,
frame = [self bounds];
if (_appearance == CPPopoverAppearanceMinimal)
{
gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [(254.0 / 255), (254.0 / 255), (254.0 / 255), 0.93,
(231.0 / 255), (231.0 / 255), (231.0 / 255), 0.93], [0,1], 2);
gradient = CGGradientCreateWithColorComponents(
CGColorSpaceCreateDeviceRGB(),
[
(254.0 / 255), (254.0 / 255), (254.0 / 255), 0.93,
(231.0 / 255), (231.0 / 255), (231.0 / 255), 0.93
],
[0, 1],
2
);
strokeColor = [CPColor colorWithHexString:@"B8B8B8"];
}
else
{
gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [(38.0 / 255), (38.0 / 255), (38.0 / 255), 0.93,
(18.0 / 255), (18.0 / 255), (18.0 / 255), 0.93], [0,1], 2);
gradient = CGGradientCreateWithColorComponents(
CGColorSpaceCreateDeviceRGB(),
[
(38.0 / 255), (38.0 / 255), (38.0 / 255), 0.93,
(18.0 / 255), (18.0 / 255), (18.0 / 255), 0.93
],
[0, 1],
2);
strokeColor = [CPColor colorWithHexString:@"222222"];
}
// fix rect to take care of stroke and shadow
aRect.origin.x += strokeWidth + shadowBlur;
aRect.origin.y += strokeWidth + (shadowBlur + shadowSize.height / 2);
aRect.size.width -= (strokeWidth * 2) + (shadowBlur * 2);
aRect.size.height -= (strokeWidth * 2) + (shadowBlur * 2 + shadowSize.height);
frame.origin.x += halfStrokeWidth + shadowBlur;
frame.origin.y += halfStrokeWidth + (shadowBlur + shadowSize.height / 2);
frame.size.width -= strokeWidth + (shadowBlur * 2);
frame.size.height -= strokeWidth + (shadowBlur * 2 + shadowSize.height);
CGContextSetStrokeColor(context, strokeColor);
CGContextSetLineWidth(context, strokeWidth);
CGContextBeginPath(context);
CGContextSetShadowWithColor(context, shadowSize, shadowBlur, shadowColor);
CGContextDrawLinearGradient(context, gradient, CGPointMake(CPRectGetMidX(aRect), 0.0), CGPointMake(CPRectGetMidX(aRect), aRect.size.height), 0);
CGContextDrawLinearGradient(context, gradient, CGPointMake(CGRectGetMidX(frame), 0.0), CGPointMake(CGRectGetMidX(frame), frame.size.height), 0);
var xMin = _CGRectGetMinX(aRect),
xMax = _CGRectGetMaxX(aRect),
yMin = _CGRectGetMinY(aRect),
yMax = _CGRectGetMaxY(aRect);
var xMin = _CGRectGetMinX(frame),
xMax = _CGRectGetMaxX(frame),
yMin = _CGRectGetMinY(frame),
yMax = _CGRectGetMaxY(frame),
arrowMinX = ALIGN_COORD(xMin + radius + strokeWidth),
arrowMaxX = ALIGN_COORD(xMax - radius - strokeWidth),
arrowMinY = ALIGN_COORD(yMin + radius + strokeWidth),
arrowMaxY = ALIGN_COORD(yMax - radius + strokeWidth),
arrowAnchor = CGPointMakeZero(),
arrowStart = CGPointMakeZero(),
pt = CGPointMakeZero();
// draw!
switch (_preferredEdge)
{
case CPMinXEdge:
// origin ne
CGContextMoveToPoint(context, xMin + radius, yMin);
// ne
CGContextAddLineToPoint(context, xMax - radius, yMin);
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
// arrow CPMinXEdge
CGContextAddLineToPoint(context, xMax, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY - (arrowHeight - 2));
CGContextAddLineToPoint(context, aRect.size.width + arrowHeight + aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY);
CGContextAddLineToPoint(context, aRect.size.width + aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2 + (arrowWidth / 2)) + aRect.origin.y + _arrowOffsetY);
// se
CGContextAddLineToPoint(context, xMax, yMax - radius);
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
// sw
CGContextAddLineToPoint(context, xMin + radius, yMax);
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
// nw
CGContextAddLineToPoint(context, xMin, yMin + radius);
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
break;
case CPMaxXEdge:
// origin ne
CGContextMoveToPoint(context, xMin + radius, yMin);
// origin nw
pt.x = ALIGN_COORD(xMin + radius);
pt.y = yMin;
CGContextMoveToPoint(context, pt.x, pt.y);
// ne
CGContextAddLineToPoint(context, xMax - radius, yMin);
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
pt.x = ALIGN_COORD(xMax - radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, xMax, yMin, xMax, ALIGN_COORD(yMin + radius));
if (_preferredEdge === CPMinXEdge)
{
// arrow CPMinXEdge
arrowAnchor.x = ALIGN_STROKE(xMax);
arrowAnchor.y = ALIGN_COORD((frame.size.height / 2) + yMin + _arrowOffsetY);
// to top edge
pt.y = ALIGN_COORD(arrowAnchor.y - (arrowWidth / 2));
// adjust starting point to not go beyond the corner
if (pt.y <= arrowMinY)
pt.y = arrowMinY;
else if ((pt.y + arrowWidth) > arrowMaxY)
pt.y = arrowMaxY - arrowWidth;
pt.x = arrowAnchor.x;
arrowStart = CGPointMakeCopy(pt);
CGContextAddLineToPoint(context, pt.x, pt.y);
// top edge -> point
pt.x = ALIGN_STROKE(arrowAnchor.x + arrowHeight);
pt.y = arrowAnchor.y;
CGContextAddLineToPoint(context, pt.x, pt.y);
// point -> bottom edge
pt.x = arrowAnchor.x;
pt.y = ALIGN_COORD(arrowStart.y + arrowWidth);
CGContextAddLineToPoint(context, pt.x, pt.y);
}
// se
CGContextAddLineToPoint(context, xMax, yMax - radius);
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
pt.x = xMax;
pt.y = ALIGN_COORD(yMax - radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, pt.x, yMax, ALIGN_COORD(xMax - radius), yMax);
// sw
CGContextAddLineToPoint(context, xMin + radius, yMax);
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
pt.x = ALIGN_COORD(xMin + radius);
pt.y = yMax;
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, xMin, pt.y, xMin, ALIGN_COORD(yMax - radius));
// arrow CPMaxXEdge
CGContextAddLineToPoint(context, xMin, (aRect.size.height / 2 + (arrowWidth / 2) + aRect.origin.y + _arrowOffsetY));
CGContextAddLineToPoint(context, aRect.origin.x - arrowHeight + _arrowOffsetX, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY);
CGContextAddLineToPoint(context, aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2 - (arrowWidth / 2) + aRect.origin.y + _arrowOffsetY));
if (_preferredEdge === CPMaxXEdge)
{
// arrow CPMaxXEdge
arrowAnchor.x = ALIGN_STROKE(xMin);
arrowAnchor.y = ALIGN_COORD((frame.size.height / 2) + yMin + _arrowOffsetY);
// to bottom edge
pt.y = ALIGN_COORD(arrowAnchor.y + (arrowWidth / 2));
// adjust starting point to not go beyond the corner
if ((pt.y - arrowWidth) < arrowMinY)
pt.y = arrowMinY + arrowWidth;
else if (pt.y > arrowMaxY)
pt.y = arrowMaxY;
pt.x = arrowAnchor.x;
arrowStart = CGPointMakeCopy(pt);
CGContextAddLineToPoint(context, pt.x, pt.y);
// bottom edge -> point
pt.x = ALIGN_STROKE(arrowAnchor.x - arrowHeight);
pt.y = arrowAnchor.y;
CGContextAddLineToPoint(context, pt.x, pt.y);
// point -> top edge
pt.x = arrowAnchor.x;
pt.y = ALIGN_COORD(arrowStart.y - arrowWidth);
CGContextAddLineToPoint(context, pt.x, pt.y);
}
// nw
CGContextAddLineToPoint(context, xMin, yMin + radius);
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
pt.x = xMin;
pt.y = ALIGN_COORD(yMin + radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, pt.x, yMin, ALIGN_COORD(xMin + radius), yMin);
break;
case CPMaxYEdge:
// origin nw
CGContextMoveToPoint(context, xMin, yMin + yMin);
// nw
CGContextAddLineToPoint(context, xMin, yMin + radius);
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
// arrow CPMaxYEdge
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX - (arrowWidth / 2), yMin);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX, aRect.origin.y - arrowHeight + _arrowOffsetY);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX, aRect.origin.y + _arrowOffsetY);
// ne
CGContextAddLineToPoint(context, xMax - radius, yMin);
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
// se
CGContextAddLineToPoint(context, xMax, yMax - radius);
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
// sw
CGContextAddLineToPoint(context, xMin + radius, yMax);
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
break;
case CPMinYEdge:
// origin nw
CGContextMoveToPoint(context, xMin, yMin + yMin);
// origin sw
pt.x = xMin;
pt.y = ALIGN_COORD(yMax - radius);
CGContextMoveToPoint(context, pt.x, pt.y);
// nw
CGContextAddLineToPoint(context, xMin, yMin + radius);
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
pt.y = ALIGN_COORD(yMin + radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, pt.x, yMin, ALIGN_COORD(xMin + radius), yMin);
if (_preferredEdge === CPMaxYEdge)
{
// arrow CPMaxYEdge
arrowAnchor.x = ALIGN_COORD((frame.size.width / 2) + xMin + _arrowOffsetX);
arrowAnchor.y = ALIGN_STROKE(yMin + _arrowOffsetY);
// to left edge
pt.x = ALIGN_COORD(arrowAnchor.x - (arrowWidth / 2));
// adjust starting point to not go beyond the corner
if (pt.x < arrowMinX)
pt.x = arrowMinX;
else if ((pt.x + arrowWidth) > arrowMaxX)
pt.x = arrowMaxX - arrowWidth;
pt.y = arrowAnchor.y;
arrowStart = CGPointMakeCopy(pt);
CGContextAddLineToPoint(context, pt.x, pt.y);
// left edge -> point
pt.x = arrowAnchor.x;
pt.y = ALIGN_STROKE(arrowAnchor.y - arrowHeight);
CGContextAddLineToPoint(context, pt.x, pt.y);
// point -> right edge
pt.x = ALIGN_COORD(arrowStart.x + arrowWidth);
pt.y = arrowAnchor.y;
CGContextAddLineToPoint(context, pt.x, pt.y);
}
// ne
CGContextAddLineToPoint(context, xMax - radius, yMin);
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
pt.x = ALIGN_COORD(xMax - radius);
pt.y = yMin;
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, xMax, pt.y, xMax, ALIGN_COORD(yMin + radius));
// se
CGContextAddLineToPoint(context, xMax, yMax - radius);
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
pt.x = xMax;
pt.y = ALIGN_COORD(yMax - radius);
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, pt.x, yMax, ALIGN_COORD(xMax - radius), yMax);
// arrow CPMinYEdge
CGContextAddLineToPoint(context, (aRect.size.width / 2) + (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX , yMax);
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX, aRect.size.height + aRect.origin.y + arrowHeight + _arrowOffsetY);
CGContextAddLineToPoint(context, (aRect.size.width / 2) - (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX, aRect.size.height + aRect.origin.y + _arrowOffsetY);
if (_preferredEdge === CPMinYEdge)
{
// arrow CPMinYEdge
arrowAnchor.x = ALIGN_COORD((frame.size.width / 2) + xMin + _arrowOffsetX);
arrowAnchor.y = ALIGN_STROKE(yMax + _arrowOffsetY);
// to right edge
pt.x = ALIGN_COORD(arrowAnchor.x + (arrowWidth / 2));
// adjust starting point to not go beyond the corner
if ((pt.x - arrowWidth) < arrowMinX)
pt.x = arrowMinX + arrowWidth;
else if (pt.x > arrowMaxX)
pt.x = arrowMaxX;
pt.y = arrowAnchor.y;
arrowStart = CGPointMakeCopy(pt);
CGContextAddLineToPoint(context, pt.x, pt.y);
// right edge -> point
pt.x = arrowAnchor.x;
pt.y = ALIGN_STROKE(arrowAnchor.y + arrowHeight);
CGContextAddLineToPoint(context, pt.x, pt.y);
// point -> left edge
pt.x = ALIGN_COORD(arrowStart.x - arrowWidth);
pt.y = arrowAnchor.y;
CGContextAddLineToPoint(context, pt.x, pt.y);
}
// sw
CGContextAddLineToPoint(context, xMin + radius, yMax);
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
pt.x = ALIGN_COORD(xMin + radius);
pt.y = yMax;
CGContextAddLineToPoint(context, pt.x, pt.y);
CGContextAddCurveToPoint(context, pt.x, pt.y, xMin, pt.y, xMin, ALIGN_COORD(yMax - radius));
break;
default:
// no computed edge means standard rounded rect
CGContextAddPath(context, CGPathWithRoundedRectangleInRect(aRect, radius, radius, YES, YES, YES, YES));
CGContextAddPath(context, CGPathWithRoundedRectangleInRect(frame, radius, radius, YES, YES, YES, YES));
}
CGContextClosePath(context);
//Draw it
CGContextStrokePath(context);
CGContextFillPath(context);
}
- (void)mouseDown:(CPEvent)anEvent
{
_mouseDownPressed = YES;
[super mouseDown:anEvent];
}
- (void)mouseUp:(CPEvent)anEvent
{
_mouseDownPressed = NO;
[super mouseUp:anEvent];
}
@end
@@ -33,7 +33,14 @@ var _CPToolbarViewBackgroundColor = nil;
+ (CPColor)toolbarBackgroundColor
{
if (!_CPToolbarViewBackgroundColor)
_CPToolbarViewBackgroundColor = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[_CPBorderlessBridgeWindowView class]] pathForResource:@"_CPToolbarView/_CPToolbarViewBackground.png"] size:CGSizeMake(1.0, 59.0)]];
{
var bundle = [CPBundle bundleForClass:[_CPBorderlessBridgeWindowView class]];
_CPToolbarViewBackgroundColor = CPColorWithImages([
["_CPToolbarView/toolbar-background-top.png", 1, 1, bundle],
["_CPToolbarView/toolbar-background-center.png", 1, 57.0, bundle],
["_CPToolbarView/toolbar-background-bottom.png", 1, 1, bundle],
], CPColorPatternIsVertical);
}
return _CPToolbarViewBackgroundColor;
}
+1 -1
View File
@@ -105,7 +105,7 @@ var HUD_TITLEBAR_HEIGHT = 26.0;
if ([[[self window] toolbar] isVisible])
{
toolbarHeight = CGRectGetHeight([[self toolbarView] frame]);
var toolbarHeight = CGRectGetHeight([[self toolbarView] frame]);
frameRect.origin.y -= toolbarHeight;
frameRect.size.height += toolbarHeight;
+1 -1
View File
@@ -197,7 +197,7 @@ var STANDARD_GRADIENT_HEIGHT = 41.0,
if ([theToolbar isVisible])
{
toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
var toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]);
frameRect.origin.y -= toolbarHeight;
frameRect.size.height += toolbarHeight;
+56
View File
@@ -0,0 +1,56 @@
/*
* CPWorkspace.j
* AppKit
*
* Created by Alexander Ljungberg.
* Copyright 2012, SlevenBits Ltd.
*
* 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/CPString.j>
var SharedWorkspace = nil;
@implementation CPWorkspace : CPObject
{
}
+ (CPWorkspace)sharedWorkspace
{
if (!SharedWorkspace)
SharedWorkspace = [CPWorkspace new];
return SharedWorkspace;
}
- (BOOL)openFile:(CPString)fullPath
{
var url = [CPURL URLWithString:fullPath];
return [self openURL:url];
}
- (BOOL)openURL:(CPURL)url
{
if (!url || ![url absoluteURL])
return NO;
window.open([url absoluteURL]);
return YES;
}
@end
+1 -1
View File
@@ -137,7 +137,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
var key = nil,
keyEnumerator = [replacementClasses keyEnumerator];
while (key = [keyEnumerator nextObject])
while ((key = [keyEnumerator nextObject]) !== nil)
[unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
}
+59
View File
@@ -0,0 +1,59 @@
/*
* CPCibHelpConnector.j
* AppKit
*
* Created by Antoine Mercadal.
* Copyright 2012, The 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 "CPCibConnector.j"
@implementation CPCibHelpConnector : CPCibConnector
{
id _destination;
id _file;
id _marker;
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_destination = [aCoder decodeObjectForKey:@"_destination"];
_file = [aCoder decodeObjectForKey:@"_file"];
_marker = [aCoder decodeObjectForKey:@"_marker"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_destination forKey:@"_destination"];
[aCoder encodeObject:_file forKey:@"_file"];
[aCoder encodeObject:_marker forKey:@"_marker"];
}
- (void)establishConnection
{
[_destination setToolTip:_marker];
}
@end
@@ -0,0 +1,64 @@
/*
* CPCibRuntimeAttributesConnector.j
* AppKit
*
* Created by Aparajita Fishman.
* Copyright 2012, The 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 "CPCibConnector.j"
var CPCibRuntimeAttributesConnectorObjectKey = @"CPCibRuntimeAttributesConnectorObjectKey",
CPCibRuntimeAttributesConnectorKeyPathsKey = @"CPCibRuntimeAttributesConnectorKeyPathsKey",
CPCibRuntimeAttributesConnectorValuesKey = @"CPCibRuntimeAttributesConnectorValuesKey";
@implementation CPCibRuntimeAttributesConnector : CPCibConnector
{
id _keyPaths;
id _values;
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_source = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorObjectKey];
_keyPaths = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorKeyPathsKey];
_values = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorValuesKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_source forKey:CPCibRuntimeAttributesConnectorObjectKey];
[aCoder encodeObject:_keyPaths forKey:CPCibRuntimeAttributesConnectorKeyPathsKey];
[aCoder encodeObject:_values forKey:CPCibRuntimeAttributesConnectorValuesKey];
}
- (void)establishConnection
{
var count = [_keyPaths count];
while (count--)
[_source setValue:_values[count] forKeyPath:_keyPaths[count]];
}
@end
+2 -2
View File
@@ -61,14 +61,14 @@ var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey",
if (!object)
{
CPLog.error("Unable to find class " + theClassName + " in cib file.");
CPLog.error("Unable to find class " + theClassName + " referenced in cib file.");
object = [self allocObjectWithCoder:aCoder className:[aCoder decodeObjectForKey:_CPCibClassSwapperOriginalClassNameKey]];
}
}
if (!object)
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " in cib file."];
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " referenced in cib file."];
return object;
}
+33 -1
View File
@@ -43,6 +43,11 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObject:aSize forKey:@"size"]];
}
+ (id)imageResourceWithName:(CPString)aResourceName size:(CGSize)aSize bundleClass:(CPString)aBundleClass
{
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObjects:[aSize, aBundleClass] forKeys:[@"size", @"bundleClass"]]];
}
- (id)initWithClassName:(CPString)aClassName resourceName:(CPString)aResourceName properties:(CPDictionary)properties
{
self = [super init];
@@ -89,12 +94,32 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
else if (_resourceName == "CPRemoveTemplate")
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
return [self imageFromBundle:[aCoder bundle]];
}
return self;
}
- (CPImage)imageFromBundle:(CPBundle)aBundle
{
if (!aBundle)
{
var bundleClass = _properties.valueForKey(@"bundleClass");
if (bundleClass)
{
bundleClass = CPClassFromString(bundleClass);
if (bundleClass)
aBundle = [CPBundle bundleForClass:bundleClass];
}
else
aBundle = [CPBundle mainBundle];
}
return [[CPImage alloc] initWithContentsOfFile:[aBundle pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
}
@end
@implementation _CPCibCustomResource (CPImage)
@@ -129,4 +154,11 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
return nil;
}
- (CPString)description
{
var image = [self imageFromBundle:nil];
return [image description];
}
@end
+26 -6
View File
@@ -29,6 +29,8 @@
@import "CPCibControlConnector.j"
@import "CPCibOutletConnector.j"
@import "CPCibBindingConnector.j"
@import "CPCibRuntimeAttributesConnector.j"
@import "CPCibHelpConnector.j"
@implementation _CPCibObjectData : CPObject
@@ -106,7 +108,7 @@
var object = nil,
objectEnumerator = [_visibleWindows objectEnumerator];
while (object = [objectEnumerator nextObject])
while ((object = [objectEnumerator nextObject]) !== nil)
[_replacementObjects[[object UID]] makeKeyAndOrderFront:self];
}
@@ -232,15 +234,15 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
{
_replacementObjects[[object UID]] = instantiatedObject;
if ([instantiatedObject isKindOfClass:[CPView class]])
if ([instantiatedObject isKindOfClass:CPView])
{
var clipView = [instantiatedObject superview];
if ([clipView isKindOfClass:[CPClipView class]])
if ([clipView isKindOfClass:CPClipView])
{
var scrollView = [clipView superview];
if ([scrollView isKindOfClass:[CPScrollView class]])
if ([scrollView isKindOfClass:CPScrollView])
[scrollView setDocumentView:instantiatedObject];
}
}
@@ -257,11 +259,29 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
_replacementObjects[[_fileOwner UID]] = anOwner;
var index = 0,
count = _connections.length;
count = _connections.length,
runtimeAttributeConnectors = [],
connection = nil;
for (; index < count; ++index)
{
var connection = _connections[index];
connection = _connections[index];
if ([connection isKindOfClass:CPCibRuntimeAttributesConnector])
// Defer runtime attribute connections until after all other connections are made
runtimeAttributeConnectors.push(connection);
else
{
[connection replaceObjects:_replacementObjects];
[connection establishConnection];
}
}
count = runtimeAttributeConnectors.length;
for (index = 0; index < count; ++index)
{
connection = runtimeAttributeConnectors[index];
[connection replaceObjects:_replacementObjects];
[connection establishConnection];
+4 -5
View File
@@ -77,8 +77,8 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemp
_windowTitle = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowTitleKey];
_windowView = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowViewKey];
_windowAutorecalculatesKeyViewLoop = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
_windowIsFullPlatformWindow = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
_windowAutorecalculatesKeyViewLoop = [aCoder decodeBoolForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
_windowIsFullPlatformWindow = [aCoder decodeBoolForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
}
return self;
@@ -125,14 +125,13 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemp
- (id)_cibInstantiate
{
var windowClass = CPClassFromString([self windowClass]);
var windowClass = CPClassFromString([self windowClass]),
theWindow = [[windowClass alloc] initWithContentRect:_windowRect styleMask:_windowStyleMask];
/* if (!windowClass)
[NSException raise:NSInvalidArgumentException format:@"Unable to locate NSWindow class %@, using NSWindow",_windowClass];
class=[NSWindow class];*/
var theWindow = [[windowClass alloc] initWithContentRect:_windowRect styleMask:_windowStyleMask];
if (_minSize)
[theWindow setMinSize:_minSize];
if (_maxSize)
+26
View File
@@ -267,6 +267,32 @@ function CGPointFromEvent(anEvent)
return _CGPointMake(anEvent.clientX, anEvent.clientY);
}
/*!
Combines two insets by adding their individual elements and returns the result.
@group CGInset
*/
function CGInsetUnion(lhsInset, rhsInset)
{
return _CGInsetMake(lhsInset.top + rhsInset.top,
lhsInset.right + rhsInset.right,
lhsInset.bottom + rhsInset.bottom,
lhsInset.left + rhsInset.left);
}
/*!
Subtract one inset from another by subtracting their individual elements and returns the result.
@group CGInset
*/
function CGInsetDifference(lhsInset, rhsInset)
{
return _CGInsetMake(lhsInset.top - rhsInset.top,
lhsInset.right - rhsInset.right,
lhsInset.bottom - rhsInset.bottom,
lhsInset.left - rhsInset.left);
}
function CGInsetFromString(aString)
{
var numbers = aString.substr(1, aString.length - 2).split(',');
+4 -4
View File
@@ -29,16 +29,16 @@ kCGGradientDrawsAfterEndLocation = 1 << 1;
function CGGradientCreateWithColorComponents(aColorSpace, components, locations, count)
{
if ( locations === undefined || locations === NULL )
if (locations === undefined || locations === NULL)
{
var num_of_colors = components.length / 4,
locations = [];
for ( var idx = 0; idx < num_of_colors; idx++ )
for (var idx = 0; idx < num_of_colors; idx++)
locations.push( idx / (num_of_colors - 1) );
}
if ( count === undefined || count === NULL)
var count = locations.length;
if (count === undefined || count === NULL)
count = locations.length;
var colors = [];
+7 -7
View File
@@ -661,7 +661,7 @@ var ModifierKeyCodes = [
- (void)keyEvent:(DOMEvent)aDOMEvent
{
var event,
timestamp = aDOMEvent.timeStamp || new Date(),
timestamp = [CPEvent currentTimestamp],
sourceElement = aDOMEvent.target || aDOMEvent.srcElement,
windowNumber = [[CPApp keyWindow] windowNumber],
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
@@ -871,11 +871,11 @@ var ModifierKeyCodes = [
{
if ([self _validateCopyCutOrPasteEvent:aDOMEvent flags:CPPlatformActionKeyMask] && !_ignoreNativeCopyOrCutEvent)
{
//we have to send out a fake copy or cut event so that we can force the copy/cut mechanisms to take place
// we have to send out a fake copy or cut event so that we can force the copy/cut mechanisms to take place
var cut = aDOMEvent.type === "beforecut",
keyCode = cut ? CPKeyCodes.X : CPKeyCodes.C,
characters = cut ? "x" : "c",
timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
timestamp = [CPEvent currentTimestamp], // fake event, might as well use current timestamp
windowNumber = [[CPApp keyWindow] windowNumber],
modifierFlags = CPPlatformActionKeyMask;
@@ -1008,7 +1008,7 @@ var ModifierKeyCodes = [
var deltaX = 0.0,
deltaY = 0.0,
windowNumber = 0,
timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
timestamp = [CPEvent currentTimestamp],
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
(aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
(aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
@@ -1135,7 +1135,7 @@ var ModifierKeyCodes = [
newEvent.clientX = touch.clientX;
newEvent.clientY = touch.clientY;
newEvent.timestamp = aDOMEvent.timestamp;
newEvent.timestamp = [CPEvent currentTimestamp];
newEvent.target = aDOMEvent.target;
newEvent.shiftKey = newEvent.ctrlKey = newEvent.altKey = newEvent.metaKey = false;
@@ -1179,7 +1179,7 @@ var ModifierKeyCodes = [
var event,
location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY),
timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
timestamp = [CPEvent currentTimestamp],
sourceElement = (aDOMEvent.target || aDOMEvent.srcElement),
windowNumber = 0,
modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
@@ -1625,7 +1625,7 @@ function CPWindowObjectList()
platformWindow = nil,
windowObjects = [];
while (platformWindow = [platformWindowEnumerator nextObject])
while ((platformWindow = [platformWindowEnumerator nextObject]) !== nil)
{
var levels = platformWindow._windowLevels,
layers = platformWindow._windowLayers,
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

+216 -217
View File
@@ -38,32 +38,31 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
@ignore
This is a simple attached window like the one that pops up
when you double click on a meeting in iCal
when you double click on a meeting in iCal.
*/
@implementation _CPAttachedWindow : CPWindow
{
BOOL _animates @accessors(property=animates);
id _targetView @accessors(property=targetView);
int _appearance @accessors(getter=appearance);
BOOL _isClosing @accessors(property=isClosing);
BOOL _closeOnBlur;
BOOL _isClosed;
BOOL _browserAnimates;
BOOL _shouldPerformAnimation;
CPButton _closeButton;
float _animationDuration;
CPInteger _implementedDelegateMethods;
}
/*!
override default windowView class loader
@param aStyleMask the window mask
@return the windowView class
*/
#pragma mark -
#pragma mark Class methods
/*!
Overrides the default windowView class loader.
@param aStyleMask the window mask
@return the windowView class
*/
+ (Class)_windowViewClassForStyleMask:(unsigned)aStyleMask
{
return _CPAttachedWindowView;
@@ -74,7 +73,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
#pragma mark Initialization
/*!
Create and init a _CPAttachedWindow with given size of and view
Create and init a _CPAttachedWindow with the given size and view.
@param aSize the size of the attached window
@param aView the target view
@@ -82,20 +81,20 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
*/
+ (id)attachedWindowWithSize:(CGSize)aSize forView:(CPView)aView
{
return [_CPAttachedWindow attachedWindowWithSize:aSize forView:aView styleMask:nil];
return [_CPAttachedWindow attachedWindowWithSize:aSize forView:aView styleMask:0];
}
/*!
Create and init a _CPAttachedWindow with given size of and view
Create and init a _CPAttachedWindow with given the size, view and style mask.
@param aSize the size of the attached window
@param aView the target view
@return ready to use _CPAttachedWindow
@param styleMask the window style mask (combine CPClosableWindowMask and CPClosableOnBlurWindowMask)
@return ready to use _CPAttachedWindow
*/
+ (id)attachedWindowWithSize:(CGSize)aSize forView:(CPView)aView styleMask:(int)aMask
{
var attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CPRectMake(0.0, 0.0, aSize.width, aSize.height) styleMask:aMask];
var attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:_CGRectMake(0.0, 0.0, aSize.width, aSize.height) styleMask:aMask];
[attachedWindow attachToView:aView];
@@ -103,19 +102,19 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
}
/*!
Create and init a _CPAttachedWindow with given frame
Create and init a _CPAttachedWindow with given the given frame.
@param aFrame the frame of the attached window
@return ready to use _CPAttachedWindow
*/
- (id)initWithContentRect:(CGRect)aFrame
{
self = [self initWithContentRect:aFrame styleMask:nil];
self = [self initWithContentRect:aFrame styleMask:0];
return self;
}
/*!
Create and init a _CPAttachedWindow with given frame
Designated initializer. Create and init a _CPAttachedWindow with the given frame and style mask.
@param aFrame the frame of the attached window
@param styleMask the window style mask (combine CPClosableWindowMask and CPClosableOnBlurWindowMask)
@@ -126,19 +125,16 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
if (self = [super initWithContentRect:aFrame styleMask:aStyleMask])
{
_animates = YES;
_animates = YES;
_animationDuration = 150;
_closeOnBlur = (aStyleMask & CPClosableOnBlurWindowMask);
_isClosed = NO;
_shouldPerformAnimation = _animates;
_isClosing = NO;
_browserAnimates = [self browserSupportsAnimation];
_shouldPerformAnimation = YES;
[self setLevel:CPStatusWindowLevel];
[self setMovableByWindowBackground:YES];
[self setHasShadow:NO];
_DOMElement.style.WebkitBackfaceVisibility = "hidden";
_DOMElement.style.WebkitTransitionProperty = "-webkit-transform, opacity";
_DOMElement.style.WebkitTransitionDuration = _animationDuration + "ms";
[self setCSS3Property:@"TransitionProperty" value:@"-webkit-transform, opacity"];
[_windowView setNeedsDisplay:YES];
}
@@ -151,15 +147,20 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
- (void)setAppearance:(int)anAppearance
{
if (_appearance == anAppearance)
if (_appearance === anAppearance)
return;
[_windowView setAppearance:anAppearance];
}
- (void)setStyleMask:(unsigned)aStyleMask
{
_closeOnBlur = (aStyleMask & CPClosableOnBlurWindowMask);
}
- (void)setDelegate:(id)aDelegate
{
if (_delegate == aDelegate)
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
@@ -176,33 +177,16 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
#pragma mark Observer
/*!
Update the _CPAttachedWindow frame if a resize event is observed
Update the _CPAttachedWindow frame if a resize event is observed.
*/
- (void)observeValueForKeyPath:(CPString)aPath ofObject:(id)anObject change:(CPDictionary)theChange context:(void)aContext
{
if ([aPath isEqual:@"frame"])
{
// @TODO: not recompute everything, just compute the move offset
var g = [_windowView preferredEdge];
// TODO: don't recompute everything, just compute the move offset
var edge = [_windowView preferredEdge];
[self positionRelativeToView:_targetView preferredEdge:g];
}
}
#pragma mark -
#pragma mark Notification handlers
- (void)_attachedWindowDidMove:(CPNotification)aNotification
{
if ([_windowView isMouseDownPressed])
{
[_targetView removeObserver:self forKeyPath:@"frame"];
[_windowView hideCursor];
[self setLevel:CPNormalWindowLevel];
[_closeButton setFrameOrigin:CPPointMake(1.0, 1.0)];
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidMoveNotification object:self];
[self positionRelativeToRect:nil ofView:_targetView preferredEdge:edge];
}
}
@@ -210,59 +194,35 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
#pragma mark -
#pragma mark Utilities
- (CPPoint)computeOrigin:(CPView)aView preferredEdge:(int)anEdge
- (CGPoint)computeOriginFromRect:(CGRect)aRect ofView:(CPView)positioningView preferredEdge:(int)anEdge
{
var frameView = [aView frame],
currentView = aView,
origin = [aView frameOrigin],
lastView;
// if somebody succeed to use the conversion function of CPView
// to get this working, please do.
while (currentView = [currentView superview])
{
origin.x += [currentView frameOrigin].x;
origin.y += [currentView frameOrigin].y;
lastView = currentView;
}
origin.x += [[lastView window] frame].origin.x;
origin.y += [[lastView window] frame].origin.y;
// take care of the scrolling point
if ([aView enclosingScrollView])
{
var offsetPoint = [[[aView enclosingScrollView] contentView] boundsOrigin];
origin.x -= offsetPoint.x;
origin.y -= offsetPoint.y;
}
return [self computeOriginFromRect:CPRectMake(origin.x, origin.y, CPRectGetWidth(frameView), CPRectGetHeight(frameView)) preferredEdge:anEdge];
}
- (CPPoint)computeOriginFromRect:(CPRect)aRect preferredEdge:(int)anEdge
{
var nativeRect = [[[CPApp mainWindow] platformWindow] nativeContentRect],
originLeft = CPPointCreateCopy(aRect.origin),
originRight = CPPointCreateCopy(aRect.origin),
originTop = CPPointCreateCopy(aRect.origin),
originBottom = CPPointCreateCopy(aRect.origin);
var mainWindow = [CPApp mainWindow],
platformWindow = [mainWindow platformWindow],
nativeRect = [platformWindow nativeContentRect],
baseOrigin = [positioningView convertPointToBase:aRect.origin],
platformOrigin = [mainWindow convertBaseToPlatformWindow:baseOrigin],
platformRect = _CGRectMake(platformOrigin.x, platformOrigin.y, aRect.size.width, aRect.size.height),
originLeft = _CGPointCreateCopy(platformOrigin),
originRight = _CGPointCreateCopy(platformOrigin),
originTop = _CGPointCreateCopy(platformOrigin),
originBottom = _CGPointCreateCopy(platformOrigin),
frameSize = [self frame].size;
// CPMaxXEdge
originRight.x += aRect.size.width;
originRight.y += (aRect.size.height / 2.0) - (CPRectGetHeight([self frame]) / 2.0);
originRight.x += platformRect.size.width;
originRight.y += (platformRect.size.height / 2.0) - (frameSize.height / 2.0);
// CPMinXEdge
originLeft.x -= CPRectGetWidth([self frame]);
originLeft.y += (aRect.size.height / 2.0) - (CPRectGetHeight([self frame]) / 2.0);
originLeft.x -= frameSize.width;
originLeft.y += (platformRect.size.height / 2.0) - (frameSize.height / 2.0);
// CPMaxYEdge
originBottom.x += aRect.size.width / 2.0 - CPRectGetWidth([self frame]) / 2.0;
originBottom.y += aRect.size.height;
originBottom.x += platformRect.size.width / 2.0 - frameSize.width / 2.0;
originBottom.y += platformRect.size.height;
// CPMinYEdge
originTop.x += aRect.size.width / 2.0 - CPRectGetWidth([self frame]) / 2.0;
originTop.y -= CPRectGetHeight([self frame]);
originTop.x += platformRect.size.width / 2.0 - frameSize.width / 2.0;
originTop.y -= frameSize.height;
var requestedEdge = (anEdge !== nil) ? anEdge : CPMaxXEdge,
requestedOrigin;
@@ -288,51 +248,57 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
for (var i = 0; i < origins.length; i++)
{
var o = origins[i],
g = edges[i];
var origin = origins[i],
edge = edges[i];
[_windowView setArrowOffsetX:0];
[_windowView setArrowOffsetY:0];
[_windowView setPreferredEdge:g];
[_windowView setPreferredEdge:edge];
if (o.x < 0)
if (origin.x < 0)
{
[_windowView setArrowOffsetX:o.x];
o.x = 0;
}
if (o.x + CPRectGetWidth([self frame]) > nativeRect.size.width)
{
[_windowView setArrowOffsetX:(o.x + CPRectGetWidth([self frame]) - nativeRect.size.width)];
o.x = nativeRect.size.width - CPRectGetWidth([self frame]);
}
if (o.y < 0)
{
[_windowView setArrowOffsetY:o.y];
o.y = 0;
}
if (o.y + CPRectGetHeight([self frame]) > nativeRect.size.height)
{
[_windowView setArrowOffsetY:(CPRectGetHeight([self frame]) + o.y - nativeRect.size.height)];
o.y = nativeRect.size.height - CPRectGetHeight([self frame]);
[_windowView setArrowOffsetX:origin.x];
origin.x = 0;
}
switch (g)
if (origin.x + frameSize.width > nativeRect.size.width)
{
[_windowView setArrowOffsetX:(origin.x + frameSize.width - nativeRect.size.width)];
origin.x = nativeRect.size.width - frameSize.width;
}
if (origin.y < 0)
{
[_windowView setArrowOffsetY:origin.y];
origin.y = 0;
}
if (origin.y + frameSize.height > nativeRect.size.height)
{
[_windowView setArrowOffsetY:(frameSize.height + origin.y - nativeRect.size.height)];
origin.y = nativeRect.size.height - frameSize.height;
}
switch (edge)
{
case CPMaxXEdge:
if (o.x >= (aRect.origin.x + aRect.size.width))
return o;
if (origin.x >= _CGRectGetMaxX(platformRect))
return origin;
break;
case CPMinXEdge:
if ((o.x + _frame.size.width) <= aRect.origin.x)
return o;
if ((origin.x + frameSize.width) <= platformRect.origin.x)
return origin;
break;
case CPMaxYEdge:
if (o.y >= (aRect.origin.y + aRect.size.height))
return o;
if (origin.y >= _CGRectGetMaxY(platformRect))
return origin;
break;
case CPMinYEdge:
if ((o.y + _frame.size.height) <= aRect.origin.y)
return o;
if ((origin.y + frameSize.height) <= platformRect.origin.y)
return origin;
break;
}
}
@@ -349,59 +315,58 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
*/
- (void)positionRelativeToView:(CPView)aView
{
[self positionRelativeToView:aView preferredEdge:nil];
[self positionRelativeToRect:nil ofView:aView preferredEdge:nil];
}
/*!
Compute the frame needed to be placed to the given view
and position the attached window according to this view
Position the _CPAttachedWindow relative to a given rect's edge.
@param aView the view where _CPAttachedWindow must be attached
@param anEdge the preferd edge to use
*/
- (void)positionRelativeToView:(CPView)aView preferredEdge:(int)anEdge
{
var point = [self computeOrigin:aView preferredEdge:anEdge];
[self setFrameOrigin:point];
[_windowView showCursor];
[self setLevel:CPStatusWindowLevel];
[_closeButton setFrameOrigin:CPPointMake(1.0, 1.0)];
[_windowView setNeedsDisplay:YES];
[self makeKeyAndOrderFront:nil];
_targetView = aView;
[_targetView addObserver:self forKeyPath:@"frame" options:nil context:nil];
}
/*!
Position the _CPAttachedWindow to a random point
@param aPoint the point where the _CPAttachedWindow will be attached
*/
- (void)positionRelativeToRect:(CPRect)aRect
{
[self positionRelativeToRect:aRect preferredEdge:nil];
}
/*!
Position the _CPAttachedWindow to a random point
@param aPoint the point where the _CPAttachedWindow will be attached
@param aRect the rect relative to which the attached window will be positioned
@param positioningView the view to which the attached window is attached
@param anEdge the prefered edge
*/
- (void)positionRelativeToRect:(CPRect)aRect preferredEdge:(int)anEdge
- (void)positionRelativeToRect:(CGRect)aRect ofView:(CPView)positioningView preferredEdge:(int)anEdge
{
var point = [self computeOriginFromRect:aRect preferredEdge:anEdge];
if (!aRect || _CGRectIsEmpty(aRect))
aRect = [positioningView bounds];
var point = [self computeOriginFromRect:aRect ofView:positioningView preferredEdge:anEdge];
[self setFrameOrigin:point];
[_windowView showCursor];
[self setLevel:CPStatusWindowLevel];
[_closeButton setFrameOrigin:CPPointMake(1.0, 1.0)];
[_windowView setNeedsDisplay:YES];
[self makeKeyAndOrderFront:nil];
if (positioningView !== _targetView)
{
[_targetView removeObserver:self forKeyPath:@"frame"];
_targetView = positioningView;
[_targetView addObserver:self forKeyPath:@"frame" options:0 context:nil];
}
}
/*! @ignore */
- (void)setCSS3Property:(CPString)property value:(CPString)value
{
_DOMElement.style['webkit' + property] = value;
// Support other browsers here eventually
}
/*! @ignore */
- (BOOL)browserSupportsAnimation
{
return typeof(_DOMElement.style.webkitTransition) !== "undefined";
/*
No others browsers supported yet.
typeof(_DOMElement.style.MozTransition) !== "undefined" ||
typeof(_DOMElement.style.MsTransition) !== "undefined" ||
typeof(_DOMElement.style.OTransition) !== "undefined";
*/
}
#pragma mark -
#pragma mark Actions
@@ -421,99 +386,133 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,
#pragma mark Overrides
/*!
Called when the window is loowing focus and close the window if CPClosableOnBlurWindowMask is setted
Called when the window is losing focus.
*/
- (void)resignMainWindow
{
if (_closeOnBlur && !_isClosed)
if (_closeOnBlur && !_isClosing)
{
if (!_delegate || ((_implementedDelegateMethods & _CPAttachedWindow_attachedWindowShouldClose_)
&& [_delegate attachedWindowShouldClose:self]))
[self close];
if (!_delegate ||
((_implementedDelegateMethods & _CPAttachedWindow_attachedWindowShouldClose_) &&
[_delegate attachedWindowShouldClose:self]))
{
[self close];
}
}
}
/*!
Order front the window as usual and add listener for CPWindowDidMoveNotification
When the window appears, show animation if necessary.
Also take this opportunity to keep track of window moves.
@param sender the sender of the action
*/
- (IBAction)orderFront:(is)aSender
{
[super orderFront:aSender];
var tranformOrigin = "50% 100%";
switch ([_windowView preferredEdge])
if (![self isMainWindow])
{
case CPMaxYEdge:
var posX = 50 + (([_windowView arrowOffsetX] * 100) / _frame.size.width);
tranformOrigin = posX + "% 0%"; // 50 0
break;
case CPMinYEdge:
var posX = 50 + (([_windowView arrowOffsetX] * 100) / _frame.size.width);
tranformOrigin = posX + "% 100%"; // 50 100
break;
case CPMinXEdge:
var posY = 50 + (([_windowView arrowOffsetY] * 100) / _frame.size.height);
tranformOrigin = "100% " + posY + "%"; // 100 50
break;
case CPMaxXEdge:
var posY = 50 + (([_windowView arrowOffsetY] * 100) / _frame.size.height);
tranformOrigin = "0% "+ posY + "%"; // 0 50
break;
}
[super orderFront:aSender];
// @TODO: implement for FF
if (_animates && _shouldPerformAnimation && typeof(_DOMElement.style.WebkitTransform) != "undefined")
{
_DOMElement.style.opacity = 0;
_DOMElement.style.WebkitTransform = "scale(0)";
_DOMElement.style.WebkitTransformOrigin = tranformOrigin;
window.setTimeout(function()
if (_animates && _browserAnimates && _shouldPerformAnimation)
{
_DOMElement.style.height = _frame.size.height + @"px";
_DOMElement.style.width = _frame.size.width + @"px";
_DOMElement.style.opacity = 1;
_DOMElement.style.WebkitTransform = "scale(1.1)";
var transitionEndFunction = function()
{
_DOMElement.style.WebkitTransform = "scale(1)";
_DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES);
};
_DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES);
},0);
}
var transformOrigin = "50% 100%",
frame = [self frame],
preferredEdge = [_windowView preferredEdge],
posX;
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_attachedWindowDidMove:) name:CPWindowDidMoveNotification object:self];
switch (preferredEdge)
{
case CPMaxYEdge:
case CPMinYEdge:
posX = 50 + (([_windowView arrowOffsetX] * 100) / frame.size.width);
transformOrigin = posX + "% " + (preferredEdge === CPMaxYEdge ? "0%" : "100%");
break;
case CPMinXEdge:
case CPMaxXEdge:
posY = 50 + (([_windowView arrowOffsetY] * 100) / frame.size.height);
transformOrigin = (preferredEdge === CPMaxXEdge ? "0% " : "100% ") + posY + "%";
break;
}
// This is the initial transform. We start scaled to zero and watch for opacity changes.
[self setCSS3Property:@"Transform" value:@"scale(0)"];
[self setCSS3Property:@"TransformOrigin" value:transformOrigin];
[self setCSS3Property:@"Transition" value:"opacity 0 linear"];
window.setTimeout(function()
{
// We are watching opacity, so this triggers the next transition
_DOMElement.style.opacity = 1;
_DOMElement.style.height = frame.size.height + @"px";
_DOMElement.style.width = frame.size.width + @"px";
// Set up the pop-out transition
[self setCSS3Property:@"Transform" value:@"scale(1.1)"];
[self setCSS3Property:@"Transition" value:@"-webkit-transform 200ms ease-in"];
var transitionEndFunction = function()
{
_DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES);
// Now set up the pop-in to normal size transition.
// Because we are watching the -webkit-transform, it will occur now.
[self setCSS3Property:@"Transform" value:@"scale(1)"];
[self setCSS3Property:@"Transition" value:@"-webkit-transform 50ms linear"];
};
_DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES);
}, 0);
}
else
{
[self setCSS3Property:@"Transition" value:@""];
_DOMElement.style.opacity = 1;
}
}
_shouldPerformAnimation = NO;
_isClosed = NO;
_isClosing = NO;
}
/*!
Close the windo with animation
Animate window closing.
*/
- (void)close
{
// set a close flag to avoid infinite loop
_isClosed = YES;
if (![self isVisible])
return;
if (_animates && typeof(_DOMElement.style.WebkitTransform) != "undefined")
// set a flag to avoid an infinite loop in resignMainWindow
_isClosing = YES;
if (_animates && _browserAnimates)
{
// Tell the element to fade out when the opacity changes
[self setCSS3Property:@"Transition" value:@"opacity 250ms linear"];
_DOMElement.style.opacity = 0;
var transitionEndFunction = function(){
[super close];
var transitionEndFunction = function()
{
_DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES);
[self _close];
};
_DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES);
}
else
[super close];
{
[self _close];
}
}
- (void)_close
{
[super close];
[_targetView removeObserver:self forKeyPath:@"frame"];
_shouldPerformAnimation = _animates;
_shouldPerformAnimation = YES;
_isClosing = NO;
if (_implementedDelegateMethods & _CPAttachedWindow_attachedWindowDidClose_)
[_delegate attachedWindowDidClose:self];
+1 -1
View File
@@ -46,7 +46,7 @@
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"divider-color"]);
CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 0.5, ROUND(_CGRectGetMinY(aRect)));
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 0.5, ROUND(_CGRectGetMaxY(aRect)));
CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 0.5, ROUND(_CGRectGetMaxY(aRect)) - 1.0);
CGContextClosePath(context);
CGContextStrokePath(context);
+26 -4
View File
@@ -100,7 +100,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
[self setAlignment:CPCenterTextAlignment];
[self setFont:[CPFont systemFontOfSize:12.0]];
[self setImagePosition:CPNoImage];
[self setImageScaling:CPScaleNone];
[self setImageScaling:CPImageScaleNone];
}
_textSize = nil;
@@ -288,6 +288,28 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
return _textShadowOffset;
}
- (CGRect)textFrame
{
[self layoutIfNeeded];
var textFrame = CGRectMakeZero();
if (_DOMTextElement)
{
var textStyle = _DOMTextElement.style;
textFrame.origin.y = parseInt(textStyle.top.substr(0, textStyle.top.length - 2), 10),
textFrame.origin.x = parseInt(textStyle.left.substr(0, textStyle.left.length - 2), 10),
textFrame.size.width = parseInt(textStyle.width.substr(0, textStyle.width.length - 2), 10),
textFrame.size.height = parseInt(textStyle.height.substr(0, textStyle.height.length - 2), 10);
textFrame.size.width += _textShadowOffset.width;
textFrame.size.height += _textShadowOffset.height;
}
return textFrame;
}
- (void)setImage:(CPImage)anImage
{
if (_image == anImage)
@@ -462,7 +484,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
if (_flags & _CPImageAndTextViewFontChangedFlag)
{
var fontStyle = [_font ? _font : [CPFont systemFontOfSize:12.0] cssString];
var fontStyle = [(_font ? _font : [CPFont systemFontOfSize:12.0]) cssString];
textStyle.font = fontStyle;
if (shadowStyle)
@@ -585,12 +607,12 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
imageWidth = imageSize.width,
imageHeight = imageSize.height;
if (_imageScaling === CPScaleToFit)
if (_imageScaling === CPImageScaleAxesIndependently)
{
imageWidth = size.width;
imageHeight = size.height;
}
else if (_imageScaling === CPScaleProportionally)
else if (_imageScaling === CPImageScaleProportionallyDown)
{
var scale = MIN(MIN(size.width, imageWidth) / imageWidth, MIN(size.height, imageHeight) / imageHeight);
+1 -118
View File
@@ -27,10 +27,7 @@
_CPToolTipWindowMask = 1 << 27;
var _CPToolTipHeight = 24.0,
_CPToolTipFontSize = 11.0,
_CPCurrentToolTip,
_CPCurrentToolTipTimer,
_CPToolTipDelay = 1.0;
_CPToolTipFontSize = 11.0;
/*! @ingroup appkit
This is a basic tooltip that behaves mostly like Cocoa ones.
@@ -178,118 +175,4 @@ var _CPToolTipHeight = 24.0,
/*! @ingroup appkit
Add tooltip support to CPView.
*/
@implementation CPView (toolTips)
/*!
Sets the tooltip for the receiver.
@param aToolTip the tooltip
*/
- (void)setToolTip:(CPString)aToolTip
{
if (_toolTip == aToolTip)
return;
_toolTip = aToolTip;
if (!_DOMElement)
return;
var fIn = function(e)
{
[self _fireToolTip];
},
fOut = function(e)
{
[self _invalidateToolTip];
};
if (_toolTip)
{
if (_DOMElement.addEventListener)
{
_DOMElement.addEventListener("mouseover", fIn, NO);
_DOMElement.addEventListener("keypress", fOut, NO);
_DOMElement.addEventListener("mouseout", fOut, NO);
}
else if (_DOMElement.attachEvent)
{
_DOMElement.attachEvent("onmouseover", fIn);
_DOMElement.attachEvent("onkeypress", fOut);
_DOMElement.attachEvent("onmouseout", fOut);
}
}
else
{
if (_DOMElement.removeEventListener)
{
_DOMElement.removeEventListener("mouseover", fIn, NO);
_DOMElement.removeEventListener("keypress", fOut, NO);
_DOMElement.removeEventListener("mouseout", fOut, NO);
}
else if (_DOMElement.detachEvent)
{
_DOMElement.detachEvent("onmouseover", fIn);
_DOMElement.detachEvent("onkeypress", fOut);
_DOMElement.detachEvent("onmouseout", fOut);
}
}
}
/*!
Returns the receiver's tooltip.
*/
- (CPString)toolTip
{
return _toolTip;
}
/*! @ignore
Starts the tooltip timer.
*/
- (void)_fireToolTip
{
if (_CPCurrentToolTipTimer)
{
[_CPCurrentToolTipTimer invalidate];
if (_CPCurrentToolTip)
[_CPCurrentToolTip close];
_CPCurrentToolTip = nil;
}
if (_toolTip)
_CPCurrentToolTipTimer = [CPTimer scheduledTimerWithTimeInterval:_CPToolTipDelay target:self selector:@selector(_showToolTip:) userInfo:nil repeats:NO];
}
/*! @ignore
Stop the tooltip timer if any
*/
- (void)_invalidateToolTip
{
if (_CPCurrentToolTipTimer)
{
[_CPCurrentToolTipTimer invalidate];
_CPCurrentToolTipTimer = nil;
}
if (_CPCurrentToolTip)
{
[_CPCurrentToolTip close];
_CPCurrentToolTip = nil;
}
}
/*! @ignore
Actually shows the tooltip if any
*/
- (void)_showToolTip:(CPTimer)aTimer
{
if (_CPCurrentToolTip)
[_CPCurrentToolTip close];
_CPCurrentToolTip = [_CPToolTip toolTipWithString:_toolTip];
}
@end
+1 -1
View File
@@ -49,7 +49,7 @@ function findCibClassDependencies(cibPath) {
var key = nil,
keyEnumerator = [replacementClasses keyEnumerator];
while (key = [keyEnumerator nextObject])
while ((key = [keyEnumerator nextObject]) !== nil)
[unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
}
+12
View File
@@ -0,0 +1,12 @@
diff -rupN a/engines/rhino/bin/narwhal-rhino b/engines/rhino/bin/narwhal-rhino
--- a/engines/rhino/bin/narwhal-rhino 2011-11-16 11:01:40.000000000 +0000
+++ b/engines/rhino/bin/narwhal-rhino 2012-04-23 18:35:45.000000000 +0100
@@ -22,7 +22,7 @@ fi
CLASSPATH=$NARWHAL_ENGINE_HOME/jars/jna.jar
BOOTCLASSPATH=$NARWHAL_ENGINE_HOME/jars/js.jar
-JAVA_OPTS="-Dnarwhal.http_proxy=$http_proxy"
+JAVA_OPTS="-Dnarwhal.http_proxy=$http_proxy $JAVA_OPTS"
if [ -n "$NARWHAL_CLASSPATH" ]; then
CLASSPATH=$NARWHAL_CLASSPATH:$CLASSPATH
+13 -101
View File
@@ -22,6 +22,7 @@
@import "CPArray.j"
@import "CPNull.j"
@import "_CPCollectionKVCOperators.j"
@implementation CPObject (CPArrayKVO)
@@ -240,6 +241,7 @@
{
if (_objectsAtIndexes)
return _objectsAtIndexes(_proxyObject, _objectsAtIndexesSEL, theIndexes);
if (_objectAtIndex)
{
var index = CPNotFound,
@@ -413,21 +415,21 @@
@end
//KVC on CPArray objects act on each item of the array, rather than on the array itself
// KVC on CPArray objects act on each item of the array, rather than on the array itself
@implementation CPArray (KeyValueCoding)
@implementation CPArray (CPKeyValueCoding)
- (id)valueForKey:(CPString)aKey
{
if (aKey.indexOf("@") === 0)
{
if (aKey.indexOf(".") !== -1)
[CPException raise:CPInvalidArgumentException reason:"called valueForKey: on an array with a complex key ("+aKey+"). use valueForKeyPath:"];
[CPException raise:CPInvalidArgumentException reason:"called valueForKey: on an array with a complex key (" + aKey + "). use valueForKeyPath:"];
if (aKey == "@count")
if (aKey === "@count")
return length;
return nil;
return [self valueForUndefinedKey:aKey];
}
else
{
@@ -451,6 +453,9 @@
- (id)valueForKeyPath:(CPString)aKeyPath
{
if (!aKeyPath)
[self valueForUndefinedKey:@"<empty path>"];
if (aKeyPath.charAt(0) === "@")
{
var dotIndex = aKeyPath.indexOf("."),
@@ -465,10 +470,7 @@
else
operator = aKeyPath.substring(1);
if (kvoOperators[operator])
return kvoOperators[operator](self, _cmd, parameter);
return nil;
return [_CPCollectionKVCOperator performOperation:operator withCollection:self propertyPath:parameter];
}
else
{
@@ -495,7 +497,7 @@
var enumerator = [self objectEnumerator],
object;
while (object = [enumerator nextObject])
while ((object = [enumerator nextObject]) !== nil)
[object setValue:aValue forKey:aKey];
}
@@ -504,86 +506,12 @@
var enumerator = [self objectEnumerator],
object;
while (object = [enumerator nextObject])
while ((object = [enumerator nextObject]) !== nil)
[object setValue:aValue forKeyPath:aKeyPath];
}
@end
var kvoOperators = [];
// HACK: prevent these from becoming globals. workaround for obj-j "function foo(){}" behavior
var avgOperator,
maxOperator,
minOperator,
countOperator,
sumOperator;
kvoOperators["avg"] = function avgOperator(self, _cmd, param)
{
var objects = [self valueForKeyPath:param],
length = [objects count],
index = length,
average = 0.0;
if (!length)
return 0;
while (index--)
average += [objects[index] doubleValue];
return average / length;
}
kvoOperators["max"] = function maxOperator(self, _cmd, param)
{
var objects = [self valueForKeyPath:param],
index = [objects count] - 1,
max = [objects lastObject];
while (index--)
{
var item = objects[index];
if ([max compare:item] < 0)
max = item;
}
return max;
}
kvoOperators["min"] = function minOperator(self, _cmd, param)
{
var objects = [self valueForKeyPath:param],
index = [objects count] - 1,
min = [objects lastObject];
while (index--)
{
var item = objects[index];
if ([min compare:item] > 0)
min = item;
}
return min;
}
kvoOperators["count"] = function countOperator(self, _cmd, param)
{
return [self count];
}
kvoOperators["sum"] = function sumOperator(self, _cmd, param)
{
var objects = [self valueForKeyPath:param],
index = [objects count],
sum = 0.0;
while (index--)
sum += [objects[index] doubleValue];
return sum;
}
@implementation CPArray (KeyValueObserving)
- (void)addObserver:(id)anObserver toObjectsAtIndexes:(CPIndexSet)indexes forKeyPath:(CPString)aKeyPath options:(unsigned)options context:(id)context
@@ -610,20 +538,4 @@ kvoOperators["sum"] = function sumOperator(self, _cmd, param)
}
}
- (void)addObserver:(id)observer forKeyPath:(CPString)aKeyPath options:(unsigned)options context:(id)context
{
if ([isa instanceMethodForSelector:_cmd] === [CPArray instanceMethodForSelector:_cmd])
[CPException raise:CPInvalidArgumentException reason:"Unsupported method on CPArray"];
else
[super addObserver:observer forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)observer forKeyPath:(CPString)aKeyPath
{
if ([isa instanceMethodForSelector:_cmd] === [CPArray instanceMethodForSelector:_cmd])
[CPException raise:CPInvalidArgumentException reason:"Unsupported method on CPArray"];
else
[super removeObserver:observer forKeyPath:aKeyPath];
}
@end
+37 -4
View File
@@ -522,7 +522,7 @@ var concat = Array.prototype.concat,
if ([objects count])
{
argumentsArray = [[nil, aSelector] arrayByAddingObjectsFromArray:objects];
var argumentsArray = [[nil, aSelector] arrayByAddingObjectsFromArray:objects];
for (; index < count; ++index)
{
@@ -536,13 +536,46 @@ var concat = Array.prototype.concat,
objj_msgSend([self objectAtIndex:index], aSelector);
}
- (void)enumerateObjectsUsingBlock:(Function)aFunction
- (void)enumerateObjectsUsingBlock:(Function /*(id anObject, int idx, @ref BOOL stop)*/)aFunction
{
// This could have been [self enumerateObjectsWithOptions:CPEnumerationNormal usingBlock:aFunction]
// but this method should be as fast as possible.
var index = 0,
count = [self count];
count = [self count],
shouldStop = NO,
shouldStopRef = AT_REF(shouldStop);
for (; index < count; ++index)
aFunction([self objectAtIndex:index], index);
{
aFunction([self objectAtIndex:index], index, shouldStopRef);
if (shouldStop)
return;
}
}
- (void)enumerateObjectsWithOptions:(CPEnumerationOptions)options usingBlock:(Function /*(id anObject, int idx, @ref BOOL stop)*/)aFunction
{
var shouldStop = NO;
if (options & CPEnumerationReverse)
{
var index = [self count] - 1,
stop = -1,
increment = -1;
}
else
{
var index = 0,
stop = [self count],
increment = 1;
}
for (; index !== stop; index += increment)
{
aFunction([self objectAtIndex:index], index, AT_REF(shouldStop));
if (shouldStop)
return;
}
}
// Comparing arrays
+1 -1
View File
@@ -163,7 +163,7 @@ var concat = Array.prototype.concat,
if ([objects count])
{
argumentsArray = [[nil, aSelector] arrayByAddingObjectsFromArray:objects];
var argumentsArray = [[nil, aSelector] arrayByAddingObjectsFromArray:objects];
for (; index < count; ++index)
{
+1 -1
View File
@@ -241,7 +241,7 @@ var CPCharacterSetInvertedKey = @"CPCharacterSetInvertedKey";
var enu = [_ranges objectEnumerator],
range;
while (range = [enu nextObject])
while ((range = [enu nextObject]) !== nil)
{
if (CPLocationInRange(c, range))
return !_inverted;
+26
View File
@@ -65,6 +65,22 @@
return [[self alloc] initWithJSONObject:anObject];
}
+ (CPData)dataWithBytes:(CPArray)bytesArray
{
var data = [[self alloc] init];
data.setBytes(bytesArray);
return data;
}
+ (CPData)dataWithBase64:(CPString)aString
{
var data = [[self alloc] init];
data.setBase64String(aString);
return data;
}
- (id)initWithRawString:(CPString)aString
{
self = [super init];
@@ -120,6 +136,16 @@
return self.JSONObject();
}
- (CPArray)bytes
{
return self.bytes();
}
- (CPString)base64
{
return self.base64();
}
- (int)length
{
return [[self rawString] length];
+37 -1
View File
@@ -119,7 +119,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 1, 1, 0, 0, 0, 0));
date.setMinutes(d[5]);
date.setSeconds(d[6]);
self = new Date(date.getTime() + (timeZoneOffset - date.getTimezoneOffset()) * 60 * 1000);
self = new Date(date.getTime() + (timeZoneOffset - date.getTimezoneOffset()) * 60 * 1000);
return self;
}
@@ -231,4 +231,40 @@ var CPDateTimeKey = @"CPDateTimeKey";
@end
// Based on 'Universal JavaScript Date.parse for ISO 8601' available at https://github.com/csnover/js-iso8601.
var numericKeys = [1, 4, 5, 6, 7, 10, 11];
Date.parseISO8601 = function (date)
{
var timestamp,
struct,
minutesOffset = 0;
// First, check for native parsing.
timestamp = Date.parse(date);
if (isNaN(timestamp) && (struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date)))
{
// avoid NaN timestamps caused by “undefined” values being passed to Date.UTC
for (var i = 0, k; (k = numericKeys[i]); ++i)
struct[k] = +struct[k] || 0;
// allow undefined days and months
struct[2] = (+struct[2] || 1) - 1;
struct[3] = +struct[3] || 1;
if (struct[8] !== 'Z' && struct[9] !== undefined)
{
minutesOffset = struct[10] * 60 + struct[11];
if (struct[9] === '+')
minutesOffset = 0 - minutesOffset;
}
return Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
}
return timestamp;
};
Date.prototype.isa = CPDate;
+136
View File
@@ -0,0 +1,136 @@
/*
* CPDateFormatter.j
* Foundation
*
* Created by Alexander Ljungberg.
* Copyright 2012, SlevenBits Ltd.
*
* 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 "Ref.h"
@import <Foundation/CPDate.j>
@import <Foundation/CPString.j>
@import <Foundation/CPFormatter.j>
CPDateFormatterNoStyle = 0;
CPDateFormatterShortStyle = 1;
CPDateFormatterMediumStyle = 2;
CPDateFormatterLongStyle = 3;
CPDateFormatterFullStyle = 4;
/*!
@ingroup foundation
@class CPDateFormatter
* Not yet implemented. This is a stub class. *
CPDateFormatter takes a CPDate value and formats it as text for
display. It also supports the converse, taking text and interpreting it as a
CPDate by configurable formatting rules.
*/
@implementation CPDateFormatter : CPFormatter
{
CPDateFormatterStyle _dateStyle @accessors(property=dateStyle);
}
- (id)init
{
if (self = [super init])
{
_dateStyle = CPDateFormatterShortStyle;
}
return self;
}
- (CPString)stringFromDate:(CPDate)aDate
{
// TODO Add locale support.
switch (_dateStyle)
{
case CPDateFormatterShortStyle:
var format = "d/m/Y";
return aDate.dateFormat(format);
default:
return [aDate description];
}
}
- (CPDate)dateFromString:(CPString)aString
{
if (!aString)
return nil;
switch (_dateStyle)
{
case CPDateFormatterShortStyle:
var format = "d/m/Y";
return Date.parseDate(string, format);
default:
return Date.parseDate(string);
}
}
- (CPString)stringForObjectValue:(id)anObject
{
if ([anObject isKindOfClass:[CPDate class]])
return [self stringFromDate:anObject];
else
return [anObject description];
}
- (CPString)editingStringForObjectValue:(id)anObject
{
return [self stringForObjectValue:anObject];
}
- (BOOL)getObjectValue:(id)anObject forString:(CPString)aString errorDescription:(CPString)anError
{
console.log("getObjectValue: forString:" + aString);
// TODO Error handling.
var value = [self dateFromString:aString];
AT_DEREF(anObject, value);
console.log("got " + value);
return YES;
}
@end
var CPDateFormatterStyleKey = "CPDateFormatterStyle";
@implementation CPDateFormatter (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_dateStyle = [aCoder decodeIntForKey:CPDateFormatterStyleKey];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_dateStyle forKey:CPDateFormatterStyleKey];
}
@end
+1 -1
View File
@@ -50,7 +50,7 @@
{
var key = [_keyEnumerator nextObject];
if (!key)
if (key === nil)
return nil;
return [_dictionary objectForKey:key];
+83 -14
View File
@@ -483,6 +483,75 @@
return description;
}
- (void)enumerateIndexesUsingBlock:(Function /*(int idx, @ref BOOL stop) */)aFunction
{
[self enumerateIndexesWithOptions:CPEnumerationNormal usingBlock:aFunction];
}
- (void)enumerateIndexesWithOptions:(CPEnumerationOptions)options usingBlock:(Function /*(int idx, @ref BOOL stop)*/)aFunction
{
if (!_count)
return;
[self enumerateIndexesInRange:CPMakeRange(0, _CPMaxRange(_ranges[_ranges.length - 1])) options:options usingBlock:aFunction];
}
- (void)enumerateIndexesInRange:(CPRange)enumerationRange options:(CPEnumerationOptions)options usingBlock:(Function /*(int idx, @ref BOOL stop)*/)aFunction
{
if (!_count || CPEmptyRange(enumerationRange))
return;
var shouldStop = NO,
index,
stop,
increment;
if (options & CPEnumerationReverse)
{
index = _ranges.length - 1,
stop = -1,
increment = -1;
}
else
{
index = 0;
stop = _ranges.length;
increment = 1;
}
for (; index !== stop; index += increment)
{
var range = _ranges[index];
var rangeIndex,
rangeStop,
rangeIncrement;
if (options & CPEnumerationReverse)
{
rangeIndex = _CPMaxRange(range) - 1;
rangeStop = range.location - 1;
rangeIncrement = -1;
}
else
{
rangeIndex = range.location;
rangeStop = _CPMaxRange(range);
rangeIncrement = 1;
}
for (; rangeIndex !== rangeStop; rangeIndex += rangeIncrement)
{
if (CPLocationInRange(rangeIndex, enumerationRange))
{
aFunction(rangeIndex, AT_REF(shouldStop));
if (shouldStop)
return;
}
}
}
}
@end
@implementation CPIndexSet(CPMutableIndexSet)
@@ -537,7 +606,7 @@
if (lhsRangeIndexCEIL === lhsRangeIndex && lhsRangeIndexCEIL < rangeCount)
aRange = CPUnionRange(aRange, _ranges[lhsRangeIndexCEIL]);
var rhsRangeIndex = assumedPositionOfIndex(_ranges, CPMaxRange(aRange)),
var rhsRangeIndex = assumedPositionOfIndex(_ranges, _CPMaxRange(aRange)),
rhsRangeIndexFLOOR = FLOOR(rhsRangeIndex);
if (rhsRangeIndexFLOOR === rhsRangeIndex && rhsRangeIndexFLOOR >= 0)
@@ -640,8 +709,8 @@
// If these ranges don't start in the same place, we have to cull it.
if (aRange.location !== existingRange.location)
{
var maxRange = CPMaxRange(aRange),
existingMaxRange = CPMaxRange(existingRange);
var maxRange = _CPMaxRange(aRange),
existingMaxRange = _CPMaxRange(existingRange);
existingRange.length = aRange.location - existingRange.location;
@@ -661,14 +730,14 @@
}
}
var rhsRangeIndex = assumedPositionOfIndex(_ranges, CPMaxRange(aRange) - 1),
var rhsRangeIndex = assumedPositionOfIndex(_ranges, _CPMaxRange(aRange) - 1),
rhsRangeIndexFLOOR = FLOOR(rhsRangeIndex);
if (rhsRangeIndex === rhsRangeIndexFLOOR && rhsRangeIndexFLOOR >= 0)
{
var maxRange = CPMaxRange(aRange),
var maxRange = _CPMaxRange(aRange),
existingRange = _ranges[rhsRangeIndexFLOOR],
existingMaxRange = CPMaxRange(existingRange);
existingMaxRange = _CPMaxRange(existingRange);
if (maxRange !== existingMaxRange)
{
@@ -714,7 +783,7 @@
for (; i >= 0; --i)
{
var range = _ranges[i],
maximum = CPMaxRange(range);
maximum = _CPMaxRange(range);
if (anIndex >= maximum)
break;
@@ -734,7 +803,7 @@
// If it's negative, it needs to be added properly later.
else if (shifted.location < 0)
{
shifted.length = CPMaxRange(shifted);
shifted.length = _CPMaxRange(shifted);
shifted.location = 0;
}
@@ -745,8 +814,8 @@
// Shift the range, and normalize it if the result is negative.
if ((range.location += aDelta) < 0)
{
_count -= range.length - CPMaxRange(range);
range.length = CPMaxRange(range);
_count -= range.length - _CPMaxRange(range);
range.length = _CPMaxRange(range);
range.location = 0;
}
}
@@ -766,7 +835,7 @@
if ((j = i + 1) < count)
{
[_ranges removeObjectsInRange:CPMakeRange(j, count - j)];
[_ranges removeObjectsInRange:_CPMakeRange(j, count - j)];
for (j = 0, count = shifts.length; j < count; ++j)
[self addIndexesInRange:shifts[j]];
@@ -882,7 +951,7 @@ var positionOfIndex = function(ranges, anIndex)
if (anIndex < range.location)
high = middle - 1;
else if (anIndex >= CPMaxRange(range))
else if (anIndex >= _CPMaxRange(range))
low = middle + 1;
else
@@ -910,7 +979,7 @@ var assumedPositionOfIndex = function(ranges, anIndex)
if (position === positionFLOOR)
{
if (positionFLOOR - 1 >= 0 && anIndex < CPMaxRange(ranges[positionFLOOR - 1]))
if (positionFLOOR - 1 >= 0 && anIndex < _CPMaxRange(ranges[positionFLOOR - 1]))
high = middle - 1;
else if (positionFLOOR < count && anIndex >= ranges[positionFLOOR].location)
@@ -926,7 +995,7 @@ var assumedPositionOfIndex = function(ranges, anIndex)
if (anIndex < range.location)
high = middle - 1;
else if (anIndex >= CPMaxRange(range))
else if (anIndex >= _CPMaxRange(range))
low = middle + 1;
else
+8 -3
View File
@@ -157,7 +157,7 @@ var CPObjectAccessorsForClassKey = @"$CPObjectAccessorsForClassKey",
- (id)valueForUndefinedKey:(CPString)aKey
{
[[CPException exceptionWithName:CPUndefinedKeyException
reason:[self description] + " is not key value coding-compliant for the key " + aKey
reason:[self _objectDescription] + " is not key value coding-compliant for the key " + aKey
userInfo:[CPDictionary dictionaryWithObjects:[self, aKey] forKeys:[CPTargetObjectUserInfoKey, CPUnknownUserInfoKey]]] raise];
}
@@ -235,7 +235,7 @@ var CPObjectAccessorsForClassKey = @"$CPObjectAccessorsForClassKey",
key,
keyEnumerator = [keyedValues keyEnumerator];
while (key = [keyEnumerator nextObject])
while ((key = [keyEnumerator nextObject]) !== nil)
{
value = [keyedValues objectForKey: key];
@@ -250,10 +250,15 @@ var CPObjectAccessorsForClassKey = @"$CPObjectAccessorsForClassKey",
- (void)setValue:(id)aValue forUndefinedKey:(CPString)aKey
{
[[CPException exceptionWithName:CPUndefinedKeyException
reason:[self description] + " is not key value coding-compliant for the key " + aKey
reason:[self _objectDescription] + " is not key value coding-compliant for the key " + aKey
userInfo:[CPDictionary dictionaryWithObjects:[self, aKey] forKeys:[CPTargetObjectUserInfoKey, CPUnknownUserInfoKey]]] raise];
}
- (CPString)_objectDescription
{
return "<" + [self className] + " 0x" + [CPString stringWithHash:[self UID]] + ">";
}
@end
@implementation CPDictionary (CPKeyValueCoding)
+18 -2
View File
@@ -69,8 +69,24 @@
[self[KVOProxyKey] _removeObserver:anObserver forKeyPath:aPath];
}
/*!
Whether -willChangeValueForKey/-didChangeValueForKey should automatically be invoked when the
setter of the given key is used. The default is YES. If you override this method to return NO
for some key, you will need to call -willChangeValueForKey/-didChangeValueForKey manually to
be KVO compliant.
The default implementation of this method will check if the receiving class implements
`+ (BOOL)automaticallyNotifiesObserversOf<aKey>` and return the response of that method if it
exists.
*/
+ (BOOL)automaticallyNotifiesObserversForKey:(CPString)aKey
{
var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substring(1),
selector = "automaticallyNotifiesObserversOf" + capitalizedKey;
if ([[self class] respondsToSelector:selector])
return objj_msgSend([self class], selector);
return YES;
}
@@ -648,7 +664,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
var forwarder = nil;
if (aPath.indexOf('.') != CPNotFound)
if (aPath.indexOf('.') !== CPNotFound && aPath.charAt(0) !== '@')
forwarder = [[_CPKVOForwardingObserver alloc] initWithKeyPath:aPath object:_targetObject observer:anObserver options:options context:aContext];
else
[self _replaceModifiersForKey:aPath];
@@ -1076,7 +1092,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti
var dotIndex = aKeyPath.indexOf('.');
if (dotIndex == CPNotFound)
if (dotIndex === CPNotFound)
[CPException raise:CPInvalidArgumentException reason:"Created _CPKVOForwardingObserver without compound key path: "+aKeyPath];
_firstPart = aKeyPath.substring(0, dotIndex);
+1 -1
View File
@@ -398,7 +398,7 @@ var _CPKeyedArchiverStringClass = Nil,
keys = [aDictionary keyEnumerator],
references = [CPDictionary dictionary];
while (key = [keys nextObject])
while ((key = [keys nextObject]) !== nil)
[references setObject:_CPKeyedArchiverEncodeObject(self, [aDictionary objectForKey:key], NO) forKey:key];
[_plistObject setObject:references forKey:aKey];
+17 -10
View File
@@ -251,7 +251,9 @@ var CPArrayClass = Ni
*/
- (float)decodeFloatForKey:(CPString)aKey
{
return [self decodeObjectForKey:aKey];
var f = [self decodeObjectForKey:aKey];
return f === nil ? 0.0 : f;
}
/*
@@ -261,7 +263,9 @@ var CPArrayClass = Ni
*/
- (double)decodeDoubleForKey:(CPString)aKey
{
return [self decodeObjectForKey:aKey];
var d = [self decodeObjectForKey:aKey];
return d === nil ? 0.0 : d;
}
/*
@@ -271,7 +275,9 @@ var CPArrayClass = Ni
*/
- (int)decodeIntForKey:(CPString)aKey
{
return [self decodeObjectForKey:aKey];
var i = [self decodeObjectForKey:aKey];
return i === nil ? 0 : i;
}
/*
@@ -284,9 +290,9 @@ var CPArrayClass = Ni
var object = [self decodeObjectForKey:aKey];
if (object)
return CPPointFromString(object);
return CGPointFromString(object);
else
return CPPointMake(0.0, 0.0);
return CGPointMakeZero();
}
/*
@@ -299,9 +305,9 @@ var CPArrayClass = Ni
var object = [self decodeObjectForKey:aKey];
if (object)
return CPRectFromString(object);
return CGRectFromString(object);
else
return CPRectMakeZero();
return CGRectMakeZero();
}
/*
@@ -314,9 +320,9 @@ var CPArrayClass = Ni
var object = [self decodeObjectForKey:aKey];
if (object)
return CPSizeFromString(object);
return CGSizeFromString(object);
else
return CPSizeMake(0.0, 0.0);
return CGSizeMakeZero();
}
/*
@@ -366,8 +372,9 @@ var CPArrayClass = Ni
return nil;
var objectClass = data.isa;
if (objectClass === CPDataClass)
return data.bytes;
return data.bytes();
return nil;
}
+3 -3
View File
@@ -103,7 +103,7 @@ var CPNotificationDefaultCenter = nil;
var name = nil,
names = [_namedRegistries keyEnumerator];
while (name = [names nextObject])
while ((name = [names nextObject]) !== nil)
[[_namedRegistries objectForKey:name] removeObserver:anObserver object:nil];
[_unnamedRegistry removeObserver:anObserver object:nil];
@@ -122,7 +122,7 @@ var CPNotificationDefaultCenter = nil;
var name = nil,
names = [_namedRegistries keyEnumerator];
while (name = [names nextObject])
while ((name = [names nextObject]) !== nil)
[[_namedRegistries objectForKey:name] removeObserver:anObserver object:anObject];
[_unnamedRegistry removeObserver:anObserver object:anObject];
@@ -225,7 +225,7 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */
keys = [_objectObservers keyEnumerator];
// Iterate through every set of observers
while (key = [keys nextObject])
while ((key = [keys nextObject]) !== nil)
{
var observers = [_objectObservers objectForKey:key],
observer = nil,
+2 -2
View File
@@ -77,7 +77,7 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain;
- (CPString)stringFromNumber:(CPNumber)number
{
// TODO Add locale support.
switch(_numberStyle)
switch (_numberStyle)
{
case CPNumberFormatterDecimalStyle:
UPDATE_NUMBER_HANDLER_IF_NECESSARY();
@@ -96,7 +96,7 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain;
// TODO This is just a temporary solution. Should be generalised.
// Add in thousands separators.
if (perMillSymbol)
while(commaPosition < [preFraction length])
while (commaPosition < [preFraction length])
{
preFraction = [preFraction stringByReplacingCharactersInRange:CPMakeRange(commaPosition, 0) withString:perMillSymbol];
commaPosition += 4;
+12
View File
@@ -329,6 +329,18 @@ CPLog(@"Got some class: %@", inst);
return objj_msgSend(self, aSelector, anObject, anotherObject);
}
/*!
Sends the specified message to the reciever, with any number of arguments.
@param aSelector the message to send
@param anObject... comma seperated objects to pass to the selector
@return the return value of the message
*/
- (id)performSelector:(SEL)aSelector withObjects:(id)anObject, ...
{
var params = [self, aSelector].concat(Array.prototype.slice.apply(arguments, [3]));
return objj_msgSend.apply(this, params);
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
return nil;
@@ -512,9 +512,10 @@ var CPComparisonPredicateModifier,
result = (_modifier == CPAllPredicateModifier),
value;
while (value = [e nextObject])
while ((value = [e nextObject]) !== nil)
{
var eval = [self _evaluateValue:value rightValue:rightValue];
if (eval != result)
return eval;
}
+1 -1
View File
@@ -170,7 +170,7 @@ var CPCompoundPredicateType;
switch (_type)
{
case CPNotPredicateType: result += "NOT %s" + [args objectAtIndex:0];
case CPNotPredicateType: result += "NOT " + [args objectAtIndex:0];
break;
case CPAndPredicateType: result += [args objectAtIndex:0];
@@ -59,7 +59,7 @@
collection = [_aggregate objectEnumerator],
exp;
while (exp = [collection nextObject])
while ((exp = [collection nextObject]) !== nil)
{
var eval = [exp expressionValueWithObject:object context:context];
[eval_array addObject:eval];
+26 -114
View File
@@ -23,6 +23,7 @@
@import "CPException.j"
@import "CPObject.j"
@import "CPSet.j"
@import "_CPCollectionKVCOperators.j"
@implementation CPObject (CPSetKVO)
@@ -218,7 +219,8 @@
{
var object,
objectEnumerator = [objects objectEnumerator];
while (object = [objectEnumerator nextObject])
while ((object = [objectEnumerator nextObject]) !== nil)
_add(_proxyObject, _addSEL, object);
}
else
@@ -237,7 +239,8 @@
{
var object,
objectEnumerator = [aSet objectEnumerator];
while (object = [objectEnumerator nextObject])
while ((object = [objectEnumerator nextObject]) !== nil)
_add(_proxyObject, _addSEL, object);
}
else
@@ -273,7 +276,8 @@
{
var object,
objectEnumerator = [aSet objectEnumerator];
while (object = [objectEnumerator nextObject])
while ((object = [objectEnumerator nextObject]) !== nil)
_remove(_proxyObject, _removeSEL, object);
}
else
@@ -295,7 +299,8 @@
{
var object,
objectEnumerator = [objects objectEnumerator];
while (object = [objectEnumerator nextObject])
while ((object = [objectEnumerator nextObject]) !== nil)
_remove(_proxyObject, _removeSEL, object);
}
else
@@ -317,7 +322,8 @@
{
var object,
objectEnumerator = [[[self _representedObject] copy] objectEnumerator];
while (object = [objectEnumerator nextObject])
while ((object = [objectEnumerator nextObject]) !== nil)
_remove(_proxyObject, _removeSEL, object);
}
else
@@ -381,7 +387,10 @@
- (id)valueForKeyPath:(CPString)aKeyPath
{
if (aKeyPath.indexOf("@") === 0)
if (!aKeyPath)
[self valueForUndefinedKey:@"<empty path>"];
if (aKeyPath.charAt(0) === "@")
{
var dotIndex = aKeyPath.indexOf("."),
operator,
@@ -395,10 +404,7 @@
else
operator = aKeyPath.substring(1);
if (kvoOperators[operator])
return kvoOperators[operator](self, _cmd, parameter);
return nil;
return [_CPCollectionKVCOperator performOperation:operator withCollection:self propertyPath:parameter];
}
else
{
@@ -406,12 +412,17 @@
containedObject,
containedObjectValue,
containedObjectEnumerator = [self objectEnumerator];
while (containedObject = [containedObjectEnumerator nextObject])
while ((containedObject = [containedObjectEnumerator nextObject]) !== nil)
{
containedObjectValue = [containedObject valueForKeyPath:aKeyPath];
if (containedObjectValue)
[valuesForKeySet addObject:containedObjectValue];
if (containedObjectValue === nil || containedObjectValue === undefined)
containedObjectValue = [CPNull null];
[valuesForKeySet addObject:containedObjectValue];
}
return valuesForKeySet;
}
}
@@ -420,108 +431,9 @@
{
var containedObject,
containedObjectEnumerator = [self objectEnumerator];
while (containedObject = [containedObjectEnumerator nextObject])
while ((containedObject = [containedObjectEnumerator nextObject]) !== nil)
[containedObject setValue:aValue forKey:aKey];
}
@end
var kvoOperators = [];
// FIXME: this is not DRY because the implementation in CPArray+KVO is merely the same!
// HACK: prevent these from becoming globals. workaround for obj-j "function foo(){}" behavior
var avgOperator,
maxOperator,
minOperator,
countOperator,
sumOperator;
kvoOperators["avg"] = function avgOperator(self, _cmd, param)
{
//CPSet returns a CPSet - to obtain an array call allObjects
var objects = [[self valueForKeyPath:param] allObjects],
length = [objects count],
index = length,
average = 0.0;
if (!length)
return 0;
while (index--)
average += [objects[index] doubleValue];
return average / length;
}
kvoOperators["max"] = function maxOperator(self, _cmd, param)
{
//CPSet returns a CPSet - to obtain an array call allObjects
var objects = [[self valueForKeyPath:param] allObjects],
index = [objects count] - 1,
max = [objects lastObject];
while (index--)
{
var item = objects[index];
if ([max compare:item] < 0)
max = item;
}
return max;
}
kvoOperators["min"] = function minOperator(self, _cmd, param)
{
//CPSet returns a CPSet - to obtain an array call allObjects
var objects = [[self valueForKeyPath:param] allObjects],
index = [objects count] - 1,
min = [objects lastObject];
while (index--)
{
var item = objects[index];
if ([min compare:item] > 0)
min = item;
}
return min;
}
kvoOperators["count"] = function countOperator(self, _cmd, param)
{
return [self count];
}
kvoOperators["sum"] = function sumOperator(self, _cmd, param)
{
//CPSet returns a CPSet - to obtain an array call allObjects
var objects = [[self valueForKeyPath:param] allObjects],
index = [objects count],
sum = 0.0;
while (index--)
sum += [objects[index] doubleValue];
return sum;
}
@implementation CPSet (CPKeyValueObserving)
- (void)addObserver:(id)observer forKeyPath:(CPString)aKeyPath options:(unsigned)options context:(id)context
{
if ([isa instanceMethodForSelector:_cmd] === [CPSet instanceMethodForSelector:_cmd])
[CPException raise:CPInvalidArgumentException reason:"Unsupported method on CPSet"];
else
[super addObserver:observer forKeyPath:aKeyPath options:options context:context];
}
- (void)removeObserver:(id)observer forKeyPath:(CPString)aKeyPath
{
if ([isa instanceMethodForSelector:_cmd] === [CPSet instanceMethodForSelector:_cmd])
[CPException raise:CPInvalidArgumentException reason:"Unsupported method on CPSet"];
else
[super removeObserver:observer forKeyPath:aKeyPath];
}
@end
+22 -9
View File
@@ -9,10 +9,9 @@
@import "CPSet.j"
@implementation CPMutableSet : CPSet
/*
/*!
Returns an initialized set with a given initial capacity.
@param aCapacity, only present for compatability
*/
@@ -21,7 +20,7 @@
return [self init];
}
/*
/*!
Creates and returns a set with a given initial capacity.
@param aCapacity, only present for compatability
*/
@@ -30,7 +29,10 @@
return [[self alloc] initWithCapacity:aCapacity];
}
- (void)filterUsingPredicate:(CPPredicate)aPredicate
/*!
Returns a set filtered using a given predicate.
@prarm aPredicate a CPPredicate object used to filter the objects in the set.
*/- (void)filterUsingPredicate:(CPPredicate)aPredicate
{
var object,
objectEnumerator = [self objectEnumerator];
@@ -40,11 +42,19 @@
[self removeObject:object];
}
/*!
Removes an object from the set.
@param anObject the object to remove from the set. If the object is not in the set, the method will not modify the set.
*/
- (void)removeObject:(id)anObject
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
/*!
Removes an array of objects from the set.
@param anArray an array of object to remove from the set.
*/
- (void)removeObjectsInArray:(CPArray)anArray
{
var index = 0,
@@ -54,6 +64,9 @@
[self removeObject:[anArray objectAtIndex:index]];
}
/*!
Removes all the objects from the set.
*/
- (void)removeAllObjects
{
var object,
@@ -63,7 +76,7 @@
[self removeObject:object];
}
/*
/*!
Adds to the receiver each object contained in a given array that is not already a member.
@param array An array of objects to add to the receiver.
*/
@@ -75,7 +88,7 @@
[self addObject:objects[count]];
}
/*
/*!
Adds to the receiver each object contained in another given set
@param set The set of objects to add to the receiver.
*/
@@ -88,7 +101,7 @@
[self addObject:object];
}
/*
/*!
Removes from the receiver each object contained in another given set that is present in the receiver.
@param set The set of objects to remove from the receiver.
*/
@@ -101,7 +114,7 @@
[self removeObject:object];
}
/*
/*!
Removes from the receiver each object that isn't a member of another given set.
@param set The set with which to perform the intersection.
*/
@@ -121,7 +134,7 @@
[self removeObject:objectsToRemove[count]];
}
/*
/*!
Empties the receiver, then adds to the receiver each object contained in another given set.
@param set The set whose members replace the receiver's content.
*/
Loaded 100 of 367 files, more files were not shown because too many files have changed in this diff. Show more