diff --git a/AppKit/CPBox.j b/AppKit/CPBox.j index 1091c860a..20bd7f30a 100644 --- a/AppKit/CPBox.j +++ b/AppKit/CPBox.j @@ -27,20 +27,20 @@ // CPBorderType CPNoBorder = 0; -CPLineBorder = 1; +CPLineBorder = 1; CPBezelBorder = 2; CPGrooveBorder = 3; @implementation CPBox : CPView { CPBorderType _borderType; - + CPColor _borderColor; CPColor _fillColor; - + float _cornerRadius; float _borderWidth; - + CPSize _contentMargin; CPView _contentView; } @@ -53,26 +53,27 @@ CPGrooveBorder = 3; [box setFrameFromContentFrame:[aView frame]]; [enclosingView replaceSubview:aView with:box]; - + [box setContentView:aView]; - + return box; } - (id)initWithFrame:(CPRect)frameRect { self = [super initWithFrame:frameRect]; - + if (self) { - _fillColor = [CPColor clearColor]; + _borderType = CPBezelBorder; + _fillColor = [CPColor colorWithWhite:0.75 alpha:0.1]; _borderColor = [CPColor blackColor]; _borderWidth = 1.0; _contentMargin = _CGSizeMake(0.0, 0.0); _contentView = [[CPView alloc] initWithFrame:[self bounds]]; - + [_contentView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable]; [self addSubview:_contentView]; [_contentView setAutoresizesSubviews:YES]; @@ -167,12 +168,11 @@ CPGrooveBorder = 3; return; [aView setFrame:_CGRectInset([self bounds], _contentMargin.width + _borderWidth, _contentMargin.height + _borderWidth)]; + [aView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable]; + [aView setAutoresizesSubviews:YES]; [self replaceSubview:_contentView with:aView]; - - _contentView = aView; - [_contentView setAutoresizesSubviews:YES]; - [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + _contentView = aView; } - (CPSize)contentViewMargins @@ -184,7 +184,7 @@ CPGrooveBorder = 3; { if (size.width < 0 || size.height < 0) [CPException raise:CPGenericException reason:@"Margins must be positive"]; - + _contentMargin = _CGSizeMakeCopy(size); [self setNeedsDisplay:YES]; } @@ -198,10 +198,10 @@ CPGrooveBorder = 3; - (void)sizeToFit { var contentFrameSize = [_contentView frameSize]; - - [self setFrameSize:_CGSizeMake(contentFrameSize.width + (_contentMargin.width * 2), + + [self setFrameSize:_CGSizeMake(contentFrameSize.width + (_contentMargin.width * 2), contentFrameSize.height + (_contentMargin.height * 2))]; - + [_contentView setFrameOrigin:_CGPointMake(_contentMargin.width, _contentMargin.height)]; } @@ -221,7 +221,7 @@ CPGrooveBorder = 3; case CPNoBorder: case CPLineBorder: CGContextFillRoundedRectangleInRect(context, fillRect, _cornerRadius, YES, YES, YES, YES); - + if (_borderType === CPLineBorder) CGContextStrokeRoundedRectangleInRect(context, strokeRect, _cornerRadius, YES, YES, YES, YES); break; @@ -254,17 +254,17 @@ var CPBoxBorderTypeKey = @"CPBoxBorderTypeKey", if (self) { _borderType = [aCoder decodeIntForKey:CPBoxBorderTypeKey]; - + _borderColor = [aCoder decodeObjectForKey:CPBoxBorderColorKey]; _fillColor = [aCoder decodeObjectForKey:CPBoxFillColorKey]; _cornerRadius = [aCoder decodeFloatForKey:CPBoxCornerRadiusKey]; _borderWidth = [aCoder decodeFloatForKey:CPBoxBorderWidthKey]; - + _contentMargin = [aCoder decodeSizeForKey:CPBoxContentMarginKey]; - + _contentView = [self subviews][0]; - + [self setAutoresizesSubviews:YES]; [_contentView setAutoresizesSubviews:YES]; [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; @@ -276,15 +276,15 @@ var CPBoxBorderTypeKey = @"CPBoxBorderTypeKey", - (void)encodeWithCoder:(CPCoder)aCoder { [super encodeWithCoder:aCoder]; - + [aCoder encodeInt:_borderType forKey:CPBoxBorderTypeKey]; - + [aCoder encodeObject:_borderColor forKey:CPBoxBorderColorKey]; [aCoder encodeObject:_fillColor forKey:CPBoxFillColorKey]; [aCoder encodeFloat:_cornerRadius forKey:CPBoxCornerRadiusKey]; [aCoder encodeFloat:_borderWidth forKey:CPBoxBorderWidthKey]; - + [aCoder encodeSize:_contentMargin forKey:CPBoxContentMarginKey]; } diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 414249a0b..3fcd87c42 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -1253,34 +1253,84 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt CGContextAddLineToPoint(context, 9.0, 0.0); CGContextAddLineToPoint(context, 4.5, 8.0); CGContextAddLineToPoint(context, 0.0, 0.0); - + CGContextClosePath(context); - CGContextSetFillColor(context, - colorForDisclosureTriangle([self hasThemeState:CPThemeStateSelected], + CGContextSetFillColor(context, + colorForDisclosureTriangle([self hasThemeState:CPThemeStateSelected], [self hasThemeState:CPThemeStateHighlighted])); CGContextFillPath(context); - - + + CGContextBeginPath(context); CGContextMoveToPoint(context, 0.0, 0.0); if(_angle === 0.0) { CGContextAddLineToPoint(context, 4.5, 8.0); CGContextAddLineToPoint(context, 9.0, 0.0); - } else { + } else { CGContextAddLineToPoint(context, 4.5, 8.0); - } + } CGContextSetStrokeColor(context, [CPColor colorWithCalibratedWhite:1.0 alpha: 0.8]); CGContextStrokePath(context); } @end + +var CPOutlineViewIndentationPerLevelKey = @"CPOutlineViewIndentationPerLevelKey", + CPOutlineViewOutlineTableColumnKey = @"CPOutlineViewOutlineTableColumnKey", + CPOutlineViewDataSourceKey = @"CPOutlineViewDataSourceKey", + CPOutlineViewDelegateKey = @"CPOutlineViewDelegateKey"; + +@implementation CPOutlineView (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + // The root item has weight "0", thus represents the weight solely of its descendants. + _rootItemInfo = { isExpanded:YES, isExpandable:NO, level:-1, row:-1, children:[], weight:0 }; + + _itemsForRows = []; + _itemInfosForItems = { }; + _disclosureControlsForRows = []; + + [self setIndentationMarkerFollowsDataView:YES]; + [self setDisclosureControlPrototype:[[CPDisclosureButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)]]; + + _outlineTableColumn = [aCoder decodeObjectForKey:CPOutlineViewOutlineTableColumnKey]; + _indentationPerLevel = [aCoder decodeFloatForKey:CPOutlineViewIndentationPerLevelKey]; + + _outlineViewDataSource = [aCoder decodeObjectForKey:CPOutlineViewDataSourceKey]; + _outlineViewDelegate = [aCoder decodeObjectForKey:CPOutlineViewDelegateKey]; + + [super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [super encodeWithCoder:aCoder]; + + [aCoder encodeObject:_outlineTableColumn forKey:CPOutlineViewOutlineTableColumnKey]; + [aCoder encodeFloat:_indentationPerLevel forKey:CPOutlineViewIndentationPerLevelKey]; + + [aCoder encodeObject:_outlineViewDataSource forKey:CPOutlineViewDataSourceKey]; + [aCoder encodeObject:_outlineViewDelegate forKey:CPOutlineViewDelegateKey]; +} + +@end + + var colorForDisclosureTriangle = function(isSelected, isHighlighted) { - return isSelected - ? (isHighlighted + return isSelected + ? (isHighlighted ? [CPColor colorWithCalibratedWhite:0.9 alpha: 1.0] - : [CPColor colorWithCalibratedWhite:1.0 alpha: 1.0]) - : (isHighlighted - ? [CPColor colorWithCalibratedWhite:0.4 alpha: 1.0] + : [CPColor colorWithCalibratedWhite:1.0 alpha: 1.0]) + : (isHighlighted + ? [CPColor colorWithCalibratedWhite:0.4 alpha: 1.0] : [CPColor colorWithCalibratedWhite:0.5 alpha: 1.0]); } diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 8066cafe5..c153dda8a 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -1846,6 +1846,9 @@ setBoundsOrigin: - (void)displayRectIgnoringOpacity:(CGRect)aRect inContext:(CPGraphicsContext)aGraphicsContext { + if ([self isHidden]) + return; + #if PLATFORM(DOM) [self lockFocus]; diff --git a/Foundation/CPDictionary.j b/Foundation/CPDictionary.j index 4fd2d46d8..dcbb4c627 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -337,6 +337,35 @@ return values; } +/*! + Returns a new array containing the keys corresponding to all occurrences of a given object in the receiver. + @param anObject The value to look for in the receiver. + @return A new array containing the keys corresponding to all occurrences of anObject in the receiver. If no object matching anObject is found, returns an empty array. + + Each object in the receiver is sent an isEqual: message to determine if itŐs equal to anObject. + If the check for isEqual fails a check is made to see if the two objects are the same object. This provides compatability for JSObjects. +*/ +- (CPArray)allKeysForObject:(id)anObject +{ + var count = _keys.length, + index = 0, + matchingKeys = [], + thisKey = nil, + thisValue = nil; + + for (; index < count; ++index) + { + thisKey = _keys[index], + thisValue = _buckets[thisKey]; + if (thisValue.isa && anObject && anObject.isa && [thisValue respondsToSelector:@selector(isEqual:)] && [thisValue isEqual:anObject]) + matchingKeys.push(thisKey); + else if (thisValue === anObject) + matchingKeys.push(thisKey); + } + + return matchingKeys; +} + /*! Returns an enumerator that enumerates over all the dictionary's keys. */ @@ -425,7 +454,7 @@ @param aKey the key for the object's entry @return the object for the entry */ -- (id)objectForKey:(CPString)aKey +- (id)objectForKey:(id)aKey { var object = _buckets[aKey]; diff --git a/Tests/Foundation/CPDictionaryTest.j b/Tests/Foundation/CPDictionaryTest.j index d520f7359..e697e2c1c 100644 --- a/Tests/Foundation/CPDictionaryTest.j +++ b/Tests/Foundation/CPDictionaryTest.j @@ -17,7 +17,7 @@ } } - string_dict = [[CPDictionary alloc] initWithObjects:[@"1", @"2"] forKeys:[@"key1", @"key2"]]; + string_dict = [[CPDictionary alloc] initWithObjects:[@"1", @"2", @"This is a String", @"This is a String"] forKeys:[@"key1", @"key2", @"key3", @"key4"]]; json_dict = [CPDictionary dictionaryWithJSObject:json recursively:YES]; } @@ -68,9 +68,9 @@ "key2": "This is a string", "key3": null } - + var dict = [CPDictionary dictionaryWithJSObject:json_with_nulls recursively:YES]; - + [self assert:3 equals:[dict count]]; [self assert:[@"key1", @"key2", @"key3"] equals:[dict allKeys]]; [self assert:[CPNull null] equals:[dict objectForKey:@"key3"]]; @@ -90,19 +90,19 @@ - (void)testCount { - [self assert:[string_dict count] equals:2]; + [self assert:[string_dict count] equals:4]; [self assert:[json_dict count] equals:3]; } - (void)testAllKeys { - [self assert:[string_dict allKeys] equals:[@"key2", @"key1"]]; + [self assert:[string_dict allKeys] equals:[@"key4", @"key3", @"key2", @"key1"]]; [self assert:[json_dict allKeys] equals:[@"key1", @"key2", @"key3"]]; } - (void)testAllValues { - [self assert:[string_dict allValues] equals:[@"1", @"2"]]; + [self assert:[string_dict allValues] equals:[@"1", @"2", @"This is a String", @"This is a String"]]; // Had to get object from key to get test passing [self assert:[json_dict allValues] equals:[[json_dict objectForKey:@"key3"], @"This is a string", ['1', '2', '3']]]; } @@ -113,6 +113,11 @@ [self assert:[json_dict objectForKey:@"key1"] equals:['1', '2', '3']]; } +- (void)testAllKeysForObject +{ + [self assert:[string_dict allKeysForObject:@"This is a String"] equals:[@"key4", @"key3"]]; +} + - (void)testKeyEnumerator { var dict = [[CPDictionary alloc] init]; @@ -156,7 +161,7 @@ { [string_dict removeObjectForKey:@"key1"]; [json_dict removeObjectForKey:@"key1"]; - [self assert:[string_dict count] equals:1]; + [self assert:[string_dict count] equals:3]; [self assert:[json_dict count] equals:2]; } @@ -164,7 +169,7 @@ { [string_dict removeObjectsForKeys:[@"key1"]]; [json_dict removeObjectsForKeys:[@"key1", @"key2"]]; - [self assert:[string_dict count] equals:1]; + [self assert:[string_dict count] equals:3]; [self assert:[json_dict count] equals:1]; } @@ -178,10 +183,10 @@ - (void)testAddEntriesFromDictionary { - var dict = [[CPDictionary alloc] initWithObjects:[@"1", @"2"] forKeys:[@"key4", @"key5"]]; + var dict = [[CPDictionary alloc] initWithObjects:[@"1", @"2"] forKeys:[@"key5", @"key6"]]; [string_dict addEntriesFromDictionary:dict] [json_dict addEntriesFromDictionary:dict] - [self assert:[string_dict count] equals:4]; + [self assert:[string_dict count] equals:6]; [self assert:[json_dict count] equals:5]; } diff --git a/Tools/nib2cib/NSAppKit.j b/Tools/nib2cib/NSAppKit.j index 4673e3439..6db239ef5 100644 --- a/Tools/nib2cib/NSAppKit.j +++ b/Tools/nib2cib/NSAppKit.j @@ -42,6 +42,7 @@ @import "NSMenu.j" @import "NSMenuItem.j" @import "NSNibConnector.j" +@import "NSOutlineView.j" @import "NSPopUpButton.j" @import "NSResponder.j" @import "NSScrollView.j" @@ -76,7 +77,7 @@ function CP_NSMapClassName(aClassName) if (aClassName.indexOf("NS") === 0) { var mappedClassName = @"CP" + aClassName.substr(2); - + if (CPClassFromString(mappedClassName)) { CPLog.info("Mapping " + aClassName + " to " + mappedClassName); diff --git a/Tools/nib2cib/NSOutlineView.j b/Tools/nib2cib/NSOutlineView.j new file mode 100644 index 000000000..e139aa084 --- /dev/null +++ b/Tools/nib2cib/NSOutlineView.j @@ -0,0 +1,65 @@ +/* + * NSOutlineView.j + * nib2cib + * + * Created by Andreas Falk. + * Copyright 2009, Andreas Falk. + * + * 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 + + +@implementation CPOutlineView (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + self = [super NS_initWithCoder:aCoder]; + + if (self) + { + if([aCoder containsValueForKey:"NSOutlineViewOutlineTableColumnKey"]) + _outlineTableColumn = [aCoder decodeObjectForKey:@"NSOutlineViewOutlineTableColumnKey"]; + else + _outlineTableColumn = [[self tableColumns] objectAtIndex:0]; + + _indentationPerLevel = [aCoder decodeFloatForKey:@"NSOutlineViewIndentationPerLevelKey"]; + + _outlineViewDataSource = [aCoder decodeObjectForKey:@"NSDataSource"]; + _outlineViewDelegate = [aCoder decodeObjectForKey:@"NSDelegate"]; + } + + return self; +} + +@end + + +@implementation NSOutlineView : CPOutlineView +{ +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPOutlineView class]; +} + +@end