From 7696b300673c2177bbc572a22008192273adc8a0 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Sun, 11 Jul 2010 16:57:17 -0500 Subject: [PATCH 01/19] Added tests for CPFormatter and Foundation import. --- Foundation/CPFormatter.j | 2 +- Foundation/Foundation.j | 1 + Tests/Foundation/CPFormatterTest.j | 44 ++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 Tests/Foundation/CPFormatterTest.j diff --git a/Foundation/CPFormatter.j b/Foundation/CPFormatter.j index a58f6cdc2..a5465aed8 100644 --- a/Foundation/CPFormatter.j +++ b/Foundation/CPFormatter.j @@ -151,7 +151,7 @@ - (BOOL)isPartialStringValue:(CPString)aPartialString proposedSelectedRange:(CPRange)aProposedSelectedRange originalString:(CPString)originalString originalSelectedRange:(CPRange)originalSelectedRange errorDescription:(CPString)anError { _CPRaiseInvalidAbstractInvocation(self, @selector(isPartialStringValue:proposedSelectedRange:originalString:originalSelectedRange:errorDescription:)); - return nil; + return NO; } - (id)initWithCoder:(CPCoder)aCoder diff --git a/Foundation/Foundation.j b/Foundation/Foundation.j index a49654dd4..f7a65ae8f 100755 --- a/Foundation/Foundation.j +++ b/Foundation/Foundation.j @@ -28,6 +28,7 @@ @import "CPDictionary.j" @import "CPEnumerator.j" @import "CPException.j" +@import "CPFormatter.j" @import "CPIndexSet.j" @import "CPInvocation.j" @import "CPJSONPConnection.j" diff --git a/Tests/Foundation/CPFormatterTest.j b/Tests/Foundation/CPFormatterTest.j new file mode 100644 index 000000000..232d23645 --- /dev/null +++ b/Tests/Foundation/CPFormatterTest.j @@ -0,0 +1,44 @@ +@import + +@implementation CPFormatterTest : OJTestCase + +- (void)testThatCPFormatterIsConstructed +{ + [self assertNotNull:[[CPFormatter alloc] init]]; +} + +- (void)testStringForObjectValue +{ + var formatter = [[CPFormatter alloc] init]; + + [self assertThrows:function(){ [formatter stringForObjectValue:@"Hello World"]; }]; +} + +- (void)testEditingStringForObjectValue +{ + var formatter = [[CPFormatter alloc] init]; + + [self assertThrows:function(){ [formatter editingStringForObjectValue:@"Hello Wolrd"]; }]; +} + +- (void)testGetObjectValueForString +{ + var formatter = [[CPFormatter alloc] init]; + + [self assertThrows:function(){ [formatter getObjectValue:@"Hello World" forString:@"Hello World" errorDescription:nil]; }]; +} + +- (void)testIsPartialStringValidNewEditingString +{ + var formatter = [[CPFormatter alloc] init]; + + [self assertThrows:function(){ [formatter isPartialStringValid:@"Hello Wolrd" newEditingString:@"Hello World" errorDescription:nil]; }]; +} + +- (void)testIsPartialStringValueProposedSelectedRange +{ + var formatter = [[CPFormatter alloc] init]; + + [self assertThrows:function(){ [formatter isPartialStringValue:@"Hello Wolrd" proposedSelectedRange:CPRangeMake(3,5) originalString:@"Hello World" originalSelectedRange:nil errorDescription:nil]; }]; +} +@end \ No newline at end of file From 70f2d86b586d0051a40287a0938445fc5891bd5d Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 12 Jul 2010 20:45:30 -0500 Subject: [PATCH 02/19] Fixes for adding and removing columns to the tableview after the tableview has already been displayed... There are still issues though. --- AppKit/CPTableView.j | 22 ++++++- Tests/Manual/TableTest/AppController.j | 83 ++++++++++++++++++++------ 2 files changed, 86 insertions(+), 19 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 465fe7f84..9d766232a 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -220,6 +220,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; CPColor _sourceListActiveBottomLineColor; int _draggedColumnIndex; + CPArray _differedColumnDataToRemove; /* CPGradient _sourceListInactiveGradient; @@ -340,6 +341,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _sourceListInactiveGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [168.0/255.0,183.0/255.0,205.0/255.0,1.0,157.0/255.0,174.0/255.0,199.0/255.0,1.0], [0,1], 2); _sourceListInactiveTopLineColor = [CPColor colorWithCalibratedRed:(173.0/255.0) green:(187.0/255.0) blue:(209.0/255.0) alpha:1.0]; _sourceListInactiveBottomLineColor = [CPColor colorWithCalibratedRed:(150.0/255.0) green:(161.0/255.0) blue:(183.0/255.0) alpha:1.0];*/ + _differedColumnDataToRemove = [ ]; } /*! @@ -725,6 +727,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; else _dirtyTableColumnRangeIndex = MIN(NUMBER_OF_COLUMNS() - 1, _dirtyTableColumnRangeIndex); + [self tile]; [self setNeedsLayout]; } @@ -742,8 +745,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; if (index === CPNotFound) return; + // we differ the actual removal until the end of the runloop in order to keep a reference to the column. + [_differedColumnDataToRemove addObject:{"column":aTableColumn, "shouldBeHidden": [aTableColumn isHidden]}]; + + [aTableColumn setHidden:YES]; [aTableColumn setTableView:nil]; - [_tableColumns removeObjectAtIndex:index]; var tableColumnUID = [aTableColumn UID]; @@ -2244,6 +2250,20 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [dataViews[count] removeFromSuperview]; } + // if we have any columns to remove do that here + if ([_differedColumnDataToRemove count]) + { + for (var i = 0; i < _differedColumnDataToRemove.length; i++) + { + var data = _differedColumnDataToRemove[i], + column = data.column; + + [column setHidden:data.shouldBeHidden]; + [_tableColumns removeObject:column]; + } + [_differedColumnDataToRemove removeAllObjects]; + } + } - (void)_unloadDataViewsInRows:(CPIndexSet)rows columns:(CPIndexSet)columns diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index f383bcc8a..2c0d275f1 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -10,6 +10,8 @@ tableTestDragType = @"CPTableViewTestDragType"; CPImage iconImage; CPArray dataSet1; CPArray dataSet2; + + CPTableColumn randomColumn; } - (void)applicationDidFinishLaunching:(CPNotification)aNotification @@ -68,6 +70,9 @@ tableTestDragType = @"CPTableViewTestDragType"; [column setEditable:YES]; [tableView addTableColumn:column]; + + if (i === 2) + randomColumn = column; } // we offset this scrollview to make sure all the coordinates are calculated correctly @@ -95,16 +100,34 @@ tableTestDragType = @"CPTableViewTestDragType"; [button setAction:@selector(addRow:)]; [contentView addSubview:button]; - var sourceListActiveGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [255.0/255.0, 153.0/255.0, 209.0/255.0,1.0, 33.0/255.0, 94.0/255.0, 208.0/255.0,1.0], [0,1], 2), - sourceListActiveTopLineColor = [CPColor colorWithCalibratedRed:(255.0/255.0) green:(123.0/255.0) blue:(218.0/255.0) alpha:1.0], - sourceListActiveBottomLineColor = [CPColor colorWithCalibratedRed:(255.0/255.0) green:(92.0/255.0) blue:(207.0/255.0) alpha:1.0]; - [tableView setSelectionGradientColors:[CPDictionary dictionaryWithObjects:[sourceListActiveGradient, sourceListActiveTopLineColor, sourceListActiveBottomLineColor] forKeys:[CPSourceListGradient, CPSourceListTopLineColor, CPSourceListBottomLineColor]]]; - var button = [[CPButton alloc] initWithFrame:CGRectMake(10,70,100, 24)]; [button setTitle:@"Switch Highlight"]; [button setTarget:self]; [button setAction:@selector(switchSelectionHighlightType:)]; [contentView addSubview:button]; + + var button = [[CPButton alloc] initWithFrame:CGRectMake(10,100,100, 24)]; + [button setTitle:@"Hide Column"]; + [button setTarget:self]; + [button setAction:@selector(hideColumn:)]; + [contentView addSubview:button]; + + var button = [[CPButton alloc] initWithFrame:CGRectMake(10,130,100, 24)]; + [button setTitle:@"Remove Column"]; + [button setTarget:self]; + [button setAction:@selector(removeColumn:)]; + [contentView addSubview:button]; + + var button = [[CPButton alloc] initWithFrame:CGRectMake(10,160,100, 24)]; + [button setTitle:@"Add Column"]; + [button setTarget:self]; + [button setAction:@selector(addColumn:)]; + [contentView addSubview:button]; + + var sourceListActiveGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [255.0/255.0, 153.0/255.0, 209.0/255.0,1.0, 33.0/255.0, 94.0/255.0, 208.0/255.0,1.0], [0,1], 2), + sourceListActiveTopLineColor = [CPColor colorWithCalibratedRed:(255.0/255.0) green:(123.0/255.0) blue:(218.0/255.0) alpha:1.0], + sourceListActiveBottomLineColor = [CPColor colorWithCalibratedRed:(255.0/255.0) green:(92.0/255.0) blue:(207.0/255.0) alpha:1.0]; + [tableView setSelectionGradientColors:[CPDictionary dictionaryWithObjects:[sourceListActiveGradient, sourceListActiveTopLineColor, sourceListActiveBottomLineColor] forKeys:[CPSourceListGradient, CPSourceListTopLineColor, CPSourceListBottomLineColor]]]; } - (void)switchSelectionHighlightType:(id)sender @@ -124,6 +147,31 @@ tableTestDragType = @"CPTableViewTestDragType"; [tableView reloadData]; } +- (void)hideColumn:(id)sender +{ + [randomColumn setHidden:![randomColumn isHidden]]; +} + +- (void)removeColumn:(id)sender +{ + // if ([[tableView tableColumns] containsObject:randomColumn]) + [tableView removeTableColumn:randomColumn]; + //else + // [tableView addTableColumn:randomColumn]; +} + +- (void)addColumn:(id)sender +{ + var column = [[CPTableColumn alloc] initWithIdentifier:"NewColumn"]; + [[column headerView] setStringValue:"New Column"]; + + [column setMinWidth:50.0]; + [column setMaxWidth:500.0]; + [column setWidth:75.0]; + + [tableView addTableColumn:column]; +} + - (void)newWindow { @@ -237,7 +285,7 @@ tableTestDragType = @"CPTableViewTestDragType"; return iconImage; if (aTableView === tableView) - return String(dataSet1[aRow]); + return String(dataSet1[aRow]* ([[aTableView tableColumns] indexOfObject:aColumn] + 1)); else if (aTableView === tableView2) return String(dataSet2[aRow]); else if(aTableView === tableView3) @@ -246,7 +294,7 @@ tableTestDragType = @"CPTableViewTestDragType"; - (void)tableView:(CPTableView)aTableView sortDescriptorsDidChange:(CPArray)oldDescriptors { - CPLogConsole(_cmd + [oldDescriptors description]); + //CPLogConsole(_cmd + [oldDescriptors description]); var newDescriptors = [aTableView sortDescriptors]; @@ -257,39 +305,39 @@ tableTestDragType = @"CPTableViewTestDragType"; - (void)tableViewSelectionIsChanging:(CPNotification)aNotification { - CPLog.debug(@"changing! %@", [aNotification description]); + //CPLog.debug(@"changing! %@", [aNotification description]); } - (void)tableViewSelectionDidChange:(CPNotification)aNotification { - CPLog.debug(@"did change! %@", [aNotification description]); + //CPLog.debug(@"did change! %@", [aNotification description]); } - (BOOL)tableView:(CPTableView)aTableView shouldSelectRow:(int)rowIndex { - CPLog.debug(@"tableView:shouldSelectRow"); + //CPLog.debug(@"tableView:shouldSelectRow"); return true; } - (BOOL)selectionShouldChangeInTableView:(CPTableView)aTableView { - CPLog.debug(@"selectionShouldChangeInTableView"); + //CPLog.debug(@"selectionShouldChangeInTableView"); return YES; } - (void)tableViewSelectionDidChange:(id)notification { - CPLogConsole(_cmd + [notification description]); + //CPLogConsole(_cmd + [notification description]); } - (void)tableViewSelectionIsChanging:(id)notification { - CPLogConsole(_cmd + [notification description]); + //CPLogConsole(_cmd + [notification description]); } - (void)_tableViewColumnDidResize:(id)notification { - CPLogConsole(_cmd + [notification description]); + //CPLogConsole(_cmd + [notification description]); } - (BOOL)tableView:(CPTableView)aTableView shouldEditTableColumn:(CPTableColumn)tableColumn row:(int)row { @@ -301,7 +349,7 @@ tableTestDragType = @"CPTableViewTestDragType"; - (void)tableView:(CPTableView)aTableView willDisplayView:(CPView)aView forTableColumn:(CPTableColumn)tableColumn row:(int)row { - CPLogConsole(_cmd + " column: " + [tableColumn identifier] + " row:" + row) + //CPLogConsole(_cmd + " column: " + [tableColumn identifier] + " row:" + row) } - (void)tableView:(CPTableView)aTableView setObjectValue:(id)aValue forTableColumn:(CPTableColumn)tableColumn row:(int)row @@ -312,7 +360,7 @@ tableTestDragType = @"CPTableViewTestDragType"; - (void)tableView:(CPTableView)aTableView sortDescriptorsDidChange:(CPArray)oldDescriptors { - CPLogConsole(_cmd + [oldDescriptors description]); + //CPLogConsole(_cmd + [oldDescriptors description]); var newDescriptors = [aTableView sortDescriptors]; @@ -403,13 +451,12 @@ tableTestDragType = @"CPTableViewTestDragType"; - (void)tableView:(CPTableView)aTableView didClickTableColumn:(CPTableColumn)aColumn { - CPLog.debug("table: "+aTableView+" clicked column: "+aColumn); + //CPLog.debug("table: "+aTableView+" clicked column: "+aColumn); } @end @implementation CPArray (MoveIndexes) - - (void)moveIndexes:(CPIndexSet)indexes toIndex:(int)insertIndex { var aboveCount = 0, From 0cbdb3b2d1b475a70111337f689ad3f6c688ebe3 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 12 Jul 2010 21:14:48 -0500 Subject: [PATCH 03/19] Fix for redrawing issues in tableview. Closes #627 --- AppKit/CPTableView.j | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 9d766232a..ad854587a 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -880,7 +880,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _selectedColumnIndexes = [columns copy]; [self _updateHighlightWithOldColumns:previousSelectedIndexes newColumns:_selectedColumnIndexes]; - [_tableDrawView display]; // FIXME: should be setNeedsDisplayInRect:enclosing rect of new (de)selected columns + [self setNeedsDisplay:YES]; // FIXME: should be setNeedsDisplayInRect:enclosing rect of new (de)selected columns // but currently -drawRect: is not implemented here if (_headerView) [_headerView setNeedsDisplay:YES]; @@ -896,7 +896,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _selectedRowIndexes = [rows copy]; [self _updateHighlightWithOldRows:previousSelectedIndexes newRows:_selectedRowIndexes]; - [_tableDrawView display]; // FIXME: should be setNeedsDisplayInRect:enclosing rect of new (de)selected rows + [self setNeedsDisplay:YES]; // FIXME: should be setNeedsDisplayInRect:enclosing rect of new (de)selected rows // but currently -drawRect: is not implemented here [[CPKeyValueBinding getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectedRowIndexes"]; @@ -2237,7 +2237,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [_tableDrawView setFrame:exposedRect]; - [_tableDrawView display]; + [self setNeedsDisplay:YES]; // Now clear all the leftovers // FIXME: this could be faster! @@ -2474,6 +2474,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return [self convertRect:CGRectIntersection([superview bounds], [self frame]) fromView:superview]; } +- (void)setNeedsDisplay:(BOOL)aFlag +{ + [super setNeedsDisplay:aFlag]; + [_tableDrawView setNeedsDisplay:aFlag]; +} + - (void)_drawRect:(CGRect)aRect { // FIX ME: All three of these methods will likely need to be rewritten for 1.0 From 36bb41a9453ccfc44929ddf8f01345bd241f416d Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 15 Jul 2010 12:49:52 +0200 Subject: [PATCH 04/19] implemented isEqual: on CPString --- Foundation/CPString.j | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Foundation/CPString.j b/Foundation/CPString.j index abbe70c2d..1ebae87ea 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -512,6 +512,18 @@ var CPStringRegexSpecialCharacters = [ return aString && aString != "" && length >= aString.length && lastIndexOf(aString) == (length - aString.length); } +- (BOOL)isEqual:(id)anObject +{ + if (self === anObject) + return YES; + + if (![anObject isKindOfClass:[CPString class]]) + return NO; + + return [self isEqualToString:anObject]; +} + + /*! Returns \c YES if the specified string contains the same characters as the receiver. */ From 023cf4604132613527af60140316d3eb878e8807 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 15 Jul 2010 14:39:24 +0200 Subject: [PATCH 05/19] check for nil in CPString isEqual: --- Foundation/CPString.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 1ebae87ea..877604f4c 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -517,7 +517,7 @@ var CPStringRegexSpecialCharacters = [ if (self === anObject) return YES; - if (![anObject isKindOfClass:[CPString class]]) + if (!anObject || ![anObject isKindOfClass:[CPString class]]) return NO; return [self isEqualToString:anObject]; From 564668587c0948da64f72b9cc610b8032db82aa1 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 15 Jul 2010 14:42:48 +0200 Subject: [PATCH 06/19] fix CPDate isEqual: and isEqualToDate: --- Foundation/CPDate.j | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index cba9ec382..07ff8fbb3 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -148,12 +148,21 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 1, 1, 0, 0, 0, 0)); - (BOOL)isEqual:(CPDate)aDate { + if (self === aDate) + return YES; + + if (!aDate || ![aDate isKindOfClass:[CPDate class]]) + return NO; + return [self isEqualToDate:aDate]; } -- (BOOL)isEqualToDate:(CPDate)anotherDate +- (BOOL)isEqualToDate:(CPDate)aDate { - return self === anotherDate || (anotherDate !== nil && anotherDate.isa && [anotherDate isKindOfClass:CPDate] && !(self < anotherDate || self > anotherDate)); + if (!aDate) + return NO; + + return self === aDate; } - (CPComparisonResult)compare:(CPDate)anotherDate From a2e6f8f96445163cc4d5395760d0ad86e9b4995c Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Thu, 15 Jul 2010 22:23:05 -0500 Subject: [PATCH 07/19] Initial theming of TableView header. --- AppKit/CPTableHeaderView.j | 47 +++++++++--------- ...bleview-headerview-highlighted-pressed.png | Bin .../tableview-headerview-highlighted.png | Bin .../tableview-headerview-pressed.png | Bin .../Resources/tableview-headerview.png | Bin .../Aristo/Resources/tableviewselection.png | Bin 0 -> 4120 bytes AppKit/Themes/Aristo/ThemeDescriptors.j | 28 ++++++++++- 7 files changed, 51 insertions(+), 24 deletions(-) rename AppKit/{ => Themes/Aristo}/Resources/tableview-headerview-highlighted-pressed.png (100%) rename AppKit/{ => Themes/Aristo}/Resources/tableview-headerview-highlighted.png (100%) rename AppKit/{ => Themes/Aristo}/Resources/tableview-headerview-pressed.png (100%) rename AppKit/{ => Themes/Aristo}/Resources/tableview-headerview.png (100%) create mode 100644 AppKit/Themes/Aristo/Resources/tableviewselection.png diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index 76f71f426..223cfec2b 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -23,53 +23,59 @@ @import "CPTableColumn.j" @import "CPTableView.j" @import "CPView.j" + +#include "CoreGraphics/CGGeometry.h" @implementation _CPTableColumnHeaderView : CPView { _CPImageAndTextView _textField; } ++ (CPString)themeClass +{ + return @"tableHeader"; +} + ++ (id)themeAttributes +{ + return [CPDictionary dictionaryWithObjects:[[CPNull null], CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], CGSizeMakeZero()] + forKeys:[@"background-color", @"text-inset", @"text-color", @"text-font", @"text-shadow-color", @"text-shadow-offset"]]; +} + - (void)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) - { [self _init]; - } return self; } - (void)_init { - _textField = [[_CPImageAndTextView alloc] initWithFrame: - CGRectMake(5.0, 0.0, CGRectGetWidth([self bounds]) - 10.0, CGRectGetHeight([self bounds]))]; - + _textField = [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()]; + [_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable]; [_textField setLineBreakMode:CPLineBreakByTruncatingTail]; - [_textField setTextColor:[CPColor colorWithRed:51.0 / 255.0 green:51.0 / 255.0 blue:51.0 / 255.0 alpha:1.0]]; - [_textField setFont:[CPFont boldSystemFontOfSize:12.0]]; [_textField setAlignment:CPLeftTextAlignment]; [_textField setVerticalAlignment:CPCenterVerticalTextAlignment]; - [_textField setTextShadowColor:[CPColor whiteColor]]; - [_textField setTextShadowOffset:CGSizeMake(0,1)]; [self addSubview:_textField]; } - (void)layoutSubviews { - var themeState = [self themeState]; + [self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]]; - if(themeState & CPThemeStateSelected && themeState & CPThemeStateHighlighted) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 23.0))]]; - else if (themeState & CPThemeStateSelected) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 23.0))]]; - else if (themeState & CPThemeStateHighlighted) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 23.0))]]; - else - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 23.0))]]; + 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 setTextColor:[self currentValueForThemeAttribute:@"text-color"]]; + [_textField setFont:[self currentValueForThemeAttribute:@"text-font"]]; + [_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]]; + [_textField setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]]; } - (void)setStringValue:(CPString)string @@ -97,11 +103,6 @@ [_textField setFont:aFont]; } -- (void)setValue:(id)aValue forThemeAttribute:(id)aKey -{ - [_textField setValue:aValue forThemeAttribute:aKey]; -} - - (void)_setIndicatorImage:(CPImage)anImage { if (anImage) diff --git a/AppKit/Resources/tableview-headerview-highlighted-pressed.png b/AppKit/Themes/Aristo/Resources/tableview-headerview-highlighted-pressed.png similarity index 100% rename from AppKit/Resources/tableview-headerview-highlighted-pressed.png rename to AppKit/Themes/Aristo/Resources/tableview-headerview-highlighted-pressed.png diff --git a/AppKit/Resources/tableview-headerview-highlighted.png b/AppKit/Themes/Aristo/Resources/tableview-headerview-highlighted.png similarity index 100% rename from AppKit/Resources/tableview-headerview-highlighted.png rename to AppKit/Themes/Aristo/Resources/tableview-headerview-highlighted.png diff --git a/AppKit/Resources/tableview-headerview-pressed.png b/AppKit/Themes/Aristo/Resources/tableview-headerview-pressed.png similarity index 100% rename from AppKit/Resources/tableview-headerview-pressed.png rename to AppKit/Themes/Aristo/Resources/tableview-headerview-pressed.png diff --git a/AppKit/Resources/tableview-headerview.png b/AppKit/Themes/Aristo/Resources/tableview-headerview.png similarity index 100% rename from AppKit/Resources/tableview-headerview.png rename to AppKit/Themes/Aristo/Resources/tableview-headerview.png diff --git a/AppKit/Themes/Aristo/Resources/tableviewselection.png b/AppKit/Themes/Aristo/Resources/tableviewselection.png new file mode 100644 index 0000000000000000000000000000000000000000..990a98983429c7bb999e18fdbd2af84166d80bdb GIT binary patch literal 4120 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 W6h=jOJE+9~0000 @import +@import @implementation AristoThemeDescriptor : BKThemeDescriptor @@ -772,6 +773,31 @@ return buttonBar; } ++ (_CPTableColumnHeaderView)themedTableHeader +{ + var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMake(0,0,50,24)], + highlightedPressed = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"tableview-headerview-highlighted-pressed.png" size:CGSizeMake(1.0, 23.0)]], + highlighted = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"tableview-headerview-highlighted.png" size:CGSizeMake(1.0, 23.0)]], + pressed = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"tableview-headerview-pressed.png" size:CGSizeMake(1.0, 23.0)]], + normal = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"tableview-headerview.png" size:CGSizeMake(1.0, 23.0)]]; + + + [header setStringValue:@"Table Header"]; + + [header setValue:normal forThemeAttribute:@"background-color"]; + [header setValue:CGInsetMake(0, 5, 0, 5) forThemeAttribute:@"text-inset"]; + [header setValue:[CPColor colorWithRed:51.0 / 255.0 green:51.0 / 255.0 blue:51.0 / 255.0 alpha:1.0] forThemeAttribute:@"text-color"]; + [header setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"text-font"]; + [header setValue:[CPColor whiteColor] forThemeAttribute:@"text-shadow-color"]; + [header setValue:CGSizeMake(0,1) forThemeAttribute:@"text-shadow-offset"]; + + [header setValue:pressed forThemeAttribute:@"background-color" inState:CPThemeStateHighlighted]; + [header setValue:highlighted forThemeAttribute:@"background-color" inState:CPThemeStateSelected]; + [header setValue:highlightedPressed forThemeAttribute:@"background-color" inState:CPThemeStateHighlighted|CPThemeStateSelected]; + + return header; +} + @end @implementation AristoHUDThemeDescriptor : BKThemeDescriptor @@ -1179,4 +1205,4 @@ function PatternColor(anImage) { return [CPColor colorWithPatternImage:anImage]; -} +} \ No newline at end of file From 2ae8d25d188299b2553cbc81aacad59afdb38fa3 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 19 Jul 2010 13:04:30 +0200 Subject: [PATCH 08/19] don't use === for date equality checking Apparently this will return false for equal dates, reverted the actual equality check to what was already in Cappuccino before my fix !(date < otherDate || date > otherDate) --- Foundation/CPDate.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index 07ff8fbb3..3ecdd21a4 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -162,7 +162,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 1, 1, 0, 0, 0, 0)); if (!aDate) return NO; - return self === aDate; + return !(self < aDate || self > aDate); } - (CPComparisonResult)compare:(CPDate)anotherDate From 85f3691432a3559e23b87a7b4d70be0f02c49482 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Mon, 19 Jul 2010 16:27:44 -0700 Subject: [PATCH 09/19] Don't add a "Shift" if it's not required. --- AppKit/CPMenuItem/CPMenuItem.j | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AppKit/CPMenuItem/CPMenuItem.j b/AppKit/CPMenuItem/CPMenuItem.j index fb352ed69..1e14e2f17 100644 --- a/AppKit/CPMenuItem/CPMenuItem.j +++ b/AppKit/CPMenuItem/CPMenuItem.j @@ -591,7 +591,8 @@ CPControlKeyMask return @""; var string = _keyEquivalent.toUpperCase(), - needsShift = _keyEquivalentModifierMask & CPShiftKeyMask || string === _keyEquivalent; + needsShift = _keyEquivalentModifierMask & CPShiftKeyMask || + (string === _keyEquivalent && _keyEquivalent.toLowerCase() !== _keyEquivalent.toUpperCase()); if (CPBrowserIsOperatingSystem(CPMacOperatingSystem)) { From 474623feb3c66108ddee7528f41e3add8f05f4cc Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Tue, 20 Jul 2010 22:17:10 -0400 Subject: [PATCH 10/19] =?UTF-8?q?Added=20support=20for=20punctuation=20bas?= =?UTF-8?q?ed=20key=20equivalents=20such=20as=20Cmd-'=20or=20Cmd-;.=20Fixe?= =?UTF-8?q?d:=20[event=20characters]=20would=20contain=20=C3=9E=20when=20C?= =?UTF-8?q?md-'=20was=20pressed=20and=20=C2=BA=20for=20Cmd-;=20since=20the?= =?UTF-8?q?=20key=20codes=20for=20punctuation=20do=20not=20match=20the=20A?= =?UTF-8?q?SCII=20codes=20and=20String.fromCharCode=20does=20not=20work.?= =?UTF-8?q?=20Manual=20test=20included.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 43 +++++--- Tests/Manual/KeyEquivalents/AppController.j | 78 +++++++++++++ Tests/Manual/KeyEquivalents/Info.plist | 12 ++ Tests/Manual/KeyEquivalents/Jakefile | 93 ++++++++++++++++ .../KeyEquivalents/Resources/spinner.gif | Bin 0 -> 1849 bytes Tests/Manual/KeyEquivalents/index-debug.html | 104 ++++++++++++++++++ Tests/Manual/KeyEquivalents/index.html | 79 +++++++++++++ Tests/Manual/KeyEquivalents/main.j | 18 +++ 8 files changed, 411 insertions(+), 16 deletions(-) create mode 100644 Tests/Manual/KeyEquivalents/AppController.j create mode 100644 Tests/Manual/KeyEquivalents/Info.plist create mode 100644 Tests/Manual/KeyEquivalents/Jakefile create mode 100644 Tests/Manual/KeyEquivalents/Resources/spinner.gif create mode 100644 Tests/Manual/KeyEquivalents/index-debug.html create mode 100644 Tests/Manual/KeyEquivalents/index.html create mode 100644 Tests/Manual/KeyEquivalents/main.j diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index 0a51a76a0..7af9e9888 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -140,21 +140,32 @@ var KeyCodesToPrevent = {}, 61: 187, // =, equals 59: 186 // ;, semicolon }, - KeyCodesToFunctionUnicodeMap = {}; + KeyCodesToUnicodeMap = {}; KeyCodesToPrevent[CPKeyCodes.A] = YES; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.BACKSPACE] = CPDeleteCharacter; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.DELETE] = CPDeleteFunctionKey; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.TAB] = CPTabCharacter; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.ENTER] = CPCarriageReturnCharacter; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.ESC] = CPEscapeFunctionKey; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.PAGE_UP] = CPPageUpFunctionKey; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.PAGE_DOWN] = CPPageDownFunctionKey; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.LEFT] = CPLeftArrowFunctionKey; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.UP] = CPUpArrowFunctionKey; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.RIGHT] = CPRightArrowFunctionKey; -KeyCodesToFunctionUnicodeMap[CPKeyCodes.DOWN] = CPDownArrowFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.BACKSPACE] = CPDeleteCharacter; +KeyCodesToUnicodeMap[CPKeyCodes.DELETE] = CPDeleteFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.TAB] = CPTabCharacter; +KeyCodesToUnicodeMap[CPKeyCodes.ENTER] = CPCarriageReturnCharacter; +KeyCodesToUnicodeMap[CPKeyCodes.ESC] = CPEscapeFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.PAGE_UP] = CPPageUpFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.PAGE_DOWN] = CPPageDownFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.LEFT] = CPLeftArrowFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.UP] = CPUpArrowFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.RIGHT] = CPRightArrowFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.DOWN] = CPDownArrowFunctionKey; +KeyCodesToUnicodeMap[CPKeyCodes.SEMICOLON] = ";"; +KeyCodesToUnicodeMap[CPKeyCodes.DASH] = "-"; +KeyCodesToUnicodeMap[CPKeyCodes.EQUALS] = "="; +KeyCodesToUnicodeMap[CPKeyCodes.COMMA] = ","; +KeyCodesToUnicodeMap[CPKeyCodes.PERIOD] = "."; +KeyCodesToUnicodeMap[CPKeyCodes.SLASH] = "/"; +KeyCodesToUnicodeMap[CPKeyCodes.APOSTROPHE] = "`"; +KeyCodesToUnicodeMap[CPKeyCodes.SINGLE_QUOTE] = "'"; +KeyCodesToUnicodeMap[CPKeyCodes.OPEN_SQUARE_BRACKET] = "["; +KeyCodesToUnicodeMap[CPKeyCodes.BACKSLASH] = "\\"; +KeyCodesToUnicodeMap[CPKeyCodes.CLOSE_SQUARE_BRACKET] = "]"; var ModifierKeyCodes = [ CPKeyCodes.META, @@ -642,9 +653,9 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; var characters; - // Is this a special key? + // Handle key codes for which String.fromCharCode won't work. if (aDOMEvent.which === 0 || aDOMEvent.charCode === 0) - characters = KeyCodesToFunctionUnicodeMap[_keyCode]; + characters = KeyCodesToUnicodeMap[_keyCode]; if (!characters) characters = String.fromCharCode(_keyCode).toLowerCase(); @@ -724,7 +735,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; var characters = overrideCharacters; // Is this a special key? if (!characters && (aDOMEvent.which === 0 || aDOMEvent.charCode === 0)) - characters = KeyCodesToFunctionUnicodeMap[charCode]; + characters = KeyCodesToUnicodeMap[charCode]; if (!characters) characters = String.fromCharCode(charCode); @@ -763,7 +774,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; if ([ModifierKeyCodes containsObject:keyCode]) break; - var characters = KeyCodesToFunctionUnicodeMap[charCode] || String.fromCharCode(charCode), + var characters = KeyCodesToUnicodeMap[charCode] || String.fromCharCode(charCode), charactersIgnoringModifiers = characters.toLowerCase(); if (!(modifierFlags & CPShiftKeyMask) && (modifierFlags & CPCommandKeyMask) && !_capsLockActive) diff --git a/Tests/Manual/KeyEquivalents/AppController.j b/Tests/Manual/KeyEquivalents/AppController.j new file mode 100644 index 000000000..8dcc6c177 --- /dev/null +++ b/Tests/Manual/KeyEquivalents/AppController.j @@ -0,0 +1,78 @@ +/* + * AppController.j + * cappuccino-keyequivalents + * + * Created by Alexander Ljungberg on July 20, 2010. + * Copyright 2010, WireLoad, LLC All rights reserved. + */ + +@import + + +@implementation AppController : CPObject +{ +} + +- (void)applicationDidFinishLaunching:(CPNotification)aNotification +{ + var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], + contentView = [theWindow contentView]; + + var label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [label setStringValue:@"Press Cmd-X on the keyboard for each button and verify that it reacts."]; + [label setFont:[CPFont boldSystemFontOfSize:24.0]]; + + [label sizeToFit]; + + [label setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin]; + [label setFrameOrigin:CGPointMake(10, 10)]; + + [contentView addSubview:label]; + + var keysToTest = [ + "a", + ";", + "-", + "=", + ",", + ".", + "/", + "`", + "'", + "[", + "\\", + "]" + ]; + + for (var i=0; i + + + + CPApplicationDelegateClass + AppController + CPBundleName + cappuccino-keyequivalents + CPPrincipalClass + CPApplication + + diff --git a/Tests/Manual/KeyEquivalents/Jakefile b/Tests/Manual/KeyEquivalents/Jakefile new file mode 100644 index 000000000..8fea6e453 --- /dev/null +++ b/Tests/Manual/KeyEquivalents/Jakefile @@ -0,0 +1,93 @@ +/* + * Jakefile + * cappuccino-keyequivalents + * + * Created by Alexander Ljungberg on July 20, 2010. + * Copyright 2010, WireLoad, LLC All rights reserved. + */ + +var ENV = require("system").env, + FILE = require("file"), + JAKE = require("jake"), + task = JAKE.task, + FileList = JAKE.FileList, + app = require("cappuccino/jake").app, + configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug", + OS = require("os"); + +app ("cappuccinoKeyequivalents", function(task) +{ + task.setBuildIntermediatesPath(FILE.join("Build", "cappuccinoKeyequivalents.build", configuration)); + task.setBuildPath(FILE.join("Build", configuration)); + + task.setProductName("cappuccino-keyequivalents"); + task.setIdentifier("com.yourcompany.cappuccinoKeyequivalents"); + task.setVersion("1.0"); + task.setAuthor("WireLoad, LLC"); + task.setEmail("feedback @nospam@ yourcompany.com"); + task.setSummary("cappuccino-keyequivalents"); + task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**"))); + task.setResources(new FileList("Resources/**")); + task.setIndexFilePath("index.html"); + task.setInfoPlistPath("Info.plist"); + + if (configuration === "Debug") + task.setCompilerFlags("-DDEBUG -g"); + else + task.setCompilerFlags("-O"); +}); + +task ("default", ["cappuccinoKeyequivalents"], function() +{ + printResults(configuration); +}); + +task ("build", ["default"]); + +task ("debug", function() +{ + ENV["CONFIGURATION"] = "Debug"; + JAKE.subjake(["."], "build", ENV); +}); + +task ("release", function() +{ + ENV["CONFIGURATION"] = "Release"; + JAKE.subjake(["."], "build", ENV); +}); + +task ("run", ["debug"], function() +{ + OS.system(["open", FILE.join("Build", "Debug", "cappuccinoKeyequivalents", "index.html")]); +}); + +task ("run-release", ["release"], function() +{ + OS.system(["open", FILE.join("Build", "Release", "cappuccinoKeyequivalents", "index.html")]); +}); + +task ("deploy", ["release"], function() +{ + FILE.mkdirs(FILE.join("Build", "Deployment", "cappuccinoKeyequivalents")); + OS.system(["press", "-f", FILE.join("Build", "Release", "cappuccinoKeyequivalents"), FILE.join("Build", "Deployment", "cappuccinoKeyequivalents")]); + printResults("Deployment") +}); + +task ("desktop", ["release"], function() +{ + FILE.mkdirs(FILE.join("Build", "Desktop", "cappuccinoKeyequivalents")); + require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "cappuccinoKeyequivalents"), FILE.join("Build", "Desktop", "cappuccinoKeyequivalents", "cappuccinoKeyequivalents.app")); + printResults("Desktop") +}); + +task ("run-desktop", ["desktop"], function() +{ + OS.system([FILE.join("Build", "Desktop", "cappuccinoKeyequivalents", "cappuccinoKeyequivalents.app", "Contents", "MacOS", "NativeHost"), "-i"]); +}); + +function printResults(configuration) +{ + print("----------------------------"); + print(configuration+" app built at path: "+FILE.join("Build", configuration, "cappuccinoKeyequivalents")); + print("----------------------------"); +} diff --git a/Tests/Manual/KeyEquivalents/Resources/spinner.gif b/Tests/Manual/KeyEquivalents/Resources/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..06dbc2bc21dddcf0e09b566d5b211aee89570f52 GIT binary patch literal 1849 zcma*odr(tX9tZHtz31lM+(&Y`A`Ou`NeG&R#DrIfV%?hng21vs6v>ooRQQFbk7E_K!V( z{?5!fpZWgIZ%*d6t%i*j24bL}AZUJm9)h6R*;%L4IWse3G#VWaN1#$zSSXcBhlYlH zJ|D}n{r&w2f+Qp)SS*&n?*G4}{}!h?td_mjU6Kad-rW*QwWYCUk7d^e+sjpZAn6kT z5rM;`{~_}-wm+L@%+E;JphLm}C3WzQAQD0wBoY|rOTQX{(@pp-WAA8Iw0HKl|15j) zhGh(SFWu#5zUCw^T!}C~eC}~?{xG-r7ugQC>taC+|L^xr&a%{#cgUOZXIM&v?)k^2 z1i5%0!U00wq)r4vlAwXBA_m5J5WNeuBm-XJQ5pG4GD%vc|K){+TJ{AkHqN@SJKczX zU}QRd9n*_bf^h94)6Ctv{CUfz_;qs#RDuQ$DR%y1&5G-a6rhf*4Y zl+UOD1*GE{GQ7vv;c-tTIMkz0ovO>9j%b5hpa@a*CBJ#W!0@ndSwF|%hMkdFtXiU) z`BEp+yhkt8ZY>tg&uyH@%^%K4jDrbA;et&vnnzZ3z22@e6<27z2Vk13kb7OtISyxv z(XoO-LNQCZe3lfzc%*pNqU<9T+p~teThOEB+~e&U0mC|zS{Q)dJZ)!^1f7L(zg*L> z*vSW%?dR~@@0(}x6-V^A`~ImD;)NaBUnP8;RH=bS2@pk`wp>>8r&jGjmGPy%1BW}v zoPo}ca$~bze@efc3kapuEVW1!%teOZT3j2Tw5=hjiAf02d}7dL0oFC%@=RXp5Ow#% z@a>+AM|YWt$n&e`>sB-32gBcuTi>R>*|8@lp`y6thc7ydyqDsuUn~YzZf|{-R@-3y zL#wx{Ii}xxL_csiW*LBn0-A$>zp4WOmkf6=ilrjlW?-l9+bCd7|i?*b5NTmy<<6NZ0T8$SN@mwdC2f z6jqK=N@bS@!=YSj%>h0}*4p+%0HbTIrE$w7UMT6+AZZ&DAo*qZAAi(OtNbIfl#Dw^ zJWeiCp~zi#&t6x}m9)O^eR4HiLV3QA<<0>HZ8%$^lrSE94Wb}=+MM^!b>n#5&-JQR zkr-CEu9C;_F*7DqDisulV6Pmg$nFL0TPn%~*m^-`Z3^BgU(sNpnx%nW(!eV9A&FvI zHL3X3lw8Wji^6=8KbQDE-e%b?svdFxxdh$8r97@7$ojeI`6AL8Ob6QC$qh&>ZWVDX1F{0vJnT%%mE;GveKWR%C} zM&4d;Jf3s9|HAA)yVUPo`Aq;0do#)uHSXi5*QF*)x@MVVHr+cN)uMZ__F|&Ta#p8d z53TOKtce!PJUuie8UWol-S(`c2nH?UGqJP{!4RR4u$LCfn)q-hj0^f=h(VYy)T6eN zhRO!ja-aDBTcgeyP(8Ua4IdiOog^*CQa?R(cP#9AgL9`j>EX-6Yf1lzX(!~``M1XC zNmM<4<6d~wWZ$Xrk0K}UteTrq@LBBk#MsjkK;pbuVhe)NI7(7Pf(l?lxC7=1Z7Pzl zMbS;nV4NI5_N{1$P)&XC)huOGQ+h^zpYUZfb*1n6>!`#*b3y52LGmi+<4sY5jyD#- zw&$d}DTguLAfnRtjrM*JfqtHqUu6rQoU=g%1E9xk%;)TDm^2<8n-0IhTsQFaek)MY}>PK4;nBk=ow4pF>vzkO& gna%Org-kgQCf=+BeMi^RbuY;YE~rTjend;_cdi8t>i_@% literal 0 HcmV?d00001 diff --git a/Tests/Manual/KeyEquivalents/index-debug.html b/Tests/Manual/KeyEquivalents/index-debug.html new file mode 100644 index 000000000..cb9946076 --- /dev/null +++ b/Tests/Manual/KeyEquivalents/index-debug.html @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + cappuccino-keyequivalents + + + + + + + + + + + + + + +
+
+ + + +
+
+ + + diff --git a/Tests/Manual/KeyEquivalents/index.html b/Tests/Manual/KeyEquivalents/index.html new file mode 100644 index 000000000..2519046d2 --- /dev/null +++ b/Tests/Manual/KeyEquivalents/index.html @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + cappuccino-keyequivalents + + + + + + + + + + + + +
+
+ + + +
+
+ + + + diff --git a/Tests/Manual/KeyEquivalents/main.j b/Tests/Manual/KeyEquivalents/main.j new file mode 100644 index 000000000..59e978a1b --- /dev/null +++ b/Tests/Manual/KeyEquivalents/main.j @@ -0,0 +1,18 @@ +/* + * AppController.j + * cappuccino-keyequivalents + * + * Created by Alexander Ljungberg on July 20, 2010. + * Copyright 2010, WireLoad, LLC All rights reserved. + */ + +@import +@import + +@import "AppController.j" + + +function main(args, namedArgs) +{ + CPApplicationMain(args, namedArgs); +} From 4d1baac4dbb92008d6000bf3eef63213962e2369 Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Sun, 18 Jul 2010 23:52:57 -0400 Subject: [PATCH 11/19] Fixed: first clearing a \r keqyEquivalent from one button and then setting it on another would result in an exception. --- AppKit/CPButton.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j index 3bc21844b..c2f212644 100644 --- a/AppKit/CPButton.j +++ b/AppKit/CPButton.j @@ -574,7 +574,7 @@ CPButtonStateMixed = CPThemeState("mixed"); if (aString === CPNewlineCharacter || aString === CPCarriageReturnCharacter) [[self window] setDefaultButton:self]; else if ([[self window] defaultButton] === self) - [[self window] setDefaultButton:NO]; + [[self window] setDefaultButton:nil]; _keyEquivalent = aString || @""; } From cffbf863517019862627ae1c8f2f3e3789170cca Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Thu, 22 Jul 2010 00:21:02 -0500 Subject: [PATCH 12/19] TableView theming --- AppKit/CPTableColumn.j | 15 +--- AppKit/CPTableHeaderView.j | 35 ++++++-- AppKit/CPTableView.j | 85 +++++++++--------- AppKit/CPTheme.j | 3 +- AppKit/CPView.j | 3 + .../tableview-headerview-ascending.png | Bin .../tableview-headerview-descending.png | Bin AppKit/Themes/Aristo/ThemeDescriptors.j | 73 ++++++++++++++- AppKit/_CPCornerView.j | 29 ++++-- 9 files changed, 174 insertions(+), 69 deletions(-) rename AppKit/{ => Themes/Aristo}/Resources/tableview-headerview-ascending.png (100%) rename AppKit/{ => Themes/Aristo}/Resources/tableview-headerview-descending.png (100%) diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j index 91edc5d50..59b44e97e 100644 --- a/AppKit/CPTableColumn.j +++ b/AppKit/CPTableColumn.j @@ -78,18 +78,7 @@ CPTableColumnUserResizingMask = 1 << 1; var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMakeZero()]; [self setHeaderView:header]; - var textDataView = [CPTextField new]; - - [textDataView setValue:[CPColor colorWithRed:51.0 / 255.0 green:51.0 / 255.0 blue:51.0 / 255.0 alpha:1.0] - forThemeAttribute:"text-color"]; - - [textDataView setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateSelectedDataView]; - [textDataView setLineBreakMode:CPLineBreakByTruncatingTail]; - [textDataView setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateSelectedDataView]; - [textDataView setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"]; - [textDataView setValue:CGInsetMake(0.0, 0.0, 0.0, 5.0) forThemeAttribute:@"content-inset"]; - - [self setDataView:textDataView]; + [self setDataView:[CPTextField new]]; } return self; @@ -259,6 +248,8 @@ CPTableColumnUserResizingMask = 1 << 1; if (_dataView) _dataViewData[[_dataView UID]] = nil; + [aView setThemeState:CPThemeStateTableDataView]; + _dataView = aView; _dataViewData[[aView UID]] = [CPKeyedArchiver archivedDataWithRootObject:aView]; } diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index 223cfec2b..be8d64798 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -33,13 +33,13 @@ + (CPString)themeClass { - return @"tableHeader"; + return @"columnHeader"; } + (id)themeAttributes { - return [CPDictionary dictionaryWithObjects:[[CPNull null], CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], CGSizeMakeZero()] - forKeys:[@"background-color", @"text-inset", @"text-color", @"text-font", @"text-shadow-color", @"text-shadow-offset"]]; + return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null], CGInsetMakeZero(), [CPNull null], [CPNull null], [CPNull null], CGSizeMakeZero()] + forKeys:[@"background-color", @"text-alignment", @"text-inset", @"text-color", @"text-font", @"text-shadow-color", @"text-shadow-offset"]]; } - (void)initWithFrame:(CGRect)frame @@ -76,6 +76,7 @@ [_textField setFont:[self currentValueForThemeAttribute:@"text-font"]]; [_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]]; [_textField setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]]; + [_textField setAlignment:[self currentValueForThemeAttribute:@"text-alignment"]]; } - (void)setStringValue:(CPString)string @@ -158,12 +159,24 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal BOOL _isResizing; BOOL _isDragging; BOOL _isTrackingColumn; + BOOL _drawsColumnLines; float _columnOldWidth; CPTableView _tableView @accessors(property=tableView); } ++ (CPString)themeClass +{ + return @"tableHeaderRow"; +} + ++ (id)themeAttributes +{ + return [CPDictionary dictionaryWithObjects:[[CPNull null]] + forKeys:[@"background-color"]]; +} + - (void)_init { _mouseDownLocation = CPPointMakeZero(); @@ -177,7 +190,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal _columnOldWidth = 0.0; - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 23.0))]]; + [self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]]; } - (id)initWithFrame:(CGRect)aFrame @@ -206,6 +219,16 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal return headerRect; } +- (void)setDrawsColumnLines:(BOOL)aFlag +{ + _drawsColumnLines = aFlag; +} + +- (BOOL)drawsColumnLines +{ + return _drawsColumnLines; +} + - (CGRect)_cursorRectForColumn:(int)column { if (column == -1 || !([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask)) @@ -582,11 +605,13 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal if([headerView superview] != self) [self addSubview:headerView]; } + + [self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]]; } - (void)drawRect:(CGRect)aRect { - if (!_tableView) + if (!_tableView || ![self drawsColumnLines]) return; var context = [[CPGraphicsContext currentContext] graphicsPort], diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index ad854587a..24c961792 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -165,6 +165,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; BOOL _allowsEmptySelection; CPArray _sortDescriptors; + //Setting Display Attributes CGSize _intercellSpacing; float _rowHeight; @@ -174,9 +175,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; unsigned _selectionHighlightStyle; CPTableColumn _currentHighlightedTableColumn; - CPColor _selectionHighlightColor; unsigned _gridStyleMask; - CPColor _gridColor; unsigned _numberOfRows; @@ -215,12 +214,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; BOOL _disableAutomaticResizing @accessors(property=disableAutomaticResizing); BOOL _lastColumnShouldSnap; - CPGradient _sourceListActiveGradient; - CPColor _sourceListActiveTopLineColor; - CPColor _sourceListActiveBottomLineColor; - int _draggedColumnIndex; - CPArray _differedColumnDataToRemove; + CPArray _differedColumnDataToRemove; /* CPGradient _sourceListInactiveGradient; @@ -229,6 +224,17 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ } ++ (CPString)themeClass +{ + return @"tableview"; +} + ++ (id)themeAttributes +{ + return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null], [CPNull null]] + forKeys:["alternating-row-colors", "grid-color", "highlighted-grid-color", "selection-color", "sourcelist-selection-color", "sort-image", "sort-image-reversed"]]; +} + - (id)initWithFrame:(CGRect)aFrame { self = [super initWithFrame:aFrame]; @@ -588,17 +594,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (void)setAlternatingRowBackgroundColors:(CPArray)alternatingRowBackgroundColors { - if ([_alternatingRowBackgroundColors isEqual:alternatingRowBackgroundColors]) - return; - - _alternatingRowBackgroundColors = alternatingRowBackgroundColors; + [self setValue:alternatingRowBackgroundColors forThemeAttribute:"alternating-row-colors"]; [self setNeedsDisplay:YES]; } - (CPArray)alternatingRowBackgroundColors { - return _alternatingRowBackgroundColors; + return [self currentValueForThemeAttribute:@"alternating-row-colors"]; } - (unsigned)selectionHighlightStyle @@ -627,10 +630,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (void)setSelectionHighlightColor:(CPColor)aColor { - if (aColor === _selectionHighlightColor) - return; + [self setValue:aColor forThemeAttribute:"selection-color"]; - _selectionHighlightColor = aColor; [self setNeedsDisplay:YES]; } @@ -639,7 +640,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (CPColor)selectionHighlightColor { - return _selectionHighlightColor; + return [self currentValueForThemeAttribute:@"selection-color"]; } /*! @@ -652,12 +653,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (void)setSelectionGradientColors:(CPDictionary)aDictionary { - if ([aDictionary valueForKey:"CPSourceListGradient"] === _sourceListActiveGradient && [aDictionary valueForKey:"CPSourceListTopLineColor"] === _sourceListActiveTopLineColor && [aDictionary valueForKey:"CPSourceListBottomLineColor"] === _sourceListActiveBottomLineColor) - return; + [self setValue:aDictionary forThemeAttribute:"sourcelist-selection-color"]; - _sourceListActiveGradient = [aDictionary valueForKey:CPSourceListGradient]; - _sourceListActiveTopLineColor = [aDictionary valueForKey:CPSourceListTopLineColor]; - _sourceListActiveBottomLineColor = [aDictionary valueForKey:CPSourceListBottomLineColor]; [self setNeedsDisplay:YES]; } @@ -669,7 +666,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (CPDictionary)selectionGradientColors { - return [CPDictionary dictionaryWithObjects:[_sourceListActiveGradient, _sourceListActiveTopLineColor, _sourceListActiveBottomLineColor] forKeys:[CPSourceListGradient, CPSourceListTopLineColor, CPSourceListBottomLineColor]]; + return [self currentValueForThemeAttribute:@"sourcelist-selection-color"]; } /*! @@ -678,17 +675,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (void)setGridColor:(CPColor)aColor { - if (_gridColor === aColor) - return; - - _gridColor = aColor; + [self setValue:aColor forThemeAttribute:"grid-color"]; [self setNeedsDisplay:YES]; } - (CPColor)gridColor { - return _gridColor; + return [self currentValueForThemeAttribute:@"grid-color"];; } /*! @@ -1914,7 +1908,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [newSortDescriptors insertObject:newMainSortDescriptor atIndex:0]; // Update indicator image & highlighted column before - var image = [newMainSortDescriptor ascending] ? [CPTableView _defaultTableHeaderSortImage] : [CPTableView _defaultTableHeaderReverseSortImage]; + var image = [newMainSortDescriptor ascending] ? [self _tableHeaderSortImage] : [self _tableHeaderReverseSortImage]; [self setIndicatorImage:nil inTableColumn:_currentHighlightedTableColumn]; [self setIndicatorImage:image inTableColumn:tableColumn]; @@ -1929,14 +1923,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [[aTableColumn headerView] _setIndicatorImage:anImage]; } -+ (CPImage)_defaultTableHeaderSortImage +- (CPImage)_tableHeaderSortImage { - return CPAppKitImage("tableview-headerview-ascending.png", CGSizeMake(9.0, 8.0)); + return [self currentValueForThemeAttribute:"sort-image"]; } -+ (CPImage)_defaultTableHeaderReverseSortImage +- (CPImage)_tableHeaderReverseSortImage { - return CPAppKitImage("tableview-headerview-descending.png", CGSizeMake(9.0, 8.0)); + return [self currentValueForThemeAttribute:"sort-image-reversed"]; } //Highlightable Column Headers @@ -2636,7 +2630,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; } CGContextClosePath(context); - CGContextSetStrokeColor(context, _gridColor); + CGContextSetStrokeColor(context, [self gridColor]); CGContextStrokePath(context); } @@ -2679,6 +2673,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; deltaHeight = 0.5 * (_gridStyleMask & CPTableViewSolidHorizontalGridLineMask); CGContextBeginPath(context); + + var gradientCache = [self selectionGradientColors], + topLineColor = [gradientCache objectForKey:CPSourceListTopLineColor], + bottomLineColor = [gradientCache objectForKey:CPSourceListBottomLineColor], + gradientColor = [gradientCache objectForKey:CPSourceListGradient]; + while (count--) { var rowRect = CGRectIntersection(objj_msgSend(self, rectSelector, indexes[count]), aRect); @@ -2691,21 +2691,21 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; maxX = _CGRectGetMaxX(rowRect), maxY = _CGRectGetMaxY(rowRect) - deltaHeight; - CGContextDrawLinearGradient(context, _sourceListActiveGradient, rowRect.origin, CGPointMake(minX, maxY), 0); + CGContextDrawLinearGradient(context, gradientColor, rowRect.origin, CGPointMake(minX, maxY), 0); CGContextClosePath(context); CGContextBeginPath(context); CGContextMoveToPoint(context, minX, minY); CGContextAddLineToPoint(context, maxX, minY); CGContextClosePath(context); - CGContextSetStrokeColor(context, _sourceListActiveTopLineColor); + CGContextSetStrokeColor(context, topLineColor); CGContextStrokePath(context); CGContextBeginPath(context); CGContextMoveToPoint(context, minX, maxY); CGContextAddLineToPoint(context, maxX, maxY - 1); CGContextClosePath(context); - CGContextSetStrokeColor(context, _sourceListActiveBottomLineColor); + CGContextSetStrokeColor(context, bottomLineColor); CGContextStrokePath(context); } } @@ -2714,7 +2714,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; if (!drawGradient) { - [_selectionHighlightColor setFill]; + [[self selectionHighlightColor] setFill]; CGContextFillPath(context); } @@ -2757,7 +2757,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; } CGContextClosePath(context); - CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"e5e5e5"]); + CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:"highlighted-grid-color"]); CGContextStrokePath(context); } @@ -3537,12 +3537,11 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", _intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey] || _CGSizeMake(0.0, 0.0); - _gridColor = [aCoder decodeObjectForKey:CPTableViewGridColorKey] || [CPColor grayColor]; + [self setGridColor:[aCoder decodeObjectForKey:CPTableViewGridColorKey] || [CPColor grayColor]]; _gridStyleMask = [aCoder decodeIntForKey:CPTableViewGridStyleMaskKey] || CPTableViewGridNone; _usesAlternatingRowBackgroundColors = [aCoder decodeObjectForKey:CPTableViewUsesAlternatingBackgroundKey]; - _alternatingRowBackgroundColors = - [[CPColor whiteColor], [CPColor colorWithRed:245.0 / 255.0 green:249.0 / 255.0 blue:252.0 / 255.0 alpha:1.0]]; + [self setAlternatingRowBackgroundColors:[aCoder decodeObjectForKey:CPTableViewAlternatingRowColorsKey]]; _headerView = [aCoder decodeObjectForKey:CPTableViewHeaderViewKey]; _cornerView = [aCoder decodeObjectForKey:CPTableViewCornerViewKey]; @@ -3576,11 +3575,11 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", [aCoder encodeObject:_tableColumns forKey:CPTableViewTableColumnsKey]; - [aCoder encodeObject:_gridColor forKey:CPTableViewGridColorKey]; + [aCoder encodeObject:[self gridColor] forKey:CPTableViewGridColorKey]; [aCoder encodeInt:_gridStyleMask forKey:CPTableViewGridStyleMaskKey]; [aCoder encodeBool:_usesAlternatingRowBackgroundColors forKey:CPTableViewUsesAlternatingBackgroundKey]; - [aCoder encodeObject:_alternatingRowBackgroundColors forKey:CPTableViewAlternatingRowColorsKey] + [aCoder encodeObject:[self alternatingRowBackgroundColors] forKey:CPTableViewAlternatingRowColorsKey] [aCoder encodeObject:_cornerView forKey:CPTableViewCornerViewKey]; [aCoder encodeObject:_headerView forKey:CPTableViewHeaderViewKey]; diff --git a/AppKit/CPTheme.j b/AppKit/CPTheme.j index 4b37e6d7a..a1d27c8e5 100644 --- a/AppKit/CPTheme.j +++ b/AppKit/CPTheme.j @@ -242,7 +242,8 @@ CPThemeStateNormal = CPThemeStates["normal"] = 0; CPThemeStateDisabled = CPThemeState("disabled"); CPThemeStateHighlighted = CPThemeState("highlighted"); CPThemeStateSelected = CPThemeState("selected"); -CPThemeStateSelectedDataView = CPThemeState("selectedDataView"); +CPThemeStateTableDataView = CPThemeState("tableDataView"); +CPThemeStateSelectedDataView = CPThemeStateSelectedTableDataView = CPThemeState("selectedTableDataView"); CPThemeStateBezeled = CPThemeState("bezeled"); CPThemeStateBordered = CPThemeState("bordered"); CPThemeStateEditable = CPThemeState("editable"); diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 51356c8d2..7b1c193d6 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -1364,6 +1364,9 @@ var CPViewFlags = { }, if (_backgroundColor == aColor) return; + if (aColor == [CPNull null]) + aColor = nil; + _backgroundColor = aColor; #if PLATFORM(DOM) diff --git a/AppKit/Resources/tableview-headerview-ascending.png b/AppKit/Themes/Aristo/Resources/tableview-headerview-ascending.png similarity index 100% rename from AppKit/Resources/tableview-headerview-ascending.png rename to AppKit/Themes/Aristo/Resources/tableview-headerview-ascending.png diff --git a/AppKit/Resources/tableview-headerview-descending.png b/AppKit/Themes/Aristo/Resources/tableview-headerview-descending.png similarity index 100% rename from AppKit/Resources/tableview-headerview-descending.png rename to AppKit/Themes/Aristo/Resources/tableview-headerview-descending.png diff --git a/AppKit/Themes/Aristo/ThemeDescriptors.j b/AppKit/Themes/Aristo/ThemeDescriptors.j index 9d8b9954e..7950ac5ba 100755 --- a/AppKit/Themes/Aristo/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo/ThemeDescriptors.j @@ -356,6 +356,16 @@ [textfield setStringValue:""]; [textfield setEditable:YES]; + + // tableview dataview stuff + [textfield setValue:[CPColor colorWithRed:51.0 / 255.0 green:51.0 / 255.0 blue:51.0 / 255.0 alpha:1.0] forThemeAttribute:"text-color" inState:CPThemeStateTableDataView]; + [textfield setValue:CPLineBreakByTruncatingTail forThemeAttribute:@"line-break-mode" inState:CPThemeStateTableDataView|CPThemeStateTableDataView]; + [textfield setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment" inState:CPThemeStateTableDataView|CPThemeStateTableDataView]; + [textfield setValue:CGInsetMake(0.0, 0.0, 0.0, 5.0) forThemeAttribute:@"content-inset" inState:CPThemeStateTableDataView|CPThemeStateTableDataView]; + [textfield setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateTableDataView|CPThemeStateSelectedTableDataView]; + [textfield setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateTableDataView|CPThemeStateSelectedTableDataView]; + + return textfield; } @@ -773,7 +783,7 @@ return buttonBar; } -+ (_CPTableColumnHeaderView)themedTableHeader ++ (_CPTableColumnHeaderView)themedColumnHeader { var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMake(0,0,50,24)], highlightedPressed = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"tableview-headerview-highlighted-pressed.png" size:CGSizeMake(1.0, 23.0)]], @@ -790,6 +800,7 @@ [header setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"text-font"]; [header setValue:[CPColor whiteColor] forThemeAttribute:@"text-shadow-color"]; [header setValue:CGSizeMake(0,1) forThemeAttribute:@"text-shadow-offset"]; + [header setValue:CPLeftTextAlignment forThemeAttribute:@"text-alignment"]; [header setValue:pressed forThemeAttribute:@"background-color" inState:CPThemeStateHighlighted]; [header setValue:highlighted forThemeAttribute:@"background-color" inState:CPThemeStateSelected]; @@ -798,6 +809,66 @@ return header; } ++ (CPTableHeaderView)themedTableHeaderRow +{ + var header = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0,0,50,24)], + normal = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"tableview-headerview.png" size:CGSizeMake(1.0, 23.0)]]; + + [header setValue:normal forThemeAttribute:@"background-color"]; + + return header; +} + ++ (_CPCornerView)themedCornerview +{ + var corner = [[_CPCornerView alloc] initWithFrame:CGRectMake(0,0,25, 23)], + normal = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"tableview-headerview.png" size:CGSizeMake(1.0, 23.0)]]; + + [corner setValue:normal forThemeAttribute:"background-color"]; + + return corner; +} + ++ (CPTableView)themedTableView +{ + // This is a bit more complicated than the rest because we actually set theme values for several different (table related) controls in this method + + var tableview = [[CPTableView alloc] initWithFrame:CGRectMake(0,0,200,200)]; + + // Now theme the tableview + var sortImage = [_CPCibCustomResource imageResourceWithName:"tableview-headerview-ascending.png" size:CGSizeMake(9.0, 8.0)], + sortImageReversed = [_CPCibCustomResource imageResourceWithName:"tableview-headerview-descending.png" size:CGSizeMake(9.0, 8.0)], + alternatingRowColors = [[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"]], + gridColor = [CPColor colorWithHexString:@"dce0e2"], + selectionColor = [CPColor colorWithHexString:@"5f83b9"], + sourceListSelectionColor = [CPDictionary dictionaryWithObjects: [ CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [89.0/255.0, 153.0/255.0, 209.0/255.0,1.0, 33.0/255.0, 94.0/255.0, 208.0/255.0,1.0], [0,1], 2), + [CPColor colorWithCalibratedRed:(61.0/255.0) green:(123.0/255.0) blue:(218.0/255.0) alpha:1.0], + [CPColor colorWithCalibratedRed:(31.0/255.0) green:(92.0/255.0) blue:(207.0/255.0) alpha:1.0] + ] + forKeys: [CPSourceListGradient, CPSourceListTopLineColor, CPSourceListBottomLineColor]]; + + [tableview setValue:alternatingRowColors forThemeAttribute:"alternating-row-colors"]; + [tableview setValue:gridColor forThemeAttribute:"grid-color"]; + [tableview setValue:[CPColor whiteColor] forThemeAttribute:"highlighted-grid-color"]; + [tableview setValue:selectionColor forThemeAttribute:"selection-color"]; + [tableview setValue:sourceListSelectionColor forThemeAttribute:"sourcelist-selection-color"]; + [tableview setValue:sortImage forThemeAttribute:"sort-image"]; + [tableview setValue:sortImageReversed forThemeAttribute:"sort-image-reversed"]; + + return tableview; +} + ++ (CPTextField)themedTableDataView +{ + var view = [self themedStandardTextField]; + + [view setBezeled:NO]; + [view setEditable:NO]; + [view setThemeState:CPThemeStateTableDataView]; + + return view; +} + @end @implementation AristoHUDThemeDescriptor : BKThemeDescriptor diff --git a/AppKit/_CPCornerView.j b/AppKit/_CPCornerView.j index a5e4f9a65..33925e5c2 100644 --- a/AppKit/_CPCornerView.j +++ b/AppKit/_CPCornerView.j @@ -1,21 +1,36 @@ - @import "CPView.j" @implementation _CPCornerView : CPView { } ++ (CPString)themeClass +{ + return @"cornerview"; +} + ++ (id)themeAttributes +{ + return [CPDictionary dictionaryWithObjects:[[CPNull null]] + forKeys:[@"background-color"]]; +} + +- (void)layoutSubviews +{ + [self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]]; +} + - (void)_init { - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 23.0))]]; + [self setBackgroundColor:[self currentValueForThemeAttribute:@"background-color"]]; } - (id)initWithFrame:(CGRect)aFrame { - if (self = [super initWithFrame:aFrame]) - { + self = [super initWithFrame:aFrame] + + if (self) [self _init]; - } return self; } @@ -23,9 +38,9 @@ - (id)initWithCoder:(CPCoder)aCoder { self = [super initWithCoder:aCoder]; - { + + if (self) [self _init]; - } return self; } From ff8e5ae42e2f2f141ff2a3ba80a397bafd08d785 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 7 Jul 2010 15:35:12 +0200 Subject: [PATCH 13/19] save _replacedKeys on the class in stead of the object instance reviewed: Ross --- Foundation/CPKeyValueObserving.j | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Foundation/CPKeyValueObserving.j b/Foundation/CPKeyValueObserving.j index 0ff9fdd26..6ea9c9a42 100644 --- a/Foundation/CPKeyValueObserving.j +++ b/Foundation/CPKeyValueObserving.j @@ -213,7 +213,6 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, _targetObject = aTarget; _nativeClass = [aTarget class]; - _replacedKeys = [CPSet set]; _observersForKey = {}; _changesForKey = {}; _observersForKeyLength = 0; @@ -230,6 +229,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, if (existingKVOClass) { _targetObject.isa = existingKVOClass; + _replacedKeys = existingKVOClass._replacedKeys; return; } @@ -237,6 +237,9 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, objj_registerClassPair(kvoClass); + _replacedKeys = [CPSet set]; + kvoClass._replacedKeys = _replacedKeys; + //copy in the methods from our model subclass var methodList = _CPKVOModelSubclass.method_list, count = methodList.length, @@ -293,6 +296,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, var theMethod = class_getInstanceMethod(_nativeClass, theSelector); class_addMethod(_targetObject.isa, theSelector, theReplacementMethod(aKey, theMethod), ""); + [_replacedKeys addObject:aKey]; } } From 0306c35b54e6233911f45f31fd4254af28ab8fbe Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 7 Jul 2010 18:24:24 +0200 Subject: [PATCH 14/19] don't copy the selection indexes in setContent: --- AppKit/CPArrayController.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPArrayController.j b/AppKit/CPArrayController.j index c11206f79..4953c3016 100644 --- a/AppKit/CPArrayController.j +++ b/AppKit/CPArrayController.j @@ -154,7 +154,7 @@ value = [value]; var oldSelection = nil, - oldSelectionIndexes = [[self selectionIndexes] copy]; + oldSelectionIndexes = [self selectionIndexes]; if ([self preservesSelection]) oldSelection = [self selectedObjects]; From 8ce63a244cabef7cb2038b3a5afe2ca7e5ba8b50 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 7 Jul 2010 18:24:44 +0200 Subject: [PATCH 15/19] store accessors in a javascript object not a CPDictionary, for slight performance improvement --- Foundation/CPKeyValueCoding.j | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Foundation/CPKeyValueCoding.j b/Foundation/CPKeyValueCoding.j index 104a6931f..c2691bd47 100644 --- a/Foundation/CPKeyValueCoding.j +++ b/Foundation/CPKeyValueCoding.j @@ -33,6 +33,9 @@ CPUndefinedKeyException = @"CPUndefinedKeyException"; CPTargetObjectUserInfoKey = @"CPTargetObjectUserInfoKey"; CPUnknownUserInfoKey = @"CPUnknownUserInfoKey"; +var CPObjectAccessorsForClassKey = @"$CPObjectAccessorsForClassKey", + CPObjectModifiersForClassKey = @"$CPObjectModifiersForClassKey"; + @implementation CPObject (CPKeyValueCoding) + (BOOL)accessInstanceVariablesDirectly @@ -43,26 +46,18 @@ CPUnknownUserInfoKey = @"CPUnknownUserInfoKey"; /* @ignore */ + (SEL)_accessorForKey:(CPString)aKey { - if (!CPObjectAccessorsForClass) - CPObjectAccessorsForClass = [CPDictionary dictionary]; - - var UID = [isa UID], - selector = nil, - accessors = [CPObjectAccessorsForClass objectForKey:UID]; + var selector = nil, + accessors = isa[CPObjectAccessorsForClassKey]; if (accessors) { - selector = [accessors objectForKey:aKey]; + selector = accessors[aKey]; if (selector) return selector === [CPNull null] ? nil : selector; } else - { - accessors = [CPDictionary dictionary]; - - [CPObjectAccessorsForClass setObject:accessors forKey:UID]; - } + accessors = isa[CPObjectAccessorsForClassKey] = {}; var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1); @@ -73,12 +68,12 @@ CPUnknownUserInfoKey = @"CPUnknownUserInfoKey"; [self instancesRespondToSelector:selector = CPSelectorFromString("_" + aKey)] || [self instancesRespondToSelector:selector = CPSelectorFromString("_is" + capitalizedKey)]) { - [accessors setObject:selector forKey:aKey]; + accessors[aKey] = selector; return selector; } - [accessors setObject:[CPNull null] forKey:aKey]; + accessors[aKey] = [CPNull null]; return nil; } From d947c849c87598921b860d399fd5e11cc31349bd Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 8 Jul 2010 16:26:17 +0200 Subject: [PATCH 16/19] made _accessorForKey slightly faster by inlining it as a function --- Foundation/CPKeyValueCoding.j | 37 ++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Foundation/CPKeyValueCoding.j b/Foundation/CPKeyValueCoding.j index c2691bd47..1449899e4 100644 --- a/Foundation/CPKeyValueCoding.j +++ b/Foundation/CPKeyValueCoding.j @@ -151,7 +151,7 @@ var CPObjectAccessorsForClassKey = @"$CPObjectAccessorsForClassKey", - (id)valueForKey:(CPString)aKey { var theClass = [self class], - selector = [theClass _accessorForKey:aKey]; + selector = _accessorForKey(theClass, aKey); if (selector) return objj_msgSend(self, selector); @@ -259,6 +259,41 @@ var CPObjectAccessorsForClassKey = @"$CPObjectAccessorsForClassKey", @end +var Null = [CPNull null]; +var _accessorForKey = function(theClass, aKey) +{ + var selector = nil, + accessors = theClass.isa[CPObjectAccessorsForClassKey]; + + if (accessors) + { + selector = accessors[aKey]; + + if (selector) + return selector === Null ? nil : selector; + } + else + accessors = theClass.isa[CPObjectAccessorsForClassKey] = {}; + + var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1); + + if ([theClass instancesRespondToSelector:selector = CPSelectorFromString("get" + capitalizedKey)] || + [theClass instancesRespondToSelector:selector = CPSelectorFromString(aKey)] || + [theClass instancesRespondToSelector:selector = CPSelectorFromString("is" + capitalizedKey)] || + [theClass instancesRespondToSelector:selector = CPSelectorFromString("_get" + capitalizedKey)] || + [theClass instancesRespondToSelector:selector = CPSelectorFromString("_" + aKey)] || + [theClass instancesRespondToSelector:selector = CPSelectorFromString("_is" + capitalizedKey)]) + { + accessors[aKey] = selector; + + return selector; + } + + accessors[aKey] = Null; + + return nil; +} + @implementation CPDictionary (KeyValueCoding) - (id)valueForKey:(CPString)aKey From 78fd9723120e6bc3dc96a7e1fd8cad1083d8c3d1 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 2 Jun 2010 15:50:21 +0200 Subject: [PATCH 17/19] only reverse set the binding on end editing --- AppKit/CPControl.j | 1 + 1 file changed, 1 insertion(+) diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index 7de6719c4..db8a22cd9 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -545,6 +545,7 @@ var CPControlBlackColor = [CPColor blackColor]; return; [self _reverseSetBinding]; + [[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]]; } From 560ea75a253e44d8242f7314ebe795e8ceec34d0 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 4 Jun 2010 15:41:12 +0200 Subject: [PATCH 18/19] added CPArrayController to AppKit.j --- AppKit/AppKit.j | 1 + 1 file changed, 1 insertion(+) diff --git a/AppKit/AppKit.j b/AppKit/AppKit.j index 9c820be65..95bbe6201 100644 --- a/AppKit/AppKit.j +++ b/AppKit/AppKit.j @@ -88,3 +88,4 @@ @import "CPWebView.j" @import "CPWindow.j" @import "CPWindowController.j" +@import "CPArrayController.j" From 90e9b86497ef767015f08f0043fca9965cace6de Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 26 Jul 2010 14:23:52 +0200 Subject: [PATCH 19/19] match CPTableView's alternating row colors with Aristo's --- AppKit/Themes/Aristo/ThemeDescriptors.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/Themes/Aristo/ThemeDescriptors.j b/AppKit/Themes/Aristo/ThemeDescriptors.j index 7950ac5ba..ec1245de8 100755 --- a/AppKit/Themes/Aristo/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo/ThemeDescriptors.j @@ -838,7 +838,7 @@ // Now theme the tableview var sortImage = [_CPCibCustomResource imageResourceWithName:"tableview-headerview-ascending.png" size:CGSizeMake(9.0, 8.0)], sortImageReversed = [_CPCibCustomResource imageResourceWithName:"tableview-headerview-descending.png" size:CGSizeMake(9.0, 8.0)], - alternatingRowColors = [[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"]], + alternatingRowColors = [[CPColor whiteColor], [CPColor colorWithRed:245.0 / 255.0 green:249.0 / 255.0 blue:252.0 / 255.0 alpha:1.0]], gridColor = [CPColor colorWithHexString:@"dce0e2"], selectionColor = [CPColor colorWithHexString:@"5f83b9"], sourceListSelectionColor = [CPDictionary dictionaryWithObjects: [ CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [89.0/255.0, 153.0/255.0, 209.0/255.0,1.0, 33.0/255.0, 94.0/255.0, 208.0/255.0,1.0], [0,1], 2),