diff --git a/AppKit/CPCursor.j b/AppKit/CPCursor.j index f693db5aa..34a076c35 100755 --- a/AppKit/CPCursor.j +++ b/AppKit/CPCursor.j @@ -212,9 +212,10 @@ var currentCursor = nil, - (id)initWithImage:(CPImage)image hotSpot:(CPPoint)hotSpot { - return [self initWithCSSString:"url(" + [image filename] + ")"]; + return [self initWithCSSString:"url(" + [image filename] + "), auto"]; } + - (void)mouseEntered:(CPEvent)event { } diff --git a/AppKit/CPKeyValueBinding.j b/AppKit/CPKeyValueBinding.j index eda0dc8e3..64ef1f583 100644 --- a/AppKit/CPKeyValueBinding.j +++ b/AppKit/CPKeyValueBinding.j @@ -247,7 +247,7 @@ var CPBindingOperationAnd = 0, valueTransformer = [options objectForKey:CPValueTransformerBindingOption]; if (valueTransformer && [[valueTransformer class] allowsReverseTransformation]) - aValue = [valueTransformer transformedValue:aValue]; + aValue = [valueTransformer reverseTransformedValue:aValue]; return aValue; } diff --git a/AppKit/CPSearchField.j b/AppKit/CPSearchField.j index 4df6d4722..5e91386c5 100644 --- a/AppKit/CPSearchField.j +++ b/AppKit/CPSearchField.j @@ -68,6 +68,11 @@ var RECENT_SEARCH_PREFIX = @" "; CPTimer _partialStringTimer; } ++ (CPString)themeClass +{ + return @"searchfield" +} + + (void)initialize { if (self != [CPSearchField class]) diff --git a/AppKit/CPStringDrawing.j b/AppKit/CPStringDrawing.j index 859c23926..0f930caf1 100644 --- a/AppKit/CPStringDrawing.j +++ b/AppKit/CPStringDrawing.j @@ -24,6 +24,9 @@ @import "CPPlatformString.j" +var CPStringSizeWithFontInWidthCache = {}; + +CPStringSizeCachingEnabled = YES; @implementation CPString (CPStringDrawing) @@ -50,7 +53,19 @@ - (CGSize)sizeWithFont:(CPFont)aFont inWidth:(float)aWidth { - return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth]; + if (!CPStringSizeCachingEnabled) + return [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth]; + + var cacheKey = self + [aFont cssString] + aWidth, + size = CPStringSizeWithFontInWidthCache[cacheKey]; + + if (size === undefined) + { + size = [CPPlatformString sizeOfString:self withFont:aFont forWidth:aWidth]; + CPStringSizeWithFontInWidthCache[cacheKey] = size; + } + + return CGSizeMakeCopy(size); } @end diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index 8924510f8..62b1b376d 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -822,7 +822,14 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _capsLockActive = NO; if ([ModifierKeyCodes containsObject:keyCode]) + { + // A modifier key will never fire keypress. We don't need to do any other processing so we just fire it here and break. + event = [CPEvent keyEventWithType:CPFlagsChanged location:location modifierFlags:modifierFlags + timestamp:timestamp windowNumber:windowNumber context:nil + characters:nil charactersIgnoringModifiers:nil isARepeat:NO keyCode:_keyCode]; + break; + } var characters = KeyCodesToUnicodeMap[charCode] || String.fromCharCode(charCode), charactersIgnoringModifiers = characters.toLowerCase(); diff --git a/AppKit/Themes/Aristo/ThemeDescriptors.j b/AppKit/Themes/Aristo/ThemeDescriptors.j index c8b1826f9..23f4b7e1a 100755 --- a/AppKit/Themes/Aristo/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo/ThemeDescriptors.j @@ -777,9 +777,10 @@ var themedButtonValues = nil, ], PatternIsHorizontal), - placeholderColor = [CPColor colorWithCalibratedRed:189.0 / 255.0 green:199.0 / 255.0 blue:211.0 / 255.0 alpha:1.0], + placeholderColor = [CPColor colorWithCalibratedRed:189.0 / 255.0 green:199.0 / 255.0 blue:211.0 / 255.0 alpha:1.0]; - themeValues = + // Global for reuse by CPSearchField + themedRoundedTextFieldValues = [ [@"bezel-color", bezelColor, CPTextFieldStateRounded | CPThemeStateBezeled], [@"bezel-color", bezelFocusedColor, CPTextFieldStateRounded | CPThemeStateBezeled | CPThemeStateEditing], @@ -795,7 +796,7 @@ var themedButtonValues = nil, [@"max-size", CGSizeMake(-1.0, 30.0), CPTextFieldStateRounded | CPThemeStateBezeled] ]; - [self registerThemeValues:themeValues forView:textfield]; + [self registerThemeValues:themedRoundedTextFieldValues forView:textfield]; [textfield setBezeled:YES]; [textfield setBezelStyle:CPTextFieldRoundedBezel]; @@ -807,6 +808,13 @@ var themedButtonValues = nil, return textfield; } ++ (CPSearchField)themedSearchField +{ + var searchField = [[CPSearchField alloc] initWithFrame:CGRectMake(0.0, 0.0, 60.0, 30.0)]; + [self registerThemeValues:nil forView:searchField inherit:themedRoundedTextFieldValues]; + return searchField; +} + + (CPTokenField)themedTokenField { var tokenfield = [[CPTokenField alloc] initWithFrame:CGRectMake(0.0, 0.0, 60.0, 30.0)], diff --git a/Foundation/CPNotificationCenter.j b/Foundation/CPNotificationCenter.j index 67babfcad..b6c9b5e96 100644 --- a/Foundation/CPNotificationCenter.j +++ b/Foundation/CPNotificationCenter.j @@ -248,7 +248,7 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ else { var key = [anObject UID], - observers = [_objectObservers objectForKey:key]; + observers = [_objectObservers objectForKey:key], count = observers ? observers.length : 0; while (count--) diff --git a/Objective-J/Runtime.js b/Objective-J/Runtime.js index c003bd9ab..77de0a2d1 100644 --- a/Objective-J/Runtime.js +++ b/Objective-J/Runtime.js @@ -440,7 +440,7 @@ class_createInstance = function(/*Class*/ aClass) while (theClass) { - var ivars = theClass.ivars; + var ivars = theClass.ivars, count = ivars.length; while (count--) diff --git a/Tests/Manual/CPCursor/AppController.j b/Tests/Manual/CPCursor/AppController.j index 516d6e993..ff79fad15 100644 --- a/Tests/Manual/CPCursor/AppController.j +++ b/Tests/Manual/CPCursor/AppController.j @@ -37,6 +37,12 @@ var selectors = ["pointingHandCursor", "resizeDownCursor", "resizeLeftCursor", " [button setTitle:@"set Cursor"]; [contentView addSubview:button]; + var button = [[CPButton alloc] initWithFrame:CGRectMake(270,150,150,24)]; + [button setAction:@selector(setUrlCursor:)]; + [button setTarget:self]; + [button setTitle:@"set Cursor from url"]; + [contentView addSubview:button]; + [theWindow orderFront:self]; // Uncomment the following line to turn on the standard menu bar. //[CPMenu setMenuBarVisible:YES]; @@ -49,4 +55,11 @@ var selectors = ["pointingHandCursor", "resizeDownCursor", "resizeLeftCursor", " [cursor set]; } +-(void)setUrlCursor:(id)sender +{ // note gifs don't animate when they are used as a cursor. + var aImage = [[CPImage alloc] initWithContentsOfFile:[[CPBundle mainBundle] pathForResource:@"spinner.gif"]]; + var cursor = [[CPCursor alloc] initWithImage:aImage hotSpot:CGPointMakeZero()]; + [cursor set]; +} + @end diff --git a/Tools/nib2cib/NSSearchField.j b/Tools/nib2cib/NSSearchField.j index 086d560d7..46e149918 100644 --- a/Tools/nib2cib/NSSearchField.j +++ b/Tools/nib2cib/NSSearchField.j @@ -33,7 +33,7 @@ if (self) { var cell = [aCoder decodeObjectForKey:@"NSCell"]; - + [self setRecentsAutosaveName:[cell recentsAutosaveName]]; [self setMaximumRecents:[cell maximumRecents]]; [self setSendsWholeSearchString:[cell sendsWholeSearchString]]; @@ -78,11 +78,11 @@ _recentsAutosaveName = [aCoder decodeObjectForKey:@"NSRecentsAutosaveName"]; _maximumRecents = [aCoder decodeIntForKey:@"NSMaximumRecents"]; _sendsWholeSearchString = [aCoder decodeBoolForKey:@"NSSendsWholeSearchString"] ? YES : NO; - + // These bytes don't seem to be used for anything else but the send immediately flag _sendsSearchStringImmediately = [aCoder decodeBytesForKey:@"NSSearchFieldFlags"] ? YES: NO; } - + return self; } diff --git a/Tools/nib2cib/NSTextField.j b/Tools/nib2cib/NSTextField.j index 746879170..98933bd36 100644 --- a/Tools/nib2cib/NSTextField.j +++ b/Tools/nib2cib/NSTextField.j @@ -31,53 +31,45 @@ - (id)NS_initWithCoder:(CPCoder)aCoder { self = [super NS_initWithCoder:aCoder]; - + if (self) { var cell = [aCoder decodeObjectForKey:@"NSCell"]; - + if ([cell isEditable] && [[cell font] isEqual:[CPFont boldSystemFontOfSize:12.0]]) [self setFont:[CPFont systemFontOfSize:12.0]]; - [self sendActionOn:CPKeyUpMask|CPKeyDownMask]; - + [self sendActionOn:CPKeyUpMask | CPKeyDownMask]; + [self setEditable:[cell isEditable]]; [self setSelectable:[cell isSelectable]]; - + [self setBordered:[cell isBordered]]; [self setBezeled:[cell isBezeled]]; [self setBezelStyle:[cell bezelStyle]]; [self setDrawsBackground:[cell drawsBackground]]; - + [self setLineBreakMode:[cell lineBreakMode]]; [self setAlignment:[cell alignment]]; [self setTextFieldBackgroundColor:[cell backgroundColor]]; - + [self setPlaceholderString:[cell placeholderString]]; - + var textColor = [cell textColor], defaultColor = [self currentValueForThemeAttribute:@"text-color"]; - + // Don't change the text color if it is not the default, that messes up the theme lookups later if (![textColor isEqual:defaultColor]) [self setTextColor:[cell textColor]]; - + var frame = [self frame]; [self setFrameOrigin:CGPointMake(frame.origin.x, frame.origin.y)]; [self setFrameSize:CGSizeMake(frame.size.width, frame.size.height)]; - // Only adjust the origin and size if this is a bezeled textfield - // this makes sure that labels positioned in IB are properly positioned after nibcib - if ([self isBezeled]) - { - [self setFrameOrigin:CGPointMake(frame.origin.x - 4.0, frame.origin.y - 4.0)]; - [self setFrameSize:CGSizeMake(frame.size.width + 8.0, frame.size.height + 8.0)]; - } - CPLog.debug([self stringValue] + " => isBordered=" + [self isBordered] + ", isBezeled=" + [self isBezeled] + ", bezelStyle=" + [self bezelStyle] + "("+[cell stringValue]+", " + [cell placeholderString] + ")"); } - + return self; } @@ -111,7 +103,7 @@ - (id)initWithCoder:(CPCoder)aCoder { self = [super initWithCoder:aCoder]; - + if (self) { _bezelStyle = [aCoder decodeObjectForKey:@"NSTextBezelStyle"] || CPTextFieldSquareBezel; @@ -120,7 +112,7 @@ _textColor = [aCoder decodeObjectForKey:@"NSTextColor"]; _placeholderString = [aCoder decodeObjectForKey:@"NSPlaceholderString"]; } - + return self; }