From e95c2b9efce252b2f76fdff7ffb1b12bc06c9d83 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Wed, 17 Sep 2008 22:39:25 -0700 Subject: [PATCH 1/5] Various fixes to support creating images with specifying the size upfront. [#41 milestone:0.5.2 state:resolved]; [#20 milestone:0.5.2 state:resolved]; --- AppKit/CPImage.j | 13 ++++++-- AppKit/CPImageView.j | 51 +++++++++++++++++++++---------- Foundation/CPNotificationCenter.j | 8 ++--- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/AppKit/CPImage.j b/AppKit/CPImage.j index f51d44805..b5baef554 100644 --- a/AppKit/CPImage.j +++ b/AppKit/CPImage.j @@ -20,10 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -import -import import +import +import import +import import "CPGeometry.j" @@ -35,6 +36,8 @@ CPImageLoadStatusInvalidData = 4; CPImageLoadStatusUnexpectedEOF = 5; CPImageLoadStatusReadError = 6; +CPImageDidLoadNotification = @"CPImageDidLoadNotification"; + @implementation CPBundle (CPImageAdditions) - (CPString)pathForResource:(CPString)aFilename @@ -219,7 +222,11 @@ CPImageLoadStatusReadError = 6; // FIXME: IE is wrong on image sizes???? if (!_size || (_size.width == -1 && _size.height == -1)) _size = CGSizeMake(_image.width, _image.height); - + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPImageDidLoadNotification + object:self]; + if ([_delegate respondsToSelector:@selector(imageDidLoad:)]) [_delegate imageDidLoad:self]; diff --git a/AppKit/CPImageView.j b/AppKit/CPImageView.j index 6aa860c5c..5cba2ae88 100644 --- a/AppKit/CPImageView.j +++ b/AppKit/CPImageView.j @@ -20,8 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -import "CPImage.j" +import + import "CPControl.j" +import "CPImage.j" import "CPShadowView.j" #include "Platform/Platform.h" @@ -110,20 +112,35 @@ var LEFT_SHADOW_INSET = 3.0, if (_image == anImage) return; + var center = [CPNotificationCenter defaultCenter]; + + if (_image) + [center removeObserver:self name:CPImageDidLoadNotification object:_image]; + _image = anImage; - _DOMImageElement.src = [anImage filename]; + + var size = [_image size]; - if (_imageScaling == CPScaleNone && _image) + if (size && size.width == -1 && size.height == -1) { - var size = [_image size]; + [center addObserver:self selector:@selector(imageDidLoad:) name:CPImageDidLoadNotification object:_image]; + + _DOMImageElement.width = 0; + _DOMImageElement.height = 0; - _DOMImageElement.width = ROUND(size.width); - _DOMImageElement.height = ROUND(size.height); + [_shadowView setHidden:YES]; } - + else + { + [self hideOrDisplayContents]; + [self tile]; + } +} + +- (void)imageDidLoad:(CPNotification)aNotification +{ [self hideOrDisplayContents]; - [self tile]; } @@ -181,13 +198,6 @@ var LEFT_SHADOW_INSET = 3.0, { CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, 0.0, 0.0); } - else if (_imageScaling == CPScaleNone && _image) - { - var size = [_image size]; - - _DOMImageElement.width = ROUND(size.width); - _DOMImageElement.height = ROUND(size.height); - } [self tile]; } @@ -240,7 +250,7 @@ var LEFT_SHADOW_INSET = 3.0, { if (!_image) return; - + var bounds = [self bounds], x = 0.0, y = 0.0, @@ -260,6 +270,9 @@ var LEFT_SHADOW_INSET = 3.0, { var size = [_image size]; + if (size.width == -1 && size.height == -1) + return; + if (_imageScaling == CPScaleProportionally) { // The max size it can be is size.width x size.height, so only @@ -289,6 +302,12 @@ var LEFT_SHADOW_INSET = 3.0, height = size.height; } + if (_imageScaling == CPScaleNone) + { + _DOMImageElement.width = ROUND(size.width); + _DOMImageElement.height = ROUND(size.height); + } + var x = (boundsWidth - width) / 2.0, y = (boundsHeight - height) / 2.0; diff --git a/Foundation/CPNotificationCenter.j b/Foundation/CPNotificationCenter.j index f0f301755..c3b166fad 100644 --- a/Foundation/CPNotificationCenter.j +++ b/Foundation/CPNotificationCenter.j @@ -219,7 +219,7 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ while (key = [keys nextObject]) { var observers = [_objectObservers objectForKey:key], - count = observers.length; + count = observers ? observers.length : 0; while (count--) if ([observers[count] observer] == anObserver) @@ -231,7 +231,7 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ observers.splice(count, 1); } - if (observers.length == 0) + if (!observers || observers.length == 0) removedKeys.push(key); } } @@ -239,7 +239,7 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ { var key = [anObject hash], observers = [_objectObservers objectForKey:key]; - count = observers.length; + count = observers ? observers.length : 0; while (count--) if ([observers[count] observer] == anObserver) @@ -251,7 +251,7 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ observers.splice(count, 1) } - if (observers.length == 0) + if (!observers || observers.length == 0) removedKeys.push(key); } From 0ee572c09418d38f440c3a1adc491dbeb501153b Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Thu, 18 Sep 2008 00:46:05 -0700 Subject: [PATCH 2/5] CPSplitView updated to draw dividers in drawDividerInRect, and use it's own runloop. [#50 state:resolved responsible:tlrobinson] [#51 state:resolved responsible:tlrobinson] --- AppKit/CPSplitView.j | 191 +++++++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 87 deletions(-) diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index 97bff90a7..adafffca9 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -35,17 +35,19 @@ var CPSplitViewHorizontalImage = nil, @implementation CPSplitView : CPView { - id _delegate; - BOOL _isVertical; - BOOL _isPaneSplitter; + id _delegate; + BOOL _isVertical; + BOOL _isPaneSplitter; - int _currentDivider; - float _initialOffset; + int _currentDivider; + float _initialOffset; - CPString _originComponent; - CPString _sizeComponent; + CPString _originComponent; + CPString _sizeComponent; - CPArray _DOMDividerElements; + CPArray _DOMDividerElements; + CPString _dividerImagePath; + int _drawingDivider; } /* @@ -92,6 +94,7 @@ var CPSplitViewHorizontalImage = nil, _originComponent = [self isVertical] ? "x" : "y"; _sizeComponent = [self isVertical] ? "width" : "height"; + _dividerImagePath = [self isVertical] ? [CPSplitViewVerticalImage filename] : [CPSplitViewHorizontalImage filename]; [self adjustSubviews]; } @@ -162,33 +165,30 @@ var CPSplitViewHorizontalImage = nil, - (void)drawRect:(CGRect)rect { -#if PLATFORM(DOM) - var dividerPath = [self isVertical] ? [CPSplitViewVerticalImage filename] : [CPSplitViewHorizontalImage filename]; - var count = [_subviews count]; - for (var i = 0; i < count; i++) + for (var _drawingDivider = 0; _drawingDivider < count-1; _drawingDivider++) { - if (!_DOMDividerElements[i]) - { - _DOMDividerElements[i] = document.createElement("div"); - _DOMDividerElements[i].style.cursor = "move"; - _DOMDividerElements[i].style.position = "absolute"; - _DOMDividerElements[i].style.backgroundRepeat = "repeat"; - CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[i]); - } - - var frame = [self rectOfDividerAtIndex:i]; - CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[i], NULL, _CGRectGetMinX(frame), _CGRectGetMinY(frame)); - CPDOMDisplayServerSetStyleSize(_DOMDividerElements[i], _CGRectGetWidth(frame), _CGRectGetHeight(frame)); - - _DOMDividerElements[i].style.backgroundImage = "url('"+dividerPath+"')"; + [self drawDividerInRect:[self rectOfDividerAtIndex:_drawingDivider]]; } -#endif } - (void)drawDividerInRect:(CGRect)aRect { - // TODO: figure out a way to "draw" dividers using DOM element +#if PLATFORM(DOM) + if (!_DOMDividerElements[_drawingDivider]) + { + _DOMDividerElements[_drawingDivider] = document.createElement("div"); + _DOMDividerElements[_drawingDivider].style.cursor = "move"; + _DOMDividerElements[_drawingDivider].style.position = "absolute"; + _DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat"; + CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]); + } + + CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect)); + CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); + + _DOMDividerElements[_drawingDivider].style.backgroundImage = "url('"+_dividerImagePath+"')"; +#endif } - (BOOL)cursorAtPoint:(CPPoint)aPoint hitDividerAtIndex:(int)anIndex @@ -207,72 +207,89 @@ var CPSplitViewHorizontalImage = nil, return CGRectContainsPoint(effectiveRect, aPoint) || (additionalRect && CGRectContainsPoint(additionalRect, aPoint)); } -- (void)mouseDown:(CPEvent)theEvent -{ - var location = [theEvent locationInWindow], - point = [self convertPoint:location fromView:nil]; - - for (var i = 0; i < [_subviews count] - 1; i++) - { - var frame = [_subviews[i] frame], - startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent]; - - if ([self cursorAtPoint:point hitDividerAtIndex:i]) - { - if ([theEvent clickCount] == 2 && - [_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] && - [_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)]) - { - var minPosition = [self minPossiblePositionOfDividerAtIndex:i], - maxPosition = [self maxPossiblePositionOfDividerAtIndex:i]; - - if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i]) - { - if ([self isSubviewCollapsed:_subviews[i]]) - [self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i]; - else - [self setPosition:minPosition ofDividerAtIndex:i]; - } - else if ([_delegate splitView:self canCollapseSubview:_subviews[i+1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i+1] forDoubleClickOnDividerAtIndex:i]) - { - if ([self isSubviewCollapsed:_subviews[i+1]]) - [self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i]; - else - [self setPosition:maxPosition ofDividerAtIndex:i]; - } - } - else - { - _currentDivider = i; - _initialOffset = startPosition - point[_originComponent]; - [self _postNotificationWillResize]; +/* + Tracks the divider. + @param anEvent the input event +*/ +- (void)trackDivider:(CPEvent)anEvent +{ + var type = [anEvent type]; + + if (type == CPLeftMouseUp) + { + if (_currentDivider != CPNotFound) + { + _currentDivider = CPNotFound; + [self _postNotificationDidResize]; + } + + return; + } + + if (type == CPLeftMouseDown) + { + var location = [anEvent locationInWindow], + point = [self convertPoint:location fromView:nil]; + + _currentDivider = CPNotFound; + for (var i = 0; i < [_subviews count] - 1; i++) + { + var frame = [_subviews[i] frame], + startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent]; + + if ([self cursorAtPoint:point hitDividerAtIndex:i]) + { + if ([anEvent clickCount] == 2 && + [_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] && + [_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)]) + { + var minPosition = [self minPossiblePositionOfDividerAtIndex:i], + maxPosition = [self maxPossiblePositionOfDividerAtIndex:i]; + + if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i]) + { + if ([self isSubviewCollapsed:_subviews[i]]) + [self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i]; + else + [self setPosition:minPosition ofDividerAtIndex:i]; + } + else if ([_delegate splitView:self canCollapseSubview:_subviews[i+1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i+1] forDoubleClickOnDividerAtIndex:i]) + { + if ([self isSubviewCollapsed:_subviews[i+1]]) + [self setPosition:(minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i]; + else + [self setPosition:maxPosition ofDividerAtIndex:i]; + } + } + else + { + _currentDivider = i; + _initialOffset = startPosition - point[_originComponent]; + + [self _postNotificationWillResize]; + } } - - return; } } - _currentDivider = CPNotFound; + + else if (type == CPLeftMouseDragged) + { + if (_currentDivider != CPNotFound) + { + var location = [anEvent locationInWindow], + point = [self convertPoint:location fromView:nil]; + + [self setPosition:(point[_originComponent] + _initialOffset) ofDividerAtIndex:_currentDivider]; + } + } + + [CPApp setTarget:self selector:@selector(trackDivider:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; } -- (void)mouseDragged:(CPEvent)theEvent +- (void)mouseDown:(CPEvent)anEvent { - if (_currentDivider != CPNotFound) - { - var location = [theEvent locationInWindow], - point = [self convertPoint:location fromView:nil]; - - [self setPosition:(point[_originComponent] + _initialOffset) ofDividerAtIndex:_currentDivider]; - } -} - -- (void)mouseUp:(CPEvent)theEvent -{ - if (_currentDivider != CPNotFound) - { - _currentDivider = CPNotFound; - [self _postNotificationDidResize]; - } + [self trackDivider:anEvent]; } - (float)maxPossiblePositionOfDividerAtIndex:(int)dividerIndex From 08d0dfd190cda41e895e9dfd570682e1e98aa360 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 18 Sep 2008 15:55:12 -0700 Subject: [PATCH 3/5] Remove the alert that was added. --- AppKit/CPControl.j | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index a035f5467..421b89b08 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -253,8 +253,8 @@ var CPControlBlackColor = [CPColor blackColor]; - (void)mouseUp:(CPEvent)anEvent { - if (_sendActionOn & CPLeftMouseUpMask && CPRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])){alert([_target description] + " : " + _action); - [self sendAction:_action to:_target];} + if (_sendActionOn & CPLeftMouseUpMask && CPRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])) + [self sendAction:_action to:_target]; [super mouseUp:anEvent]; } From 07d4ebdf9f0526e5e3575528c8c702d59e65ec33 Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Thu, 18 Sep 2008 16:33:01 -0700 Subject: [PATCH 4/5] Tests README --- Tests/README | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Tests/README diff --git a/Tests/README b/Tests/README new file mode 100644 index 000000000..b81dbe228 --- /dev/null +++ b/Tests/README @@ -0,0 +1,5 @@ +Requires objj be installed, as well as ojunit, located at http://github.com/280north/ojunit + +Run individual tests using a command similar to the following: + + objj ojunit/OJTestRunnerText.j cappuccino/Tests/Foundation/CPDateTest.j From f9e6cf3da98e3bc217382c26e9415a0b4ec6839d Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 18 Sep 2008 16:38:41 -0700 Subject: [PATCH 5/5] Fix infinite loop in CPTextField, add selectText: [#55 state:resolved] --- AppKit/CPTextField.j | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 900015de8..da3d9fdd2 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -140,7 +140,7 @@ var _CPTextFieldSquareBezelColor = nil; - (id)initWithFrame:(CGRect)aFrame { self = [super initWithFrame:aFrame]; - + if (self) { _value = @""; @@ -432,7 +432,7 @@ var _CPTextFieldSquareBezelColor = nil; return [[self class] _inputElement].value; #endif - return [self stringValue]; + return [super stringValue]; } /* @@ -469,6 +469,19 @@ var _CPTextFieldSquareBezelColor = nil; #endif } +/* + Select all the text in the CPTextField. +*/ +- (void)selectText:(id)sender +{ +#if PLATFORM(DOM) + var element = [[self class] _inputElement]; + + if (element.parentNode == _DOMElement && ([self isEditable] || [self isSelectable])) + element.select(); +#endif +} + @end var CPTextFieldIsSelectableKey = @"CPTextFieldIsSelectableKey",