diff --git a/AppKit/AppKit.j b/AppKit/AppKit.j index 27f3a3001..bada5344d 100644 --- a/AppKit/AppKit.j +++ b/AppKit/AppKit.j @@ -55,6 +55,7 @@ @import "CPController.j" @import "CPCookie.j" @import "CPCursor.j" +@import "CPDatePicker.j" @import "CPDocument.j" @import "CPDocumentController.j" @import "CPEvent.j" diff --git a/AppKit/CPAccordionView.j b/AppKit/CPAccordionView.j index 3f28cfa3c..c3e4b4f52 100644 --- a/AppKit/CPAccordionView.j +++ b/AppKit/CPAccordionView.j @@ -106,7 +106,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection _itemViews = []; _expandedItemIndexes = [CPIndexSet indexSet]; - [self setItemHeaderPrototype:[[CPButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 100.0, 24.0)]]; + [self setItemHeaderPrototype:[[CPButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 24.0)]]; } return self; @@ -258,18 +258,18 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection - (void)setFrameSize:(CGSize)aSize { - var width = _CGRectGetWidth([self frame]); + var width = CGRectGetWidth([self frame]); [super setFrameSize:aSize]; - if (width !== _CGRectGetWidth([self frame])) + if (width !== CGRectGetWidth([self frame])) [self _invalidateItemsStartingAtIndex:0]; } - (void)layoutSubviews { if (_items.length <= 0) - return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)]; + return [self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), 0.0)]; if (_dirtyItemIndex === CPNotFound) return; @@ -278,7 +278,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection var index = _dirtyItemIndex, count = _itemViews.length, - width = _CGRectGetWidth([self bounds]), + width = CGRectGetWidth([self bounds]), y = index > 0 ? CGRectGetMaxY([_itemViews[index - 1] frame]) : 0.0; // Do this now (instead of after looping), so that if we are made dirty again in the middle we don't blow this value away. @@ -293,7 +293,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection y = CGRectGetMaxY([itemView frame]); } - [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), y)]; + [self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), y)]; } @end @@ -310,7 +310,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection - (id)initWithAccordionView:(CPAccordionView)anAccordionView { - self = [super initWithFrame:_CGRectMakeZero()]; + self = [super initWithFrame:CGRectMakeZero()]; if (self) { @@ -376,21 +376,21 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection - (void)setFrameY:(float)aY width:(float)aWidth { - var headerHeight = _CGRectGetHeight([_headerView frame]); + var headerHeight = CGRectGetHeight([_headerView frame]); // Size to fit or something? - [_headerView setFrameSize:_CGSizeMake(aWidth, headerHeight)]; - [_contentView setFrameOrigin:_CGPointMake(0.0, headerHeight)]; + [_headerView setFrameSize:CGSizeMake(aWidth, headerHeight)]; + [_contentView setFrameOrigin:CGPointMake(0.0, headerHeight)]; if ([self isCollapsed]) - [self setFrame:_CGRectMake(0.0, aY, aWidth, headerHeight)]; + [self setFrame:CGRectMake(0.0, aY, aWidth, headerHeight)]; else { - var contentHeight = _CGRectGetHeight([_contentView frame]); + var contentHeight = CGRectGetHeight([_contentView frame]); - [_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)]; - [self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)]; + [_contentView setFrameSize:CGSizeMake(aWidth, contentHeight)]; + [self setFrame:CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)]; } } diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j index 01132ecd4..946e01149 100644 --- a/AppKit/CPApplication.j +++ b/AppKit/CPApplication.j @@ -20,8 +20,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#import "../Foundation/CPRange.h" - @import @import "CPCompatibility.j" @@ -87,6 +85,7 @@ CPRunContinuesResponse = -1002; @implementation CPApplication : CPResponder { CPArray _eventListeners; + int _eventListenerInsertionIndex; CPEvent _currentEvent; CPWindow _lastMouseMoveWindow; @@ -144,6 +143,7 @@ CPRunContinuesResponse = -1002; if (self) { _eventListeners = []; + _eventListenerInsertionIndex = 0; _windows = [[CPNull null]]; } @@ -371,22 +371,32 @@ CPRunContinuesResponse = -1002; applicationVersion = [options objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"], copyright = [options objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"]; - var aboutPanelPath = [[CPBundle bundleForClass:[CPWindowController class]] pathForResource:@"AboutPanel.cib"], - aboutPanelController = [CPWindowController alloc], - aboutPanelController = [aboutPanelController initWithWindowCibPath:aboutPanelPath owner:aboutPanelController], - aboutPanel = [aboutPanelController window], - contentView = [aboutPanel contentView], - imageView = [contentView viewWithTag:1], - applicationLabel = [contentView viewWithTag:2], - versionLabel = [contentView viewWithTag:3], - copyrightLabel = [contentView viewWithTag:4], - standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"]; + var windowWidth = 275, + windowHeight = 223, + imgWidth = 100, + imgHeight = 100, + interField = 8, + aboutPanel = [[CPWindow alloc] initWithContentRect:CGRectMake(0, 0, windowWidth, windowHeight) styleMask:CPClosableWindowMask], + imageView = [[CPImageView alloc] initWithFrame:CGRectMake((windowWidth / 2) - (imgWidth / 2), interField, imgWidth, imgHeight)], + applicationLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 16, windowWidth - 34, 24)], + versionLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 48, windowWidth - 34, 16)], + copyrightLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 72, windowWidth - 34, 32)], + contentView = [aboutPanel contentView]; - // FIXME move this into the CIB eventually [applicationLabel setFont:[CPFont boldSystemFontOfSize:[CPFont systemFontSize] + 2]]; [applicationLabel setAlignment:CPCenterTextAlignment]; + [versionLabel setFont:[CPFont systemFontOfSize:[CPFont systemFontSize] - 1]]; [versionLabel setAlignment:CPCenterTextAlignment]; + [copyrightLabel setFont:[CPFont systemFontOfSize:[CPFont systemFontSize] - 1]]; [copyrightLabel setAlignment:CPCenterTextAlignment]; + [copyrightLabel setLineBreakMode:CPLineBreakByWordWrapping]; + + [contentView addSubview:imageView]; + [contentView addSubview:applicationLabel]; + [contentView addSubview:versionLabel]; + [contentView addSubview:copyrightLabel]; + + var standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"]; [imageView setImage:applicationIcon || [[CPImage alloc] initWithContentsOfFile:standardPath size:CGSizeMake(256, 256)]]; @@ -400,7 +410,7 @@ CPRunContinuesResponse = -1002; else [versionLabel setStringValue:@""]; - [copyrightLabel setStringValue:copyright || ""]; + [copyrightLabel setStringValue:copyright || @""]; [aboutPanel center]; _aboutPanel = aboutPanel; @@ -509,6 +519,8 @@ CPRunContinuesResponse = -1002; if (_eventListeners[count]._callback === _CPRunModalLoop) { _eventListeners.splice(count, 1); + if (count <= _eventListenerInsertionIndex) + _eventListenerInsertionIndex--; return; } @@ -625,26 +637,34 @@ CPRunContinuesResponse = -1002; _lastMouseMoveWindow = theWindow; } - if (_eventListeners.length) + /* + Event listeners are processed from back to front so that newer event listeners normally take + precedence. If during the execution of a callback a new event listener is added, it should + be inserted after the current callback but before any higher priority callbacks. This makes + repeating event listeners (those that reinsert themselves) stable relative to each other. + */ + for (var i = _eventListeners.length - 1; i >= 0; i--) { - var listener = _eventListeners[_eventListeners.length - 1]; + var listener = _eventListeners[i]; if (listener._mask & (1 << [anEvent type])) { - _eventListeners.pop(); + _eventListeners.splice(i, 1); + // In case the callback wants to add more listeners. + _eventListenerInsertionIndex = i; listener._callback(anEvent); - } - /* - FIXME: This does not match Cocoa documented behavior for the dequeue - flag. Cocoa says the event is dequeued only if it matches the mask. - Unfortunately event handling code in Cappuccino is depending - on an event being dequeued even if it does not match. - */ - if (listener._dequeue) - return; + if (listener._dequeue) + { + // Don't process the event normally and don't send it to any other listener. + _eventListenerInsertionIndex = _eventListeners.length; + return; + } + } } + _eventListenerInsertionIndex = _eventListeners.length; + if (theWindow) [theWindow sendEvent:anEvent]; } @@ -695,7 +715,7 @@ CPRunContinuesResponse = -1002; - (CPArray)windows { // Return all windows, but not the CPNull placeholder in _windows[0]. - return [_windows subarrayWithRange:_CPMakeRange(1, [_windows count] - 1)]; + return [_windows subarrayWithRange:CPMakeRange(1, [_windows count] - 1)]; } /*! @@ -923,6 +943,12 @@ CPRunContinuesResponse = -1002; /*! Fires a callback function when an event matching a given mask occurs. + + If multiple callbacks are set which match the same event, later callbacks + take priority over earlier callbacks, unless a new callback is set while + an existing callback is being processed in which case it's given the same + priority as the currently processing callback. + @param aCallback A js function to be fired. @prarm aMask An event mask for the next event. @param anExpiration The date for which this callback expires (not implemented). @@ -932,13 +958,18 @@ CPRunContinuesResponse = -1002; */ - (void)setCallback:(Function)aCallback forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue { - _eventListeners.push(_CPEventListenerMake(aMask, aCallback, shouldDequeue)); + _eventListeners.splice(_eventListenerInsertionIndex++, 0, _CPEventListenerMake(aMask, aCallback, shouldDequeue)); } /*! Assigns a target and action for the next event matching a given event mask. The callback method called will be passed the CPEvent when it fires. + If multiple callbacks are set which match the same event, later callbacks + take priority over earlier callbacks, unless a new callback is set while + an existing callback is being processed in which case it's given the same + priority as the currently processing callback. + @param aTarget The target object for the callback. @param aSelector The selector which should be called on the target object. @param aMask The mask for a given event which should trigger the callback. @@ -949,7 +980,7 @@ CPRunContinuesResponse = -1002; */ - (void)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue { - _eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }, shouldDequeue)); + _eventListeners.splice(_eventListenerInsertionIndex++, 0, _CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }, shouldDequeue)); } /*! @@ -967,10 +998,10 @@ CPRunContinuesResponse = -1002; @param aSheet the window to display as a sheet @param aWindow the window that will hold the sheet as a child @param aModalDelegate - @param aDidEndSelector - @param aContextInfo + @param didEndSelector + @param contextInfo */ -- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo +- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)didEndSelector contextInfo:(id)contextInfo { if ([aWindow isSheet]) { @@ -978,17 +1009,8 @@ CPRunContinuesResponse = -1002; return; } - [aSheet._windowView _enableSheet:YES]; - - // -dw- if a sheet is already visible, we skip this since it serves no purpose and causes - // orderOut: to be called on the sheet, which is not what we want. - if (![aWindow isVisible]) - { - [aWindow orderFront:self]; - [aSheet setPlatformWindow:[aWindow platformWindow]]; - } - - [aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo]; + [aSheet._windowView _enableSheet:YES inWindow:aWindow]; + [aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:didEndSelector contextInfo:contextInfo]; } /*! @@ -1013,7 +1035,7 @@ CPRunContinuesResponse = -1002; var aWindow = [_windows objectAtIndex:count], context = aWindow._sheetContext; - if (context != nil && context["sheet"] === sheet) + if (context && context["sheet"] === sheet) { context["returnCode"] = returnCode; [aWindow _endSheet]; diff --git a/AppKit/CPArrayController.j b/AppKit/CPArrayController.j index 4e3c3c04f..0b25334d9 100644 --- a/AppKit/CPArrayController.j +++ b/AppKit/CPArrayController.j @@ -65,51 +65,51 @@ + (CPSet)keyPathsForValuesAffectingContentArray { - return [CPSet setWithObjects:"content"]; + return [CPSet setWithObjects:@"content"]; } + (CPSet)keyPathsForValuesAffectingArrangedObjects { // Also depends on "filterPredicate" but we'll handle that manually. - return [CPSet setWithObjects:"content", "sortDescriptors"]; + return [CPSet setWithObjects:@"content", @"sortDescriptors"]; } + (CPSet)keyPathsForValuesAffectingSelection { - return [CPSet setWithObjects:"selectionIndexes"]; + return [CPSet setWithObjects:@"selectionIndexes"]; } + (CPSet)keyPathsForValuesAffectingSelectionIndex { - return [CPSet setWithObjects:"selectionIndexes"]; + return [CPSet setWithObjects:@"selectionIndexes"]; } + (CPSet)keyPathsForValuesAffectingSelectionIndexes { // When the arranged objects change, selection preservation may cause the indexes // to change. - return [CPSet setWithObjects:"arrangedObjects"]; + return [CPSet setWithObjects:@"arrangedObjects"]; } + (CPSet)keyPathsForValuesAffectingSelectedObjects { // Don't need to depend on arrangedObjects here because selectionIndexes already does. - return [CPSet setWithObjects:"selectionIndexes"]; + return [CPSet setWithObjects:@"selectionIndexes"]; } + (CPSet)keyPathsForValuesAffectingCanRemove { - return [CPSet setWithObjects:"selectionIndexes"]; + return [CPSet setWithObjects:@"selectionIndexes"]; } + (CPSet)keyPathsForValuesAffectingCanSelectNext { - return [CPSet setWithObjects:"selectionIndexes"]; + return [CPSet setWithObjects:@"selectionIndexes"]; } + (CPSet)keyPathsForValuesAffectingCanSelectPrevious { - return [CPSet setWithObjects:"selectionIndexes"]; + return [CPSet setWithObjects:@"selectionIndexes"]; } @@ -744,6 +744,7 @@ return; var willClearPredicate = NO; + if (_clearsFilterPredicateOnInsertion && _filterPredicate) { [self willChangeValueForKey:@"filterPredicate"]; @@ -792,10 +793,18 @@ // not appear in arrangedObjects and we do not have to update at all. */ - // This will also send notificaitons for arrangedObjects. + // TODO: Remove these lines when granular notifications are implemented + var proxy = [_CPKVOProxy proxyForObject:self]; + [proxy setAdding:YES]; + + // This will also send notifications for arrangedObjects. [self didChangeValueForKey:@"content"]; + if (willClearPredicate) [self didChangeValueForKey:@"filterPredicate"]; + + // TODO: Remove this line when granular notifications are implemented + [proxy setAdding:NO]; } /*! @@ -811,6 +820,7 @@ return; var willClearPredicate = NO; + if (_clearsFilterPredicateOnInsertion && _filterPredicate) { [self willChangeValueForKey:@"filterPredicate"]; @@ -848,9 +858,15 @@ if ([self avoidsEmptySelection] && [[self selectionIndexes] count] <= 0 && [_contentObject count] > 0) [self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:0]]; + var proxy = [_CPKVOProxy proxyForObject:self]; + [proxy setAdding:YES]; + [self didChangeValueForKey:@"content"]; + if (willClearPredicate) [self didChangeValueForKey:@"filterPredicate"]; + + [proxy setAdding:NO]; } /*! @@ -914,11 +930,10 @@ var newObject = [self automaticallyPreparesContent] ? [self newObject] : [self _defaultNewObject], lastSelectedIndex = [_selectionIndexes lastIndex]; - if (lastSelectedIndex) + if (lastSelectedIndex !== CPNotFound) [self insertObject:newObject atArrangedObjectIndex:lastSelectedIndex]; else [self addObject:newObject]; - } /*! diff --git a/AppKit/CPBezierPath.j b/AppKit/CPBezierPath.j index e6ab87e76..eb5899d65 100644 --- a/AppKit/CPBezierPath.j +++ b/AppKit/CPBezierPath.j @@ -48,6 +48,8 @@ var DefaultLineWidth = 1.0; { CGPath _path; float _lineWidth; + CPArray _lineDashes; + float _lineDashesPhase; } /*! @@ -205,6 +207,7 @@ var DefaultLineWidth = 1.0; CGContextBeginPath(ctx); CGContextAddPath(ctx, _path); CGContextSetLineWidth(ctx, [self lineWidth]); + CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes); CGContextStrokePath(ctx); } @@ -218,10 +221,50 @@ var DefaultLineWidth = 1.0; CGContextBeginPath(ctx); CGContextAddPath(ctx, _path); CGContextSetLineWidth(ctx, [self lineWidth]); + CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes); CGContextClosePath(ctx); CGContextFillPath(ctx); } +/*! + Cocoa compatibility. +*/ +- (void)getLineDash:(CPArrayRef)patternRef count:(NSInteger)count phase:(CGFloatRef)phaseRef +{ + return [self getLineDash:patternRef phase:phaseRef]; +} + +/*! + Retrieve the line dash pattern and phase and write them into the provided references. +*/ +- (void)getLineDash:(CPArrayRef)patternRef phase:(CGFloatRef)phaseRef +{ + if (patternRef) + @deref(patternRef) = [_lineDashes copy]; + if (phaseRef) + @deref(phaseRef) = _lineDashesPhase; +} + +/*! + Cocoa compatibility. +*/ +- (void)setLineDash:(CPArray)aPattern count:(NSInteger)count phase:(CGFloat)aPhase +{ + [self setLineDash:aPattern phase:aPhase]; +} + +/*! + Set stroke line dash pattern. + + @param aPattern an array of stroke-skip lengths such as [2, 2, 4, 4] + @param aPhase amount of shift for the starting position of the first stroke +*/ +- (void)setLineDash:(CPArray)aPattern phase:(CGFloat)aPhase +{ + _lineDashes = aPattern; + _lineDashesPhase = aPhase; +} + /*! Get the line width. */ diff --git a/AppKit/CPBox.j b/AppKit/CPBox.j index 9dc3742b2..0a9240d7b 100644 --- a/AppKit/CPBox.j +++ b/AppKit/CPBox.j @@ -444,9 +444,9 @@ CPBelowBottom = 6; case CPBoxSeparator: // NSBox does not include a horizontal flag for the separator type. We have to determine // the type of separator to draw by the width and height of the frame. - if (_CGRectGetWidth(bounds) === 5.0) + if (CGRectGetWidth(bounds) === 5.0) return [self _drawVerticalSeparatorInRect:bounds]; - else if (_CGRectGetHeight(bounds) === 5.0) + else if (CGRectGetHeight(bounds) === 5.0) return [self _drawHorizontalSeparatorInRect:bounds]; break; @@ -493,8 +493,8 @@ CPBelowBottom = 6; CGContextSetStrokeColor(context, [self borderColor]); CGContextSetLineWidth(context, 1.0); - CGContextMoveToPoint(context, _CGRectGetMinX(aRect), _CGRectGetMidY(aRect)); - CGContextAddLineToPoint(context, _CGRectGetWidth(aRect), _CGRectGetMidY(aRect)); + CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMidY(aRect)); + CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMidY(aRect)); CGContextStrokePath(context); } @@ -505,8 +505,8 @@ CPBelowBottom = 6; CGContextSetStrokeColor(context, [self borderColor]); CGContextSetLineWidth(context, 1.0); - CGContextMoveToPoint(context, _CGRectGetMidX(aRect), _CGRectGetMinY(aRect)); - CGContextAddLineToPoint(context, _CGRectGetMidX(aRect), _CGRectGetHeight(aRect)); + CGContextMoveToPoint(context, CGRectGetMidX(aRect), CGRectGetMinY(aRect)); + CGContextAddLineToPoint(context, CGRectGetMidX(aRect), CGRectGetHeight(aRect)); CGContextStrokePath(context); } diff --git a/AppKit/CPBrowser.j b/AppKit/CPBrowser.j index ac827d890..9557e1aca 100644 --- a/AppKit/CPBrowser.j +++ b/AppKit/CPBrowser.j @@ -179,6 +179,11 @@ var oldValue = _tableViews.length - 1, indexPlusOne = columnIndex + 1; // unloads all later columns. + if (columnIndex > 0) + [_tableViews[columnIndex - 1] setNeedsDisplay:YES]; + + [_tableViews[columnIndex] setNeedsDisplay:YES]; + [[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"] makeObjectsPerformSelector:@selector(removeFromSuperview)]; @@ -820,6 +825,14 @@ return _browser; } +/*! + @ignore +*/ +- (BOOL)_isFocused +{ + return ([super _isFocused] || [_browser tableViewInColumn:[_browser selectedColumn]] === self); +} + - (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes atPoint:(CGPoint)mouseDownPoint { return [_browser canDragRowsWithIndexes:rowIndexes inColumn:[_browser columnOfTableView:self] withEvent:[CPApp currentEvent]]; diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j index ca041056e..ac9b1b4bb 100644 --- a/AppKit/CPButton.j +++ b/AppKit/CPButton.j @@ -154,8 +154,8 @@ CPButtonImageOffset = 3.0; return @{ @"image": [CPNull null], @"image-offset": 0.0, - @"bezel-inset": _CGInsetMakeZero(), - @"content-inset": _CGInsetMakeZero(), + @"bezel-inset": CGInsetMakeZero(), + @"content-inset": CGInsetMakeZero(), @"bezel-color": [CPNull null], }; } @@ -596,7 +596,7 @@ CPButtonImageOffset = 3.0; { var contentInset = [self currentValueForThemeAttribute:@"content-inset"]; - return _CGRectInsetByInset(bounds, contentInset); + return CGRectInsetByInset(bounds, contentInset); } - (CGRect)bezelRectForBounds:(CGRect)bounds @@ -607,7 +607,7 @@ CPButtonImageOffset = 3.0; var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"]; - return _CGRectInsetByInset(bounds, bezelInset); + return CGRectInsetByInset(bounds, bezelInset); } - (CGSize)_minimumFrameSize @@ -667,14 +667,14 @@ CPButtonImageOffset = 3.0; { if (aName === "bezel-view") { - var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + var view = [[CPView alloc] initWithFrame:CGRectMakeZero()]; [view setHitTests:NO]; return view; } else - return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()]; + return [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()]; } - (void)layoutSubviews diff --git a/AppKit/CPClipView.j b/AppKit/CPClipView.j index 6d3518e73..a59f83f12 100644 --- a/AppKit/CPClipView.j +++ b/AppKit/CPClipView.j @@ -108,19 +108,19 @@ - (CGPoint)constrainScrollPoint:(CGPoint)aPoint { if (!_documentView) - return _CGPointMakeZero(); + return CGPointMakeZero(); var documentFrame = [_documentView frame]; - aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(_bounds), 0.0))); - aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(_CGRectGetHeight(documentFrame) - _CGRectGetHeight(_bounds), 0.0))); + aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(CGRectGetWidth(documentFrame) - CGRectGetWidth(_bounds), 0.0))); + aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(CGRectGetHeight(documentFrame) - CGRectGetHeight(_bounds), 0.0))); return aPoint; } - (void)setBoundsOrigin:(CGPoint)aPoint { - if (_CGPointEqualToPoint(_bounds.origin, aPoint)) + if (CGPointEqualToPoint(_bounds.origin, aPoint)) return; [super setBoundsOrigin:aPoint]; diff --git a/AppKit/CPCollectionView.j b/AppKit/CPCollectionView.j index caa414c96..4bbbeeeba 100644 --- a/AppKit/CPCollectionView.j +++ b/AppKit/CPCollectionView.j @@ -20,9 +20,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#import "../Foundation/CPRange.h" -#import "../Foundation/Ref.h" - @import @import @import @@ -35,9 +32,6 @@ @import "CPPasteboard.j" @import "CPView.j" -@class CPClipView - - /*! @ingroup appkit @class CPCollectionView @@ -131,8 +125,8 @@ var HORIZONTAL_MARGIN = 2; _maxNumberOfRows = 0; _maxNumberOfColumns = 0; - _minItemSize = _CGSizeMakeZero(); - _maxItemSize = _CGSizeMakeZero(); + _minItemSize = CGSizeMakeZero(); + _maxItemSize = CGSizeMakeZero(); [self setBackgroundColors:nil]; @@ -156,11 +150,11 @@ var HORIZONTAL_MARGIN = 2; _numberOfColumns = CPNotFound; _numberOfRows = CPNotFound; - _itemSize = _CGSizeMakeZero(); + _itemSize = CGSizeMakeZero(); _selectionIndexes = [CPIndexSet indexSet]; - _storedFrameSize = _CGSizeMakeZero(); + _storedFrameSize = CGSizeMakeZero(); _needsMinMaxItemSizeUpdate = YES; _uniformSubviewsResizing = NO; @@ -176,50 +170,47 @@ var HORIZONTAL_MARGIN = 2; /*! Sets the item prototype to \c anItem + @param anItem the new item prototype. - The item prototype should implement the CPCoding protocol - because the item is copied by archiving and unarchiving the - prototypal view. + @note + - If anItem is located in an external cib file, representedObject, outlets, and bindings will be automatically restored when an item is created. + - If anItem and its view belong to the same cib as the collection view, the item prototype should implement the CPCoding protocol because the item is copied by archiving and unarchiving the prototypal view. + @note + Bindings won't be restored through archiving, instead you need to subclass the -representedObject: method and update the view there. - Example: + @par Example: -
-      @implement MyCustomView : CPCollectionViewItem
-      {
-          CPArray   items   @accessors;
-      }
+@code
+@implementation MyCustomPrototypeItem: CPCollectionViewItem
+{
+    @outlet CPTextField textField;
+}
 
-      - (id)initWithFrame:(CGRect)aFrame
-      {
-        self = [super initWithFrame:aFrame];
-        if (self)
-        {
-          items = [];
-        }
-        return self;
-      }
+- (id)initWithCoder:(CPCoder)aCoder
+{
+    self = [super initWithCoder:aCoder];
 
-      - (id)initWithCoder:(CPCoder)aCoder
-      {
-        self = [super initWithCoder:aCoder];
-        items = [aCoder decodeObjectForKey:@"KEY"];
-        return self;
-      }
+    textField = [aCoder decodeObjectForKey:@"TextField"];
 
-      - (void)encodeWithCoder:(CPCoder)aCoder
-      {
-        [aCoder encodeObject:items forKey:@"KEY"];
-        [super encodeWithCoder:aCoder];
-      }
+    return self;
+}
 
-      @end
-    
+- (void)encodeWithCoder:(CPCoder)aCoder +{ + [super encodeWithCoder:aCoder]; + [aCoder encodeConditionalObject:textField forKey:@"TextField"]; +} - This will allow the collection view to create multiple 'clean' copies - of the item prototype which will maintain the original values for item - and all of the properties archived by the super class. +- (void)setRepresentedObject:(id)anObject +{ + [super setRepresentedObject:anObject]; + [textField setStringValue:[anObject objectForKey:@"value"]]; + [[self view] setColor:[anObject objectForKey:@"color"]]; +} + +@end +@endcode - @param anItem the new item prototype */ - (void)setItemPrototype:(CPCollectionViewItem)anItem { @@ -501,7 +492,7 @@ var HORIZONTAL_MARGIN = 2; [self _updateMinMaxItemSizeIfNeeded]; - [self _computeGridWithSize:frameSize count:AT_REF(count)]; + [self _computeGridWithSize:frameSize count:@ref(count)]; //CPLog.debug("frameSize="+CPStringFromSize(frameSize) + "itemSize="+CPStringFromSize(itemSize) + " ncols=" + colsRowsCount[0] +" nrows="+ colsRowsCount[1]+" displayCount="+ colsRowsCount[2]); @@ -511,7 +502,7 @@ var HORIZONTAL_MARGIN = 2; if (!lazyFlag || _numberOfColumns !== oldNumberOfColumns || _numberOfRows !== oldNumberOfRows || - !_CGSizeEqualToSize(_itemSize, oldItemSize)) + !CGSizeEqualToSize(_itemSize, oldItemSize)) [self displayItems:_items frameSize:_storedFrameSize itemSize:_itemSize columns:_numberOfColumns rows:_numberOfRows count:count]; } @@ -520,7 +511,7 @@ var HORIZONTAL_MARGIN = 2; { var width = aSuperviewSize.width, height = aSuperviewSize.height, - itemSize = _CGSizeMakeCopy(_minItemSize), + itemSize = CGSizeMakeCopy(_minItemSize), maxItemSizeWidth = _maxItemSize.width, maxItemSizeHeight = _maxItemSize.height, itemsCount = [_items count], @@ -559,8 +550,8 @@ var HORIZONTAL_MARGIN = 2; if (maxItemSizeHeight > 0) itemSizeHeight = MIN(itemSizeHeight, maxItemSizeHeight); - _itemSize = _CGSizeMake(MAX(_minItemSize.width, itemSize.width), MAX(_minItemSize.height, itemSizeHeight)); - _storedFrameSize = _CGSizeMake(MAX(width, _minItemSize.width), height); + _itemSize = CGSizeMake(MAX(_minItemSize.width, itemSize.width), MAX(_minItemSize.height, itemSizeHeight)); + _storedFrameSize = CGSizeMake(MAX(width, _minItemSize.width), height); _numberOfColumns = numberOfColumns; _numberOfRows = numberOfRows; countRef(MIN(itemsCount, numberOfColumns * numberOfRows)); @@ -581,7 +572,7 @@ var HORIZONTAL_MARGIN = 2; if (idx >= displayCount) { - [view setFrameOrigin:_CGPointMake(-anItemSize.width, -anItemSize.height)]; + [view setFrameOrigin:CGPointMake(-anItemSize.width, -anItemSize.height)]; return; } @@ -591,7 +582,7 @@ var HORIZONTAL_MARGIN = 2; y += _verticalMargin + anItemSize.height; } - [view setFrameOrigin:_CGPointMake(x, y)]; + [view setFrameOrigin:CGPointMake(x, y)]; [view setFrameSize:anItemSize]; x += anItemSize.width + _horizontalMargin; @@ -694,12 +685,12 @@ var HORIZONTAL_MARGIN = 2; if (aSize === nil || aSize === undefined) [CPException raise:CPInvalidArgumentException reason:"Invalid value provided for minimum size"]; - if (_CGSizeEqualToSize(_minItemSize, aSize)) + if (CGSizeEqualToSize(_minItemSize, aSize)) return; - _minItemSize = _CGSizeMakeCopy(aSize); + _minItemSize = CGSizeMakeCopy(aSize); - if (_CGSizeEqualToSize(_minItemSize, _CGSizeMakeZero())) + if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero())) _needsMinMaxItemSizeUpdate = YES; [self tile]; @@ -719,10 +710,10 @@ var HORIZONTAL_MARGIN = 2; */ - (void)setMaxItemSize:(CGSize)aSize { - if (_CGSizeEqualToSize(_maxItemSize, aSize)) + if (CGSizeEqualToSize(_maxItemSize, aSize)) return; - _maxItemSize = _CGSizeMakeCopy(aSize); + _maxItemSize = CGSizeMakeCopy(aSize); // if (_maxItemSize.width == 0 || _maxItemSize.height == 0) // _needsMinMaxItemSizeUpdate = YES; @@ -794,9 +785,9 @@ var HORIZONTAL_MARGIN = 2; newSelectedRange = nil; if (index < firstSelectedIndex) - newSelectedRange = _CPMakeRange(index, (firstSelectedIndex - index) + 1); + newSelectedRange = CPMakeRange(index, (firstSelectedIndex - index) + 1); else - newSelectedRange = _CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1); + newSelectedRange = CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1); indexes = [[self selectionIndexes] copy]; [indexes addIndexesInRange:newSelectedRange]; @@ -945,9 +936,9 @@ var HORIZONTAL_MARGIN = 2; // Create and position the drop indicator view. if (!_dropView) - _dropView = [[_CPCollectionViewDropIndicator alloc] initWithFrame:_CGRectMake(-8, -8, 0, 0)]; + _dropView = [[_CPCollectionViewDropIndicator alloc] initWithFrame:CGRectMake(-8, -8, 0, 0)]; - [_dropView setFrameSize:_CGSizeMake(10, _itemSize.height + _verticalMargin)]; + [_dropView setFrameSize:CGSizeMake(10, _itemSize.height + _verticalMargin)]; [self addSubview:_dropView]; } @@ -983,14 +974,14 @@ var HORIZONTAL_MARGIN = 2; [[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self]; - var dragImageOffset = _CGSizeMakeZero(), + var dragImageOffset = CGSizeMakeZero(), view = [self _draggingViewForItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent offset:dragImageOffset]; [view setFrameSize:_itemSize]; [view setAlphaValue:0.7]; var dragLocation = [self convertPoint:locationInWindow fromView:nil], - dragPoint = _CGPointMake(dragLocation.x - _itemSize.width / 2 , dragLocation.y - _itemSize.height / 2); + dragPoint = CGPointMake(dragLocation.x - _itemSize.width / 2 , dragLocation.y - _itemSize.height / 2); [self dragView:view at:dragPoint @@ -1032,7 +1023,7 @@ var HORIZONTAL_MARGIN = 2; - (CPDragOperation)draggingEntered:(id)draggingInfo { var dropIndex = -1, - dropIndexRef = AT_REF(dropIndex), + dropIndexRef = @ref(dropIndex), dragOp = [self _validateDragWithInfo:draggingInfo dropIndex:dropIndexRef dropOperation:1]; dropIndex = dropIndexRef(); @@ -1050,7 +1041,7 @@ var HORIZONTAL_MARGIN = 2; return _currentDragOperation; var dropIndex, - dropIndexRef = AT_REF(dropIndex); + dropIndexRef = @ref(dropIndex); var dragOperation = [self _validateDragWithInfo:draggingInfo dropIndex:dropIndexRef dropOperation:1]; @@ -1068,7 +1059,7 @@ var HORIZONTAL_MARGIN = 2; if ([_delegate respondsToSelector:@selector(collectionView:validateDrop:proposedIndex:dropOperation:)]) { - var dropIndexRef2 = AT_REF(dropIndex); + var dropIndexRef2 = @ref(dropIndex); result = [_delegate collectionView:self validateDrop:draggingInfo proposedIndex:dropIndexRef2 dropOperation:dropOperation]; @@ -1122,12 +1113,12 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype: _currentDragOperation = dragOperation; var frameOrigin, - dropviewFrameWidth = _CGRectGetWidth([_dropView frame]); + dropviewFrameWidth = CGRectGetWidth([_dropView frame]); if (_currentDropIndex == -1 || _currentDragOperation == CPDragOperationNone) - frameOrigin = _CGPointMake(-dropviewFrameWidth, 0); + frameOrigin = CGPointMake(-dropviewFrameWidth, 0); else if (_currentDropIndex == 0) - frameOrigin = _CGPointMake(0, 0); + frameOrigin = CGPointMake(0, 0); else { var offset; @@ -1144,7 +1135,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype: var rect = [self frameForItemAtIndex:dropIndex]; - frameOrigin = _CGPointMake(_CGRectGetMaxX(rect) + offset, rect.origin.y - _verticalMargin); + frameOrigin = CGPointMake(CGRectGetMaxX(rect) + offset, rect.origin.y - _verticalMargin); } [_dropView setFrameOrigin:frameOrigin]; @@ -1191,8 +1182,8 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype: - (void)drawRect:(CGRect)aRect { var context = [[CPGraphicsContext currentContext] graphicsPort], - width = _CGRectGetWidth(aRect), - circleRect = _CGRectMake(1, 1, width - 2, width - 2); + width = CGRectGetWidth(aRect), + circleRect = CGRectMake(1, 1, width - 2, width - 2); CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); CGContextSetFillColor(context, [CPColor whiteColor]); @@ -1206,8 +1197,8 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype: //then draw the line CGContextBeginPath(context); - CGContextMoveToPoint(context, FLOOR(width / 2), _CGRectGetMinY(aRect) + width); - CGContextAddLineToPoint(context, FLOOR(width / 2), _CGRectGetHeight(aRect)); + CGContextMoveToPoint(context, FLOOR(width / 2), CGRectGetMinY(aRect) + width); + CGContextAddLineToPoint(context, FLOOR(width / 2), CGRectGetHeight(aRect)); CGContextStrokePath(context); } @@ -1217,7 +1208,12 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype: - (void)_modifySelectionWithNewIndex:(int)anIndex direction:(int)aDirection expand:(BOOL)shouldExpand { - anIndex = MIN(MAX(anIndex, 0), [[self items] count] - 1); + var count = [[self items] count]; + + if (count === 0) + return; + + anIndex = MIN(MAX(anIndex, 0), count - 1); if (_allowsMultipleSelection && shouldExpand) { @@ -1227,9 +1223,9 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype: // if the direction is backward (-1) check with the bottom anchor if (aDirection === -1) - [indexes addIndexesInRange:_CPMakeRange(anIndex, bottomAnchor - anIndex + 1)]; + [indexes addIndexesInRange:CPMakeRange(anIndex, bottomAnchor - anIndex + 1)]; else - [indexes addIndexesInRange:_CPMakeRange(topAnchor, anIndex - topAnchor + 1)]; + [indexes addIndexesInRange:CPMakeRange(topAnchor, anIndex - topAnchor + 1)]; } else indexes = [CPIndexSet indexSetWithIndex:anIndex]; @@ -1242,7 +1238,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype: { var frame = [self frameForItemsAtIndexes:[self selectionIndexes]]; - if (!_CGRectIsNull(frame)) + if (!CGRectIsEmpty(frame)) [self scrollRectToVisible:frame]; } @@ -1390,10 +1386,10 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK { [super encodeWithCoder:aCoder]; - if (!_CGSizeEqualToSize(_minItemSize, _CGSizeMakeZero())) + if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero())) [aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey]; - if (!_CGSizeEqualToSize(_maxItemSize, _CGSizeMakeZero())) + if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero())) [aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey]; [aCoder encodeInt:_maxNumberOfRows forKey:CPCollectionViewMaxNumberOfRowsKey]; diff --git a/AppKit/CPColorPicker.j b/AppKit/CPColorPicker.j index 39451d0cf..7a1d43961 100644 --- a/AppKit/CPColorPicker.j +++ b/AppKit/CPColorPicker.j @@ -115,12 +115,12 @@ - (id)initView { - var aFrame = _CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight); + var aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight); _pickerView = [[CPView alloc] initWithFrame:aFrame]; [_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; - _brightnessSlider = [[CPSlider alloc] initWithFrame:_CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)]; + _brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)]; [_brightnessSlider setValue:15.0 forThemeAttribute:@"track-width"]; [_brightnessSlider setValue:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPColorPicker class]] pathForResource:@"brightness_bar.png"]]] forThemeAttribute:@"track-color"]; @@ -133,7 +133,7 @@ [_brightnessSlider setAction:@selector(brightnessSliderDidChange:)]; [_brightnessSlider setAutoresizingMask:CPViewWidthSizable | CPViewMinYMargin]; - _hueSaturationView = [[__CPColorWheel alloc] initWithFrame:_CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)]; + _hueSaturationView = [[__CPColorWheel alloc] initWithFrame:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)]; [_hueSaturationView setDelegate:self]; [_hueSaturationView setAutoresizingMask:(CPViewWidthSizable | CPViewHeightSizable)]; diff --git a/AppKit/CPColorWell.j b/AppKit/CPColorWell.j index 274f9c04e..8ebe88ce9 100644 --- a/AppKit/CPColorWell.j +++ b/AppKit/CPColorWell.j @@ -61,10 +61,10 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv + (id)themeAttributes { return @{ - @"bezel-inset": _CGInsetMakeZero(), + @"bezel-inset": CGInsetMakeZero(), @"bezel-color": [CPNull null], - @"content-inset": _CGInsetMake(3.0, 3.0, 3.0, 3.0), - @"content-border-inset": _CGInsetMakeZero(), + @"content-inset": CGInsetMake(3.0, 3.0, 3.0, 3.0), + @"content-border-inset": CGInsetMakeZero(), @"content-border-color": [CPNull null], }; } @@ -249,21 +249,21 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv { var contentInset = [self currentValueForThemeAttribute:@"content-inset"]; - return _CGRectInsetByInset(bounds, contentInset); + return CGRectInsetByInset(bounds, contentInset); } - (CGRect)bezelRectForBounds:(CGRect)bounds { var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"]; - return _CGRectInsetByInset(bounds, bezelInset); + return CGRectInsetByInset(bounds, bezelInset); } - (CGRect)contentBorderRectForBounds:(CGRect)bounds { var contentBorderInset = [self currentValueForThemeAttribute:@"content-border-inset"]; - return _CGRectInsetByInset(bounds, contentBorderInset); + return CGRectInsetByInset(bounds, contentBorderInset); } - (CGRect)rectForEphemeralSubviewNamed:(CPString)aName @@ -283,7 +283,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv - (CPView)createEphemeralSubviewNamed:(CPString)aName { - var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + var view = [[CPView alloc] initWithFrame:CGRectMakeZero()]; [view setHitTests:NO]; diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index 73e3097e5..0651d53ee 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -61,8 +61,8 @@ var CPComboBoxTextSubview = @"text", + (id)themeAttributes { return @{ - @"popup-button-size": _CGSizeMake(21.0, 29.0), - @"border-inset": _CGInsetMake(3.0, 3.0, 3.0, 3.0), + @"popup-button-size": CGSizeMake(21.0, 29.0), + @"border-inset": CGInsetMake(3.0, 3.0, 3.0, 3.0), }; } @@ -854,7 +854,7 @@ var CPComboBoxTextSubview = @"text", { if (aName === "popup-button-view") { - var view = [[_CPComboBoxPopUpButton alloc] initWithFrame:_CGRectMakeZero() comboBox:self]; + var view = [[_CPComboBoxPopUpButton alloc] initWithFrame:CGRectMakeZero() comboBox:self]; return view; } diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index f1cd1a53b..fb11b6ebc 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -20,8 +20,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#import "../Foundation/Ref.h" - @import @import @@ -119,11 +117,11 @@ var CPControlBlackColor = [CPColor blackColor]; @"text-color": [CPColor blackColor], @"font": [CPFont systemFontOfSize:CPFontCurrentSystemSize], @"text-shadow-color": [CPNull null], - @"text-shadow-offset": _CGSizeMakeZero(), + @"text-shadow-offset": CGSizeMakeZero(), @"image-position": CPImageLeft, @"image-scaling": CPScaleToFit, - @"min-size": _CGSizeMakeZero(), - @"max-size": _CGSizeMake(-1.0, -1.0), + @"min-size": CGSizeMakeZero(), + @"max-size": CGSizeMake(-1.0, -1.0), }; } @@ -553,10 +551,10 @@ var CPControlBlackColor = [CPColor blackColor]; { value = nil; - if ([_formatter getObjectValue:AT_REF(value) forString:aString errorDescription:nil] === NO) + if ([_formatter getObjectValue:@ref(value) forString:aString errorDescription:nil] === NO) { // If the given string is non-empty and doesn't work, Cocoa tries an empty string. - if (!aString || [_formatter getObjectValue:AT_REF(value) forString:@"" errorDescription:nil] === NO) + if (!aString || [_formatter getObjectValue:@ref(value) forString:@"" errorDescription:nil] === NO) value = undefined; // Means the value is invalid } } diff --git a/AppKit/CPDatePicker/CPDatePicker.j b/AppKit/CPDatePicker/CPDatePicker.j new file mode 100644 index 000000000..af7b9938c --- /dev/null +++ b/AppKit/CPDatePicker/CPDatePicker.j @@ -0,0 +1,686 @@ +/* CPDatePicker.j +* AppKit +* +* Created by Alexandre Wilhelm +* Copyright 2012 +* +* 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 "CPControl.j" +@import "CPFont.j" +@import "CPTextField.j" +@import "_CPDatePickerTextField.j" +@import "_CPDatePickerCalendar.j" + +@import +@import +@import +@import +@import + +@class CPStepper +@class CPApp + +@global CPLocaleLanguageCode +@global CPDateFormatterShortStyle + +var CPDatePicker_validateProposedDateValue_timeInterval = 1 << 1; + +CPSingleDateMode = 0; +CPRangeDateMode = 1; + +CPTextFieldAndStepperDatePickerStyle = 0; +CPClockAndCalendarDatePickerStyle = 1; +CPTextFieldDatePickerStyle = 2; + +CPHourMinuteDatePickerElementFlag = 0x000c; +CPHourMinuteSecondDatePickerElementFlag = 0x000e; +CPTimeZoneDatePickerElementFlag = 0x0010; +CPYearMonthDatePickerElementFlag = 0x00c0; +CPYearMonthDayDatePickerElementFlag = 0x00e0; +CPEraDatePickerElementFlag = 0x0100; + +/*! + @ingroup appkit + This control displays a datepicker in a Cappuccino application +*/ +@implementation CPDatePicker : CPControl +{ + BOOL _isBordered @accessors(getter=isBordered, setter=setBordered:); + BOOL _isBezeled @accessors(getter=isBezeled, setter=setBezeled:); + BOOL _drawsBackground @accessors(property=drawsBackground); + CPDate _dateValue @accessors(property=dateValue); + CPDate _minDate @accessors(property=minDate); + CPDate _maxDate @accessors(property=maxDate); + CPFont _textFont @accessors(property=textFont); + CPLocale _locale @accessors(property=locale); + //CPCalendar _calendar @accessors(property=calendar); + //CPTimeZone _timeZone @accessors(property=timeZone); + CPDateFormatter _formatter @accessors(property=formatter); + id _delegate @accessors(property=delegate); + unsigned _datePickerElements @accessors(property=datePickerElements); + CPInteger _datePickerMode @accessors(property=datePickerMode); + CPInteger _datePickerStyle @accessors(property=datePickerStyle); + CPInteger _timeInterval @accessors(property=timeInterval); + + _CPDatePickerTextField _datePickerTextfield; + _CPDatePickerCalendar _datePickerCalendar; + unsigned _implementedCDatePickerDelegateMethods; +} + + +#pragma mark - +#pragma mark Theme methods + ++ (CPString)defaultThemeClass +{ + return @"datePicker"; +} + ++ (id)themeAttributes +{ + return @{ + @"bezel-color": [CPColor clearColor], + @"border-width" : 1.0, + @"border-color": [CPColor clearColor], + @"content-inset": CGInsetMakeZero(), + @"bezel-inset": CGInsetMakeZero(), + @"datepicker-textfield-bezel-color": [CPColor clearColor], + @"min-size-datepicker-textfield": CGSizeMakeZero(), + @"content-inset-datepicker-textfield": CGInsetMakeZero(), + @"content-inset-datepicker-textfield-separator": CGInsetMakeZero(), + @"separator-content-inset": CGInsetMakeZero(), + @"date-hour-margin": 5.0, + @"stepper-margin": 5.0, + @"bezel-color-calendar": [CPColor clearColor], + @"title-text-color": [CPColor blackColor], + @"title-text-shadow-color": [CPColor clearColor], + @"title-text-shadow-offset": CGSizeMakeZero(), + @"title-font": [CPNull null], + @"weekday-text-color": [CPColor blackColor], + @"weekday-text-shadow-color": [CPColor clearColor], + @"weekday-text-shadow-offset": CGSizeMakeZero(), + @"weekday-font": [CPNull null], + @"arrow-image-left": [CPNull null], + @"arrow-image-right": [CPNull null], + @"arrow-image-left-highlighted": [CPNull null], + @"arrow-image-right-highlighted": [CPNull null], + @"arrow-inset": CGInsetMakeZero(), + @"circle-image": [CPNull null], + @"circle-image-highlighted": [CPNull null], + @"tile-text-color": [CPColor blackColor], + @"tile-text-shadow-color": [CPColor clearColor], + @"tile-text-shadow-offset": CGSizeMakeZero(), + @"tile-font": [CPNull null], + @"size-tile": CGSizeMakeZero(), + @"size-calendar": CGSizeMakeZero(), + @"size-header": CGSizeMakeZero(), + @"min-size-calendar": CGSizeMakeZero(), + @"max-size-calendar": CGSizeMakeZero(), + @"bezel-color-clock": [CPColor clearColor], + @"clock-text-color": [CPColor blackColor], + @"clock-text-shadow-color": [CPColor clearColor], + @"clock-text-shadow-offset": CGSizeMakeZero(), + @"clock-font": [CPNull null], + @"second-hand-color": [CPColor clearColor], + @"hour-hand-color": [CPColor clearColor], + @"middle-hand-color": [CPColor clearColor], + @"minute-hand-color": [CPColor clearColor], + @"size-clock": CGSizeMakeZero(), + @"second-hand-size": CGSizeMakeZero(), + @"hour-hand-size": CGSizeMakeZero(), + @"middle-hand-size": CGSizeMakeZero(), + @"minute-hand-size": CGSizeMakeZero(), + }; +} + + +#pragma mark - +#pragma mark Binding methods + ++ (Class)_binderClassForBinding:(CPString)theBinding +{ + if (theBinding == CPValueBinding || theBinding == CPMinValueBinding || theBinding == CPMaxValueBinding) + return [_CPDatePickerValueBinder class]; + + return [super _binderClassForBinding:theBinding]; +} + +- (id)_replacementKeyPathForBinding:(CPString)aBinding +{ + if (aBinding == CPValueBinding) + return @"dateValue"; + + if (aBinding == CPMinValueBinding) + return @"minDate"; + + if (aBinding == CPMaxValueBinding) + return @"maxDate"; + + return [super _replacementKeyPathForBinding:aBinding]; +} + + +#pragma mark - +#pragma mark Init methods + +- (id)initWithFrame:(CGRect)aFrame +{ + if (self = [super initWithFrame:aFrame]) + { + _drawsBackground = YES; + _datePickerStyle = CPTextFieldAndStepperDatePickerStyle; + _datePickerMode = CPSingleDateMode; + _datePickerElements = CPYearMonthDayDatePickerElementFlag | CPHourMinuteSecondDatePickerElementFlag; + _timeInterval = 0; + _implementedCDatePickerDelegateMethods = 0; + _formatter = [[CPDateFormatter alloc] init]; + + [self setObjectValue:[CPDate date]]; + _minDate = [CPDate distantPast]; + _maxDate = [CPDate distantFuture]; + + [self setBezeled:YES]; + [self setBordered:YES]; + + [self _init]; + } + + return self +} + +- (void)_init +{ + if (!_locale) + _locale = [CPLocale currentLocale]; + + _datePickerTextfield = [[_CPDatePickerTextField alloc] initWithFrame:[self bounds] withDatePicker:self]; + + [_datePickerTextfield setDateValue:_dateValue]; + [self addSubview:_datePickerTextfield]; + + _datePickerCalendar = [[_CPDatePickerCalendar alloc] initWithFrame:[self bounds] withDatePicker:self]; + [_datePickerCalendar setDateValue:_dateValue]; + [_datePickerCalendar setHidden:YES]; + [self addSubview:_datePickerCalendar]; + + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; +} + + +#pragma mark - +#pragma mark Delegate methods + +/*! Set the delegate of the datePicker + @param aDelegate delegate of the datePicker +*/ +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; + _implementedCDatePickerDelegateMethods = 0; + + // Look if the delegate implements or not the delegate methods + if ([_delegate respondsToSelector:@selector(datePicker:validateProposedDateValue:timeInterval:)]) + _implementedCDatePickerDelegateMethods |= CPDatePicker_validateProposedDateValue_timeInterval; +} + + +#pragma mark - +#pragma mark Layout method + +/*! Layout the subviews +*/ +- (void)layoutSubviews +{ + [super layoutSubviews]; + + if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle) + { + [_datePickerTextfield setHidden:NO]; + [_datePickerCalendar setHidden:YES]; + [_datePickerTextfield setNeedsLayout]; + } + else + { + [_datePickerCalendar setHidden:NO]; + [_datePickerTextfield setHidden:YES]; + [_datePickerCalendar setNeedsLayout]; + } +} + +#pragma mark - +#pragma mark Setter + +/*! Return the objectValue of the datePicker. The objectValue is made with the current formatter of the datePicker +*/ +- (void)objectValue +{ + // try + // { + // return [_formatter stringFromDate:_dateValue]; + // } + // catch(e) + // { + return _dateValue + // } +} + +/*! Set the objectValue ofhe datePier. It has to be a CPDate + @param aDateValue the dateValue +*/ +- (void)setObjectValue:(CPDate)aValue +{ + [self setDateValue:aValue]; +} + +/* Set the dateValue of the datePicker + @param aDateValue the dateValue +*/ +- (void)setDateValue:(CPDate)aDateValue +{ + if (aDateValue == nil) + return; + + [self _setDateValue:aDateValue timeInterval:_timeInterval]; +} + +/*! Set the dateValue and the timeInterval. This method checks the min and max date of the datePicker also. It will call the delegate if possible. + @param aDateValue the dateValue + @param aTimeInterval the timeInterval +*/ +- (void)_setDateValue:(CPDate)aDateValue timeInterval:(CPTimeInterval)aTimeInterval +{ + if (_minDate) + aDateValue = new Date (MAX(aDateValue, _minDate)); + + if (_maxDate) + aDateValue = new Date (MIN(aDateValue, _maxDate)); + + aTimeInterval = MAX(MIN(aTimeInterval, [_maxDate timeIntervalSinceDate:aDateValue]), [_minDate timeIntervalSinceDate:aDateValue]); + + if ([aDateValue isEqualToDate:_dateValue] && aTimeInterval == _timeInterval) + return; + + if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval) + { + // constrain timeInterval also + var aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;} + var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;} + + [_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef]; + } + + [self willChangeValueForKey:@"objectValue"]; + [self willChangeValueForKey:@"dateValue"]; + _dateValue = aDateValue; + [super setObjectValue:_dateValue]; + [self didChangeValueForKey:@"dateValue"]; + [self didChangeValueForKey:@"objectValue"]; + + [self willChangeValueForKey:@"timeInterval"]; + _timeInterval = (_datePickerMode == CPSingleDateMode)? 0 : aTimeInterval; + [self didChangeValueForKey:@"timeInterval"]; + + [self sendAction:[self action] to:[self target]]; + + if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle) + [_datePickerTextfield setDateValue:_dateValue]; + else + [_datePickerCalendar setDateValue:_dateValue]; +} + +/*! Set the minDate of the datePicker + @param aMinDate the minDate +*/ +- (void)setMinDate:(CPDate)aMinDate +{ + [self willChangeValueForKey:@"minDate"]; + _minDate = aMinDate; + [self didChangeValueForKey:@"minDate"]; + + [self _setDateValue:_dateValue timeInterval:_timeInterval]; +} + +/*! Set the maxDate of the datePicker + @param aMaxDate the maxDate +*/ +- (void)setMaxDate:(CPDate)aMaxDate +{ + [self willChangeValueForKey:@"maxDate"]; + _maxDate = aMaxDate; + [self didChangeValueForKey:@"maxDate"]; + + [self _setDateValue:_dateValue timeInterval:_timeInterval]; +} + +/*! Set the syle of the datePicker + @param aDatePickerStyle the datePicker style +*/ +- (void)setDatePickerStyle:(CPDate)aDatePickerStyle +{ + _datePickerStyle = aDatePickerStyle; + + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; +} + +/*! Set the elements of the datePicker + @param aDatePickerElements the datePicker elements +*/ +- (void)setDatePickerElements:(CPDate)aDatePickerElements +{ + _datePickerElements = aDatePickerElements; + + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; +} + +/*! Set the mode of the datePicker + @param aDatePickerMode the datePicker mode +*/ +- (void)setDatePickerMode:(CPDate)aDatePickerMode +{ + _datePickerMode = aDatePickerMode; + + if (_datePickerMode == CPSingleDateMode) + [self _setDateValue:[self dateValue] timeInterval:0]; + + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; +} + +/*! Set the timeInterval of the datePicker + @param aTimeInterval the timeInterval of the datePicker +*/ +- (void)setTimeInterval:(CPInteger)aTimeInterval +{ + if (_datePickerMode == CPSingleDateMode) + return; + + [self _setDateValue:[self dateValue] timeInterval:aTimeInterval]; +} + +/*! Set the locale of the datePicker. This update laso the locale of the formatter. + @param aLocale the locale +*/ +- (void)setLocale:(CPLocale)aLocale +{ + _locale = aLocale; + + if (_formatter) + { + [self willChangeValueForKey:@"locale"]; + [_formatter setLocale:_locale]; + [self didChangeValueForKey:@"locale"]; + } + + // This will update the textFields (usefull when changing with a date with pm and am) + [_datePickerTextfield setDateValue:_dateValue]; + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; +} + +/*! + Sets whether the datepicker will have a bezeled border. + @param shouldBeBezeled \c YES means the datepicker will draw a bezeled border +*/ +- (void)setBezeled:(BOOL)shouldBeBezeled +{ + _isBezeled = shouldBeBezeled; + + if (shouldBeBezeled) + [self setThemeState:CPThemeStateBezeled]; + else + [self unsetThemeState:CPThemeStateBezeled]; +} + +/*! + Sets whether the datepicker will have a border drawn. (actually it does nothing) + @param shouldBeBordered \c YES makes the datepicker draw a border +*/ +- (void)setBordered:(BOOL)shouldBeBordered +{ + _isBordered = shouldBeBordered; + + if (shouldBeBordered) + [self setThemeState:CPThemeStateBordered]; + else + [self unsetThemeState:CPThemeStateBordered]; +} + +/*! + Sets the font of the control. + @param aFont +*/ +- (void)setTextFont:(CPFont)aFont +{ + [self setFont:aFont]; +} + +/*! Sets the enabled status of the control. Controls that are not enabled can not be used by the user and obtain the CPThemeStateDisabled theme state. + @param a boolean. YES if the control should be enabled, otherwise NO. +*/ +- (void)setEnabled:(BOOL)aBoolean +{ + [super setEnabled:aBoolean]; + + [_datePickerTextfield setEnabled:aBoolean]; + [_datePickerCalendar setEnabled:aBoolean]; +} + +/*! Set the background color of the datePicker + @param aColor +*/ +- (void)setBackgroundColor:(CPColor)aColor +{ + _backgroundColor = aColor; + [self setNeedsLayout]; +} + +/*! Set the boolean drawsBackgroundColor + @param aBoolean +*/ +- (void)setDrawsBackground:(BOOL)aBoolean +{ + [self willChangeValueForKey:@"drawsBackground"]; + _drawsBackground = aBoolean; + [self didChangeValueForKey:@"drawsBackground"]; + + [self setNeedsLayout]; +} + + +#pragma mark - +#pragma mark First responder methods + +/*! Return YES if style is set to CPTextFieldAndStepperDatePickerStyle or CPTextFieldDatePickerStyle +*/ +- (BOOL)becomeFirstResponder +{ + if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle) + [_datePickerTextfield _selecteTextFieldWithFlags:[[CPApp currentEvent] modifierFlags]]; + else + return NO; + + return YES; +} + +/*! Return YES +*/ +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +/*! Return YES +*/ +- (BOOL)resignFirstResponder +{ + if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle) + [_datePickerTextfield resignFirstResponder]; + + return YES; +} + + +#pragma mark - +#pragma mark getter + +/*! + Returns \c YES if the textfield is bezeled. +*/ +- (BOOL)isBezeled +{ + return [self hasThemeState:CPThemeStateBezeled]; +} + +/*! + Returns \c YES if the textfield has a border. +*/ +- (BOOL)isBordered +{ + return [self hasThemeState:CPThemeStateBordered]; +} + +/*! + Returns the font of the control. +*/ +- (CPFont)textFont +{ + return [self font]; +} + +/*! Check if we are in the american format or not. Depending on the locale +*/ +- (BOOL)_isAmericanFormat +{ + return [[_locale objectForKey:CPLocaleCountryCode] isEqualToString:@"US"]; +} + +/*! Check if we are in the english format or not. Depending on the locale +*/ +- (BOOL)_isEnglishFormat +{ + return [[_locale objectForKey:CPLocaleLanguageCode] isEqualToString:@"en"]; +} + + +#pragma mark - +#pragma mark Key event + +/*! Key down event + @param anEvent +*/ +- (void)keyDown:(CPEvent)anEvent +{ + if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle) + [_datePickerTextfield keyDown:anEvent]; +} + +@end + +var CPDatePickerModeKey = @"CPDatePickerModeKey", + CPIntervalKey = @"CPIntervalKey", + CPMinDateKey = @"CPMinDateKey", + CPMaxDateKey = @"CPMaxDateKey", + CPBackgroundColorKey = @"CPBackgroundColorKey", + CPDrawsBackgroundKey = @"CPDrawsBackgroundKey", + CPTextFontKey = @"CPTextFontKey", + CPDatePickerElementsKey = @"CPDatePickerElementsKey", + CPDatePickerStyleKey = @"CPDatePickerStyleKey", + CPLocaleKey = @"CPLocaleKey", + CPFormatterKey = @"CPFormatterKey", + CPBorderedKey = @"CPBorderedKey", + CPDateValueKey = @"CPDateValueKey"; + +@implementation CPDatePicker (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + _textFont = [aCoder decodeObjectForKey:CPTextFontKey]; + _minDate = [aCoder decodeObjectForKey:CPMinDateKey] || [CPDate distantPast]; + _maxDate = [aCoder decodeObjectForKey:CPMaxDateKey] || [CPDate distantFuture]; + _timeInterval = [aCoder decodeDoubleForKey:CPIntervalKey]; + _datePickerMode = [aCoder decodeIntForKey:CPDatePickerModeKey]; + _datePickerElements = [aCoder decodeIntForKey:CPDatePickerElementsKey]; + _datePickerStyle = [aCoder decodeIntForKey:CPDatePickerStyleKey]; + _locale = [aCoder decodeObjectForKey:CPLocaleKey]; + _formatter = [aCoder decodeObjectForKey:CPFormatterKey]; + _dateValue = [aCoder decodeObjectForKey:CPDateValueKey]; + _backgroundColor = [aCoder decodeObjectForKey:CPBackgroundColorKey]; + _drawsBackground = [aCoder decodeBoolForKey:CPDrawsBackgroundKey]; + _isBordered = [aCoder decodeBoolForKey:CPBorderedKey]; + [self _init]; + } + + return self +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [super encodeWithCoder:aCoder]; + [aCoder encodeDouble:_timeInterval forKey:CPIntervalKey]; + [aCoder encodeInt:_datePickerMode forKey:CPDatePickerModeKey]; + [aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey]; + [aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey]; + [aCoder encodeObject:_minDate forKey:CPMinDateKey]; + [aCoder encodeObject:_maxDate forKey:CPMaxDateKey] + [aCoder encodeObject:_dateValue forKey:CPDateValueKey];; + [aCoder encodeObject:_textFont forKey:CPTextFontKey]; + [aCoder encodeObject:_locale forKey:CPLocaleKey]; + [aCoder encodeObject:_formatter forKey:CPFormatterKey]; + [aCoder encodeObject:_backgroundColor forKey:CPBackgroundColorKey]; + [aCoder encodeObject:_drawsBackground forKey:CPDrawsBackgroundKey]; + [aCoder encodeObject:_isBordered forKey:CPBorderedKey]; +} + +@end + +@implementation _CPDatePickerValueBinder : CPBinder +{ +} + +@end + +@implementation CPDate (CPDatePickerAdditions) + +- (int)_daysInMonth +{ + return 32 - new Date(self.getFullYear(), self.getMonth(), 32).getDate(); +} + +- (void)_resetToMidnight +{ + self.setHours(0); + self.setMinutes(0); + self.setSeconds(0); + self.setMilliseconds(0); +} + +- (void)_resetToLastSeconds +{ + self.setHours(23); + self.setMinutes(59); + self.setSeconds(59); + self.setMilliseconds(99); +} + +@end \ No newline at end of file diff --git a/AppKit/CPDatePicker/_CPDatePickerCalendar.j b/AppKit/CPDatePicker/_CPDatePickerCalendar.j new file mode 100644 index 000000000..bf5e9399a --- /dev/null +++ b/AppKit/CPDatePicker/_CPDatePickerCalendar.j @@ -0,0 +1,1212 @@ +/* _CPDatePickerCalendar.j +* AppKit +* +* Created by Alexandre Wilhelm +* Copyright 2012 +* +* 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 "CPControl.j" +@import "CPTextField.j" +@import "CPButton.j" +@import "CPView.j" +@import "CPBezierPath.j" +@import "_CPDatePickerClock.j" + +@import + +@class CPDatePicker + +@global CPSingleDateMode +@global CPRangeDateMode + +@global CPTextFieldAndStepperDatePickerStyle +@global CPTextFieldDatePickerStyle + +@global CPHourMinuteDatePickerElementFlag +@global CPHourMinuteSecondDatePickerElementFlag +@global CPTimeZoneDatePickerElementFlag +@global CPYearMonthDatePickerElementFlag +@global CPYearMonthDayDatePickerElementFlag +@global CPEraDatePickerElementFlag + +var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"], + CPShortWeekDayNameArrayUS = [@"Su", @"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa"], + CPShortWeekDayNameArrayFr = [@"L", @"M", @"M", @"J", @"V", @"S", @"D"], + CPShortWeekDayNameArrayDe = [@"M", @"D", @"M", @"D", @"F", @"S", @"S"], + CPShortWeekDayNameArrayEs = [@"L", @"M", @"X", @"J", @"V", @"S", @"D"], + CPShortMonthNameArrayEn = [@"Jan", @"Feb", @"Mar", @"Apr", @"May", @"Jun", @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec"], + CPShortMonthNameArrayFr = [@"janv.", String.fromCharCode(102, 233, 118, 46), @"mars", @"apr.", @"mai", @"juin", @"juil.", String.fromCharCode(97, 111, 251, 116), @"sept.", @"oct.", @"nov.", String.fromCharCode(100, 233, 99, 46)], + CPShortMonthNameArrayDe = [@"Jan", @"Feb", String.fromCharCode(77, 228, 114), @"Apr", @"Mai", @"Jun", @"Jul", @"Aug", @"Sep", @"Okt", @"Nov", @"Dez"], + CPShortMonthNameArrayEs = [@"ene", @"feb", @"mar", @"abr", @"may", @"jun", @"jul", @"ago", @"sep", @"oct", @"nov", @"dic"]; + +@implementation _CPDatePickerCalendar : CPControl +{ + _CPDatePickerMonthView _monthView; + _CPDatePickerHeaderView _headerView; + _CPDatePickerClock _datePickerClock; + CPBox _box; + CPDatePicker _datePicker; + CPInteger _startSelectionIndex; + CPInteger _currentSelectionIndex; +} + + +#pragma mark - +#pragma mark Init method + +/*! Init a _CPDatePickerCalendar + @param aFrame + @param aDatePicker + @return a new instance of _CPDatePickerCalendar +*/ +- (id)initWithFrame:(CGRect)aFrame withDatePicker:(CPDatePicker)aDatePicker +{ + if (self = [super initWithFrame:aFrame]) + { + _datePicker = aDatePicker + [self _init]; + } + return self; +} + +/*! Init the object +*/ +- (void)_init +{ + var sizeHeader = [_datePicker valueForThemeAttribute:@"size-header"], + sizeCalendar = [_datePicker valueForThemeAttribute:@"size-calendar"], + sizeClock = [_datePicker valueForThemeAttribute:@"size-clock"]; + + _box = [[_DatePickerBox alloc] initWithFrame:CGRectMake(0, 0, sizeCalendar.width, sizeHeader.height + sizeCalendar.height)]; + [_box setDatePicker:_datePicker]; + + _headerView = [[_CPDatePickerHeaderView alloc] initWithFrame:CGRectMake(0, 0, sizeHeader.width, sizeHeader.height) datePicker:_datePicker delegate:self]; + [_box addSubview:_headerView]; + + _monthView = [[_CPDatePickerMonthView alloc] initWithFrame:CGRectMake(0, sizeHeader.height, sizeCalendar.width, sizeCalendar.height) datePicker:_datePicker delegate:self]; + [_box addSubview:_monthView]; + + _datePickerClock = [[_CPDatePickerClock alloc] initWithFrame:CGRectMake(sizeCalendar.width + 10, sizeHeader.height + sizeCalendar.height / 2 - sizeClock.height / 2, sizeClock.width, sizeClock.height) datePicker:_datePicker]; + [_datePickerClock setHidden:YES]; + [self addSubview:_datePickerClock]; + + [self addSubview:_box]; + + [self setNeedsLayout]; +} + + +#pragma mark - +#pragma mark Responder methods + +- (BOOL)becomeFirstResponder +{ + return YES; +} + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + + +#pragma mark - +#pragma mark Getter Setter methods + +/*! Set the date value of the component. It sets the dateValue of the header and the monthView also + @param aDateValue +*/ +- (void)setDateValue:(CPDate)aDateValue +{ + [_monthView setMonthForDate:aDateValue]; + [_headerView setMonthForDate:[_monthView monthDate]]; + + [self setNeedsLayout]; + [self setNeedsDisplay:YES]; +} + +/*! Set enabled + @param aBoolean +*/ +- (void)setEnabled:(BOOL)aBoolean +{ + [super setEnabled:aBoolean]; + + [_datePickerClock setEnabled:aBoolean]; + [_headerView setEnabled:aBoolean]; + [_monthView setEnabled:aBoolean]; +} + + +#pragma mark - +#pragma mark Layout methods + +/*! Manager the subviews. It hides or not the clock. +*/ +- (void)layoutSubviews +{ + if ([_datePicker datePickerStyle] == CPTextFieldAndStepperDatePickerStyle || [_datePicker datePickerStyle] == CPTextFieldDatePickerStyle) + return; + + var minSize = [_datePicker valueForThemeAttribute:@"min-size-calendar"], + sizeHeader = [_datePicker valueForThemeAttribute:@"size-header"], + sizeCalendar = [_datePicker valueForThemeAttribute:@"size-calendar"], + sizeClock = [_datePicker valueForThemeAttribute:@"size-clock"]; + + [super layoutSubviews]; + + if ([_datePicker datePickerElements] & CPHourMinuteSecondDatePickerElementFlag || [_datePicker datePickerElements] & CPHourMinuteDatePickerElementFlag) + { + [_datePickerClock setHidden:NO]; + [_datePickerClock setNeedsLayout]; + + if ([_datePicker datePickerElements] & CPYearMonthDatePickerElementFlag || [_datePicker datePickerElements] & CPYearMonthDayDatePickerElementFlag) + { + var frameSize = CGSizeMakeCopy(minSize); + frameSize.width += sizeClock.width + 10; + + [_datePicker setFrameSize:frameSize]; + [_datePickerClock setFrameOrigin:CGPointMake(sizeCalendar.width + 10, [self bounds].size.height / 2 - sizeClock.height / 2)]; + } + else + { + [_datePicker setFrameSize:sizeClock]; + [_datePickerClock setFrameOrigin:CGPointMake(0, 0)]; + } + + } + else + { + [_datePicker setFrameSize:minSize]; + [_datePickerClock setHidden:YES]; + } + + if ([_datePicker datePickerElements] & CPYearMonthDatePickerElementFlag || [_datePicker datePickerElements] & CPYearMonthDayDatePickerElementFlag) + { + [_box setHidden:NO]; + [_headerView setHidden:NO]; + [_monthView setHidden:NO]; + [_box setNeedsLayout]; + [_box setNeedsDisplay:YES]; + [_headerView setNeedsLayout]; + [_monthView setNeedsLayout]; + [_monthView setNeedsDisplay:YES]; + } + else + { + [_box setHidden:YES]; + [_headerView setHidden:YES]; + [_monthView setHidden:YES]; + } +} + + +#pragma mark - +#pragma mark Action methods + +/*! Move to the nextMonth without changing the dateValue of the datePicker +*/ +- (void)_nextMonth:(id)sender +{ + [self setDateValue:[_monthView nextMonth]]; +} + +/*! Move to the previous month without changing the dateValue of the datePicker +*/ +- (void)_previousMonth:(id)sender +{ + [self setDateValue:[_monthView previousMonth]]; +} + +/*! Move to the current selected day +*/ +- (void)_currentMonth:(id)sender +{ + [self setDateValue:[_datePicker dateValue]]; +} + +@end + + +@implementation _CPDatePickerHeaderView : CPControl +{ + CPArray _dayLabels; + CPArray _monthNames; + CPButton _nextButton; + CPButton _previousButton; + CPButton _currentButton; + CPDatePicker _datePicker; + CPDate _date; + CPTextField _title; +} + + +#pragma mark - +#pragma mark Init methods + +/*! Init a new instance of _CPDatePickerHeaderView + @param aFrame + @param aDatePicker + @return a new instance of _CPDatePickerHeaderView +*/ +- (id)initWithFrame:(CGRect)aFrame datePicker:(CPDatePicker)aDatePicker delegate:(id)aDelegate +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _datePicker = aDatePicker; + + // Title + _title = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [_title setValue:[_datePicker valueForThemeAttribute:@"title-font" inState:CPThemeStateNormal] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_title setValue:[_datePicker valueForThemeAttribute:@"title-text-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_title setValue:[_datePicker valueForThemeAttribute:@"title-text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_title setValue:[_datePicker valueForThemeAttribute:@"title-text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + + [_title setValue:[_datePicker valueForThemeAttribute:@"title-font" inState:CPThemeStateDisabled] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_title setValue:[_datePicker valueForThemeAttribute:@"title-text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_title setValue:[_datePicker valueForThemeAttribute:@"title-text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_title setValue:[_datePicker valueForThemeAttribute:@"title-text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [self addSubview:_title]; + + _dayLabels = [CPArray array]; + + // Days + for (var i = 0; i < [[self _dayNames] count]; i++) + { + var label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + [label setValue:CPCenterTextAlignment forThemeAttribute:@"alignment"]; + + [label setValue:[_datePicker valueForThemeAttribute:@"weekday-font" inState:CPThemeStateNormal] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [label setValue:[_datePicker valueForThemeAttribute:@"weekday-text-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [label setValue:[_datePicker valueForThemeAttribute:@"weekday-text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [label setValue:[_datePicker valueForThemeAttribute:@"weekday-text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + + [label setValue:[_datePicker valueForThemeAttribute:@"weekday-font" inState:CPThemeStateDisabled] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [label setValue:[_datePicker valueForThemeAttribute:@"weekday-text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [label setValue:[_datePicker valueForThemeAttribute:@"weekday-text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [label setValue:[_datePicker valueForThemeAttribute:@"weekday-text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_dayLabels addObject:label]; + [self addSubview:label]; + } + + // Arrows + _previousButton = [[CPButton alloc] initWithFrame:CGRectMakeZero()]; + [_previousButton setButtonType:CPMomentaryChangeButton]; + [_previousButton setBordered:NO]; + [_previousButton setImage:[_datePicker valueForThemeAttribute:@"arrow-image-left"]]; + [_previousButton setAlternateImage:[_datePicker valueForThemeAttribute:@"arrow-image-left-highlighted"]]; + [self addSubview:_previousButton]; + + _nextButton = [[CPButton alloc] initWithFrame:CGRectMakeZero()]; + [_nextButton setButtonType:CPMomentaryChangeButton]; + [_nextButton setBordered:NO]; + [_nextButton setImage:[_datePicker valueForThemeAttribute:@"arrow-image-right"]]; + [_nextButton setAlternateImage:[_datePicker valueForThemeAttribute:@"arrow-image-right-highlighted"]]; + [self addSubview:_nextButton]; + + _currentButton = [[CPButton alloc] initWithFrame:CGRectMakeZero()]; + [_currentButton setButtonType:CPMomentaryChangeButton]; + [_currentButton setBordered:NO]; + [_currentButton setImage:[_datePicker valueForThemeAttribute:@"circle-image"]]; + [_currentButton setAlternateImage:[_datePicker valueForThemeAttribute:@"circle-image-highlighted"]]; + [self addSubview:_currentButton]; + + [_previousButton setTarget:aDelegate]; + [_previousButton setAction:@selector(_previousMonth:)]; + + [_nextButton setTarget:aDelegate]; + [_nextButton setAction:@selector(_nextMonth:)]; + + [_currentButton setTarget:aDelegate]; + [_currentButton setAction:@selector(_currentMonth:)]; + + [self setNeedsLayout]; + } + + return self; +} + + +#pragma mark - +#pragma mark Getter Setter methods + +/*! Return the day names depending on the CPLocale of the datePicker + @return an array +*/ +- (CPArray)_dayNames +{ + switch ([[_datePicker locale] objectForKey:CPLocaleLanguageCode]) + { + case @"en": + + // Check if it's in the american format. If yes the week will begin the sunday + if ([_datePicker _isAmericanFormat]) + return CPShortWeekDayNameArrayUS; + else + return CPShortWeekDayNameArrayEn; + break; + + case @"es": + return CPShortWeekDayNameArrayEs; + break; + + case @"de": + return CPShortWeekDayNameArrayDe; + break; + + case @"fr": + return CPShortWeekDayNameArrayFr; + break; + + default: + return CPShortWeekDayNameArrayEn + break; + } +} + +/*! Return the month names depending on the CPLocale of the datePicker + @return an array +*/ +- (CPArray)_monthNames +{ + switch ([[_datePicker locale] objectForKey:CPLocaleLanguageCode]) + { + case @"en": + return CPShortMonthNameArrayEn; + break; + + case @"es": + return CPShortMonthNameArrayEs; + break; + + case @"de": + return CPShortMonthNameArrayDe; + break; + + case @"fr": + return CPShortMonthNameArrayFr; + break; + + default: + return CPShortMonthNameArrayEn + break; + } + +} + +/*! Set the monthDate of the header + @aMonthDate the new monthDate +*/ +- (void)setMonthForDate:(CPDate)aMonthDate +{ + _date = aMonthDate; + [self setNeedsLayout]; +} + +/*! Set enabled + @param aBoolean +*/ +- (void)setEnabled:(BOOL)aBoolean +{ + [_previousButton setEnabled:aBoolean]; + [_nextButton setEnabled:aBoolean]; + [_currentButton setEnabled:aBoolean]; + [_dayLabels makeObjectsPerformSelector:@selector(setEnabled:) withObject:aBoolean]; + [_title setEnabled:aBoolean]; +} + + +#pragma mark - +#pragma mark Layout methods + +/*! Layout the subviews +*/ +- (void)layoutSubviews +{ + var bounds = [self bounds], + dayNames = [self _dayNames], + width = CGRectGetWidth(bounds), + buttonInset = [_datePicker valueForThemeAttribute:@"arrow-inset"], + numberOfLabels = [_dayLabels count], + labelWidth = width / numberOfLabels, + sizeButtonLeft = [[_datePicker valueForThemeAttribute:@"arrow-image-left"] size], + sizeButtonRight = [[_datePicker valueForThemeAttribute:@"arrow-image-right"] size], + sizeButtonCircle = [[_datePicker valueForThemeAttribute:@"circle-image"] size], + sizeTileWidth = [_datePicker valueForThemeAttribute:@"size-tile"].width; + + // Arrows + [_nextButton setFrame:CGRectMake(width - [_nextButton frameSize].width - buttonInset.right, buttonInset.top, sizeButtonRight.width, sizeButtonRight.height)]; + [_currentButton setFrame:CGRectMake(CGRectGetMinX([_nextButton frame]) - sizeButtonCircle.width - buttonInset.left - buttonInset.right, buttonInset.top, sizeButtonCircle.width, sizeButtonCircle.height)]; + [_previousButton setFrame:CGRectMake(CGRectGetMinX([_currentButton frame]) - sizeButtonLeft.width - buttonInset.left - buttonInset.right, buttonInset.top, sizeButtonLeft.width, sizeButtonLeft.height)]; + + var firstDayTileX; + + // Weekday label + for (var i = 0; i < numberOfLabels; i++) + { + var dayLabel = _dayLabels[i]; + + [dayLabel setStringValue:dayNames[i]]; + [dayLabel sizeToFit] + [dayLabel setFrameOrigin:CGPointMake(sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2, 23)]; + + if (i == 0) + firstDayTileX = sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2 + } + + // Title + [_title setStringValue:[CPString stringWithFormat:@"%s %i", [self _monthNames][_date.getMonth()], _date.getFullYear()]]; + [_title sizeToFit]; + [_title setFrameOrigin:CGPointMake(firstDayTileX, 6)]; +} + +@end + + +@implementation _CPDatePickerMonthView : CPControl +{ + BOOL _isMonthJustChanged; + CPArray _dayTiles; + CPDate _clickDate; + CPDate _dragDate; + CPDate _date; + CPDate _previousMonth @accessors(property=previousMonth); + CPDate _nextMonth @accessors(property=nextMonth); + CPDatePicker _datePicker; + CPEvent _eventDragged; + CPTimer _timerMonth; + id _delegate; + int _indexDayTile; +} + + +#pragma mark - +#pragma mark Init methods + +/*! Init a _CPDatePickerMonthView + @param aFrame + @param aDatePicker + @return a new _CPDatePickerMonthView +*/ +- (id)initWithFrame:(CGRect)aFrame datePicker:(CPDatePicker)aDatePicker delegate:(id)aDelegate +{ + if (self = [super initWithFrame:aFrame]) + { + _delegate = aDelegate; + _isMonthJustChanged = NO; + _indexDayTile = -1; + _datePicker = aDatePicker; + _dayTiles = [CPArray array]; + + // Create tiles + for (var i = 0; i < 42; i++) + { + var dayView = [[_CPDatePickerDayView alloc] initWithFrame:CGRectMakeZero() withDatePicker:_datePicker]; + [self addSubview:dayView]; + [_dayTiles addObject:dayView]; + } + + [self setNeedsLayout]; + } + return self; +} + + +#pragma mark - +#pragma mark Getter Setter methods + +/*! Set the monthDate of the component + @param aDate +*/ +- (void)setMonthForDate:(CPDate)aDate +{ + if (_dragDate) + { + if (_dragDate.getMonth() != _date.getMonth()) + _isMonthJustChanged = YES; + + _date = [_dragDate copy]; + } + else + { + _date = [aDate copy]; + } + + if (![aDate isEqualToDate:[CPDate distantFuture]]) + { + // Reset the date to the first day of the month & midnight + _date.setDate(1); + [_date _resetToMidnight]; + + // There must be a better way to do this. + var firstDay = [_date copy]; + firstDay.setDate(1); + + // Set the previous and next month date. This is usefull for the tile of the next/previous month + _previousMonth = new Date(firstDay.getTime() - 86400000); + _previousMonth.setDate(1); + + _nextMonth = new Date(firstDay.getTime() + (([_date _daysInMonth] + 1) * 86400000)); + _nextMonth.setDate(1); + } + + [self reloadData]; + + if (_isMonthJustChanged) + { + var dayTile = [_dayTiles objectAtIndex:_indexDayTile]; + + if ([dayTile date].getMonth() == _date.getMonth()) + { + [self mouseDragged:_eventDragged]; + } + else + { + if ([dayTile date].getMonth() - _date.getMonth() == 1 || [dayTile date].getFullYear() - _date.getFullYear() == 1) + _timerMonth = [CPTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(_timerNextMonthEvent:) userInfo:nil repeats:NO]; + else + _timerMonth = [CPTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(_timerPreviousMonthEvent:) userInfo:nil repeats:NO]; + } + } +} + +- (void)monthDate +{ + return _date; +} + +/*! Return the size of a tile +*/ +- (CGSize)tileSize +{ + return [_datePicker valueForThemeAttribute:@"size-tile"]; +} + +/*! Return the first index day of the month +*/ +- (int)startOfWeekForDate:(CPDate)aDate +{ + var day = aDate.getDay(); + + // American people begins the week the sunday + if (![_datePicker _isAmericanFormat]) + return (day + 6) % 7; + + return day; +} + +/*! Set enabled + @param aBoolean +*/ +- (void)setEnabled:(BOOL)aBoolean +{ + [super setEnabled:aBoolean]; + [self reloadData]; +} + + +/*! Return the index of tile depending of the giving event + @param anEvent + @return an index +*/ +- (CPInteger)indexOfTileForEvent:(CPEvent)anEvent +{ + var locationInView = [self convertPoint:[anEvent locationInWindow] fromView:nil], + tileSize = [self tileSize]; + + // Get the week row + var rowIndex = FLOOR(locationInView.y / tileSize.height), + columnIndex = FLOOR(locationInView.x / tileSize.width); + + columnIndex = MIN(MAX(columnIndex, 0), 6); + rowIndex = MIN(MAX(rowIndex, 0), 5); + + var tileIndex = (rowIndex * 7) + columnIndex; + + return tileIndex; +} + +#pragma mark - +#pragma mark Reload data + +/*! Reload the data +*/ +- (void)reloadData +{ + if (!_date) + return; + + var currentMonth = _date, + startOfMonthDay = [self startOfWeekForDate:currentMonth], + daysInPreviousMonth = [_previousMonth _daysInMonth], + firstDayToShowInPreviousMonth = daysInPreviousMonth - startOfMonthDay, + currentDate = new Date(_previousMonth.getFullYear(), _previousMonth.getMonth(), firstDayToShowInPreviousMonth), + now = [CPDate date], + dateValue = [_datePicker dateValue]; + + // Update the tiles + for (var i = 0; i < [_dayTiles count]; i++) + { + var dayTile = _dayTiles[i]; + + // Increment to next day + currentDate.setTime(currentDate.getTime() + 90000000); + [currentDate _resetToMidnight]; + + var isPresentMonth = (now.getMonth() == currentDate.getMonth() + && now.getFullYear() == currentDate.getFullYear()); + + [dayTile setDate:[currentDate copy]]; + [dayTile setStringValue:currentDate.getDate()]; + [dayTile setDisabled:![self isEnabled] || currentDate.getMonth() !== currentMonth.getMonth()]; + [dayTile setHighlighted:isPresentMonth && currentDate.getDate() == now.getDate()]; + } + + // Select the dates + [self _selectDate:[_datePicker dateValue] timeInterval:[_datePicker timeInterval]]; +} + + +#pragma mark - +#pragma mark Select methods + +/*! Select one date or several date depending of the giving interval + @param aStartDate + @param anInterval; +*/ +- (void)_selectDate:(CPDate)aStartDate timeInterval:(CPInteger)anInterval +{ + var endDate = [[CPDate alloc] initWithTimeInterval:anInterval sinceDate:aStartDate], + tilesCount = [_dayTiles count]; + + aStartDate = [aStartDate copy]; + + [aStartDate _resetToMidnight]; + [endDate _resetToMidnight]; + + for (var i = 0; i < tilesCount; i++) + { + var tile = _dayTiles[i], + tileDate = [[tile date] copy], + selected = NO; + + [tileDate _resetToMidnight] + + if (aStartDate) + selected = tileDate >= aStartDate && tileDate <= endDate; + + // Select a tile + [tile setSelected:selected]; + } +} + +#pragma mark - +#pragma mark Layout methods + +/*! Tile the view +*/ +- (void)tile +{ + var tileSize = [self tileSize], + width = tileSize.width, + height = tileSize.height, + tilesCount = [_dayTiles count], + borderWidth = [_datePicker valueForThemeAttribute:@"border-width"], + tileIndex; + + // Set the frame of the tiles + for (tileIndex = 0; tileIndex < tilesCount; tileIndex++) + { + var dayInWeek = tileIndex % 7, + weekInMonth = (tileIndex - dayInWeek) / 7, + tileFrame = CGRectMake(dayInWeek * width, weekInMonth * height, width + borderWidth, height + borderWidth); + + [_dayTiles[tileIndex] setFrame:tileFrame]; + } + + [self reloadData]; +} + +/*! Layout the subviews +*/ +- (void)layoutSubviews +{ + [super layoutSubviews]; + + [self tile]; + [_dayTiles makeObjectsPerformSelector:@selector(setNeedsLayout)]; +} + +/*! Draw the component. This draws the border of the tile. + The selected tile are drawed in the drawRect method of the tile. But the unselected tile here. + It avoids some problems with tiles over other tiles (otherwise the color of the tile border would be different). + Rememeber that the first pixel of a tile are over the last pixel of the last tile (because the border) +*/ +- (void)drawRect:(CGRect)aRect +{ + [super drawRect:aRect]; + + var context = [[CPGraphicsContext currentContext] graphicsPort], + width = [self tileSize].width, + height = [self tileSize].height, + isBorderPair = ([_datePicker valueForThemeAttribute:@"border-width"] % 2) == 0; + + CGContextBeginPath(context); + CGContextSetStrokeColor(context, [_datePicker valueForThemeAttribute:@"border-color" inState:[_datePicker themeState]]); + CGContextSetLineWidth(context, [_datePicker valueForThemeAttribute:@"border-width"]); + + if ([_datePicker isBordered]) + { + for (var i = 0; i < 6; i++) + { + var y = i * height; + + // Very usefull to avoid to have a line of two pixels instead one + if (!isBorderPair) + y += 0.5 + + CGContextMoveToPoint(context, 0, y); + CGContextAddLineToPoint(context, [self bounds].size.width, y); + } + + for (var i = 0; i < 7; i++) + { + var x = i * width; + + // Very usefull to avoid to have a line of two pixels instead one + if (!isBorderPair) + x += 0.5 + + CGContextMoveToPoint(context, x, 0); + CGContextAddLineToPoint(context, x, [self bounds].size.height); + } + } + else + { + var y = 0; + + // Very usefull to avoid to have a line of two pixels instead one + if (!isBorderPair) + y += 0.5 + + CGContextMoveToPoint(context, 0, y); + CGContextAddLineToPoint(context, [self bounds].size.width, y); + } + + CGContextStrokePath(context); + CGContextClosePath(context); +} + + +#pragma mark - +#pragma mark Mouse event + +/*! Mouse down event +*/ +- (void)mouseDown:(CPEvent)anEvent +{ + if (![self isEnabled]) + return; + + var dayTile = [_dayTiles objectAtIndex:[self indexOfTileForEvent:anEvent]], + dateTile = [[dayTile date] copy], + dateValue = [_datePicker dateValue]; + + _clickDate = [dateTile copy]; + _dragDate = nil; + _indexDayTile = -1; + _eventDragged = nil + + // Check if we have to change or not the month of the component + if ([dayTile date].getMonth() == _date.getMonth()) + { + var minDate = [[_datePicker minDate] copy], + maxDate = [[_datePicker maxDate] copy]; + + [minDate _resetToMidnight]; + [maxDate _resetToLastSeconds]; + + if (dateTile >= minDate && dateTile <= maxDate) + [_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:dateTile] timeInterval:0]; + } + else + { + // Check the year and the month. The year is usefull when changing from Jan to Dec. + if (_date.getMonth() - [dayTile date].getMonth() == 1 || _date.getFullYear() - [dayTile date].getFullYear() == 1) + [_delegate _previousMonth:self]; + else + [_delegate _nextMonth:self]; + } +} + +/*! Mouse dragged event +*/ +- (void)mouseDragged:(CPEvent)anEvent +{ + if (![self isEnabled] || !CGRectContainsPoint([self bounds],[self convertPoint:[anEvent locationInWindow] fromView:nil])) + return; + + var dayTile = [_dayTiles objectAtIndex:[self indexOfTileForEvent:anEvent]], + dateTile = [[dayTile date] copy], + dateValue = [_datePicker dateValue]; + + _dragDate = [dateTile copy]; + _indexDayTile = [self indexOfTileForEvent:anEvent]; + _eventDragged = anEvent; + + if ([_datePicker datePickerMode] == CPSingleDateMode) + { + // Check if we have to change or not the month of the component + if ([dayTile date].getMonth() == _date.getMonth()) + { + [_timerMonth invalidate]; + _isMonthJustChanged = NO; + + [_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:dateTile] timeInterval:0]; + } + else if (!_isMonthJustChanged) + { + [_timerMonth invalidate]; + _isMonthJustChanged = NO; + + // Check the year and the month. The year is usefull when changing from Jan to Dec. + if (_date.getMonth() - [dayTile date].getMonth() == 1 || _date.getFullYear() - [dayTile date].getFullYear() == 1) + [_delegate _previousMonth:self]; + else + [_delegate _nextMonth:self]; + } + } + else + { + if (dateTile.getMonth() == _date.getMonth() || !_isMonthJustChanged) + { + [_timerMonth invalidate]; + _isMonthJustChanged = NO; + + var dateValueAtMidnight = [[_datePicker dateValue] copy]; + + [dateValueAtMidnight _resetToMidnight]; + + if (dateTile < _clickDate) + [_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:dateTile] timeInterval:[_clickDate timeIntervalSinceDate:dateTile]]; + else if ([[dayTile date] isEqualToDate:_clickDate]) + [_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:dateTile] timeInterval:0]; + else + [_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:_clickDate] timeInterval:[dateTile timeIntervalSinceDate:dateValueAtMidnight]]; + } + } +} + +- (void)mouseUp:(CPEvent)anEvent +{ + [_timerMonth invalidate]; + _dragDate = nil; + _clickDate = nil; + _isMonthJustChanged = NO; + _indexDayTile = -1; + _eventDragged = nil; +} + + +#pragma mark - +#pragma mark Timer + +- (void)_timerNextMonthEvent:(CPEvent)anEvent +{ + if (_isMonthJustChanged) + { + _dragDate.setMonth(_date.getMonth() + 1); + [_delegate _nextMonth:self]; + } +} + +- (void)_timerPreviousMonthEvent:(CPEvent)anEvent +{ + if (_isMonthJustChanged) + { + _dragDate.setMonth(_date.getMonth() - 1); + [_delegate _previousMonth:self]; + } +} + + +#pragma mark - +#pragma mark Date methods + +- (CPDate)_hoursMinutesSecondsFromDatePickerForDate:(CPDate)aDate +{ + var dateValue = [_datePicker dateValue]; + + aDate.setHours(dateValue.getHours()); + aDate.setMinutes(dateValue.getMinutes()); + aDate.setSeconds(dateValue.getSeconds()); + + return aDate; +} + +@end + + +@implementation _CPDatePickerDayView : CPControl +{ + CPDate _date @accessors(property=date); + + BOOL _isDisabled; + BOOL _isHighlighted; + BOOL _isSelected; + CPDatePicker _datePicker; + CPTextField _textField; +} + + +#pragma mark - +#pragma mark Init methods + +/*! Create a new instance of _CPDatePickerDayView + @param aFrame + @param aDatePicker + @return a new instance of _CPDatePickerDayView +*/ +- (id)initWithFrame:(CGRect)aFrame withDatePicker:(CPDatePicker)aDatePicker +{ + if (self = [super initWithFrame:aFrame]) + { + [self setHitTests:NO]; + + _datePicker = aDatePicker; + + _textField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateNormal] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateSelected] forThemeAttribute:@"font" inState:CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected]; + + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateDisabled] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateDisabled | CPThemeStateSelected] forThemeAttribute:@"font" inState:CPThemeStateDisabled | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateDisabled | CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateDisabled | CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateDisabled | CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled | CPThemeStateSelected]; + + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateHighlighted] forThemeAttribute:@"font" inState:CPThemeStateHighlighted]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateHighlighted] forThemeAttribute:@"text-color" inState:CPThemeStateHighlighted]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateHighlighted] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateHighlighted]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateHighlighted] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateHighlighted]; + + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"font" inState:CPThemeStateHighlighted | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateHighlighted | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateHighlighted | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateHighlighted | CPThemeStateSelected]; + + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"font" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected]; + + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState: CPThemeStateDisabled | CPThemeStateHighlighted ] forThemeAttribute:@"font" inState: CPThemeStateDisabled | CPThemeStateHighlighted ]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted ] forThemeAttribute:@"text-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted ]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted ] forThemeAttribute:@"text-shadow-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted ]; + [_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState: CPThemeStateDisabled | CPThemeStateHighlighted ] forThemeAttribute:@"text-shadow-offset" inState: CPThemeStateDisabled | CPThemeStateHighlighted]; + + [self addSubview:_textField]; + + [self setNeedsLayout]; + } + + return self; +} + + +#pragma mark - +#pragma mark Theme methods + +/*! Set a theme +*/ +- (void)setThemeState:(CPThemeState)aState +{ + [_textField setThemeState:aState]; + [super setThemeState:aState]; +} + +/*! Unset a theme +*/ +- (void)unsetThemeState:(CPThemeState)aState +{ + [_textField unsetThemeState:aState]; + [super unsetThemeState:aState]; +} + + +#pragma mark - +#pragma mark Getter methods + +/*! Select the tile +*/ +- (void)setSelected:(BOOL)shouldBeSelected +{ + if (_isSelected === shouldBeSelected) + return; + + _isSelected = shouldBeSelected; + + if (_isSelected) + [self setThemeState:CPThemeStateSelected]; + else + [self unsetThemeState:CPThemeStateSelected]; +} + +/*! Disabled the tile (used for previous and next month tile) +*/ +- (void)setDisabled:(BOOL)shouldBeDisabled +{ + if (_isDisabled === shouldBeDisabled) + return; + + _isDisabled = shouldBeDisabled; + + if (_isDisabled) + [self setThemeState:CPThemeStateDisabled]; + else + [self unsetThemeState:CPThemeStateDisabled]; +} + +/*! Highlight the tile (used for current day) +*/ +- (void)setHighlighted:(BOOL)shouldBeHighlighted +{ + if (_isHighlighted === shouldBeHighlighted) + return; + + _isHighlighted = shouldBeHighlighted; + + if (_isHighlighted) + [self setThemeState:CPThemeStateHighlighted]; + else + [self unsetThemeState:CPThemeStateHighlighted]; +} + +/*! Set the stringValue of the tile + @param aStringValue +*/ +- (void)setStringValue:(CPString)aStringValue +{ + [_textField setStringValue:aStringValue]; + [_textField sizeToFit]; +} + + +#pragma mark - +#pragma mark Layout methods + +/*! Layout the subviews +*/ +- (void)layoutSubviews +{ + var bounds = [self bounds]; + [_textField sizeToFit]; + [_textField setFrameOrigin:CGPointMake(bounds.size.width / 2 - [_textField frameSize].width / 2 + [_datePicker valueForThemeAttribute:@"border-width"], bounds.size.height / 2 - [_textField frameSize].height / 2)]; +} + +/*! Drawrect +*/ +- (void)drawRect:(CGRect)aRect +{ + [super drawRect:aRect]; + + var themeState = [self themeState], + context = [[CPGraphicsContext currentContext] graphicsPort]; + + if (themeState & CPThemeStateSelected) + { + [self setBackgroundColor:[_datePicker valueForThemeAttribute:@"bezel-color-calendar" inState:themeState]]; + CGContextSetLineWidth(context, [_datePicker valueForThemeAttribute:@"border-width"]); + CGContextSetStrokeColor(context, [_datePicker valueForThemeAttribute:@"border-color" inState:themeState]); + CGContextAddRect(context, [self bounds]); + CGContextStrokeRect(context, [self bounds]); + } + else + { + // Clear color, because the original color of a tile is handle by his superview + [self setBackgroundColor:[CPColor clearColor]]; + } + +} + +@end + + +@implementation _DatePickerBox : CPView +{ + CPDatePicker _datePicker @accessors(property=datePicker); +} + +- (id)init +{ + if (self = [super init]) + { + } + return self; +} + +- (void)drawRect:(CGRect)aRect +{ + [super drawRect:aRect]; + + if ([_datePicker isBordered]) + { + var context = [[CPGraphicsContext currentContext] graphicsPort], + borderWidth = [_datePicker valueForThemeAttribute:@"border-width"] / 2; + + CGContextBeginPath(context); + CGContextSetStrokeColor(context, [_datePicker valueForThemeAttribute:@"border-color" inState:[_datePicker themeState]]); + CGContextSetLineWidth(context, [_datePicker valueForThemeAttribute:@"border-width"]); + + CGContextMoveToPoint(context, borderWidth,borderWidth); + CGContextAddLineToPoint(context, aRect.size.width - borderWidth,borderWidth); + CGContextAddLineToPoint(context, aRect.size.width - borderWidth,aRect.size.height - borderWidth); + CGContextAddLineToPoint(context, borderWidth,aRect.size.height - borderWidth); + CGContextAddLineToPoint(context, borderWidth,borderWidth); + + CGContextStrokePath(context); + CGContextClosePath(context); + } +} + +- (void)layoutSubviews +{ + if ([_datePicker drawsBackground]) + [self setBackgroundColor:[_datePicker backgroundColor]]; + else + [self setBackgroundColor:[CPColor clearColor]]; +} + + +@end diff --git a/AppKit/CPDatePicker/_CPDatePickerClock.j b/AppKit/CPDatePicker/_CPDatePickerClock.j new file mode 100644 index 000000000..0015a41da --- /dev/null +++ b/AppKit/CPDatePicker/_CPDatePickerClock.j @@ -0,0 +1,284 @@ +/* _CPDatePickerClock.j +* AppKit +* +* Created by Alexandre Wilhelm +* Copyright 2012 +* +* 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 "CPView.j" +@import "CPTextField.j" +@import "CPImageView.j" +@import "CALayer.j" + +@class CPDatePicker + +@global CPHourMinuteSecondDatePickerElementFlag + +@implementation _CPDatePickerClock : CPView +{ + BOOL _isEnabled; + CALayer _rootLayer; + CALayer _hourHandLayer; + CALayer _minuteHandLayer; + CALayer _secondHandLayer; + CALayer _middleHandLayer; + CPDatePicker _datePicker; + CPTextField _PMAMTextField; +} + + +#pragma mark - +#pragma mark Init methods + +/*! Init a new _CPDatePickerClock + @param aFrame + @param aDatePicker + @return a new instance of _CPDatePickerClock +*/ +- (id)initWithFrame:(CGRect)aFrame datePicker:(CPDatePicker)aDatePicker +{ + if (self = [super initWithFrame:aFrame]) + { + _datePicker = aDatePicker; + + _PMAMTextField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-font" inState:CPThemeStateNormal] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + + [_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-font" inState:CPThemeStateDisabled] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [self addSubview:_PMAMTextField]; + + var middleHandSize = [_datePicker valueForThemeAttribute:@"middle-hand-size"], + minuteHandSize = [_datePicker valueForThemeAttribute:@"minute-hand-size"], + hourHandSize = [_datePicker valueForThemeAttribute:@"hour-hand-size"], + secondHandSize = [_datePicker valueForThemeAttribute:@"second-hand-size"]; + + // We use layer to make the rotation possible + _hourHandLayer = [[HandLayer alloc] initWithSize:hourHandSize]; + [_hourHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)]; + [_hourHandLayer setAnchorPoint:CGPointMakeZero()]; + [_hourHandLayer setPosition:CGPointMake(0.0, 0.0)]; + + _minuteHandLayer = [[HandLayer alloc] initWithSize:minuteHandSize]; + [_minuteHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)]; + [_minuteHandLayer setAnchorPoint:CGPointMakeZero()]; + [_minuteHandLayer setPosition:CGPointMake(0.0, 0.0)]; + + _secondHandLayer = [[HandLayer alloc] initWithSize:secondHandSize]; + [_secondHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)]; + [_secondHandLayer setAnchorPoint:CGPointMakeZero()]; + [_secondHandLayer setPosition:CGPointMake(0.0, 0.0)]; + + _middleHandLayer = [[HandLayer alloc] initWithSize:middleHandSize]; + [_middleHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)]; + [_middleHandLayer setAnchorPoint:CGPointMakeZero()]; + [_middleHandLayer setPosition:CGPointMake(0.0, 0.0)]; + + _rootLayer = [CALayer layer]; + [self setWantsLayer:YES]; + [self setLayer:_rootLayer]; + + [_hourHandLayer setNeedsDisplay]; + [_middleHandLayer setNeedsDisplay]; + [_secondHandLayer setNeedsDisplay]; + [_minuteHandLayer setNeedsDisplay]; + + [_rootLayer addSublayer:_hourHandLayer]; + [_rootLayer addSublayer:_minuteHandLayer]; + [_rootLayer addSublayer:_secondHandLayer]; + [_rootLayer addSublayer:_middleHandLayer]; + + [_rootLayer setNeedsDisplay]; + + } + return self; +} + + +#pragma mark - +#pragma mark Layout methods + +/*! Layout the subviews +*/ +- (void)layoutSubviews +{ + [super layoutSubviews]; + + var bounds = [self bounds]; + + [self setBackgroundColor:[_datePicker valueForThemeAttribute:@"bezel-color-clock" inState:[_datePicker themeState]]]; + [_middleHandLayer setBackgroundHandColor:[_datePicker valueForThemeAttribute:@"middle-hand-color" inState:[_datePicker themeState]]]; + [_hourHandLayer setBackgroundHandColor:[_datePicker valueForThemeAttribute:@"hour-hand-color" inState:[_datePicker themeState]]]; + [_minuteHandLayer setBackgroundHandColor:[_datePicker valueForThemeAttribute:@"minute-hand-color" inState:[_datePicker themeState]]]; + [_secondHandLayer setBackgroundHandColor:[_datePicker valueForThemeAttribute:@"second-hand-color" inState:[_datePicker themeState]]]; + + if ([_datePicker _isEnglishFormat]) + { + if ([_datePicker dateValue].getHours() > 11) + [_PMAMTextField setStringValue:@"PM"] + else + [_PMAMTextField setStringValue:@"AM"]; + + [_PMAMTextField sizeToFit]; + [_PMAMTextField setFrameOrigin:CGPointMake(bounds.size.width / 2 - [_PMAMTextField frameSize].width / 2, bounds.size.height / 2 + 15)]; + [_PMAMTextField setHidden:NO]; + } + else + { + [_PMAMTextField setHidden:YES]; + } + + [_hourHandLayer setRotationRadians:[self _hourPositionRadianForDate:[_datePicker dateValue]]]; + [_minuteHandLayer setRotationRadians:[self _minutePositionRadianForDate:[_datePicker dateValue]]]; + [_secondHandLayer setRotationRadians:[self _secondPositionRadianForDate:[_datePicker dateValue]]]; + + // Check if we have to display the hand second + if (([_datePicker datePickerElements] & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag) + [_secondHandLayer setHidden:NO]; + else + [_secondHandLayer setHidden:YES]; + + [_rootLayer setNeedsDisplay]; +} + + +#pragma mark - +#pragma mark Getter Setter methods + +/*! Return the radian position of the hour +*/ +- (float)_hourPositionRadianForDate:(CPDate)aDate +{ + var hours = aDate.getHours() + aDate.getMinutes() / 60; + + return (360 * hours / 12) * (Math.PI / 180) +} + +/*! Return the radian position of the second +*/ +- (float)_secondPositionRadianForDate:(CPDate)aDate +{ + return (360 * aDate.getSeconds() / 60) * (Math.PI / 180) +} + +/*! Return the radian position of the minute +*/ +- (float)_minutePositionRadianForDate:(CPDate)aDate +{ + var minutes = aDate.getMinutes() + aDate.getSeconds() / 60; + + return (360 * minutes / 60) * (Math.PI / 180) +} + +/*! Set enabled + @param aBoolean +*/ +- (void)setEnabled:(BOOL)aBoolean +{ + _isEnabled = aBoolean; + [_PMAMTextField setEnabled:aBoolean]; + [_hourHandLayer setEnabled:aBoolean]; + [_middleHandLayer setEnabled:aBoolean]; + [_secondHandLayer setEnabled:aBoolean]; + [_minuteHandLayer setEnabled:aBoolean]; + + [self setNeedsLayout]; +} + +@end + + +@implementation HandLayer : CALayer +{ + BOOL _isEnabled @accessors(setter=setEnabled:, getter=isEnabled); + + CALayer _imageLayer; + float _rotationRadians; +} + + +#pragma mark - +#pragma mark Init methods + +/*! Init a new hand layer with an image. The image will be draw in a ImageLayer + @param anImage + @return a new instance of handLayer +*/ +- (id)initWithSize:(CGSize)aSize +{ + if (self = [super init]) + { + _isEnabled = YES; + _imageLayer = [CALayer layer]; + _rotationRadians = 0; + + [_imageLayer setDelegate:self]; + [_imageLayer setBounds:CGRectMake(0.0, 0.0, aSize.width, aSize.height)]; + + [self addSublayer:_imageLayer]; + } + return self; +} + + +#pragma mark - +#pragma mark Setter Getter methods + +/*! Set the bounds of the layer. The imageLayer will be at the center of this bounds + @param aRect +*/ +- (void)setBounds:(CGRect)aRect +{ + [super setBounds:aRect]; + + [_imageLayer setPosition:CGPointMake(CGRectGetMidX(aRect), CGRectGetMidY(aRect))]; +} + +/*! Set the rotation of the imageLayer + @param radians +*/ +- (void)setRotationRadians:(float)radians +{ + if (_rotationRadians == radians) + return; + + _rotationRadians = radians; + + [_imageLayer setAffineTransform:CGAffineTransformScale( + CGAffineTransformMakeRotation(_rotationRadians), + 1.0, 1.0)]; +} + +- (void)setBackgroundHandColor:(CPColor)aColor +{ + [_imageLayer setBackgroundColor:aColor]; +} + +- (void)setEnabled:(BOOL)aBoolean +{ + _isEnabled = aBoolean; + [self setNeedsDisplay]; +} + +@end diff --git a/AppKit/CPDatePicker/_CPDatePickerTextField.j b/AppKit/CPDatePicker/_CPDatePickerTextField.j new file mode 100644 index 000000000..6681631af --- /dev/null +++ b/AppKit/CPDatePicker/_CPDatePickerTextField.j @@ -0,0 +1,1444 @@ +/* _CPDatePickerTextField.j +* AppKit +* +* Created by Alexandre Wilhelm +* Copyright 2012 +* +* 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 "CPControl.j" +@import "CPFont.j" +@import "CPTextField.j" + +@import +@import +@import +@import +@import + +@class CPDatePicker +@class CPStepper + +@global CPSingleDateMode +@global CPRangeDateMode + +@global CPTextFieldAndStepperDatePickerStyle +@global CPClockAndCalendarDatePickerStyle +@global CPTextFieldDatePickerStyle + +@global CPHourMinuteDatePickerElementFlag +@global CPHourMinuteSecondDatePickerElementFlag +@global CPTimeZoneDatePickerElementFlag +@global CPYearMonthDatePickerElementFlag +@global CPYearMonthDayDatePickerElementFlag +@global CPEraDatePickerElementFlag + +var CPDatePickerElementTextFieldBecomeFirstResponder = @"CPDatePickerElementTextFieldBecomeFirstResponder", + CPDatePickerElementTextFieldAMPMChangedNotification = @"CPDatePickerElementTextFieldAMPMChangedNotification"; + +var CPZeroKeyCode = 48, + CPNineKeyCode = 57, + CPMajAKeyCode = 65, + CPMajPKeyCode = 80, + CPAKeyCode = 97, + CPPKeyCode = 112; + +// This class is used to represente the datePicker with the CPTextFieldAndStepperDatePickerStyle/CPTextFieldDatePickerStyle mode +@implementation _CPDatePickerTextField : CPControl +{ + _CPDatePickerElementTextField _firstTextField @accessors(property=firstTextField); + _CPDatePickerElementTextField _lastTextField @accessors(property=lastTextField); + + _CPDatePickerElementTextField _currentTextField; + _CPDatePickerElementView _datePickerElementView; + CPDatePicker _datePicker; + CPStepper _stepper; + CPTimer _timerEdition; +} + + +#pragma mark - +#pragma mark Init + +- (id)initWithFrame:(CGRect)aFrame withDatePicker:(CPDatePicker)aDatePicker +{ + if (self = [super initWithFrame:aFrame]) + { + _datePicker = aDatePicker + [self _init]; + } + return self; +} + +- (void)_init +{ + _datePickerElementView = [[_CPDatePickerElementView alloc] initWithFrame:CGRectMakeZero() withDatePicker:_datePicker]; + [self addSubview:_datePickerElementView]; + + _stepper = [CPStepper stepper]; + [_stepper setTarget:self]; + [_stepper setAction:@selector(_clickStepper:)]; + [self addSubview:_stepper]; + + [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_datePickerElementTextFieldBecomeFirstResponder:) name:CPDatePickerElementTextFieldBecomeFirstResponder object:self]; + + [self setNeedsLayout]; + [self setNeedsDisplay:YES]; +} + + +#pragma mark - +#pragma mark Responder methods + +- (BOOL)becomeFirstResponder +{ + return NO; +} + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (BOOL)resignFirstResponder +{ + // End the timer of editing + [self _endTimer]; + + // Don't forget to unbind, otherwise several steppers will increase or decrease + [_currentTextField unbind:@"objectValue"]; + [_currentTextField makeDeselectable]; + _currentTextField = nil + + // This is usefull when clicking on the stepper when the datePicker is not selected + [_stepper setObjectValue:0]; + + return YES; +} + + +#pragma mark - +#pragma mark Setter Getter methods + + +/*! Set the value of the control + @param aDateValue +*/ +- (void)setDateValue:(CPDate)aDateValue +{ + [_datePickerElementView setDateValue:aDateValue]; +} + +/*! Set the widget enabled or not + @param aBoolean +*/ +- (void)setEnabled:(BOOL)aBoolean +{ + [super setEnabled:aBoolean]; + [_stepper setEnabled:aBoolean]; + [_datePickerElementView setEnabled:aBoolean]; +} + + +#pragma mark - +#pragma mark Notification methods + +/*! This is called to when the user just changed the selected textField + @param aNotification +*/ +- (void)_datePickerElementTextFieldBecomeFirstResponder:(CPNotification)aNotification +{ + if ([[aNotification userInfo] objectForKey:@"textField"] == _currentTextField) + return; + + [self _selectTextField:[[aNotification userInfo] objectForKey:@"textField"]]; + + // This is tricky, its to avoid to have the cursor + if ([[self window] firstResponder] != _datePicker) + [[self window] makeFirstResponder:_datePicker]; +} + + +#pragma mark - +#pragma mark SelectTextField action + +- (void)_selecteTextFieldWithFlags:(unsigned)flags +{ + // We select the firstTextField when the datePicker becomes firstResponder if _currentTextField is null. It can be null just when using tab + if (!_currentTextField) + { + if (flags & CPShiftKeyMask) + [self _selectTextField:_lastTextField]; + else + [self _selectTextField:_firstTextField]; + } + +} + +/*! Select a textField + @param aDatePickerElementTextField the textField +*/ +- (void)_selectTextField:(_CPDatePickerElementTextField)aDatePickerElementTextField +{ + if (_currentTextField == aDatePickerElementTextField) + return; + + // End the timer of editing + [self _endTimer]; + + // Don't forget to unbind, otherwise several steppers will increase or decrease + [_currentTextField unbind:@"objectValue"]; + [_currentTextField makeDeselectable]; + + _currentTextField = aDatePickerElementTextField; + [_currentTextField makeSelectable]; + + // We cannot assign a value with the textField AM/PM + if ([_currentTextField dateType] != CPAMPMDateType) + { + // We update the value of the stepper dependind on the textField + [_stepper setObjectValue:parseInt([_currentTextField objectValue])]; + [_stepper setMaxValue:[_currentTextField maxNumber]]; + [_stepper setMinValue:[_currentTextField minNumber]]; + + // We bind the stepper with textField + [_currentTextField bind:@"objectValue" toObject:_stepper withKeyPath:@"objectValue" options:nil]; + } +} + + +#pragma mark - +#pragma mark Events + +/*! Called when the user click on the stepper +*/ +- (void)_clickStepper:(id)sender +{ + // Success when clicking on the stepper if the datePicker is not selected + if ([[self window] firstResponder] != _datePicker || !_currentTextField) + { + var isUp = NO; + + if ([sender objectValue] == 1) + isUp = YES; + + [self _selectTextField:_firstTextField]; + [[self window] makeFirstResponder:_datePicker]; + + // This gonna update the dateValue with the binding + if (isUp) + [_stepper setDoubleValue:parseInt([_currentTextField objectValue]) + 1]; + else + [_stepper setDoubleValue:parseInt([_currentTextField objectValue]) - 1]; + + return; + } + + if ([_currentTextField dateType] != CPAMPMDateType) + { + // Make sure to get the good value, especially when we reach the maxDate or minDate + [sender setDoubleValue:parseInt([_currentTextField objectValue])]; + } + else + { + // AM/PM behavior + if ([[_currentTextField stringValue] isEqualToString:@"PM"]) + [_currentTextField setStringValue:@"AM"]; + else + [_currentTextField setStringValue:@"PM"]; + + [[CPNotificationCenter defaultCenter] postNotificationName:CPDatePickerElementTextFieldAMPMChangedNotification object:_currentTextField userInfo:nil]; + } +} + +/*! performKeyEquivalent event + Used for moving in the textField +*/ +- (BOOL)performKeyEquivalent:(CPEvent)anEvent +{ + if (![self isEnabled] || !_currentTextField || [[self window] firstResponder] != _datePicker) + return NO; + + var key = [anEvent charactersIgnoringModifiers]; + + if (key == CPUpArrowFunctionKey) + { + [self _endTimer]; + [_stepper setDoubleValue:parseInt([_currentTextField objectValue])]; + [_stepper performClickUp:self]; + return YES; + } + + if (key == CPDownArrowFunctionKey) + { + [self _endTimer]; + [_stepper setDoubleValue:parseInt([_currentTextField objectValue])]; + [_stepper performClickDown:self]; + return YES; + } + + if (key == CPLeftArrowFunctionKey || [anEvent keyCode] == CPTabKeyCode && [anEvent modifierFlags] & CPShiftKeyMask) + { + if (_currentTextField == _firstTextField && [anEvent keyCode] == CPTabKeyCode) + { + if ([_datePicker previousKeyView]) + [[self window] makeFirstResponder:[_datePicker previousKeyView]]; + + return YES; + } + + [self _selectTextField:[_currentTextField previousKeyView]]; + return YES; + } + + if (key == CPRightArrowFunctionKey || [anEvent keyCode] == CPTabKeyCode) + { + + if (_currentTextField == _lastTextField && [anEvent keyCode] == CPTabKeyCode) + { + if ([_datePicker nextKeyView]) + [[self window] makeFirstResponder:[_datePicker nextKeyView]]; + + return YES; + } + + [self _selectTextField:[_currentTextField nextKeyView]]; + return YES; + } + + if ([anEvent keyCode] == CPReturnKeyCode && _timerEdition) + { + [_timerEdition fire]; + return YES; + } + + return NO; +} + +/*! KeyDown event + We just care care about the event A/P and every numbers +*/ +- (void)keyDown:(CPEvent)anEvent +{ + if (![self isEnabled]) + return; + + if ([_datePicker _isEnglishFormat] && [_currentTextField dateType] == CPAMPMDateType && ([anEvent keyCode] == CPAKeyCode || [anEvent keyCode] == CPPKeyCode || [anEvent keyCode] == CPMajAKeyCode || [anEvent keyCode] == CPMajPKeyCode)) + { + if ([anEvent keyCode] == CPAKeyCode || [anEvent keyCode] == CPMajAKeyCode) + [_currentTextField setStringValue:@"AM"]; + else + [_currentTextField setStringValue:@"PM"]; + + [[CPNotificationCenter defaultCenter] postNotificationName:CPDatePickerElementTextFieldAMPMChangedNotification object:_currentTextField userInfo:nil]; + + return; + } + + if ([anEvent keyCode] != CPDeleteKeyCode && [anEvent keyCode] != CPDeleteForwardKeyCode && [anEvent keyCode] < CPZeroKeyCode || [anEvent keyCode] > CPNineKeyCode) + return; + + // Here, at the first editing we launch a timer to auto-finish the editing. There is another behavior when the user has already edited something + if (!_timerEdition) + { + _timerEdition = [CPTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(_timerKeyEvent:) userInfo:nil repeats:NO]; + + // Take care about the delete key + if ([anEvent keyCode] == CPDeleteKeyCode || [anEvent keyCode] == CPDeleteForwardKeyCode) + [_currentTextField setStringKeyValue:@""]; + else + [_currentTextField setStringKeyValue:[anEvent characters]]; + } + else + { + var newFireDate = [CPDate date], + key; + + newFireDate.setSeconds(newFireDate.getSeconds() + 2); + + [_timerEdition setFireDate:newFireDate]; + + // Take care about the delete key + if ([anEvent keyCode] == CPDeleteKeyCode || [anEvent keyCode] == CPDeleteForwardKeyCode) + key = [[_currentTextField stringValue] substringToIndex:[[_currentTextField stringValue] length] - 1]; + else + key = [CPString stringWithFormat:@"%i%i",parseInt([_currentTextField stringValue]), parseInt([anEvent characters])]; + + [_currentTextField setStringKeyValue:key]; + } +} + + +#pragma mark - +#pragma mark Timer event + +/*! End of the timer +*/ +- (void)_timerKeyEvent:(id)sender +{ + _timerEdition = nil; + + if (![[_currentTextField stringValue] isEqualToString:@" "] && ![[_currentTextField stringValue] isEqualToString:@" "]) + { + var value = [_currentTextField stringValue]; + + if ([_datePicker _isEnglishFormat] && [_currentTextField dateType] == CPHourDateType) + { + if (![_datePickerElementView _isAMHour] && value != 12) + value = parseInt(value) + 12; + + if (value == 12 && ![_datePickerElementView _isAMHour]) + value = 12; + else if (value == 12) + value = 0; + } + + [_currentTextField setObjectValue:value]; + } + else + { + [_currentTextField setObjectValue:@"0"]; + } + + +} + +/*! We force to end the timer +*/ +- (void)_endTimer +{ + if (_timerEdition) + { + [_timerEdition invalidate]; + [self _timerKeyEvent:_timerEdition]; + _timerEdition = nil; + } +} + + +#pragma mark - +#pragma mark Layout methods + +/*! Layout the subviews +*/ +- (void)layoutSubviews +{ + if ([_datePicker datePickerStyle] == CPClockAndCalendarDatePickerStyle) + return; + + [super layoutSubviews]; + + var frameSize = CGSizeMakeZero(), + bezelInset = [_datePicker valueForThemeAttribute:@"bezel-inset" inState:[_datePicker themeState]]; + + // Check the mode to display or not the stepper + if ([_datePicker datePickerStyle] == CPTextFieldAndStepperDatePickerStyle) + { + frameSize = CGSizeMake(CGRectGetWidth([_datePicker frame]) - CGRectGetWidth([_stepper frame]) - [_datePicker valueForThemeAttribute:@"stepper-margin"], CGRectGetHeight([_datePicker frame])); + + frameSize.width -= bezelInset.left; + frameSize.height -= bezelInset.top + bezelInset.bottom; + + [_datePickerElementView setFrameSize:frameSize]; + [_datePickerElementView setFrameOrigin:CGPointMake(bezelInset.left, bezelInset.top)]; + [_stepper setHidden:NO]; + } + else if ([_datePicker datePickerStyle] == CPTextFieldDatePickerStyle) + { + frameSize = CGSizeMake(CGRectGetWidth([_datePicker frame]), CGRectGetHeight([_datePicker frame])); + + frameSize.width -= bezelInset.left + bezelInset.right; + frameSize.height -= bezelInset.top + bezelInset.bottom; + + [_datePickerElementView setFrameSize:frameSize]; + [_datePickerElementView setFrameOrigin:CGPointMake(bezelInset.left, bezelInset.top)]; + [_stepper setHidden:YES]; + } + + [_stepper setFrameOrigin:CGPointMake(CGRectGetMaxX([_datePickerElementView frame]) + [_datePicker valueForThemeAttribute:@"stepper-margin"], bezelInset.top + CGRectGetHeight([_datePickerElementView frame]) / 2 - CGRectGetHeight([_stepper frame]) / 2)]; + + [_datePickerElementView setNeedsLayout]; +} + +@end + + +/*! This class is used to display the elements (all of the textFields) in the datePicker +*/ +@implementation _CPDatePickerElementView : CPControl +{ + _CPDatePickerElementTextField _textFieldDay; + _CPDatePickerElementTextField _textFieldMonth; + _CPDatePickerElementTextField _textFieldYear; + _CPDatePickerElementTextField _textFieldHour; + _CPDatePickerElementTextField _textFieldMinute; + _CPDatePickerElementTextField _textFieldSecond; + _CPDatePickerElementTextField _textFieldPMAM; + CPDatePicker _datePicker; + CPTextField _textFieldSeparatorOne; + CPTextField _textFieldSeparatorTwo; + CPTextField _textFieldSeparatorThree; + CPTextField _textFieldSeparatorFour; +} + + +#pragma mark - +#pragma mark Init + +- (id)initWithFrame:(CGRect)aFrame withDatePicker:(CPDatePicker)aDatePicker +{ + if (self = [super init]) + { + _datePicker = aDatePicker; + [self _init]; + } + return self; +} + +- (void)_init +{ + _textFieldDay = [_CPDatePickerElementTextField new]; + [_textFieldDay setBezeled:NO]; + [_textFieldDay setBordered:NO]; + [_textFieldDay setDateType:CPDayDateType]; + [_textFieldDay setDatePicker:_datePicker]; + [_textFieldDay setAlignment:CPRightTextAlignment]; + [self addSubview:_textFieldDay]; + + _textFieldMonth = [_CPDatePickerElementTextField new]; + [_textFieldMonth setBezeled:NO]; + [_textFieldMonth setBordered:NO]; + [_textFieldMonth setDateType:CPMonthDateType]; + [_textFieldMonth setDatePicker:_datePicker]; + [_textFieldMonth setAlignment:CPRightTextAlignment]; + [self addSubview:_textFieldMonth]; + + _textFieldYear = [_CPDatePickerElementTextField new]; + [_textFieldYear setBezeled:NO]; + [_textFieldYear setBordered:NO]; + [_textFieldYear setDateType:CPYearDateType]; + [_textFieldYear setDatePicker:_datePicker]; + [_textFieldYear setAlignment:CPRightTextAlignment]; + [self addSubview:_textFieldYear]; + + _textFieldHour = [_CPDatePickerElementTextField new]; + [_textFieldHour setBezeled:NO]; + [_textFieldHour setBordered:NO]; + [_textFieldHour setDateType:CPHourDateType]; + [_textFieldHour setDatePicker:_datePicker]; + [_textFieldHour setAlignment:CPRightTextAlignment]; + [self addSubview:_textFieldHour]; + + _textFieldMinute = [_CPDatePickerElementTextField new]; + [_textFieldMinute setBezeled:NO]; + [_textFieldMinute setBordered:NO]; + [_textFieldMinute setDateType:CPMinuteDateType]; + [_textFieldMinute setDatePicker:_datePicker]; + [_textFieldMinute setAlignment:CPRightTextAlignment]; + [self addSubview:_textFieldMinute]; + + _textFieldSecond = [_CPDatePickerElementTextField new]; + [_textFieldSecond setBezeled:NO]; + [_textFieldSecond setBordered:NO]; + [_textFieldSecond setDateType:CPSecondDateType]; + [_textFieldSecond setDatePicker:_datePicker]; + [_textFieldSecond setAlignment:CPRightTextAlignment]; + [self addSubview:_textFieldSecond]; + + _textFieldPMAM = [_CPDatePickerElementTextField new]; + [_textFieldPMAM setBezeled:NO]; + [_textFieldPMAM setBordered:NO]; + [_textFieldPMAM setDateType:CPAMPMDateType]; + [_textFieldPMAM setDatePicker:_datePicker]; + [_textFieldPMAM setAlignment:CPRightTextAlignment]; + [self addSubview:_textFieldPMAM]; + + _textFieldSeparatorOne = [CPTextField labelWithTitle:@"/"]; + _textFieldSeparatorTwo = [CPTextField labelWithTitle:@"/"]; + _textFieldSeparatorThree = [CPTextField labelWithTitle:@":"]; + _textFieldSeparatorFour = [CPTextField labelWithTitle:@":"]; + + [self addSubview: _textFieldSeparatorOne]; + [self addSubview: _textFieldSeparatorTwo]; + [self addSubview: _textFieldSeparatorThree]; + [self addSubview: _textFieldSeparatorFour]; + + [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_datePickerElementTextFieldAMPMChangedNotification:) name:CPDatePickerElementTextFieldAMPMChangedNotification object:_textFieldPMAM]; + + [self setNeedsLayout]; +} + + +#pragma mark - +#pragma mark Responder methods + +- (BOOL)acceptFirstResponder +{ + return NO; +} + + +#pragma mark - +#pragma mark Setter Getter methods + +/*! Set the value of the textFields + @param aDateValue the value +*/ +- (void)setDateValue:(CPDate)aDateValue +{ + [_textFieldDay setStringValue:[CPString stringWithFormat:@"%i", aDateValue.getDate()]]; + [_textFieldMonth setStringValue:[CPString stringWithFormat:@"%i", aDateValue.getMonth() + 1]]; + [_textFieldYear setStringValue:[CPString stringWithFormat:@"%i", aDateValue.getFullYear()]]; + [_textFieldHour setStringValue:[CPString stringWithFormat:@"%i", aDateValue.getHours()]]; + [_textFieldMinute setStringValue:[CPString stringWithFormat:@"%i", aDateValue.getMinutes()]]; + [_textFieldSecond setStringValue:[CPString stringWithFormat:@"%i", aDateValue.getSeconds()]]; + + if (aDateValue.getHours() > 11) + [_textFieldPMAM setStringValue:@"PM"]; + else + [_textFieldPMAM setStringValue:@"AM"]; +} + + +/*! Set the widget enabled or not + @param aBoolean +*/ +- (void)setEnabled:(BOOL)aBoolean +{ + [super setEnabled:aBoolean]; + [_textFieldDay setEnabled:aBoolean]; + [_textFieldMonth setEnabled:aBoolean]; + [_textFieldYear setEnabled:aBoolean]; + [_textFieldHour setEnabled:aBoolean]; + [_textFieldMinute setEnabled:aBoolean]; + [_textFieldSecond setEnabled:aBoolean]; + [_textFieldSeparatorOne setEnabled:aBoolean]; + [_textFieldSeparatorTwo setEnabled:aBoolean]; + [_textFieldSeparatorThree setEnabled:aBoolean]; + [_textFieldSeparatorFour setEnabled:aBoolean]; + [_textFieldPMAM setEnabled:aBoolean]; +} + +/*! Return YES if the hour is set to the morning +*/ +- (BOOL)_isAMHour +{ + return [[_textFieldPMAM stringValue] isEqualToString:@"AM"]; +} + + +#pragma mark - +#pragma mark Notification methods + +/*! Called when changing AM or PM + @param aNotification +*/ +- (void)_datePickerElementTextFieldAMPMChangedNotification:(CPNotification)aNotification +{ + var value = [[aNotification object] stringValue], + dateValue = [[_datePicker dateValue] copy]; + + if ([value isEqualToString:@"PM"]) + { + if (dateValue.getHours() <= 11) + dateValue.setHours(dateValue.getHours() + 12); + } + else + { + if (dateValue.getHours() > 11) + dateValue.setHours(dateValue.getHours() - 12); + } + + [_datePicker setDateValue:dateValue]; +} + + +#pragma mark - +#pragma mark Layout methods + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + var themeState = [_datePicker themeState]; + + if ([_datePicker isBezeled] && [_datePicker drawsBackground] || [_datePicker isBordered] && [_datePicker drawsBackground]) + [self setBackgroundColor:[_datePicker valueForThemeAttribute:@"bezel-color" inState:themeState]]; + else if ([_datePicker drawsBackground]) + [self setBackgroundColor:[_datePicker backgroundColor]]; + else + [self setBackgroundColor:[CPColor clearColor]]; + + [self _themeTextFields]; + + [self _updateResponderTextField]; + [self _updateHiddenTextFields]; + [self _sizeToFit]; + [self _updatePositions]; + + [self setNeedsDisplay:YES]; +} + +- (void)drawRect:(CGRect)aRect +{ + [super drawRect:aRect]; + + if (([_datePicker isBordered] || [_datePicker isBezeled]) && ![_datePicker drawsBackground]) + { + var context = [[CPGraphicsContext currentContext] graphicsPort], + borderWidth = [_datePicker valueForThemeAttribute:@"border-width"] / 2, + bezelInset = [_datePicker valueForThemeAttribute:@"bezel-inset" inState:[_datePicker themeState]]; + + CGContextBeginPath(context); + CGContextSetStrokeColor(context, [_datePicker valueForThemeAttribute:@"border-color" inState:[_datePicker themeState]]); + CGContextSetLineWidth(context, [_datePicker valueForThemeAttribute:@"border-width"]); + + CGContextMoveToPoint(context, borderWidth - bezelInset.left, borderWidth); + CGContextAddLineToPoint(context, [self bounds].size.width + bezelInset.left - borderWidth, borderWidth); + CGContextAddLineToPoint(context, [self bounds].size.width + bezelInset.left - borderWidth, [self bounds].size.height - borderWidth); + CGContextAddLineToPoint(context, borderWidth - bezelInset.left, [self bounds].size.height - borderWidth); + CGContextAddLineToPoint(context, borderWidth - bezelInset.left, borderWidth); + + CGContextStrokePath(context); + CGContextClosePath(context); + } + +} + +/*! Theme the textFields depending of the theme of the datePicker +*/ +- (void)_themeTextFields +{ + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"min-size-datepicker-textfield"] forThemeAttribute:@"min-size"]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateSelected] forThemeAttribute:@"bezel-color" inState:CPThemeStateSelected]; + [_textFieldDay setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateSelected]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateSelected]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateNormal] forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal]; + [_textFieldDay setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldDay setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled]; + [_textFieldDay setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldDay setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"min-size-datepicker-textfield"] forThemeAttribute:@"min-size"]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateSelected] forThemeAttribute:@"bezel-color" inState:CPThemeStateSelected]; + [_textFieldMonth setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateSelected]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateSelected]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateNormal] forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal]; + [_textFieldMonth setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldMonth setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled]; + [_textFieldMonth setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldMonth setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"min-size-datepicker-textfield"] forThemeAttribute:@"min-size"]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateSelected] forThemeAttribute:@"bezel-color" inState:CPThemeStateSelected]; + [_textFieldYear setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateSelected]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateSelected]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateNormal] forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal]; + [_textFieldYear setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldYear setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled]; + [_textFieldYear setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldYear setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"min-size-datepicker-textfield"] forThemeAttribute:@"min-size"]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateSelected] forThemeAttribute:@"bezel-color" inState:CPThemeStateSelected]; + [_textFieldHour setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateSelected]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateSelected]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateNormal] forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal]; + [_textFieldHour setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldHour setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled]; + [_textFieldHour setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldHour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"min-size-datepicker-textfield"] forThemeAttribute:@"min-size"]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateSelected] forThemeAttribute:@"bezel-color" inState:CPThemeStateSelected]; + [_textFieldMinute setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateSelected]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateSelected]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateNormal] forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal]; + [_textFieldMinute setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldMinute setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled]; + [_textFieldMinute setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldMinute setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"min-size-datepicker-textfield"] forThemeAttribute:@"min-size"]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateSelected] forThemeAttribute:@"bezel-color" inState:CPThemeStateSelected]; + [_textFieldSecond setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateSelected]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateSelected]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateNormal] forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal]; + [_textFieldSecond setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldSecond setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled]; + [_textFieldSecond setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldSecond setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"min-size-datepicker-textfield"] forThemeAttribute:@"min-size"]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateSelected] forThemeAttribute:@"bezel-color" inState:CPThemeStateSelected]; + [_textFieldPMAM setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateSelected]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateSelected]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateSelected]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateSelected]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateNormal] forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal]; + [_textFieldPMAM setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldPMAM setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"datepicker-textfield-bezel-color" inState:CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled]; + [_textFieldPMAM setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldPMAM setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldSeparatorOne setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield-separator" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldSeparatorOne setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield-separator" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldSeparatorOne setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldSeparatorOne setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldSeparatorOne setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldSeparatorOne setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldSeparatorOne setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldSeparatorOne setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldSeparatorOne setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldSeparatorOne setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldSeparatorTwo setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield-separator" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldSeparatorTwo setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield-separator" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldSeparatorTwo setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldSeparatorTwo setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldSeparatorTwo setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldSeparatorTwo setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldSeparatorTwo setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldSeparatorTwo setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldSeparatorTwo setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldSeparatorTwo setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldSeparatorThree setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield-separator" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldSeparatorThree setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield-separator" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldSeparatorThree setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldSeparatorThree setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldSeparatorThree setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldSeparatorThree setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldSeparatorThree setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldSeparatorThree setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldSeparatorThree setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldSeparatorThree setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + + [_textFieldSeparatorFour setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield-separator" inState:CPThemeStateNormal] forThemeAttribute:@"content-inset" inState:CPThemeStateNormal]; + [_textFieldSeparatorFour setValue:[_datePicker valueForThemeAttribute:@"content-inset-datepicker-textfield-separator" inState:CPThemeStateSelected] forThemeAttribute:@"content-inset" inState:CPThemeStateSelected]; + [_textFieldSeparatorFour setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateNormal]; + [_textFieldSeparatorFour setValue:[_datePicker textColor] forThemeAttribute:@"text-color" inState:CPThemeStateNormal]; + [_textFieldSeparatorFour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal]; + [_textFieldSeparatorFour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal]; + [_textFieldSeparatorFour setValue:[_datePicker textFont] forThemeAttribute:@"font" inState:CPThemeStateDisabled]; + [_textFieldSeparatorFour setValue:[_datePicker valueForThemeAttribute:@"text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled]; + [_textFieldSeparatorFour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled]; + [_textFieldSeparatorFour setValue:[_datePicker valueForThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled]; + +} + +/*! Hide or not the textField depending on the datePickerElements flag +*/ +- (void)_updateHiddenTextFields +{ + var datePickerElements = [_datePicker datePickerElements], + isEnglishFormat = [_datePicker _isEnglishFormat]; + + if (datePickerElements & CPYearMonthDatePickerElementFlag) + { + [_textFieldDay setHidden:YES]; + [_textFieldMonth setHidden:NO]; + [_textFieldYear setHidden:NO]; + [_textFieldSeparatorTwo setHidden:NO]; + [_textFieldSeparatorOne setHidden:YES]; + + if (([datePickerElements & CPYearMonthDayDatePickerElementFlag]) == CPYearMonthDayDatePickerElementFlag) + { + [_textFieldDay setHidden:NO]; + [_textFieldSeparatorOne setHidden:NO]; + } + } + else + { + [_textFieldMonth setHidden:YES]; + [_textFieldYear setHidden:YES]; + [_textFieldDay setHidden:YES]; + [_textFieldSeparatorTwo setHidden:YES]; + [_textFieldSeparatorOne setHidden:YES]; + } + + if (datePickerElements & CPHourMinuteDatePickerElementFlag) + { + [_textFieldHour setHidden:NO]; + [_textFieldMinute setHidden:NO]; + [_textFieldSecond setHidden:YES]; + [_textFieldSeparatorThree setHidden:NO]; + [_textFieldSeparatorFour setHidden:YES]; + + if (isEnglishFormat) + [_textFieldPMAM setHidden:NO]; + else + [_textFieldPMAM setHidden:YES]; + + if ((datePickerElements & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag) + { + [_textFieldSecond setHidden:NO]; + [_textFieldSeparatorFour setHidden:NO]; + } + } + else + { + [_textFieldHour setHidden:YES]; + [_textFieldMinute setHidden:YES]; + [_textFieldSecond setHidden:YES]; + [_textFieldSeparatorThree setHidden:YES]; + [_textFieldSeparatorFour setHidden:YES]; + [_textFieldPMAM setHidden:YES]; + } +} + +/*! Update the position of the textField depending on the datePickerElements flag +*/ +- (void)_updatePositions +{ + var contentInset = [_datePicker valueForThemeAttribute:@"content-inset" inState:[_datePicker themeState]], + separatorContentInset = [_datePicker valueForThemeAttribute:@"separator-content-inset"], + horizontalInset = contentInset.left - contentInset.right, + verticalInset = contentInset.top - contentInset.bottom, + firstTexField = _textFieldMonth, + secondTextField = _textFieldDay, + isEnglishFormat = [_datePicker _isEnglishFormat]; + + if (!isEnglishFormat) + { + firstTexField = _textFieldDay; + secondTextField = _textFieldMonth; + } + + [firstTexField setFrameOrigin:CGPointMake(horizontalInset,verticalInset)]; + [_textFieldSeparatorOne setFrameOrigin:CGPointMake(CGRectGetMaxX([firstTexField frame]) + separatorContentInset.left, verticalInset)]; + + if ([firstTexField isHidden]) + [secondTextField setFrameOrigin:CGPointMake(horizontalInset,verticalInset)]; + else + [secondTextField setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldSeparatorOne frame]) + separatorContentInset.right, verticalInset)]; + + if (isEnglishFormat && [secondTextField isHidden]) + [_textFieldSeparatorTwo setFrameOrigin:CGPointMake(CGRectGetMaxX([firstTexField frame]) + separatorContentInset.left, verticalInset)]; + else + [_textFieldSeparatorTwo setFrameOrigin:CGPointMake(CGRectGetMaxX([secondTextField frame]) + separatorContentInset.left, verticalInset)]; + + [_textFieldYear setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldSeparatorTwo frame]) + separatorContentInset.right, verticalInset)]; + + if ([_textFieldMonth isHidden]) + [_textFieldHour setFrameOrigin:CGPointMake(horizontalInset, verticalInset)]; + else + [_textFieldHour setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldYear frame]) + [_datePicker valueForThemeAttribute:@"date-hour-margin"],verticalInset)]; + + [_textFieldSeparatorThree setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldHour frame]) + separatorContentInset.left, verticalInset)]; + [_textFieldMinute setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldSeparatorThree frame]) + separatorContentInset.right, verticalInset)]; + [_textFieldSeparatorFour setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldMinute frame]) + separatorContentInset.left, verticalInset)]; + [_textFieldSecond setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldSeparatorFour frame]) + separatorContentInset.right, verticalInset)]; + + if ([_textFieldSecond isHidden]) + [_textFieldPMAM setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldMinute frame]) + 2, verticalInset)]; + else + [_textFieldPMAM setFrameOrigin:CGPointMake(CGRectGetMaxX([_textFieldSecond frame]) + 2, verticalInset)]; +} + +/*! Size to fit all of the textFields +*/ +- (void)_sizeToFit +{ + [_textFieldDay sizeToFit]; + [_textFieldMonth sizeToFit]; + [_textFieldYear sizeToFit]; + [_textFieldHour sizeToFit]; + [_textFieldMinute sizeToFit]; + [_textFieldSecond sizeToFit]; + [_textFieldSeparatorOne sizeToFit]; + [_textFieldSeparatorTwo sizeToFit]; + [_textFieldSeparatorThree sizeToFit]; + [_textFieldSeparatorFour sizeToFit]; + [_textFieldPMAM sizeToFit]; +} + + +#pragma mark - +#pragma mark Responder methods + +- (void)_updateResponderTextField +{ + [self _updateFirstLastTextField]; + [self _updateKeyView]; +} + +/*! Update the var _firstTextField and _lastTextField +*/ +- (void)_updateFirstLastTextField +{ + var datePickerElements = [_datePicker datePickerElements]; + + if ([_datePicker _isEnglishFormat]) + { + if (datePickerElements & CPYearMonthDayDatePickerElementFlag || datePickerElements & CPYearMonthDatePickerElementFlag) + [[self superview] setFirstTextField:_textFieldMonth]; + else + [[self superview] setFirstTextField:_textFieldHour]; + + if (datePickerElements & CPHourMinuteSecondDatePickerElementFlag || datePickerElements & CPHourMinuteDatePickerElementFlag) + [[self superview] setLastTextField:_textFieldPMAM]; + else + [[self superview] setLastTextField:_textFieldYear]; + } + else + { + if ((datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag) + [[self superview] setFirstTextField:_textFieldDay]; + else if (datePickerElements & CPYearMonthDayDatePickerElementFlag || datePickerElements & CPYearMonthDatePickerElementFlag) + [[self superview] setFirstTextField:_textFieldMonth]; + else + [[self superview] setFirstTextField:_textFieldHour]; + + if ((datePickerElements & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag) + [[self superview] setLastTextField:_textFieldSecond]; + else if (datePickerElements & CPHourMinuteSecondDatePickerElementFlag || datePickerElements & CPHourMinuteDatePickerElementFlag) + [[self superview] setLastTextField:_textFieldMinute]; + else + [[self superview] setLastTextField:_textFieldYear]; + } +} + +/*! Update the nextTextField params of all of the textField. This is used to move the current textField with the arrows +*/ +- (void)_updateKeyView +{ + var datePickerElements = [_datePicker datePickerElements], + firstTexField = _textFieldMonth, + secondTextField = _textFieldDay, + isEnglishFormat = [_datePicker _isEnglishFormat]; + + if (!isEnglishFormat) + { + firstTexField = _textFieldDay; + secondTextField = _textFieldMonth; + } + + if ((datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag) + [firstTexField setNextKeyView:secondTextField]; + else + [firstTexField setNextKeyView:_textFieldYear]; + + [secondTextField setNextKeyView:_textFieldYear]; + + if (datePickerElements & CPHourMinuteSecondDatePickerElementFlag || datePickerElements & CPHourMinuteDatePickerElementFlag) + [_textFieldYear setNextKeyView:_textFieldHour]; + else if (isEnglishFormat || (datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag) + [_textFieldYear setNextKeyView:firstTexField]; + else + [_textFieldYear setNextKeyView:secondTextField]; + + [_textFieldHour setNextKeyView:_textFieldMinute]; + + if ((datePickerElements & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag) + [_textFieldMinute setNextKeyView:_textFieldSecond]; + else if (isEnglishFormat) + [_textFieldMinute setNextKeyView:_textFieldPMAM]; + else if ((datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag) + [_textFieldMinute setNextKeyView:firstTexField]; + else if (datePickerElements & CPYearMonthDatePickerElementFlag) + [_textFieldMinute setNextKeyView:secondTextField]; + else + [_textFieldMinute setNextKeyView:_textFieldHour]; + + if (isEnglishFormat) + [_textFieldSecond setNextKeyView:_textFieldPMAM]; + else if ((datePickerElements & CPYearMonthDayDatePickerElementFlag) == CPYearMonthDayDatePickerElementFlag) + [_textFieldSecond setNextKeyView:firstTexField]; + else if (datePickerElements & CPYearMonthDatePickerElementFlag) + [_textFieldSecond setNextKeyView:secondTextField]; + else + [_textFieldSecond setNextKeyView:_textFieldHour]; + + if (datePickerElements & CPYearMonthDayDatePickerElementFlag) + [_textFieldPMAM setNextKeyView:_textFieldMonth]; + else + [_textFieldPMAM setNextKeyView:_textFieldHour]; +} + +@end + + +var CPMonthDateType = 0, + CPDayDateType = 1, + CPYearDateType = 2, + CPHourDateType = 3, + CPSecondDateType = 4, + CPMinuteDateType = 5, + CPAMPMDateType = 6; + +/*! An element textField +*/ +@implementation _CPDatePickerElementTextField : CPTextField +{ + CPDatePicker _datePicker @accessors(setter=setDatePicker:); + + int _dateType @accessors(getter=dateType); + int _maxNumber @accessors(getter=maxNumber); + int _minNumber @accessors(getter=minNumber); +} + + +#pragma mark - +#pragma mark Getter Setter methods + +- (BOOL)acceptFirstResponder +{ + return NO; +} + +/*! Set the dateType of the textField +*/ +- (void)setDateType:(int)aDateType +{ + _dateType = aDateType; + + switch (aDateType) + { + case CPMonthDateType: + _minNumber = 1; + _maxNumber = 12; + break; + + case CPDayDateType: + _minNumber = 1; + _maxNumber = 31; + break; + + case CPYearDateType: + _minNumber = 0; + _maxNumber = 9999; + break; + + case CPHourDateType: + _minNumber = 0; + _maxNumber = 23; + break; + + case CPSecondDateType: + _minNumber = 0; + _maxNumber = 59; + break; + + case CPMinuteDateType: + _minNumber = 0; + _maxNumber = 59; + break; + } +} + +/*! Return the maxNumber of the textField +*/ +- (int)maxNumber +{ + if (_dateType == CPDayDateType) + return [[_datePicker dateValue] _daysInMonth]; + + return _maxNumber; +} + +/*! Return the maxNumber of the textField depending of the maxDate +*/ +- (int)_maxNumberWithMaxDate +{ + var maxDate = [_datePicker maxDate], + date = [_datePicker dateValue]; + + if (maxDate) + { + switch (_dateType) + { + case CPMonthDateType: + if (maxDate.getFullYear() == date.getFullYear()) + return maxDate.getMonth(); + break; + + case CPDayDateType: + if (maxDate.getFullYear() == date.getFullYear() && maxDate.getMonth() == date.getMonth()) + return maxDate.getDate(); + break; + + case CPYearDateType: + return maxDate.getFullYear(); + + case CPHourDateType: + if (maxDate.getFullYear() == date.getFullYear() && maxDate.getMonth() == date.getMonth() && maxDate.getDate() == date.getDate()) + return maxDate.getHours(); + break; + + case CPSecondDateType: + if (maxDate.getFullYear() == date.getFullYear() && maxDate.getMonth() == date.getMonth() && maxDate.getDate() == date.getDate() && maxDate.getHours() == date.getHours() && maxDate.getMinutes() == date.getMinutes()) + return maxDate.getSeconds(); + break; + + case CPMinuteDateType: + if (maxDate.getFullYear() == date.getFullYear() && maxDate.getMonth() == date.getMonth() && maxDate.getDate() == date.getDate() && maxDate.getHours() == date.getHours()) + return maxDate.getMinutes(); + break; + } + } + + return _maxNumber; +} + +/*! Set the stringValue of the textField. This is going to check if there is 2 or 4 letters. If not it adds a space. Check also the maxDate + It's called when the user is editing with the keyboard + @param aStringValue a CPString +*/ +- (void)setStringKeyValue:(id)anObjectValue +{ + if (_dateType == CPYearDateType) + { + if ([anObjectValue length] > 4) + return + + while ([anObjectValue length] < 4) + anObjectValue = " " + anObjectValue; + } + else + { + if ([anObjectValue length] > 2) + return + + while ([anObjectValue length] < 2) + anObjectValue = " " + anObjectValue; + } + + if (parseInt(anObjectValue) > [self _maxNumberWithMaxDate]) + return; + + if ([_datePicker _isEnglishFormat] && _dateType == CPHourDateType && parseInt(anObjectValue) > 12) + return; + + [super setObjectValue:anObjectValue]; +} + +/*! Set the stringValue of the TextField. Add some zeros of there isn't 2/4 letters in the value. It's called at the end of the editing process + @param aStringValue a CPString +*/ +- (void)setStringValue:(id)aStringValue +{ + if (_dateType == CPYearDateType) + { + while ([aStringValue length] < 4) + aStringValue = "0" + aStringValue; + } + else if (_dateType != CPAMPMDateType) + { + if (_dateType == CPHourDateType && [_datePicker _isEnglishFormat]) + { + var value = parseInt(aStringValue); + + if (value == 0) + value = 12; + else if (value > 12) + value = value - 12; + + aStringValue = value.toString(); + } + + while ([aStringValue length] < 2) + aStringValue = "0" + aStringValue; + } + + [super setObjectValue:aStringValue]; +} + +/*! Set the objectValue. This will update the dateValue of the datePicker also. It's called with the binding of the stepper or arrows + This is not going to update the objectValue of the control !!! It updates the dateValue of the datePicker who's going to update the datePickerTextField if necessary + It's a bit tricky + @param aObjectValue +*/ +- (void)setObjectValue:(id)anObjectValue +{ + var dateValue = [[_datePicker dateValue] copy]; + + switch (_dateType) + { + case CPMonthDateType: + + var dateNextMonth = [dateValue copy]; + + dateNextMonth.setDate(1); + dateNextMonth.setMonth(parseInt(anObjectValue) - 1); + + var numberDayNextMonth = [dateNextMonth _daysInMonth]; + + if (numberDayNextMonth < [dateValue _daysInMonth] && dateValue.getDate() > numberDayNextMonth) + dateValue.setDate(numberDayNextMonth); + + dateValue.setMonth(parseInt(anObjectValue) - 1); + break; + + case CPDayDateType: + dateValue.setDate(parseInt(anObjectValue)); + break; + + case CPYearDateType: + dateValue.setFullYear(parseInt(anObjectValue)); + break; + + case CPHourDateType: + dateValue.setHours(parseInt(anObjectValue)); + break; + + case CPSecondDateType: + dateValue.setSeconds(parseInt(anObjectValue)); + break; + + case CPMinuteDateType: + dateValue.setMinutes(parseInt(anObjectValue)); + break; + } + + [_datePicker setDateValue:dateValue]; +} + +/*! Return the objectValue of the textField. Needed for the binding. + This returns the objectValue relative to the dateValue +*/ +- (void)objectValue +{ + var dateValue = [[_datePicker dateValue] copy]; + + switch (_dateType) + { + case CPMonthDateType: + return dateValue.getMonth() + 1; + break; + + case CPDayDateType: + return dateValue.getDate(); + break; + + case CPYearDateType: + return dateValue.getFullYear(); + break; + + case CPHourDateType: + return dateValue.getHours(); + break; + + case CPSecondDateType: + return dateValue.getSeconds(); + break; + + case CPMinuteDateType: + return dateValue.getMinutes(); + break; + + default: + return [super objectValue]; + break; + } + + return [super objectValue]; +} + +#pragma mark - +#pragma mark Mouse event + +/*! Mouse down event. Launch a notification to notif the new first responder textField +*/ +- (void)mouseDown:(CPEvent)anEvent +{ + if (![self isEnabled]) + return; + + [super mouseDown:anEvent]; + [[CPNotificationCenter defaultCenter] postNotificationName:CPDatePickerElementTextFieldBecomeFirstResponder object:[[self superview] superview] userInfo:[CPDictionary dictionaryWithObject:self forKey:@"textField"]]; +} + + +#pragma mark - +#pragma mark Theme functions + +/*! Set the theme CPThemeStateSelected +*/ +- (void)makeSelectable +{ + [self setThemeState:CPThemeStateSelected]; +} + +/*! Unsert the theme CPThemeStateSelected +*/ +- (void)makeDeselectable +{ + [self unsetThemeState:CPThemeStateSelected]; +} + +@end \ No newline at end of file diff --git a/AppKit/CPDragServer.j b/AppKit/CPDragServer.j index e96bd56aa..1fc16eb9f 100644 --- a/AppKit/CPDragServer.j +++ b/AppKit/CPDragServer.j @@ -163,7 +163,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, if (self) { - _draggedWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask]; + _draggedWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessWindowMask]; [_draggedWindow setLevel:CPDraggingWindowLevel]; } @@ -201,7 +201,12 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, - (void)draggingSourceUpdatedWithGlobalLocation:(CGPoint)aGlobalLocation { if (![CPPlatform supportsDragAndDrop]) - [_draggedWindow setFrameOrigin:_CGPointMake(aGlobalLocation.x - _draggingOffset.width, aGlobalLocation.y - _draggingOffset.height)]; + { + var frame = [_draggedWindow frame]; + frame.origin.x = aGlobalLocation.x - _draggingOffset.width; + frame.origin.y = aGlobalLocation.y - _draggingOffset.height; + [_draggedWindow _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO]; + } if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_movedTo_) [_draggingSource draggedImage:[_draggedView image] movedTo:aGlobalLocation]; @@ -265,10 +270,10 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, { if ([scrollView hasVerticalScroller]) { - if (eventLocation.y < _CGRectGetMinY(insetBounds)) - deltaY = _CGRectGetMinY(insetBounds) - eventLocation.y; - else if (eventLocation.y > _CGRectGetMaxY(insetBounds)) - deltaY = _CGRectGetMaxY(insetBounds) - eventLocation.y; + if (eventLocation.y < CGRectGetMinY(insetBounds)) + deltaY = CGRectGetMinY(insetBounds) - eventLocation.y; + else if (eventLocation.y > CGRectGetMaxY(insetBounds)) + deltaY = CGRectGetMaxY(insetBounds) - eventLocation.y; if (deltaY < -insetBounds.size.height) deltaY = -insetBounds.size.height; if (deltaY > insetBounds.size.height) @@ -277,17 +282,17 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, if ([scrollView hasHorizontalScroller]) { - if (eventLocation.x < _CGRectGetMinX(insetBounds)) - deltaX = _CGRectGetMinX(insetBounds) - eventLocation.x; - else if (eventLocation.x > _CGRectGetMaxX(insetBounds)) - deltaX = _CGRectGetMaxX(insetBounds) - eventLocation.x; + if (eventLocation.x < CGRectGetMinX(insetBounds)) + deltaX = CGRectGetMinX(insetBounds) - eventLocation.x; + else if (eventLocation.x > CGRectGetMaxX(insetBounds)) + deltaX = CGRectGetMaxX(insetBounds) - eventLocation.x; if (deltaX < -insetBounds.size.width) deltaX = -insetBounds.size.width; if (deltaX > insetBounds.size.width) deltaX = insetBounds.size.width; } - var scrollPoint = _CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY); + var scrollPoint = CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY); [contentView scrollToPoint:scrollPoint]; [[scrollView _headerView] scrollPoint:scrollPoint]; @@ -365,22 +370,26 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, if (mouseDownWindow) mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation]; - _draggingOffset = _CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y); + _draggingOffset = CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y); } else - _draggingOffset = _CGSizeMakeZero(); + _draggingOffset = CGSizeMakeZero(); if ([CPPlatform isBrowser]) [_draggedWindow setPlatformWindow:[aWindow platformWindow]]; - [aView setFrameOrigin:_CGPointMakeZero()]; + [aView setFrameOrigin:CGPointMakeZero()]; - var mouseLocation = [CPEvent mouseLocation]; + var mouseLocation = [CPEvent mouseLocation], + viewSize = [aView frameSize], + startDragLocationX = mouseLocation.x - _draggingOffset.width, + startDragLocationY = mouseLocation.y - _draggingOffset.height, + draggedWindowFrame = CGRectMake(startDragLocationX, startDragLocationY, viewSize.width, viewSize.height); // Place it where the mouse pointer is. - _startDragLocation = _CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height); - [_draggedWindow setFrameOrigin:_startDragLocation]; - [_draggedWindow setFrameSize:[aView frame].size]; + _startDragLocation = CGPointMake(startDragLocationX, startDragLocationY); + + [_draggedWindow _setFrame:draggedWindowFrame display:YES animate:NO constrainWidth:NO constrainHeight:NO]; [[_draggedWindow contentView] addSubview:aView]; @@ -429,7 +438,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, var imageSize = [anImage size]; if (!_imageView) - _imageView = [[CPImageView alloc] initWithFrame:_CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)]; + _imageView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)]; [_imageView setImage:anImage]; diff --git a/AppKit/CPEvent.j b/AppKit/CPEvent.j index 77ea70792..478a08897 100644 --- a/AppKit/CPEvent.j +++ b/AppKit/CPEvent.j @@ -235,7 +235,7 @@ var _CPEventPeriodicEventPeriod = 0, */ - (CGPoint)locationInWindow { - return _CGPointMakeCopy(_location); + return CGPointMakeCopy(_location); } - (CGPoint)globalLocation @@ -527,7 +527,7 @@ var _CPEventPeriodicEventPeriod = 0, function _CPEventFirePeriodEvent() { - [CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:_CGPointMakeZero() modifierFlags:0 timestamp:[CPEvent currentTimestamp] windowNumber:0 context:nil subtype:0 data1:0 data2:0]]; + [CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:CGPointMakeZero() modifierFlags:0 timestamp:[CPEvent currentTimestamp] windowNumber:0 context:nil subtype:0 data1:0 data2:0]]; } var CPEventClass = [CPEvent class]; diff --git a/AppKit/CPFont.j b/AppKit/CPFont.j index aa91ac694..5bfc16419 100644 --- a/AppKit/CPFont.j +++ b/AppKit/CPFont.j @@ -37,12 +37,12 @@ CPFontCurrentSystemSize = -1; // For internal use only by this class and subclasses _CPFontSystemFacePlaceholder = "_CPFontSystemFacePlaceholder"; -var _CPFontCache = {}, - _CPSystemFontCache = {}, - _CPFontSystemFontFace = CPFontDefaultSystemFontFace, - _CPFontSystemFontSize = 12, - _CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "), - _CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g"); +var _CPFontCache = {}, + _CPSystemFontCache = {}, + _CPFontSystemFontFace = CPFontDefaultSystemFontFace, + _CPFontSystemFontSize = 12, + _CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "), + _CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g"); #define _CPRealFontSize(aSize) (aSize <= 0 ? _CPFontSystemFontSize : aSize) @@ -181,8 +181,10 @@ following: { case CPSmallControlSize: return _CPFontSystemFontSize - 1; + case CPMiniControlSize: return _CPFontSystemFontSize - 2; + case CPRegularControlSize: default: return _CPFontSystemFontSize; diff --git a/AppKit/CPGradient.j b/AppKit/CPGradient.j index dcd861fb0..dfa7a3437 100644 --- a/AppKit/CPGradient.j +++ b/AppKit/CPGradient.j @@ -108,13 +108,13 @@ CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation; angle = ((angle % 360.0) + 360.0) % 360.0; if (angle < 90.0) - startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMinY(rect)); + startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect)); else if (angle < 180.0) - startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMinY(rect)); + startPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect)); else if (angle < 270.0) - startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMaxY(rect)); + startPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect)); else - startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMaxY(rect)); + 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 @@ -129,9 +129,9 @@ CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation; // 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)); + length = ABS(CGRectGetWidth(rect) * COS(radians)) + ABS(CGRectGetHeight(rect) * SIN(radians)); - endPoint = _CGPointMake(startPoint.x + length * COS(radians), + endPoint = CGPointMake(startPoint.x + length * COS(radians), startPoint.y + length * SIN(radians)); [self drawFromPoint:startPoint toPoint:endPoint options:CPGradientDrawsBeforeStartingLocation | CPGradientDrawsAfterEndingLocation]; diff --git a/AppKit/CPGraphics.j b/AppKit/CPGraphics.j index cbf51c440..380bea393 100644 --- a/AppKit/CPGraphics.j +++ b/AppKit/CPGraphics.j @@ -60,9 +60,9 @@ function CPDrawColorTiledRects( if (sides.length != colors.length) [CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and colors (length: " + colors.length + ") must have the same length."]; - var resultRect = _CGRectMakeCopy(boundsRect), - slice = _CGRectMakeZero(), - remainder = _CGRectMakeZero(), + var resultRect = CGRectMakeCopy(boundsRect), + slice = CGRectMakeZero(), + remainder = CGRectMakeZero(), context = [[CPGraphicsContext currentContext] graphicsPort]; CGContextSaveGState(context); @@ -77,7 +77,7 @@ function CPDrawColorTiledRects( slice = CGRectIntersection(slice, clipRect); // Cocoa docs say that only slices that are within the clipRect are actually drawn - if (_CGRectIsEmpty(slice)) + if (CGRectIsEmpty(slice)) continue; var minX, @@ -88,23 +88,23 @@ function CPDrawColorTiledRects( if (side == CPMinXEdge || side == CPMaxXEdge) { // Make sure we have at least 1 pixel to draw a line - if (_CGRectGetWidth(slice) < 1.0) + if (CGRectGetWidth(slice) < 1.0) continue; - minX = _CGRectGetMinX(slice) + 0.5; + minX = CGRectGetMinX(slice) + 0.5; maxX = minX; - minY = _CGRectGetMinY(slice); - maxY = _CGRectGetMaxY(slice); + minY = CGRectGetMinY(slice); + maxY = CGRectGetMaxY(slice); } else // CPMinYEdge || CPMaxYEdge { // Make sure we have at least 1 pixel to draw a line - if (_CGRectGetHeight(slice) < 1.0) + if (CGRectGetHeight(slice) < 1.0) continue; - minX = _CGRectGetMinX(slice); - maxX = _CGRectGetMaxX(slice); - minY = _CGRectGetMinY(slice) + 0.5; + minX = CGRectGetMinX(slice); + maxX = CGRectGetMaxX(slice); + minY = CGRectGetMinY(slice) + 0.5; maxY = minY; } diff --git a/AppKit/CPImage.j b/AppKit/CPImage.j index 60730cf3c..cc9a9901f 100644 --- a/AppKit/CPImage.j +++ b/AppKit/CPImage.j @@ -48,8 +48,8 @@ var imagesForNames = { }, AppKitImageForNames = { }, ImageDescriptionFormat = "%s {\n filename: \"%s\",\n size: { width:%f, height:%f }\n}"; -AppKitImageForNames[CPImageNameColorPanel] = _CGSizeMake(26.0, 29.0); -AppKitImageForNames[CPImageNameColorPanelHighlighted] = _CGSizeMake(26.0, 29.0); +AppKitImageForNames[CPImageNameColorPanel] = CGSizeMake(26.0, 29.0); +AppKitImageForNames[CPImageNameColorPanelHighlighted] = CGSizeMake(26.0, 29.0); /*! Returns a resource image with a relative path and size @@ -72,7 +72,7 @@ function CPImageInBundle() if (typeof(arguments[1]) === "number") { if (arguments[1] !== nil && arguments[1] !== undefined) - size = _CGSizeMake(arguments[1], arguments[2]); + size = CGSizeMake(arguments[1], arguments[2]); bundle = arguments[3]; } @@ -131,7 +131,7 @@ function CPAppKitImage(aFilename, aSize) - (id)init { - return [self initByReferencingFile:@"" size:_CGSizeMake(-1, -1)]; + return [self initByReferencingFile:@"" size:CGSizeMake(-1, -1)]; } /*! @@ -148,7 +148,7 @@ function CPAppKitImage(aFilename, aSize) if (self) { - _size = _CGSizeMakeCopy(aSize); + _size = CGSizeMakeCopy(aSize); _filename = aFilename; _loadStatus = CPImageLoadStatusInitialized; } @@ -180,7 +180,7 @@ function CPAppKitImage(aFilename, aSize) */ - (id)initWithContentsOfFile:(CPString)aFilename { - self = [self initByReferencingFile:aFilename size:_CGSizeMake(-1, -1)]; + self = [self initByReferencingFile:aFilename size:CGSizeMake(-1, -1)]; if (self) [self load]; @@ -247,7 +247,7 @@ function CPAppKitImage(aFilename, aSize) */ - (void)setSize:(CGSize)aSize { - _size = _CGSizeMakeCopy(aSize); + _size = CGSizeMakeCopy(aSize); } /*! @@ -446,7 +446,7 @@ function CPAppKitImage(aFilename, aSize) // FIXME: IE is wrong on image sizes???? if (!_size || (_size.width == -1 && _size.height == -1)) - _size = _CGSizeMake(_image.width, _image.height); + _size = CGSizeMake(_image.width, _image.height); [[CPNotificationCenter defaultCenter] postNotificationName:CPImageDidLoadNotification diff --git a/AppKit/CPImageView.j b/AppKit/CPImageView.j index 1205fe12c..a56f62c07 100644 --- a/AppKit/CPImageView.j +++ b/AppKit/CPImageView.j @@ -302,8 +302,8 @@ var CPImageViewEmptyPlaceholderImage = nil; y = 0.0, insetWidth = (_hasShadow ? [_shadowView horizontalInset] : 0.0), insetHeight = (_hasShadow ? [_shadowView verticalInset] : 0.0), - boundsWidth = _CGRectGetWidth(bounds), - boundsHeight = _CGRectGetHeight(bounds), + boundsWidth = CGRectGetWidth(bounds), + boundsHeight = CGRectGetHeight(bounds), width = boundsWidth - insetWidth, height = boundsHeight - insetHeight; @@ -401,10 +401,10 @@ var CPImageViewEmptyPlaceholderImage = nil; #endif } - _imageRect = _CGRectMake(x, y, width, height); + _imageRect = CGRectMake(x, y, width, height); if (_hasShadow) - [_shadowView setFrame:_CGRectMake(x - [_shadowView leftInset], y - [_shadowView topInset], width + insetWidth, height + insetHeight)]; + [_shadowView setFrame:CGRectMake(x - [_shadowView leftInset], y - [_shadowView topInset], width + insetWidth, height + insetHeight)]; } - (void)mouseDown:(CPEvent)anEvent @@ -585,7 +585,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey", @end -@implementation CPImage (CahedImage) +@implementation CPImage (CachedImage) + (CPImage)cachedImageWithContentsOfFile:(CPString)aFile { @@ -601,4 +601,4 @@ var CPImageViewImageKey = @"CPImageViewImageKey", return image; } -@end \ No newline at end of file +@end diff --git a/AppKit/CPKeyValueBinding.j b/AppKit/CPKeyValueBinding.j index e48f9fc22..06ce850b7 100644 --- a/AppKit/CPKeyValueBinding.j +++ b/AppKit/CPKeyValueBinding.j @@ -257,7 +257,11 @@ var CPBindingOperationAnd = 0, if (valueTransformer) aValue = [valueTransformer transformedValue:aValue]; - if (aValue === undefined || aValue === nil || aValue === [CPNull null]) + // If the value is nil AND the source doesn't respond to setPlaceholderString: then + // we set the value to the placeholder. Otherwise, we do not want to short cut the process + // of setting the placeholder that is based on the fact that the value is nil. + if ((aValue === undefined || aValue === nil || aValue === [CPNull null]) + && ![_source respondsToSelector:@selector(setPlaceholderString:)]) aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil; return aValue; @@ -345,12 +349,12 @@ var CPBindingOperationAnd = 0, [self _updatePlaceholdersWithOptions:options]; } -- (void)_placeholderForMarker:aMarker +- (JSObject)_placeholderForMarker:(id)aMarker { - var placeholder = _placeholderForMarker[aMarker]; + var placeholder = _placeholderForMarker[[aMarker UID]]; if (placeholder) - return placeholder['value']; + return placeholder.value; return nil; } @@ -359,14 +363,14 @@ var CPBindingOperationAnd = 0, { if (isDefault) { - var existingPlaceholder = _placeholderForMarker[aMarker]; + var existingPlaceholder = _placeholderForMarker[[aMarker UID]]; // Don't overwrite an explicitly set placeholder with a default. - if (existingPlaceholder && !existingPlaceholder['isDefault']) + if (existingPlaceholder && !existingPlaceholder.isDefault) return; } - _placeholderForMarker[aMarker] = { 'isDefault': isDefault, 'value': aPlaceholder }; + _placeholderForMarker[[aMarker UID]] = { 'isDefault': isDefault, 'value': aPlaceholder }; } @end @@ -802,6 +806,26 @@ var CPBindingOperationAnd = 0, @end +@implementation _CPStateMarker : CPObject +{ + CPString _name; +} + +- (id)initWithName:(CPString)aName +{ + if (self = [super init]) + _name = aName + + return self; +} + +- (CPString)description +{ + return "<" + _name + ">"; +} + +@end + // Keys in options dictionary @@ -811,10 +835,10 @@ CPObservedKeyPathKey = @"CPObservedKeyPathKey"; CPOptionsKey = @"CPOptionsKey"; // special markers -CPMultipleValuesMarker = @"CPMultipleValuesMarker"; -CPNoSelectionMarker = @"CPNoSelectionMarker"; -CPNotApplicableMarker = @"CPNotApplicableMarker"; -CPNullMarker = @"CPNullMarker"; +CPNoSelectionMarker = [[_CPStateMarker alloc] initWithName:@"NO SELECTION MARKER"]; +CPMultipleValuesMarker = [[_CPStateMarker alloc] initWithName:@"MULTIPLE VALUES MARKER"]; +CPNotApplicableMarker = [[_CPStateMarker alloc] initWithName:@"NOT APPLICABLE MARKER"]; +CPNullMarker = [[_CPStateMarker alloc] initWithName:@"NULL MARKER"]; // Binding name constants CPAlignmentBinding = @"alignment"; diff --git a/AppKit/CPLevelIndicator.j b/AppKit/CPLevelIndicator.j index aa0cb9c76..92a631c42 100644 --- a/AppKit/CPLevelIndicator.j +++ b/AppKit/CPLevelIndicator.j @@ -122,7 +122,7 @@ CPRatingLevelIndicatorStyle = 3; - (CPView)createEphemeralSubviewNamed:(CPString)aName { - return [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + return [[CPView alloc] initWithFrame:CGRectMakeZero()]; } - (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName @@ -130,11 +130,11 @@ CPRatingLevelIndicatorStyle = 3; // TODO Put into theme attributes. var bezelHeight = 18, segmentHeight = 17, - bounds = _CGRectCreateCopy([self bounds]); + bounds = CGRectCreateCopy([self bounds]); if (aViewName == "bezel") { - bounds.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0; + bounds.origin.y = (CGRectGetHeight(bounds) - bezelHeight) / 2.0; bounds.size.height = bezelHeight; return bounds; } @@ -144,13 +144,13 @@ CPRatingLevelIndicatorStyle = 3; segmentCount = _maxValue - _minValue; if (segment >= segmentCount) - return _CGRectMakeZero(); + return CGRectMakeZero(); var basicSegmentWidth = bounds.size.width / segmentCount, segmentFrame = CGRectCreateCopy([self bounds]), spacing = [self valueForThemeAttribute:@"spacing"]; - segmentFrame.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0; + segmentFrame.origin.y = (CGRectGetHeight(bounds) - bezelHeight) / 2.0; segmentFrame.origin.x = FLOOR(segment * basicSegmentWidth); segmentFrame.size.width = (segment == segmentCount - 1) ? bounds.size.width - segmentFrame.origin.x : FLOOR(((segment + 1) * basicSegmentWidth)) - FLOOR((segment * basicSegmentWidth)) - spacing; segmentFrame.size.height = segmentHeight; @@ -158,7 +158,7 @@ CPRatingLevelIndicatorStyle = 3; return segmentFrame; } - return _CGRectMakeZero(); + return CGRectMakeZero(); } /*! diff --git a/AppKit/CPMenu/CPMenu.j b/AppKit/CPMenu/CPMenu.j index 26ae6da2b..58630f9ab 100644 --- a/AppKit/CPMenu/CPMenu.j +++ b/AppKit/CPMenu/CPMenu.j @@ -68,6 +68,8 @@ var _CPMenuBarVisible = NO, int _highlightedIndex; _CPMenuWindow _menuWindow; + + CPEvent _lastCloseEvent; } // Managing the Menu Bar @@ -849,6 +851,8 @@ var _CPMenuBarVisible = NO, var theWindow = [aView window], menuWindow = [_CPMenuWindow menuWindowWithMenu:aMenu font:aFont]; + [_CPMenuWindow poolMenuWindow:menuWindow]; + [menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle]; var constraintRect = [CPMenu _constraintRectForView:aView], @@ -944,6 +948,10 @@ var _CPMenuBarVisible = NO, - (void)_menuDidClose { + // Remember which event caused this menu to close, if any. CPPopUpButton uses this to detect + // when a click on the button itself caused the menu to close. + _lastCloseEvent = [CPApp currentEvent]; + var delegate = [self delegate]; if ([delegate respondsToSelector:@selector(menuDidClose:)]) @@ -963,7 +971,7 @@ var _CPMenuBarVisible = NO, { [CPApp sendEvent:[CPEvent otherEventWithType:CPAppKitDefined - location:_CGPointMakeZero() + location:CGPointMakeZero() modifierFlags:0 timestamp:0 windowNumber:0 diff --git a/AppKit/CPMenu/_CPMenuBarWindow.j b/AppKit/CPMenu/_CPMenuBarWindow.j index 60cc01b72..2c6c2bcaa 100644 --- a/AppKit/CPMenu/_CPMenuBarWindow.j +++ b/AppKit/CPMenu/_CPMenuBarWindow.j @@ -67,6 +67,8 @@ if (self) { + _constrainsToUsableScreen = NO; + [self setLevel:CPMainMenuWindowLevel]; [self setAutoresizingMask:CPWindowWidthSizable]; @@ -141,6 +143,7 @@ _textColor = aColor; [_menuItemViews makeObjectsPerformSelector:@selector(setTextColor:) withObject:_textColor]; + [_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuTextColor:) withObject:_textColor]; } - (void)setTitleColor:(CPColor)aColor @@ -161,6 +164,7 @@ _textShadowColor = aColor; [_menuItemViews makeObjectsPerformSelector:@selector(setTextShadowColor:) withObject:_textShadowColor]; + [_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuTextShadowColor:) withObject:_textShadowColor]; } - (void)setTitleShadowColor:(CPColor)aColor @@ -179,6 +183,8 @@ return; _highlightColor = aColor; + + [_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightColor:) withObject:_highlightColor]; } - (void)setHighlightTextColor:(CPColor)aColor @@ -188,7 +194,7 @@ _highlightTextColor = aColor; -// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateColor:) withObject:_highlightTextColor]; + [_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightTextColor:) withObject:_highlightTextColor]; } - (void)setHighlightTextShadowColor:(CPColor)aColor @@ -198,7 +204,7 @@ _highlightTextShadowColor = aColor; -// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateShadowColor:) withObject:_highlightTextShadowColor]; + [_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightTextShadowColor:) withObject:_highlightTextShadowColor]; } - (void)setMenu:(CPMenu)aMenu @@ -411,7 +417,7 @@ [super setFrame:aRect display:shouldDisplay animate:shouldAnimate]; - if (!_CGSizeEqualToSize(size, aRect.size)) + if (!CGSizeEqualToSize(size, aRect.size)) [self tile]; } diff --git a/AppKit/CPMenu/_CPMenuManager.j b/AppKit/CPMenu/_CPMenuManager.j index 45c8ac321..dd5b7abaf 100644 --- a/AppKit/CPMenu/_CPMenuManager.j +++ b/AppKit/CPMenu/_CPMenuManager.j @@ -45,6 +45,7 @@ var STICKY_TIME_INTERVAL = 0.4, @implementation _CPMenuManager: CPObject { CPTimeInterval _startTime; + CPEvent _openEvent; BOOL _mouseWasDragged; int _scrollingState; CGPoint _lastGlobalLocation; @@ -103,6 +104,7 @@ var STICKY_TIME_INTERVAL = 0.4, CPApp._activeMenu = menu; _startTime = [anEvent timestamp]; + _openEvent = anEvent; _scrollingState = _CPMenuManagerScrollingStateNone; _constraintRect = aRect; @@ -132,6 +134,11 @@ var STICKY_TIME_INTERVAL = 0.4, [self trackEvent:anEvent]; } +- (void)_trackAgain +{ + [CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseDownMask | CPLeftMouseUpMask | CPRightMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES]; +} + - (void)trackEvent:(CPEvent)anEvent { var type = [anEvent type], @@ -141,8 +148,6 @@ var STICKY_TIME_INTERVAL = 0.4, if (type === CPAppKitDefined) return [self completeTracking]; - [CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPRightMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES]; - if (type === CPKeyDown) { var menu = trackingMenu, @@ -158,6 +163,7 @@ var STICKY_TIME_INTERVAL = 0.4, if ([menu numberOfItems]) [self interpretKeyEvent:anEvent forMenu:menu]; + [self _trackAgain]; return; } @@ -165,7 +171,10 @@ var STICKY_TIME_INTERVAL = 0.4, var globalLocation = type === CPPeriodic ? _lastGlobalLocation : [anEvent globalLocation]; if (!globalLocation) + { + [self _trackAgain]; return; + } // Find which menu window the mouse is currently on top of var activeMenuContainer = [self menuContainerForPoint:globalLocation], @@ -176,15 +185,35 @@ var STICKY_TIME_INTERVAL = 0.4, activeItemIndex = activeMenuContainer ? [activeMenuContainer itemIndexAtPoint:menuLocation] : CPNotFound, activeItem = activeItemIndex !== CPNotFound ? [activeMenu itemAtIndex:activeItemIndex] : nil; - if (_keyBuffer) - { - if (([anEvent timestamp] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2)) - [self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:YES]; + /* + Click outside the menu structure? - if (type === CPPeriodic) - return; + The event which caused the menu to open is not considered even if it's + technically a click outside of an open menu, since this would mean the same + click which opened the menu could also close it. This is actually common. + E.g. you click on a button and it opens a menu below itself. + */ + if (type === CPLeftMouseDown && _openEvent !== anEvent && (!activeMenuContainer || !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation))) + { + [self completeTracking]; + + /* + You can close and interact with a control in a single click. E.g. you can have a menu open, + click on a button outside of it and have the menu immediately close and the button activate, + without having to click once to close the menu and once to activate the button. + + Since we normally dequeue the event after tracking it, we'll have to put it back on the stack + in this special case. Note that it's important the event is executed /right now/, since certain + controls such as HTML upload buttons need a native click event at the top of the stack trace + to activate - it's not something we can fake later. + */ + [CPApp sendEvent:anEvent]; + + return; } + [self _trackAgain]; + // unhighlight when mouse is moved off the menu if (_lastGlobalLocation && CGRectContainsPoint([activeMenuContainer globalFrame], _lastGlobalLocation) && !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation)) @@ -221,9 +250,9 @@ var STICKY_TIME_INTERVAL = 0.4, if (_lastMouseOverMenuView != mouseOverMenuView) { - [mouseOverMenuView mouseExited:anEvent]; + [_lastMouseOverMenuView mouseExited:anEvent]; // FIXME: Possibly multiple of these? - [_lastMouseOverMenuView mouseEntered:anEvent]; + [mouseOverMenuView mouseEntered:anEvent]; _lastMouseOverMenuView = mouseOverMenuView; } @@ -252,7 +281,7 @@ var STICKY_TIME_INTERVAL = 0.4, _lastMouseOverMenuView = nil; } - if (activeItemIndex != CPNotFound) + if (activeItemIndex !== CPNotFound) [activeMenu _highlightItemAtIndex:activeItemIndex]; if (type === CPMouseMoved || type === CPLeftMouseDragged || type === CPLeftMouseDown || type === CPPeriodic) @@ -428,8 +457,8 @@ var STICKY_TIME_INTERVAL = 0.4, { var menuContainer = _menuContainerStack[index], menuContainerFrame = [menuContainer globalFrame], - menuContainerMinX = _CGRectGetMinX(menuContainerFrame), - menuContainerMaxX = _CGRectGetMaxX(menuContainerFrame); + menuContainerMinX = CGRectGetMinX(menuContainerFrame), + menuContainerMaxX = CGRectGetMaxX(menuContainerFrame); // If within the x bounds of this menu container, return it. if (x < menuContainerMaxX && x >= menuContainerMinX) @@ -525,6 +554,9 @@ var STICKY_TIME_INTERVAL = 0.4, } else if (!(modifierFlags & (CPCommandKeyMask | CPControlKeyMask))) { + if (([anEvent timestamp] - _startTime) > STICKY_TIME_INTERVAL) + _keyBuffer = nil; + if (!_keyBuffer) { _startTime = [anEvent timestamp]; @@ -536,12 +568,12 @@ var STICKY_TIME_INTERVAL = 0.4, else _keyBuffer += character; - [self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:NO]; - _lastGlobalLocation = Nil; + [self selectNextItemBeginningWith:_keyBuffer inMenu:menu]; + _lastGlobalLocation = nil; } } -- (void)selectNextItemBeginningWith:(CPString)characters inMenu:(CPMenu)menu clearBuffer:(BOOL)shouldClear +- (void)selectNextItemBeginningWith:(CPString)characters inMenu:(CPMenu)menu { var iter = [[menu itemArray] objectEnumerator], obj; @@ -558,13 +590,7 @@ var STICKY_TIME_INTERVAL = 0.4, } } - if (shouldClear) - { - [CPEvent stopPeriodicEvents]; - _keyBuffer = Nil; - } - else - _startTime = [CPEvent currentTimestamp]; + _startTime = [CPEvent currentTimestamp]; } - (void)scrollToBeginningOfDocument:(CPMenu)menu diff --git a/AppKit/CPMenu/_CPMenuWindow.j b/AppKit/CPMenu/_CPMenuWindow.j index ddd697051..19cf4d6f7 100644 --- a/AppKit/CPMenu/_CPMenuWindow.j +++ b/AppKit/CPMenu/_CPMenuWindow.j @@ -80,13 +80,15 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2; - (id)initWithContentRect:(CGRect)aRect styleMask:(unsigned)aStyleMask { - _constraintRect = _CGRectMakeZero(); - _unconstrainedFrame = _CGRectMakeZero(); + _constraintRect = CGRectMakeZero(); + _unconstrainedFrame = CGRectMakeZero(); self = [super initWithContentRect:aRect styleMask:CPBorderlessWindowMask]; if (self) { + _constrainsToUsableScreen = NO; + [self setLevel:CPPopUpMenuWindowLevel]; [self setHasShadow:YES]; [self setShadowStyle:CPMenuWindowShadowStyle]; @@ -207,26 +209,26 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2; - (CGRect)unconstrainedFrame { - return _CGRectMakeCopy(_unconstrainedFrame); + return CGRectMakeCopy(_unconstrainedFrame); } // We need this because if not this will call setFrame: with -frame instead of -unconstrainedFrame, turning // the constrained frame into the unconstrained frame. - (void)setFrameOrigin:(CGPoint)aPoint { - [super setFrame:_CGRectMake(aPoint.x, aPoint.y, _CGRectGetWidth(_unconstrainedFrame), _CGRectGetHeight(_unconstrainedFrame))]; + [super setFrame:CGRectMake(aPoint.x, aPoint.y, CGRectGetWidth(_unconstrainedFrame), CGRectGetHeight(_unconstrainedFrame))]; } - (void)setFrameSize:(CGSize)aSize { - [super setFrame:_CGRectMake(_CGRectGetMinX(_unconstrainedFrame), _CGRectGetMinY(_unconstrainedFrame), aSize.width, aSize.height)]; + [super setFrame:CGRectMake(CGRectGetMinX(_unconstrainedFrame), CGRectGetMinY(_unconstrainedFrame), aSize.width, aSize.height)]; } - (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate { // FIXME: There are integral window issues with platform windows. // FIXME: This gets called far too often. - _unconstrainedFrame = _CGRectMakeCopy(aFrame); + _unconstrainedFrame = CGRectMakeCopy(aFrame); var constrainedFrame = CGRectIntersection(_unconstrainedFrame, _constraintRect), marginInset = [_menuView valueForThemeAttribute:@"menu-window-margin-inset"], diff --git a/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j b/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j index 1dfd49441..8d213511d 100644 --- a/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j +++ b/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j @@ -28,13 +28,18 @@ @implementation _CPMenuItemMenuBarView : CPView { + CPColor _highlightColor @accessors(property=highlightColor); + CPColor _textColor @accessors(property=textColor); + CPColor _textShadowColor @accessors(property=textShadowColor); + CPColor _highlightTextColor @accessors(property=highlightTextColor); + CPColor _highlightTextShadowColor @accessors(property=highlightTextShadowColor); + CPMenuItem _menuItem @accessors(property=menuItem); CPFont _font; - CPColor _textColor; - CPColor _textShadowColor; BOOL _isDirty; + BOOL _shouldHighlight; _CPImageAndTextView _imageAndTextView; } @@ -47,9 +52,7 @@ + (id)themeAttributes { return @{ - @"menu-item-selection-color": [CPNull null], - @"menu-item-text-shadow-color": [CPNull null], - @"horizontal-margin": 12.0, + @"horizontal-margin": 9.0, @"submenu-indicator-margin": 3.0, @"vertical-margin": 4.0, }; @@ -81,12 +84,36 @@ return self; } +- (CPColor)setTextColor:(CPColor)aColor +{ + _textColor = aColor; + [self setNeedsLayout]; +} + +- (CPColor)setTextShadowColor:(CPColor)aColor +{ + _textShadowColor = aColor; + [self setNeedsLayout]; +} + +- (CPColor)setHighlightTextColor:(CPColor)aColor +{ + _highlightTextColor = aColor; + [self setNeedsLayout]; +} + +- (CPColor)setHighlightTextShadowColor:(CPColor)aColor +{ + _highlightTextShadowColor = aColor; + [self setNeedsLayout]; +} + - (CPColor)textColor { if (![_menuItem isEnabled]) return [CPColor lightGrayColor]; - return _textColor || [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0]; + return _textColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-text-color" forClass:_CPMenuView]; } - (CPColor)textShadowColor @@ -94,7 +121,28 @@ if (![_menuItem isEnabled]) return [CPColor clearColor]; - return _textShadowColor || [CPColor colorWithWhite:1.0 alpha:0.8]; + return _textShadowColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-text-shadow-color" forClass:_CPMenuView]; +} + +- (CPColor)highlightTextColor +{ + if (![_menuItem isEnabled]) + return [CPColor lightGrayColor]; + + return _highlightTextColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-highlight-text-color" forClass:_CPMenuView]; +} + +- (CPColor)highlightTextShadowColor +{ + if (![_menuItem isEnabled]) + return [CPColor clearColor]; + + return _highlightTextShadowColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-highlight-text-shadow-color" forClass:_CPMenuView]; +} + +- (CPColor)highlightColor +{ + return _highlightColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-window-background-selected-color" forClass:_CPMenuView]; } - (void)update @@ -102,13 +150,11 @@ var x = [self valueForThemeAttribute:@"horizontal-margin"], height = 0.0; + [_imageAndTextView setText:[_menuItem title]]; [_imageAndTextView setFont:[_menuItem font] || [_CPMenuBarWindow font]]; [_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment]; - [_imageAndTextView setImage:[_menuItem image]]; - [_imageAndTextView setText:[_menuItem title]]; - [_imageAndTextView setTextColor:[self textColor]]; - [_imageAndTextView setTextShadowColor:[self textShadowColor]]; [_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)]; + [_imageAndTextView setImage:[_menuItem image]]; [_imageAndTextView sizeToFit]; var imageAndTextViewFrame = [_imageAndTextView frame]; @@ -123,6 +169,7 @@ [self setAutoresizesSubviews:NO]; [self setFrameSize:CGSizeMake(x + [self valueForThemeAttribute:@"horizontal-margin"], height)]; [self setAutoresizesSubviews:YES]; + [self setNeedsLayout]; } - (void)highlight:(BOOL)shouldHighlight @@ -131,14 +178,20 @@ if (![_menuItem isEnabled]) shouldHighlight = NO; - if (shouldHighlight) + _shouldHighlight = shouldHighlight; + [self setNeedsLayout]; +} + +- (void)layoutSubviews +{ + if (_shouldHighlight) { if (![_menuItem _isMenuBarButton]) - [self setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-window-background-selected-color" forClass:_CPMenuView]]; + [self setBackgroundColor:[self highlightColor]]; [_imageAndTextView setImage:[_menuItem alternateImage] || [_menuItem image]]; - [_imageAndTextView setTextColor:[CPColor whiteColor]]; - [_imageAndTextView setTextShadowColor:[self valueForThemeAttribute:@"menu-item-text-shadow-color"]]; + [_imageAndTextView setTextColor:[self highlightTextColor]]; + [_imageAndTextView setTextShadowColor:[self highlightTextShadowColor]]; } else { diff --git a/AppKit/CPMenuItem/_CPMenuItemView.j b/AppKit/CPMenuItem/_CPMenuItemView.j index a0311b333..9dc244b44 100644 --- a/AppKit/CPMenuItem/_CPMenuItemView.j +++ b/AppKit/CPMenuItem/_CPMenuItemView.j @@ -220,6 +220,36 @@ return [_menuItem isEnabled] ? (_textShadowColor ? _textShadowColor : [CPColor colorWithWhite:1.0 alpha:0.8]) : [CPColor colorWithWhite:0.8 alpha:0.8]; } +- (void)setParentMenuHighlightColor:(CPColor)aColor +{ + if ([_view respondsToSelector:@selector(setHighlightColor:)]) + [_view setHighlightColor:aColor]; +} + +- (void)setParentMenuHighlightTextColor:(CPColor)aColor +{ + if ([_view respondsToSelector:@selector(setHighlightTextColor:)]) + [_view setHighlightTextColor:aColor]; +} + +- (void)setParentMenuHighlightTextShadowColor:(CPColor)aColor +{ + if ([_view respondsToSelector:@selector(setHighlightTextShadowColor:)]) + [_view setHighlightTextShadowColor:aColor]; +} + +- (void)setParentMenuTextColor:(CPColor)aColor +{ + if ([_view respondsToSelector:@selector(setTextColor:)]) + [_view setTextColor:aColor]; +} + +- (void)setParentMenuTextShadowColor:(CPColor)aColor +{ + if ([_view respondsToSelector:@selector(setTextShadowColor:)]) + [_view setTextShadowColor:aColor]; +} + @end @implementation _CPMenuItemArrowView : CPView diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 079fb0099..bc69b5d3f 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -52,6 +52,7 @@ var CPOutlineViewDataSource_outlineView_objectValue_forTableColumn_byItem_ CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 11; var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1, + CPOutlineViewDelegate_outlineView_viewForTableColumn_item_ = 1 << 26, CPOutlineViewDelegate_outlineView_didClickTableColumn_ = 1 << 2, CPOutlineViewDelegate_outlineView_didDragTableColumn_ = 1 << 3, CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 4, @@ -709,11 +710,11 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, { var theItem = [self itemAtRow:aRow]; if (![self isExpandable:theItem] || ![self _shouldShowOutlineDisclosureControlForItem:theItem]) - return _CGRectMakeZero(); + return CGRectMakeZero(); var dataViewFrame = [self _frameOfOutlineDataViewAtRow:aRow], - disclosureWidth = _CGRectGetWidth([_disclosureControlPrototype frame]), - frame = _CGRectMake(_CGRectGetMinX(dataViewFrame) - disclosureWidth, _CGRectGetMinY(dataViewFrame), disclosureWidth, _CGRectGetHeight(dataViewFrame)); + disclosureWidth = CGRectGetWidth([_disclosureControlPrototype frame]), + frame = CGRectMake(CGRectGetMinX(dataViewFrame) - disclosureWidth, CGRectGetMinY(dataViewFrame), disclosureWidth, CGRectGetHeight(dataViewFrame)); return frame; } @@ -871,6 +872,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, var delegateMethods = [ CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ , @selector(outlineView:dataViewForTableColumn:item:), + CPOutlineViewDelegate_outlineView_viewForTableColumn_item_ , @selector(outlineView:viewForTableColumn:item:), CPOutlineViewDelegate_outlineView_didClickTableColumn_ , @selector(outlineView:didClickTableColumn:), CPOutlineViewDelegate_outlineView_didDragTableColumn_ , @selector(outlineView:didDragTableColumn:), CPOutlineViewDelegate_outlineView_heightOfRowByItem_ , @selector(outlineView:heightOfRowByItem:), @@ -963,6 +965,10 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, name:CPOutlineViewItemDidCollapseNotification object:self]; + [self _updateIsViewBased]; + + if ([self _delegateRespondsToDataViewForTableColumn]) + CPLog.warn("outlineView:dataViewForTableColumn:item: is deprecated. You should use -outlineView:viewForTableColumn:item: where you can request the view with -makeViewWithIdentifier:owner:"); } - (BOOL)_sendDelegateDeleteKeyPressed @@ -1060,7 +1066,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, var dragView = [[_CPColumnDragView alloc] initWithLineColor:[self gridColor]], tableColumn = [[self tableColumns] objectAtIndex:theColumnIndex], defaultRowHeight = [self valueForThemeAttribute:@"default-row-height"], - bounds = _CGRectMake(0.0, 0.0, [tableColumn width], _CGRectGetHeight([self exposedRect]) + defaultRowHeight), + bounds = CGRectMake(0.0, 0.0, [tableColumn width], CGRectGetHeight([self exposedRect]) + defaultRowHeight), columnRect = [self rectOfColumn:theColumnIndex], headerView = [tableColumn headerView], row = [_exposedRows firstIndex]; @@ -1074,7 +1080,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, dataViewFrame.origin.x = 0.0; // Offset by table header height - scroll position - dataViewFrame.origin.y = ( _CGRectGetMinY(dataViewFrame) - _CGRectGetMinY([self exposedRect]) ) + defaultRowHeight; + dataViewFrame.origin.y = (CGRectGetMinY(dataViewFrame) - CGRectGetMinY([self exposedRect])) + defaultRowHeight; [dataView setFrame:dataViewFrame]; [dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]]; @@ -1098,7 +1104,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, // Add the column header view var headerFrame = [headerView frame]; - headerFrame.origin = _CGPointMakeZero(); + headerFrame.origin = CGPointMakeZero(); var columnHeaderView = [[_CPTableColumnHeaderView alloc] initWithFrame:headerFrame]; [columnHeaderView setStringValue:[headerView stringValue]]; @@ -1304,7 +1310,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, var disclosureControlFrame = [self frameOfOutlineDisclosureControlAtRow:row]; - if (_CGRectIsEmpty(disclosureControlFrame)) + if (CGRectIsEmpty(disclosureControlFrame)) continue; var control = [self _dequeueDisclosureControl]; @@ -1361,7 +1367,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, - (void)_toggleFromDisclosureControl:(CPControl)aControl { var controlFrame = [aControl frame], - item = [self itemAtRow:[self rowAtPoint:_CGPointMake(_CGRectGetMinX(controlFrame), _CGRectGetMidY(controlFrame))]]; + item = [self itemAtRow:[self rowAtPoint:CGPointMake(CGRectGetMinX(controlFrame), CGRectGetMidY(controlFrame))]]; if ([self isItemExpanded:item]) [self collapseItem:item]; @@ -1534,11 +1540,26 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, [super keyDown:anEvent]; } +- (CPView)_viewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow +{ + return [_outlineViewDelegate outlineView:self viewForTableColumn:aTableColumn item:[self itemAtRow:aRow]]; +} + +- (CPView)_dataViewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow +{ + return [_outlineViewDelegate outlineView:self dataViewForTableColumn:aTableColumn item:[self itemAtRow:aRow]]; +} + - (BOOL)_dataSourceRespondsToObjectValueForTableColumn { return _implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_objectValue_forTableColumn_byItem_; } +- (BOOL)_delegateRespondsToViewForTableColumn +{ + return _implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_viewForTableColumn_item_; +} + - (BOOL)_delegateRespondsToDataViewForTableColumn { return _implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_; @@ -1893,17 +1914,6 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return [_outlineView menu] || [[_outlineView class] defaultMenu]; } -- (CPView)tableView:(CPTableView)aTableView dataViewForTableColumn:(CPTableColumn)aTableColumn row:(int)aRow -{ - if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_)) - { - var item = [_outlineView itemAtRow:aRow]; - return [_outlineView._outlineViewDelegate outlineView:_outlineView dataViewForTableColumn:aTableColumn item:item] - } - - return nil; -} - @end @implementation CPDisclosureButton : CPButton @@ -1936,14 +1946,14 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { var bounds = [self bounds], context = [[CPGraphicsContext currentContext] graphicsPort], - width = _CGRectGetWidth(bounds), - height = _CGRectGetHeight(bounds); + width = CGRectGetWidth(bounds), + height = CGRectGetHeight(bounds); CGContextBeginPath(context); if (_angle) { - var centre = _CGPointMake(FLOOR(width / 2.0), FLOOR(height / 2.0)); + 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); @@ -2007,6 +2017,8 @@ var CPOutlineViewIndentationPerLevelKey = @"CPOutlineViewIndentationPerLevelKey" [super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]]; [super setDelegate:[[_CPOutlineViewTableViewDelegate alloc] initWithOutlineView:self]]; + + [self _updateIsViewBased]; } return self; diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index 8b97a61aa..08800bf1b 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -667,10 +667,15 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down"); if (![self isEnabled] || ![self numberOfItems]) return; + var menu = [self menu]; + + // Don't reopen the menu based on the same click which caused it to close, e.g. a click on this button. + if (menu._lastCloseEvent === anEvent) + return; + [self highlight:YES]; - var menu = [self menu], - bounds = [self bounds], + var bounds = [self bounds], minimumWidth = CGRectGetWidth(bounds); // FIXME: setFont: should set the font on the menu. diff --git a/AppKit/CPPopover.j b/AppKit/CPPopover.j index 46991f0d9..cc2048d5e 100644 --- a/AppKit/CPPopover.j +++ b/AppKit/CPPopover.j @@ -63,7 +63,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, @outlet CPViewController _contentViewController @accessors(property=contentViewController); @outlet id _delegate @accessors(getter=delegate); - BOOL _animates @accessors(property=animates); + BOOL _animates @accessors(getter=animates); int _appearance @accessors(property=appearance); int _behavior @accessors(getter=behavior); @@ -153,6 +153,20 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, return [_popoverWindow isVisible]; } +/*! + Set if the popover should animate for open/close actions. + + @param shouldAnimate if YES, the popover will be animated. +*/ +- (void)setAnimates:(BOOL)shouldAnimate +{ + if (_animates == shouldAnimate) + return; + + _animates = shouldAnimate; + [_popoverWindow setAnimates:_animates]; +} + /*! Set the behavior of the CPPopover. It can be: diff --git a/AppKit/CPProgressIndicator.j b/AppKit/CPProgressIndicator.j index 1bc74dcaa..e0ea06ab4 100644 --- a/AppKit/CPProgressIndicator.j +++ b/AppKit/CPProgressIndicator.j @@ -371,7 +371,7 @@ var CPProgressIndicatorSpinningStyleColors = []; - (CPView)createEphemeralSubviewNamed:(CPString)aName { - return [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + return [[CPView alloc] initWithFrame:CGRectMakeZero()]; } - (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName @@ -387,7 +387,7 @@ var CPProgressIndicatorSpinningStyleColors = []; if (_indeterminate) barWidth = width; - return _CGRectMake(0, 0, barWidth, [self valueForThemeAttribute:@"default-height"]); + return CGRectMake(0, 0, barWidth, [self valueForThemeAttribute:@"default-height"]); } return nil; diff --git a/AppKit/CPRuleEditor/CPRuleEditor.j b/AppKit/CPRuleEditor/CPRuleEditor.j index 107e8c972..50e2905b8 100644 --- a/AppKit/CPRuleEditor/CPRuleEditor.j +++ b/AppKit/CPRuleEditor/CPRuleEditor.j @@ -1877,17 +1877,17 @@ TODO: implement - (CPString)_toolTipForAddCompoundRowButton { - return @"Add Compound row"; + return [_standardLocalizer localizedStringForString:@"Add compound row"]; } - (CPString)_toolTipForAddSimpleRowButton { - return @"Add row"; + return [_standardLocalizer localizedStringForString:@"Add row"]; } - (CPString)_toolTipForDeleteRowButton { - return @"Delete row"; + return [_standardLocalizer localizedStringForString:@"Delete row"]; } - (void)_updateSliceIndentations diff --git a/AppKit/CPRuleEditor/_CPRuleEditorViewSlice.j b/AppKit/CPRuleEditor/_CPRuleEditorViewSlice.j index 455d594f3..58b637a63 100644 --- a/AppKit/CPRuleEditor/_CPRuleEditorViewSlice.j +++ b/AppKit/CPRuleEditor/_CPRuleEditorViewSlice.j @@ -53,8 +53,8 @@ if (select == _selected) return; - var selector = select ? @"setThemeState:" : @"unsetThemeState:"; - [[self subviews] makeObjectsPerformSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelectedDataView]; + var selector = select ? @selector(setThemeState:) : @selector(unsetThemeState:); + [[self subviews] makeObjectsPerformSelector:selector withObject:CPThemeStateSelectedDataView]; _selected = select; } diff --git a/AppKit/CPScreen.j b/AppKit/CPScreen.j index afa8ef2d5..e4a763088 100644 --- a/AppKit/CPScreen.j +++ b/AppKit/CPScreen.j @@ -43,9 +43,9 @@ - (CGRect)visibleFrame { #if PLATFORM(DOM) - return _CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight); + return CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight); #else - return _CGRectMakeZero(); + return CGRectMakeZero(); #endif } diff --git a/AppKit/CPScrollView.j b/AppKit/CPScrollView.j index fa957fc60..f8ce6820b 100644 --- a/AppKit/CPScrollView.j +++ b/AppKit/CPScrollView.j @@ -151,7 +151,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay, + (CGSize)contentSizeForFrameSize:(CGSize)frameSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType { - var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType], + var bounds = [self _insetBounds:CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType], scrollerWidth = [CPScroller scrollerWidth]; if (hFlag) @@ -165,10 +165,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay, + (CGSize)frameSizeForContentSize:(CGSize)contentSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType { - var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType], + var bounds = [self _insetBounds:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType], widthInset = contentSize.width - bounds.size.width, heightInset = contentSize.height - bounds.size.height, - frameSize = _CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset), + frameSize = CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset), scrollerWidth = [CPScroller scrollerWidth]; if (hFlag) @@ -186,10 +186,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay, { case CPLineBorder: case CPBezelBorder: - return _CGRectInset(bounds, 1.0, 1.0); + return CGRectInset(bounds, 1.0, 1.0); case CPGrooveBorder: - bounds = _CGRectInset(bounds, 2.0, 2.0); + bounds = CGRectInset(bounds, 2.0, 2.0); ++bounds.origin.y; --bounds.size.height; return bounds; @@ -517,8 +517,8 @@ Notifies the delegate when the scroll view has finished scrolling. { var bounds = [self _insetBounds]; - [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]]; - [[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])]; + [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]]; + [[self horizontalScroller] setFrameSize:CGSizeMake(CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])]; } [self reflectScrolledClipView:_contentView]; @@ -582,8 +582,8 @@ Notifies the delegate when the scroll view has finished scrolling. { var bounds = [self _insetBounds]; - [self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(_CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]]; - [[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], _CGRectGetHeight(bounds))]; + [self setVerticalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]]; + [[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], CGRectGetHeight(bounds))]; } [self reflectScrolledClipView:_contentView]; @@ -859,13 +859,13 @@ Notifies the delegate when the scroll view has finished scrolling. - (CGRect)_cornerViewFrame { if (!_cornerView) - return _CGRectMakeZero(); + return CGRectMakeZero(); var bounds = [self _insetBounds], frame = [_cornerView frame]; - frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame); - frame.origin.y = _CGRectGetMinY(bounds); + frame.origin.x = CGRectGetMaxX(bounds) - CGRectGetWidth(frame); + frame.origin.y = CGRectGetMinY(bounds); return frame; } @@ -876,14 +876,14 @@ Notifies the delegate when the scroll view has finished scrolling. var headerView = [self _headerView]; if (!headerView) - return _CGRectMakeZero(); + return CGRectMakeZero(); var frame = [self _insetBounds]; - frame.size.height = _CGRectGetHeight([headerView frame]); + frame.size.height = CGRectGetHeight([headerView frame]); if (SHOULD_SHOW_CORNER_VIEW()) - frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]); + frame.size.width -= CGRectGetWidth([self _cornerViewFrame]); return frame; } @@ -924,18 +924,18 @@ Notifies the delegate when the scroll view has finished scrolling. break; case CPScrollerDecrementPage: - contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll; + contentBounds.origin.y -= CGRectGetHeight(contentBounds) - _verticalPageScroll; break; case CPScrollerIncrementPage: - contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll; + contentBounds.origin.y += CGRectGetHeight(contentBounds) - _verticalPageScroll; break; // We want integral bounds! case CPScrollerKnobSlot: case CPScrollerKnob: default: - contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds))); + contentBounds.origin.y = ROUND(value * (CGRectGetHeight(documentFrame) - CGRectGetHeight(contentBounds))); } [self _sendDelegateMessages]; @@ -961,18 +961,18 @@ Notifies the delegate when the scroll view has finished scrolling. break; case CPScrollerDecrementPage: - contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll; + contentBounds.origin.x -= CGRectGetWidth(contentBounds) - _horizontalPageScroll; break; case CPScrollerIncrementPage: - contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll; + contentBounds.origin.x += CGRectGetWidth(contentBounds) - _horizontalPageScroll; break; // We want integral bounds! case CPScrollerKnobSlot: case CPScrollerKnob: default: - contentBounds.origin.x = ROUND(value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds))); + contentBounds.origin.x = ROUND(value * (CGRectGetWidth(documentFrame) - CGRectGetWidth(contentBounds))); } [self _sendDelegateMessages]; @@ -1096,7 +1096,7 @@ Notifies the delegate when the scroll view has finished scrolling. } [_contentView setFrame:[self _insetBounds]]; - [_headerClipView setFrame:_CGRectMakeZero()]; + [_headerClipView setFrame:CGRectMakeZero()]; --_recursionCount; @@ -1106,12 +1106,12 @@ Notifies the delegate when the scroll view has finished scrolling. var documentFrame = [documentView frame], // the size of the whole document contentFrame = [self _insetBounds], // assume it takes up the entire size of the scrollview (no scrollers) headerClipViewFrame = [self _headerClipViewFrame], - headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame); + headerClipViewHeight = CGRectGetHeight(headerClipViewFrame); contentFrame.origin.y += headerClipViewHeight; contentFrame.size.height -= headerClipViewHeight; - var difference = _CGSizeMake(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentFrame), _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentFrame)), + var difference = CGSizeMake(CGRectGetWidth(documentFrame) - CGRectGetWidth(contentFrame), CGRectGetHeight(documentFrame) - CGRectGetHeight(contentFrame)), verticalScrollerWidth = [CPScroller scrollerWidthInStyle:[_verticalScroller style]], horizontalScrollerHeight = [CPScroller scrollerWidthInStyle:[_horizontalScroller style]], hasVerticalScroll = difference.height > 0.0, @@ -1162,18 +1162,18 @@ Notifies the delegate when the scroll view has finished scrolling. if (shouldShowVerticalScroller) { var verticalScrollerY = - MAX(_CGRectGetMinY(contentFrame), MAX(_CGRectGetMaxY([self _cornerViewFrame]), _CGRectGetMaxY(headerClipViewFrame))); + MAX(CGRectGetMinY(contentFrame), MAX(CGRectGetMaxY([self _cornerViewFrame]), CGRectGetMaxY(headerClipViewFrame))); - var verticalScrollerHeight = _CGRectGetMaxY(contentFrame) - verticalScrollerY; + var verticalScrollerHeight = CGRectGetMaxY(contentFrame) - verticalScrollerY; // Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap. if (_scrollerStyle === CPScrollerStyleOverlay && hasHorizontalScroll) verticalScrollerHeight -= horizontalScrollerHeight; - var documentHeight = _CGRectGetHeight(documentFrame); + var documentHeight = CGRectGetHeight(documentFrame); [_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height]; - [_verticalScroller setKnobProportion:documentHeight > 0 ? _CGRectGetHeight(contentFrame) / documentHeight : 1.0]; - [_verticalScroller setFrame:_CGRectMake(_CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)]; + [_verticalScroller setKnobProportion:documentHeight > 0 ? CGRectGetHeight(contentFrame) / documentHeight : 1.0]; + [_verticalScroller setFrame:CGRectMake(CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)]; } else if (wasShowingVerticalScroller) { @@ -1183,16 +1183,16 @@ Notifies the delegate when the scroll view has finished scrolling. if (shouldShowHorizontalScroller) { - var horizontalScrollerWidth = _CGRectGetWidth(contentFrame); + var horizontalScrollerWidth = CGRectGetWidth(contentFrame); // Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap. if (_scrollerStyle === CPScrollerStyleOverlay && hasVerticalScroll) horizontalScrollerWidth -= verticalScrollerWidth; - var documentWidth = _CGRectGetWidth(documentFrame); + var documentWidth = CGRectGetWidth(documentFrame); [_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width]; - [_horizontalScroller setKnobProportion:documentWidth > 0 ? _CGRectGetWidth(contentFrame) / documentWidth : 1.0]; - [_horizontalScroller setFrame:_CGRectMake(_CGRectGetMinX(contentFrame), _CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)]; + [_horizontalScroller setKnobProportion:documentWidth > 0 ? CGRectGetWidth(contentFrame) / documentWidth : 1.0]; + [_horizontalScroller setFrame:CGRectMake(CGRectGetMinX(contentFrame), CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)]; } else if (wasShowingHorizontalScroller) { @@ -1272,7 +1272,7 @@ Notifies the delegate when the scroll view has finished scrolling. { case CPLineBorder: CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"border-color"]); - CGContextStrokeRect(context, _CGRectInset(strokeRect, 0.5, 0.5)); + CGContextStrokeRect(context, CGRectInset(strokeRect, 0.5, 0.5)); break; case CPBezelBorder: @@ -1290,10 +1290,10 @@ Notifies the delegate when the scroll view has finished scrolling. - (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect { - var minX = _CGRectGetMinX(aRect), - maxX = _CGRectGetMaxX(aRect), - minY = _CGRectGetMinY(aRect), - maxY = _CGRectGetMaxY(aRect), + var minX = CGRectGetMinX(aRect), + maxX = CGRectGetMaxX(aRect), + minY = CGRectGetMinY(aRect), + maxY = CGRectGetMaxY(aRect), y = minY + 0.5; // Slightly darker line on top. @@ -1324,10 +1324,10 @@ Notifies the delegate when the scroll view has finished scrolling. - (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect { - var minX = _CGRectGetMinX(aRect), - maxX = _CGRectGetMaxX(aRect), - minY = _CGRectGetMinY(aRect), - maxY = _CGRectGetMaxY(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]); @@ -1357,11 +1357,11 @@ Notifies the delegate when the scroll view has finished scrolling. CGContextBeginPath(context); CGContextSetStrokeColor(context, [CPColor whiteColor]); - var rect = _CGRectOffset(aRect, 1.0, 1.0); + var rect = CGRectOffset(aRect, 1.0, 1.0); rect.size.width -= 1.0; rect.size.height -= 1.0; - CGContextStrokeRect(context, _CGRectInset(rect, 0.5, 0.5)); + CGContextStrokeRect(context, CGRectInset(rect, 0.5, 0.5)); CGContextBeginPath(context); CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]); @@ -1395,29 +1395,29 @@ Notifies the delegate when the scroll view has finished scrolling. - (void)scrollPageUp:(id)sender { var contentBounds = [_contentView bounds]; - [self moveByOffset:CGSizeMake(0.0, -(_CGRectGetHeight(contentBounds) - _verticalPageScroll))]; + [self moveByOffset:CGSizeMake(0.0, -(CGRectGetHeight(contentBounds) - _verticalPageScroll))]; } - (void)scrollPageDown:(id)sender { var contentBounds = [_contentView bounds]; - [self moveByOffset:CGSizeMake(0.0, _CGRectGetHeight(contentBounds) - _verticalPageScroll)]; + [self moveByOffset:CGSizeMake(0.0, CGRectGetHeight(contentBounds) - _verticalPageScroll)]; } - (void)scrollToBeginningOfDocument:(id)sender { - [_contentView scrollToPoint:_CGPointMakeZero()]; - [_headerClipView scrollToPoint:_CGPointMakeZero()]; + [_contentView scrollToPoint:CGPointMakeZero()]; + [_headerClipView scrollToPoint:CGPointMakeZero()]; } - (void)scrollToEndOfDocument:(id)sender { var contentBounds = [_contentView bounds], documentFrame = [[self documentView] frame], - scrollPoint = _CGPointMake(0.0, _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)); + scrollPoint = CGPointMake(0.0, CGRectGetHeight(documentFrame) - CGRectGetHeight(contentBounds)); [_contentView scrollToPoint:scrollPoint]; - [_headerClipView scrollToPoint:_CGPointMakeZero()]; + [_headerClipView scrollToPoint:CGPointMakeZero()]; } - (void)moveLeft:(id)sender diff --git a/AppKit/CPScroller.j b/AppKit/CPScroller.j index 92afb74ca..e5a19a0f8 100644 --- a/AppKit/CPScroller.j +++ b/AppKit/CPScroller.j @@ -116,11 +116,11 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); @"decrement-line-color": [CPNull null], @"increment-line-color": [CPNull null], @"knob-color": [CPNull null], - @"decrement-line-size":_CGSizeMakeZero(), - @"increment-line-size":_CGSizeMakeZero(), - @"track-inset":_CGInsetMakeZero(), - @"knob-inset": _CGInsetMakeZero(), - @"minimum-knob-length":21.0, + @"decrement-line-size": CGSizeMakeZero(), + @"increment-line-size": CGSizeMakeZero(), + @"track-inset": CGInsetMakeZero(), + @"knob-inset": CGInsetMakeZero(), + @"minimum-knob-length": 21.0, @"track-border-overlay": 9.0 }; } @@ -194,7 +194,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); // We have to choose an orientation. If for some bizarre reason width === height, // punt and choose vertical. - [self _setIsVertical:_CGRectGetHeight(aFrame) >= _CGRectGetWidth(aFrame)]; + [self _setIsVertical:CGRectGetHeight(aFrame) >= CGRectGetWidth(aFrame)]; } return self; @@ -321,7 +321,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); - (CGRect)rectForPart:(CPScrollerPart)aPart { if (aPart == CPScrollerNoPart) - return _CGRectMakeZero(); + return CGRectMakeZero(); return _partRects[aPart]; } @@ -391,8 +391,8 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); var knobInset = [self currentValueForThemeAttribute:@"knob-inset"], trackInset = [self currentValueForThemeAttribute:@"track-inset"], - width = _CGRectGetWidth(bounds), - height = _CGRectGetHeight(bounds); + width = CGRectGetWidth(bounds), + height = CGRectGetHeight(bounds); if ([self isVertical]) { @@ -406,21 +406,21 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); knobHeight = MAX(minimumKnobLength, (slotSize * _knobProportion)), knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight) * [self floatValue]; - _partRects[CPScrollerDecrementPage] = _CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight); - _partRects[CPScrollerKnob] = _CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight); - _partRects[CPScrollerIncrementPage] = _CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight); - _partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotSize); - _partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height); - _partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height); + _partRects[CPScrollerDecrementPage] = CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight); + _partRects[CPScrollerKnob] = CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight); + _partRects[CPScrollerIncrementPage] = CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight); + _partRects[CPScrollerKnobSlot] = CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotSize); + _partRects[CPScrollerDecrementLine] = CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height); + _partRects[CPScrollerIncrementLine] = CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height); if (height < knobHeight + decrementLineSize.height + incrementLineSize.height + trackInset.top + trackInset.bottom) - _partRects[CPScrollerKnob] = _CGRectMakeZero(); + _partRects[CPScrollerKnob] = CGRectMakeZero(); if (height < decrementLineSize.height + incrementLineSize.height - 2) { - _partRects[CPScrollerIncrementLine] = _CGRectMakeZero(); - _partRects[CPScrollerDecrementLine] = _CGRectMakeZero(); - _partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height); + _partRects[CPScrollerIncrementLine] = CGRectMakeZero(); + _partRects[CPScrollerDecrementLine] = CGRectMakeZero(); + _partRects[CPScrollerKnobSlot] = CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height); } } else @@ -435,21 +435,21 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); knobHeight = height - knobInset.top - knobInset.bottom, knobLocation = effectiveDecrementLineWidth + (slotSize - knobWidth) * [self floatValue]; - _partRects[CPScrollerDecrementPage] = _CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height); - _partRects[CPScrollerKnob] = _CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight); - _partRects[CPScrollerIncrementPage] = _CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height); - _partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotSize, height - trackInset.top - trackInset.bottom); - _partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height); - _partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height); + _partRects[CPScrollerDecrementPage] = CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height); + _partRects[CPScrollerKnob] = CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight); + _partRects[CPScrollerIncrementPage] = CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height); + _partRects[CPScrollerKnobSlot] = CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotSize, height - trackInset.top - trackInset.bottom); + _partRects[CPScrollerDecrementLine] = CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height); + _partRects[CPScrollerIncrementLine] = CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height); if (width < knobWidth + decrementLineSize.width + incrementLineSize.width + trackInset.left + trackInset.right) - _partRects[CPScrollerKnob] = _CGRectMakeZero(); + _partRects[CPScrollerKnob] = CGRectMakeZero(); if (width < decrementLineSize.width + incrementLineSize.width - 2) { - _partRects[CPScrollerIncrementLine] = _CGRectMakeZero(); - _partRects[CPScrollerDecrementLine] = _CGRectMakeZero(); - _partRects[CPScrollerKnobSlot] = _CGRectMake(0.0, 0.0, width, slotSize); + _partRects[CPScrollerIncrementLine] = CGRectMakeZero(); + _partRects[CPScrollerDecrementLine] = CGRectMakeZero(); + _partRects[CPScrollerKnobSlot] = CGRectMake(0.0, 0.0, width, slotSize); } } } @@ -517,7 +517,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); - (CPView)createViewForPart:(CPScrollerPart)aPart { - var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + var view = [[CPView alloc] initWithFrame:CGRectMakeZero()]; [view setHitTests:NO]; @@ -531,7 +531,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); - (CPView)createEphemeralSubviewNamed:(CPString)aName { - var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + var view = [[CPView alloc] initWithFrame:CGRectMakeZero()]; [view setHitTests:NO]; @@ -606,7 +606,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); { var knobRect = [self rectForPart:CPScrollerKnob], knobSlotRect = [self rectForPart:CPScrollerKnobSlot], - remainder = ![self isVertical] ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect)); + remainder = ![self isVertical] ? (CGRectGetWidth(knobSlotRect) - CGRectGetWidth(knobRect)) : (CGRectGetHeight(knobSlotRect) - CGRectGetHeight(knobRect)); if (remainder <= 0) [self setFloatValue:0.0]; @@ -660,11 +660,11 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark"); else if (_trackingPart === CPScrollerDecrementPage || _trackingPart === CPScrollerIncrementPage) { var knobRect = [self rectForPart:CPScrollerKnob], - knobWidth = ![self isVertical] ? _CGRectGetWidth(knobRect) : _CGRectGetHeight(knobRect), + knobWidth = ![self isVertical] ? CGRectGetWidth(knobRect) : CGRectGetHeight(knobRect), knobSlotRect = [self rectForPart:CPScrollerKnobSlot], - remainder = (![self isVertical] ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth; + remainder = (![self isVertical] ? CGRectGetWidth(knobSlotRect) : CGRectGetHeight(knobSlotRect)) - knobWidth; - [self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder]; + [self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder]; _hitPart = CPScrollerKnob; diff --git a/AppKit/CPSearchField.j b/AppKit/CPSearchField.j index 11a2ce4ef..4fea175d5 100644 --- a/AppKit/CPSearchField.j +++ b/AppKit/CPSearchField.j @@ -229,22 +229,22 @@ var RECENT_SEARCH_PREFIX = @" "; - (CGRect)searchTextRectForBounds:(CGRect)rect { var leftOffset = 0, - width = _CGRectGetWidth(rect), + width = CGRectGetWidth(rect), bounds = [self bounds]; if (_searchButton) { var searchBounds = [self searchButtonRectForBounds:bounds]; - leftOffset = _CGRectGetMaxX(searchBounds) + 2; + leftOffset = CGRectGetMaxX(searchBounds) + 2; } if (_cancelButton) { var cancelRect = [self cancelButtonRectForBounds:bounds]; - width = _CGRectGetMinX(cancelRect) - leftOffset; + width = CGRectGetMinX(cancelRect) - leftOffset; } - return _CGRectMake(leftOffset, _CGRectGetMinY(rect), width, _CGRectGetHeight(rect)); + return CGRectMake(leftOffset, CGRectGetMinY(rect), width, CGRectGetHeight(rect)); } /*! @@ -256,7 +256,7 @@ var RECENT_SEARCH_PREFIX = @" "; { var size = [[self valueForThemeAttribute:@"image-search"] size] || CGSizeMakeZero(); - return _CGRectMake(5, (_CGRectGetHeight(rect) - size.height) / 2, size.width, size.height); + return CGRectMake(5, (CGRectGetHeight(rect) - size.height) / 2, size.width, size.height); } /*! @@ -268,7 +268,7 @@ var RECENT_SEARCH_PREFIX = @" "; { var size = [[self valueForThemeAttribute:@"image-cancel"] size] || CGSizeMakeZero(); - return _CGRectMake(_CGRectGetWidth(rect) - size.width - 5, (_CGRectGetHeight(rect) - size.width) / 2, size.height, size.height); + return CGRectMake(CGRectGetWidth(rect) - size.width - 5, (CGRectGetHeight(rect) - size.width) / 2, size.height, size.height); } // Managing Menu Templates @@ -482,7 +482,7 @@ var RECENT_SEARCH_PREFIX = @" "; - (CPView)hitTest:(CGPoint)aPoint { // Make sure a hit anywhere within the search field returns the search field itself - if (_CGRectContainsPoint([self frame], aPoint)) + if (CGRectContainsPoint([self frame], aPoint)) return self; else return nil; @@ -498,7 +498,7 @@ var RECENT_SEARCH_PREFIX = @" "; var location = [anEvent locationInWindow], point = [self convertPoint:location fromView:nil]; - if (_CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point)) + if (CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point)) { if (_searchMenuTemplate == nil) { @@ -510,7 +510,7 @@ var RECENT_SEARCH_PREFIX = @" "; else [self _showMenu]; } - else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point)) + else if (CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point)) [_cancelButton mouseDown:anEvent]; else [super mouseDown:anEvent]; diff --git a/AppKit/CPSegmentedControl.j b/AppKit/CPSegmentedControl.j index 2c04d19b8..28f8bdc95 100644 --- a/AppKit/CPSegmentedControl.j +++ b/AppKit/CPSegmentedControl.j @@ -63,8 +63,8 @@ CPSegmentSwitchTrackingMomentary = 2; @"vertical-alignment": CPCenterVerticalTextAlignment, @"image-position": CPImageLeft, @"image-scaling": CPImageScaleNone, - @"bezel-inset": _CGInsetMakeZero(), - @"content-inset": _CGInsetMakeZero(), + @"bezel-inset": CGInsetMakeZero(), + @"content-inset": CGInsetMakeZero(), @"left-segment-bezel-color": [CPNull null], @"right-segment-bezel-color": [CPNull null], @"center-segment-bezel-color": [CPNull null], @@ -564,9 +564,9 @@ CPSegmentSwitchTrackingMomentary = 2; - (CPView)createEphemeralSubviewNamed:(CPString)aName { if ([aName hasPrefix:@"segment-content"]) - return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()]; + return [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()]; - return [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + return [[CPView alloc] initWithFrame:CGRectMakeZero()]; } - (void)layoutSubviews diff --git a/AppKit/CPShadowView.j b/AppKit/CPShadowView.j index fb1092022..942477ecf 100644 --- a/AppKit/CPShadowView.j +++ b/AppKit/CPShadowView.j @@ -60,7 +60,7 @@ CPThemeStateShadowViewHeavy = CPThemeState("shadowview-style-heavy"); var shadowView = [CPShadowView new], inset = [shadowView valueForThemeAttribute:@"content-inset" inState:(aWeight == CPLightShadow) ? CPThemeStateShadowViewLight : CPThemeStateShadowViewHeavy]; - return CGRectMake(_CGRectGetMinX(aFrame) - inset.left, _CGRectGetMinY(aFrame) - inset.top, _CGRectGetWidth(aFrame) + inset.left + inset.right, _CGRectGetHeight(aFrame) + inset.top + inset.bottom); + return CGRectMake(CGRectGetMinX(aFrame) - inset.left, CGRectGetMinY(aFrame) - inset.top, CGRectGetWidth(aFrame) + inset.left + inset.right, CGRectGetHeight(aFrame) + inset.top + inset.bottom); } + (id)shadowViewEnclosingView:(CPView)aView diff --git a/AppKit/CPSlider.j b/AppKit/CPSlider.j index 54bc0c36f..b9b7e92da 100644 --- a/AppKit/CPSlider.j +++ b/AppKit/CPSlider.j @@ -53,7 +53,7 @@ CPCircularSlider = 1; { return @{ @"knob-color": [CPNull null], - @"knob-size": _CGSizeMakeZero(), + @"knob-size": CGSizeMakeZero(), @"track-width": 0.0, @"track-color": [CPNull null], }; @@ -162,16 +162,16 @@ CPCircularSlider = 1; var trackWidth = [self currentValueForThemeAttribute:@"track-width"]; if (trackWidth <= 0) - return _CGRectMakeZero(); + return CGRectMakeZero(); if ([self isVertical]) { - bounds.origin.x = (_CGRectGetWidth(bounds) - trackWidth) / 2.0; + bounds.origin.x = (CGRectGetWidth(bounds) - trackWidth) / 2.0; bounds.size.width = trackWidth; } else { - bounds.origin.y = (_CGRectGetHeight(bounds) - trackWidth) / 2.0; + bounds.origin.y = (CGRectGetHeight(bounds) - trackWidth) / 2.0; bounds.size.height = trackWidth; } } @@ -184,13 +184,13 @@ CPCircularSlider = 1; var knobSize = [self currentValueForThemeAttribute:@"knob-size"]; if (knobSize.width <= 0 || knobSize.height <= 0) - return _CGRectMakeZero(); + return CGRectMakeZero(); - var knobRect = _CGRectMake(0.0, 0.0, knobSize.width, knobSize.height), + var knobRect = CGRectMake(0.0, 0.0, knobSize.width, knobSize.height), trackRect = [self trackRectForBounds:bounds]; // No track, do our best to approximate a place for this thing. - if (!trackRect || _CGRectIsEmpty(trackRect)) + if (!trackRect || CGRectIsEmpty(trackRect)) trackRect = bounds; if ([self hasThemeState:CPThemeStateCircular]) @@ -203,13 +203,13 @@ CPCircularSlider = 1; } else if ([self isVertical]) { - knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0; - knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height); + knobRect.origin.x = CGRectGetMidX(trackRect) - knobSize.width / 2.0; + knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (CGRectGetHeight(trackRect) - knobSize.height); } else { - knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetWidth(trackRect) - knobSize.width); - knobRect.origin.y = _CGRectGetMidY(trackRect) - knobSize.height / 2.0; + knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (CGRectGetWidth(trackRect) - knobSize.width); + knobRect.origin.y = CGRectGetMidY(trackRect) - knobSize.height / 2.0; } return knobRect; @@ -260,8 +260,8 @@ CPCircularSlider = 1; { // Recalculate isVertical. var bounds = [self bounds], - width = _CGRectGetWidth(bounds), - height = _CGRectGetHeight(bounds); + width = CGRectGetWidth(bounds), + height = CGRectGetHeight(bounds); _isVertical = width < height ? 1 : (width > height ? 0 : -1); @@ -306,55 +306,55 @@ CPCircularSlider = 1; if ([self hasThemeState:CPThemeStateCircular]) { - var knobWidth = _CGRectGetWidth(knobRect); + var knobWidth = CGRectGetWidth(knobRect); trackRect.origin.x += knobWidth / 2; trackRect.size.width -= knobWidth; var minValue = [self minValue], - dx = aPoint.x - _CGRectGetMidX(trackRect), - dy = aPoint.y - _CGRectGetMidY(trackRect); + dx = aPoint.x - CGRectGetMidX(trackRect), + dy = aPoint.y - CGRectGetMidY(trackRect); return MAX(0.0, MIN(1.0, 1.0 - (3 * PI_2 - ATAN2(dy, dx)) % PI2 / PI2)) * ([self maxValue] - minValue) + minValue; } else if ([self isVertical]) { - var knobHeight = _CGRectGetHeight(knobRect); + var knobHeight = CGRectGetHeight(knobRect); trackRect.origin.y += knobHeight / 2; trackRect.size.height -= knobHeight; var minValue = [self minValue]; - return MAX(0.0, MIN(1.0, (_CGRectGetMaxY(trackRect) - aPoint.y) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue; + return MAX(0.0, MIN(1.0, (CGRectGetMaxY(trackRect) - aPoint.y) / CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue; } else { - var knobWidth = _CGRectGetWidth(knobRect); + var knobWidth = CGRectGetWidth(knobRect); trackRect.origin.x += knobWidth / 2; trackRect.size.width -= knobWidth; var minValue = [self minValue]; - return MAX(0.0, MIN(1.0, (aPoint.x - _CGRectGetMinX(trackRect)) / _CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue; + return MAX(0.0, MIN(1.0, (aPoint.x - CGRectGetMinX(trackRect)) / CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue; } } - (BOOL)startTrackingAt:(CGPoint)aPoint { var bounds = [self bounds], - knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)]; + knobRect = [self knobRectForBounds:CGRectMakeCopy(bounds)]; - if (_CGRectContainsPoint(knobRect, aPoint)) - _dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y); + if (CGRectContainsPoint(knobRect, aPoint)) + _dragOffset = CGSizeMake(CGRectGetMidX(knobRect) - aPoint.x, CGRectGetMidY(knobRect) - aPoint.y); else { var trackRect = [self trackRectForBounds:bounds]; - if (trackRect && _CGRectContainsPoint(trackRect, aPoint)) + if (trackRect && CGRectContainsPoint(trackRect, aPoint)) { - _dragOffset = _CGSizeMakeZero(); + _dragOffset = CGSizeMakeZero(); [self setObjectValue:[self _valueAtPoint:aPoint]]; } @@ -373,7 +373,7 @@ CPCircularSlider = 1; - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint { - [self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]]; + [self setObjectValue:[self _valueAtPoint:CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]]; return YES; } diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index f9090ea8a..7e62a4d5d 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -334,8 +334,8 @@ var ShouldSuppressResizeNotifications = 1, } [self _setupDOMDivider]; - CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect)); - CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); + CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, CGRectGetMinX(aRect), CGRectGetMinY(aRect)); + CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], CGRectGetWidth(aRect), CGRectGetHeight(aRect)); #endif } @@ -1110,7 +1110,7 @@ The sum of the views and the sum of the dividers should be equal to the size of */ - (void)_restoreFromAutosaveIfNeeded { - if (_shouldRestoreFromAutosaveUnlessFrameSize && !_CGSizeEqualToSize([self frameSize], _shouldRestoreFromAutosaveUnlessFrameSize)) + if (_shouldRestoreFromAutosaveUnlessFrameSize && !CGSizeEqualToSize([self frameSize], _shouldRestoreFromAutosaveUnlessFrameSize)) { [self _restoreFromAutosave]; } diff --git a/AppKit/CPStepper.j b/AppKit/CPStepper.j index 15b16684b..0e7fc7586 100644 --- a/AppKit/CPStepper.j +++ b/AppKit/CPStepper.j @@ -55,7 +55,7 @@ */ + (CPStepper)stepperWithInitialValue:(float)aValue minValue:(float)aMinValue maxValue:(float)aMaxValue { - var stepper = [[CPStepper alloc] initWithFrame:_CGRectMakeZero()]; + var stepper = [[CPStepper alloc] initWithFrame:CGRectMakeZero()]; [stepper setDoubleValue:aValue]; [stepper setMinValue:aMinValue]; @@ -122,14 +122,14 @@ - (void)_init { - _buttonUp = [[CPButton alloc] initWithFrame:_CGRectMakeZero()]; + _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 = [[CPButton alloc] initWithFrame:CGRectMakeZero()]; [_buttonDown setContinuous:_autorepeat]; [_buttonDown setTarget:self]; [_buttonDown setAction:@selector(_buttonDidClick:)]; @@ -161,8 +161,8 @@ { var upSize = [self valueForThemeAttribute:@"up-button-size"], downSize = [self valueForThemeAttribute:@"down-button-size"], - minSize = _CGSizeMake(upSize.width, upSize.height + downSize.height), - frame = _CGRectMakeCopy(aFrame); + minSize = CGSizeMake(upSize.width, upSize.height + downSize.height), + frame = CGRectMakeCopy(aFrame); frame.size.width = MAX(minSize.width, frame.size.width); frame.size.height = MAX(minSize.height, frame.size.height); @@ -175,8 +175,8 @@ var aFrame = [self frame], upSize = [self valueForThemeAttribute:@"up-button-size"], downSize = [self valueForThemeAttribute:@"down-button-size"], - upFrame = _CGRectMake(aFrame.size.width - upSize.width, 0, upSize.width, upSize.height), - downFrame = _CGRectMake(aFrame.size.width - downSize.width, upSize.height, downSize.width, downSize.height); + upFrame = CGRectMake(aFrame.size.width - upSize.width, 0, upSize.width, upSize.height), + downFrame = CGRectMake(aFrame.size.width - downSize.width, upSize.height, downSize.width, downSize.height); [_buttonUp setFrame:upFrame]; [_buttonDown setFrame:downFrame]; @@ -272,8 +272,8 @@ return @{ @"bezel-color-up-button": [CPNull null], @"bezel-color-down-button": [CPNull null], - @"up-button-size": _CGSizeMakeZero(), - @"down-button-size": _CGSizeMakeZero(), + @"up-button-size": CGSizeMakeZero(), + @"down-button-size": CGSizeMakeZero(), }; } diff --git a/AppKit/CPTabView.j b/AppKit/CPTabView.j index c1959e439..b6874a01b 100644 --- a/AppKit/CPTabView.j +++ b/AppKit/CPTabView.j @@ -79,11 +79,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1, { _selectedIndex = CPNotFound; - _tabs = [[CPSegmentedControl alloc] initWithFrame:_CGRectMake(0, 0, 0, 0)]; + _tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; [_tabs setHitTests:NO]; var height = [_tabs valueForThemeAttribute:@"default-height"]; - [_tabs setFrameSize:_CGSizeMake(0, height)]; + [_tabs setFrameSize:CGSizeMake(0, height)]; _box = [[CPBox alloc] initWithFrame:[self bounds]]; [self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]]; @@ -373,11 +373,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1, else { var aFrame = [self frame], - segmentedHeight = _CGRectGetHeight([_tabs frame]), + segmentedHeight = CGRectGetHeight([_tabs frame]), origin = _type === CPTopTabsBezelBorder ? segmentedHeight / 2 : 0; - [_box setFrame:_CGRectMake(0, origin, _CGRectGetWidth(aFrame), - _CGRectGetHeight(aFrame) - segmentedHeight / 2)]; + [_box setFrame:CGRectMake(0, origin, CGRectGetWidth(aFrame), + CGRectGetHeight(aFrame) - segmentedHeight / 2)]; [self _repositionTabs]; } @@ -447,13 +447,13 @@ var CPTabViewDidSelectTabViewItemSelector = 1, - (void)_repositionTabs { - var horizontalCenterOfSelf = _CGRectGetWidth([self bounds]) / 2, - verticalCenterOfTabs = _CGRectGetHeight([_tabs bounds]) / 2; + var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2, + verticalCenterOfTabs = CGRectGetHeight([_tabs bounds]) / 2; if (_type === CPBottomTabsBezelBorder) - [_tabs setCenter:_CGPointMake(horizontalCenterOfSelf, _CGRectGetHeight([self bounds]) - verticalCenterOfTabs)]; + [_tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)]; else - [_tabs setCenter:_CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)]; + [_tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)]; } - (void)_setSelectedIndex:(CPNumber)index @@ -504,8 +504,6 @@ var CPTabViewItemsKey = "CPTabViewItemsKey", _items = [aCoder decodeObjectForKey:CPTabViewItemsKey]; [_items makeObjectsPerformSelector:@selector(_setTabView:) withObject:self]; - [self _updateItems]; - [self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]]; self.selectOnAwake = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey]; @@ -517,6 +515,10 @@ var CPTabViewItemsKey = "CPTabViewItemsKey", - (void)awakeFromCib { + // This cannot be run in initWithCoder because it might call selectTabViewItem:, which is + // not safe to call before the views of the tab views items are fully decoded. + [self _updateItems]; + if (self.selectOnAwake) { [self selectTabViewItem:self.selectOnAwake]; @@ -532,7 +534,13 @@ var CPTabViewItemsKey = "CPTabViewItemsKey", - (void)encodeWithCoder:(CPCoder)aCoder { + // Don't bother to encode the CPBox. We will recreate it on decode and its content view is already + // stored by the tab view item. Not encoding _box makes the resulting archive smaller and reduces + // the surface for decoding bugs (of which we've had many in tab view). + var subviews = [self subviews]; + [_box removeFromSuperview]; [super encodeWithCoder:aCoder]; + [self setSubviews:subviews]; [aCoder encodeObject:_items forKey:CPTabViewItemsKey]; diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j index e0cf361f9..823fdc73a 100644 --- a/AppKit/CPTableColumn.j +++ b/AppKit/CPTableColumn.j @@ -283,7 +283,7 @@ CPTableColumnUserResizingMask = 1 << 1; */ - (void)sizeToFit { - var width = _CGRectGetWidth([_headerView frame]); + var width = CGRectGetWidth([_headerView frame]); if (width < [self minWidth]) [self setMinWidth:width]; diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index cd5e43c9b..c98fab98b 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -69,7 +69,7 @@ - (void)_init { - _textField = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()]; + _textField = [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()]; [_textField setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; @@ -87,7 +87,7 @@ var inset = [self currentValueForThemeAttribute:@"text-inset"], bounds = [self bounds]; - [_textField setFrame:_CGRectMake(inset.right, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)]; + [_textField setFrame:CGRectMake(inset.right, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)]; [_textField setTextColor:[self currentValueForThemeAttribute:@"text-color"]]; [_textField setFont:[self currentValueForThemeAttribute:@"font"]]; [_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]]; @@ -256,8 +256,8 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal - (void)_init { - _mouseDownLocation = _CGPointMakeZero(); - _previousTrackingLocation = _CGPointMakeZero(); + _mouseDownLocation = CGPointMakeZero(); + _previousTrackingLocation = CGPointMakeZero(); _activeColumn = -1; _pressedColumn = -1; @@ -291,8 +291,8 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal var headerRect = CGRectMakeCopy([self bounds]), columnRect = [_tableView rectOfColumn:aColumnIndex]; - headerRect.origin.x = _CGRectGetMinX(columnRect); - headerRect.size.width = _CGRectGetWidth(columnRect); + headerRect.origin.x = CGRectGetMinX(columnRect); + headerRect.size.width = CGRectGetWidth(columnRect); return headerRect; } @@ -310,11 +310,11 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal - (CGRect)_cursorRectForColumn:(int)column { if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask)) - return _CGRectMakeZero(); + return CGRectMakeZero(); var rect = [self headerRectOfColumn:column]; - rect.origin.x = _CGRectGetMaxX(rect) - 5; + rect.origin.x = CGRectGetMaxX(rect) - 5; rect.size.width = 20; return rect; @@ -354,7 +354,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal currentLocation.x -= 5.0; var columnIndex = [self columnAtPoint:currentLocation], - shouldResize = [self shouldResizeTableColumn:columnIndex at:_CGPointMake(currentLocation.x + 5.0, currentLocation.y)]; + shouldResize = [self shouldResizeTableColumn:columnIndex at:CGPointMake(currentLocation.x + 5.0, currentLocation.y)]; if (type === CPLeftMouseUp) { @@ -398,7 +398,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal [self continueResizingTableColumn:_activeColumn at:currentLocation]; else { - if (_activeColumn === columnIndex && _CGRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation)) + if (_activeColumn === columnIndex && CGRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation)) { if (_isTrackingColumn && _pressedColumn !== -1) { @@ -427,14 +427,14 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal if ([self _shouldDragTableColumn:aColumnIndex at:aPoint]) { var columnRect = [self headerRectOfColumn:aColumnIndex], - offset = _CGPointMakeZero(), + offset = CGPointMakeZero(), view = [_tableView _dragViewForColumn:aColumnIndex event:[CPApp currentEvent] offset:offset], - viewLocation = _CGPointMakeZero(); + viewLocation = CGPointMakeZero(); - viewLocation.x = ( _CGRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x ); - viewLocation.y = _CGRectGetMinY(columnRect) + offset.y; + viewLocation.x = ( CGRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x ); + viewLocation.y = CGRectGetMinY(columnRect) + offset.y; - [self dragView:view at:viewLocation offset:_CGSizeMakeZero() event:[CPApp currentEvent] + [self dragView:view at:viewLocation offset:CGSizeMakeZero() event:[CPApp currentEvent] pasteboard:[CPPasteboard pasteboardWithName:CPDragPboard] source:self slideBack:YES]; return NO; @@ -446,7 +446,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal - (BOOL)_shouldStopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint { return _isTrackingColumn && _activeColumn === aColumnIndex && - _CGRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint); + CGRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint); } - (void)stopTrackingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint @@ -490,10 +490,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal frame.origin = [self convertPoint:frame.origin fromView:nil]; // This effectively clamps the value between the minimum and maximum - frame.origin.x = MAX(0.0, MIN(_CGRectGetMinX(frame), _CGRectGetMaxX(lastColumnRect) - _CGRectGetWidth(activeColumnRect))); + frame.origin.x = MAX(0.0, MIN(CGRectGetMinX(frame), CGRectGetMaxX(lastColumnRect) - CGRectGetWidth(activeColumnRect))); // Make sure the column cannot move vertically - frame.origin.y = _CGRectGetMinY(lastColumnRect); + frame.origin.y = CGRectGetMinY(lastColumnRect); // Convert the calculated origin back to the window coordinate system frame.origin = [self convertPoint:frame.origin toView:nil]; @@ -535,9 +535,9 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal var hoverPoint = CGPointCreateCopy(aPoint); if (aPoint.x < _previousTrackingLocation.x) - hoverPoint = _CGPointMake(_CGRectGetMinX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame)); + hoverPoint = CGPointMake(CGRectGetMinX(dragWindowFrame), CGRectGetMinY(dragWindowFrame)); else if (aPoint.x > _previousTrackingLocation.x) - hoverPoint = _CGPointMake(_CGRectGetMaxX(dragWindowFrame), _CGRectGetMinY(dragWindowFrame)); + hoverPoint = CGPointMake(CGRectGetMaxX(dragWindowFrame), CGRectGetMinY(dragWindowFrame)); // Convert the hover point from the global coordinate system to windows' coordinate system hoverPoint = [[self window] convertGlobalToBase:hoverPoint]; @@ -549,7 +549,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal if (hoveredColumn !== _lastDragDestinationColumnIndex && hoveredColumn !== -1) { var columnRect = [self headerRectOfColumn:hoveredColumn], - columnCenterPoint = [self convertPoint:CGPointMake(_CGRectGetMidX(columnRect), _CGRectGetMidY(columnRect)) fromView:self]; + columnCenterPoint = [self convertPoint:CGPointMake(CGRectGetMidX(columnRect), CGRectGetMidY(columnRect)) fromView:self]; if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x) { @@ -588,7 +588,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal if (_isTrackingColumn) return NO; - return [_tableView allowsColumnResizing] && _CGRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint); + return [_tableView allowsColumnResizing] && CGRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint); } - (void)startResizingTableColumn:(int)aColumnIndex at:(CGPoint)aPoint @@ -644,7 +644,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y), overColumn = [self columnAtPoint:mouseOverLocation]; - if (overColumn >= 0 && _CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation)) + if (overColumn >= 0 && CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation)) { var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn], width = [tableColumn width]; @@ -733,10 +733,10 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal var columnIndex = columnsArray[columnArrayIndex], columnToStroke = [self headerRectOfColumn:columnIndex]; - columnMaxX = _CGRectGetMaxX(columnToStroke); + columnMaxX = CGRectGetMaxX(columnToStroke); - CGContextMoveToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMinY(columnToStroke))); - CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(_CGRectGetMaxY(columnToStroke)) - 1.0); + CGContextMoveToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(CGRectGetMinY(columnToStroke))); + CGContextAddLineToPoint(context, FLOOR(columnMaxX) - 0.5, ROUND(CGRectGetMaxY(columnToStroke)) - 1.0); } CGContextClosePath(context); diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 0306ad670..50ca17411 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -62,7 +62,8 @@ var CPTableViewDataSource_numberOfRowsInTableView_ CPTableViewDataSource_tableView_sortDescriptorsDidChange_ = 1 << 7; var CPTableViewDelegate_selectionShouldChangeInTableView_ = 1 << 0, - CPTableViewDelegate_tableView_dataViewForTableColumn_row_ = 1 << 1, + CPTableViewDelegate_tableView_viewForTableColumn_row_ = 1 << 1, + CPTableViewDelegate_tableView_dataViewForTableColumn_row_ = 1 << 21, CPTableViewDelegate_tableView_didClickTableColumn_ = 1 << 2, CPTableViewDelegate_tableView_didDragTableColumn_ = 1 << 3, CPTableViewDelegate_tableView_heightOfRow_ = 1 << 4, @@ -93,9 +94,9 @@ CPTableViewDraggingDestinationFeedbackStyleSourceList = 1; CPTableViewDropOn = 0; CPTableViewDropAbove = 1; -CPSourceListGradient = "CPSourceListGradient"; -CPSourceListTopLineColor = "CPSourceListTopLineColor"; -CPSourceListBottomLineColor = "CPSourceListBottomLineColor"; +CPSourceListGradient = @"CPSourceListGradient"; +CPSourceListTopLineColor = @"CPSourceListTopLineColor"; +CPSourceListBottomLineColor = @"CPSourceListBottomLineColor"; // TODO: add docs @@ -138,7 +139,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var frame = [self frame], context = [[CPGraphicsContext currentContext] graphicsPort]; - CGContextTranslateCTM(context, -_CGRectGetMinX(frame), -_CGRectGetMinY(frame)); + CGContextTranslateCTM(context, -CGRectGetMinX(frame), -CGRectGetMinY(frame)); [_tableView _drawRect:aRect]; } @@ -210,6 +211,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; CPArray _alternatingRowBackgroundColors; unsigned _selectionHighlightStyle; + CPColor _unfocusedSelectionHighlightColor; + CPDictionary _unfocusedSourceListSelectionColor; CPTableColumn _currentHighlightedTableColumn; unsigned _gridStyleMask; @@ -264,6 +267,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; BOOL _isViewBased; BOOL _contentBindingExpicitelySet; + SEL _viewForTableColumnRowSelector; + CPTableColumn _draggedColumn; CPArray _differedColumnDataToRemove; } @@ -321,14 +326,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _dirtyTableColumnRangeIndex = CPNotFound; _numberOfHiddenColumns = 0; - _intercellSpacing = _CGSizeMake(3.0, 2.0); + _intercellSpacing = CGSizeMake(3.0, 2.0); _rowHeight = [self valueForThemeAttribute:@"default-row-height"]; [self setGridColor:[CPColor colorWithHexString:@"dce0e2"]]; [self setGridStyleMask:CPTableViewGridNone]; - [self setHeaderView:[[CPTableHeaderView alloc] initWithFrame:_CGRectMake(0, 0, [self bounds].size.width, _rowHeight)]]; - [self setCornerView:[[_CPCornerView alloc] initWithFrame:_CGRectMake(0, 0, [CPScroller scrollerWidth], _CGRectGetHeight([_headerView frame]))]]; + [self setHeaderView:[[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)]]; + [self setCornerView:[[_CPCornerView alloc] initWithFrame:CGRectMake(0, 0, [CPScroller scrollerWidth], CGRectGetHeight([_headerView frame]))]]; _currentHighlightedTableColumn = nil; @@ -361,7 +366,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _selectedColumnIndexes = [CPIndexSet indexSet]; _selectedRowIndexes = [CPIndexSet indexSet]; - _dropOperationFeedbackView = [[_CPDropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; + _dropOperationFeedbackView = [[_CPDropOperationDrawingView alloc] initWithFrame:CGRectMakeZero()]; [_dropOperationFeedbackView setTableView:self]; _lastColumnShouldSnap = NO; @@ -380,6 +385,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _exposedColumns = [CPIndexSet indexSet]; _cachedDataViews = { }; _archivedDataViews = nil; + _viewForTableColumnRowSelector = nil; _unavailable_custom_cibs = { }; _cachedRowHeights = []; @@ -695,10 +701,10 @@ NOT YET IMPLEMENTED */ - (void)setIntercellSpacing:(CGSize)aSize { - if (_CGSizeEqualToSize(_intercellSpacing, aSize)) + if (CGSizeEqualToSize(_intercellSpacing, aSize)) return; - _intercellSpacing = _CGSizeMakeCopy(aSize); + _intercellSpacing = CGSizeMakeCopy(aSize); _dirtyTableColumnRangeIndex = 0; // so that _recalculateTableColumnRanges will work [self _recalculateTableColumnRanges]; @@ -715,7 +721,7 @@ NOT YET IMPLEMENTED */ - (CGSize)intercellSpacing { - return _CGSizeMakeCopy(_intercellSpacing); + return CGSizeMakeCopy(_intercellSpacing); } /*! @@ -813,12 +819,15 @@ NOT YET IMPLEMENTED - (void)setSelectionHighlightStyle:(unsigned)aSelectionHighlightStyle { _selectionHighlightStyle = aSelectionHighlightStyle; - [self setNeedsDisplay:YES]; if (aSelectionHighlightStyle === CPTableViewSelectionHighlightStyleSourceList) _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleSourceList; else _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; + + [self _updateHighlightWithOldRows:[CPIndexSet indexSet] newRows:_selectedRowIndexes]; + [self _updateHighlightWithOldColumns:[CPIndexSet indexSet] newColumns:_selectedColumnIndexes]; + [self setNeedsDisplay:YES]; } /*! @@ -828,19 +837,32 @@ NOT YET IMPLEMENTED */ - (void)setSelectionHighlightColor:(CPColor)aColor { - [self setValue:aColor forThemeAttribute:@"selection-color"]; + if ([[self selectionHighlightColor] isEqual:aColor]) + return; + [self setValue:aColor forThemeAttribute:@"selection-color"]; [self setNeedsDisplay:YES]; } /*! - Returns the highlight color for a row or column selection. + Returns the highlight color for a focused row or column selection. */ - (CPColor)selectionHighlightColor { return [self currentValueForThemeAttribute:@"selection-color"]; } +/*! + Returns the highlight color for an unfocused row or column selection. +*/ +- (CPColor)unfocusedSelectionHighlightColor +{ + if (!_unfocusedSelectionHighlightColor) + _unfocusedSelectionHighlightColor = [self _unfocusedSelectionColorFromColor:[self selectionHighlightColor] saturation:0]; + + return _unfocusedSelectionHighlightColor; +} + /*! Sets the highlight gradient for a row or column selection @@ -855,7 +877,6 @@ NOT YET IMPLEMENTED - (void)setSelectionGradientColors:(CPDictionary)aDictionary { [self setValue:aDictionary forThemeAttribute:@"sourcelist-selection-color"]; - [self setNeedsDisplay:YES]; } @@ -872,6 +893,54 @@ NOT YET IMPLEMENTED return [self currentValueForThemeAttribute:@"sourcelist-selection-color"]; } +/*! + Returns a dictionary of containing the keys: +
+    CPSourceListGradient
+    CPSourceListTopLineColor
+    CPSourceListBottomLineColor
+
+*/ + +- (void)unfocusedSelectionGradientColors +{ + if (!_unfocusedSourceListSelectionColor) + { + var sourceListColors = [self selectionGradientColors]; + + _unfocusedSourceListSelectionColor = @{ + CPSourceListGradient: [self _unfocusedGradientFromGradient:[sourceListColors objectForKey:CPSourceListGradient]], + CPSourceListTopLineColor: [self _unfocusedSelectionColorFromColor:[sourceListColors objectForKey:CPSourceListTopLineColor] saturation:0.2], + CPSourceListBottomLineColor: [self _unfocusedSelectionColorFromColor:[sourceListColors objectForKey:CPSourceListBottomLineColor] saturation:0.2] + }; + } + + return _unfocusedSourceListSelectionColor; +} + +- (CPColor)_unfocusedSelectionColorFromColor:(CPColor)aColor saturation:(float)saturation +{ + var hsb = [aColor hsbComponents]; + + return [CPColor colorWithHue:hsb[0] saturation:hsb[1] * saturation brightness:hsb[2]]; +} + +- (CGGradient)_unfocusedGradientFromGradient:(CGGradient)aGradient +{ + var colors = [aGradient.colors copy], + count = [colors count]; + + while (count--) + { + var rgba = colors[count].components, + hsb = [self _unfocusedSelectionColorFromColor:[CPColor colorWithRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]] saturation:0.2]; + + colors[count] = CGColorCreate(aGradient.colorspace, [[hsb components] copy]); + } + + return CGGradientCreateWithColors(aGradient.colorspace, colors, aGradient.locations); +} + /*! Sets the grid color in the non highlighted state. @param aColor a CPColor @@ -1244,30 +1313,31 @@ NOT YET IMPLEMENTED [deselectRowIndexes getIndexes:deselectRows maxCount:-1 inIndexRange:CPMakeRange(firstExposedRow, exposedLength)]; [selectRowIndexes getIndexes:selectRows maxCount:-1 inIndexRange:CPMakeRange(firstExposedRow, exposedLength)]; + var showsSelection = _selectionHighlightStyle !== CPTableViewSelectionHighlightStyleNone, + selectors = [@selector(unsetThemeState:), @selector(setThemeState:)], + selectInfo = [ + { rows:deselectRows, selectorIndex:0 }, + { rows:selectRows, selectorIndex:showsSelection ? 1 : 0 } + ]; + for (var identifier in _dataViewsForTableColumns) { - var dataViewsInTableColumn = _dataViewsForTableColumns[identifier], - count = deselectRows.length; - while (count--) - [self _performSelection:NO forRow:deselectRows[count] context:dataViewsInTableColumn]; + var dataViewsInTableColumn = _dataViewsForTableColumns[identifier] - count = selectRows.length; - while (count--) - [self _performSelection:YES forRow:selectRows[count] context:dataViewsInTableColumn]; + for (var i = 0; i < selectInfo.length; ++i) + { + var info = selectInfo[i], + count = info.rows.length; + + while (count--) + { + var view = dataViewsInTableColumn[info.rows[count]]; + [view performSelector:selectors[info.selectorIndex] withObject:CPThemeStateSelectedDataView]; + } + } } } -/*! - @ignore -*/ -- (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(id)context -{ - var view = context[rowIndex], - selector = select ? @"setThemeState:" : @"unsetThemeState:"; - - [view performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelectedDataView]; -} - /*! @ignore */ @@ -1286,45 +1356,50 @@ NOT YET IMPLEMENTED [selectColumnIndexes getIndexes:selectColumns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedLength)]; [_exposedRows getIndexes:selectRows maxCount:-1 inIndexRange:nil]; - var rowsCount = selectRows.length, - count = deselectColumns.length; - while (count--) + var showsSelection = _selectionHighlightStyle !== CPTableViewSelectionHighlightStyleNone, + selectors = [@selector(unsetThemeState:), @selector(setThemeState:)], + + // Rows do not show selection with CPTableViewSelectionHighlightStyleNone, but headers do + selectInfo = [ + { + columns:deselectColumns, + rowSelectorIndex:0, + headerSelectorIndex:0 + }, + { + columns:selectColumns, + rowSelectorIndex:showsSelection ? 1 : 0, + headerSelectorIndex:1 + } + ], + rowsCount = selectRows.length; + + for (var selectIndex = 0; selectIndex < selectInfo.length; ++selectIndex) { - var columnIndex = deselectColumns[count], - identifier = [_tableColumns[columnIndex] UID], - dataViewsInTableColumn = _dataViewsForTableColumns[identifier]; + var info = selectInfo[selectIndex], + count = info.columns.length, + rowSelector = selectors[info.rowSelectorIndex], + headerSelector = selectors[info.headerSelectorIndex]; - for (var i = 0; i < rowsCount; i++) + while (count--) { - var rowIndex = selectRows[i], - dataView = dataViewsInTableColumn[rowIndex]; - [dataView unsetThemeState:CPThemeStateSelectedDataView]; - } + var columnIndex = info.columns[count], + identifier = [_tableColumns[columnIndex] UID], + dataViewsInTableColumn = _dataViewsForTableColumns[identifier]; - if (_headerView) - { - var headerView = [_tableColumns[columnIndex] headerView]; - [headerView unsetThemeState:CPThemeStateSelected]; - } - } + for (var i = 0; i < rowsCount; i++) + { + var rowIndex = selectRows[i], + dataView = dataViewsInTableColumn[rowIndex]; - count = selectColumns.length; - while (count--) - { - var columnIndex = selectColumns[count], - identifier = [_tableColumns[columnIndex] UID], - dataViewsInTableColumn = _dataViewsForTableColumns[identifier]; + [dataView performSelector:rowSelector withObject:CPThemeStateSelectedDataView]; + } - for (var i = 0; i < rowsCount; i++) - { - var rowIndex = selectRows[i], - dataView = dataViewsInTableColumn[rowIndex]; - [dataView setThemeState:CPThemeStateSelectedDataView]; - } - if (_headerView) - { - var headerView = [_tableColumns[columnIndex] headerView]; - [headerView setThemeState:CPThemeStateSelected]; + if (_headerView) + { + var headerView = [_tableColumns[columnIndex] headerView]; + [headerView performSelector:headerSelector withObject:CPThemeStateSelected]; + } } } } @@ -1545,6 +1620,7 @@ NOT YET IMPLEMENTED { if (!_editingCellIndex) return CPNotFound; + return _editingCellIndex.x; } @@ -1555,6 +1631,7 @@ NOT YET IMPLEMENTED { if (!_editingCellIndex) return CPNotFound; + return _editingCellIndex.y; } @@ -1610,7 +1687,7 @@ NOT YET IMPLEMENTED if (_headerView) { [_headerView setTableView:self]; - [_headerView setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), _CGRectGetHeight([_headerView frame]))]; + [_headerView setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), CGRectGetHeight([_headerView frame]))]; } else { @@ -1680,18 +1757,18 @@ NOT YET IMPLEMENTED aColumnIndex = +aColumnIndex; if (aColumnIndex < 0 || aColumnIndex >= NUMBER_OF_COLUMNS()) - return _CGRectMakeZero(); + return CGRectMakeZero(); var column = [[self tableColumns] objectAtIndex:aColumnIndex]; if ([column isHidden]) - return _CGRectMakeZero(); + return CGRectMakeZero(); UPDATE_COLUMN_RANGES_IF_NECESSARY(); var range = _tableColumnRanges[aColumnIndex]; - return _CGRectMake(range.location, 0.0, range.length, _CGRectGetHeight([self bounds])); + return CGRectMake(range.location, 0.0, range.length, CGRectGetHeight([self bounds])); } // Complexity: @@ -1708,7 +1785,7 @@ NOT YET IMPLEMENTED var lastIndex = [self numberOfRows] - 1; if (checkRange && (aRowIndex > lastIndex || aRowIndex < 0)) - return _CGRectMakeZero(); + return CGRectMakeZero(); if (_implementedDelegateMethods & CPTableViewDelegate_tableView_heightOfRow_) { @@ -1740,7 +1817,7 @@ NOT YET IMPLEMENTED height = _rowHeight + _intercellSpacing.height; } - return _CGRectMake(0.0, y, _CGRectGetWidth([self bounds]), height); + return CGRectMake(0.0, y, CGRectGetWidth([self bounds]), height); } /*! @@ -1778,7 +1855,7 @@ NOT YET IMPLEMENTED if (firstRow < 0) firstRow = 0; - var lastRow = [self rowAtPoint:_CGPointMake(0.0, _CGRectGetMaxY(aRect))]; + var lastRow = [self rowAtPoint:CGPointMake(0.0, CGRectGetMaxY(aRect))]; // last row has to be overshot, because if not we wouldn't be intersecting. if (lastRow < 0) @@ -1796,8 +1873,8 @@ NOT YET IMPLEMENTED var boundedRange = [self rowsInRect:aRect], lastRow = CPMaxRange(boundedRange), rectOfLastRow = [self _rectOfRow:lastRow checkRange:NO], - bottom = _CGRectGetMaxY(aRect), - bottomOfBoundedRows = _CGRectGetMaxY(rectOfLastRow); + bottom = CGRectGetMaxY(aRect), + bottomOfBoundedRows = CGRectGetMaxY(rectOfLastRow); // we only have to worry about the rows below the last... if (bottom <= bottomOfBoundedRows) @@ -1821,8 +1898,8 @@ NOT YET IMPLEMENTED */ - (CPIndexSet)columnIndexesInRect:(CGRect)aRect { - var column = MAX(0, [self columnAtPoint:_CGPointMake(aRect.origin.x, 0.0)]), - lastColumn = [self columnAtPoint:_CGPointMake(_CGRectGetMaxX(aRect), 0.0)]; + var column = MAX(0, [self columnAtPoint:CGPointMake(aRect.origin.x, 0.0)]), + lastColumn = [self columnAtPoint:CGPointMake(CGRectGetMaxX(aRect), 0.0)]; if (lastColumn === CPNotFound) lastColumn = NUMBER_OF_COLUMNS() - 1; @@ -1857,7 +1934,7 @@ NOT YET IMPLEMENTED { var bounds = [self bounds]; - if (!_CGRectContainsPoint(bounds, aPoint)) + if (!CGRectContainsPoint(bounds, aPoint)) return CPNotFound; UPDATE_COLUMN_RANGES_IF_NECESSARY(); @@ -1967,11 +2044,12 @@ NOT YET IMPLEMENTED return -1; var cellView = aView, - contentView = [[self window] contentView]; + contentView = [[self window] contentView], + max_rec = 100; - while (1) + while (max_rec--) { - if (cellView == contentView) + if (!cellView || cellView === contentView) { return -1; } @@ -2028,14 +2106,14 @@ NOT YET IMPLEMENTED UPDATE_COLUMN_RANGES_IF_NECESSARY(); if (aColumn > [self numberOfColumns] || aRow > [self numberOfRows]) - return _CGRectMakeZero(); + return CGRectMakeZero(); var tableColumnRange = _tableColumnRanges[aColumn], rectOfRow = [self rectOfRow:aRow], leftInset = FLOOR(_intercellSpacing.width / 2.0), topInset = FLOOR(_intercellSpacing.height / 2.0); - return _CGRectMake(tableColumnRange.location + leftInset, _CGRectGetMinY(rectOfRow) + topInset, tableColumnRange.length - _intercellSpacing.width, _CGRectGetHeight(rectOfRow) - _intercellSpacing.height); + return CGRectMake(tableColumnRange.location + leftInset, CGRectGetMinY(rectOfRow) + topInset, tableColumnRange.length - _intercellSpacing.width, CGRectGetHeight(rectOfRow) - _intercellSpacing.height); } /*! @@ -2060,7 +2138,7 @@ NOT YET IMPLEMENTED return; var superviewWidth = [superview bounds].size.width, - lastColumnMaxX = _CGRectGetMaxX([self rectOfColumn:[self numberOfColumns] -1]); + lastColumnMaxX = CGRectGetMaxX([self rectOfColumn:[self numberOfColumns] -1]); // Fix me: this fires on the table setup at times if (lastColumnMaxX >= superviewWidth && lastColumnMaxX <= aSize.width || lastColumnMaxX <= superviewWidth && lastColumnMaxX >= aSize.width) @@ -2150,7 +2228,7 @@ NOT YET IMPLEMENTED [resizableColumns addIndex:i]; } - var maxXofColumns = _CGRectGetMaxX([self rectOfColumn:[resizableColumns lastIndex]]), + var maxXofColumns = CGRectGetMaxX([self rectOfColumn:[resizableColumns lastIndex]]), remainingSpace = superviewWidth - maxXofColumns, resizeableColumnsCount = [resizableColumns count], proportionate = 0; @@ -2187,7 +2265,7 @@ NOT YET IMPLEMENTED while (count-- && [_tableColumns[count] isHidden]); // find the max x, but subtract a single pixel since the spacing isn't applicable here. - var delta = superviewWidth - _CGRectGetMaxX([self rectOfColumn:count]) - ([self intercellSpacing].width || 1), + var delta = superviewWidth - CGRectGetMaxX([self rectOfColumn:count]) - ([self intercellSpacing].width || 1), newSize = [item width] + delta; [item _tryToResizeToWidth:newSize]; @@ -2337,10 +2415,8 @@ NOT YET IMPLEMENTED var heightObject = _cachedRowHeights[_cachedRowHeights.length - 1], height = heightObject.heightAboveRow + heightObject.height + _intercellSpacing.height; - } - if ([superview isKindOfClass:[CPClipView class]]) { var superviewSize = [superview bounds].size; @@ -2349,7 +2425,7 @@ NOT YET IMPLEMENTED height = MAX(superviewSize.height, height); } - [self setFrameSize:_CGSizeMake(width, height)]; + [self setFrameSize:CGSizeMake(width, height)]; [self setNeedsLayout]; [self setNeedsDisplay:YES]; @@ -2474,7 +2550,6 @@ NOT YET IMPLEMENTED @"width": [column width] }; - [columnsSetup addObject:metaData]; } @@ -2516,7 +2591,7 @@ NOT YET IMPLEMENTED Sets the delegate of the receiver. @param aDelegate the delegate object for the tableview. - The delegate can provide easy notification for user interaction, display behaviour, contextual menus, and more. + The delegate can provide notification for user interaction, display behaviour, contextual menus, and more. @section Providing Views for Rows and Columns: @@ -2538,7 +2613,7 @@ The view's properties should be properly set up before returning the result. The When using bindings, this method is optional if at least one identifier has been associated with the table view at design time. If this method is not implemented, the table will automatically call the CPTableView method makeViewWithIdentifier:owner: with the tableColumn parameter’s identifier and the table view’s delegate respectively as parameters, to attempt to reuse a previous view, or automatically unarchive a prototype associated with the table view. -The autoresizingMask of the returned view will automatically be set to CPViewNotSizable if the data view was created in Interface builder in a table column. Otherwise, for example if the view is created manually in code, this methods expects the data view to have a CPViewNotSizable mask. +The autoresizingMask of the returned view will automatically be set to CPViewNotSizable if the data view was created in Interface builder in a table column. Otherwise, for example if the view is created manually in code, this method expects the data view to have a CPViewNotSizable mask. @section displayingcells Displaying Cells: @@ -2554,8 +2629,6 @@ Group rows are a way to separate a groups of data in a tableview. Return YES if @endcode - - @section editingcells Editing Cells: Return YES if the dataview at a given index and column should be edited, otherwise NO. @@ -2564,9 +2637,6 @@ Return YES if the dataview at a given index and column should be edited, otherwi @endcode - - - @section sizes Setting Row and Column Size: Return the height of the row at a given index. Only implement this if you want variable row heights. Otherwise use setRowHeight: on the tableview. @@ -2575,8 +2645,6 @@ Return the height of the row at a given index. Only implement this if you want v @endcode - - @section selection Selecting in the TableView: @note These methods are only called when the user does something.@endnote @@ -2595,7 +2663,7 @@ Return YES if the table column given should be selected, otherwise NO to deny th - (BOOL)tableView:(CPTableView)aTableView shouldSelectTableColumn:(CPTableColumn)aTableColumn; @endcode -Inform the delegate that the tableview is in the process of chaining the selection. +Informs the delegate that the tableview is in the process of changing the selection. This usually happens when the user is dragging their mouse across rows. @code - (void)tableViewSelectionIsChanging:(CPNotification)aNotification @@ -2607,10 +2675,7 @@ Informs the delegate that the tableview selection has changed. @endcode - - - -@section movingandresizingcolumsn Moving and Resizing Columns: +@section movingandresizingcolumns Moving and Resizing Columns: Return YES if the column at a given index should move to a new column index, otherwise NO. When a column is initially dragged by the user, the delegate is first called with a newColumnIndex value of -1 @@ -2620,13 +2685,13 @@ When a column is initially dragged by the user, the delegate is first called wit @endcode -Notifies the delegate that the tableview drag occurred. This is send on mouse up. +Notifies the delegate that the tableview drag occurred. This is sent on mouse up. @code - (void)tableView:(CPTableView)tableView didDragTableColumn:(CPTableColumn)tableColumn; @endcode -Notifies the delegate that a tablecolumn was moved by the user. +Notifies the delegate that a table column was moved by the user. @code - (void)tableViewColumnDidMove:(CPNotification)aNotification; @endcode @@ -2637,8 +2702,6 @@ Notifies the delegate that the user resized the table column @endcode - - @section mousevents Responding to Mouse Events: Sent when the user clicks a table column but doesn't drag. @@ -2647,7 +2710,7 @@ Sent when the user clicks a table column but doesn't drag. @endcode -Notify the delegate that the user click the table header of a column. +Notify the delegate that the user has clicked the table header of a column. @code - (void)tableView:(CPTableView)tableView mouseDownInHeaderOfTableColumn:(CPTableColumn)tableColumn; @endcode @@ -2655,15 +2718,15 @@ Notify the delegate that the user click the table header of a column. @section contextualmenus Contextual Menus: -Called when the user right clicks on the tableview. -1 is passed for the row or column if the user doesn't right click on a real row or column -Return a CPMenu that should be displayed if the user right clicks. If you do not implement this the tableview will just call super on menuForEvent +Called when the user right-clicks on the tableview. -1 is passed for the row or column if the user doesn't right click on a real row or column +Return a CPMenu that should be displayed if the user right-clicks. If you do not implement this the tableview will call super on menuForEvent @code - (CPMenu)tableView:(CPTableView)aTableView menuForTableColumn:(CPTableColumn)aColumn row:(int)aRow; @endcode @section deletekey Delete Key -Called when the user presses the delete key. Many times you will want to delete data (or prompt for deletion) when the user hids the delete key. +Called when the user presses the delete key. Many times you will want to delete data (or prompt for deletion) when the user presses the delete key. Your delegate can implement this method to avoid subclassing the tableview to add this behaviour. @code @@ -2710,8 +2773,13 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if ([_delegate respondsToSelector:@selector(selectionShouldChangeInTableView:)]) _implementedDelegateMethods |= CPTableViewDelegate_selectionShouldChangeInTableView_; - if ([_delegate respondsToSelector:@selector(tableView:dataViewForTableColumn:row:)]) + if ([_delegate respondsToSelector:@selector(tableView:viewForTableColumn:row:)]) + _implementedDelegateMethods |= CPTableViewDelegate_tableView_viewForTableColumn_row_; + else if ([_delegate respondsToSelector:@selector(tableView:dataViewForTableColumn:row:)]) + { _implementedDelegateMethods |= CPTableViewDelegate_tableView_dataViewForTableColumn_row_; + CPLog.warn("tableView:dataViewForTableColumn: is deprecated. You should use -tableView:viewForTableColumn: where you can request the view with -makeViewWithIdentifier:owner:"); + } [self _updateIsViewBased]; @@ -2862,6 +2930,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad { [self _sendDelegateDidClickColumn:clickedColumn]; + [self _changeSortDescriptorsForClickOnColumn:clickedColumn]; + if (_allowsColumnSelection) { [self _noteSelectionIsChanging]; @@ -2888,8 +2958,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad else [self selectColumnIndexes:[CPIndexSet indexSetWithIndex:clickedColumn] byExtendingSelection:NO]; } - - [self _changeSortDescriptorsForClickOnColumn:clickedColumn]; } // From GNUSTEP @@ -3064,8 +3132,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad } var dragPoint = [self convertPoint:[theDragEvent locationInWindow] fromView:nil]; - dragViewOffset.x = _CGRectGetWidth(bounds) / 2 - dragPoint.x; - dragViewOffset.y = _CGRectGetHeight(bounds) / 2 - dragPoint.y; + dragViewOffset.x = CGRectGetWidth(bounds) / 2 - dragPoint.x; + dragViewOffset.y = CGRectGetHeight(bounds) / 2 - dragPoint.y; return view; } @@ -3081,7 +3149,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad var dragView = [[_CPColumnDragView alloc] initWithLineColor:[self gridColor]], tableColumn = [[self tableColumns] objectAtIndex:theColumnIndex], defaultRowHeight = [self valueForThemeAttribute:@"default-row-height"], - bounds = _CGRectMake(0.0, 0.0, [tableColumn width], _CGRectGetHeight([self exposedRect]) + defaultRowHeight), + bounds = CGRectMake(0.0, 0.0, [tableColumn width], CGRectGetHeight([self exposedRect]) + defaultRowHeight), columnRect = [self rectOfColumn:theColumnIndex], headerView = [tableColumn headerView], row = [_exposedRows firstIndex]; @@ -3097,7 +3165,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad dataViewFrame.origin.x = 0.0; // Offset by table header height - scroll position - dataViewFrame.origin.y = ( _CGRectGetMinY(dataViewFrame) - _CGRectGetMinY([self exposedRect]) ) + defaultRowHeight; + dataViewFrame.origin.y = ( CGRectGetMinY(dataViewFrame) - CGRectGetMinY([self exposedRect]) ) + defaultRowHeight; [dataView setFrame:dataViewFrame]; [self _setObjectValueForTableColumn:tableColumn row:row forView:dataView]; @@ -3143,7 +3211,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad [[CPException exceptionWithName:@"Error" reason:reason userInfo:nil] raise]; } - _retargetedDropRow = row; _retargetedDropOperation = operation; } @@ -3228,12 +3295,10 @@ Your delegate can implement this method to avoid subclassing the tableview to ad - (void)setSortDescriptors:(CPArray)sortDescriptors { var oldSortDescriptors = [[self sortDescriptors] copy], - newSortDescriptors = nil; - - if (sortDescriptors == nil) newSortDescriptors = [CPArray array]; - else - newSortDescriptors = [CPArray arrayWithArray:sortDescriptors]; + + if (sortDescriptors !== nil) + [newSortDescriptors addObjectsFromArray:sortDescriptors]; if ([newSortDescriptors isEqual:oldSortDescriptors]) return; @@ -3283,6 +3348,11 @@ Your delegate can implement this method to avoid subclassing the tableview to ad return _implementedDelegateMethods & CPTableViewDelegate_tableView_dataViewForTableColumn_row_; } +- (BOOL)_delegateRespondsToViewForTableColumn +{ + return _implementedDelegateMethods & CPTableViewDelegate_tableView_viewForTableColumn_row_; +} + /*! @ignore */ @@ -3307,7 +3377,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad objectValue = [_dataSource tableView:self objectValueForTableColumn:aTableColumn row:aRowIndex]; tableColumnObjectValues[aRowIndex] = objectValue; } - else if (![self _delegateRespondsToDataViewForTableColumn] && ![self infoForBinding:@"content"]) + else if (!_isViewBased && ![self infoForBinding:@"content"]) { CPLog.warn(@"no content binding established and data source " + [_dataSource description] + " does not implement tableView:objectValueForTableColumn:row:"); } @@ -3330,7 +3400,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad // there are multiple views in the clip view? if ([superview isKindOfClass:[CPClipView class]]) _exposedRect = [superview bounds]; - else _exposedRect = [self bounds]; } @@ -3450,12 +3519,14 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (!dataViews || row >= dataViews.length) continue; + if (row === _editingRow && column === _editingColumn) + [[self window] makeFirstResponder:self]; + var dataView = [dataViews objectAtIndex:row]; [dataViews replaceObjectAtIndex:row withObject:nil]; - if (row !== _editingRow || column !== _editingColumn) - [self _enqueueReusableDataView:dataView]; + [self _enqueueReusableDataView:dataView]; } } } @@ -3508,8 +3579,11 @@ Your delegate can implement this method to avoid subclassing the tableview to ad [self _setObjectValueForTableColumn:tableColumn row:row forView:dataView]; - if (isColumnSelected || [self isRowSelected:row]) + if ((_selectionHighlightStyle !== CPTableViewSelectionHighlightStyleNone) && + (isColumnSelected || [self isRowSelected:row])) + { [dataView setThemeState:CPThemeStateSelectedDataView]; + } else [dataView unsetThemeState:CPThemeStateSelectedDataView]; @@ -3578,7 +3652,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (_contentBindingExpicitelySet) [self _prepareContentBindedDataView:aDataView forRow:aRow]; else - // For both cell-based and view-based + // For both cell-based and view-based [aTableColumn _prepareDataView:aDataView forRow:aRow]; } @@ -3691,19 +3765,14 @@ Your delegate can implement this method to avoid subclassing the tableview to ad /*! @ignore */ +- (CPView)_viewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow +{ + return [_delegate tableView:self viewForTableColumn:aTableColumn row:aRow]; +} + - (CPView)_dataViewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow { - var view = nil; - - if ([self _delegateRespondsToDataViewForTableColumn]) - { - view = [_delegate tableView:self dataViewForTableColumn:aTableColumn row:aRow]; - - if (!view) - [CPException raise:CPInternalInconsistencyException reason:"The view returned by -tableView:dataViewForTableColumn:row: should not be nil"]; - } - - return view; + return [_delegate tableView:self dataViewForTableColumn:aTableColumn row:aRow]; } /*! @@ -3711,7 +3780,10 @@ Your delegate can implement this method to avoid subclassing the tableview to ad */ - (CPView)_newDataViewForRow:(CPInteger)aRow tableColumn:(CPTableColumn)aTableColumn { - var view = [self _dataViewForTableColumn:aTableColumn row:aRow]; + var view = nil; + + if (_viewForTableColumnRowSelector) + view = objj_msgSend(self, _viewForTableColumnRowSelector, aTableColumn, aRow); if (!view) { @@ -3742,7 +3814,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad @discussion Typically identifier is associated with an external CIB and the table view will automatically instantiate the CIB with the provided owner. The owner of the CIB that may be loaded and instantiated to create a new view with the particular identifier is typically the table view’s delegate. The owner is useful in setting up outlets and target and actions from the view. - This method will typically be called by the delegate in tableView:dataViewForTableColumn:row:, but it can also be overridden to provide custom views for the identifier. This method may also return a reused view with the same identifier that was no longer available on screen. + This method will typically be called by the delegate in tableView:viewForTableColumn:row:, but it can also be overridden to provide custom views for the identifier. This method may also return a reused view with the same identifier that was no longer available on screen. */ - (id)makeViewWithIdentifier:(CPString)anIdentifier owner:(id)anOwner { @@ -3807,8 +3879,14 @@ Your delegate can implement this method to avoid subclassing the tableview to ad - (void)_updateIsViewBased { - _isViewBased = (_implementedDelegateMethods & CPTableViewDelegate_tableView_dataViewForTableColumn_row_ || _archivedDataViews != nil); + if ([self _delegateRespondsToViewForTableColumn]) + _viewForTableColumnRowSelector = @selector(_viewForTableColumn:row:); + else if ([self _delegateRespondsToDataViewForTableColumn]) + _viewForTableColumnRowSelector = @selector(_dataViewForTableColumn:row:); + + _isViewBased = (_viewForTableColumnRowSelector !== nil || _archivedDataViews !== nil); } + /*! @ignore */ @@ -3835,7 +3913,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad [super setFrameSize:aSize]; if (_headerView) - [_headerView setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), _CGRectGetHeight([_headerView frame]))]; + [_headerView setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), CGRectGetHeight([_headerView frame]))]; _exposedRect = nil; } @@ -3890,6 +3968,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad [[self headerView] setNeedsLayout]; } +/*! + @ignore +*/ +- (BOOL)_isFocused +{ + var isEditing = _editingRow !== CPNotFound || _editingCellIndex; + + return [[self window] isKeyWindow] && ([[self window] firstResponder] === self || isEditing); +} /*! @ignore @@ -3986,14 +4073,14 @@ Your delegate can implement this method to avoid subclassing the tableview to ad row = exposedRows.location, lastRow = CPMaxRange(exposedRows) - 1, rowY = -0.5, - minX = _CGRectGetMinX(aRect), - maxX = _CGRectGetMaxX(aRect); + minX = CGRectGetMinX(aRect), + maxX = CGRectGetMaxX(aRect); for (; row <= lastRow; ++row) { // grab each row rect and add the top and bottom lines var rowRect = [self _rectOfRow:row checkRange:NO], - rowY = _CGRectGetMaxY(rowRect) - 0.5; + rowY = CGRectGetMaxY(rowRect) - 0.5; CGContextMoveToPoint(context, minX, rowY); CGContextAddLineToPoint(context, maxX, rowY); @@ -4002,7 +4089,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (_rowHeight > 0.0) { var rowHeight = _rowHeight + _intercellSpacing.height, - totalHeight = _CGRectGetMaxY(aRect); + totalHeight = CGRectGetMaxY(aRect); while (rowY < totalHeight) { @@ -4023,13 +4110,13 @@ Your delegate can implement this method to avoid subclassing the tableview to ad var columnArrayIndex = 0, columnArrayCount = columnsArray.length, - minY = _CGRectGetMinY(aRect), - maxY = _CGRectGetMaxY(aRect); + minY = CGRectGetMinY(aRect), + maxY = CGRectGetMaxY(aRect); for (; columnArrayIndex < columnArrayCount; ++columnArrayIndex) { var columnRect = [self rectOfColumn:columnsArray[columnArrayIndex]], - columnX = _CGRectGetMaxX(columnRect) - 0.5; + columnX = CGRectGetMaxX(columnRect) - 0.5; CGContextMoveToPoint(context, columnX, minY); CGContextAddLineToPoint(context, columnX, maxY); @@ -4081,19 +4168,20 @@ Your delegate can implement this method to avoid subclassing the tableview to ad return; var drawGradient = (CPFeatureIsCompatible(CPHTMLCanvasFeature) && _selectionHighlightStyle === CPTableViewSelectionHighlightStyleSourceList && [_selectedRowIndexes count] >= 1), - deltaHeight = 0.5 * (_gridStyleMask & CPTableViewSolidHorizontalGridLineMask); + deltaHeight = 0.5 * (_gridStyleMask & CPTableViewSolidHorizontalGridLineMask), + focused = [self _isFocused]; CGContextBeginPath(context); if (drawGradient) { - var gradientCache = [self selectionGradientColors], + var gradientCache = focused ? [self selectionGradientColors] : [self unfocusedSelectionGradientColors], topLineColor = [gradientCache objectForKey:CPSourceListTopLineColor], bottomLineColor = [gradientCache objectForKey:CPSourceListBottomLineColor], gradientColor = [gradientCache objectForKey:CPSourceListGradient]; } - var normalSelectionHighlightColor = [self selectionHighlightColor]; + var normalSelectionHighlightColor = focused ? [self selectionHighlightColor] : [self unfocusedSelectionHighlightColor]; // don't do these lookups if there are no group rows if ([_groupRows count]) @@ -4114,10 +4202,10 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (drawGradient || shouldUseGroupGradient) { - var minX = _CGRectGetMinX(rowRect), - minY = _CGRectGetMinY(rowRect), - maxX = _CGRectGetMaxX(rowRect), - maxY = _CGRectGetMaxY(rowRect) - deltaHeight; + var minX = CGRectGetMinX(rowRect), + minY = CGRectGetMinY(rowRect), + maxX = CGRectGetMaxX(rowRect), + maxY = CGRectGetMaxY(rowRect) - deltaHeight; if (!drawGradient) { @@ -4130,7 +4218,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad CGContextAddRect(context, rowRect); - CGContextDrawLinearGradient(context, (shouldUseGroupGradient) ? gradientGroupColor : gradientColor, rowRect.origin, _CGPointMake(minX, maxY), 0); + CGContextDrawLinearGradient(context, (shouldUseGroupGradient) ? gradientGroupColor : gradientColor, rowRect.origin, CGPointMake(minX, maxY), 0); CGContextBeginPath(context); CGContextMoveToPoint(context, minX, minY + .5); @@ -4181,10 +4269,10 @@ Your delegate can implement this method to avoid subclassing the tableview to ad for (var i = 0; i < count2; i++) { var rect = objj_msgSend(self, rectSelector, indexes[i]), - minX = _CGRectGetMinX(rect) - 0.5, - maxX = _CGRectGetMaxX(rect) - 0.5, - minY = _CGRectGetMinY(rect) - 0.5, - maxY = _CGRectGetMaxY(rect) - 0.5; + minX = CGRectGetMinX(rect) - 0.5, + maxX = CGRectGetMaxX(rect) - 0.5, + minY = CGRectGetMinY(rect) - 0.5, + maxY = CGRectGetMaxY(rect) - 0.5; if ([_selectedRowIndexes count] >= 1 && gridStyleMask & CPTableViewSolidVerticalGridLineMask) { @@ -4200,7 +4288,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad for (var c = firstExposedColumn; c < exposedColumnCount; c++) { var colRect = [self rectOfColumn:exposedColumnIndexes[c]], - colX = _CGRectGetMaxX(colRect) + 0.5; + colX = CGRectGetMaxX(colRect) + 0.5; CGContextMoveToPoint(context, colX, minY); CGContextAddLineToPoint(context, colX, maxY); @@ -4397,7 +4485,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad else _selectionAnchorRow = row; - //set ivars for startTrackingPoint and time... _startTrackingPoint = aPoint; _startTrackingTimestamp = new Date(); @@ -4463,7 +4550,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad else _draggedRowIndexes = [CPIndexSet indexSetWithIndex:row]; - //ask the datasource for the data var pboard = [CPPasteboard pasteboardWithName:CPDragPboard]; @@ -4670,7 +4756,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad var row = [self _proposedRowAtPoint:theDragPoint], rowRect = [self rectOfRow:row]; - // If there is no (the default) or to little inter cell spacing we create some room for the CPTableViewDropAbove indicator + // If there is no (the default) or too little inter-cell spacing we create some room for the CPTableViewDropAbove indicator // This probably doesn't work if the row height is smaller than or around 5.0 if ([self intercellSpacing].height < 5.0) rowRect = CGRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); @@ -4690,15 +4776,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad - (CPInteger)_proposedRowAtPoint:(CGPoint)dragPoint { var row = [self rowAtPoint:dragPoint], - // Determine if the mouse is currently closer to this row or the row below it + // Determine if the mouse is currently closer to this row or the row below it lowerRow = row + 1, rect = [self rectOfRow:row], - bottomPoint = _CGRectGetMaxY(rect), - bottomThirty = bottomPoint - ((bottomPoint - _CGRectGetMinY(rect)) * 0.3), + bottomPoint = CGRectGetMaxY(rect), + bottomThirty = bottomPoint - ((bottomPoint - CGRectGetMinY(rect)) * 0.3), numberOfRows = [self numberOfRows]; if (row < 0) - row = (_CGRectGetMaxY(rect) < dragPoint.y) ? numberOfRows : row; + row = (CGRectGetMaxY(rect) < dragPoint.y) ? numberOfRows : row; else if (dragPoint.y > MAX(bottomThirty, bottomPoint - 6)) row = lowerRow; @@ -4763,7 +4849,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (dropOperation === CPTableViewDropOn && row >= numberOfRows) row = numberOfRows - 1; - var rect = _CGRectMakeZero(); + var rect = CGRectMakeZero(); if (row === -1) rect = [self exposedRect]; @@ -4789,7 +4875,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad - (BOOL)prepareForDragOperation:(id)sender { // FIX ME: is there anything else that needs to happen here? - // actual validation is called in dragginUpdated: + // actual validation is called in draggingUpdated: [_dropOperationFeedbackView removeFromSuperview]; return (_implementedDataSourceMethods & CPTableViewDataSource_tableView_validateDrop_proposedRow_proposedDropOperation_); @@ -4954,11 +5040,37 @@ Your delegate can implement this method to avoid subclassing the tableview to ad userInfo:nil]; } +/*! + @ignore +*/ +- (void)becomeKeyWindow +{ + [self setNeedsDisplay:YES]; +} + +/*! + @ignore +*/ +- (void)resignKeyWindow +{ + [self setNeedsDisplay:YES]; +} + /*! @ignore */ - (BOOL)becomeFirstResponder { + [self setNeedsDisplay:YES]; + return YES; +} + +/*! + @ignore +*/ +- (BOOL)resignFirstResponder +{ + [self setNeedsDisplay:YES]; return YES; } @@ -4969,6 +5081,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad { return YES; } + /*! @ignore */ @@ -5004,6 +5117,13 @@ Your delegate can implement this method to avoid subclassing the tableview to ad { var responder = [[self window] firstResponder]; + if (![responder isKindOfClass:[CPView class]] || ![responder isDescendantOf:self]) + { + _editingRow = CPNotFound; + _editingColumn = CPNotFound; + return; + } + _editingRow = [self rowForView:responder]; _editingColumn = [self columnForView:responder]; @@ -5026,7 +5146,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad - (void)_textFieldEditingDidEnd:(CPNotification)aNote { -// FIXME: When you edit a text field and hit enter without any text mofification, the CPControlTextDidEndEditingNotification is NOT sent. This is a bug in CPTextField or CPControl according to cocoa. + // FIXME: When you edit a text field and hit enter without any text modification, the CPControlTextDidEndEditingNotification + // is NOT sent. This is a bug in CPTextField or CPControl according to cocoa. var textField = [aNote object]; [self _unregisterForEndEditingNote:textField]; @@ -5039,7 +5160,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad - (SEL)_disableActionIfExists:(CPView)aView { -// TODO: We disable action to prevent it from beeing sent twice when we resign the FR inside a textEndEditing notification. Check if this is due to a bug in CPTextField. + // TODO: We disable action to prevent it from beeing sent twice when we resign the FR inside a textEndEditing notification. + // Check if this is due to a bug in CPTextField. var action = nil; if ([aView respondsToSelector:@selector(action)] && (action = [aView action])) [aView setAction:nil]; @@ -5134,7 +5256,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad if (i >= [self numberOfRows] || i < 0) return; - if (_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_) { @@ -5188,6 +5309,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad @end + @implementation CPTableView (Bindings) + (id)_binderClassForBinding:(CPString)aBinding @@ -5241,6 +5363,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad @end + @implementation CPTableContentBinder : CPBinder { id _content @accessors(property=content); @@ -5258,6 +5381,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad @end + var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", CPTableViewDelegateKey = @"CPTableViewDelegateKey", CPTableViewHeaderViewKey = @"CPTableViewHeaderViewKey", @@ -5305,8 +5429,8 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", _rowHeight = [aCoder decodeFloatForKey:CPTableViewRowHeightKey] || [self valueForThemeAttribute:@"default-row-height"]; _intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey]; - if (_CGSizeEqualToSize(_intercellSpacing, _CGSizeMakeZero())) - _intercellSpacing = _CGSizeMake(3.0, 2.0); + if (CGSizeEqualToSize(_intercellSpacing, CGSizeMakeZero())) + _intercellSpacing = CGSizeMake(3.0, 2.0); [self setGridColor:[aCoder decodeObjectForKey:CPTableViewGridColorKey]]; _gridStyleMask = [aCoder decodeIntForKey:CPTableViewGridStyleMaskKey]; @@ -5374,6 +5498,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", @end + @implementation CPIndexSet (tableview) - (void)removeMatches:(CPIndexSet)otherSet @@ -5427,7 +5552,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", { //if row is selected don't fill and stroke white var selectedRows = [tableView selectedRowIndexes], - newRect = _CGRectMake(aRect.origin.x + 2, aRect.origin.y + 2, aRect.size.width - 4, aRect.size.height - 5); + newRect = CGRectMake(aRect.origin.x + 2, aRect.origin.y + 2, aRect.size.width - 4, aRect.size.height - 5); if ([selectedRows containsIndex:currentRow]) { @@ -5446,7 +5571,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", else if (dropOperation === CPTableViewDropAbove) { //reposition the view up a tad - [self setFrameOrigin:_CGPointMake(_frame.origin.x, _frame.origin.y - 8)]; + [self setFrameOrigin:CGPointMake(_frame.origin.x, _frame.origin.y - 8)]; var selectedRows = [tableView selectedRowIndexes]; @@ -5455,7 +5580,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", CGContextSetStrokeColor(context, [CPColor whiteColor]); CGContextSetLineWidth(context, 4); //draw the circle thing - CGContextStrokeEllipseInRect(context, _CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); + CGContextStrokeEllipseInRect(context, CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); //then draw the line CGContextBeginPath(context); CGContextMoveToPoint(context, 10, aRect.origin.y + 8); @@ -5467,7 +5592,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", } //draw the circle thing - CGContextStrokeEllipseInRect(context, _CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); + CGContextStrokeEllipseInRect(context, CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); //then draw the line CGContextBeginPath(context); CGContextMoveToPoint(context, 10, aRect.origin.y + 8); @@ -5504,6 +5629,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", @end + @implementation _CPColumnDragView : CPView { CPColor _lineColor; @@ -5511,7 +5637,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", - (id)initWithLineColor:(CPColor)aColor { - self = [super initWithFrame:_CGRectMakeZero()]; + self = [super initWithFrame:CGRectMakeZero()]; if (self) _lineColor = aColor; @@ -5526,15 +5652,15 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", CGContextSetStrokeColor(context, _lineColor); var points = [ - _CGPointMake(0.5, 0), - _CGPointMake(0.5, aRect.size.height) + CGPointMake(0.5, 0), + CGPointMake(0.5, aRect.size.height) ]; CGContextStrokeLineSegments(context, points, 2); points = [ - _CGPointMake(aRect.size.width - 0.5, 0), - _CGPointMake(aRect.size.width - 0.5, aRect.size.height) + CGPointMake(aRect.size.width - 0.5, 0), + CGPointMake(aRect.size.width - 0.5, aRect.size.height) ]; CGContextStrokeLineSegments(context, points, 2); @@ -5542,6 +5668,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", @end + @implementation CPTableCellView : CPView { id _objectValue @accessors(property=objectValue); diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 5cdbeeb18..6acd12975 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -20,8 +20,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#import "../Foundation/Ref.h" - @import "CPControl.j" @import "CPStringDrawing.j" @import "CPCompatibility.j" @@ -61,26 +59,33 @@ function CPTextFieldBlurFunction(anEvent, owner, domElement, inputElement, resig if (owner && domElement != inputElement.parentNode) return; - if (!resigning && [[owner window] isKeyWindow]) + var ownerWindow = [owner window]; + + if (!resigning && [ownerWindow isKeyWindow]) { /* - Browsers blur text fields when a click occurs anywhere outside the text field. That is normal for browsers, but in Cocoa the key view retains focus unless the click target accepts first responder. So if we lost focus but were not told to resign and our window is still key, restore focus. + Browsers blur text fields when a click occurs anywhere outside the text field. That is normal for browsers, but in Cocoa the key view retains focus unless the click target accepts first responder. So if we lost focus but were not told to resign and our window is still key, restore focus, + but only if the text field is completely within the browser window. If we restore focus when it + is off screen, the entire body scrolls out of our control. */ - window.setTimeout(function() + if ([owner _isWithinUsablePlatformRect]) { - inputElement.focus(); - }, 0.0); + window.setTimeout(function() + { + inputElement.focus(); + }, 0.0); + } } - CPTextFieldHandleBlur(anEvent, AT_REF(owner)); - AT_DEREF(didBlurRef, YES); + CPTextFieldHandleBlur(anEvent, @ref(owner)); + @deref(didBlurRef) = YES; return true; } function CPTextFieldHandleBlur(anEvent, ownerRef) { - AT_DEREF(ownerRef, nil); + @deref(ownerRef) = nil; [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; } @@ -207,8 +212,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); + (id)themeAttributes { return @{ - @"bezel-inset": _CGInsetMakeZero(), - @"content-inset": _CGInsetMake(1.0, 0.0, 0.0, 0.0), + @"bezel-inset": CGInsetMakeZero(), + @"content-inset": CGInsetMake(1.0, 0.0, 0.0, 0.0), @"bezel-color": [CPNull null], }; } @@ -233,10 +238,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); return CPTextFieldBlurFunction( anEvent, CPTextFieldInputOwner, - CPTextFieldInputOwner._DOMElement, + CPTextFieldInputOwner ? CPTextFieldInputOwner._DOMElement : nil, CPTextFieldDOMInputElement, CPTextFieldInputResigning, - AT_REF(CPTextFieldInputDidBlur)); + @ref(CPTextFieldInputDidBlur)); }; if (CPFeatureIsCompatible(CPInputOnInputEventFeature)) @@ -247,7 +252,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); return; var cappEvent = [CPEvent keyEventWithType:CPKeyUp - location:_CGPointMakeZero() + location:CGPointMakeZero() modifierFlags:0 timestamp:[CPEvent currentTimestamp] windowNumber:[[CPApp keyWindow] windowNumber] @@ -527,7 +532,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); /* @ignore */ - (BOOL)acceptsFirstResponder { - return [self isEditable] && [self isEnabled]; + return [self isEditable] && [self isEnabled] && [self _isWithinUsablePlatformRect]; } /* @ignore */ @@ -539,7 +544,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); _isEditing = NO; if ([[self window] isKeyWindow]) - [self _becomeFirstKeyResponder]; + return [self _becomeFirstKeyResponder]; return YES; } @@ -549,10 +554,12 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); Since a first responder but non-key window text field can't receive input it should not even look like an active text field (Cocoa has a "slightly active" text field look it uses when another window is the key window, but Cappuccino doesn't today.) */ -- (void)_becomeFirstKeyResponder +- (BOOL)_becomeFirstKeyResponder { - // Make sure the text field is visible so the browser will not scroll without the NSScrollView knowing about it. - [self scrollRectToVisible:[self bounds]]; + // If the text field is still not completely on screen, refuse to become + // first responder, because the browser will scroll it into view out of our control. + if (![self _isWithinUsablePlatformRect]) + return NO; [self setThemeState:CPThemeStateEditing]; @@ -578,11 +585,16 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); switch ([self alignment]) { - case CPCenterTextAlignment: element.style.textAlign = "center"; - break; - case CPRightTextAlignment: element.style.textAlign = "right"; - break; - default: element.style.textAlign = "left"; + case CPCenterTextAlignment: + element.style.textAlign = "center"; + break; + + case CPRightTextAlignment: + element.style.textAlign = "right"; + break; + + default: + element.style.textAlign = "left"; } var contentRect = [self contentRectForBounds:[self bounds]], @@ -591,31 +603,32 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); switch (verticalAlign) { case CPTopVerticalTextAlignment: - var topPoint = _CGRectGetMinY(contentRect) + "px"; + var topPoint = CGRectGetMinY(contentRect) + "px"; break; case CPCenterVerticalTextAlignment: - var topPoint = (_CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px"; + var topPoint = (CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px"; break; case CPBottomVerticalTextAlignment: - var topPoint = (_CGRectGetMaxY(contentRect) - lineHeight) + "px"; + var topPoint = (CGRectGetMaxY(contentRect) - lineHeight) + "px"; break; default: - var topPoint = _CGRectGetMinY(contentRect) + "px"; + var topPoint = CGRectGetMinY(contentRect) + "px"; break; } element.style.top = topPoint; - var left = _CGRectGetMinX(contentRect); + + var left = CGRectGetMinX(contentRect); // If the browser has a built in left padding, compensate for it. We need the input text to be exactly on top of the original text. if (CPFeatureIsCompatible(CPInput1PxLeftPadding)) left -= 1; element.style.left = left + "px"; - element.style.width = _CGRectGetWidth(contentRect) + "px"; + element.style.width = CGRectGetWidth(contentRect) + "px"; element.style.height = ROUND(lineHeight) + "px"; element.style.lineHeight = ROUND(lineHeight) + "px"; element.style.verticalAlign = "top"; @@ -660,6 +673,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); }, 0.0); #endif + + return YES; } /* @ignore */ @@ -769,7 +784,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); - (void)_windowDidBecomeKey:(CPNotification)aNotification { if ([[self window] isKeyWindow] && [[self window] firstResponder] === self) - [self _becomeFirstKeyResponder]; + if (![self _becomeFirstKeyResponder]) + [[self window] makeFirstResponder:nil]; } - (BOOL)_valueIsValid:(CPString)aValue @@ -778,7 +794,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); var error = @""; - if ([self _setStringValue:aValue isNewValue:NO errorDescription:AT_REF(error)] === NO) + if ([self _setStringValue:aValue isNewValue:NO errorDescription:@ref(error)] === NO) { var acceptInvalidValue = NO; @@ -1045,7 +1061,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); { var object = nil; - if ([formatter getObjectValue:AT_REF(object) forString:aValue errorDescription:anError]) + if ([formatter getObjectValue:@ref(object) forString:aValue errorDescription:anError]) objectValue = object; else { @@ -1084,7 +1100,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); // Formatting failed, get an "empty" object by formatting an empty string. // If that fails, the value is undefined. - if ([formatter getObjectValue:AT_REF(value) forString:@"" errorDescription:nil] === NO) + if ([formatter getObjectValue:@ref(value) forString:@"" errorDescription:nil] === NO) value = undefined; [super setObjectValue:value]; @@ -1171,7 +1187,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); maxSize = [self currentValueForThemeAttribute:@"max-size"], lineBreakMode = [self lineBreakMode], text = (_stringValue || @" "), - textSize = _CGSizeMakeCopy(frameSize), + textSize = CGSizeMakeCopy(frameSize), font = [self currentValueForThemeAttribute:@"font"]; textSize.width -= contentInset.left + contentInset.right; @@ -1465,14 +1481,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); { var contentInset = [self currentValueForThemeAttribute:@"content-inset"]; - return _CGRectInsetByInset(bounds, contentInset); + return CGRectInsetByInset(bounds, contentInset); } - (CGRect)bezelRectForBounds:(CGRect)bounds { var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"]; - return _CGRectInsetByInset(bounds, bezelInset); + return CGRectInsetByInset(bounds, bezelInset); } - (CGRect)rectForEphemeralSubviewNamed:(CPString)aName @@ -1490,7 +1506,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); { if (aName === "bezel-view") { - var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + var view = [[CPView alloc] initWithFrame:CGRectMakeZero()]; [view setHitTests:NO]; @@ -1498,7 +1514,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); } else { - var view = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()]; + var view = [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()]; [view setHitTests:NO]; @@ -1565,6 +1581,25 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); } } +#pragma mark Private + +- (BOOL)_isWithinUsablePlatformRect +{ + // Make sure the text field is completely within the platform window + // so the browser will not scroll it into view. + + var wind = [self window], + frame = [self convertRectToBase:[self bounds]], + usableRect = [[wind platformWindow] usableContentFrame]; + + frame.origin = [wind convertBaseToGlobal:frame.origin]; + + return (CGRectGetMinX(frame) >= CGRectGetMinX(usableRect) && + CGRectGetMaxX(frame) <= CGRectGetMaxX(usableRect) && + CGRectGetMinY(frame) >= CGRectGetMinY(usableRect) && + CGRectGetMaxY(frame) <= CGRectGetMaxY(usableRect)); +} + @end var secureStringForString = function(aString) diff --git a/AppKit/CPTheme.j b/AppKit/CPTheme.j index 9d6854206..dac337fd3 100644 --- a/AppKit/CPTheme.j +++ b/AppKit/CPTheme.j @@ -404,25 +404,25 @@ function CPThemeStateName(aState) return name; } -CPThemeStateNames[0] = "normal"; -CPThemeStateNormal = CPThemeStates["normal"] = 0; -CPThemeStateDisabled = CPThemeState("disabled"); -CPThemeStateHovered = CPThemeState("hovered"); -CPThemeStateHighlighted = CPThemeState("highlighted"); -CPThemeStateSelected = CPThemeState("selected"); -CPThemeStateTableDataView = CPThemeState("tableDataView"); -CPThemeStateSelectedDataView = CPThemeStateSelectedTableDataView = CPThemeState("selectedTableDataView"); -CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow"); -CPThemeStateBezeled = CPThemeState("bezeled"); -CPThemeStateBordered = CPThemeState("bordered"); -CPThemeStateEditable = CPThemeState("editable"); -CPThemeStateEditing = CPThemeState("editing"); -CPThemeStateVertical = CPThemeState("vertical"); -CPThemeStateDefault = CPThemeState("default"); -CPThemeStateCircular = CPThemeState("circular"); -CPThemeStateAutocompleting = CPThemeState("autocompleting"); -CPThemeStateMainWindow = CPThemeState("mainWindow"); -CPThemeStateKeyWindow = CPThemeState("keyWindow"); +CPThemeStateNames[0] = "normal"; +CPThemeStateNormal = CPThemeStates["normal"] = 0; +CPThemeStateDisabled = CPThemeState("disabled"); +CPThemeStateHovered = CPThemeState("hovered"); +CPThemeStateHighlighted = CPThemeState("highlighted"); +CPThemeStateSelected = CPThemeState("selected"); +CPThemeStateTableDataView = CPThemeState("tableDataView"); +CPThemeStateSelectedDataView = CPThemeState("selectedTableDataView"); +CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow"); +CPThemeStateBezeled = CPThemeState("bezeled"); +CPThemeStateBordered = CPThemeState("bordered"); +CPThemeStateEditable = CPThemeState("editable"); +CPThemeStateEditing = CPThemeState("editing"); +CPThemeStateVertical = CPThemeState("vertical"); +CPThemeStateDefault = CPThemeState("default"); +CPThemeStateCircular = CPThemeState("circular"); +CPThemeStateAutocompleting = CPThemeState("autocompleting"); +CPThemeStateMainWindow = CPThemeState("mainWindow"); +CPThemeStateKeyWindow = CPThemeState("keyWindow"); @implementation _CPThemeAttribute : CPObject { @@ -431,7 +431,7 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow"); CPDictionary _values @accessors(readonly, getter=values); JSObject _cache; - _CPThemeAttribute _parentAttribute; + _CPThemeAttribute _themeDefaultAttribute; } - (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue @@ -542,11 +542,18 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow"); } if (value === undefined || value === nil) - value = [_parentAttribute valueForState:aState]; + value = [_themeDefaultAttribute valueForState:aState]; if (value === undefined || value === nil) + { value = _defaultValue; + // Class theme attributes cannot use nil because it's a dictionary. + // So transform CPNull into nil. + if (value === [CPNull null]) + value = nil; + } + _cache[aState] = value; return value; @@ -554,11 +561,11 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow"); - (void)setParentAttribute:(_CPThemeAttribute)anAttribute { - if (_parentAttribute === anAttribute) + if (_themeDefaultAttribute === anAttribute) return; _cache = { }; - _parentAttribute = anAttribute; + _themeDefaultAttribute = anAttribute; } - (_CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute diff --git a/AppKit/CPTokenField.j b/AppKit/CPTokenField.j index 3521610b1..1498d2033 100755 --- a/AppKit/CPTokenField.j +++ b/AppKit/CPTokenField.j @@ -20,9 +20,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#import "../Foundation/CPRange.h" -#import "../Foundation/Ref.h" - @import @import @import @@ -101,7 +98,7 @@ CPTokenFieldDeleteButtonType = 1; + (id)themeAttributes { - return @{ @"editor-inset": _CGInsetMakeZero() }; + return @{ @"editor-inset": CGInsetMakeZero() }; } - (id)initWithFrame:(CGRect)frame @@ -125,7 +122,7 @@ CPTokenFieldDeleteButtonType = 1; - (void)_init { - _selectedRange = _CPMakeRange(0, 0); + _selectedRange = CPMakeRange(0, 0); var frame = [self frame]; @@ -215,7 +212,7 @@ CPTokenFieldDeleteButtonType = 1; if (delegateApprovedObjectsCount) location += delegateApprovedObjectsCount; - _selectedRange = _CPMakeRange(location, 0); + _selectedRange = CPMakeRange(location, 0); [self _inputElement].value = @""; [self setNeedsLayout]; @@ -235,12 +232,12 @@ CPTokenFieldDeleteButtonType = 1; if (indexOfToken == CPNotFound) { if (!extend) - _selectedRange = _CPMakeRange([[self _tokens] count], 0); + _selectedRange = CPMakeRange([[self _tokens] count], 0); } else if (extend) - _selectedRange = CPUnionRange(_selectedRange, _CPMakeRange(indexOfToken, 1)); + _selectedRange = CPUnionRange(_selectedRange, CPMakeRange(indexOfToken, 1)); else - _selectedRange = _CPMakeRange(indexOfToken, 1); + _selectedRange = CPMakeRange(indexOfToken, 1); [self setNeedsLayout]; } @@ -250,7 +247,7 @@ CPTokenFieldDeleteButtonType = 1; var indexOfToken = [[self _tokens] indexOfObject:token]; if (CPLocationInRange(indexOfToken, _selectedRange)) - _selectedRange = _CPMakeRange(MAX(indexOfToken, _selectedRange.location), MIN(_selectedRange.length, indexOfToken - _selectedRange.location)); + _selectedRange = CPMakeRange(MAX(indexOfToken, _selectedRange.location), MIN(_selectedRange.length, indexOfToken - _selectedRange.location)); [self setNeedsLayout]; } @@ -303,7 +300,7 @@ CPTokenFieldDeleteButtonType = 1; [self setObjectValue:tokens]; // setObjectValue moves the cursor to the end of the selection. We want it to stay // where the selected tokens were. - _selectedRange = _CPMakeRange(collapsedSelection, 0); + _selectedRange = CPMakeRange(collapsedSelection, 0); [self _controlTextDidChange]; } @@ -333,13 +330,18 @@ CPTokenFieldDeleteButtonType = 1; [self scrollRectToVisible:[self bounds]]; if ([[self window] isKeyWindow]) - [self _becomeFirstKeyResponder]; + return [self _becomeFirstKeyResponder]; return YES; } -- (void)_becomeFirstKeyResponder +- (BOOL)_becomeFirstKeyResponder { + // If the token field is still not completely on screen, refuse to become + // first responder, because the browser will scroll it into view out of our control. + if (![self _isWithinUsablePlatformRect]) + return NO; + [self setThemeState:CPThemeStateEditing]; [self _updatePlaceholderState]; @@ -359,11 +361,16 @@ CPTokenFieldDeleteButtonType = 1; switch ([self alignment]) { - case CPCenterTextAlignment: element.style.textAlign = "center"; - break; - case CPRightTextAlignment: element.style.textAlign = "right"; - break; - default: element.style.textAlign = "left"; + case CPCenterTextAlignment: + element.style.textAlign = "center"; + break; + + case CPRightTextAlignment: + element.style.textAlign = "right"; + break; + + default: + element.style.textAlign = "left"; } var contentRect = [self contentRectForBounds:[self bounds]]; @@ -401,6 +408,8 @@ CPTokenFieldDeleteButtonType = 1; } #endif + + return YES; } - (BOOL)resignFirstResponder @@ -482,7 +491,7 @@ CPTokenFieldDeleteButtonType = 1; - (void)_mouseUpOnToken:(_CPTokenFieldToken)aToken withEvent:(CPEvent)anEvent { - if (_mouseDownEvent && _CGPointEqualToPoint([_mouseDownEvent locationInWindow], [anEvent locationInWindow])) + if (_mouseDownEvent && CGPointEqualToPoint([_mouseDownEvent locationInWindow], [anEvent locationInWindow])) { [self _selectToken:aToken byExtendingSelection:[anEvent modifierFlags] & CPShiftKeyMask]; [[self window] makeFirstResponder:self]; @@ -667,7 +676,7 @@ CPTokenFieldDeleteButtonType = 1; CPTokenFieldInputOwner ? [CPTokenFieldInputOwner._tokenScrollView documentView]._DOMElement : nil, CPTokenFieldDOMInputElement, CPTokenFieldInputResigning, - AT_REF(CPTokenFieldInputDidBlur)); + @ref(CPTokenFieldInputDidBlur)); }; // FIXME make this not onblur @@ -818,7 +827,7 @@ CPTokenFieldDeleteButtonType = 1; if (_selectedRange.length) { // Place the cursor at the end of the selection and collapse. - _selectedRange.location = _CPMaxRange(_selectedRange); + _selectedRange.location = CPMaxRange(_selectedRange); _selectedRange.length = 0; } else @@ -839,7 +848,7 @@ CPTokenFieldDeleteButtonType = 1; - (void)moveRightAndModifySelection:(id)sender { - if (_CPMaxRange(_selectedRange) < [[self _tokens] count] && [self _editorValue] == "") + if (CPMaxRange(_selectedRange) < [[self _tokens] count] && [self _editorValue] == "") { // Leave the selection location in place but include the next token to the right. _selectedRange.length++; @@ -918,7 +927,7 @@ CPTokenFieldDeleteButtonType = 1; // Finish any editing. [self _autocomplete]; - _selectedRange = _CPMakeRange(0, [[self _tokens] count]); + _selectedRange = CPMakeRange(0, [[self _tokens] count]); [self setNeedsLayout]; } @@ -1010,7 +1019,7 @@ CPTokenFieldDeleteButtonType = 1; return; // Move each token into the right position. - var contentRect = _CGRectMakeCopy([contentView bounds]), + var contentRect = CGRectMakeCopy([contentView bounds]), contentOrigin = contentRect.origin, contentSize = contentRect.size, offset = CGPointMake(contentOrigin.x, contentOrigin.y), @@ -1027,11 +1036,11 @@ CPTokenFieldDeleteButtonType = 1; // Get the height of a typical token, or a token token if you will. [tokenToken sizeToFit]; - var tokenHeight = _CGRectGetHeight([tokenToken bounds]); + var tokenHeight = CGRectGetHeight([tokenToken bounds]); var fitAndFrame = function(width, height) { - var r = _CGRectMake(0, 0, width, height); + var r = CGRectMake(0, 0, width, height); if (offset.x + width >= contentSize.width && offset.x > contentOrigin.x) { @@ -1044,8 +1053,8 @@ CPTokenFieldDeleteButtonType = 1; // Make sure the frame fits. var scrollHeight = offset.y + tokenHeight + CEIL(spaceBetweenTokens.height / 2.0); - if (_CGRectGetHeight([contentView bounds]) < scrollHeight) - [contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)]; + if (CGRectGetHeight([contentView bounds]) < scrollHeight) + [contentView setFrameSize:CGSizeMake(CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)]; offset.x += width + spaceBetweenTokens.width; @@ -1079,12 +1088,12 @@ CPTokenFieldDeleteButtonType = 1; // When editing, always scroll to the cursor. if (_selectedRange.length == 0) - [[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, _inputFrame.origin.y)]; + [[_tokenScrollView documentView] scrollPoint:CGPointMake(0, _inputFrame.origin.y)]; }; for (var i = 0, count = [tokens count]; i < count; i++) { - if (isEditing && !_selectedRange.length && i == _CPMaxRange(_selectedRange)) + if (isEditing && !_selectedRange.length && i == CPMaxRange(_selectedRange)) placeEditor(false); var tokenView = [tokens objectAtIndex:i]; @@ -1105,7 +1114,7 @@ CPTokenFieldDeleteButtonType = 1; [tokenView setButtonType:_buttonType]; } - if (isEditing && !_selectedRange.length && _CPMaxRange(_selectedRange) >= [tokens count]) + if (isEditing && !_selectedRange.length && CPMaxRange(_selectedRange) >= [tokens count]) placeEditor(true); // Hide the editor if there are selected tokens, but still keep it active @@ -1126,8 +1135,8 @@ CPTokenFieldDeleteButtonType = 1; // Trim off any excess height downwards (in case we shrank). var scrollHeight = offset.y + tokenHeight; - if (_CGRectGetHeight([contentView bounds]) > scrollHeight) - [contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)]; + if (CGRectGetHeight([contentView bounds]) > scrollHeight) + [contentView setFrameSize:CGSizeMake(CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)]; if (_shouldScrollTo !== CPScrollDestinationNone) { @@ -1139,7 +1148,7 @@ CPTokenFieldDeleteButtonType = 1; if (scrollToToken === CPScrollDestinationLeft) scrollToToken = tokens[_selectedRange.location] else if (scrollToToken === CPScrollDestinationRight) - scrollToToken = tokens[MAX(0, _CPMaxRange(_selectedRange) - 1)]; + scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)]; [self _scrollTokenViewToVisible:scrollToToken]; } @@ -1152,7 +1161,7 @@ CPTokenFieldDeleteButtonType = 1; if (!aToken) return; - return [[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, [aToken frameOrigin].y)]; + return [[_tokenScrollView documentView] scrollPoint:CGPointMake(0, [aToken frameOrigin].y)]; } @end @@ -1184,7 +1193,7 @@ CPTokenFieldDeleteButtonType = 1; - (CGPoint)_completionOrigin:(_CPAutocompleteMenu)anAutocompleteMenu { var relativeFrame = _inputFrame ? [[_tokenScrollView documentView] convertRect:_inputFrame toView:self ] : [self bounds]; - return _CGPointMake(_CGRectGetMinX(relativeFrame), _CGRectGetMaxY(relativeFrame)); + return CGPointMake(CGRectGetMinX(relativeFrame), CGRectGetMaxY(relativeFrame)); } /*! @@ -1404,7 +1413,7 @@ CPTokenFieldDeleteButtonType = 1; - (CGSize)_minimumFrameSize { - var size = _CGSizeMakeZero(), + var size = CGSizeMakeZero(), minSize = [self currentValueForThemeAttribute:@"min-size"], contentInset = [self currentValueForThemeAttribute:@"content-inset"]; @@ -1479,7 +1488,7 @@ CPTokenFieldDeleteButtonType = 1; buttonOffset = [_disclosureButton currentValueForThemeAttribute:@"offset"], buttonSize = [_disclosureButton currentValueForThemeAttribute:@"min-size"]; - [_disclosureButton setFrame:_CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)]; + [_disclosureButton setFrame:CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)]; break; case CPTokenFieldDeleteButtonType: [_deleteButton setEnabled:[self isEditable] && [self isEnabled]]; @@ -1488,7 +1497,7 @@ CPTokenFieldDeleteButtonType = 1; buttonOffset = [_deleteButton currentValueForThemeAttribute:@"offset"], buttonSize = [_deleteButton currentValueForThemeAttribute:@"min-size"]; - [_deleteButton setFrame:_CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)]; + [_deleteButton setFrame:CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)]; break; } } @@ -1530,7 +1539,7 @@ CPTokenFieldDeleteButtonType = 1; { var attributes = [CPButton themeAttributes]; - [attributes setObject:_CGPointMake(15, 5) forKey:@"offset"]; + [attributes setObject:CGPointMake(15, 5) forKey:@"offset"]; return attributes; } @@ -1560,7 +1569,7 @@ CPTokenFieldDeleteButtonType = 1; { var attributes = [CPButton themeAttributes]; - [attributes setObject:_CGPointMake(15, 5) forKey:@"offset"]; + [attributes setObject:CGPointMake(15, 5) forKey:@"offset"]; return attributes; } diff --git a/AppKit/CPToolbar.j b/AppKit/CPToolbar.j index fd97bf531..8f1974f34 100644 --- a/AppKit/CPToolbar.j +++ b/AppKit/CPToolbar.j @@ -610,7 +610,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth) @"extra-item-width": 20.0, @"extra-item-extra-image": [CPNull null], @"extra-item-extra-alternate-image": [CPNull null], - @"content-inset": _CGInsetMake(4.0, 4.0, 4.0, 10), + @"content-inset": CGInsetMake(4.0, 4.0, 4.0, 10), @"regular-size-height": 59.0, @"small-size-height": 46.0, @"image-item-separator-color": [CPNull null], @@ -629,7 +629,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth) _labelColor = [CPColor blackColor]; _labelShadowColor = [CPColor colorWithWhite:1.0 alpha:0.75]; - _additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES]; + _additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES]; [_additionalItemsButton setBordered:NO]; [_additionalItemsButton setImagePosition:CPImageOnly]; @@ -679,7 +679,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth) { // We begin by recalculating the visible items. var items = [_toolbar items], - itemsWidth = _CGRectGetWidth([self bounds]), + itemsWidth = CGRectGetWidth([self bounds]), minWidth = _minWidth, // FIXME: This should be a CPSet. invisibleItemsSortedByPriority = []; @@ -766,7 +766,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth) // static width (min==max). This handles the case where the user did setView: // with a view of a different size than minSize/maxSize else - [view setFrameSize:_CGSizeMake(minSize.width, height)]; + [view setFrameSize:CGSizeMake(minSize.width, height)]; [view setHidden:NO]; } @@ -801,7 +801,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth) remainingSpace += proposedWidth - constrainedWidth; } - [view setFrameSize:_CGSizeMake(constrainedWidth, height)]; + [view setFrameSize:CGSizeMake(constrainedWidth, height)]; } } @@ -815,9 +815,9 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth) for (; index < count; ++index) { var view = [self viewForItem:_visibleItems[index]], - viewWidth = _CGRectGetWidth([view frame]); + viewWidth = CGRectGetWidth([view frame]); - [view setFrame:_CGRectMake(x, y, viewWidth, height)]; + [view setFrame:CGRectMake(x, y, viewWidth, height)]; x += viewWidth + [self valueForThemeAttribute:@"item-margin"]; } @@ -851,7 +851,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth) if (needsAdditionalItemsButton) { - [_additionalItemsButton setFrameOrigin:_CGPointMake(itemsWidth + 5.0, (_CGRectGetHeight([self bounds]) - _CGRectGetHeight([_additionalItemsButton frame])) / 2.0)]; + [_additionalItemsButton setFrameOrigin:CGPointMake(itemsWidth + 5.0, (CGRectGetHeight([self bounds]) - CGRectGetHeight([_additionalItemsButton frame])) / 2.0)]; [self addSubview:_additionalItemsButton]; @@ -994,12 +994,12 @@ var LABEL_MARGIN = 2.0; { _toolbarItem = aToolbarItem; - _labelField = [[CPTextField alloc] initWithFrame:_CGRectMakeZero()]; + _labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; [_labelField setFont:[CPFont systemFontOfSize:11.0]]; [_labelField setTextColor:[self FIXME_labelColor]]; [_labelField setTextShadowColor:[self FIXME_labelShadowColor]]; - [_labelField setTextShadowOffset:_CGSizeMake(0.0, 1.0)]; + [_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)]; [_labelField setAutoresizingMask:CPViewWidthSizable | CPViewMinXMargin]; [self addSubview:_labelField]; @@ -1101,8 +1101,8 @@ var LABEL_MARGIN = 2.0; [_labelField setHidden:iconOnly]; [_view setHidden:labelOnly]; - _minSize = _CGSizeMake(MAX(_labelSize.width, minSize.width), (labelOnly ? 0 : minSize.height) + (iconOnly ? 0 : _labelSize.height + LABEL_MARGIN)); - _maxSize = _CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0); + _minSize = CGSizeMake(MAX(_labelSize.width, minSize.width), (labelOnly ? 0 : minSize.height) + (iconOnly ? 0 : _labelSize.height + LABEL_MARGIN)); + _maxSize = CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0); [_toolbar tile]; } @@ -1116,14 +1116,14 @@ var LABEL_MARGIN = 2.0; return; var bounds = [self bounds], - width = _CGRectGetWidth(bounds); + width = CGRectGetWidth(bounds); if (identifier === CPToolbarSeparatorItemIdentifier) { var itemSeparatorColor = [_toolbar valueForThemeAttribute:@"image-item-separator-color"], itemSeparatorSize = [_toolbar valueForThemeAttribute:@"image-item-separator-size"]; - [_view setFrame:_CGRectMake(ROUND((width - itemSeparatorSize.size.width) / 2.0), 0.0, itemSeparatorSize.size.width, _CGRectGetHeight(bounds))]; + [_view setFrame:CGRectMake(ROUND((width - itemSeparatorSize.size.width) / 2.0), 0.0, itemSeparatorSize.size.width, CGRectGetHeight(bounds))]; [_view setBackgroundColor:itemSeparatorColor]; return; @@ -1133,17 +1133,17 @@ var LABEL_MARGIN = 2.0; var view = _view || _imageView, itemMaxSize = [_toolbarItem maxSize], iconOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeIconOnly, - height = _CGRectGetHeight(bounds) - (iconOnly ? 0 : _labelSize.height), + height = CGRectGetHeight(bounds) - (iconOnly ? 0 : _labelSize.height), viewWidth = MIN(itemMaxSize.width, width), viewHeight = MIN(itemMaxSize.height, height); - [view setFrame:_CGRectMake(ROUND((width - viewWidth) / 2.0), + [view setFrame:CGRectMake(ROUND((width - viewWidth) / 2.0), ROUND((height - viewHeight) / 2.0), viewWidth, viewHeight)]; // Label is always drawn at the bottom of the view. So if the view is really tall but the icon is tiny, the icon is centred above the label while the label remains on the bottom. - [_labelField setFrameOrigin:_CGPointMake(ROUND((width - _labelSize.width) / 2.0), _CGRectGetHeight(bounds) - _labelSize.height)]; + [_labelField setFrameOrigin:CGPointMake(ROUND((width - _labelSize.width) / 2.0), CGRectGetHeight(bounds) - _labelSize.height)]; } - (void)mouseDown:(CPEvent)anEvent @@ -1210,7 +1210,7 @@ var LABEL_MARGIN = 2.0; if (alternateImage) [_imageView setImage:alternateImage]; - [_labelField setTextShadowOffset:_CGSizeMakeZero()]; + [_labelField setTextShadowOffset:CGSizeMakeZero()]; } else { @@ -1219,7 +1219,7 @@ var LABEL_MARGIN = 2.0; if (image) [_imageView setImage:image]; - [_labelField setTextShadowOffset:_CGSizeMake(0.0, 1.0)]; + [_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)]; } [_labelField setTextShadowColor:[self FIXME_labelShadowColor]]; diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 49e0e4aea..186d1089f 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -294,8 +294,8 @@ var CPViewFlags = { }, if (self) { - var width = _CGRectGetWidth(aFrame), - height = _CGRectGetHeight(aFrame); + var width = CGRectGetWidth(aFrame), + height = CGRectGetHeight(aFrame); _subviews = []; _registeredDraggedTypes = [CPSet set]; @@ -303,8 +303,8 @@ var CPViewFlags = { }, _tag = -1; - _frame = _CGRectMakeCopy(aFrame); - _bounds = _CGRectMake(0.0, 0.0, width, height); + _frame = CGRectMakeCopy(aFrame); + _bounds = CGRectMake(0.0, 0.0, width, height); _autoresizingMask = CPViewNotSizable; _autoresizesSubviews = YES; @@ -317,7 +317,7 @@ var CPViewFlags = { }, #if PLATFORM(DOM) _DOMElement = DOMElementPrototype.cloneNode(false); - CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(aFrame), _CGRectGetMinY(aFrame)); + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(aFrame), CGRectGetMinY(aFrame)); CPDOMDisplayServerSetStyleSize(_DOMElement, width, height); if (typeof(appkit_tag_dom_elements) !== "undefined" && !!appkit_tag_dom_elements) @@ -829,7 +829,7 @@ var CPViewFlags = { }, */ - (void)setFrame:(CGRect)aFrame { - if (_CGRectEqualToRect(_frame, aFrame)) + if (CGRectEqualToRect(_frame, aFrame)) return; _inhibitFrameAndBoundsChangedNotifications = YES; @@ -849,17 +849,17 @@ var CPViewFlags = { }, */ - (CGRect)frame { - return _CGRectMakeCopy(_frame); + return CGRectMakeCopy(_frame); } - (CGPoint)frameOrigin { - return _CGPointMakeCopy(_frame.origin); + return CGPointMakeCopy(_frame.origin); } - (CGSize)frameSize { - return _CGSizeMakeCopy(_frame.size); + return CGSizeMakeCopy(_frame.size); } /*! @@ -894,7 +894,7 @@ var CPViewFlags = { }, { var origin = _frame.origin; - if (!aPoint || _CGPointEqualToPoint(origin, aPoint)) + if (!aPoint || CGPointEqualToPoint(origin, aPoint)) return; origin.x = aPoint.x; @@ -920,10 +920,10 @@ var CPViewFlags = { }, { var size = _frame.size; - if (!aSize || _CGSizeEqualToSize(size, aSize)) + if (!aSize || CGSizeEqualToSize(size, aSize)) return; - var oldSize = _CGSizeMakeCopy(size); + var oldSize = CGSizeMakeCopy(size); size.width = aSize.width; size.height = aSize.height; @@ -1060,7 +1060,7 @@ var CPViewFlags = { }, */ - (void)setBounds:(CGRect)bounds { - if (_CGRectEqualToRect(_bounds, bounds)) + if (CGRectEqualToRect(_bounds, bounds)) return; _inhibitFrameAndBoundsChangedNotifications = YES; @@ -1080,17 +1080,17 @@ var CPViewFlags = { }, */ - (CGRect)bounds { - return _CGRectMakeCopy(_bounds); + return CGRectMakeCopy(_bounds); } - (CGPoint)boundsOrigin { - return _CGPointMakeCopy(_bounds.origin); + return CGPointMakeCopy(_bounds.origin); } - (CGSize)boundsSize { - return _CGSizeMakeCopy(_bounds.size); + return CGSizeMakeCopy(_bounds.size); } /*! @@ -1103,7 +1103,7 @@ var CPViewFlags = { }, { var origin = _bounds.origin; - if (_CGPointEqualToPoint(origin, aPoint)) + if (CGPointEqualToPoint(origin, aPoint)) return; origin.x = aPoint.x; @@ -1111,7 +1111,7 @@ var CPViewFlags = { }, if (origin.x != 0 || origin.y != 0) { - _boundsTransform = _CGAffineTransformMakeTranslation(-origin.x, -origin.y); + _boundsTransform = CGAffineTransformMakeTranslation(-origin.x, -origin.y); _inverseBoundsTransform = CGAffineTransformInvert(_boundsTransform); } else @@ -1146,12 +1146,12 @@ var CPViewFlags = { }, { var size = _bounds.size; - if (_CGSizeEqualToSize(size, aSize)) + if (CGSizeEqualToSize(size, aSize)) return; var frameSize = _frame.size; - if (!_CGSizeEqualToSize(size, frameSize)) + if (!CGSizeEqualToSize(size, frameSize)) { var origin = _bounds.origin; @@ -1162,7 +1162,7 @@ var CPViewFlags = { }, size.width = aSize.width; size.height = aSize.height; - if (!_CGSizeEqualToSize(size, frameSize)) + if (!CGSizeEqualToSize(size, frameSize)) { var origin = _bounds.origin; @@ -1187,21 +1187,29 @@ var CPViewFlags = { }, return; var frame = _superview._frame, - newFrame = _CGRectMakeCopy(_frame), - dX = (_CGRectGetWidth(frame) - aSize.width) / - (((mask & CPViewMinXMargin) ? 1 : 0) + (mask & CPViewWidthSizable ? 1 : 0) + (mask & CPViewMaxXMargin ? 1 : 0)), - dY = (_CGRectGetHeight(frame) - aSize.height) / - ((mask & CPViewMinYMargin ? 1 : 0) + (mask & CPViewHeightSizable ? 1 : 0) + (mask & CPViewMaxYMargin ? 1 : 0)); + newFrame = CGRectMakeCopy(_frame), + dX = frame.size.width - aSize.width, + dY = frame.size.height - aSize.height, + evenFractionX = 1.0 / ((mask & CPViewMinXMargin ? 1 : 0) + (mask & CPViewWidthSizable ? 1 : 0) + (mask & CPViewMaxXMargin ? 1 : 0)), + evenFractionY = 1.0 / ((mask & CPViewMinYMargin ? 1 : 0) + (mask & CPViewHeightSizable ? 1 : 0) + (mask & CPViewMaxYMargin ? 1 : 0)), + baseX = (mask & CPViewMinXMargin ? _frame.origin.x : 0) + + (mask & CPViewWidthSizable ? _frame.size.width : 0) + + (mask & CPViewMaxXMargin ? aSize.width - _frame.size.width - _frame.origin.x : 0), + baseY = (mask & CPViewMinYMargin ? _frame.origin.y : 0) + + (mask & CPViewHeightSizable ? _frame.size.height : 0) + + (mask & CPViewMaxYMargin ? aSize.height - _frame.size.height - _frame.origin.y : 0); if (mask & CPViewMinXMargin) - newFrame.origin.x += dX; + newFrame.origin.x += dX * (baseX > 0 ? _frame.origin.x / baseX : evenFractionX); + if (mask & CPViewWidthSizable) - newFrame.size.width += dX; + newFrame.size.width += dX * (baseX > 0 ? _frame.size.width / baseX : evenFractionX); if (mask & CPViewMinYMargin) - newFrame.origin.y += dY; + newFrame.origin.y += dY * (baseY > 0 ? _frame.origin.y / baseY : evenFractionY); + if (mask & CPViewHeightSizable) - newFrame.size.height += dY; + newFrame.size.height += dY * (baseY > 0 ? _frame.size.height / baseY : evenFractionY); [self setFrame:newFrame]; } @@ -1539,15 +1547,15 @@ var CPViewFlags = { }, */ - (CPView)hitTest:(CGPoint)aPoint { - if (_isHidden || !_hitTests || !_CGRectContainsPoint(_frame, aPoint)) + if (_isHidden || !_hitTests || !CGRectContainsPoint(_frame, aPoint)) return nil; var view = nil, i = _subviews.length, - adjustedPoint = _CGPointMake(aPoint.x - _CGRectGetMinX(_frame), aPoint.y - _CGRectGetMinY(_frame)); + adjustedPoint = CGPointMake(aPoint.x - CGRectGetMinX(_frame), aPoint.y - CGRectGetMinY(_frame)); if (_inverseBoundsTransform) - adjustedPoint = _CGPointApplyAffineTransform(adjustedPoint, _inverseBoundsTransform); + adjustedPoint = CGPointApplyAffineTransform(adjustedPoint, _inverseBoundsTransform); while (i--) if (view = [_subviews[i] hitTest:adjustedPoint]) @@ -1986,9 +1994,6 @@ setFrameOrigin: return; _postsFrameChangedNotifications = shouldPostFrameChangedNotifications; - - if (_postsFrameChangedNotifications) - [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; } /*! @@ -2019,9 +2024,6 @@ setBoundsOrigin: return; _postsBoundsChangedNotifications = shouldPostBoundsChangedNotifications; - - if (_postsBoundsChangedNotifications) - [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; } /*! @@ -2134,20 +2136,20 @@ setBoundsOrigin: if (!(_viewClassFlags & CPViewHasCustomDrawRect)) return; - if (_CGRectIsEmpty(aRect)) + if (CGRectIsEmpty(aRect)) return; - if (_dirtyRect && !_CGRectIsEmpty(_dirtyRect)) + if (_dirtyRect && !CGRectIsEmpty(_dirtyRect)) _dirtyRect = CGRectUnion(aRect, _dirtyRect); else - _dirtyRect = _CGRectMakeCopy(aRect); + _dirtyRect = CGRectMakeCopy(aRect); _CPDisplayServerAddDisplayObject(self); } - (BOOL)needsDisplay { - return _dirtyRect && !_CGRectIsEmpty(_dirtyRect); + return _dirtyRect && !CGRectIsEmpty(_dirtyRect); } /*! @@ -2223,13 +2225,13 @@ setBoundsOrigin: _DOMContentsElement.style.position = "absolute"; _DOMContentsElement.style.visibility = "visible"; - _DOMContentsElement.width = ROUND(_CGRectGetWidth(_frame)); - _DOMContentsElement.height = ROUND(_CGRectGetHeight(_frame)); + _DOMContentsElement.width = ROUND(CGRectGetWidth(_frame)); + _DOMContentsElement.height = ROUND(CGRectGetHeight(_frame)); _DOMContentsElement.style.top = "0px"; _DOMContentsElement.style.left = "0px"; - _DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_frame)) + "px"; - _DOMContentsElement.style.height = ROUND(_CGRectGetHeight(_frame)) + "px"; + _DOMContentsElement.style.width = ROUND(CGRectGetWidth(_frame)) + "px"; + _DOMContentsElement.style.height = ROUND(CGRectGetHeight(_frame)) + "px"; // The performance implications of this aren't clear, but without this subviews might not be redrawn when this // view moves. @@ -2337,7 +2339,7 @@ setBoundsOrigin: aRect = CGRectIntersection(aRect, _bounds); // If aRect is empty no scrolling required. - if (_CGRectIsEmpty(aRect)) + if (CGRectIsEmpty(aRect)) return NO; var enclosingClipView = [self _enclosingClipView]; @@ -2360,18 +2362,18 @@ setBoundsOrigin: if (CGRectContainsRect(documentViewVisibleRect, rectInDocumentView)) return NO; - var scrollPoint = _CGPointMakeCopy(documentViewVisibleRect.origin); + var scrollPoint = CGPointMakeCopy(documentViewVisibleRect.origin); // One of the following has to be true since our current visible rect didn't contain aRect. - if (_CGRectGetMinX(rectInDocumentView) < _CGRectGetMinX(documentViewVisibleRect)) - scrollPoint.x = _CGRectGetMinX(rectInDocumentView); - else if (_CGRectGetMaxX(rectInDocumentView) > _CGRectGetMaxX(documentViewVisibleRect)) - scrollPoint.x += _CGRectGetMaxX(rectInDocumentView) - _CGRectGetMaxX(documentViewVisibleRect); + if (CGRectGetMinX(rectInDocumentView) < CGRectGetMinX(documentViewVisibleRect)) + scrollPoint.x = CGRectGetMinX(rectInDocumentView); + else if (CGRectGetMaxX(rectInDocumentView) > CGRectGetMaxX(documentViewVisibleRect)) + scrollPoint.x += CGRectGetMaxX(rectInDocumentView) - CGRectGetMaxX(documentViewVisibleRect); - if (_CGRectGetMinY(rectInDocumentView) < _CGRectGetMinY(documentViewVisibleRect)) - scrollPoint.y = _CGRectGetMinY(rectInDocumentView); - else if (_CGRectGetMaxY(rectInDocumentView) > _CGRectGetMaxY(documentViewVisibleRect)) - scrollPoint.y += _CGRectGetMaxY(rectInDocumentView) - _CGRectGetMaxY(documentViewVisibleRect); + if (CGRectGetMinY(rectInDocumentView) < CGRectGetMinY(documentViewVisibleRect)) + scrollPoint.y = CGRectGetMinY(rectInDocumentView); + else if (CGRectGetMaxY(rectInDocumentView) > CGRectGetMaxY(documentViewVisibleRect)) + scrollPoint.y += CGRectGetMaxY(rectInDocumentView) - CGRectGetMaxY(documentViewVisibleRect); [enclosingClipView scrollToPoint:scrollPoint]; @@ -2557,21 +2559,35 @@ setBoundsOrigin: - (void)_setPreviousKeyView:(CPView)previous { - if ([previous isEqual:self]) - _previousKeyView = nil; - else - _previousKeyView = previous; + if (![previous isEqual:self]) + { + var previousWindow = [previous window]; + + if (!previousWindow || previousWindow === _window) + { + _previousKeyView = previous; + return; + } + } + + _previousKeyView = nil; } - (void)setNextKeyView:(CPView)next { - if ([next isEqual:self]) - _nextKeyView = nil; - else + if (![next isEqual:self]) { - _nextKeyView = next; - [_nextKeyView _setPreviousKeyView:self]; + var nextWindow = [next window]; + + if (!nextWindow || nextWindow === _window) + { + _nextKeyView = next; + [_nextKeyView _setPreviousKeyView:self]; + return; + } } + + _nextKeyView = nil; } @end @@ -2948,7 +2964,7 @@ setBoundsOrigin: - (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName { - return _CGRectMakeZero(); + return CGRectMakeZero(); } - (CPView)layoutEphemeralSubviewNamed:(CPString)aViewName @@ -3087,8 +3103,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", _DOMImageParts = []; _DOMImageSizes = []; - CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame)); - CPDOMDisplayServerSetStyleSize(_DOMElement, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)); + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(_frame), CGRectGetMinY(_frame)); + CPDOMDisplayServerSetStyleSize(_DOMElement, CGRectGetWidth(_frame), CGRectGetHeight(_frame)); var index = 0, count = _subviews.length; @@ -3240,12 +3256,12 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView) { var frame = view._frame; - transform.tx += _CGRectGetMinX(frame); - transform.ty += _CGRectGetMinY(frame); + transform.tx += CGRectGetMinX(frame); + transform.ty += CGRectGetMinY(frame); if (view._boundsTransform) { - _CGAffineTransformConcatTo(transform, view._boundsTransform, transform); + CGAffineTransformConcatTo(transform, view._boundsTransform, transform); } view = view._superview; @@ -3266,8 +3282,8 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView) var frame = [fromWindow frame]; - transform.tx += _CGRectGetMinX(frame); - transform.ty += _CGRectGetMinY(frame); + transform.tx += CGRectGetMinX(frame); + transform.ty += CGRectGetMinY(frame); } } } @@ -3279,12 +3295,12 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView) { var frame = view._frame; - transform.tx -= _CGRectGetMinX(frame); - transform.ty -= _CGRectGetMinY(frame); + transform.tx -= CGRectGetMinX(frame); + transform.ty -= CGRectGetMinY(frame); if (view._boundsTransform) { - _CGAffineTransformConcatTo(transform, view._inverseBoundsTransform, transform); + CGAffineTransformConcatTo(transform, view._inverseBoundsTransform, transform); } view = view._superview; @@ -3294,8 +3310,8 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView) { var frame = [toWindow frame]; - transform.tx -= _CGRectGetMinX(frame); - transform.ty -= _CGRectGetMinY(frame); + transform.tx -= CGRectGetMinX(frame); + transform.ty -= CGRectGetMinY(frame); } /* var views = [], view = toView; @@ -3312,8 +3328,8 @@ var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView) { var frame = views[index]._frame; - transform.tx -= _CGRectGetMinX(frame); - transform.ty -= _CGRectGetMinY(frame); + transform.tx -= CGRectGetMinX(frame); + transform.ty -= CGRectGetMinY(frame); }*/ return transform; diff --git a/AppKit/CPViewAnimation.j b/AppKit/CPViewAnimation.j index 932085442..85f76e2a2 100644 --- a/AppKit/CPViewAnimation.j +++ b/AppKit/CPViewAnimation.j @@ -116,7 +116,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect"; view = [self _targetView:dictionary], startFrame = [self _startFrame:dictionary], endFrame = [self _endFrame:dictionary], - differenceFrame = _CGRectMakeZero(), + differenceFrame = CGRectMakeZero(), value = [super currentValue]; differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x; @@ -124,7 +124,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect"; differenceFrame.size.width = endFrame.size.width - startFrame.size.width; differenceFrame.size.height = endFrame.size.height - startFrame.size.height; - var intermediateFrame = _CGRectMakeZero(); + var intermediateFrame = CGRectMakeZero(); intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * value; intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * value; intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * value; @@ -140,7 +140,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect"; [view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * value]; if (progress === 1.0) - [self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0]; + [self _targetView:view setHidden:CGRectIsEmpty(endFrame) || [view alphaValue] === 0.0]; } } @@ -161,7 +161,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect"; else if (effect === CPViewAnimationFadeOutEffect) [view setAlphaValue:0.0]; - [self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0]; + [self _targetView:view setHidden:CGRectIsEmpty(endFrame) || [view alphaValue] === 0.0]; } [super stopAnimation]; diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index c1f8a677e..ccac5bf02 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -56,7 +56,10 @@ var CPWindowSaveImage = nil, CPWindowResizeTime = 0.2, - CPWindowResizeStyleGlobalChangeNotification = @"CPWindowResizeStyleGlobalChangeNotification"; + CPWindowResizeStyleGlobalChangeNotification = @"CPWindowResizeStyleGlobalChangeNotification", + + CPWindowMinVisibleHorizontalMargin = 40, + CPWindowMinVisibleVerticalMargin = 2; /* Keys for which action messages will be sent by default when unhandled, e.g. complete:. @@ -144,6 +147,7 @@ var CPWindowActionMessageKeys = [ BOOL _hasShadow; BOOL _isMovableByWindowBackground; BOOL _isMovable; + BOOL _constrainsToUsableScreen; unsigned _shadowStyle; BOOL _showsResizeIndicator; @@ -226,7 +230,7 @@ var CPWindowActionMessageKeys = [ - (id)init { - return [self initWithContentRect:_CGRectMakeZero() styleMask:CPTitledWindowMask]; + return [self initWithContentRect:CGRectMakeZero() styleMask:CPTitledWindowMask]; } /*! @@ -253,6 +257,7 @@ CPTexturedBackgroundWindowMask var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask]; _frame = [windowViewClass frameRectForContentRect:aContentRect]; + _constrainsToUsableScreen = YES; [self _setSharesChromeWithPlatformWindow:![CPPlatform isBrowser]]; @@ -298,19 +303,19 @@ CPTexturedBackgroundWindowMask [self setLevel:CPNormalWindowLevel]; // Create our border view which is the actual root of our view hierarchy. - _windowView = [[windowViewClass alloc] initWithFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)) styleMask:aStyleMask]; + _windowView = [[windowViewClass alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)) styleMask:aStyleMask]; [_windowView _setWindow:self]; [_windowView setNextResponder:self]; // Size calculation needs _windowView - _minSize = [self _calculateMinSizeForProposedSize:_CGSizeMake(0.0, 0.0)]; - _maxSize = _CGSizeMake(1000000.0, 1000000.0); + _minSize = [self _calculateMinSizeForProposedSize:CGSizeMake(0.0, 0.0)]; + _maxSize = CGSizeMake(1000000.0, 1000000.0); [self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask]; // Create a generic content view. - [self setContentView:[[CPView alloc] initWithFrame:_CGRectMakeZero()]]; + [self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]]; _firstResponder = self; @@ -323,7 +328,7 @@ CPTexturedBackgroundWindowMask if (![self _sharesChromeWithPlatformWindow]) { - CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame)); + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(_frame), CGRectGetMinY(_frame)); } CPDOMDisplayServerSetStyleSize(_DOMElement, 1, 1); @@ -542,7 +547,7 @@ CPTexturedBackgroundWindowMask _fullPlatformWindowSession = _CPWindowFullPlatformWindowSessionMake(_windowView, [self contentRectForFrameRect:[self frame]], [self hasShadow], [self level]); var fullPlatformWindowViewClass = [[self class] _windowViewClassForFullPlatformWindowStyleMask:_styleMask], - windowView = [[fullPlatformWindowViewClass alloc] initWithFrame:_CGRectMakeZero() styleMask:_styleMask]; + windowView = [[fullPlatformWindowViewClass alloc] initWithFrame:CGRectMakeZero() styleMask:_styleMask]; [self _setWindowView:windowView]; @@ -628,7 +633,7 @@ CPTexturedBackgroundWindowMask */ - (CGRect)frame { - return _CGRectMakeCopy(_frame); + return CGRectMakeCopy(_frame); } /*! @@ -640,48 +645,54 @@ CPTexturedBackgroundWindowMask */ - (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate { - aFrame = _CGRectMakeCopy(aFrame); + [self _setFrame:aFrame display:shouldDisplay animate:shouldAnimate constrainWidth:NO constrainHeight:YES]; +} - var value = aFrame.origin.x, +- (void)_setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate constrainWidth:(BOOL)shouldConstrainWidth constrainHeight:(BOOL)shouldConstrainHeight +{ + var frame = CGRectMakeCopy(aFrame), + value = frame.origin.x, delta = value - FLOOR(value); if (delta) - aFrame.origin.x = value > 0.879 ? CEIL(value) : FLOOR(value); + frame.origin.x = value > 0.879 ? CEIL(value) : FLOOR(value); - value = aFrame.origin.y; + value = frame.origin.y; delta = value - FLOOR(value); if (delta) - aFrame.origin.y = value > 0.879 ? CEIL(value) : FLOOR(value); + frame.origin.y = value > 0.879 ? CEIL(value) : FLOOR(value); - value = aFrame.size.width; + value = frame.size.width; delta = value - FLOOR(value); if (delta) - aFrame.size.width = value > 0.15 ? CEIL(value) : FLOOR(value); + frame.size.width = value > 0.15 ? CEIL(value) : FLOOR(value); - value = aFrame.size.height; + value = frame.size.height; delta = value - FLOOR(value); if (delta) - aFrame.size.height = value > 0.15 ? CEIL(value) : FLOOR(value); + frame.size.height = value > 0.15 ? CEIL(value) : FLOOR(value); + + frame = [self _constrainFrame:frame toUsableScreenWidth:shouldConstrainWidth andHeight:shouldConstrainHeight]; if (shouldAnimate) { [_frameAnimation stopAnimation]; - _frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame]; + _frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:frame]; [_frameAnimation startAnimation]; } else { var origin = _frame.origin, - newOrigin = aFrame.origin, - originMoved = !_CGPointEqualToPoint(origin, newOrigin); + newOrigin = frame.origin, + originMoved = !CGPointEqualToPoint(origin, newOrigin); if (originMoved) { - delta = _CGPointMake(newOrigin.x - origin.x, newOrigin.y - origin.y); + delta = CGPointMake(newOrigin.x - origin.x, newOrigin.y - origin.y); origin.x = newOrigin.x; origin.y = newOrigin.y; @@ -692,13 +703,17 @@ CPTexturedBackgroundWindowMask } #endif + // reposition sheet + if ([self attachedSheet]) + [self _setAttachedSheetFrameOrigin]; + [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMoveNotification object:self]; } var size = _frame.size, - newSize = aFrame.size; + newSize = frame.size; - if (!_CGSizeEqualToSize(size, newSize)) + if (!CGSizeEqualToSize(size, newSize)) { size.width = newSize.width; size.height = newSize.height; @@ -720,13 +735,87 @@ CPTexturedBackgroundWindowMask } } +- (CGRect)_constrainFrame:(CGRect)aFrame toUsableScreenWidth:(BOOL)constrainWidth andHeight:(BOOL)constrainHeight +{ + var frame = CGRectMakeCopy(aFrame); + + if (!_constrainsToUsableScreen || !_isVisible) + return frame; + + var usableRect = [_platformWindow usableContentFrame]; + + if (constrainWidth) + { + // First move the frame right to ensure the left side is within the usable rect. + frame.origin.x = MAX(frame.origin.x, usableRect.origin.x); + + // Now move the frame left so that the right side is within the usable rect. + var maxX = MIN(CGRectGetMaxX(frame), CGRectGetMaxX(usableRect)); + frame.origin.x = maxX - frame.size.width; + + // Finally, adjust the left + width to ensure the left side is within the usable rect. + var usableWidth = CGRectGetWidth(usableRect); + + if (CGRectGetWidth(frame) > usableWidth) + { + frame.origin.x = CGRectGetMinX(usableRect); + frame.size.width = usableWidth; + } + } + + if (constrainHeight) + { + // First move the frame down to ensure the top is within the usable rect. + frame.origin.y = MAX(frame.origin.y, usableRect.origin.y); + + // Now move the frame up so that the bottom is within the usable rect. + var maxY = MIN(CGRectGetMaxY(frame), CGRectGetMaxY(usableRect)); + frame.origin.y = maxY - frame.size.height; + + // Finally, adjust the top + height to ensure the top is within the usable rect. + var usableHeight = CGRectGetHeight(usableRect); + + if (CGRectGetHeight(frame) > usableHeight) + { + frame.origin.y = CGRectGetMinY(usableRect); + frame.size.height = usableHeight; + } + } + + return frame; +} + +- (CGRect)_constrainOriginOfFrame:(CGRect)aFrame +{ + var frame = CGRectMakeCopy(aFrame); + + if (!_constrainsToUsableScreen || !_isVisible) + return frame; + + /* + - CPWindowMinVisibleHorizontalMargin is kept onscreen at the left/right of the window. + - The top of the window is kept below the top of the usable content. + - The top of the contentView + CPWindowMinVisibleVerticalMargin is kept above the bottom of the usable content. + */ + var usableRect = [_platformWindow usableContentFrame], + maxUsableY = CGRectGetMaxY(usableRect) - CGRectGetMinY([_contentView frame]) - CPWindowMinVisibleVerticalMargin; + + frame.origin.x = MAX(frame.origin.x, CGRectGetMinX(usableRect) + CPWindowMinVisibleHorizontalMargin - CGRectGetWidth(frame)); + frame.origin.x = MIN(frame.origin.x, CGRectGetMaxX(usableRect) - CPWindowMinVisibleHorizontalMargin); + + frame.origin.y = MAX(frame.origin.y, CGRectGetMinY(usableRect)); + frame.origin.y = MIN(frame.origin.y, maxUsableY); + + return frame; +} + - (void)_moveChildWindows:(CGPoint)delta { [_childWindows enumerateObjectsUsingBlock:function(childWindow) { var origin = [childWindow frame].origin; - [childWindow setFrameOrigin:_CGPointMake(origin.x + delta.x, origin.y + delta.y)]; + [childWindow setFrameOrigin:CGPointMake(origin.x + delta.x, origin.y + delta.y)]; } ]; } @@ -756,11 +845,8 @@ CPTexturedBackgroundWindowMask */ - (void)setFrameOrigin:(CGPoint)anOrigin { - [self setFrame:_CGRectMake(anOrigin.x, anOrigin.y, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)) display:YES animate:NO]; - - // reposition sheet - if ([self attachedSheet]) - [self _setAttachedSheetFrameOrigin]; + var frame = [self _constrainOriginOfFrame:CGRectMake(anOrigin.x, anOrigin.y, _frame.size.width, _frame.size.height)]; + [self _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO]; } /*! @@ -769,7 +855,7 @@ CPTexturedBackgroundWindowMask */ - (void)setFrameSize:(CGSize)aSize { - [self setFrame:_CGRectMake(_CGRectGetMinX(_frame), _CGRectGetMinY(_frame), aSize.width, aSize.height) display:YES animate:NO]; + [self setFrame:CGRectMake(CGRectGetMinX(_frame), CGRectGetMinY(_frame), aSize.width, aSize.height) display:YES animate:NO]; } /*! @@ -785,9 +871,12 @@ CPTexturedBackgroundWindowMask { #if PLATFORM(DOM) // -dw- if a sheet is clicked, the parent window should come up too - if ([self isSheet]) + if (_isSheet) [_parentView orderFront:self]; + if (!_isVisible) + [self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES]; + [_platformWindow orderFront:self]; [_platformWindow order:CPWindowAbove window:self relativeTo:nil]; #endif @@ -994,7 +1083,7 @@ CPTexturedBackgroundWindowMask if (_contentView) [_contentView removeFromSuperview]; - var bounds = _CGRectMake(0.0, 0.0, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)); + var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)); _contentView = aView; [_contentView setFrame:[self contentRectForFrameRect:bounds]]; @@ -1061,12 +1150,12 @@ CPTexturedBackgroundWindowMask */ - (void)setMinSize:(CGSize)aSize { - if (_CGSizeEqualToSize(_minSize, aSize)) + if (CGSizeEqualToSize(_minSize, aSize)) return; _minSize = [self _calculateMinSizeForProposedSize:aSize]; - var size = _CGSizeMakeCopy([self frame].size), + var size = CGSizeMakeCopy([self frame].size), needsFrameChange = NO; if (size.width < _minSize.width) @@ -1097,9 +1186,9 @@ CPTexturedBackgroundWindowMask - (CGSize)_calculateMinSizeForProposedSize:(CGSize)proposedSize { var contentFrame = [self contentRectForFrameRect:_frame], - minHeight = _CGRectGetHeight(_frame) - _CGRectGetHeight(contentFrame); + minHeight = CGRectGetHeight(_frame) - CGRectGetHeight(contentFrame); - return _CGSizeMake(MAX(proposedSize.width, 0), MAX(proposedSize.height, minHeight)); + return CGSizeMake(MAX(proposedSize.width, 0), MAX(proposedSize.height, minHeight)); } /*! @@ -1110,12 +1199,12 @@ CPTexturedBackgroundWindowMask */ - (void)setMaxSize:(CGSize)aSize { - if (_CGSizeEqualToSize(_maxSize, aSize)) + if (CGSizeEqualToSize(_maxSize, aSize)) return; - _maxSize = _CGSizeMakeCopy(aSize); + _maxSize = CGSizeMakeCopy(aSize); - var size = _CGSizeMakeCopy([self frame].size), + var size = CGSizeMakeCopy([self frame].size), needsFrameChange = NO; if (size.width > _maxSize.width) @@ -1169,7 +1258,7 @@ CPTexturedBackgroundWindowMask if (_hasShadow && !_shadowView) { - _shadowView = [[_CPShadowWindowView alloc] initWithFrame:CGRectMakeZero()]; + _shadowView = [[_CPShadowWindowView alloc] initWithFrame:CGRectMakeZero()]; [_shadowView setWindowView:_windowView]; [_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; @@ -1454,8 +1543,6 @@ CPTexturedBackgroundWindowMask [_windowView setTitle:aTitle]; [_platformWindow _setTitle:_title window:self]; - - [self _synchronizeMenuBarTitleWithWindowTitle]; } /*! @@ -1552,7 +1639,7 @@ CPTexturedBackgroundWindowMask var size = [self frame].size, containerSize = [CPPlatform isBrowser] ? [_platformWindow contentBounds].size : [[self screen] visibleFrame].size; - var origin = _CGPointMake((containerSize.width - size.width) / 2.0, (containerSize.height - size.height) / 2.0); + var origin = CGPointMake((containerSize.width - size.width) / 2.0, (containerSize.height - size.height) / 2.0); if (origin.x < 0.0) origin.x = 0.0; @@ -1570,13 +1657,12 @@ CPTexturedBackgroundWindowMask - (void)sendEvent:(CPEvent)anEvent { var type = [anEvent type], - point = [anEvent locationInWindow]; + sheet = [self attachedSheet]; // If a sheet is attached events get filtered here. // It is not clear what events should be passed to the view, perhaps all? // CPLeftMouseDown is needed for window moving and resizing to work. // CPMouseMoved is needed for rollover effects on title bar buttons. - var sheet = [self attachedSheet]; if (sheet) { @@ -1588,15 +1674,20 @@ CPTexturedBackgroundWindowMask // -dw- if the window is clicked, the sheet should come to front, and become key, // and the window should be immediately behind [sheet makeKeyAndOrderFront:self]; - break; - case CPMouseMoved: - [_windowView mouseMoved:anEvent]; - break; - } + return; - return; + case CPMouseMoved: + // Allow these through to the parent + break; + + default: + // Everything else is filtered + return; + } } + var point = [anEvent locationInWindow]; + switch (type) { case CPFlagsChanged: @@ -1717,7 +1808,8 @@ CPTexturedBackgroundWindowMask case CPMouseMoved: [_windowView setCursorForLocation:point resizing:NO]; - if (!_acceptsMouseMovedEvents) + // Ignore mouse moves for parents of sheets + if (!_acceptsMouseMovedEvents || sheet) return; if (!_mouseEnteredStack) @@ -2234,6 +2326,13 @@ CPTexturedBackgroundWindowMask */ - (void)makeMainWindow { + // Sheets cannot be main. Their parent window becomes main. + if (_isSheet) + { + [_parentView makeMainWindow]; + return; + } + if ([CPApp mainWindow] === self || ![self canBecomeMainWindow]) return; @@ -2248,7 +2347,6 @@ CPTexturedBackgroundWindowMask { CPApp._mainWindow = self; - [self _synchronizeMenuBarTitleWithWindowTitle]; [self _synchronizeSaveMenuWithDocumentSaving]; [_windowView noteMainWindowStateChanged]; @@ -2387,7 +2485,7 @@ CPTexturedBackgroundWindowMask - (void)_noteToolbarChanged { - var frame = _CGRectMakeCopy([self frame]), + var frame = CGRectMakeCopy([self frame]), newFrame; [_windowView noteToolbarChanged]; @@ -2396,7 +2494,7 @@ CPTexturedBackgroundWindowMask newFrame = [_platformWindow visibleFrame]; else { - newFrame = _CGRectMakeCopy([self frame]); + newFrame = CGRectMakeCopy([self frame]); newFrame.origin = frame.origin; } @@ -2453,6 +2551,22 @@ CPTexturedBackgroundWindowMask return _parentWindow; } +/*! + Return YES if anAncestor is the parent or a higher ancestor of the receiver. + + @ignore +*/ +- (BOOL)_hasAncestorWindow:(CPWindow)anAncestor +{ + if (!_parentWindow || !anAncestor) + return NO; + + if (anAncestor === _parentWindow) + return YES; + + return [_parentWindow _hasAncestorWindow:anAncestor]; +} + - (CPWindow)setParentWindow:(CPWindow)parentWindow { _parentWindow = parentWindow; @@ -2473,25 +2587,24 @@ CPTexturedBackgroundWindowMask return CPWindowResizeTime; } -/* @ignore */ - (void)_setAttachedSheetFrameOrigin { // Position the sheet above the contentRect. var attachedSheet = [self attachedSheet], contentRect = [_contentView frame], - sheetFrame = _CGRectMakeCopy([attachedSheet frame]); + sheetFrame = CGRectMakeCopy([attachedSheet frame]); - sheetFrame.origin.y = _CGRectGetMinY(_frame) + _CGRectGetMinY(contentRect); - sheetFrame.origin.x = _CGRectGetMinX(_frame) + FLOOR((_CGRectGetWidth(_frame) - _CGRectGetWidth(sheetFrame)) / 2.0); + sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect); + sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0); [attachedSheet setFrame:sheetFrame display:YES animate:NO]; } -/* @ignore +/* Starting point for sheet session, called from CPApplication beginSheet: */ - (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate - didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo + didEndSelector:(SEL)didEndSelector contextInfo:(id)contextInfo { if (_sheetContext) { @@ -2500,24 +2613,21 @@ CPTexturedBackgroundWindowMask return; } - var sheetFrame = [aSheet frame]; + _sheetContext = { + "sheet": aSheet, + "modalDelegate": aModalDelegate, + "endSelector": didEndSelector, + "contextInfo": contextInfo, + "returnCode": -1, + "opened": NO, + "isAttached": YES, + "savedConstrains": aSheet._constrainsToUsableScreen + }; - _sheetContext = {"sheet": aSheet, "modalDelegate": aModalDelegate, "endSelector": aDidEndSelector, - "contextInfo": aContextInfo, "frame": _CGRectMakeCopy(sheetFrame), "returnCode": -1, - "opened": NO}; + // Sheets are not constrained, they are controlled by their parent + aSheet._constrainsToUsableScreen = NO; - [self _attachSheetWindow]; -} - -/* @ignore - Called to animate the sheet in. The timer seems to solve a bug where sheets would - be partially animated under certain conditions. -*/ -- (void)_attachSheetWindow -{ - _sheetContext["isAttached"] = YES; - - // it would be ideal to block here and spin an event loop, until attach is complete + // A timer seems to be necessary for the animation to work correctly [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(_sheetShouldAnimateIn:) @@ -2525,7 +2635,7 @@ CPTexturedBackgroundWindowMask repeats:NO]; } -/* @ignore +/* Called to end the sheet. Note that orderOut: is needed to animate the sheet out, as in Cocoa. The sheet isn't completely gone until _cleanupSheetWindow gets called. */ @@ -2546,7 +2656,7 @@ CPTexturedBackgroundWindowMask } } -/* @ignore +/* Called to animate the sheet out. If called while animating in, schedules an animate out at completion */ @@ -2554,7 +2664,8 @@ CPTexturedBackgroundWindowMask { _sheetContext["isAttached"] = NO; - // it would be ideal to block here and spin the event loop, until attach is complete + // A timer seems to be necessary for the animation to work correctly. + // It would be ideal to block here and spin the event loop, until attach is complete. [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(_sheetShouldAnimateOut:) @@ -2562,27 +2673,26 @@ CPTexturedBackgroundWindowMask repeats:NO]; } -/* @ignore +/* Called to cleanup sheet, when we are definitely done with it */ - (void)_cleanupSheetWindow { var sheet = _sheetContext["sheet"], - lastFrame = _sheetContext["frame"], deferDidEnd = _sheetContext["deferDidEndSelector"]; - [sheet setFrame:lastFrame]; - [self _restoreMasksForView:[sheet contentView]]; - - // if the parent window is modal, the sheet started its own modal session + // If the parent window is modal, the sheet started its own modal session if (sheet._isModal) [CPApp stopModal]; - // restore the state of window before it was sheetified - [sheet._windowView _enableSheet:NO]; + [self _removeClipForSheet:sheet]; - // close it + // Restore the state of window before it was sheetified sheet._isSheet = NO; + [sheet._windowView _enableSheet:NO inWindow:self]; + sheet._constrainsToUsableScreen = _sheetContext["savedConstrains"]; + + // Close it [sheet orderOut:self]; [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self]; @@ -2594,7 +2704,7 @@ CPTexturedBackgroundWindowMask returnCode = _sheetContext["returnCode"], contextInfo = _sheetContext["contextInfo"]; - // context must be destroyed, since didEnd might want to attach another sheet + // Context must be destroyed, since didEnd might want to attach another sheet _sheetContext = nil; sheet._parentView = nil; @@ -2622,31 +2732,19 @@ CPTexturedBackgroundWindowMask repeats:NO]; } -/* @ignore */ - (void)_sheetShouldAnimateIn:(CPTimer)timer { - // can't open sheet while opening or closing animation is going on - if (_sheetContext["isOpening"] || - _sheetContext["isClosing"]) + // Can't open sheet while opening or closing animation is going on + if (_sheetContext["isOpening"] || _sheetContext["isClosing"]) return; - var sheet = _sheetContext["sheet"], - sheetFrame = [sheet frame], - frame = [self frame]; - - [self _setUpMasksForView:[sheet contentView]]; - + var sheet = _sheetContext["sheet"]; sheet._isSheet = YES; sheet._parentView = self; - var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2), - originy = frame.origin.y + [_contentView frame].origin.y, - startFrame = _CGRectMake(originx, originy, sheetFrame.size.width, 0), - endFrame = _CGRectMake(originx, originy, sheetFrame.size.width, sheetFrame.size.height); - [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self]; - // if sheet is attached to a modal window, the sheet runs + // If sheet is attached to a modal window, the sheet runs // as if itself and the parent window are modal sheet._isModal = NO; @@ -2656,7 +2754,22 @@ CPTexturedBackgroundWindowMask sheet._isModal = YES; } + // The sheet starts hidden just above the top of a clip rect + var sheetFrame = [sheet frame], + sheetShadowFrame = sheet._hasShadow ? [sheet._shadowView frame] : sheetFrame, + frame = [self frame], + originX = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2), + startFrame = CGRectMake(originX, -sheetShadowFrame.size.height, sheetFrame.size.width, sheetFrame.size.height), + endY = [_windowView bodyOffset] - [[self contentView] frame].origin.y, + endFrame = CGRectMake(originX, endY, sheetFrame.size.width, sheetFrame.size.height); + + // Move the sheet offscreen before ordering front so it doesn't appear briefly + [sheet setFrameOrigin:CGPointMake(0, -13000)]; + + // Because clipping does funny thing with the DOM, we have to orderFront before clipping [sheet orderFront:self]; + [self _clipSheet:sheet]; + [sheet setFrame:startFrame display:YES animate:NO]; _sheetContext["opened"] = YES; @@ -2664,23 +2777,13 @@ CPTexturedBackgroundWindowMask _sheetContext["isOpening"] = YES; [sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut]; - - // NOTE: cocoa doesn't make window key until animation is done, but a - // keypress while animating eventually gets to the window. Therefore, - // there must be a runloop specifically designed for sheets? - [sheet makeKeyWindow]; } -/* @ignore */ - (void)_sheetShouldAnimateOut:(CPTimer)timer { - var sheet = _sheetContext["sheet"], - startFrame = [sheet frame], - endFrame = _CGRectMakeCopy(startFrame); - if (_sheetContext["isOpening"]) { - // allow sheet to be closed while opening, it will close when animate in completes + // Allow sheet to be closed while opening, it will close when animate in completes _sheetContext["shouldClose"] = YES; return; } @@ -2689,14 +2792,24 @@ CPTexturedBackgroundWindowMask return; _sheetContext["opened"] = NO; - _sheetContext["frame"] = startFrame; _sheetContext["isClosing"] = YES; - // the parent window can be orderedOut to disable the sheet animate out, as in Cocoa + // The parent window can be orderedOut to disable the sheet animate out, as in Cocoa if ([self isVisible]) { - endFrame.size.height = 0; - [self _setUpMasksForView:[sheet contentView]]; + var sheet = _sheetContext["sheet"], + sheetFrame = [sheet frame], + fullHeight = sheet._hasShadow ? [sheet._shadowView frame].size.height : sheetFrame.size.height, + endFrame = CGRectMakeCopy(sheetFrame), + contentOrigin = [self convertBaseToGlobal:[[self contentView] frame].origin]; + + // Don't constrain sheets, they are controlled by the parent + sheet._constrainsToUsableScreen = NO; + + [sheet setFrameOrigin:CGPointMake(sheetFrame.origin.x, sheetFrame.origin.y - contentOrigin.y)]; + [self _clipSheet:sheet]; + + endFrame.origin.y = -fullHeight; [sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn]; } else @@ -2705,7 +2818,6 @@ CPTexturedBackgroundWindowMask } } -/* @ignore */ - (void)_sheetAnimationDidEnd:(CPTimer)timer { var sheet = _sheetContext["sheet"]; @@ -2715,12 +2827,17 @@ CPTexturedBackgroundWindowMask if (_sheetContext["opened"] === YES) { - // sheet is open and completely visible - [self _restoreMasksForView:[sheet contentView]]; + var sheetFrame = [sheet frame], + sheetOrigin = CGPointMakeCopy(sheetFrame.origin); + + [self _removeClipForSheet:sheet]; + [sheet setFrameOrigin:CGPointMake(sheetOrigin.x, [sheet frame].origin.y + sheetOrigin.y)]; // we wanted to close the sheet while it animated in, do that now if (_sheetContext["shouldClose"] === YES) [self _detachSheetWindow]; + else + [sheet makeKeyWindow]; } else { @@ -2729,36 +2846,17 @@ CPTexturedBackgroundWindowMask } } -- (void)_setUpMasksForView:(CPView)aView +- (void)_clipSheet:(CPWindow)aSheet { - var views = [aView subviews]; + var clipRect = [_platformWindow contentBounds]; + clipRect.origin.y = [self frame].origin.y + [[self contentView] frame].origin.y; - [views addObject:aView]; - - for (var i = 0, count = [views count]; i < count; i++) - { - var view = [views objectAtIndex:i], - mask = [view autoresizingMask], - maskToAdd = (mask & CPViewMinYMargin) ? 128 : CPViewMinYMargin; - - [view setAutoresizingMask:(mask | maskToAdd)]; - } + [[_platformWindow layerAtLevel:_level create:NO] clipWindow:aSheet toRect:clipRect]; } -- (void)_restoreMasksForView:(CPView)aView +- (void)_removeClipForSheet:(CPWindow)aSheet { - var views = [aView subviews]; - - [views addObject:aView]; - - for (var i = 0, count = [views count]; i < count; i++) - { - var view = [views objectAtIndex:i], - mask = [view autoresizingMask], - maskToRemove = (mask & 128) ? 128 : CPViewMinYMargin; - - [view setAutoresizingMask:(mask & (~ maskToRemove))]; - } + [[_platformWindow layerAtLevel:_level create:NO] removeClipForWindow:aSheet]; } /*! @@ -3125,11 +3223,11 @@ var keyViewComparator = function(lhs, rhs, context) { var lhsBounds = [lhs convertRect:[lhs bounds] toView:nil], rhsBounds = [rhs convertRect:[rhs bounds] toView:nil], - lhsY = _CGRectGetMinY(lhsBounds), - rhsY = _CGRectGetMinY(rhsBounds), - lhsX = _CGRectGetMinX(lhsBounds), - rhsX = _CGRectGetMinX(rhsBounds), - intersectsVertically = MIN(_CGRectGetMaxY(lhsBounds), _CGRectGetMaxY(rhsBounds)) - MAX(lhsY, rhsY); + lhsY = CGRectGetMinY(lhsBounds), + rhsY = CGRectGetMinY(rhsBounds), + lhsX = CGRectGetMinX(lhsBounds), + rhsX = CGRectGetMinX(rhsBounds), + intersectsVertically = MIN(CGRectGetMaxY(lhsBounds), CGRectGetMaxY(rhsBounds)) - MAX(lhsY, rhsY); // If two views are "on the same line" (intersect vertically), then rely on the x comparison. if (intersectsVertically > 0) @@ -3152,19 +3250,6 @@ var keyViewComparator = function(lhs, rhs, context) return CPOrderedDescending; }; -@implementation CPWindow (MenuBar) - -- (void)_synchronizeMenuBarTitleWithWindowTitle -{ - // Windows with Documents automatically update the native window title and the menu bar title. - if (![_windowController document] || ![self isMainWindow]) - return; - - [CPMenu setMenuBarTitle:_title]; -} - -@end - @implementation CPWindow (BridgeSupport) /* @@ -3175,23 +3260,25 @@ var keyViewComparator = function(lhs, rhs, context) if ([self isFullPlatformWindow]) return [self setFrame:[_platformWindow visibleFrame]]; - if (_autoresizingMask == CPWindowNotSizable) + if (_autoresizingMask === CPWindowNotSizable) return; var frame = [_platformWindow contentBounds], - newFrame = _CGRectMakeCopy(_frame), - dX = (_CGRectGetWidth(frame) - aSize.width) / + newFrame = CGRectMakeCopy(_frame), + dX = (CGRectGetWidth(frame) - aSize.width) / (((_autoresizingMask & CPWindowMinXMargin) ? 1 : 0) + (_autoresizingMask & CPWindowWidthSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxXMargin ? 1 : 0)), - dY = (_CGRectGetHeight(frame) - aSize.height) / + dY = (CGRectGetHeight(frame) - aSize.height) / ((_autoresizingMask & CPWindowMinYMargin ? 1 : 0) + (_autoresizingMask & CPWindowHeightSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxYMargin ? 1 : 0)); if (_autoresizingMask & CPWindowMinXMargin) newFrame.origin.x += dX; + if (_autoresizingMask & CPWindowWidthSizable) newFrame.size.width += dX; if (_autoresizingMask & CPWindowMinYMargin) newFrame.origin.y += dY; + if (_autoresizingMask & CPWindowHeightSizable) newFrame.size.height += dY; @@ -3236,11 +3323,11 @@ var keyViewComparator = function(lhs, rhs, context) - (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint { if ([self _sharesChromeWithPlatformWindow]) - return _CGPointMakeCopy(aPoint); + return CGPointMakeCopy(aPoint); var origin = [self frame].origin; - return _CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y); + return CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y); } /*! @@ -3249,11 +3336,11 @@ var keyViewComparator = function(lhs, rhs, context) - (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint { if ([self _sharesChromeWithPlatformWindow]) - return _CGPointMakeCopy(aPoint); + return CGPointMakeCopy(aPoint); var origin = [self frame].origin; - return _CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y); + return CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y); } - (CGPoint)convertScreenToBase:(CGPoint)aPoint @@ -3329,7 +3416,7 @@ var keyViewComparator = function(lhs, rhs, context) - (BOOL)containsPoint:(CGPoint)aPoint { - return _CGRectContainsPoint(_frame, aPoint); + return CGRectContainsPoint(_frame, aPoint); } /* aPoint should be global */ @@ -3337,9 +3424,9 @@ var keyViewComparator = function(lhs, rhs, context) { // If we are using the new resizing mode, mouse events are valid // outside the window's frame for non-full platform windows. - var mouseFrame = (!_isFullPlatformWindow && (_styleMask & CPResizableWindowMask) && (CPWindowResizeStyle === CPWindowResizeStyleModern)) ? _CGRectInset(_frame, -_CPWindowViewResizeSlop, -_CPWindowViewResizeSlop) : _frame; + var mouseFrame = (!_isFullPlatformWindow && (_styleMask & CPResizableWindowMask) && (CPWindowResizeStyle === CPWindowResizeStyleModern)) ? CGRectInset(_frame, -_CPWindowViewResizeSlop, -_CPWindowViewResizeSlop) : _frame; - return _CGRectContainsPoint(mouseFrame, aPoint); + return CGRectContainsPoint(mouseFrame, aPoint); } @end @@ -3405,8 +3492,8 @@ var interpolate = function(fromValue, toValue, progress) { _window = aWindow; - _targetFrame = _CGRectMakeCopy(aTargetFrame); - _startFrame = _CGRectMakeCopy([_window frame]); + _targetFrame = CGRectMakeCopy(aTargetFrame); + _startFrame = CGRectMakeCopy([_window frame]); } return self; @@ -3428,11 +3515,11 @@ var interpolate = function(fromValue, toValue, progress) if (value == 1.0) _window._isAnimating = NO; - var newFrame = _CGRectMake( - interpolate(_CGRectGetMinX(_startFrame), _CGRectGetMinX(_targetFrame), value), - interpolate(_CGRectGetMinY(_startFrame), _CGRectGetMinY(_targetFrame), value), - interpolate(_CGRectGetWidth(_startFrame), _CGRectGetWidth(_targetFrame), value), - interpolate(_CGRectGetHeight(_startFrame), _CGRectGetHeight(_targetFrame), value)); + var newFrame = CGRectMake( + interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value), + interpolate(CGRectGetMinY(_startFrame), CGRectGetMinY(_targetFrame), value), + interpolate(CGRectGetWidth(_startFrame), CGRectGetWidth(_targetFrame), value), + interpolate(CGRectGetHeight(_startFrame), CGRectGetHeight(_targetFrame), value)); [_window setFrame:newFrame display:YES animate:NO]; } diff --git a/AppKit/CPWindow/_CPDocModalWindowView.j b/AppKit/CPWindow/_CPDocModalWindowView.j index 5a420b986..775b9542d 100644 --- a/AppKit/CPWindow/_CPDocModalWindowView.j +++ b/AppKit/CPWindow/_CPDocModalWindowView.j @@ -26,7 +26,6 @@ @implementation _CPDocModalWindowView : _CPWindowView { CPView _bodyView; - CPView _shadowView; } + (CPString)defaultThemeClass @@ -38,7 +37,7 @@ { return @{ @"body-color": [CPColor whiteColor], - @"height-shadow": 8, + @"shadow-height": 8, }; } @@ -50,7 +49,7 @@ */ var contentRect = [super contentRectForFrameRect:aFrameRect]; - return _CGRectInset(contentRect, 1.0, 1.0); + return CGRectInset(contentRect, 1.0, 1.0); } - (id)initWithFrame:(CGRect)aFrame styleMask:(unsigned)aStyleMask @@ -61,17 +60,13 @@ { var bounds = [self bounds]; - _bodyView = [[CPView alloc] initWithFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(bounds), _CGRectGetHeight(bounds))]; + _bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), CGRectGetHeight(bounds))]; [_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; [_bodyView setHitTests:NO]; [self addSubview:_bodyView]; - - _shadowView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, _CGRectGetWidth(bounds), [self valueForThemeAttribute:@"height-shadow"])]; - [_shadowView setAutoresizingMask:CPViewWidthSizable]; - [self addSubview:_shadowView]; - } + } return self; } @@ -86,11 +81,6 @@ return [[self class] frameRectForContentRect:aContentRect]; } -- (void)_enableSheet:(BOOL)enable -{ - // do nothing, already a sheet -} - - (void)layoutSubviews { [super layoutSubviews]; @@ -98,9 +88,11 @@ var bounds = [self bounds]; [_bodyView setBackgroundColor:[self valueForThemeAttribute:@"body-color"]]; +} - [_shadowView setFrame:CGRectMake(0,0, _CGRectGetWidth(bounds), [self valueForThemeAttribute:@"height-shadow"])]; - [_shadowView setBackgroundColor:[self valueForThemeAttribute:@"attached-sheet-shadow-color"]]; +- (int)bodyOffset +{ + return [_bodyView frame].origin.y; } @end diff --git a/AppKit/CPWindow/_CPHUDWindowView.j b/AppKit/CPWindow/_CPHUDWindowView.j index 865b6c4d0..829f78eee 100644 --- a/AppKit/CPWindow/_CPHUDWindowView.j +++ b/AppKit/CPWindow/_CPHUDWindowView.j @@ -127,7 +127,7 @@ - (CGSize)toolbarOffset { - return _CGSizeMake(0.0, [[self class] titleBarHeight]); + return CGSizeMake(0.0, [[self class] titleBarHeight]); } - (void)tile @@ -136,22 +136,22 @@ var theWindow = [self window], bounds = [self bounds], - width = _CGRectGetWidth(bounds); + width = CGRectGetWidth(bounds); - [_titleField setFrame:_CGRectMake(20.0, 0, width - 40.0, [self toolbarOffset].height)]; + [_titleField setFrame:CGRectMake(20.0, 0, width - 40.0, [self toolbarOffset].height)]; var maxY = [self toolbarMaxY]; if ([_titleField isHidden]) maxY -= ([self toolbarOffset]).height; - var contentRect = _CGRectMake(0.0, maxY, width, _CGRectGetHeight(bounds) - maxY); + var contentRect = CGRectMake(0.0, maxY, width, CGRectGetHeight(bounds) - maxY); [[theWindow contentView] setFrame:contentRect]; } -- (void)_enableSheet:(BOOL)enable +- (void)_enableSheet:(BOOL)enable inWindow:(CPWindow)parentWindow { - [super _enableSheet:enable]; + // No need to call super, it just deals with the shadow view, which we don't want [_closeButton setHidden:enable]; [_titleField setHidden:enable]; @@ -164,15 +164,17 @@ if (enable) dy = -dy; - var newHeight = _CGRectGetMaxY(frame) + dy, - newWidth = _CGRectGetMaxX(frame); + var newHeight = CGRectGetMaxY(frame) + dy, + newWidth = CGRectGetMaxX(frame); frame.size.height += dy; - [self setFrameSize:_CGSizeMake(newWidth, newHeight)]; + [self setFrameSize:CGSizeMake(newWidth, newHeight)]; [self tile]; [theWindow setFrame:frame display:NO animate:NO]; [theWindow setMovableByWindowBackground:!enable]; + + [self setNeedsLayout]; } - (void)layoutSubviews diff --git a/AppKit/CPWindow/_CPPopoverWindowView.j b/AppKit/CPWindow/_CPPopoverWindowView.j index 020896213..958bb7b34 100644 --- a/AppKit/CPWindow/_CPPopoverWindowView.j +++ b/AppKit/CPWindow/_CPPopoverWindowView.j @@ -28,10 +28,10 @@ @global CPPopoverAppearanceMinimal -var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), +var _CPPopoverWindowViewDefaultCursorSize = CGSizeMake(16, 10), _CPPopoverWindowViewRadius = 5.0, _CPPopoverWindowViewStrokeWidth = 1.0, - _CPPopoverWindowViewShadowSize = _CGSizeMake(0, 6), + _CPPopoverWindowViewShadowSize = CGSizeMake(0, 6), _CPPopoverWindowViewShadowBlur = 15.0; /*! @@ -71,7 +71,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), */ - (CGRect)contentRectForFrameRect:(CGRect)aFrameRect { - var contentRect = _CGRectMakeCopy(aFrameRect), + var contentRect = CGRectMakeCopy(aFrameRect), modifierX = 16, modifierY = 19; @@ -79,7 +79,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), // // @comment: If we use this, each time we open the popover, the content // view is reduced a little over and over - // return _CGRectInset(contentRect, modifierX, modifierY); + // return CGRectInset(contentRect, modifierX, modifierY); contentRect.origin.x += modifierX; contentRect.origin.y += modifierY; @@ -96,7 +96,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), */ + (CGRect)frameRectForContentRect:(CGRect)aContentRect { - var frameRect = _CGRectMakeCopy(aContentRect), + var frameRect = CGRectMakeCopy(aContentRect), modifierX = 16, modifierY = 19; @@ -104,7 +104,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), // @comment: If we use this, each time we open the popover, the content // // view is reduced a little over and over - // return _CGRectOffset(frameRect, modifierX, modifierY); + // return CGRectOffset(frameRect, modifierX, modifierY); frameRect.origin.x -= modifierX; frameRect.origin.y -= modifierY; @@ -124,7 +124,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), _arrowOffsetX = 0.0; _arrowOffsetY = 0.0; _appearance = CPPopoverAppearanceMinimal; - _cursorSize = _CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize); + _cursorSize = CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize); } return self; @@ -135,7 +135,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), */ - (void)hideCursor { - _cursorSize = _CGSizeMakeZero(); + _cursorSize = CGSizeMakeZero(); [self setNeedsDisplay:YES]; } @@ -144,7 +144,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), */ - (void)showCursor { - _cursorSize = _CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize); + _cursorSize = CGSizeMakeCopy(_CPPopoverWindowViewDefaultCursorSize); [self setNeedsDisplay:YES]; } @@ -190,19 +190,19 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), CGContextBeginPath(context); CGContextSetShadowWithColor(context, shadowSize, shadowBlur, shadowColor); - CGContextDrawLinearGradient(context, gradient, _CGPointMake(_CGRectGetMidX(frame), 0.0), _CGPointMake(_CGRectGetMidX(frame), frame.size.height), 0); + CGContextDrawLinearGradient(context, gradient, CGPointMake(CGRectGetMidX(frame), 0.0), CGPointMake(CGRectGetMidX(frame), frame.size.height), 0); - var xMin = _CGRectGetMinX(frame), - xMax = _CGRectGetMaxX(frame), - yMin = _CGRectGetMinY(frame), - yMax = _CGRectGetMaxY(frame), + var xMin = CGRectGetMinX(frame), + xMax = CGRectGetMaxX(frame), + yMin = CGRectGetMinY(frame), + yMax = CGRectGetMaxY(frame), arrowMinX = CGAlignCoordinate(xMin + radius + strokeWidth), arrowMaxX = CGAlignCoordinate(xMax - radius - strokeWidth), arrowMinY = CGAlignCoordinate(yMin + radius + strokeWidth), arrowMaxY = CGAlignCoordinate(yMax - radius + strokeWidth), - arrowAnchor = _CGPointMakeZero(), - arrowStart = _CGPointMakeZero(), - pt = _CGPointMakeZero(); + arrowAnchor = CGPointMakeZero(), + arrowStart = CGPointMakeZero(), + pt = CGPointMakeZero(); // draw! var path = CGPathCreateMutable(); @@ -237,7 +237,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), pt.y = arrowMaxY - arrowWidth; pt.x = arrowAnchor.x; - arrowStart = _CGPointMakeCopy(pt); + arrowStart = CGPointMakeCopy(pt); CGPathAddLineToPoint(path, NULL, pt.x, pt.y); // top edge -> point @@ -279,7 +279,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), pt.y = arrowMaxY; pt.x = arrowAnchor.x; - arrowStart = _CGPointMakeCopy(pt); + arrowStart = CGPointMakeCopy(pt); CGPathAddLineToPoint(path, NULL, pt.x, pt.y); // bottom edge -> point @@ -328,7 +328,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), pt.x = arrowMaxX - arrowWidth; pt.y = arrowAnchor.y; - arrowStart = _CGPointMakeCopy(pt); + arrowStart = CGPointMakeCopy(pt); CGPathAddLineToPoint(path, NULL, pt.x, pt.y); // left edge -> point @@ -370,7 +370,7 @@ var _CPPopoverWindowViewDefaultCursorSize = _CGSizeMake(16, 10), pt.x = arrowMaxX; pt.y = arrowAnchor.y; - arrowStart = _CGPointMakeCopy(pt); + arrowStart = CGPointMakeCopy(pt); CGPathAddLineToPoint(path, NULL, pt.x, pt.y); // right edge -> point diff --git a/AppKit/CPWindow/_CPShadowWindowView.j b/AppKit/CPWindow/_CPShadowWindowView.j index c78811141..d7095a750 100644 --- a/AppKit/CPWindow/_CPShadowWindowView.j +++ b/AppKit/CPWindow/_CPShadowWindowView.j @@ -54,7 +54,7 @@ shadowDistance = [_windowView valueForThemeAttribute:@"shadow-distance"], shadowInset = [_windowView valueForThemeAttribute:@"shadow-inset"], size = [_windowView frameSize], - shadowSize = _CGSizeMake(size.width, size.height); + shadowSize = CGSizeMake(size.width, size.height); // if the shadow would be taller/wider than the window height, // make it the same as the window height. this allows views to diff --git a/AppKit/CPWindow/_CPStandardWindowView.j b/AppKit/CPWindow/_CPStandardWindowView.j index be25f9f0b..b2c68ef6a 100644 --- a/AppKit/CPWindow/_CPStandardWindowView.j +++ b/AppKit/CPWindow/_CPStandardWindowView.j @@ -51,10 +51,10 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; if (self) { _parentView = parentView; - _gradientView = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + _gradientView = [[CPView alloc] initWithFrame:CGRectMakeZero()]; [self addSubview:_gradientView]; - _solidView = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + _solidView = [[CPView alloc] initWithFrame:CGRectMakeZero()]; [self addSubview:_solidView]; } @@ -68,10 +68,10 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; var gradientHeight = [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView], bounds = [self bounds]; - [_gradientView setFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(bounds), gradientHeight)]; + [_gradientView setFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), gradientHeight)]; [_gradientView setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"bezel-head-color" inState:[_parentView themeState] forClass:_CPStandardWindowView]]; - [_solidView setFrame:_CGRectMake(0.0, gradientHeight, _CGRectGetWidth(bounds), _CGRectGetHeight(bounds) - gradientHeight)]; + [_solidView setFrame:CGRectMake(0.0, gradientHeight, CGRectGetWidth(bounds), CGRectGetHeight(bounds) - gradientHeight)]; [_solidView setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"solid-color" forClass:_CPStandardWindowView]]; } @@ -79,8 +79,8 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; { var bounds = [self bounds]; - [_gradientView setFrameSize:_CGSizeMake(_CGRectGetWidth(bounds), [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])]; - [_solidView setFrameSize:_CGSizeMake(_CGRectGetWidth(bounds), _CGRectGetHeight(bounds) - [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])]; + [_gradientView setFrameSize:CGSizeMake(CGRectGetWidth(bounds), [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])]; + [_solidView setFrameSize:CGSizeMake(CGRectGetWidth(bounds), CGRectGetHeight(bounds) - [[CPTheme defaultTheme] valueForAttributeWithName:@"gradient-height" forClass:_CPStandardWindowView])]; } @end @@ -130,7 +130,6 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; The top coordinate has already been adjusted by _CPTitleableWindowView. */ var contentRect = [super contentRectForFrameRect:aFrameRect]; - contentRect.origin.x += 1; contentRect.size.width -= 2; contentRect.size.height -= 1; @@ -151,34 +150,34 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; var theClass = [self class], bounds = [self bounds]; - _headView = [[_CPTexturedWindowHeadView alloc] initWithFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(bounds), [self valueForThemeAttribute:@"title-bar-height"]) windowView:self]; + _headView = [[_CPTexturedWindowHeadView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), [self valueForThemeAttribute:@"title-bar-height"]) windowView:self]; [_headView setAutoresizingMask:CPViewWidthSizable];; [_headView setHitTests:NO]; [self addSubview:_headView positioned:CPWindowBelow relativeTo:_titleField]; - _dividerView = [[CPView alloc] initWithFrame:_CGRectMake(0.0, _CGRectGetMaxY([_headView frame]), _CGRectGetWidth(bounds), _CPStandardWindowViewDividerViewHeight)]; + _dividerView = [[CPView alloc] initWithFrame:CGRectMake(0.0, CGRectGetMaxY([_headView frame]), CGRectGetWidth(bounds), _CPStandardWindowViewDividerViewHeight)]; [_dividerView setAutoresizingMask:CPViewWidthSizable]; [_dividerView setHitTests:NO]; [self addSubview:_dividerView]; - var y = _CGRectGetMaxY([_dividerView frame]); + var y = CGRectGetMinY([_dividerView frame]); - _bodyView = [[CPView alloc] initWithFrame:_CGRectMake(0.0, y, _CGRectGetWidth(bounds), _CGRectGetHeight(bounds) - y)]; + _bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, y, CGRectGetWidth(bounds), CGRectGetHeight(bounds) - y)]; [_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; [_bodyView setHitTests:NO]; [self addSubview:_bodyView]; - [self setResizeIndicatorOffset:_CGSizeMake(2.0, 2.0)]; + [self setResizeIndicatorOffset:CGSizeMake(2.0, 2.0)]; if (_styleMask & CPClosableWindowMask) { - _closeButton = [[CPButton alloc] initWithFrame:_CGRectMake(8.0, 8.0, 16.0, 16.0)]; + _closeButton = [[CPButton alloc] initWithFrame:CGRectMake(8.0, 8.0, 16.0, 16.0)]; [_closeButton setButtonType:CPMomentaryChangeButton]; [_closeButton setBordered:NO]; @@ -189,7 +188,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; if (_styleMask & CPMiniaturizableWindowMask && ![CPPlatform isBrowser]) { - _minimizeButton = [[CPButton alloc] initWithFrame:_CGRectMake(27.0, 7.0, 16.0, 16.0)]; + _minimizeButton = [[CPButton alloc] initWithFrame:CGRectMake(27.0, 7.0, 16.0, 16.0)]; [_minimizeButton setButtonType:CPMomentaryChangeButton]; [_minimizeButton setBordered:NO]; @@ -213,7 +212,7 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; - (CGSize)toolbarOffset { - return _CGSizeMake(0.0, [self valueForThemeAttribute:@"title-bar-height"]); + return CGSizeMake(0.0, [self valueForThemeAttribute:@"title-bar-height"]); } - (void)tile @@ -222,22 +221,19 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; var theWindow = [self window], bounds = [self bounds], - width = _CGRectGetWidth(bounds), + width = CGRectGetWidth(bounds), headHeight = [self toolbarMaxY]; - [_headView setFrameSize:_CGSizeMake(width, headHeight)]; - [_dividerView setFrame:_CGRectMake(0.0, headHeight, width, 1.0)]; + [_headView setFrameSize:CGSizeMake(width, headHeight)]; + [_dividerView setFrame:CGRectMake(0.0, headHeight, width, _CPStandardWindowViewDividerViewHeight)]; - var dividerMaxY = 0, - dividerMinY = 0; + var dividerMinY = 0, + dividerFrame = [_dividerView frame]; if (![_dividerView isHidden]) - { - dividerMinY = _CGRectGetMinY([_dividerView frame]); - dividerMaxY = _CGRectGetMaxY([_dividerView frame]); - } + dividerMinY = CGRectGetMinY(dividerFrame); - [_bodyView setFrame:_CGRectMake(0.0, dividerMaxY, width, _CGRectGetHeight(bounds) - dividerMaxY)]; + [_bodyView setFrame:CGRectMake(0.0, dividerMinY, width, CGRectGetHeight(bounds) - dividerMinY)]; var leftOffset = 8; @@ -246,11 +242,10 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; if (_minimizeButton) leftOffset += 19.0; - [_titleField setFrame:_CGRectMake(leftOffset, 0, width - leftOffset * 2.0, [self valueForThemeAttribute:@"title-bar-height"])]; + [_titleField setFrame:CGRectMake(leftOffset, 0, width - leftOffset * 2.0, [self valueForThemeAttribute:@"title-bar-height"])]; - var contentRect = _CGRectMake(0.0, dividerMaxY, width, _CGRectGetHeight([_bodyView frame])); - - [[theWindow contentView] setFrame:contentRect]; + var contentFrame = [_bodyView frame]; + [[theWindow contentView] setFrame:CGRectInset(contentFrame, 1.0, 1.0)]; } /* @@ -307,15 +302,15 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; - (BOOL)couldBeMoveEvent:(CPEvent)anEvent { if (![_headView isHidden]) - if (_CGRectContainsPoint([_headView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil])) + if (CGRectContainsPoint([_headView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil])) return YES; return [super couldBeMoveEvent:anEvent]; } -- (void)_enableSheet:(BOOL)enable +- (void)_enableSheet:(BOOL)enable inWindow:(CPWindow)parentWindow { - [super _enableSheet:enable]; + [super _enableSheet:enable inWindow:parentWindow]; [_headView setHidden:enable]; [_dividerView setHidden:enable]; @@ -324,26 +319,33 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; [_titleField setHidden:enable]; if (enable) + { [_bodyView setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"body-color" forClass:_CPDocModalWindowView]]; + + // Move the shadow view down so it is inside the content border + var shadowFrame = [_sheetShadowView frame]; + [_sheetShadowView setFrameOrigin:CGPointMake(shadowFrame.origin.x, shadowFrame.origin.y + 1)]; + } else [_bodyView setBackgroundColor:[self valueForThemeAttribute:@"body-color"]]; // resize the window var theWindow = [self window], frame = [theWindow frame], + dividerHeight = [_dividerView frame].size.height, dy; if (enable) - dy = -(_CGRectGetHeight([_headView frame]) + _CGRectGetHeight([_dividerView frame])); + dy = -[_headView frame].size.height; else - dy = [self toolbarMaxY] + 1.0; + dy = [self toolbarMaxY] + dividerHeight; - var newHeight = _CGRectGetMaxY(frame) + dy, - newWidth = _CGRectGetMaxX(frame); + var newHeight = CGRectGetHeight(frame) + dy, + newWidth = CGRectGetWidth(frame); frame.size.height += dy; - [self setFrameSize:_CGSizeMake(newWidth, newHeight)]; + [self setFrameSize:CGSizeMake(newWidth, newHeight)]; [self tile]; [theWindow setFrame:frame display:NO animate:NO]; @@ -380,4 +382,9 @@ var _CPStandardWindowViewDividerViewHeight = 1.0; return size; } +- (int)bodyOffset +{ + return [_bodyView frame].origin.y; +} + @end diff --git a/AppKit/CPWindow/_CPTitleableWindowView.j b/AppKit/CPWindow/_CPTitleableWindowView.j index 34e597eab..4a5dcae4b 100644 --- a/AppKit/CPWindow/_CPTitleableWindowView.j +++ b/AppKit/CPWindow/_CPTitleableWindowView.j @@ -95,7 +95,7 @@ // The vertical alignment of the title is set by the theme, so just give it all available space. By default // the title will vertically centre within. - [_titleField setFrame:_CGRectMake(20.0, 0, width - 40.0, [[self class] titleBarHeight])]; + [_titleField setFrame:CGRectMake(20.0, 0, width - 40.0, [[self class] titleBarHeight])]; } - (void)layoutSubviews @@ -121,4 +121,9 @@ return size; } +- (int)bodyOffset +{ + return [self contentRectForFrameRect:[self frame]].origin.y; +} + @end diff --git a/AppKit/CPWindow/_CPWindowView.j b/AppKit/CPWindow/_CPWindowView.j index 9b49f8624..8cd74b0e3 100644 --- a/AppKit/CPWindow/_CPWindowView.j +++ b/AppKit/CPWindow/_CPWindowView.j @@ -57,7 +57,7 @@ _CPWindowViewResizeSlop = 3; CGSize _toolbarOffset; // BOOL _isAnimatingToolbar; - CGRect _resizeFrame; + CGRect _cachedFrame; int _resizeRegion; CGPoint _mouseDraggedPoint; @@ -68,12 +68,12 @@ _CPWindowViewResizeSlop = 3; + (CGRect)contentRectForFrameRect:(CGRect)aFrameRect { - return _CGRectMakeCopy(aFrameRect); + return CGRectMakeCopy(aFrameRect); } + (CGRect)frameRectForContentRect:(CGRect)aContentRect { - return _CGRectMakeCopy(aContentRect); + return CGRectMakeCopy(aContentRect); } + (CPString)defaultThemeClass @@ -91,6 +91,7 @@ _CPWindowViewResizeSlop = 3; @"size-indicator": CGSizeMakeZero(), @"resize-indicator": [CPNull null], @"attached-sheet-shadow-color": [CPColor blackColor], + @"shadow-height": 8, @"close-image-origin": [CPNull null], @"close-image-size": [CPNull null], @"close-image": [CPNull null], @@ -99,7 +100,7 @@ _CPWindowViewResizeSlop = 3; @"title-text-color": [CPColor blackColor], @"title-font": [CPFont systemFontOfSize:CPFontCurrentSystemSize], @"title-text-shadow-color": [CPNull null], - @"title-text-shadow-offset": _CGSizeMakeZero(), + @"title-text-shadow-offset": CGSizeMakeZero(), @"title-alignment": CPCenterTextAlignment, @"title-line-break-mode": CPLineBreakByTruncatingTail, @"title-vertical-alignment": CPTopVerticalTextAlignment, @@ -113,7 +114,7 @@ _CPWindowViewResizeSlop = 3; if ([theToolbar isVisible]) { - var toolbarHeight = _CGRectGetHeight([[theToolbar _toolbarView] frame]); + var toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]); contentRect.origin.y += toolbarHeight; contentRect.size.height -= toolbarHeight; @@ -129,7 +130,7 @@ _CPWindowViewResizeSlop = 3; if ([theToolbar isVisible]) { - var toolbarHeight = _CGRectGetHeight([[theToolbar _toolbarView] frame]); + var toolbarHeight = CGRectGetHeight([[theToolbar _toolbarView] frame]); frameRect.origin.y -= toolbarHeight; frameRect.size.height += toolbarHeight; @@ -145,8 +146,8 @@ _CPWindowViewResizeSlop = 3; if (self) { _styleMask = aStyleMask; - _resizeIndicatorOffset = _CGSizeMakeZero(); - _toolbarOffset = _CGSizeMakeZero(); + _resizeIndicatorOffset = CGSizeMakeZero(); + _toolbarOffset = CGSizeMakeZero(); } return self; @@ -178,7 +179,7 @@ _CPWindowViewResizeSlop = 3; - (void)mouseDown:(CPEvent)anEvent { var theWindow = [self window], - couldResize = _styleMask & CPResizableWindowMask; + couldResize = _styleMask & CPResizableWindowMask && ![theWindow isFullPlatformWindow]; couldResize = couldResize && ( (CPWindowResizeStyle === CPWindowResizeStyleModern) || @@ -201,8 +202,8 @@ _CPWindowViewResizeSlop = 3; { // Extend the resize frame to the edge of the window frame var resizeFrame = [_resizeIndicator frame]; - resizeFrame.size.width = _CGRectGetWidth(windowFrame) - _CGRectGetMinX(resizeFrame); - resizeFrame.size.height = _CGRectGetHeight(windowFrame) - _CGRectGetMinY(resizeFrame); + resizeFrame.size.width = CGRectGetWidth(windowFrame) - CGRectGetMinX(resizeFrame); + resizeFrame.size.height = CGRectGetHeight(windowFrame) - CGRectGetMinY(resizeFrame); var localPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil]; shouldResize = CGRectContainsPoint(resizeFrame, localPoint); @@ -245,6 +246,8 @@ _CPWindowViewResizeSlop = 3; rects are the same size. So to save calculations, we can just create 3 rects and move them around to do hit testing. Start with the corners and then do left/right and top/bottom. + + NOTE: If the window is a sheet, the top is never eligible for resizing. */ var wind = [self window], frame = [wind frame], @@ -252,87 +255,88 @@ _CPWindowViewResizeSlop = 3; minSize = [wind minSize], maxSize = [wind maxSize], isFixedWidth = minSize.width === maxSize.width, - isFixedHeight = minSize.height === maxSize.height; + isFixedHeight = minSize.height === maxSize.height, + isSheet = wind._isSheet; if (isFixedWidth) { - rect = _CGRectMake(frame.origin.x - _CPWindowViewResizeSlop, + rect = CGRectMake(frame.origin.x - _CPWindowViewResizeSlop, frame.origin.y - _CPWindowViewResizeSlop, frame.size.width + (_CPWindowViewResizeSlop * 2), _CPWindowViewResizeSlop * 2); - if (_CGRectContainsPoint(rect, aPoint)) - return _CPWindowViewResizeRegionTop; + if (CGRectContainsPoint(rect, aPoint)) + return isSheet ? _CPWindowViewResizeRegionNone : _CPWindowViewResizeRegionTop; - rect.origin.y = _CGRectGetMaxY(frame) - _CPWindowViewResizeSlop; + rect.origin.y = CGRectGetMaxY(frame) - _CPWindowViewResizeSlop; - if (_CGRectContainsPoint(rect, aPoint)) + if (CGRectContainsPoint(rect, aPoint)) return _CPWindowViewResizeRegionBottom; } else if (isFixedHeight) { - rect = _CGRectMake(frame.origin.x - _CPWindowViewResizeSlop, + rect = CGRectMake(frame.origin.x - _CPWindowViewResizeSlop, frame.origin.y - _CPWindowViewResizeSlop, _CPWindowViewResizeSlop * 2, frame.size.height + (_CPWindowViewResizeSlop * 2)); - if (_CGRectContainsPoint(rect, aPoint)) + if (CGRectContainsPoint(rect, aPoint)) return _CPWindowViewResizeRegionLeft; - rect.origin.x = _CGRectGetMaxX(frame) - _CPWindowViewResizeSlop; + rect.origin.x = CGRectGetMaxX(frame) - _CPWindowViewResizeSlop; - if (_CGRectContainsPoint(rect, aPoint)) + if (CGRectContainsPoint(rect, aPoint)) return _CPWindowViewResizeRegionRight; } else { - rect = _CGRectMake(frame.origin.x - _CPWindowViewResizeSlop, + rect = CGRectMake(frame.origin.x - _CPWindowViewResizeSlop, frame.origin.y - _CPWindowViewResizeSlop, _CPWindowViewCornerResizeRectWidth + _CPWindowViewResizeSlop, _CPWindowViewCornerResizeRectWidth + _CPWindowViewResizeSlop); - if (_CGRectContainsPoint(rect, aPoint)) - return _CPWindowViewResizeRegionTopLeft; + if (CGRectContainsPoint(rect, aPoint)) + return isSheet ? _CPWindowViewResizeRegionNone : _CPWindowViewResizeRegionTopLeft; - rect.origin.x = _CGRectGetMaxX(frame) - _CPWindowViewCornerResizeRectWidth; + rect.origin.x = CGRectGetMaxX(frame) - _CPWindowViewCornerResizeRectWidth; - if (_CGRectContainsPoint(rect, aPoint)) - return _CPWindowViewResizeRegionTopRight; + if (CGRectContainsPoint(rect, aPoint)) + return isSheet ? _CPWindowViewResizeRegionNone : _CPWindowViewResizeRegionTopRight; - rect.origin.y = _CGRectGetMaxY(frame) - _CPWindowViewCornerResizeRectWidth; + rect.origin.y = CGRectGetMaxY(frame) - _CPWindowViewCornerResizeRectWidth; - if (_CGRectContainsPoint(rect, aPoint)) + if (CGRectContainsPoint(rect, aPoint)) return _CPWindowViewResizeRegionBottomRight; rect.origin.x = frame.origin.x - _CPWindowViewResizeSlop; - if (_CGRectContainsPoint(rect, aPoint)) + if (CGRectContainsPoint(rect, aPoint)) return _CPWindowViewResizeRegionBottomLeft; - rect = _CGRectMake(rect.origin.x, + rect = CGRectMake(rect.origin.x, frame.origin.y + _CPWindowViewCornerResizeRectWidth, _CPWindowViewResizeSlop * 2, - _CGRectGetHeight(frame) - (_CPWindowViewCornerResizeRectWidth * 2)); + CGRectGetHeight(frame) - (_CPWindowViewCornerResizeRectWidth * 2)); - if (_CGRectContainsPoint(rect, aPoint)) + if (CGRectContainsPoint(rect, aPoint)) return _CPWindowViewResizeRegionLeft; - rect.origin.x = _CGRectGetMaxX(frame) - _CPWindowViewResizeSlop; + rect.origin.x = CGRectGetMaxX(frame) - _CPWindowViewResizeSlop; - if (_CGRectContainsPoint(rect, aPoint)) + if (CGRectContainsPoint(rect, aPoint)) return _CPWindowViewResizeRegionRight; - rect = _CGRectMake(frame.origin.x + _CPWindowViewCornerResizeRectWidth, + rect = CGRectMake(frame.origin.x + _CPWindowViewCornerResizeRectWidth, frame.origin.y - _CPWindowViewResizeSlop, - _CGRectGetWidth(frame) - (_CPWindowViewCornerResizeRectWidth * 2), + CGRectGetWidth(frame) - (_CPWindowViewCornerResizeRectWidth * 2), _CPWindowViewResizeSlop * 2); - if (_CGRectContainsPoint(rect, aPoint)) - return _CPWindowViewResizeRegionTop; + if (CGRectContainsPoint(rect, aPoint)) + return isSheet ? _CPWindowViewResizeRegionNone : _CPWindowViewResizeRegionTop; - rect.origin.y = _CGRectGetMaxY(frame) - _CPWindowViewResizeSlop; + rect.origin.y = CGRectGetMaxY(frame) - _CPWindowViewResizeSlop; - if (_CGRectContainsPoint(rect, aPoint)) + if (CGRectContainsPoint(rect, aPoint)) return _CPWindowViewResizeRegionBottom; } @@ -367,9 +371,9 @@ _CPWindowViewResizeSlop = 3; switch (resizeRegion) { case _CPWindowViewResizeRegionTopLeft: - if (minSize && _CGSizeEqualToSize(frameSize, minSize)) + if (minSize && CGSizeEqualToSize(frameSize, minSize)) [[CPCursor resizeNorthwestCursor] set]; - else if (maxSize && _CGSizeEqualToSize(frameSize, maxSize)) + else if (maxSize && CGSizeEqualToSize(frameSize, maxSize)) [[CPCursor resizeSoutheastCursor] set]; else [[CPCursor resizeNorthwestSoutheastCursor] set]; @@ -380,16 +384,16 @@ _CPWindowViewResizeSlop = 3; [[CPCursor resizeUpCursor] set]; else if (maxSize && (frameSize.height === maxSize.height)) [[CPCursor resizeDownCursor] set]; - else if ([CPMenu menuBarVisible] && (_CGRectGetMinY([theWindow frame]) <= [CPMenu menuBarHeight])) + else if ([CPMenu menuBarVisible] && (CGRectGetMinY([theWindow frame]) <= [CPMenu menuBarHeight])) [[CPCursor resizeDownCursor] set]; else [[CPCursor resizeNorthSouthCursor] set]; break; case _CPWindowViewResizeRegionTopRight: - if (minSize && _CGSizeEqualToSize(frameSize, minSize)) + if (minSize && CGSizeEqualToSize(frameSize, minSize)) [[CPCursor resizeNortheastCursor] set]; - else if (maxSize && _CGSizeEqualToSize(frameSize, maxSize)) + else if (maxSize && CGSizeEqualToSize(frameSize, maxSize)) [[CPCursor resizeSouthwestCursor] set]; else [[CPCursor resizeNortheastSouthwestCursor] set]; @@ -405,9 +409,9 @@ _CPWindowViewResizeSlop = 3; break; case _CPWindowViewResizeRegionBottomRight: - if (minSize && _CGSizeEqualToSize(frameSize, minSize)) + if (minSize && CGSizeEqualToSize(frameSize, minSize)) [[CPCursor resizeSoutheastCursor] set]; - else if (maxSize && _CGSizeEqualToSize(frameSize, maxSize)) + else if (maxSize && CGSizeEqualToSize(frameSize, maxSize)) [[CPCursor resizeNorthwestCursor] set]; else [[CPCursor resizeNorthwestSoutheastCursor] set]; @@ -423,9 +427,9 @@ _CPWindowViewResizeSlop = 3; break; case _CPWindowViewResizeRegionBottomLeft: - if (minSize && _CGSizeEqualToSize(frameSize, minSize)) + if (minSize && CGSizeEqualToSize(frameSize, minSize)) [[CPCursor resizeSouthwestCursor] set]; - else if (maxSize && _CGSizeEqualToSize(frameSize, maxSize)) + else if (maxSize && CGSizeEqualToSize(frameSize, maxSize)) [[CPCursor resizeNortheastCursor] set]; else [[CPCursor resizeNortheastSouthwestCursor] set]; @@ -450,7 +454,10 @@ _CPWindowViewResizeSlop = 3; var type = [anEvent type]; if (type === CPLeftMouseUp) + { + _cachedScreenFrame = nil; return; + } var location = [anEvent locationInWindow], theWindow = [self window], @@ -459,28 +466,31 @@ _CPWindowViewResizeSlop = 3; if (type === CPLeftMouseDown) { - _mouseDraggedPoint = _CGPointMakeCopy(globalLocation); - _resizeFrame = _CGRectMakeCopy(frame); + _mouseDraggedPoint = CGPointMake(globalLocation.x, globalLocation.y); + _cachedFrame = CGRectMakeCopy(frame); + _cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame]; } - else if (type === CPLeftMouseDragged) { var deltaX = globalLocation.x - _mouseDraggedPoint.x, deltaY = globalLocation.y - _mouseDraggedPoint.y, - startX = _CGRectGetMinX(_resizeFrame), - startY = _CGRectGetMinY(_resizeFrame), - startWidth = _CGRectGetWidth(_resizeFrame), - startHeight = _CGRectGetHeight(_resizeFrame), + startX = CGRectGetMinX(_cachedFrame), + startY = CGRectGetMinY(_cachedFrame), + startWidth = CGRectGetWidth(_cachedFrame), + startHeight = CGRectGetHeight(_cachedFrame), newX, newY, newWidth, newHeight, - platformFrame = [[theWindow platformWindow] usableContentFrame], resizeMinSize = [self _minimumResizeSize], minSize = [theWindow minSize], maxSize = [theWindow maxSize]; - minSize = _CGSizeMake(MAX(minSize.width, resizeMinSize.width), MAX(minSize.height, resizeMinSize.height)); + minSize = CGSizeMake(MAX(minSize.width, resizeMinSize.width), MAX(minSize.height, resizeMinSize.height)); + + // If it's a sheet, horizontal resizing is symmetrical, so the movement is effectively doubled + if (theWindow._isSheet) + deltaX *= 2; // Calculate x and width first switch (_resizeRegion) @@ -498,8 +508,24 @@ _CPWindowViewResizeSlop = 3; else if (deltaX < 0) deltaX = -MIN(maxSize.width - startWidth, ABS(deltaX)); - // When resizing from the left, we change the origin and the width + if (theWindow._isSheet) + deltaX = FLOOR(deltaX / 2); + newX = startX + deltaX; + + // Pin the left edge to the usable screen left edge + var pinnedX = MAX(newX, CGRectGetMinX(_cachedScreenFrame)); + + if (pinnedX !== newX) + { + deltaX += pinnedX - newX; + newX = pinnedX; + } + + // When resizing from the left, we change the origin and the width + if (theWindow._isSheet) + deltaX *= 2; + newWidth = startWidth - deltaX; break; @@ -516,9 +542,26 @@ _CPWindowViewResizeSlop = 3; else if (deltaX < 0) deltaX = -MIN(startWidth - minSize.width, ABS(deltaX)); - // When resizing from the right, change only the width - newX = startX; - newWidth = startWidth + deltaX; + if (theWindow._isSheet) + deltaX = FLOOR(deltaX / 2); + + // Pin the right edge to the usable screen right edge + var newMaxX = startX + startWidth + deltaX, + pinnedX = MIN(newMaxX, CGRectGetMaxX(_cachedScreenFrame)); + + if (pinnedX !== newMaxX) + deltaX += pinnedX - newMaxX; + + if (theWindow._isSheet) + { + newWidth = startWidth + (deltaX * 2); + newX = startX - FLOOR((newWidth - startWidth) / 2); + } + else + { + newWidth = startWidth + deltaX; + newX = startX; + } break; default: @@ -542,8 +585,18 @@ _CPWindowViewResizeSlop = 3; else if (deltaY < 0) deltaY = -MIN(maxSize.height - startHeight, ABS(deltaY)); - // When resizing from the top, change the origin and the height newY = startY + deltaY; + + // Pin the top edge to the usable screen top edge + var pinnedY = MAX(newY, CGRectGetMinY(_cachedScreenFrame)); + + if (pinnedY !== newY) + { + deltaY += pinnedY - newY; + newY = pinnedY; + } + + // When resizing from the top, change the origin and the height newHeight = startHeight - deltaY; break; @@ -560,8 +613,16 @@ _CPWindowViewResizeSlop = 3; else if (deltaY < 0) deltaY = -MIN(startHeight - minSize.height, ABS(deltaY)); - // When resizing from the bottom, change only the height newY = startY; + + // Pin the bottom edge to the usable screen bottom edge + var newMaxY = startY + startHeight + deltaY, + pinnedY = MIN(newMaxY, CGRectGetMaxY(_cachedScreenFrame)); + + if (pinnedY !== newMaxY) + deltaY += pinnedY - newMaxY; + + // When resizing from the bottom, change only the height newHeight = startHeight + deltaY; break; @@ -570,72 +631,40 @@ _CPWindowViewResizeSlop = 3; newHeight = startHeight; } - if (theWindow._isSheet && theWindow._parentView && (frame.size.width !== newWidth)) - [theWindow._parentView _setAttachedSheetFrameOrigin]; - - // Constrain resize to fit within the platform window. - var newFrame = CGRectIntersection(_CGRectMake(newX, newY, newWidth, newHeight), platformFrame); - - [theWindow setFrame:newFrame]; + [theWindow _setFrame:CGRectMake(newX, newY, newWidth, newHeight) display:YES animate:NO constrainWidth:NO constrainHeight:NO]; [self setCursorForLocation:location resizing:YES]; } [CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; } -- (CGPoint)_pointWithinScreenFrame:(CGPoint)aPoint -{ - // FIXME: this is WRONG, all of this is WRONG - if (![CPPlatform isBrowser]) - return aPoint; - - var visibleFrame = _cachedScreenFrame; - - if (!visibleFrame) - visibleFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame]; - - var minPointY = 0; - - if ([CPMenu menuBarVisible]) - minPointY = [[CPApp mainMenu] menuBarHeight]; - - var restrictedPoint = _CGPointMake(0, 0); - - restrictedPoint.x = MIN(MAX(aPoint.x, -_frame.size.width + 4.0), _CGRectGetMaxX(visibleFrame) - 4.0); - restrictedPoint.y = MIN(MAX(aPoint.y, minPointY), _CGRectGetMaxY(visibleFrame) - 8.0); - - return restrictedPoint; -} - - (void)trackMoveWithEvent:(CPEvent)anEvent { - if (![[self window] isMovable]) + var theWindow = [self window]; + + if (![theWindow isMovable]) return; var type = [anEvent type]; if (type === CPLeftMouseUp) { - _cachedScreenFrame = nil; return; } else if (type === CPLeftMouseDown) { - _mouseDraggedPoint = [[self window] convertBaseToGlobal:[anEvent locationInWindow]]; - _cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame]; + _mouseDraggedPoint = [theWindow convertBaseToGlobal:[anEvent locationInWindow]]; + _cachedFrame = CGRectMakeCopy([theWindow frame]); } else if (type === CPLeftMouseDragged) { var theWindow = [self window], - frame = [theWindow frame], location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]], deltaX = location.x - _mouseDraggedPoint.x, deltaY = location.y - _mouseDraggedPoint.y, - origin = [self _pointWithinScreenFrame:_CGPointMake(frame.origin.x + deltaX, - frame.origin.y + deltaY)]; - [theWindow setFrameOrigin:origin]; + origin = CGPointMake(_cachedFrame.origin.x + deltaX, _cachedFrame.origin.y + deltaY); - _mouseDraggedPoint = [self _pointWithinScreenFrame:location]; + [theWindow setFrameOrigin:origin]; } [CPApp setTarget:self selector:@selector(trackMoveWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; @@ -646,10 +675,16 @@ _CPWindowViewResizeSlop = 3; [super setFrameSize:newSize]; // reposition sheet if the parent window resizes or moves - var theWindow = [self window]; + var theWindow = [self window], + sheet = [theWindow attachedSheet]; - if ([theWindow attachedSheet]) + if (sheet) + { [theWindow _setAttachedSheetFrameOrigin]; + [sheet._windowView _adjustShadowViewSize]; + } + else if (theWindow._isSheet) + [self _adjustShadowViewSize]; } - (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator @@ -678,7 +713,7 @@ _CPWindowViewResizeSlop = 3; - (void)setResizeIndicatorOffset:(CGSize)anOffset { - if (_CGSizeEqualToSize(_resizeIndicatorOffset, anOffset)) + if (CGSizeEqualToSize(_resizeIndicatorOffset, anOffset)) return; _resizeIndicatorOffset = anOffset; @@ -689,7 +724,7 @@ _CPWindowViewResizeSlop = 3; var size = [_resizeIndicator frame].size, boundsSize = [self frame].size; - [_resizeIndicator setFrameOrigin:_CGPointMake(boundsSize.width - size.width - anOffset.width, boundsSize.height - size.height - anOffset.height)]; + [_resizeIndicator setFrameOrigin:CGPointMake(boundsSize.width - size.width - anOffset.width, boundsSize.height - size.height - anOffset.height)]; } - (CGSize)resizeIndicatorOffset @@ -725,7 +760,7 @@ _CPWindowViewResizeSlop = 3; if (!_toolbarView || [_toolbarView isHidden]) return [self toolbarOffset].height; - return _CGRectGetMaxY([_toolbarView frame]); + return CGRectGetMaxY([_toolbarView frame]); } - (_CPToolbarView)toolbarView @@ -737,14 +772,14 @@ _CPWindowViewResizeSlop = 3; { var theWindow = [self window], bounds = [self bounds], - width = _CGRectGetWidth(bounds); + width = CGRectGetWidth(bounds); if ([[theWindow toolbar] isVisible]) { var toolbarView = [self toolbarView], toolbarOffset = [self toolbarOffset]; - [toolbarView setFrame:_CGRectMake(toolbarOffset.width, toolbarOffset.height, width, _CGRectGetHeight([toolbarView frame]))]; + [toolbarView setFrame:CGRectMake(toolbarOffset.width, toolbarOffset.height, width, CGRectGetHeight([toolbarView frame]))]; } if ([self showsResizeIndicator]) @@ -752,7 +787,7 @@ _CPWindowViewResizeSlop = 3; var size = [_resizeIndicator frame].size, boundsSize = [self bounds].size; - [_resizeIndicator setFrameOrigin:_CGPointMake(boundsSize.width - size.width - _resizeIndicatorOffset.width, boundsSize.height - size.height - _resizeIndicatorOffset.height)]; + [_resizeIndicator setFrameOrigin:CGPointMake(boundsSize.width - size.width - _resizeIndicatorOffset.width, boundsSize.height - size.height - _resizeIndicatorOffset.height)]; } } @@ -829,22 +864,36 @@ _CPWindowViewResizeSlop = 3; [self addSubview:_resizeIndicator]; } -- (void)_enableSheet:(BOOL)enable +- (void)_enableSheet:(BOOL)enable inWindow:(CPWindow)parentWindow { if (enable) { - _sheetShadowView = [[CPView alloc] initWithFrame:_CGRectMake(0, 0, _CGRectGetWidth([self bounds]), 8)]; + // Clip the shadow view width to the parent's content view + var myWidth = [self bounds].size.width, + shadowWidth = [self _shadowViewWidthForParentWindow:parentWindow], + shadowHeight = [self currentValueForThemeAttribute:@"shadow-height"]; + + _sheetShadowView = [[CPView alloc] initWithFrame:CGRectMake(FLOOR((myWidth - shadowWidth) / 2), 0, shadowWidth, shadowHeight)]; [_sheetShadowView setAutoresizingMask:CPViewWidthSizable]; [self addSubview:_sheetShadowView]; } else { [_sheetShadowView removeFromSuperview]; + _sheetShadowView = nil; } [self setNeedsLayout]; } +- (CGRect)_shadowViewWidthForParentWindow:(CPWindow)parentWindow +{ + var myWidth = [self bounds].size.width, + parentWidth = [[parentWindow contentView] bounds].size.width; + + return MIN(myWidth, parentWidth); +} + - (void)layoutSubviews { [super layoutSubviews]; @@ -861,9 +910,28 @@ _CPWindowViewResizeSlop = 3; } } +- (void)_adjustShadowViewSize +{ + if (!_sheetShadowView) + return; + + var myWidth = [self frame].size.width, + shadowFrame = [_sheetShadowView frame], + shadowWidth = [self _shadowViewWidthForParentWindow:_window._parentView]; + + shadowFrame.origin.x = FLOOR((myWidth - shadowWidth) / 2); + shadowFrame.size.width = shadowWidth; + [_sheetShadowView setFrame:shadowFrame]; +} + - (CGSize)_minimumResizeSize { - return _CGSizeMake(0, _CPWindowViewMinContentHeight); + return CGSizeMake(0, _CPWindowViewMinContentHeight); +} + +- (int)bodyOffset +{ + return [self frame].origin.y; } @end diff --git a/AppKit/Cib/CPCib.j b/AppKit/Cib/CPCib.j index a56b77897..12c9611af 100644 --- a/AppKit/Cib/CPCib.j +++ b/AppKit/Cib/CPCib.j @@ -165,7 +165,14 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; - (BOOL)instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects { - return [self instantiateCibWithExternalNameTable:@{ CPCibOwner: anOwner, CPCibTopLevelObjects: topLevelObjects }]; + // anOwner can be nil, and we can't store nil in a dictionary. If we leave it out, + // anyone who asks for CPCibOwner will get nil back. + var nameTable = @{ CPCibTopLevelObjects: topLevelObjects }; + + if (anOwner) + [nameTable setObject:anOwner forKey:CPCibOwner]; + + return [self instantiateCibWithExternalNameTable:nameTable]; } @end diff --git a/AppKit/Cib/_CPCibCustomResource.j b/AppKit/Cib/_CPCibCustomResource.j index aefe07e67..d929cd0c7 100644 --- a/AppKit/Cib/_CPCibCustomResource.j +++ b/AppKit/Cib/_CPCibCustomResource.j @@ -31,7 +31,7 @@ @import "CPTheme.j" @class CPButtonBar - +@class CPView var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", _CPCibCustomResourceResourceNameKey = @"_CPCibCustomResourceResourceNameKey", @@ -42,6 +42,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", CPString _className; CPString _resourceName; CPDictionary _properties; + CPBundle _bundle; } + (id)imageResourceWithName:(CPString)aResourceName size:(CGSize)aSize @@ -63,6 +64,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", _className = aClassName; _resourceName = aResourceName; _properties = properties; + _bundle = nil; } return self; @@ -77,6 +79,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", _className = [aCoder decodeObjectForKey:_CPCibCustomResourceClassNameKey]; _resourceName = [aCoder decodeObjectForKey:_CPCibCustomResourceResourceNameKey]; _properties = [aCoder decodeObjectForKey:_CPCibCustomResourcePropertiesKey]; + _bundle = nil; } return self; @@ -100,39 +103,72 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", else if (_resourceName == "CPRemoveTemplate") return [[CPTheme defaultTheme] valueForAttributeWithName:@"button-image-minus" forClass:[CPButtonBar class]]; - return [self imageFromBundle:[aCoder bundle]]; + return [self imageFromCoder:aCoder]; } 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) +- (CPBundle)imageBundleWithCoder:(CPCoder)aCoder +{ + if (_bundle) + return _bundle; + + var bundleIdentifier = [_properties valueForKey:@"bundleIdentifier"]; + + if (bundleIdentifier) + _bundle = [CPBundle bundleWithIdentifier:bundleIdentifier]; + else + { + var bundleClass = [_properties valueForKey:@"bundleClass"]; + + if (bundleClass) + { + bundleClass = CPClassFromString(bundleClass); + + if (bundleClass) + _bundle = [CPBundle bundleForClass:bundleClass]; + } + } + + if (!_bundle) + { + var framework = [_properties valueForKey:@"framework"]; + + if (framework) + { + // Get AppKit and hope the framework is in the same directory + var appKit = [CPBundle bundleForClass:[CPView class]], + url = [[appKit bundleURL] URLByDeletingLastPathComponent]; + + url = [CPURL URLWithString:framework relativeToURL:url]; + _bundle = [CPBundle bundleWithURL:url]; + } + } + + if (!_bundle) + { + if (aCoder) + _bundle = [aCoder bundle]; + else + _bundle = [CPBundle mainBundle]; + } + + return _bundle; +} + +- (CPImage)imageFromCoder:(CPCoder)aCoder +{ + return [[CPImage alloc] initWithContentsOfFile:[[self imageBundleWithCoder:aCoder] pathForResource:_resourceName] size:[_properties valueForKey:@"size"]]; +} + - (CPString)filename { - return [[CPBundle mainBundle] pathForResource:_resourceName]; + return [[self imageBundleWithCoder:nil] pathForResource:_resourceName]; } - (CGSize)size @@ -162,7 +198,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", - (CPString)description { - var image = [self imageFromBundle:nil]; + var image = [self imageFromCoder:nil]; return [image description]; } diff --git a/AppKit/CoreAnimation/CALayer.j b/AppKit/CoreAnimation/CALayer.j index 1baf8e3cd..066ff8437 100644 --- a/AppKit/CoreAnimation/CALayer.j +++ b/AppKit/CoreAnimation/CALayer.j @@ -157,6 +157,7 @@ var CALayerRegisteredRunLoopUpdates = nil; _sublayers = []; +#if PLATFORM(DOM) _DOMElement = document.createElement("div"); _DOMElement.style.overflow = "visible"; @@ -167,6 +168,7 @@ var CALayerRegisteredRunLoopUpdates = nil; _DOMElement.style.zIndex = 0; _DOMElement.style.width = "0px"; _DOMElement.style.height = "0px"; +#endif } return self; @@ -184,7 +186,7 @@ var CALayerRegisteredRunLoopUpdates = nil; var oldOrigin = _bounds.origin; - _bounds = _CGRectMakeCopy(aBounds); + _bounds = CGRectMakeCopy(aBounds); if (_hasSublayerTransform) _CALayerUpdateSublayerTransformForSublayers(self); @@ -219,7 +221,7 @@ var CALayerRegisteredRunLoopUpdates = nil; if (CGPointEqualToPoint(_position, aPosition)) return; - _position = _CGPointMakeCopy(aPosition); + _position = CGPointMakeCopy(aPosition); _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask); } @@ -252,7 +254,7 @@ var CALayerRegisteredRunLoopUpdates = nil; */ - (void)setAnchorPoint:(CGPoint)anAnchorPoint { - anAnchorPoint = _CGPointMakeCopy(anAnchorPoint); + anAnchorPoint = CGPointMakeCopy(anAnchorPoint); anAnchorPoint.x = MIN(1.0, MAX(0.0, anAnchorPoint.x)); anAnchorPoint.y = MIN(1.0, MAX(0.0, anAnchorPoint.y)); @@ -265,7 +267,7 @@ var CALayerRegisteredRunLoopUpdates = nil; _CALayerUpdateSublayerTransformForSublayers(self); if (_owningView) - _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); + _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y); _CALayerRecalculateGeometry(self, CALayerGeometryAnchorPointMask); } @@ -287,7 +289,7 @@ var CALayerRegisteredRunLoopUpdates = nil; if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform)) return; - _affineTransform = _CGAffineTransformMakeCopy(anAffineTransform); + _affineTransform = CGAffineTransformMakeCopy(anAffineTransform); _CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask); } @@ -311,8 +313,8 @@ var CALayerRegisteredRunLoopUpdates = nil; var hadSublayerTransform = _hasSublayerTransform; - _sublayerTransform = _CGAffineTransformMakeCopy(anAffineTransform); - _hasSublayerTransform = !_CGAffineTransformIsIdentity(_sublayerTransform); + _sublayerTransform = CGAffineTransformMakeCopy(anAffineTransform); + _hasSublayerTransform = !CGAffineTransformIsIdentity(_sublayerTransform); if (_hasSublayerTransform) { @@ -400,8 +402,8 @@ var CALayerRegisteredRunLoopUpdates = nil; var bounds = [_superlayer bounds], frame = [_superlayer convertRect:bounds toLayer:nil]; - aFrame.origin.x -= _CGRectGetMinX(frame); - aFrame.origin.y -= _CGRectGetMinY(frame); + aFrame.origin.x -= CGRectGetMinX(frame); + aFrame.origin.y -= CGRectGetMinY(frame); } else aFrame = CGRectMakeCopy(aFrame); @@ -449,7 +451,7 @@ var CALayerRegisteredRunLoopUpdates = nil; if (USE_BUFFER && !_contents || !_context) return; - CGContextClearRect(_context, _CGRectMake(0.0, 0.0, _CGRectGetWidth(_backingStoreFrame), _CGRectGetHeight(_backingStoreFrame))); + CGContextClearRect(_context, CGRectMake(0.0, 0.0, CGRectGetWidth(_backingStoreFrame), CGRectGetHeight(_backingStoreFrame))); // Recomposite var transform; @@ -469,8 +471,8 @@ var CALayerRegisteredRunLoopUpdates = nil; // Copy so we don't affect the original. transform = CGAffineTransformCreateCopy(_transformFromLayer); - transform.tx -= _CGRectGetMinX(_backingStoreFrame); - transform.ty -= _CGRectGetMinY(_backingStoreFrame); + transform.tx -= CGRectGetMinX(_backingStoreFrame); + transform.ty -= CGRectGetMinY(_backingStoreFrame); CGContextSaveGState(_context); @@ -479,7 +481,7 @@ var CALayerRegisteredRunLoopUpdates = nil; if (USE_BUFFER) { // CGContextDrawImage(_context, _bounds, _contents.context); - _context.drawImage(_contents.buffer, _CGRectGetMinX(_bounds), _CGRectGetMinY(_bounds));//, _CGRectGetWidth(_standardBackingStoreFrame), _CGRectGetHeight(_standardBackingStoreFrame)); + _context.drawImage(_contents.buffer, CGRectGetMinX(_bounds), CGRectGetMinY(_bounds));//, CGRectGetWidth(_standardBackingStoreFrame), CGRectGetHeight(_standardBackingStoreFrame)); } else [self drawInContext:_context]; @@ -504,13 +506,13 @@ var CALayerRegisteredRunLoopUpdates = nil; _DOMContentsElement.style.position = "absolute"; _DOMContentsElement.style.visibility = "visible"; - _DOMContentsElement.width = ROUND(_CGRectGetWidth(_backingStoreFrame)); - _DOMContentsElement.height = ROUND(_CGRectGetHeight(_backingStoreFrame)); + _DOMContentsElement.width = ROUND(CGRectGetWidth(_backingStoreFrame)); + _DOMContentsElement.height = ROUND(CGRectGetHeight(_backingStoreFrame)); _DOMContentsElement.style.top = "0px"; _DOMContentsElement.style.left = "0px"; - _DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_backingStoreFrame)) + "px"; - _DOMContentsElement.style.height = ROUND(_CGRectGetHeight(_backingStoreFrame)) + "px"; + _DOMContentsElement.style.width = ROUND(CGRectGetWidth(_backingStoreFrame)) + "px"; + _DOMContentsElement.style.height = ROUND(CGRectGetHeight(_backingStoreFrame)) + "px"; _DOMElement.appendChild(_DOMContentsElement); } @@ -520,7 +522,7 @@ var CALayerRegisteredRunLoopUpdates = nil; if (_delegateRespondsToDisplayLayerSelector) return [_delegate displayInLayer:self]; - if (_CGRectGetWidth(_backingStoreFrame) == 0.0 || _CGRectGetHeight(_backingStoreFrame) == 0.0) + if (CGRectGetWidth(_backingStoreFrame) == 0.0 || CGRectGetHeight(_backingStoreFrame) == 0.0) return; if (!_contents) @@ -711,10 +713,12 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex) [_sublayers insertObject:aLayer atIndex:anIndex]; +#if PLATFORM(DOM) if (anIndex >= _sublayers.length - 1) _DOMElement.appendChild(DOM(aLayer)); else _DOMElement.insertBefore(DOM(aLayer), _sublayers[anIndex + 1]._DOMElement); +#endif aLayer._superlayer = self; @@ -913,7 +917,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex) */ - (BOOL)containsPoint:(CGPoint)aPoint { - return _CGRectContainsPoint(_bounds, aPoint); + return CGRectContainsPoint(_bounds, aPoint); } /*! @@ -928,7 +932,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex) var point = CGPointApplyAffineTransform(aPoint, _transformToLayer); - if (!_CGRectContainsPoint(_bounds, point)) + if (!CGRectContainsPoint(_bounds, point)) return nil; var layer = nil, @@ -979,7 +983,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex) _owningView = anOwningView; _bounds.size = CGSizeMakeCopy([_owningView bounds].size); - _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); + _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y); } _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask); @@ -989,7 +993,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex) - (void)_owningViewBoundsChanged { _bounds.size = CGSizeMakeCopy([_owningView bounds].size); - _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); + _position = CGPointMake(CGRectGetWidth(_bounds) * _anchorPoint.x, CGRectGetHeight(_bounds) * _anchorPoint.y); _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask); } @@ -1021,8 +1025,8 @@ function _CALayerUpdateSublayerTransformForSublayers(aLayer) { var bounds = aLayer._bounds, anchorPoint = aLayer._anchorPoint, - translateX = _CGRectGetWidth(bounds) * anchorPoint.x, - translateY = _CGRectGetHeight(bounds) * anchorPoint.y; + translateX = CGRectGetWidth(bounds) * anchorPoint.x, + translateY = CGRectGetHeight(bounds) * anchorPoint.y; aLayer._sublayerTransformForSublayers = CGAffineTransformConcat( CGAffineTransformMakeTranslation(-translateX, -translateY), @@ -1041,14 +1045,14 @@ function _CALayerUpdateDOM(aLayer, aMask) if (aMask & CALayerFrameOriginUpdateMask) { - DOMElementStyle.top = ROUND(_CGRectGetMinY(frame)) + "px"; - DOMElementStyle.left = ROUND(_CGRectGetMinX(frame)) + "px"; + DOMElementStyle.top = ROUND(CGRectGetMinY(frame)) + "px"; + DOMElementStyle.left = ROUND(CGRectGetMinX(frame)) + "px"; } if (aMask & CALayerFrameSizeUpdateMask) { - var width = MAX(0.0, ROUND(_CGRectGetWidth(frame))), - height = MAX(0.0, ROUND(_CGRectGetHeight(frame))), + var width = MAX(0.0, ROUND(CGRectGetWidth(frame))), + height = MAX(0.0, ROUND(CGRectGetHeight(frame))), DOMContentsElement = aLayer._DOMContentsElement; DOMElementStyle.width = width + "px"; @@ -1068,24 +1072,24 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange) { var bounds = aLayer._bounds, superlayer = aLayer._superlayer, - width = _CGRectGetWidth(bounds), - height = _CGRectGetHeight(bounds), + width = CGRectGetWidth(bounds), + height = CGRectGetHeight(bounds), position = aLayer._position, anchorPoint = aLayer._anchorPoint, affineTransform = aLayer._affineTransform, - backingStoreFrameSize = _CGSizeMakeCopy(aLayer._backingStoreFrame), + backingStoreFrameSize = CGSizeMakeCopy(aLayer._backingStoreFrame), hasCustomBackingStoreFrame = aLayer._hasCustomBackingStoreFrame; // Go to anchor, transform, go back to bounds. aLayer._transformFromLayer = CGAffineTransformConcat( - CGAffineTransformMakeTranslation(-width * anchorPoint.x - _CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - _CGRectGetMinY(aLayer._bounds)), + CGAffineTransformMakeTranslation(-width * anchorPoint.x - CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - CGRectGetMinY(aLayer._bounds)), CGAffineTransformConcat(affineTransform, CGAffineTransformMakeTranslation(position.x, position.y))); if (superlayer && superlayer._hasSublayerTransform) { // aLayer._transformFromLayer = CGAffineTransformConcat(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers); - _CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer); + CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer); } aLayer._transformToLayer = CGAffineTransformInvert(aLayer._transformFromLayer); @@ -1101,8 +1105,8 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange) var bounds = [superlayer bounds], frame = [superlayer convertRect:bounds toLayer:nil]; - aLayer._standardBackingStoreFrame.origin.x -= _CGRectGetMinX(frame); - aLayer._standardBackingStoreFrame.origin.y -= _CGRectGetMinY(frame); + aLayer._standardBackingStoreFrame.origin.x -= CGRectGetMinX(frame); + aLayer._standardBackingStoreFrame.origin.y -= CGRectGetMinY(frame); } // We used to use CGRectIntegral here, but what we actually want, is the largest integral @@ -1128,13 +1132,13 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange) // These values get rounded in the DOM, so don't both updating them if they're // not going to be different after rounding. - if (ROUND(_CGRectGetMinX(backingStoreFrame)) != ROUND(_CGRectGetMinX(aLayer._backingStoreFrame)) || - ROUND(_CGRectGetMinY(backingStoreFrame)) != ROUND(_CGRectGetMinY(aLayer._backingStoreFrame))) + if (ROUND(CGRectGetMinX(backingStoreFrame)) != ROUND(CGRectGetMinX(aLayer._backingStoreFrame)) || + ROUND(CGRectGetMinY(backingStoreFrame)) != ROUND(CGRectGetMinY(aLayer._backingStoreFrame))) [aLayer registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask]; // Any change in size due to a geometry change is purely due to rounding error. - if ((_CGRectGetWidth(backingStoreFrame) != ROUND(_CGRectGetWidth(aLayer._backingStoreFrame)) || - _CGRectGetHeight(backingStoreFrame) != ROUND(_CGRectGetHeight(aLayer._backingStoreFrame)))) + if ((CGRectGetWidth(backingStoreFrame) != ROUND(CGRectGetWidth(aLayer._backingStoreFrame)) || + CGRectGetHeight(backingStoreFrame) != ROUND(CGRectGetHeight(aLayer._backingStoreFrame)))) [aLayer registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask]; aLayer._backingStoreFrame = backingStoreFrame; @@ -1172,7 +1176,7 @@ function _CALayerGetTransform(fromLayer, toLayer) var transformFromLayer = layer._transformFromLayer; //transform = CGAffineTransformConcat(transform, layer._transformFromLayer); - _CGAffineTransformConcatTo(transform, transformFromLayer, transform); + CGAffineTransformConcatTo(transform, transformFromLayer, transform); layer = layer._superlayer; } @@ -1197,7 +1201,7 @@ function _CALayerGetTransform(fromLayer, toLayer) { var transformToLayer = layers[index]._transformToLayer; - _CGAffineTransformConcatTo(transform, transformToLayer, transform); + CGAffineTransformConcatTo(transform, transformToLayer, transform); } return transform; diff --git a/AppKit/CoreGraphics/CGAffineTransform.h b/AppKit/CoreGraphics/CGAffineTransform.h deleted file mode 100644 index 4eea12e67..000000000 --- a/AppKit/CoreGraphics/CGAffineTransform.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * CGAffineTransform.h - * AppKit - * - * Created by Francisco Tolmasky. - * Copyright 2008, 280 North, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "../../Foundation/_CGGeometry.h" - -#define _CGAffineTransformMake(a_, b_, c_, d_, tx_, ty_) { a:a_, b:b_, c:c_, d:d_, tx:tx_, ty:ty_ } -#define _CGAffineTransformMakeIdentity() _CGAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) -#define _CGAffineTransformMakeCopy(aTransform) _CGAffineTransformMake(aTransform.a, aTransform.b, aTransform.c, aTransform.d, aTransform.tx, aTransform.ty) - -#define _CGAffineTransformMakeScale(sx, sy) _CGAffineTransformMake(sx, 0.0, 0.0, sy, 0.0, 0.0) -#define _CGAffineTransformMakeTranslation(tx, ty) _CGAffineTransformMake(1.0, 0.0, 0.0, 1.0, tx, ty) - -#define _CGAffineTransformTranslate(aTransform, tx, ty) _CGAffineTransformMake(aTransform.a, aTransform.b, aTransform.c, aTransform.d, aTransform.tx + aTransform.a * tx + aTransform.c * ty, aTransform.ty + aTransform.b * tx + aTransform.d * ty) -#define _CGAffineTransformScale(aTransform, sx, sy) _CGAffineTransformMake(aTransform.a * sx, aTransform.b * sx, aTransform.c * sy, aTransform.d * sy, aTransform.tx, aTransform.ty) - -#define _CGAffineTransformConcat(lhs, rhs) _CGAffineTransformMake(lhs.a * rhs.a + lhs.b * rhs.c, lhs.a * rhs.b + lhs.b * rhs.d, lhs.c * rhs.a + lhs.d * rhs.c, lhs.c * rhs.b + lhs.d * rhs.d, lhs.tx * rhs.a + lhs.ty * rhs.c + rhs.tx, lhs.tx * rhs.b + lhs.ty * rhs.d + rhs.ty) - -#define _CGPointApplyAffineTransform(aPoint, aTransform) _CGPointMake(aPoint.x * aTransform.a + aPoint.y * aTransform.c + aTransform.tx, aPoint.x * aTransform.b + aPoint.y * aTransform.d + aTransform.ty) -#define _CGSizeApplyAffineTransform(aSize, aTransform) _CGSizeMake(aSize.width * aTransform.a + aSize.height * aTransform.c, aSize.width * aTransform.b + aSize.height * aTransform.d) -#define _CGRectApplyAffineTransform(aRect, aTransform) { origin:_CGPointApplyAffineTransform(aRect.origin, aTransform), size:_CGSizeApplyAffineTransform(aRect.size, aTransform) } - -#define _CGAffineTransformIsIdentity(aTransform) (aTransform.a == 1 && aTransform.b == 0 && aTransform.c == 0 && aTransform.d == 1 && aTransform.tx == 0 && aTransform.ty == 0) -#define _CGAffineTransformEqualToTransform(lhs, rhs) (lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c && lhs.d == rhs.d && lhs.tx == rhs.tx && lhs.ty == rhs.ty) - -#define _CGStringCreateWithCGAffineTransform(aTransform) (" [[ " + aTransform.a + ", " + aTransform.b + ", 0 ], [ " + aTransform.c + ", " + aTransform.d + ", 0 ], [ " + aTransform.tx + ", " + aTransform.ty + ", 1]]") - -#define _CGAffineTransformConcatTo(lhs, rhs, to) \ -var tx = lhs.tx * rhs.a + lhs.ty * rhs.c + rhs.tx;\ -to.ty = lhs.tx * rhs.b + lhs.ty * rhs.d + rhs.ty;\ -to.tx = tx;\ -var a = lhs.a * rhs.a + lhs.b * rhs.c,\ - b = lhs.a * rhs.b + lhs.b * rhs.d,\ - c = lhs.c * rhs.a + lhs.d * rhs.c;\ -to.d = lhs.c * rhs.b + lhs.d * rhs.d;\ -to.a = a;\ -to.b = b;\ -to.c = c;\ - -/* -a b 0 cos sin 0 -c d 0 -sin cos 0 -tx ty 1 0 0 1 -*/ diff --git a/AppKit/CoreGraphics/CGAffineTransform.j b/AppKit/CoreGraphics/CGAffineTransform.j index e55fbb24f..b73f26f07 100644 --- a/AppKit/CoreGraphics/CGAffineTransform.j +++ b/AppKit/CoreGraphics/CGAffineTransform.j @@ -23,35 +23,110 @@ @import "CGGeometry.j" -#define _function(inline) function inline { return _##inline; } +function CGAffineTransformMake(a, b, c, d, tx, ty) +{ + return { a:a, b:b, c:c, d:d, tx:tx, ty:ty }; +} -_function(CGAffineTransformMake(a, b, c, d, tx, ty)) -_function(CGAffineTransformMakeIdentity()) -_function(CGAffineTransformMakeCopy(anAffineTransform)) +function CGAffineTransformMakeIdentity() +{ + return { a:1.0, b:0.0, c:0.0, d:1.0, tx:0.0, ty:0.0 }; +} -_function(CGAffineTransformMakeScale(sx, sy)) -_function(CGAffineTransformMakeTranslation(tx, ty)) -_function(CGAffineTransformTranslate(aTransform, tx, ty)) -_function(CGAffineTransformScale(aTransform, sx, sy)) +function CGAffineTransformMakeCopy(anAffineTransform) +{ + return { a:anAffineTransform.a, b:anAffineTransform.b, c:anAffineTransform.c, d:anAffineTransform.d, tx:anAffineTransform.tx, ty:anAffineTransform.ty }; +} -_function(CGAffineTransformConcat(lhs, rhs)) -_function(CGPointApplyAffineTransform(aPoint, aTransform)) -_function(CGSizeApplyAffineTransform(aSize, aTransform)) +function CGAffineTransformMakeScale(sx, sy) +{ + return { a:sx, b:0.0, c:0.0, d:sy, tx:0.0, ty:0.0 }; +} -_function(CGAffineTransformIsIdentity(aTransform)) -_function(CGAffineTransformEqualToTransform(lhs, rhs)) +function CGAffineTransformMakeTranslation(tx, ty) +{ + return { a:1.0, b:0.0, c:0.0, d:1.0, tx:tx, ty:ty }; +} + +function CGAffineTransformTranslate(aTransform, tx, ty) +{ + return CGAffineTransformMake(aTransform.a, aTransform.b, aTransform.c, aTransform.d, aTransform.tx + aTransform.a * tx + aTransform.c * ty, aTransform.ty + aTransform.b * tx + aTransform.d * ty); +} + +function CGAffineTransformScale(aTransform, sx, sy) +{ + return CGAffineTransformMake(aTransform.a * sx, aTransform.b * sx, aTransform.c * sy, aTransform.d * sy, aTransform.tx, aTransform.ty); +} + + +function CGAffineTransformConcat(lhs, rhs) +{ + return CGAffineTransformMake(lhs.a * rhs.a + lhs.b * rhs.c, lhs.a * rhs.b + lhs.b * rhs.d, lhs.c * rhs.a + lhs.d * rhs.c, lhs.c * rhs.b + lhs.d * rhs.d, lhs.tx * rhs.a + lhs.ty * rhs.c + rhs.tx, lhs.tx * rhs.b + lhs.ty * rhs.d + rhs.ty); +} + +function CGAffineTransformConcatTo(lhs, rhs, to) +{ + var tx = lhs.tx * rhs.a + lhs.ty * rhs.c + rhs.tx; + + to.ty = lhs.tx * rhs.b + lhs.ty * rhs.d + rhs.ty; + to.tx = tx; + + var a = lhs.a * rhs.a + lhs.b * rhs.c, + b = lhs.a * rhs.b + lhs.b * rhs.d, + c = lhs.c * rhs.a + lhs.d * rhs.c; + + to.d = lhs.c * rhs.b + lhs.d * rhs.d; + to.a = a; + to.b = b; + to.c = c; +} + +function CGPointApplyAffineTransform(aPoint, aTransform) +{ + return { x:aPoint.x * aTransform.a + aPoint.y * aTransform.c + aTransform.tx, + y:aPoint.x * aTransform.b + aPoint.y * aTransform.d + aTransform.ty }; +} + +function CGSizeApplyAffineTransform(aSize, aTransform) +{ + return { width:aSize.width * aTransform.a + aSize.height * aTransform.c, + height:aSize.width * aTransform.b + aSize.height * aTransform.d }; +} + + +function CGAffineTransformIsIdentity(aTransform) +{ + return (aTransform.a === 1.0 && + aTransform.b === 0.0 && + aTransform.c === 0.0 && + aTransform.d === 1.0 && + aTransform.tx === 0.0 && + aTransform.ty === 0.0); +} + +function CGAffineTransformEqualToTransform(lhs, rhs) +{ + return (lhs.a === rhs.a && + lhs.b === rhs.b && + lhs.c === rhs.c && + lhs.d === rhs.d && + lhs.tx === rhs.tx && + lhs.ty === rhs.ty); +} + + +function CGStringCreateWithCGAffineTransform(aTransform) +{ + return (" [[ " + aTransform.a + ", " + aTransform.b + ", 0 ], [ " + aTransform.c + ", " + aTransform.d + ", 0 ], [ " + aTransform.tx + ", " + aTransform.ty + ", 1]]"); +} -_function(CGStringCreateWithCGAffineTransform(aTransform)) /* FIXME: !!!! @return void @group CGAffineTransform */ -function CGAffineTransformCreateCopy(aTransform) -{ - return _CGAffineTransformMakeCopy(aTransform); -} +CGAffineTransformCreateCopy = CGAffineTransformMakeCopy; /*! Returns a transform that rotates a coordinate system. @@ -66,7 +141,7 @@ function CGAffineTransformMakeRotation(anAngle) var sin = SIN(anAngle), cos = COS(anAngle); - return _CGAffineTransformMake(cos, sin, -sin, cos, 0.0, 0.0); + return CGAffineTransformMake(cos, sin, -sin, cos, 0.0, 0.0); } /*! @@ -121,20 +196,20 @@ function CGAffineTransformInvert(aTransform) */ function CGRectApplyAffineTransform(aRect, anAffineTransform) { - var top = _CGRectGetMinY(aRect), - left = _CGRectGetMinX(aRect), - right = _CGRectGetMaxX(aRect), - bottom = _CGRectGetMaxY(aRect), - topLeft = CGPointApplyAffineTransform(_CGPointMake(left, top), anAffineTransform), - topRight = CGPointApplyAffineTransform(_CGPointMake(right, top), anAffineTransform), - bottomLeft = CGPointApplyAffineTransform(_CGPointMake(left, bottom), anAffineTransform), - bottomRight = CGPointApplyAffineTransform(_CGPointMake(right, bottom), anAffineTransform), + var top = CGRectGetMinY(aRect), + left = CGRectGetMinX(aRect), + right = CGRectGetMaxX(aRect), + bottom = CGRectGetMaxY(aRect), + topLeft = CGPointApplyAffineTransform(CGPointMake(left, top), anAffineTransform), + topRight = CGPointApplyAffineTransform(CGPointMake(right, top), anAffineTransform), + bottomLeft = CGPointApplyAffineTransform(CGPointMake(left, bottom), anAffineTransform), + bottomRight = CGPointApplyAffineTransform(CGPointMake(right, bottom), anAffineTransform), minX = MIN(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x), maxX = MAX(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x), minY = MIN(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y), maxY = MAX(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); - return _CGRectMake(minX, minY, (maxX - minX), (maxY - minY)); + return CGRectMake(minX, minY, (maxX - minX), (maxY - minY)); } /*! diff --git a/AppKit/CoreGraphics/CGContext.j b/AppKit/CoreGraphics/CGContext.j index b60d38c22..c0b43eabd 100644 --- a/AppKit/CoreGraphics/CGContext.j +++ b/AppKit/CoreGraphics/CGContext.j @@ -116,7 +116,7 @@ function CGGStateCreate() { return { alpha:1.0, strokeStyle:"#000", fillStyle:"#ccc", lineWidth:1.0, lineJoin:kCGLineJoinMiter, lineCap:kCGLineCapButt, miterLimit:10.0, globalAlpha:1.0, blendMode:kCGBlendModeNormal, - shadowOffset:_CGSizeMakeZero(), shadowBlur:0.0, shadowColor:NULL, CTM:_CGAffineTransformMakeIdentity() }; + shadowOffset:CGSizeMakeZero(), shadowBlur:0.0, shadowColor:NULL, CTM:CGAffineTransformMakeIdentity() }; } /*! @@ -129,7 +129,7 @@ function CGGStateCreateCopy(aGState) return { alpha:aGState.alpha, strokeStyle:aGState.strokeStyle, fillStyle:aGState.fillStyle, lineWidth:aGState.lineWidth, lineJoin:aGState.lineJoin, lineCap:aGState.lineCap, miterLimit:aGState.miterLimit, globalAlpha:aGState.globalAlpha, blendMode:aGState.blendMode, - shadowOffset:_CGSizeMakeCopy(aGState.shadowOffset), shadowBlur:aGState.shadowBlur, shadowColor:aGState.shadowColor, CTM:_CGAffineTransformMakeCopy(aGState.CTM) }; + shadowOffset:CGSizeMakeCopy(aGState.shadowOffset), shadowBlur:aGState.shadowBlur, shadowColor:aGState.shadowColor, CTM:CGAffineTransformMakeCopy(aGState.CTM) }; } /*! @@ -166,6 +166,12 @@ function CGContextSetLineCap(aContext, aLineCap) aContext.gState.lineCap = aLineCap; } +function CGContextSetLineDash(aContext, aPhase, someDashes) +{ + aContext.gState.lineDashes = someDashes; + aContext.gState.lineDashesPhase = aPhase; +} + function CGContextSetLineJoin(aContext, aLineJoin) { aContext.gState.lineJoin = aLineJoin; @@ -418,7 +424,7 @@ function CGContextConcatCTM(aContext, aTransform) { var CTM = aContext.gState.CTM; - _CGAffineTransformConcatTo(CTM, aTransform, CTM); + CGAffineTransformConcatTo(CTM, aTransform, CTM); } /*! @@ -456,7 +462,7 @@ function CGContextScaleCTM(aContext, sx, sy) { var gState = aContext.gState; - gState.CTM = _CGAffineTransformScale(gState.CTM, sx, sy); + gState.CTM = CGAffineTransformScale(gState.CTM, sx, sy); } /*! @@ -470,7 +476,7 @@ function CGContextTranslateCTM(aContext, tx, ty) { var gState = aContext.gState; - gState.CTM = _CGAffineTransformTranslate(gState.CTM, tx, ty); + gState.CTM = CGAffineTransformTranslate(gState.CTM, tx, ty); } /*! @@ -485,7 +491,7 @@ function CGContextSetShadow(aContext, aSize, aBlur) { var gState = aContext.gState; - gState.shadowOffset = _CGSizeMakeCopy(aSize); + gState.shadowOffset = CGSizeMakeCopy(aSize); gState.shadowBlur = aBlur; gState.shadowColor = [CPColor shadowColor]; } @@ -502,7 +508,7 @@ function CGContextSetShadowWithColor(aContext, aSize, aBlur, aColor) { var gState = aContext.gState; - gState.shadowOffset = _CGSizeMakeCopy(aSize); + gState.shadowOffset = CGSizeMakeCopy(aSize); gState.shadowBlur = aBlur; gState.shadowColor = aColor; } diff --git a/AppKit/CoreGraphics/CGContextCanvas.j b/AppKit/CoreGraphics/CGContextCanvas.j index 6d83aa799..892813d3d 100644 --- a/AppKit/CoreGraphics/CGContextCanvas.j +++ b/AppKit/CoreGraphics/CGContextCanvas.j @@ -38,9 +38,9 @@ var CANVAS_LINECAP_TABLE = [ "butt", "round", "square" ], #define _CGContextClosePathCanvas(aContext) aContext.closePath() #define _CGContextMoveToPointCanvas(aContext, x, y) aContext.moveTo(x, y) -#define _CGContextAddRectCanvas(aContext, aRect) aContext.rect(_CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)) +#define _CGContextAddRectCanvas(aContext, aRect) aContext.rect(CGRectGetMinX(aRect), CGRectGetMinY(aRect), CGRectGetWidth(aRect), CGRectGetHeight(aRect)) #define _CGContextBeginPathCanvas(aContext) aContext.beginPath() -#define _CGContextFillRectCanvas(aContext, aRect) aContext.fillRect(_CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)) +#define _CGContextFillRectCanvas(aContext, aRect) aContext.fillRect(CGRectGetMinX(aRect), CGRectGetMinY(aRect), CGRectGetWidth(aRect), CGRectGetHeight(aRect)) #define _CGContextClipCanvas(aContext) aContext.clip() // In Cocoa, all primitives excepts rects cannot be added to the context's path @@ -68,6 +68,29 @@ function CGContextSetLineCap(aContext, aLineCap) aContext.lineCap = CANVAS_LINECAP_TABLE[aLineCap]; } +function CGContextSetLineDash(aContext, aPhase, someDashes) +{ + if (aContext.setLineDash) + { + aContext.setLineDash(someDashes); + aContext.lineDashOffset = aPhase; + } + else if (typeof aContext['webkitLineDash'] !== 'undefined') + { + aContext.webkitLineDash = someDashes; + aContext.webkitLineDashOffset = aPhase; + } + else if (typeof aContext['mozDash'] !== 'undefined') + { + aContext.mozDash = someDashes; + aContext.mozDashOffset = aPhase; + } + else if (someDashes) + { + CPLog.warn("CGContextSetLineDash not implemented in this environment.") + } +} + function CGContextSetLineJoin(aContext, aLineJoin) { aContext.lineJoin = CANVAS_LINEJOIN_TABLE[aLineJoin]; @@ -247,7 +270,7 @@ function CGContextMoveToPoint(aContext, x, y) function CGContextClearRect(aContext, aRect) { - aContext.clearRect(_CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); + aContext.clearRect(CGRectGetMinX(aRect), CGRectGetMinY(aRect), CGRectGetWidth(aRect), CGRectGetHeight(aRect)); aContext.hasPath = NO; } @@ -288,7 +311,7 @@ function CGContextFillRects(aContext, rects, count) function CGContextStrokeRect(aContext, aRect) { - aContext.strokeRect(_CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); + aContext.strokeRect(CGRectGetMinX(aRect), CGRectGetMinY(aRect), CGRectGetWidth(aRect), CGRectGetHeight(aRect)); aContext.hasPath = NO; } @@ -560,7 +583,7 @@ CGContextConcatCTM = function(aContext, anAffineTransform) function CGContextDrawImage(aContext, aRect, anImage) { - aContext.drawImage(anImage._image, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); + aContext.drawImage(anImage._image, CGRectGetMinX(aRect), CGRectGetMinY(aRect), CGRectGetWidth(aRect), CGRectGetHeight(aRect)); aContext.hasPath = NO; } diff --git a/AppKit/CoreGraphics/CGContextVML.j b/AppKit/CoreGraphics/CGContextVML.j index 66d17d89f..d8431a857 100644 --- a/AppKit/CoreGraphics/CGContextVML.j +++ b/AppKit/CoreGraphics/CGContextVML.j @@ -82,7 +82,7 @@ function CGContextDrawImage(aContext, aRect, anImage) { var angle = CGPointMake(1.0, 0.0); - angle = _CGPointApplyAffineTransform(angle, ctm); + angle = CGPointApplyAffineTransform(angle, ctm); vml.push(";rotation:", ATAN2(angle.y - ctm.ty, angle.x - ctm.tx) * 180 / PI); }*/ @@ -95,7 +95,7 @@ function CGContextDrawImage(aContext, aRect, anImage) { var transformedRect = CGRectApplyAffineTransform(aRect, ctm); - vml.push( ";padding:0 ", ROUND(_CGRectGetMaxX(transformedRect)), "px ", ROUND(_CGRectGetMaxY(transformedRect)), + vml.push( ";padding:0 ", ROUND(CGRectGetMaxX(transformedRect)), "px ", ROUND(CGRectGetMaxY(transformedRect)), "px 0;filter:progid:DXImageTransform.Microsoft.Matrix(", "M11='", ctm.a, "',M12='", ctm.c, "',M21='", ctm.b, "',M22='", ctm.d, "',", "Dx='", ROUND(origin.x), "', Dy='", ROUND(origin.y), "', sizingmethod='clip');"); @@ -104,7 +104,7 @@ function CGContextDrawImage(aContext, aRect, anImage) // vml.push(";top:", ROUND(origin.y - 0.5), "px;left:", ROUND(origin.x - 0.5), "px;"); vml.push( "\">"); string = vml.join(""); @@ -175,7 +175,7 @@ function CGContextDrawPath(aContext, aMode) endAngle = element.endAngle, startAngle = element.startAngle, - start = _CGPointMake(x + radius * COS(startAngle), y + radius * SIN(startAngle)); + start = CGPointMake(x + radius * COS(startAngle), y + radius * SIN(startAngle)); // If the angle's are equal, then we won't actually draw an arc, but instead // simply move to its start/end to get the proper fill. @@ -188,12 +188,12 @@ function CGContextDrawPath(aContext, aMode) continue; } - var end = _CGPointMake(x + radius * COS(endAngle), y + radius * SIN(endAngle)); + var end = CGPointMake(x + radius * COS(endAngle), y + radius * SIN(endAngle)); // Only do the start correction if the angles aren't equal. If they are, then // let the circle be empty. // FIXME: Should this be |star.x - end.x| < 0.125 ? - if (clockwise && startAngle != endAngle && _CGPointEqualToPoint(start, end)) + if (clockwise && startAngle != endAngle && CGPointEqualToPoint(start, end)) if (start.x >= x) { if (start.y < y) diff --git a/AppKit/CoreGraphics/CGPath.j b/AppKit/CoreGraphics/CGPath.j index fb01d5c34..05d1651d8 100644 --- a/AppKit/CoreGraphics/CGPath.j +++ b/AppKit/CoreGraphics/CGPath.j @@ -43,7 +43,7 @@ kCGPathElementAddArcToPoint = 6; */ function CGPathCreateMutable() { - return { count:0, start:_CGPointMake(0, 0), current:_CGPointMake(0, 0), elements:[] }; + return { count:0, start:CGPointMake(0, 0), current:CGPointMake(0, 0), elements:[] }; } /*! @@ -79,15 +79,15 @@ function CGPathRetain(aPath) function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle, isClockwise) { - if (aTransform && !_CGAffineTransformIsIdentity(aTransform)) + if (aTransform && !CGAffineTransformIsIdentity(aTransform)) { - var center = _CGPointMake(x, y), - end = _CGPointMake(COS(anEndAngle), SIN(anEndAngle)), - start = _CGPointMake(COS(aStartAngle), SIN(aStartAngle)); + var center = CGPointMake(x, y), + end = CGPointMake(COS(anEndAngle), SIN(anEndAngle)), + start = CGPointMake(COS(aStartAngle), SIN(aStartAngle)); - end = _CGPointApplyAffineTransform(end, aTransform); - start = _CGPointApplyAffineTransform(start, aTransform); - center = _CGPointApplyAffineTransform(center, aTransform); + end = CGPointApplyAffineTransform(end, aTransform); + start = CGPointApplyAffineTransform(start, aTransform); + center = CGPointApplyAffineTransform(center, aTransform); x = center.x; y = center.y; @@ -107,8 +107,8 @@ function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle, else aStartAngle = aStartAngle - PI2; - aRadius = _CGSizeMake(aRadius, 0); - aRadius = _CGSizeApplyAffineTransform(aRadius, aTransform); + aRadius = CGSizeMake(aRadius, 0); + aRadius = CGSizeApplyAffineTransform(aRadius, aTransform); aRadius = SQRT(aRadius.width * aRadius.width + aRadius.height * aRadius.height); } @@ -132,22 +132,22 @@ function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle, var arcStartX = x + aRadius * COS(aStartAngle), arcStartY = y + aRadius * SIN(aStartAngle); - aPath.start = _CGPointMake(arcStartX, arcStartY); + aPath.start = CGPointMake(arcStartX, arcStartY); } - aPath.current = _CGPointMake(arcEndX, arcEndY); + aPath.current = CGPointMake(arcEndX, arcEndY); aPath.elements[aPath.count++] = { type:kCGPathElementAddArc, x:x, y:y, radius:aRadius, startAngle:aStartAngle, endAngle:anEndAngle, clockwise:isClockwise }; } function CGPathAddArcToPoint(aPath, aTransform, x1, y1, x2, y2, aRadius) { - var p1 = _CGPointMake(x1, y1), - p2 = _CGPointMake(x2, y2); + var p1 = CGPointMake(x1, y1), + p2 = CGPointMake(x2, y2); if (aTransform) { - p1 = _CGPointApplyAffineTransform(p1, aTransform); - p2 = _CGPointApplyAffineTransform(p2, aTransform); + p1 = CGPointApplyAffineTransform(p1, aTransform); + p2 = CGPointApplyAffineTransform(p2, aTransform); } /* @@ -171,15 +171,15 @@ function CGPathAddArcToPoint(aPath, aTransform, x1, y1, x2, y2, aRadius) function CGPathAddCurveToPoint(aPath, aTransform, cp1x, cp1y, cp2x, cp2y, x, y) { - var cp1 = _CGPointMake(cp1x, cp1y), - cp2 = _CGPointMake(cp2x, cp2y), - end = _CGPointMake(x, y); + var cp1 = CGPointMake(cp1x, cp1y), + cp2 = CGPointMake(cp2x, cp2y), + end = CGPointMake(x, y); if (aTransform) { - cp1 = _CGPointApplyAffineTransform(cp1, aTransform); - cp2 = _CGPointApplyAffineTransform(cp2, aTransform); - end = _CGPointApplyAffineTransform(end, aTransform); + cp1 = CGPointApplyAffineTransform(cp1, aTransform); + cp2 = CGPointApplyAffineTransform(cp2, aTransform); + end = CGPointApplyAffineTransform(end, aTransform); } aPath.current = end; @@ -202,10 +202,10 @@ function CGPathAddLines(aPath, aTransform, points, count) function CGPathAddLineToPoint(aPath, aTransform, x, y) { - var point = _CGPointMake(x, y); + var point = CGPointMake(x, y); if (aTransform !== NULL) - point = _CGPointApplyAffineTransform(point, aTransform); + point = CGPointApplyAffineTransform(point, aTransform); aPath.elements[aPath.count++] = { type: kCGPathElementAddLineToPoint, x:point.x, y:point.y }; aPath.current = point; @@ -262,13 +262,13 @@ function CGPathAddPath(aPath, aTransform, anotherPath) function CGPathAddQuadCurveToPoint(aPath, aTransform, cpx, cpy, x, y) { - var cp = _CGPointMake(cpx, cpy), - end = _CGPointMake(x, y); + var cp = CGPointMake(cpx, cpy), + end = CGPointMake(x, y); if (aTransform) { - cp = _CGPointApplyAffineTransform(cp, aTransform); - end = _CGPointApplyAffineTransform(end, aTransform); + cp = CGPointApplyAffineTransform(cp, aTransform); + end = CGPointApplyAffineTransform(end, aTransform); } aPath.elements[aPath.count++] = { type:kCGPathElementAddQuadCurveToPoint, cpx:cp.x, cpy:cp.y, x:end.x, y:end.y } @@ -291,10 +291,10 @@ function CGPathAddRects(aPath, aTransform, rects, count) { var rect = rects[i]; - CGPathMoveToPoint(aPath, aTransform, _CGRectGetMinX(rect), _CGRectGetMinY(rect)); - CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMaxX(rect), _CGRectGetMinY(rect)); - CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMaxX(rect), _CGRectGetMaxY(rect)); - CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMinX(rect), _CGRectGetMaxY(rect)); + CGPathMoveToPoint(aPath, aTransform, CGRectGetMinX(rect), CGRectGetMinY(rect)); + CGPathAddLineToPoint(aPath, aTransform, CGRectGetMaxX(rect), CGRectGetMinY(rect)); + CGPathAddLineToPoint(aPath, aTransform, CGRectGetMaxX(rect), CGRectGetMaxY(rect)); + CGPathAddLineToPoint(aPath, aTransform, CGRectGetMinX(rect), CGRectGetMaxY(rect)); CGPathCloseSubpath(aPath); } @@ -302,10 +302,10 @@ function CGPathAddRects(aPath, aTransform, rects, count) function CGPathMoveToPoint(aPath, aTransform, x, y) { - var point = _CGPointMake(x, y); + var point = CGPointMake(x, y); if (aTransform !== NULL) - point = _CGPointApplyAffineTransform(point, aTransform); + point = CGPointApplyAffineTransform(point, aTransform); aPath.start = aPath.current = point; @@ -331,12 +331,12 @@ function CGPathWithEllipseInRect(aRect) { var path = CGPathCreateMutable(); - if (_CGRectGetWidth(aRect) === _CGRectGetHeight(aRect)) - CGPathAddArc(path, nil, _CGRectGetMidX(aRect), _CGRectGetMidY(aRect), _CGRectGetWidth(aRect) / 2.0, 0.0, 2 * PI, YES); + if (CGRectGetWidth(aRect) === CGRectGetHeight(aRect)) + CGPathAddArc(path, nil, CGRectGetMidX(aRect), CGRectGetMidY(aRect), CGRectGetWidth(aRect) / 2.0, 0.0, 2 * PI, YES); else { - var axis = _CGSizeMake(_CGRectGetWidth(aRect) / 2.0, _CGRectGetHeight(aRect) / 2.0), - center = _CGPointMake(_CGRectGetMinX(aRect) + axis.width, _CGRectGetMinY(aRect) + axis.height); + var axis = CGSizeMake(CGRectGetWidth(aRect) / 2.0, CGRectGetHeight(aRect) / 2.0), + center = CGPointMake(CGRectGetMinX(aRect) + axis.width, CGRectGetMinY(aRect) + axis.height); CGPathMoveToPoint(path, nil, center.x, center.y - axis.height); @@ -354,10 +354,10 @@ function CGPathWithEllipseInRect(aRect) function CGPathWithRoundedRectangleInRect(aRect, xRadius, yRadius/*not currently supported*/, ne, se, sw, nw) { var path = CGPathCreateMutable(), - xMin = _CGRectGetMinX(aRect), - xMax = _CGRectGetMaxX(aRect), - yMin = _CGRectGetMinY(aRect), - yMax = _CGRectGetMaxY(aRect); + xMin = CGRectGetMinX(aRect), + xMax = CGRectGetMaxX(aRect), + yMin = CGRectGetMinY(aRect), + yMax = CGRectGetMaxY(aRect); CGPathMoveToPoint(path, nil, xMin + xRadius, yMin); @@ -407,7 +407,7 @@ function CGPathCloseSubpath(aPath) return; // After closing, the current point is the previous path's starting point - aPath.current = _CGPointCreateCopy(aPath.start); + aPath.current = CGPointCreateCopy(aPath.start); aPath.elements[aPath.count++] = { type:kCGPathElementCloseSubpath, start:aPath.start }; } @@ -416,7 +416,7 @@ function CGPathEqualToPath(aPath, anotherPath) if (aPath === anotherPath) return YES; - if (aPath.count !== anotherPath.count || !_CGPointEqualToPoint(aPath.start, anotherPath.start) || !_CGPointEqualToPoint(aPath.current, anotherPath.current)) + if (aPath.count !== anotherPath.count || !CGPointEqualToPoint(aPath.start, anotherPath.start) || !CGPointEqualToPoint(aPath.current, anotherPath.current)) return NO; var i = 0, @@ -487,7 +487,7 @@ function CGPathEqualToPath(aPath, anotherPath) break; case kCGPathElementCloseSubpath: - if (!_CGPointEqualToPoint(element.start, anotherElement.start)) + if (!CGPointEqualToPoint(element.start, anotherElement.start)) return NO; break; } @@ -498,7 +498,7 @@ function CGPathEqualToPath(aPath, anotherPath) function CGPathGetCurrentPoint(aPath) { - return _CGPointCreateCopy(aPath.current); + return CGPointCreateCopy(aPath.current); } function CGPathIsEmpty(aPath) @@ -512,7 +512,7 @@ function CGPathIsEmpty(aPath) function CGPathGetBoundingBox(aPath) { if (!aPath || !aPath.count) - return _CGRectMakeZero(); + return CGRectMakeZero(); var ox = 0, oy = 0, @@ -591,7 +591,7 @@ function CGPathGetBoundingBox(aPath) break; case kCGPathElementMoveToPoint: - movePoint = _CGPointMake(element.x, element.y); + movePoint = CGPointMake(element.x, element.y); break; case kCGPathElementCloseSubpath: @@ -605,7 +605,7 @@ function CGPathGetBoundingBox(aPath) } } - return _CGRectMake(ox, oy, rx - ox, ry - oy); + return CGRectMake(ox, oy, rx - ox, ry - oy); } /*! diff --git a/AppKit/Platform/CPPlatformString.j b/AppKit/Platform/CPPlatformString.j index ddc7e29d1..b0a930c6d 100644 --- a/AppKit/Platform/CPPlatformString.j +++ b/AppKit/Platform/CPPlatformString.j @@ -33,7 +33,7 @@ + (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth { - return _CGSizeMakeZero(); + return CGSizeMakeZero(); } @end @@ -45,7 +45,7 @@ + (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth { - return _CGSizeMakeZero(); + return CGSizeMakeZero(); } + (CPDictionary)metricsOfFont:(CPFont)aFont diff --git a/AppKit/Platform/CPPlatformWindow.j b/AppKit/Platform/CPPlatformWindow.j index d5988787c..d75858dca 100644 --- a/AppKit/Platform/CPPlatformWindow.j +++ b/AppKit/Platform/CPPlatformWindow.j @@ -106,7 +106,7 @@ var PrimaryPlatformWindow = NULL; if (self) { - _contentRect = _CGRectMakeCopy(aRect); + _contentRect = CGRectMakeCopy(aRect); #if PLATFORM(DOM) _windowLevels = []; @@ -121,19 +121,19 @@ var PrimaryPlatformWindow = NULL; - (id)init { - return [self initWithContentRect:_CGRectMake(0.0, 0.0, 400.0, 500.0)]; + return [self initWithContentRect:CGRectMake(0.0, 0.0, 400.0, 500.0)]; } - (CGRect)contentRect { - return _CGRectMakeCopy(_contentRect); + return CGRectMakeCopy(_contentRect); } - (CGRect)contentBounds { var contentBounds = [self contentRect]; - contentBounds.origin = _CGPointMakeZero(); + contentBounds.origin = CGPointMakeZero(); return contentBounds; } @@ -142,7 +142,7 @@ var PrimaryPlatformWindow = NULL; { var frame = [self contentBounds]; - frame.origin = _CGPointMakeZero(); + frame.origin = CGPointMakeZero(); if ([CPMenu menuBarVisible] && [CPPlatformWindow primaryPlatformWindow] === self) { @@ -162,10 +162,10 @@ var PrimaryPlatformWindow = NULL; - (void)setContentRect:(CGRect)aRect { - if (!aRect || _CGRectEqualToRect(_contentRect, aRect)) + if (!aRect || CGRectEqualToRect(_contentRect, aRect)) return; - _contentRect = _CGRectMakeCopy(aRect); + _contentRect = CGRectMakeCopy(aRect); #if PLATFORM(DOM) [self updateNativeContentRect]; @@ -181,14 +181,14 @@ var PrimaryPlatformWindow = NULL; { var contentRect = [self contentRect]; - return _CGPointMake(aPoint.x + _CGRectGetMinX(contentRect), aPoint.y + _CGRectGetMinY(contentRect)); + return CGPointMake(aPoint.x + CGRectGetMinX(contentRect), aPoint.y + CGRectGetMinY(contentRect)); } - (CGPoint)convertScreenToBase:(CGPoint)aPoint { var contentRect = [self contentRect]; - return _CGPointMake(aPoint.x - _CGRectGetMinX(contentRect), aPoint.y - _CGRectGetMinY(contentRect)); + return CGPointMake(aPoint.x - CGRectGetMinX(contentRect), aPoint.y - CGRectGetMinY(contentRect)); } - (BOOL)isVisible diff --git a/AppKit/Platform/DOM/CPDOMDisplayServer.h b/AppKit/Platform/DOM/CPDOMDisplayServer.h index 34e3ba838..3aa1a22af 100644 --- a/AppKit/Platform/DOM/CPDOMDisplayServer.h +++ b/AppKit/Platform/DOM/CPDOMDisplayServer.h @@ -49,26 +49,26 @@ CPDOMDisplayServerInstructions[__index + 4] = y; #if !DOM_OPTIMIZATION #define CPDOMDisplayServerSetStyleLeftTop(aDOMElement, aTransform, aLeft, aTop) \ -if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aLeft, aTop), aTransform); \ -else var ____p = _CGPointMake(aLeft, aTop); \ +if (aTransform) var ____p = CGPointApplyAffineTransform(CGPointMake(aLeft, aTop), aTransform); \ +else var ____p = CGPointMake(aLeft, aTop); \ aDOMElement.style.left = ROUND(____p.x) + "px";\ aDOMElement.style.top = ROUND(____p.y) + "px"; #define CPDOMDisplayServerSetStyleRightTop(aDOMElement, aTransform, aRight, aTop) \ -if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aRight, aTop), aTransform); \ -else var ____p = _CGPointMake(aRight, aTop); \ +if (aTransform) var ____p = CGPointApplyAffineTransform(CGPointMake(aRight, aTop), aTransform); \ +else var ____p = CGPointMake(aRight, aTop); \ aDOMElement.style.right = ROUND(____p.x) + "px";\ aDOMElement.style.top = ROUND(____p.y) + "px"; #define CPDOMDisplayServerSetStyleLeftBottom(aDOMElement, aTransform, aLeft, aBottom) \ -if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aLeft, aBottom), aTransform); \ -else var ____p = _CGPointMake(aLeft, aBottom); \ +if (aTransform) var ____p = CGPointApplyAffineTransform(CGPointMake(aLeft, aBottom), aTransform); \ +else var ____p = CGPointMake(aLeft, aBottom); \ aDOMElement.style.left = ROUND(____p.x) + "px";\ aDOMElement.style.bottom = ROUND(____p.y) + "px"; #define CPDOMDisplayServerSetStyleRightBottom(aDOMElement, aTransform, aRight, aBottom) \ -if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aRight, aBottom), aTransform); \ -else var ____p = _CGPointMake(aRight, aBottom); \ +if (aTransform) var ____p = CGPointApplyAffineTransform(CGPointMake(aRight, aBottom), aTransform); \ +else var ____p = CGPointMake(aRight, aBottom); \ aDOMElement.style.right = ROUND(____p.x) + "px";\ aDOMElement.style.bottom = ROUND(____p.y) + "px"; @@ -166,8 +166,8 @@ CPDOMDisplayServerInstructionCount = 0; var transform = CPDOMDisplayServerInstructions[index++];\ if (transform)\ {\ - var point = _CGPointMake(CPDOMDisplayServerInstructions[index++], CPDOMDisplayServerInstructions[index++]),\ - transformed = _CGPointApplyAffineTransform(point, transform);\ + var point = CGPointMake(CPDOMDisplayServerInstructions[index++], CPDOMDisplayServerInstructions[index++]),\ + transformed = CGPointApplyAffineTransform(point, transform);\ style[x] = ROUND(transformed.x) + "px";\ style[y] = ROUND(transformed.y) + "px";\ }\ diff --git a/AppKit/Platform/DOM/CPDOMWindowLayer.j b/AppKit/Platform/DOM/CPDOMWindowLayer.j index 926074a3d..5ef90849d 100644 --- a/AppKit/Platform/DOM/CPDOMWindowLayer.j +++ b/AppKit/Platform/DOM/CPDOMWindowLayer.j @@ -130,4 +130,52 @@ return _windows; } +/*! + Places \c aWindow within an element that clips it to the global rect \c clipRect. + + NOTE: This is only meant for temporary usage during animation and should be balanced + with a call to removeClipForWindow:. No attempt is made to make the clipping element follow + changes to the window. +*/ +- (void)clipWindow:(CPWindow)aWindow toRect:(CGRect)clipRect +{ + // First check to see if the window is already clipped. + // If so, just update its rect. + var windowElement = aWindow._DOMElement, + clip = document.createElement("div"), + style = clip.style; + + style = clip.style; + style.className = "cpwindowclip"; + style.position = "absolute"; + style.overflow = "hidden"; + + style.left = clipRect.origin.x + "px"; + style.top = clipRect.origin.y + "px"; + style.width = clipRect.size.width + "px"; + style.height = clipRect.size.height + "px"; + + // Replace the window with the clip element, then put it inside the clip + var parent = windowElement.parentNode; + CPDOMDisplayServerInsertBefore(parent, clip, windowElement); + CPDOMDisplayServerRemoveChild(parent, windowElement); + CPDOMDisplayServerAppendChild(clip, windowElement); +} + +/*! + Unclips a window that was previously clipped with clipWindow:toWindow:. + If the window was not clipped, a warning is logged. +*/ +- (void)removeClipForWindow:(CPWindow)aWindow +{ + var windowElement = aWindow._DOMElement, + clip = windowElement.parentNode, + parent = clip.parentNode; + + CPDOMDisplayServerRemoveChild(clip, windowElement); + [aWindow setFrameOrigin:CGPointMake([aWindow frame].origin.x, clip.offsetTop)]; + CPDOMDisplayServerInsertBefore(parent, windowElement, clip); + CPDOMDisplayServerRemoveChild(parent, clip); +} + @end diff --git a/AppKit/Platform/DOM/CPPlatformString.j b/AppKit/Platform/DOM/CPPlatformString.j index aff149962..f35c891f5 100644 --- a/AppKit/Platform/DOM/CPPlatformString.j +++ b/AppKit/Platform/DOM/CPPlatformString.j @@ -151,7 +151,7 @@ var DOMFixedWidthSpanElement = nil, else if (CPFeatureIsCompatible(CPJavaScriptTextContentFeature)) span.textContent = aString; - return _CGSizeMake(span.clientWidth, span.clientHeight); + return CGSizeMake(span.clientWidth, span.clientHeight); } + (CPDictionary)metricsOfFont:(CPFont)aFont diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index b4af9d0de..546c05871 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -210,7 +210,7 @@ var resizeTimer = nil; if (self) { _DOMWindow = window; - _contentRect = _CGRectMakeZero(); + _contentRect = CGRectMakeZero(); _windowLevels = []; _windowLayers = @{}; @@ -232,25 +232,25 @@ var resizeTimer = nil; if (_DOMWindow.cpFrame) return _DOMWindow.cpFrame(); - var contentRect = _CGRectMakeZero(); + var contentRect = CGRectMakeZero(); if (window.screenTop) - contentRect.origin = _CGPointMake(_DOMWindow.screenLeft, _DOMWindow.screenTop); + contentRect.origin = CGPointMake(_DOMWindow.screenLeft, _DOMWindow.screenTop); else if (window.screenX) - contentRect.origin = _CGPointMake(_DOMWindow.screenX, _DOMWindow.screenY); + contentRect.origin = CGPointMake(_DOMWindow.screenX, _DOMWindow.screenY); // Safari, Mozilla, Firefox, and Opera if (_DOMWindow.innerWidth) - contentRect.size = _CGSizeMake(_DOMWindow.innerWidth, _DOMWindow.innerHeight); + contentRect.size = CGSizeMake(_DOMWindow.innerWidth, _DOMWindow.innerHeight); // Internet Explorer 6 in Strict Mode else if (document.documentElement && document.documentElement.clientWidth) - contentRect.size = _CGSizeMake(_DOMWindow.document.documentElement.clientWidth, _DOMWindow.document.documentElement.clientHeight); + contentRect.size = CGSizeMake(_DOMWindow.document.documentElement.clientWidth, _DOMWindow.document.documentElement.clientHeight); // Internet Explorer X else - contentRect.size = _CGSizeMake(_DOMWindow.document.body.clientWidth, _DOMWindow.document.body.clientHeight); + contentRect.size = CGSizeMake(_DOMWindow.document.body.clientWidth, _DOMWindow.document.body.clientHeight); return contentRect; } @@ -548,7 +548,7 @@ var resizeTimer = nil; if (_DOMWindow) return _DOMWindow.focus(); - _DOMWindow = window.open("about:blank", "_blank", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no,left=" + _CGRectGetMinX(_contentRect) + ",top=" + _CGRectGetMinY(_contentRect) + ",width=" + _CGRectGetWidth(_contentRect) + ",height=" + _CGRectGetHeight(_contentRect)); + _DOMWindow = window.open("about:blank", "_blank", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no,left=" + CGRectGetMinX(_contentRect) + ",top=" + CGRectGetMinY(_contentRect) + ",width=" + CGRectGetWidth(_contentRect) + ",height=" + CGRectGetHeight(_contentRect)); [PlatformWindows addObject:self]; @@ -585,7 +585,7 @@ var resizeTimer = nil; { var type = aDOMEvent.type, dragServer = [CPDragServer sharedDragServer], - location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY), + location = CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY), pasteboard = [_CPDOMDataTransferPasteboard DOMDataTransferPasteboard]; [pasteboard _setDataTransfer:aDOMEvent.dataTransfer]; @@ -600,8 +600,8 @@ var resizeTimer = nil; draggedWindowFrame = [draggedWindow frame], DOMDragElement = draggedWindow._DOMElement; - DOMDragElement.style.left = -_CGRectGetWidth(draggedWindowFrame) + "px"; - DOMDragElement.style.top = -_CGRectGetHeight(draggedWindowFrame) + "px"; + DOMDragElement.style.left = -CGRectGetWidth(draggedWindowFrame) + "px"; + DOMDragElement.style.top = -CGRectGetHeight(draggedWindowFrame) + "px"; var parentNode = DOMDragElement.parentNode; @@ -615,7 +615,7 @@ var resizeTimer = nil; aDOMEvent.dataTransfer.setDragImage(DOMDragElement, draggingOffset.width, draggingOffset.height); aDOMEvent.dataTransfer.effectAllowed = "all"; - [dragServer draggingStartedInPlatformWindow:self globalLocation:[CPPlatform isBrowser] ? location : _CGPointMake(aDOMEvent.screenX, aDOMEvent.screenY)]; + [dragServer draggingStartedInPlatformWindow:self globalLocation:[CPPlatform isBrowser] ? location : CGPointMake(aDOMEvent.screenX, aDOMEvent.screenY)]; } else if (type === "drag") { @@ -624,7 +624,7 @@ var resizeTimer = nil; if (CPFeatureIsCompatible(CPHTML5DragAndDropSourceYOffBy1)) y -= 1; - [dragServer draggingSourceUpdatedWithGlobalLocation:[CPPlatform isBrowser] ? location : _CGPointMake(aDOMEvent.screenX, y)]; + [dragServer draggingSourceUpdatedWithGlobalLocation:[CPPlatform isBrowser] ? location : CGPointMake(aDOMEvent.screenX, y)]; } else if (type === "dragover" || type === "dragleave") { @@ -656,7 +656,7 @@ var resizeTimer = nil; else dragOperation = CPDragOperationNone; - [dragServer draggingEndedInPlatformWindow:self globalLocation:[CPPlatform isBrowser] ? location : _CGPointMake(aDOMEvent.screenX, aDOMEvent.screenY) operation:dragOperation]; + [dragServer draggingEndedInPlatformWindow:self globalLocation:[CPPlatform isBrowser] ? location : CGPointMake(aDOMEvent.screenX, aDOMEvent.screenY) operation:dragOperation]; } else //if (type === "drop") { @@ -676,7 +676,7 @@ var resizeTimer = nil; - (void)keyEvent:(DOMEvent)aDOMEvent { var event, - location = _lastMouseEventLocation || _CGPointMakeZero(), + location = _lastMouseEventLocation || CGPointMakeZero(), timestamp = [CPEvent currentTimestamp], sourceElement = aDOMEvent.target || aDOMEvent.srcElement, windowNumber = [[CPApp keyWindow] windowNumber], @@ -897,7 +897,7 @@ var resizeTimer = nil; timestamp = [CPEvent currentTimestamp], // fake event, might as well use current timestamp windowNumber = [[CPApp keyWindow] windowNumber], modifierFlags = CPPlatformActionKeyMask, - location = _lastMouseEventLocation || _CGPointMakeZero(), + location = _lastMouseEventLocation || CGPointMakeZero(), event = [CPEvent keyEventWithType:CPKeyDown location:location modifierFlags:modifierFlags timestamp:timestamp windowNumber:windowNumber context:nil characters:characters charactersIgnoringModifiers:characters isARepeat:NO keyCode:keyCode]; @@ -1018,12 +1018,12 @@ var resizeTimer = nil; } while (element = element.offsetParent); } - location = _CGPointMake((x + ((aDOMEvent.clientX - 8) / 15)), (y + ((aDOMEvent.clientY - 8) / 15))); + location = CGPointMake((x + ((aDOMEvent.clientX - 8) / 15)), (y + ((aDOMEvent.clientY - 8) / 15))); } else if (aDOMEvent._overrideLocation) location = aDOMEvent._overrideLocation; else - location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY); + location = CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY); var deltaX = 0.0, deltaY = 0.0, @@ -1212,7 +1212,7 @@ var resizeTimer = nil; } var event, - location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY), + location = CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY), timestamp = [CPEvent currentTimestamp], sourceElement = (aDOMEvent.target || aDOMEvent.srcElement), windowNumber = 0, diff --git a/AppKit/Resources/AboutPanel.cib b/AppKit/Resources/AboutPanel.cib deleted file mode 100644 index 0f3bfd601..000000000 --- a/AppKit/Resources/AboutPanel.cib +++ /dev/null @@ -1 +0,0 @@ -280NPLIST;1.0;D;K;4;$topD;K;18;CPCibObjectDataKeyD;K;6;CP$UIDd;1;2E;K;21;CPCibObjectRecordsKeyD;K;6;CP$UIDd;1;4E;E;K;8;$objectsA;S;5;$nullD;K;10;$classnameS;16;_CPCibObjectDataK;8;$classesA;S;16;_CPCibObjectDataS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;1E;K;28;_CPCibObjectDataNamesKeysKeyD;K;6;CP$UIDd;1;5E;K;30;_CPCibObjectDataNamesValuesKeyD;K;6;CP$UIDd;1;6E;K;30;_CPCibObjectDataClassesKeysKeyD;K;6;CP$UIDd;1;7E;K;32;_CPCibObjectDataClassesValuesKeyD;K;6;CP$UIDd;1;8E;K;30;_CPCibObjectDataConnectionsKeyD;K;6;CP$UIDd;1;9E;K;28;_CPCibObjectDataFrameworkKeyD;K;6;CP$UIDd;2;10E;K;26;_CPCibObjectDataNextOidKeyD;K;6;CP$UIDd;2;11E;K;30;_CPCibObjectDataObjectsKeysKeyD;K;6;CP$UIDd;2;12E;K;32;_CPCibObjectDataObjectsValuesKeyD;K;6;CP$UIDd;2;13E;K;26;_CPCibObjectDataOidKeysKeyD;K;6;CP$UIDd;2;14E;K;28;_CPCibObjectDataOidValuesKeyD;K;6;CP$UIDd;2;15E;K;28;_CPCibObjectDataFileOwnerKeyD;K;6;CP$UIDd;2;17E;K;33;_CPCibObjectDataVisibleWindowsKeyD;K;6;CP$UIDd;2;19E;E;D;K;10;$classnameS;7;CPArrayK;8;$classesA;S;7;CPArrayS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;21E;D;K;6;CP$UIDd;2;22E;D;K;6;CP$UIDd;2;23E;D;K;6;CP$UIDd;2;24E;D;K;6;CP$UIDd;2;25E;D;K;6;CP$UIDd;2;26E;D;K;6;CP$UIDd;2;27E;D;K;6;CP$UIDd;2;28E;D;K;6;CP$UIDd;2;29E;D;K;6;CP$UIDd;2;30E;D;K;6;CP$UIDd;2;31E;D;K;6;CP$UIDd;2;32E;D;K;6;CP$UIDd;2;33E;D;K;6;CP$UIDd;2;21E;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;35E;D;K;6;CP$UIDd;2;36E;D;K;6;CP$UIDd;2;37E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;17E;D;K;6;CP$UIDd;2;39E;D;K;6;CP$UIDd;2;40E;D;K;6;CP$UIDd;2;42E;D;K;6;CP$UIDd;2;44E;D;K;6;CP$UIDd;2;46E;D;K;6;CP$UIDd;2;47E;D;K;6;CP$UIDd;2;48E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;49E;D;K;6;CP$UIDd;2;50E;D;K;6;CP$UIDd;2;51E;D;K;6;CP$UIDd;2;52E;D;K;6;CP$UIDd;2;53E;D;K;6;CP$UIDd;2;54E;D;K;6;CP$UIDd;2;54E;D;K;6;CP$UIDd;2;54E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;56E;E;E;S;16;IBCocoaFrameworkd;3;461D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;39E;D;K;6;CP$UIDd;2;40E;D;K;6;CP$UIDd;2;42E;D;K;6;CP$UIDd;2;44E;D;K;6;CP$UIDd;2;46E;D;K;6;CP$UIDd;2;47E;D;K;6;CP$UIDd;2;48E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;17E;D;K;6;CP$UIDd;2;17E;D;K;6;CP$UIDd;2;39E;D;K;6;CP$UIDd;2;42E;D;K;6;CP$UIDd;2;42E;D;K;6;CP$UIDd;2;42E;D;K;6;CP$UIDd;2;42E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;10;$classnameS;18;_CPCibCustomObjectK;8;$classesA;S;18;_CPCibCustomObjectS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;16E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;57E;E;D;K;10;$classnameS;5;CPSetK;8;$classesA;S;5;CPSetS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;18E;K;15;CPSetObjectsKeyD;K;6;CP$UIDd;2;58E;E;D;K;10;$classnameS;15;CibObjectRecordK;8;$classesA;S;15;CibObjectRecordS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;59E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;60E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;61E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;62E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;63E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;2;42E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;64E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;48E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;54E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;65E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;66E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;67E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;68E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;2;42E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;69E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;47E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;54E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;70E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;71E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;72E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;73E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;2;42E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;74E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;46E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;54E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;75E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;76E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;77E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;78E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;1;0E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;79E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;80E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;2;42E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;81E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;44E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;53E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;2;60E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;82E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;17E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;51E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;2;39E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;83E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;42E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;52E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;2;60E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;84E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;39E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;50E;E;D;K;6;$classD;K;6;CP$UIDd;2;20E;K;24;CibObjectRecordParentKeyD;K;6;CP$UIDd;2;60E;K;26;CibObjectRecordChildrenKeyD;K;6;CP$UIDd;2;85E;K;24;CibObjectRecordObjectKeyD;K;6;CP$UIDd;2;40E;K;23;CibObjectRecordLabelKeyD;K;6;CP$UIDd;2;51E;E;D;K;10;$classnameS;20;_CPCibWindowTemplateK;8;$classesA;S;20;_CPCibWindowTemplateS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;38E;K;30;_CPCibWindowTemplateMaxSizeKeyD;K;6;CP$UIDd;2;86E;K;32;_CPCibWindowTemplateViewClassKeyD;K;6;CP$UIDd;1;0E;K;34;_CPCibWindowTemplateWindowClassKeyD;K;6;CP$UIDd;2;87E;K;33;_CPCibWindowTemplateWindowRectKeyD;K;6;CP$UIDd;2;88E;K;30;_CPCibWindowTempatStyleMaskKeyD;K;6;CP$UIDd;2;89E;K;34;_CPCibWindowTemplateWindowTitleKeyD;K;6;CP$UIDd;2;90E;K;33;_CPCibWindowTemplateWindowViewKeyD;K;6;CP$UIDd;2;42E;E;D;K;6;$classD;K;6;CP$UIDd;2;16E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;91E;E;D;K;10;$classnameS;6;CPViewK;8;$classesA;S;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;41E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;92E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;93E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;94E;K;15;CPViewWindowKeyD;K;6;CP$UIDd;2;95E;K;17;CPViewSubviewsKeyD;K;6;CP$UIDd;2;96E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;92E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;97E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;98E;E;D;K;10;$classnameS;11;CPImageViewK;8;$classesA;S;11;CPImageViewS;9;CPControlS;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;43E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;42E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;99E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;100E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;101E;K;15;CPViewWindowKeyD;K;6;CP$UIDd;2;95E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;42E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;3;102E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;98E;K;15;$aimage-scalingD;K;6;CP$UIDd;3;103E;K;11;$aalignmentD;K;6;CP$UIDd;3;103E;K;17;CPControlValueKeyD;K;6;CP$UIDd;3;105E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;3;106E;K;23;CPImageViewHasShadowKeyD;K;6;CP$UIDd;1;0E;E;D;K;10;$classnameS;11;CPTextFieldK;8;$classesA;S;11;CPTextFieldS;9;CPControlS;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;45E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;42E;K;12;CPViewTagKeyD;K;6;CP$UIDd;3;107E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;108E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;109E;K;15;CPViewWindowKeyD;K;6;CP$UIDd;2;95E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;42E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;3;110E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;98E;K;6;$afontD;K;6;CP$UIDd;3;112E;K;12;$atext-colorD;K;6;CP$UIDd;3;114E;K;11;$aalignmentD;K;6;CP$UIDd;3;106E;K;17;CPControlValueKeyD;K;6;CP$UIDd;3;115E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;3;116E;K;24;CPTextFieldIsEditableKeyD;K;6;CP$UIDd;3;117E;K;26;CPTextFieldIsSelectableKeyD;K;6;CP$UIDd;3;117E;K;29;CPTextFieldDrawsBackgroundKeyD;K;6;CP$UIDd;1;0E;K;29;CPTextFieldBackgroundColorKeyD;K;6;CP$UIDd;1;0E;K;31;CPTextFieldPlaceholderStringKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;45E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;42E;K;12;CPViewTagKeyD;K;6;CP$UIDd;3;118E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;119E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;120E;K;15;CPViewWindowKeyD;K;6;CP$UIDd;2;95E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;42E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;3;110E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;98E;K;6;$afontD;K;6;CP$UIDd;3;121E;K;12;$atext-colorD;K;6;CP$UIDd;3;122E;K;11;$aalignmentD;K;6;CP$UIDd;3;106E;K;17;CPControlValueKeyD;K;6;CP$UIDd;3;123E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;3;116E;K;24;CPTextFieldIsEditableKeyD;K;6;CP$UIDd;3;117E;K;26;CPTextFieldIsSelectableKeyD;K;6;CP$UIDd;3;117E;K;29;CPTextFieldDrawsBackgroundKeyD;K;6;CP$UIDd;1;0E;K;29;CPTextFieldBackgroundColorKeyD;K;6;CP$UIDd;1;0E;K;31;CPTextFieldPlaceholderStringKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;45E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;42E;K;12;CPViewTagKeyD;K;6;CP$UIDd;3;124E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;125E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;126E;K;15;CPViewWindowKeyD;K;6;CP$UIDd;2;95E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;42E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;3;110E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;98E;K;6;$afontD;K;6;CP$UIDd;3;127E;K;12;$atext-colorD;K;6;CP$UIDd;3;128E;K;11;$aalignmentD;K;6;CP$UIDd;3;106E;K;17;CPControlValueKeyD;K;6;CP$UIDd;3;129E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;3;116E;K;24;CPTextFieldIsEditableKeyD;K;6;CP$UIDd;3;117E;K;26;CPTextFieldIsSelectableKeyD;K;6;CP$UIDd;3;117E;K;29;CPTextFieldDrawsBackgroundKeyD;K;6;CP$UIDd;1;0E;K;29;CPTextFieldBackgroundColorKeyD;K;6;CP$UIDd;1;0E;K;31;CPTextFieldPlaceholderStringKeyD;K;6;CP$UIDd;1;0E;E;S;12;File's OwnerS;6;WindowS;11;ApplicationS;4;ViewS;10;Image viewS;10;Text fieldD;K;10;$classnameS;20;CPCibOutletConnectorK;8;$classesA;S;20;CPCibOutletConnectorS;14;CPCibConnectorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;55E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;17E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;39E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;130E;E;S;18;CPWindowControllerD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;17E;D;K;6;CP$UIDd;2;39E;D;K;6;CP$UIDd;2;40E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;S;5;ArrayD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;48E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;47E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;47E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;46E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;46E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;44E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;44E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;44E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;44E;D;K;6;CP$UIDd;2;46E;D;K;6;CP$UIDd;2;47E;D;K;6;CP$UIDd;2;48E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;42E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;S;26;{3.40282e+38, 3.40282e+38}S;8;CPWindowS;22;{{72, 57}, {219, 263}}d;1;7S;0;S;13;CPApplicationS;5;$nullS;21;{{0, 26}, {219, 263}}S;20;{{0, 0}, {219, 263}}S;5;$nullD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;44E;D;K;6;CP$UIDd;2;46E;D;K;6;CP$UIDd;2;47E;D;K;6;CP$UIDd;2;48E;E;E;d;2;18S;6;normalS;1;1S;24;{{45.5, 16}, {128, 128}}S;20;{{0, 0}, {128, 128}}d;2;37d;1;0D;K;10;$classnameS;20;_CPCibCustomResourceK;8;$classesA;S;20;_CPCibCustomResourceS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;3;104E;K;32;_CPCibCustomResourceClassNameKeyD;K;6;CP$UIDd;3;131E;K;35;_CPCibCustomResourceResourceNameKeyD;K;6;CP$UIDd;3;132E;K;33;_CPCibCustomResourcePropertiesKeyD;K;6;CP$UIDd;3;134E;E;d;1;4S;1;2S;22;{{16, 165}, {187, 25}}S;19;{{0, 0}, {187, 25}}d;2;36D;K;10;$classnameS;6;CPFontK;8;$classesA;S;6;CPFontS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;3;111E;K;13;CPFontNameKeyD;K;6;CP$UIDd;3;135E;K;13;CPFontSizeKeyD;K;6;CP$UIDd;3;136E;K;15;CPFontIsBoldKeyD;K;6;CP$UIDd;3;117E;E;D;K;10;$classnameS;7;CPColorK;8;$classesA;S;7;CPColorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;3;113E;K;20;CPColorComponentsKeyD;K;6;CP$UIDd;3;137E;E;S;7;AppNamed;4;3072F;S;1;3S;22;{{16, 194}, {187, 20}}S;19;{{0, 0}, {187, 20}}D;K;6;$classD;K;6;CP$UIDd;3;111E;K;13;CPFontNameKeyD;K;6;CP$UIDd;3;135E;K;13;CPFontSizeKeyD;K;6;CP$UIDd;3;136E;K;15;CPFontIsBoldKeyD;K;6;CP$UIDd;3;117E;E;D;K;6;$classD;K;6;CP$UIDd;3;113E;K;20;CPColorComponentsKeyD;K;6;CP$UIDd;3;138E;E;S;19;Version XXX (build)S;1;4S;22;{{16, 222}, {187, 22}}S;19;{{0, 0}, {187, 22}}D;K;6;$classD;K;6;CP$UIDd;3;111E;K;13;CPFontNameKeyD;K;6;CP$UIDd;3;135E;K;13;CPFontSizeKeyD;K;6;CP$UIDd;3;136E;K;15;CPFontIsBoldKeyD;K;6;CP$UIDd;3;117E;E;D;K;6;$classD;K;6;CP$UIDd;3;113E;K;20;CPColorComponentsKeyD;K;6;CP$UIDd;3;139E;E;S;9;CopyrightS;6;windowS;7;CPImageS;8;Icon.pngD;K;10;$classnameS;12;CPDictionaryK;8;$classesA;S;12;CPDictionaryS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;3;133E;K;10;CP.objectsD;K;4;sizeD;K;6;CP$UIDd;3;141E;E;E;S;5;Ariald;2;13D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;142E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;142E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;103E;D;K;6;CP$UIDd;3;142E;E;E;D;K;10;$classnameS;21;_CPKeyedArchiverValueK;8;$classesA;S;21;_CPKeyedArchiverValueS;7;CPValueS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;3;140E;K;15;CPValueValueKeyD;K;6;CP$UIDd;3;143E;E;d;1;1S;24;{"width":-1,"height":-1}E;K;9;$archiverS;15;CPKeyedArchiverK;8;$versionS;6;100000E; \ No newline at end of file diff --git a/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-left-highlighted.png b/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-left-highlighted.png new file mode 100644 index 000000000..de074caf9 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-left-highlighted.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-left.png b/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-left.png new file mode 100644 index 000000000..8f1fc7370 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-left.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-right-highlighted.png b/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-right-highlighted.png new file mode 100644 index 000000000..0c4af90e2 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-right-highlighted.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-right.png b/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-right.png new file mode 100644 index 000000000..ca16659ee Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-calendar-arrow-right.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-circle-image-highlighted.png b/AppKit/Themes/Aristo/Resources/datepicker-circle-image-highlighted.png new file mode 100644 index 000000000..2b3a52153 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-circle-image-highlighted.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-circle-image.png b/AppKit/Themes/Aristo/Resources/datepicker-circle-image.png new file mode 100644 index 000000000..c315ff4b1 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-circle-image.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-disabled.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-disabled.png new file mode 100644 index 000000000..856977746 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-disabled.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-hour-hand-disabled.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-hour-hand-disabled.png new file mode 100644 index 000000000..d4413ceb1 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-hour-hand-disabled.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-hour-hand.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-hour-hand.png new file mode 100644 index 000000000..d42a0c2b2 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-hour-hand.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-middle-hand-disabled.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-middle-hand-disabled.png new file mode 100644 index 000000000..535b44678 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-middle-hand-disabled.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-middle-hand.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-middle-hand.png new file mode 100644 index 000000000..f0fbbc3fb Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-middle-hand.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-minute-hand-disabled.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-minute-hand-disabled.png new file mode 100644 index 000000000..c051338e9 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-minute-hand-disabled.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-minute-hand.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-minute-hand.png new file mode 100644 index 000000000..a553f841e Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-minute-hand.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-second-hand-disabled.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-second-hand-disabled.png new file mode 100644 index 000000000..9daea2c05 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-second-hand-disabled.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock-second-hand.png b/AppKit/Themes/Aristo/Resources/datepicker-clock-second-hand.png new file mode 100644 index 000000000..7c50c2cd5 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock-second-hand.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-clock.png b/AppKit/Themes/Aristo/Resources/datepicker-clock.png new file mode 100644 index 000000000..251d086cf Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-clock.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-date-segment-0.png b/AppKit/Themes/Aristo/Resources/datepicker-date-segment-0.png new file mode 100644 index 000000000..d9d618051 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-date-segment-0.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-date-segment-1.png b/AppKit/Themes/Aristo/Resources/datepicker-date-segment-1.png new file mode 100644 index 000000000..c08199498 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-date-segment-1.png differ diff --git a/AppKit/Themes/Aristo/Resources/datepicker-date-segment-2.png b/AppKit/Themes/Aristo/Resources/datepicker-date-segment-2.png new file mode 100644 index 000000000..314102fa7 Binary files /dev/null and b/AppKit/Themes/Aristo/Resources/datepicker-date-segment-2.png differ diff --git a/AppKit/Themes/Aristo/Resources/window-attached-sheet-shadow.png b/AppKit/Themes/Aristo/Resources/window-attached-sheet-shadow.png index b39cae110..eeab7d517 100644 Binary files a/AppKit/Themes/Aristo/Resources/window-attached-sheet-shadow.png and b/AppKit/Themes/Aristo/Resources/window-attached-sheet-shadow.png differ diff --git a/AppKit/Themes/Aristo/ThemeDescriptors.j b/AppKit/Themes/Aristo/ThemeDescriptors.j index 2a61a47d1..ed9f0cc15 100755 --- a/AppKit/Themes/Aristo/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo/ThemeDescriptors.j @@ -30,6 +30,7 @@ @import @import @import +@import @import @import @import @@ -986,20 +987,20 @@ var themedButtonValues = nil, [@"content-inset", CGInsetMake(3.0, 3.0, 3.0, 5.0), CPThemeStateTableDataView], [@"text-color", [CPColor colorWithCalibratedWhite:51.0 / 255.0 alpha:1.0], CPThemeStateTableDataView], - [@"text-color", [CPColor whiteColor], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView], - [@"font", [CPFont boldSystemFontOfSize:CPFontCurrentSystemSize], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView], + [@"text-color", [CPColor whiteColor], CPThemeStateTableDataView | CPThemeStateSelectedDataView], + [@"font", [CPFont systemFontOfSize:CPFontCurrentSystemSize], CPThemeStateTableDataView | CPThemeStateSelectedDataView], [@"text-color", [CPColor blackColor], CPThemeStateTableDataView | CPThemeStateEditable], - [@"text-color", [CPColor blackColor], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView | CPThemeStateEditing], + [@"text-color", [CPColor blackColor], CPThemeStateTableDataView | CPThemeStateSelectedDataView | CPThemeStateEditing], [@"text-color", [CPColor blackColor], CPThemeStateTableDataView | CPThemeStateBezeled], [@"content-inset", CGInsetMake(8.0, 8.0, 7.0, 5.0), CPThemeStateTableDataView | CPThemeStateEditing], [@"font", [CPFont systemFontOfSize:CPFontCurrentSystemSize], CPThemeStateTableDataView | CPThemeStateEditing], [@"bezel-inset", CGInsetMake(-1.0, -1.0, -1.0, -1.0), CPThemeStateTableDataView | CPThemeStateEditing], [@"text-color", [CPColor colorWithCalibratedWhite:125.0 / 255.0 alpha:1.0], CPThemeStateTableDataView | CPThemeStateGroupRow], - [@"text-color", [CPColor colorWithCalibratedWhite:1.0 alpha:1.0], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedTableDataView], + [@"text-color", [CPColor colorWithCalibratedWhite:1.0 alpha:1.0], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedDataView], [@"text-shadow-color", [CPColor whiteColor], CPThemeStateTableDataView | CPThemeStateGroupRow], [@"text-shadow-offset", CGSizeMake(0,1), CPThemeStateTableDataView | CPThemeStateGroupRow], - [@"text-shadow-color", [CPColor colorWithCalibratedWhite:0.0 alpha:0.6], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedTableDataView], + [@"text-shadow-color", [CPColor colorWithCalibratedWhite:0.0 alpha:0.6], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedDataView], [@"font", [CPFont boldSystemFontOfSize:CPFontCurrentSystemSize], CPThemeStateTableDataView | CPThemeStateGroupRow] ]; @@ -1094,6 +1095,228 @@ var themedButtonValues = nil, return searchField; } ++ (CPDatePicker)themedDatePicker +{ + var datePicker = [[CPDatePicker alloc] initWithFrame:CGRectMake(40,140,300,29)], + + bezelColor = PatternColor( + [ + ["textfield-bezel-square-0.png", 6.0, 6.0], + ["textfield-bezel-square-1.png", 1.0, 6.0], + ["textfield-bezel-square-2.png", 6.0, 6.0], + ["textfield-bezel-square-3.png", 6.0, 1.0], + ["textfield-bezel-square-4.png", 1.0, 1.0], + ["textfield-bezel-square-5.png", 6.0, 1.0], + ["textfield-bezel-square-6.png", 6.0, 6.0], + ["textfield-bezel-square-7.png", 1.0, 6.0], + ["textfield-bezel-square-8.png", 6.0, 6.0] + ]), + + bezelDisabledColor = PatternColor( + [ + ["textfield-bezel-square-disabled-0.png", 6.0, 6.0], + ["textfield-bezel-square-disabled-1.png", 1.0, 6.0], + ["textfield-bezel-square-disabled-2.png", 6.0, 6.0], + ["textfield-bezel-square-disabled-3.png", 6.0, 1.0], + ["textfield-bezel-square-disabled-4.png", 1.0, 1.0], + ["textfield-bezel-square-disabled-5.png", 6.0, 1.0], + ["textfield-bezel-square-disabled-6.png", 6.0, 6.0], + ["textfield-bezel-square-disabled-7.png", 1.0, 6.0], + ["textfield-bezel-square-disabled-8.png", 6.0, 6.0] + ]), + + bezelColorDatePickerTextField = PatternColor( + [ + [@"datepicker-date-segment-0.png", 4.0, 18.0], + [@"datepicker-date-segment-1.png", 1.0, 18.0], + [@"datepicker-date-segment-2.png", 4.0, 18.0] + ], PatternIsHorizontal), + + themeValues = + [ + [@"bezel-color", bezelColor, CPThemeStateBezeled], + [@"bezel-color", bezelDisabledColor, CPThemeStateBezeled | CPThemeStateDisabled], + + [@"font", [CPFont boldSystemFontOfSize:13.0]], + [@"text-color", [CPColor colorWithWhite:0.2 alpha:0.8]], + [@"text-color", textDisabledColor, CPThemeStateDisabled], + + [@"content-inset", CGInsetMake(6.0, 0.0, 0.0, 3.0), CPThemeStateNormal], + [@"content-inset", CGInsetMake(6.0, 0.0, 0.0, 5.0), CPThemeStateBezeled], + [@"bezel-inset", CGInsetMake(0.0, -3.0, 0.0, -3.0), CPThemeStateBezeled], + + [@"datepicker-textfield-bezel-color", [CPColor clearColor], CPThemeStateNormal], + [@"datepicker-textfield-bezel-color", bezelColorDatePickerTextField, CPThemeStateSelected], + [@"datepicker-textfield-bezel-color", [CPColor clearColor], CPThemeStateNormal | CPThemeStateDisabled], + [@"datepicker-textfield-bezel-color", bezelColorDatePickerTextField, CPThemeStateSelected | CPThemeStateDisabled], + + [@"min-size-datepicker-textfield", CGSizeMake(6.0, 18.0)], + + [@"separator-content-inset", CGInsetMake(0.0, -2.0, 0.0, -1.0)], + + [@"content-inset-datepicker-textfield", CGInsetMake(2.0, 2.0, 0.0, 1.0), CPThemeStateNormal], + [@"content-inset-datepicker-textfield-separator", CGInsetMake(2.0, 0.0, 0.0, 0.0), CPThemeStateNormal], + [@"content-inset-datepicker-textfield", CGInsetMake(2.0, 2.0, 0.0, 1.0), CPThemeStateSelected], + [@"content-inset-datepicker-textfield-separator", CGInsetMake(2.0, 0.0, 0.0, 0.0), CPThemeStateSelected], + + [@"date-hour-margin", 7.0], + [@"stepper-margin", 2.0], + + [@"min-size", CGSizeMake(0.0, 29.0)], + [@"max-size", CGSizeMake(-1.0, 29.0)] + ]; + + [self registerThemeValues:themeValues forView:datePicker]; + + return datePicker; +} + ++ (CPDatePicker)themedDatePickerCalendar +{ + var datePicker = [[CPDatePicker alloc] initWithFrame:CGRectMake(40,140,300,29)], + + arrowImageLeft = PatternImage("datepicker-calendar-arrow-left.png", 7.0, 10.0), + arrowImageRight = PatternImage("datepicker-calendar-arrow-right.png", 7.0, 10.0), + circleImage = PatternImage("datepicker-circle-image.png", 9.0, 10.0), + + arrowImageLeftHighlighted = PatternImage("datepicker-calendar-arrow-left-highlighted.png", 7.0, 10.0), + arrowImageRightHighlighted = PatternImage("datepicker-calendar-arrow-right-highlighted.png", 7.0, 10.0), + circleImageHighlighted = PatternImage("datepicker-circle-image-highlighted.png", 9.0, 10.0), + + secondHandColor = PatternColor("datepicker-clock-second-hand.png", 89.0, 89.0), + minuteHandColor = PatternColor("datepicker-clock-minute-hand.png", 85.0, 85.0), + hourHandColor = PatternColor("datepicker-clock-hour-hand.png", 47.0, 47.0), + middleHandColor = PatternColor("datepicker-clock-middle-hand.png", 13.0, 13.0), + clockImageColor = PatternColor("datepicker-clock.png", 122.0, 123.0), + + secondHandColorDisabled = PatternColor("datepicker-clock-second-hand-disabled.png", 89.0, 89.0), + minuteHandColorDisabled = PatternColor("datepicker-clock-minute-hand-disabled.png", 85.0, 85.0), + hourHandColorDisabled = PatternColor("datepicker-clock-hour-hand-disabled.png", 47.0, 47.0), + middleHandColorDisabled = PatternColor("datepicker-clock-middle-hand-disabled.png", 13.0, 13.0), + clockImageColorDisabled = PatternColor("datepicker-clock-disabled.png", 122.0, 123.0), + + themeValues = + [ + [@"border-color", [CPColor colorWithCalibratedRed:217.0 / 255.0 green:217.0 / 255.0 blue:211.0 / 255.0 alpha:1.0], CPThemeStateNormal], + [@"border-color", [CPColor colorWithCalibratedRed:100.0 / 255.0 green:154.0 / 255.0 blue:184.0 / 255.0 alpha:1.0], CPThemeStateSelected], + [@"border-color", [CPColor colorWithCalibratedRed:217.0 / 255.0 green:217.0 / 255.0 blue:211.0 / 255.0 alpha:0.5], CPThemeStateNormal | CPThemeStateDisabled], + [@"border-color", [CPColor colorWithCalibratedRed:100.0 / 255.0 green:154.0 / 255.0 blue:184.0 / 255.0 alpha:0.5], CPThemeStateSelected | CPThemeStateDisabled], + + [@"bezel-color-calendar", [CPColor whiteColor]], + [@"bezel-color-calendar", [CPColor colorWithCalibratedRed:159.0 / 255.0 green:201.0 / 255.0 blue:225.0 / 255.0 alpha:1.0], CPThemeStateSelected], + [@"bezel-color-calendar", [CPColor colorWithCalibratedRed:159.0 / 255.0 green:201.0 / 255.0 blue:225.0 / 255.0 alpha:0.5], CPThemeStateSelected |CPThemeStateDisabled], + [@"bezel-color-clock", clockImageColor], + [@"bezel-color-clock", clockImageColorDisabled, CPThemeStateDisabled], + + [@"title-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:1.0]], + [@"title-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0]], + [@"title-text-shadow-offset", CGSizeMake(0,1)], + [@"title-font", [CPFont boldSystemFontOfSize:12.0]], + + [@"title-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:0.5], CPThemeStateDisabled], + [@"title-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateDisabled], + [@"title-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled], + [@"title-font", [CPFont boldSystemFontOfSize:12.0], CPThemeStateDisabled], + + [@"weekday-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:1.0]], + [@"weekday-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0]], + [@"weekday-text-shadow-offset", CGSizeMake(0,1)], + [@"weekday-font", [CPFont systemFontOfSize:11.0]], + + [@"weekday-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:0.5], CPThemeStateDisabled], + [@"weekday-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateDisabled], + [@"weekday-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled], + [@"weekday-font", [CPFont systemFontOfSize:11.0], CPThemeStateDisabled], + + [@"clock-text-color", [CPColor colorWithCalibratedRed:153.0 / 255.0 green:153.0 / 255.0 blue:153.0 / 255.0 alpha:1.0]], + [@"clock-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0]], + [@"clock-text-shadow-offset", CGSizeMake(0,1)], + [@"clock-font", [CPFont systemFontOfSize:11.0]], + + [@"clock-text-color", [CPColor colorWithCalibratedRed:153.0 / 255.0 green:153.0 / 255.0 blue:153.0 / 255.0 alpha:0.5], CPThemeStateDisabled], + [@"clock-text-shadow-color", [CPColor whiteColor], CPThemeStateDisabled], + [@"clock-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled], + [@"clock-font", [CPFont systemFontOfSize:11.0], CPThemeStateDisabled], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:1.0], CPThemeStateNormal], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateNormal], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateNormal], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateNormal], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:100.0 / 255.0 green:154.0 / 255.0 blue:184.0 / 255.0 alpha:1.0], CPThemeStateHighlighted], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateHighlighted], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateHighlighted], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateHighlighted], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:100.0 / 255.0 green:154.0 / 255.0 blue:184.0 / 255.0 alpha:0.5], CPThemeStateHighlighted | CPThemeStateDisabled], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateHighlighted | CPThemeStateDisabled], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateHighlighted | CPThemeStateDisabled], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateHighlighted | CPThemeStateDisabled], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:1.0], CPThemeStateSelected], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateSelected], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateSelected], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateSelected], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:1.0], CPThemeStateHighlighted | CPThemeStateSelected], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateHighlighted | CPThemeStateSelected], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateHighlighted | CPThemeStateSelected], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateHighlighted | CPThemeStateSelected], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:179.0 / 255.0 green:179.0 / 255.0 blue:179.0 / 255.0 alpha:1.0], CPThemeStateDisabled], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateDisabled], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateDisabled], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:0.5], CPThemeStateDisabled | CPThemeStateSelected | CPThemeStateHighlighted], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateDisabled | CPThemeStateSelected | CPThemeStateHighlighted], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled | CPThemeStateSelected | CPThemeStateHighlighted], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateDisabled | CPThemeStateSelected | CPThemeStateHighlighted], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:13.0 / 255.0 green:51.0 / 255.0 blue:70.0 / 255.0 alpha:0.5], CPThemeStateDisabled | CPThemeStateSelected], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedWhite:240.0 / 255.0 alpha:1.0], CPThemeStateDisabled | CPThemeStateSelected], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled | CPThemeStateSelected], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateDisabled | CPThemeStateSelected], + + [@"arrow-image-left", arrowImageLeft], + [@"arrow-image-right", arrowImageRight], + [@"arrow-image-left-highlighted", arrowImageLeftHighlighted], + [@"arrow-image-right-highlighted", arrowImageRightHighlighted], + [@"circle-image", circleImage], + [@"circle-image-highlighted", circleImageHighlighted], + [@"arrow-inset", CGInsetMake(9.0, 4.0, 0.0, 0.0)], + + [@"second-hand-color", secondHandColor], + [@"hour-hand-color", hourHandColor], + [@"middle-hand-color", middleHandColor], + [@"minute-hand-color", minuteHandColor], + + [@"second-hand-color", secondHandColorDisabled, CPThemeStateDisabled], + [@"hour-hand-color", hourHandColorDisabled, CPThemeStateDisabled], + [@"middle-hand-color", middleHandColorDisabled, CPThemeStateDisabled], + [@"minute-hand-color", minuteHandColorDisabled, CPThemeStateDisabled], + + [@"second-hand-size", CGSizeMake(89.0, 89.0)], + [@"hour-hand-size", CGSizeMake(47.0, 47.0)], + [@"middle-hand-size", CGSizeMake(13.0, 13.0)], + [@"minute-hand-size", CGSizeMake(85.0, 85.0)], + + [@"border-width", 1.0], + [@"size-header", CGSizeMake(141.0, 39.0)], + [@"size-tile", CGSizeMake(20.0, 18.0)], + [@"size-clock", CGSizeMake(122.0, 123.0)], + [@"size-calendar", CGSizeMake(141.0, 109.0)], + [@"min-size-calendar", CGSizeMake(141.0, 148.0)], + [@"max-size-calendar", CGSizeMake(141.0, 148.0)] + + ]; + + [datePicker setDatePickerStyle:CPClockAndCalendarDatePickerStyle]; + [self registerThemeValues:themeValues forView:datePicker]; + + return datePicker; +} + + (CPTokenField)themedTokenField { var tokenfield = [[CPTokenField alloc] initWithFrame:CGRectMake(0.0, 0.0, 60.0, 29.0)], @@ -1843,7 +2066,7 @@ var themedButtonValues = nil, sourceListSelectionColor = @{ CPSourceListGradient: CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [98.0 / 255.0, 143.0 / 210.0, 209.0 / 255.0, 1.0, 46.0 / 255.0, 88.0 / 176.0, 208.0 / 255.0,1.0], [0,1], 2), CPSourceListTopLineColor: [CPColor colorWithCalibratedRed:81.0 / 255.0 green:127.0 / 255.0 blue:200.0 / 255.0 alpha:1.0], - CPSourceListBottomLineColor: [CPColor colorWithCalibratedRed:34.0 / 255.0 green:63.0 / 255.0 blue:123.0 / 255.0 alpha:1.0], + CPSourceListBottomLineColor: [CPColor colorWithCalibratedRed:34.0 / 255.0 green:63.0 / 255.0 blue:123.0 / 255.0 alpha:1.0] }, themedTableViewValues = @@ -2327,7 +2550,7 @@ var themedButtonValues = nil, { var windowView = [[_CPWindowView alloc] initWithFrame:CGRectMakeZero()], - sheetShadow = PatternColor(@"window-attached-sheet-shadow.png", 9, 8), + sheetShadow = PatternColor(@"window-attached-sheet-shadow.png", 1, 8), resizeIndicator = PatternImage(@"window-resize-indicator.png", 12, 12), shadowColor = PatternColor( @@ -2350,6 +2573,7 @@ var themedButtonValues = nil, [@"window-shadow-color", shadowColor], [@"resize-indicator", resizeIndicator], [@"attached-sheet-shadow-color", sheetShadow], + [@"shadow-height", 8], [@"size-indicator", CGSizeMake(12, 12)] ]; @@ -2457,7 +2681,6 @@ var themedButtonValues = nil, minimizeButtonImage = PatternImage(@"window-standard-minimize-button.png",16, 16), minimizeButtonImageHighlighted = PatternImage(@"window-standard-minimize-button-highlighted.png",16, 16), - sheetShadow = PatternColor(@"window-attached-sheet-shadow.png", 9, 8), resizeIndicator = PatternImage(@"window-resize-indicator.png", 12, 12), themeValues = @@ -2492,7 +2715,6 @@ var themedButtonValues = nil, [@"close-image-origin", CGPointMake(8.0, 10.0)], [@"resize-indicator", resizeIndicator], - [@"attached-sheet-shadow-color", sheetShadow], [@"size-indicator", CGSizeMake(12, 12)] ]; @@ -2503,7 +2725,7 @@ var themedButtonValues = nil, + (_CPDocModalWindowView)themedDocModalWindowView { - var docModalWindowView = [[_CPDocModalWindowView alloc] initWithFrame:CGRectMake(0,0,200,200) styleMask:nil], + var docModalWindowView = [[_CPDocModalWindowView alloc] initWithFrame:CGRectMake(0, 0, 200, 200) styleMask:nil], bezelColor = PatternColor( [ @@ -2518,13 +2740,9 @@ var themedButtonValues = nil, [@"window-standard-bottom-right.png", 2.0, 2.0] ]), - sheetShadow = PatternColor(@"window-attached-sheet-shadow.png", 9, 8), - themeValues = [ - [@"body-color", bezelColor], - [@"height-shadow", 8], - [@"attached-sheet-shadow-color", sheetShadow] + [@"body-color", bezelColor] ]; [self registerThemeValues:themeValues forView:docModalWindowView inherit:themedWindowViewValues]; @@ -2590,8 +2808,6 @@ var themedButtonValues = nil, themeValues = [ - [@"menu-item-selection-color", [CPColor colorWithHexString:@"5C85D8"]], - [@"menu-item-text-shadow-color", [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]], [@"horizontal-margin", 12.0], [@"submenu-indicator-margin", 3.0], [@"vertical-margin", 4.0] diff --git a/AppKit/Themes/Aristo2/Artwork/Aristo 11-06-07.psd b/AppKit/Themes/Aristo2/Artwork/Aristo 11-06-07.psd index 3ff6d3e5f..ef95c237f 100755 Binary files a/AppKit/Themes/Aristo2/Artwork/Aristo 11-06-07.psd and b/AppKit/Themes/Aristo2/Artwork/Aristo 11-06-07.psd differ diff --git a/AppKit/Themes/Aristo2/Artwork/window-attached-sheet-shadow.psd b/AppKit/Themes/Aristo2/Artwork/window-attached-sheet-shadow.psd new file mode 100644 index 000000000..407342a8a Binary files /dev/null and b/AppKit/Themes/Aristo2/Artwork/window-attached-sheet-shadow.psd differ diff --git a/AppKit/Themes/Aristo2/Resources/Aristo-11-06-07_501.png b/AppKit/Themes/Aristo2/Resources/Aristo-11-06-07_501.png new file mode 100644 index 000000000..2fda06e9b Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/Aristo-11-06-07_501.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-left-highlighted.png b/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-left-highlighted.png new file mode 100644 index 000000000..de074caf9 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-left-highlighted.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-left.png b/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-left.png new file mode 100644 index 000000000..8f1fc7370 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-left.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-right-highlighted.png b/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-right-highlighted.png new file mode 100644 index 000000000..0c4af90e2 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-right-highlighted.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-right.png b/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-right.png new file mode 100644 index 000000000..ca16659ee Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-calendar-arrow-right.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-circle-image-highlighted.png b/AppKit/Themes/Aristo2/Resources/datepicker-circle-image-highlighted.png new file mode 100644 index 000000000..2b3a52153 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-circle-image-highlighted.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-circle-image.png b/AppKit/Themes/Aristo2/Resources/datepicker-circle-image.png new file mode 100644 index 000000000..c315ff4b1 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-circle-image.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-disabled.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-disabled.png new file mode 100644 index 000000000..856977746 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-disabled.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-hour-hand-disabled.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-hour-hand-disabled.png new file mode 100644 index 000000000..d4413ceb1 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-hour-hand-disabled.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-hour-hand.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-hour-hand.png new file mode 100644 index 000000000..d42a0c2b2 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-hour-hand.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-middle-hand-disabled.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-middle-hand-disabled.png new file mode 100644 index 000000000..535b44678 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-middle-hand-disabled.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-middle-hand.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-middle-hand.png new file mode 100644 index 000000000..f0fbbc3fb Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-middle-hand.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-minute-hand-disabled.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-minute-hand-disabled.png new file mode 100644 index 000000000..c051338e9 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-minute-hand-disabled.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-minute-hand.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-minute-hand.png new file mode 100644 index 000000000..a553f841e Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-minute-hand.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-second-hand-disabled.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-second-hand-disabled.png new file mode 100644 index 000000000..9daea2c05 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-second-hand-disabled.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock-second-hand.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock-second-hand.png new file mode 100644 index 000000000..7c50c2cd5 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock-second-hand.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-clock.png b/AppKit/Themes/Aristo2/Resources/datepicker-clock.png new file mode 100644 index 000000000..251d086cf Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-clock.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-0.png b/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-0.png new file mode 100644 index 000000000..d9d618051 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-0.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-1.png b/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-1.png new file mode 100644 index 000000000..c08199498 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-1.png differ diff --git a/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-2.png b/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-2.png new file mode 100644 index 000000000..314102fa7 Binary files /dev/null and b/AppKit/Themes/Aristo2/Resources/datepicker-date-segment-2.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-attached-sheet-shadow.png b/AppKit/Themes/Aristo2/Resources/window-attached-sheet-shadow.png index b39cae110..eeab7d517 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-attached-sheet-shadow.png and b/AppKit/Themes/Aristo2/Resources/window-attached-sheet-shadow.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-bottom-center.png b/AppKit/Themes/Aristo2/Resources/window-standard-bottom-center.png index 39396fe31..7312a639d 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-bottom-center.png and b/AppKit/Themes/Aristo2/Resources/window-standard-bottom-center.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-bottom-left.png b/AppKit/Themes/Aristo2/Resources/window-standard-bottom-left.png index dab5660a0..e9e11451c 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-bottom-left.png and b/AppKit/Themes/Aristo2/Resources/window-standard-bottom-left.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-bottom-right.png b/AppKit/Themes/Aristo2/Resources/window-standard-bottom-right.png index 00a92564a..756701d20 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-bottom-right.png and b/AppKit/Themes/Aristo2/Resources/window-standard-bottom-right.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-center-center.png b/AppKit/Themes/Aristo2/Resources/window-standard-center-center.png index 1830f6d53..46b33352d 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-center-center.png and b/AppKit/Themes/Aristo2/Resources/window-standard-center-center.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-center-left.png b/AppKit/Themes/Aristo2/Resources/window-standard-center-left.png index cbffd9b5a..ad7cf8c28 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-center-left.png and b/AppKit/Themes/Aristo2/Resources/window-standard-center-left.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-center-right.png b/AppKit/Themes/Aristo2/Resources/window-standard-center-right.png index 92a277fbd..395fd0044 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-center-right.png and b/AppKit/Themes/Aristo2/Resources/window-standard-center-right.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-top-center.png b/AppKit/Themes/Aristo2/Resources/window-standard-top-center.png index a564ec3c4..0acc88870 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-top-center.png and b/AppKit/Themes/Aristo2/Resources/window-standard-top-center.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-top-left.png b/AppKit/Themes/Aristo2/Resources/window-standard-top-left.png index bc1d5b3a8..2a3df104f 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-top-left.png and b/AppKit/Themes/Aristo2/Resources/window-standard-top-left.png differ diff --git a/AppKit/Themes/Aristo2/Resources/window-standard-top-right.png b/AppKit/Themes/Aristo2/Resources/window-standard-top-right.png index 096e807e8..03bed6695 100644 Binary files a/AppKit/Themes/Aristo2/Resources/window-standard-top-right.png and b/AppKit/Themes/Aristo2/Resources/window-standard-top-right.png differ diff --git a/AppKit/Themes/Aristo2/ThemeDescriptors.j b/AppKit/Themes/Aristo2/ThemeDescriptors.j index c24f57c68..37a9bfae4 100644 --- a/AppKit/Themes/Aristo2/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo2/ThemeDescriptors.j @@ -29,6 +29,7 @@ @import @import @import +@import @import @import @import @@ -532,7 +533,7 @@ var themedButtonValues = nil, [@"bezel-color", bezelColor["@"], CPThemeStateBezeled], [@"bezel-color", bezelFocusedColor, CPThemeStateBezeled | CPThemeStateEditing], [@"bezel-color", bezelColor["disabled"], CPThemeStateBezeled | CPThemeStateDisabled], - [@"font", [CPFont systemFontOfSize:12.0], CPThemeStateBezeled], + [@"font", [CPFont systemFontOfSize:CPFontCurrentSystemSize], CPThemeStateBezeled], [@"content-inset", CGInsetMake(8.0, 7.0, 5.0, 10.0), CPThemeStateBezeled], [@"content-inset", CGInsetMake(8.0, 7.0, 5.0, 10.0), CPThemeStateBezeled | CPThemeStateEditing], @@ -546,20 +547,20 @@ var themedButtonValues = nil, [@"content-inset", CGInsetMake(0.0, 0.0, 0.0, 5.0), CPThemeStateTableDataView], [@"text-color", [CPColor colorWithCalibratedWhite:51.0 / 255.0 alpha:1.0], CPThemeStateTableDataView], - [@"text-color", [CPColor whiteColor], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView], - [@"font", [CPFont boldSystemFontOfSize:12.0], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView], + [@"text-color", [CPColor whiteColor], CPThemeStateTableDataView | CPThemeStateSelectedDataView], + [@"font", [CPFont systemFontOfSize:CPFontCurrentSystemSize], CPThemeStateTableDataView | CPThemeStateSelectedDataView], [@"text-color", [CPColor blackColor], CPThemeStateTableDataView | CPThemeStateEditing], - [@"text-color", [CPColor blackColor], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView | CPThemeStateEditable], + [@"text-color", [CPColor blackColor], CPThemeStateTableDataView | CPThemeStateSelectedDataView | CPThemeStateEditable], [@"content-inset", CGInsetMake(7.0, 7.0, 5.0, 10.0), CPThemeStateTableDataView | CPThemeStateEditable], - [@"font", [CPFont systemFontOfSize:12.0], CPThemeStateTableDataView | CPThemeStateEditing], + [@"font", [CPFont systemFontOfSize:CPFontCurrentSystemSize], CPThemeStateTableDataView | CPThemeStateEditing], [@"bezel-inset", CGInsetMake(-2.0, -2.0, -2.0, -2.0), CPThemeStateTableDataView | CPThemeStateEditing], [@"text-color", [CPColor colorWithCalibratedWhite:125.0 / 255.0 alpha:1.0], CPThemeStateTableDataView | CPThemeStateGroupRow], - [@"text-color", [CPColor colorWithCalibratedWhite:1.0 alpha:1.0], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedTableDataView], + [@"text-color", [CPColor colorWithCalibratedWhite:1.0 alpha:1.0], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedDataView], [@"text-shadow-color", [CPColor whiteColor], CPThemeStateTableDataView | CPThemeStateGroupRow], [@"text-shadow-offset", CGSizeMake(0, 1), CPThemeStateTableDataView | CPThemeStateGroupRow], - [@"text-shadow-color", [CPColor colorWithCalibratedWhite:0.0 alpha:0.6], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedTableDataView], - [@"font", [CPFont boldSystemFontOfSize:12.0], CPThemeStateTableDataView | CPThemeStateGroupRow] + [@"text-shadow-color", [CPColor colorWithCalibratedWhite:0.0 alpha:0.6], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedDataView], + [@"font", [CPFont boldSystemFontOfSize:CPFontCurrentSystemSize], CPThemeStateTableDataView | CPThemeStateGroupRow] ]; [self registerThemeValues:themedTextFieldValues forView:textfield]; @@ -652,6 +653,210 @@ var themedButtonValues = nil, return searchField; } ++ (CPDatePicker)themedDatePicker +{ + var datePicker = [[CPDatePicker alloc] initWithFrame:CGRectMake(40,140,300,29)], + + bezelColor = PatternColor( + "textfield-bezel-square{state}{position}.png", + { + states: ["", "disabled"], + positions: "#", + width: 4.0, + height: 4.0 + }), + + bezelColorDatePickerTextField = PatternColor( + [ + [@"datepicker-date-segment-0.png", 4.0, 18.0], + [@"datepicker-date-segment-1.png", 1.0, 18.0], + [@"datepicker-date-segment-2.png", 4.0, 18.0] + ], PatternIsHorizontal), + + themeValues = + [ + [@"bezel-color", bezelColor["@"], CPThemeStateBezeled], + [@"bezel-color", bezelColor["disabled"], CPThemeStateBezeled | CPThemeStateDisabled], + + [@"font", [CPFont boldSystemFontOfSize:13.0]], + [@"text-color", [CPColor colorWithWhite:0.2 alpha:0.8]], + [@"text-color", [CPColor colorWithWhite:0.2 alpha:0.5], CPThemeStateDisabled], + + [@"content-inset", CGInsetMake(6.0, 0.0, 0.0, 3.0), CPThemeStateNormal], + [@"content-inset", CGInsetMake(3.0, 0.0, 0.0, 3.0), CPThemeStateBezeled], + [@"bezel-inset", CGInsetMake(3.0, 0.0, 3.0, 0.0), CPThemeStateBezeled], + + [@"datepicker-textfield-bezel-color", [CPColor clearColor], CPThemeStateNormal], + [@"datepicker-textfield-bezel-color", bezelColorDatePickerTextField, CPThemeStateSelected], + [@"datepicker-textfield-bezel-color", [CPColor clearColor], CPThemeStateNormal | CPThemeStateDisabled], + [@"datepicker-textfield-bezel-color", [CPColor clearColor], CPThemeStateSelected | CPThemeStateDisabled], + + [@"min-size-datepicker-textfield", CGSizeMake(6.0, 18.0)], + + [@"separator-content-inset", CGInsetMake(0.0, -2.0, 0.0, -1.0)], + + [@"content-inset-datepicker-textfield", CGInsetMake(2.0, 2.0, 0.0, 1.0), CPThemeStateNormal], + [@"content-inset-datepicker-textfield-separator",CGInsetMake(2.0, 0.0, 0.0, 0.0), CPThemeStateNormal], + [@"content-inset-datepicker-textfield", CGInsetMake(2.0, 2.0, 0.0, 1.0) , CPThemeStateSelected], + [@"content-inset-datepicker-textfield-separator",CGInsetMake(2.0, 0.0, 0.0, 0.0), CPThemeStateSelected], + + [@"date-hour-margin", 7.0], + [@"stepper-margin", 5.0], + + [@"min-size", CGSizeMake(0.0, 29.0)], + [@"max-size", CGSizeMake(-1.0, 29.0)] + ]; + + [self registerThemeValues:themeValues forView:datePicker]; + + return datePicker; +} + ++ (CPDatePicker)themedDatePickerCalendar +{ + var datePicker = [[CPDatePicker alloc] initWithFrame:CGRectMake(40,140,300,29)], + + arrowImageLeft = PatternImage("datepicker-calendar-arrow-left.png", 7.0, 10.0), + arrowImageRight = PatternImage("datepicker-calendar-arrow-right.png", 7.0, 10.0), + circleImage = PatternImage("datepicker-circle-image.png", 9.0, 10.0), + + arrowImageLeftHighlighted = PatternImage("datepicker-calendar-arrow-left-highlighted.png", 7.0, 10.0), + arrowImageRightHighlighted = PatternImage("datepicker-calendar-arrow-right-highlighted.png", 7.0, 10.0), + circleImageHighlighted = PatternImage("datepicker-circle-image-highlighted.png", 9.0, 10.0), + + secondHandColor = PatternColor("datepicker-clock-second-hand.png", 89.0, 89.0), + minuteHandColor = PatternColor("datepicker-clock-minute-hand.png", 85.0, 85.0), + hourHandColor = PatternColor("datepicker-clock-hour-hand.png", 47.0, 47.0), + middleHandColor = PatternColor("datepicker-clock-middle-hand.png", 13.0, 13.0), + clockImageColor = PatternColor("datepicker-clock.png", 122.0, 123.0), + + secondHandColorDisabled = PatternColor("datepicker-clock-second-hand-disabled.png", 89.0, 89.0), + minuteHandColorDisabled = PatternColor("datepicker-clock-minute-hand-disabled.png", 85.0, 85.0), + hourHandColorDisabled = PatternColor("datepicker-clock-hour-hand-disabled.png", 47.0, 47.0), + middleHandColorDisabled = PatternColor("datepicker-clock-middle-hand-disabled.png", 13.0, 13.0), + clockImageColorDisabled = PatternColor("datepicker-clock-disabled.png", 122.0, 123.0), + + themeValues = + [ + [@"border-color", [CPColor colorWithCalibratedRed:217.0 / 255.0 green:217.0 / 255.0 blue:211.0 / 255.0 alpha:1.0], CPThemeStateNormal], + [@"border-color", [CPColor colorWithCalibratedRed:68.0 / 255.0 green:109.0 / 255.0 blue:198.0 / 255.0 alpha:1.0], CPThemeStateSelected], + [@"border-color", [CPColor colorWithCalibratedRed:217.0 / 255.0 green:217.0 / 255.0 blue:211.0 / 255.0 alpha:0.5], CPThemeStateNormal | CPThemeStateDisabled], + [@"border-color", [CPColor colorWithCalibratedRed:68.0 / 255.0 green:109.0 / 255.0 blue:198.0 / 255.0 alpha:0.5], CPThemeStateSelected | CPThemeStateDisabled], + + [@"bezel-color-calendar", [CPColor whiteColor]], + [@"bezel-color-calendar", [CPColor colorWithCalibratedRed:87.0 / 255.0 green:128.0 / 255.0 blue:216.0 / 255.0 alpha:1.0], CPThemeStateSelected], + [@"bezel-color-calendar", [CPColor colorWithCalibratedRed:87.0 / 255.0 green:128.0 / 255.0 blue:216.0 / 255.0 alpha:0.5], CPThemeStateSelected |CPThemeStateDisabled], + [@"bezel-color-clock", clockImageColor], + [@"bezel-color-clock", clockImageColorDisabled, CPThemeStateDisabled], + + [@"title-text-color", [CPColor colorWithCalibratedRed:79.0 / 255.0 green:79.0 / 255.0 blue:79.0 / 255.0 alpha:1.0]], + [@"title-text-shadow-color", [CPColor whiteColor]], + [@"title-text-shadow-offset", CGSizeMake(0,1)], + [@"title-font", [CPFont boldSystemFontOfSize:12.0]], + + [@"title-text-color", [CPColor colorWithCalibratedRed:79.0 / 255.0 green:79.0 / 255.0 blue:79.0 / 255.0 alpha:0.5], CPThemeStateDisabled], + [@"title-text-shadow-color", [CPColor whiteColor], CPThemeStateDisabled], + [@"title-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled], + [@"title-font", [CPFont boldSystemFontOfSize:12.0], CPThemeStateDisabled], + + [@"weekday-text-color", [CPColor colorWithCalibratedRed:79.0 / 255.0 green:79.0 / 255.0 blue:79.0 / 255.0 alpha:1.0]], + [@"weekday-text-shadow-color", [CPColor whiteColor]], + [@"weekday-text-shadow-offset", CGSizeMake(0,1)], + [@"weekday-font", [CPFont systemFontOfSize:11.0]], + + [@"weekday-text-color", [CPColor colorWithCalibratedRed:79.0 / 255.0 green:79.0 / 255.0 blue:79.0 / 255.0 alpha:0.5], CPThemeStateDisabled], + [@"weekday-text-shadow-color", [CPColor whiteColor], CPThemeStateDisabled], + [@"weekday-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled], + [@"weekday-font", [CPFont systemFontOfSize:11.0], CPThemeStateDisabled], + + [@"clock-text-color", [CPColor colorWithCalibratedRed:153.0 / 255.0 green:153.0 / 255.0 blue:153.0 / 255.0 alpha:1.0]], + [@"clock-text-shadow-color", [CPColor whiteColor]], + [@"clock-text-shadow-offset", CGSizeMake(0,1)], + [@"clock-font", [CPFont systemFontOfSize:11.0]], + + [@"clock-text-color", [CPColor colorWithCalibratedRed:153.0 / 255.0 green:153.0 / 255.0 blue:153.0 / 255.0 alpha:0.5], CPThemeStateDisabled], + [@"clock-text-shadow-color", [CPColor whiteColor], CPThemeStateDisabled], + [@"clock-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled], + [@"clock-font", [CPFont systemFontOfSize:11.0], CPThemeStateDisabled], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:34.0 / 255.0 green:34.0 / 255.0 blue:34.0 / 255.0 alpha:1.0], CPThemeStateNormal], + [@"tile-text-shadow-color", [CPColor whiteColor], CPThemeStateNormal], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateNormal], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateNormal], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:87.0 / 255.0 green:128.0 / 255.0 blue:216.0 / 255.0 alpha:1.0], CPThemeStateHighlighted], + [@"tile-text-shadow-color", [CPColor whiteColor], CPThemeStateHighlighted], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateHighlighted], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateHighlighted], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:87.0 / 255.0 green:128.0 / 255.0 blue:216.0 / 255.0 alpha:0.5], CPThemeStateHighlighted | CPThemeStateDisabled], + [@"tile-text-shadow-color", [CPColor whiteColor], CPThemeStateHighlighted | CPThemeStateDisabled], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateHighlighted | CPThemeStateDisabled], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateHighlighted | CPThemeStateDisabled], + + [@"tile-text-color", [CPColor whiteColor], CPThemeStateHighlighted | CPThemeStateSelected], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedRed:0.0 / 255.0 green:0.0 / 255.0 blue:0.0 / 255.0 alpha:0.2], CPThemeStateHighlighted | CPThemeStateSelected], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateHighlighted | CPThemeStateSelected], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateHighlighted | CPThemeStateSelected], + + [@"tile-text-color", [CPColor whiteColor], CPThemeStateSelected], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedRed:0.0 / 255.0 green:0.0 / 255.0 blue:0.0 / 255.0 alpha:0.2], CPThemeStateSelected], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateSelected], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateSelected], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:179.0 / 255.0 green:179.0 / 255.0 blue:179.0 / 255.0 alpha:1.0], CPThemeStateDisabled], + [@"tile-text-shadow-color", [CPColor whiteColor], CPThemeStateDisabled], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateDisabled], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:255.0 / 255.0 green:255.0 / 255.0 blue:255.0 / 255.0 alpha:0.5], CPThemeStateDisabled | CPThemeStateSelected | CPThemeStateHighlighted], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedRed:0.0 / 255.0 green:0.0 / 255.0 blue:0.0 / 255.0 alpha:0.2], CPThemeStateDisabled | CPThemeStateSelected | CPThemeStateHighlighted], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled | CPThemeStateSelected | CPThemeStateHighlighted], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateDisabled | CPThemeStateSelected | CPThemeStateHighlighted], + + [@"tile-text-color", [CPColor colorWithCalibratedRed:255.0 / 255.0 green:255.0 / 255.0 blue:255.0 / 255.0 alpha:0.5], CPThemeStateDisabled | CPThemeStateSelected], + [@"tile-text-shadow-color", [CPColor colorWithCalibratedRed:0.0 / 255.0 green:0.0 / 255.0 blue:0.0 / 255.0 alpha:0.2], CPThemeStateDisabled | CPThemeStateSelected], + [@"tile-text-shadow-offset", CGSizeMake(0,1), CPThemeStateDisabled | CPThemeStateSelected], + [@"tile-font", [CPFont systemFontOfSize:10.0], CPThemeStateDisabled | CPThemeStateSelected], + + [@"arrow-image-left", arrowImageLeft], + [@"arrow-image-right", arrowImageRight], + [@"arrow-image-left-highlighted", arrowImageLeftHighlighted], + [@"arrow-image-right-highlighted", arrowImageRightHighlighted], + [@"circle-image", circleImage], + [@"circle-image-highlighted", circleImageHighlighted], + [@"arrow-inset", CGInsetMake(9.0, 4.0, 0.0, 0.0)], + + [@"second-hand-color", secondHandColor], + [@"hour-hand-color", hourHandColor], + [@"middle-hand-color", middleHandColor], + [@"minute-hand-color", minuteHandColor], + + [@"second-hand-color", secondHandColorDisabled, CPThemeStateDisabled], + [@"hour-hand-color", hourHandColorDisabled, CPThemeStateDisabled], + [@"middle-hand-color", middleHandColorDisabled, CPThemeStateDisabled], + [@"minute-hand-color", minuteHandColorDisabled, CPThemeStateDisabled], + + [@"second-hand-size", CGSizeMake(89.0, 89.0)], + [@"hour-hand-size", CGSizeMake(47.0, 47.0)], + [@"middle-hand-size", CGSizeMake(13.0, 13.0)], + [@"minute-hand-size", CGSizeMake(85.0, 85.0)], + + [@"border-width", 1.0], + [@"size-header", CGSizeMake(141.0, 39.0)], + [@"size-tile", CGSizeMake(20.0, 18.0)], + [@"size-clock", CGSizeMake(122.0, 123.0)], + [@"size-calendar", CGSizeMake(141.0, 109.0)], + [@"min-size-calendar", CGSizeMake(141.0, 148.0)], + [@"max-size-calendar", CGSizeMake(141.0, 148.0)] + ]; + + [datePicker setDatePickerStyle:CPClockAndCalendarDatePickerStyle]; + [self registerThemeValues:themeValues forView:datePicker]; + + return datePicker; +} + + (CPTokenField)themedTokenField { var tokenfield = [[CPTokenField alloc] initWithFrame:CGRectMake(0.0, 0.0, 160.0, 29.0)], @@ -1303,8 +1508,8 @@ var themedButtonValues = nil, [0, 1], 2 ), - CPSourceListTopLineColor: [CPColor colorWithCalibratedRed:73.0 / 255.0 green:109.0 / 255.0 blue:187.0 / 255.0 alpha:1.0], - CPSourceListBottomLineColor: [CPColor colorWithCalibratedRed:44.0 / 255.0 green:79.0 / 255.0 blue:155.0 / 255.0 alpha:1.0], + CPSourceListTopLineColor: [CPColor colorWithCalibratedRed:70.0 / 255.0 green:107.0 / 255.0 blue:215.0 / 255.0 alpha:1.0], + CPSourceListBottomLineColor: [CPColor colorWithCalibratedRed:42.0 / 255.0 green:74.0 / 255.0 blue:177.0 / 255.0 alpha:1.0] }, themedTableViewValues = @@ -1773,7 +1978,7 @@ var themedButtonValues = nil, { var windowView = [[_CPWindowView alloc] initWithFrame:CGRectMakeZero(0.0, 0.0, 200, 200)], - sheetShadow = PatternColor(@"window-attached-sheet-shadow.png", 9, 8), + sheetShadow = PatternColor(@"window-attached-sheet-shadow.png", 1, 8), resizeIndicator = PatternImage(@"window-resize-indicator.png", 12, 12), shadowColor = PatternColor( @@ -1794,6 +1999,7 @@ var themedButtonValues = nil, [@"window-shadow-color", shadowColor], [@"resize-indicator", resizeIndicator], [@"attached-sheet-shadow-color", sheetShadow], + [@"shadow-height", 8], [@"size-indicator", CGSizeMake(12, 12)] ]; @@ -1890,7 +2096,6 @@ var themedButtonValues = nil, minimizeButtonImage = PatternImage(@"window-standard-minimize-button.png", 16, 16), minimizeButtonImageHighlighted = PatternImage(@"window-standard-minimize-button-highlighted.png", 16, 16), - sheetShadow = PatternColor(@"window-attached-sheet-shadow.png", 9, 8), resizeIndicator = PatternImage(@"window-resize-indicator.png", 12, 12), themeValues = @@ -1930,7 +2135,6 @@ var themedButtonValues = nil, [@"close-image-origin", CGPointMake(8.0, 10.0)], [@"resize-indicator", resizeIndicator], - [@"attached-sheet-shadow-color", sheetShadow], [@"size-indicator", CGSizeMake(12, 12)] ]; @@ -1951,13 +2155,9 @@ var themedButtonValues = nil, height: 5.0 }), - sheetShadow = PatternColor(@"window-attached-sheet-shadow.png", 9, 8), - themeValues = [ - [@"body-color", bezelColor], - [@"height-shadow", 8], - [@"attached-sheet-shadow-color", sheetShadow] + [@"body-color", bezelColor] ]; [self registerThemeValues:themeValues forView:docModalWindowView inherit:themedWindowViewValues]; @@ -2026,9 +2226,7 @@ var themedButtonValues = nil, themeValues = [ - [@"menu-item-selection-color", [CPColor colorWithHexString:@"5C85D8"]], - [@"menu-item-text-shadow-color", [CPColor colorWithCalibratedRed:26.0 / 255.0 green: 73.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]], - [@"horizontal-margin", 12.0], + [@"horizontal-margin", 9.0], [@"submenu-indicator-margin", 3.0], [@"vertical-margin", 4.0] ]; diff --git a/AppKit/_CPAutocompleteMenu.j b/AppKit/_CPAutocompleteMenu.j index ebd174944..04ee865e3 100644 --- a/AppKit/_CPAutocompleteMenu.j +++ b/AppKit/_CPAutocompleteMenu.j @@ -161,9 +161,9 @@ var _CPAutocompleteMenuMaximumHeight = 307; var dataView = [tableColumn dataView], fontNormal = [dataView valueForThemeAttribute:@"font" inState:CPThemeStateTableDataView], - fontSelected = [dataView valueForThemeAttribute:@"font" inState:CPThemeStateTableDataView | CPThemeStateSelectedTableDataView], + fontSelected = [dataView valueForThemeAttribute:@"font" inState:CPThemeStateTableDataView | CPThemeStateSelectedDataView], contentInsetNormal = [dataView valueForThemeAttribute:@"content-inset" inState:CPThemeStateTableDataView], - contentInsetSelected = [dataView valueForThemeAttribute:@"content-inset" inState:CPThemeStateTableDataView | CPThemeStateSelectedTableDataView]; + contentInsetSelected = [dataView valueForThemeAttribute:@"content-inset" inState:CPThemeStateTableDataView | CPThemeStateSelectedDataView]; var mergedString = contentArray.join("\n"); @@ -270,11 +270,25 @@ var _CPAutocompleteMenuMaximumHeight = 307; @implementation _CPAutocompleteWindow : CPPanel +- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask +{ + if (self = [super initWithContentRect:aContentRect styleMask:aStyleMask]) + _constrainsToUsableScreen = NO; + + return self; +} + - (BOOL)becomesKeyOnlyIfNeeded { return YES; } +- (BOOL)worksWhenModal +{ + // Windows which serve as auxiliary controls should work when modal. + return YES; +} + @end @implementation _CPNonFirstResponderTableView : CPTableView diff --git a/AppKit/_CPCornerView.j b/AppKit/_CPCornerView.j index da7dd48fe..02371b3c5 100644 --- a/AppKit/_CPCornerView.j +++ b/AppKit/_CPCornerView.j @@ -47,8 +47,8 @@ CGContextSetLineWidth(context, 1); CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"divider-color"]); - CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 0.5, ROUND(_CGRectGetMinY(aRect))); - CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 0.5, ROUND(_CGRectGetMaxY(aRect)) - 1.0); + CGContextMoveToPoint(context, CGRectGetMinX(aRect) + 0.5, ROUND(CGRectGetMinY(aRect))); + CGContextAddLineToPoint(context, CGRectGetMinX(aRect) + 0.5, ROUND(CGRectGetMaxY(aRect)) - 1.0); CGContextClosePath(context); CGContextStrokePath(context); diff --git a/AppKit/_CPImageAndTextView.j b/AppKit/_CPImageAndTextView.j index 131beeb61..f42dfadca 100644 --- a/AppKit/_CPImageAndTextView.j +++ b/AppKit/_CPImageAndTextView.j @@ -80,7 +80,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, if (self) { - _textShadowOffset = _CGSizeMakeZero(); + _textShadowOffset = CGSizeMakeZero(); [self setVerticalAlignment:CPTopVerticalTextAlignment]; if (aControl) @@ -277,10 +277,10 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, - (void)setTextShadowOffset:(CGSize)anOffset { - if (_CGSizeEqualToSize(_textShadowOffset, anOffset)) + if (CGSizeEqualToSize(_textShadowOffset, anOffset)) return; - _textShadowOffset = _CGSizeMakeCopy(anOffset); + _textShadowOffset = CGSizeMakeCopy(anOffset); [self setNeedsLayout]; } @@ -294,7 +294,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, { [self layoutIfNeeded]; - var textFrame = _CGRectMakeZero(); + var textFrame = CGRectMakeZero(); #if PLATFORM(DOM) if (_DOMTextElement) @@ -319,9 +319,6 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, if (_image == anImage) return; - if ([_image delegate] === self) - [[CPNotificationCenter defaultCenter] removeObserver:self name:CPImageDidLoadNotification object:_image]; - _image = anImage; _flags |= _CPImageAndTextViewImageChangedFlag; @@ -347,6 +344,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, - (void)imageDidLoad:(CPNotification)aNotification { + [[CPNotificationCenter defaultCenter] removeObserver:self name:CPImageDidLoadNotification object:_image]; _flags |= _CPImageAndTextViewImageChangedFlag; [self setNeedsLayout]; } @@ -602,7 +600,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, } var size = [self bounds].size, - textRect = _CGRectMake(0.0, 0.0, size.width, size.height); + textRect = CGRectMake(0.0, 0.0, size.width, size.height); if (hasDOMImageElement) { @@ -680,10 +678,10 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, if (hasDOMTextElement) { - var textRectX = _CGRectGetMinX(textRect), - textRectY = _CGRectGetMinY(textRect), - textRectWidth = _CGRectGetWidth(textRect), - textRectHeight = _CGRectGetHeight(textRect); + var textRectX = CGRectGetMinX(textRect), + textRectY = CGRectGetMinY(textRect), + textRectWidth = CGRectGetWidth(textRect), + textRectHeight = CGRectGetHeight(textRect); if (textRectWidth <= 0 || textRectHeight <= 0) { @@ -753,7 +751,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, - (void)sizeToFit { - var size = _CGSizeMakeZero(); + var size = CGSizeMakeZero(); if ((_imagePosition !== CPNoImage) && _image) { diff --git a/AppKit/_CPPopUpList.j b/AppKit/_CPPopUpList.j index 024bc291a..2dfbce85e 100644 --- a/AppKit/_CPPopUpList.j +++ b/AppKit/_CPPopUpList.j @@ -852,6 +852,14 @@ var _CPPopUpListDataSourceKey = @"_CPPopUpListDataSourceKey", @implementation _CPPopUpPanel : CPPanel +- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask +{ + if (self = [super initWithContentRect:aContentRect styleMask:aStyleMask]) + _constrainsToUsableScreen = NO; + + return self; +} + - (void)sendEvent:(CPEvent)anEvent { var type = [anEvent type]; diff --git a/AppKit/_CPPopoverWindow.j b/AppKit/_CPPopoverWindow.j index d3e2b16e9..b16b35e67 100644 --- a/AppKit/_CPPopoverWindow.j +++ b/AppKit/_CPPopoverWindow.j @@ -182,16 +182,15 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0, { var mainWindow = [positioningView window], platformWindow = [mainWindow platformWindow], - nativeRect = [platformWindow nativeContentRect], + nativeRect = [platformWindow usableContentFrame], 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, - menuBarHeight = [CPMenu menuBarVisible] ? [CPMenu menuBarHeight] : 0; + 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 += platformRect.size.width; @@ -243,34 +242,34 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0, [_windowView setArrowOffsetY:0]; [_windowView setPreferredEdge:edge]; - if (origin.x < 0) + if (origin.x < CGRectGetMinX(nativeRect)) { [_windowView setArrowOffsetX:origin.x]; - origin.x = 0; + origin.x = CGRectGetMinX(nativeRect); } - if (origin.x + frameSize.width > nativeRect.size.width) + if (origin.x + frameSize.width > CGRectGetMaxX(nativeRect)) { - [_windowView setArrowOffsetX:(origin.x + frameSize.width - nativeRect.size.width)]; - origin.x = nativeRect.size.width - frameSize.width; + [_windowView setArrowOffsetX:(origin.x + frameSize.width - CGRectGetMaxX(nativeRect))]; + origin.x = CGRectGetMaxX(nativeRect) - frameSize.width; } - if (origin.y < 0) + if (origin.y < CGRectGetMinY(nativeRect)) { - [_windowView setArrowOffsetY:origin.y - menuBarHeight]; - origin.y = menuBarHeight; + [_windowView setArrowOffsetY:origin.y - CGRectGetMinY(nativeRect)]; + origin.y = CGRectGetMinY(nativeRect); } - if (origin.y + frameSize.height > nativeRect.size.height) + if (origin.y + frameSize.height > CGRectGetMaxY(nativeRect)) { - [_windowView setArrowOffsetY:(frameSize.height + origin.y - nativeRect.size.height)]; - origin.y = nativeRect.size.height - frameSize.height; + [_windowView setArrowOffsetY:(frameSize.height + origin.y - CGRectGetMaxY(nativeRect))]; + origin.y = CGRectGetMaxY(nativeRect) - frameSize.height; } switch (edge) { case CPMaxXEdge: - if (origin.x >= _CGRectGetMaxX(platformRect)) + if (origin.x >= CGRectGetMaxX(platformRect)) return origin; break; @@ -280,7 +279,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0, break; case CPMaxYEdge: - if (origin.y >= _CGRectGetMaxY(platformRect)) + if (origin.y >= CGRectGetMaxY(platformRect)) return origin; break; @@ -317,7 +316,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0, { var wasVisible = [self isVisible]; - if (!aRect || _CGRectIsEmpty(aRect)) + if (!aRect || CGRectIsEmpty(aRect)) aRect = [positioningView bounds]; var point = [self computeOriginFromRect:aRect ofView:positioningView preferredEdge:anEdge]; @@ -543,6 +542,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0, #endif [_targetView removeObserver:self forKeyPath:@"frame"]; + [_parentWindow removeChildWindow:self]; [super _orderOutRecursively:recursive]; _shouldPerformAnimation = YES; @@ -569,7 +569,9 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0, var mouseWindow = [anEvent window]; - if (mouseWindow === self) + // Consider clicks in child windows to be "inside". This keeps a transient popover from + // closing if e.g. the window containing the menu of a token field is clicked. + if (mouseWindow === self || [mouseWindow _hasAncestorWindow:self]) [self _trapNextMouseDown]; else { diff --git a/AppKit/_CPToolTip.j b/AppKit/_CPToolTip.j index 4f271cc0e..a669d4cf0 100644 --- a/AppKit/_CPToolTip.j +++ b/AppKit/_CPToolTip.j @@ -167,6 +167,8 @@ var _CPToolTipHeight = 24.0, if (self = [super initWithContentRect:toolTipFrame styleMask:aStyleMask]) { + _constrainsToUsableScreen = NO; + textFrameSize.height += 4; _content = [CPTextField labelWithTitle:aString]; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5a04118e8..1bde4969b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,43 +33,127 @@ Some things are difficult to unit test in a way that's worthwhile. For instance The style and format of your commit messages are very important to the health of the project. A good commit message helps not only users reading the release notes, but also your fellow Cappuccino developers as they review `git log` or `git blame` to figure out what you were doing. -This is the preferred format of commit messages for complex changes: +Commit messages should be in the following format: - [New:] + : - [OPTIONAL DESCRIPTION ABOUT WHAT THIS THING DOES.] + -Or for fixes: +