From 11d30566bfc71a6c152880fffb3d43c17d74c51d Mon Sep 17 00:00:00 2001 From: cacaodev Date: Sun, 31 Jan 2010 22:12:37 +0100 Subject: [PATCH 01/12] CPTableHeaderView: change background in -layoutSubviews instead of -setThemeState: ; Added a CPThemeStatePressed used privately, makes things easier for custom headers --- AppKit/CPTableHeaderView.j | 108 +++++++++++++++---------------------- 1 file changed, 44 insertions(+), 64 deletions(-) diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index 9b298b812..12eb5294b 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -23,26 +23,27 @@ @import "CPTableColumn.j" @import "CPTableView.j" @import "CPView.j" -@import +/*@import var _headerGradient = nil, _selectedHeaderGradient = nil, _pressedHeaderGradient = nil, - _selectedPressedHeaderGradient = nil, - - supportsCanvasGradient = NO; + _selectedPressedHeaderGradient = nil, + supportsCanvasGradient = NO;*/ + +var CPThemeStatePressed = CPThemeState("pressed"); // FIX ME: _CPTableColumnHeaderView has code for drawn gradients. // We need to decide if we're going to draw it or just use images throughout. @implementation _CPTableColumnHeaderView : CPView { - BOOL _isPressed; CPTextField _textField; } +/* + (void)initialize { - supportsCanvasGradient = NO;//CPFeatureIsCompatible(CPHTMLCanvasFeature); + supportsCanvasGradient = CPFeatureIsCompatible(CPHTMLCanvasFeature); } + (CGGradient)headerGradient @@ -76,59 +77,36 @@ var _headerGradient = nil, return _selectedPressedHeaderGradient; } +*/ - (void)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - _isPressed = NO; _textField = [[CPTextField alloc] initWithFrame:[self bounds]]; [_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable]; [self addSubview:_textField]; - - if (!supportsCanvasGradient) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]]; - + //[self setValue:headerColor forThemeAttribute:@"background-color" inState:CPThemeStateNormal]; - //[self setValue:headerHighlightedColor forThemeAttribute:@"background-color" inState:CPThemeStateHighlighted]; + //[self setValue:headerHighlightedColor forThemeAttribute:@"background-color" inState:CPThemeStateSelected]; } return self; } -- (void)setPressed:(BOOL)flag +- (void)layoutSubviews { - _isPressed = flag; - var isSelected = ([self themeState] & CPThemeStateSelected); - - if(_isPressed && isSelected) + var themeState = [self themeState]; + + if((themeState & CPThemeStateSelected) && (themeState & CPThemeStatePressed)) [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 22.0))]]; - else if (isSelected) + else if (themeState == CPThemeStateSelected) [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]]; - else if (_isPressed) + else if (themeState == CPThemeStatePressed) [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 22.0))]]; else [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]]; - - - [self setNeedsDisplay:YES]; -} - -- (BOOL)setThemeState:(CPThemeState)aState -{ - if (supportsCanvasGradient) - [super setThemeState:aState]; - else if (aState & CPThemeStateHighlighted) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]]; -} - -- (BOOL)unsetThemeState:(CPThemeState)aState -{ - if (supportsCanvasGradient) - [super unsetThemeState:aState]; - else if (aState & CPThemeStateHighlighted) - [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]]; } - (void)setStringValue:(CPString)string @@ -148,22 +126,20 @@ var _headerGradient = nil, - (void)sizeToFit { + [_textField sizeToFit]; } - +/* - (void)drawRect:(CGRect)rect { - if (!supportsCanvasGradient) - return; - var context = [[CPGraphicsContext currentContext] graphicsPort], bounds = [self bounds], - isSelected = ([self themeState] & CPThemeStateSelected); + themeState = [self themeState]; - if (_isPressed && isSelected) + if((themeState & CPThemeStateSelected) && (themeState & CPThemeStatePressed)) gradient = [_CPTableColumnHeaderView selectedPressedHeaderGradient]; - else if (isSelected) + else if (themeState == CPThemeStateSelected) gradient = [_CPTableColumnHeaderView selectedHeaderGradient]; - else if (_isPressed) + else if (themeState == CPThemeStatePressed) gradient = [_CPTableColumnHeaderView pressedHeaderGradient]; else gradient = [_CPTableColumnHeaderView headerGradient]; @@ -173,7 +149,7 @@ var _headerGradient = nil, CGContextDrawLinearGradient(context, gradient, CGPointMakeZero(), CGPointMake(0, CGRectGetHeight(bounds)), 0); CGContextClosePath(context); } - +*/ @end @implementation CPTableHeaderView : CPView @@ -258,11 +234,21 @@ var _headerGradient = nil, return rect; } -- (void)_updatePressed:(BOOL)flag +- (void)_setPressedColumn:(CPInteger)column { - var headerView = [_tableView._tableColumns[_pressedColumn] headerView]; - if ([headerView respondsToSelector:@selector(setPressed:)]) - [headerView setPressed:flag]; + if (_pressedColumn != CPNotFound) + { + var headerView = [_tableView._tableColumns[_pressedColumn] headerView]; + [headerView unsetThemeState:CPThemeStatePressed]; + } + + if (column != CPNotFound) + { + var headerView = [_tableView._tableColumns[column] headerView]; + [headerView setThemeState:CPThemeStatePressed]; + } + + _pressedColumn = column; } - (void)mouseDown:(CPEvent)theEvent @@ -279,8 +265,7 @@ var _headerGradient = nil, [[_tableView delegate] tableView:_tableView mouseDownInHeaderOfTableColumn:[[_tableView tableColumns] objectAtIndex:clickedColumn]]; - _pressedColumn = clickedColumn; - [self _updatePressed:YES]; + [self _setPressedColumn:clickedColumn]; } - (void)mouseUp:(CPEvent)theEvent @@ -291,11 +276,7 @@ var _headerGradient = nil, if (clickedColumn == -1) return; - if (_pressedColumn != CPNotFound) - { - [self _updatePressed:NO]; - _pressedColumn = CPNotFound; - } + [self _setPressedColumn:CPNotFound]; if ([_tableView allowsColumnSelection]) { @@ -374,15 +355,13 @@ var _headerGradient = nil, columnMaxX = CGRectGetMaxX(columnToStroke); CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMinY(columnToStroke))); - CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMaxY(columnToStroke)) - 1); + CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMaxY(columnToStroke))); } CGContextClosePath(context); CGContextStrokePath(context); - - return; - - /* + +/* var maxY = CGRectGetMaxY([self bounds]); // draw normal gradient for remaining space if (supportsCanvasGradient) @@ -400,7 +379,8 @@ var _headerGradient = nil, CGContextMoveToPoint(context, 0, maxY - 0.5); CGContextAddLineToPoint(context, CGRectGetMaxX([self bounds]), maxY - 0.5); CGContextClosePath(context); - CGContextStrokePath(context);*/ + CGContextStrokePath(context); +*/ } @end From 1c81e0eee05dbe7a2080e6f3318db2445acd4904 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 31 Jan 2010 15:07:23 -0800 Subject: [PATCH 02/12] Closes #429. Doesn't necessarily address the root cause however. The problem stems from a bug in Safari which is allowing callbacks to interrupt running code (which should be impossible in JavaScript). The change essentially makes it so that in the case where this happens, which is rare, we'll end up accidentally creating an extra iframe. This isn't ideal, but it also isn't harmful, versus the current situation where code will simply break. --- AppKit/Platform/DOM/CPPlatform.j | 5 +++ AppKit/Platform/DOM/CPPlatformString.j | 52 ++++++++++++++++++-------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/AppKit/Platform/DOM/CPPlatform.j b/AppKit/Platform/DOM/CPPlatform.j index 47af4b175..60ac59129 100644 --- a/AppKit/Platform/DOM/CPPlatform.j +++ b/AppKit/Platform/DOM/CPPlatform.j @@ -21,6 +21,7 @@ */ CPPlatformDidClearBodyElementNotification = @"CPPlatformDidClearBodyElementNotification"; +CPPlatformWillClearBodyElementNotification = @"CPPlatformWillClearBodyElementNotification"; var screenNeedsInitialization = NO, mainBodyElement = nil; @@ -91,6 +92,10 @@ var screenNeedsInitialization = NO, screenNeedsInitialization = NO; + [[CPNotificationCenter defaultCenter] + postNotificationName:CPPlatformWillClearBodyElementNotification + object:self]; + var bodyElement = [self mainBodyElement]; // Get rid of any of the original contents of the page. diff --git a/AppKit/Platform/DOM/CPPlatformString.j b/AppKit/Platform/DOM/CPPlatformString.j index e0431b0d4..1beb80c6f 100644 --- a/AppKit/Platform/DOM/CPPlatformString.j +++ b/AppKit/Platform/DOM/CPPlatformString.j @@ -22,8 +22,8 @@ #include "../CoreGraphics/CGGeometry.h" - var DOMSpanElement = nil, + DOMIFrameElement = nil, DefaultFont = nil; @implementation CPPlatformString : CPBasePlatformString @@ -39,11 +39,20 @@ var DOMSpanElement = nil, selector:@selector(platformDidClearBodyElement:) name:CPPlatformDidClearBodyElementNotification object:CPPlatform]; + + [[CPNotificationCenter defaultCenter] + addObserver:self + selector:@selector(platformWillClearBodyElement:) + name:CPPlatformWillClearBodyElementNotification + object:CPPlatform]; } + (void)createDOMElements { - var DOMIFrameElement = document.createElement("iframe"); + if (DOMIFrameElement) + return; + + DOMIFrameElement = document.createElement("iframe"); // necessary for Safari caching bug: DOMIFrameElement.name = "iframe_" + FLOOR(RAND() * 10000); DOMIFrameElement.style.position = "absolute"; @@ -80,11 +89,27 @@ var DOMSpanElement = nil, DOMDivElement.appendChild(DOMSpanElement); } ++ (void)removeDOMElements +{ + var iframe = DOMIFrameElement, + bodyElement = [CPPlatform mainBodyElement]; + + DOMSpanElement = nil; + DOMIFrameElement = nil; + + bodyElement.removeChild(iframe); +} + + (void)platformDidClearBodyElement:(CPNotification)aNotification { [self createDOMElements]; } ++ (void)platformWillClearBodyElement:(CPNotification)aNotification +{ + [self removeDOMElements]; +} + + (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth { if (!aFont) @@ -95,35 +120,30 @@ var DOMSpanElement = nil, aFont = DefaultFont; } + if (!DOMIFrameElement) + [self createDOMElements]; + var style = DOMSpanElement.style; - if (aWidth === NULL) + if (!aWidth) { style.width = ""; style.whiteSpace = "pre"; } - else { style.width = ROUND(aWidth) + "px"; - - if (document.attachEvent) - style.wordWrap = "break-word"; - - else - { - style.whiteSpace = "-o-pre-wrap"; - style.whiteSpace = "-pre-wrap"; - style.whiteSpace = "-moz-pre-wrap"; - style.whiteSpace = "pre-wrap"; - } + style.wordWrap = "break-word"; + style.whiteSpace = "-o-pre-wrap"; + style.whiteSpace = "-pre-wrap"; + style.whiteSpace = "-moz-pre-wrap"; + style.whiteSpace = "pre-wrap"; } style.font = [aFont cssString]; if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature)) DOMSpanElement.innerText = aString; - else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature)) DOMSpanElement.textContent = aString; From c911dd8aa62307404112f49355f97e382d62e544 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 31 Jan 2010 15:37:06 -0800 Subject: [PATCH 03/12] Slight order change. This really should not matter. --- AppKit/Platform/DOM/CPPlatformString.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/Platform/DOM/CPPlatformString.j b/AppKit/Platform/DOM/CPPlatformString.j index 1beb80c6f..371e41a0c 100644 --- a/AppKit/Platform/DOM/CPPlatformString.j +++ b/AppKit/Platform/DOM/CPPlatformString.j @@ -94,8 +94,8 @@ var DOMSpanElement = nil, var iframe = DOMIFrameElement, bodyElement = [CPPlatform mainBodyElement]; - DOMSpanElement = nil; DOMIFrameElement = nil; + DOMSpanElement = nil; bodyElement.removeChild(iframe); } From 26945bde4223518e15f13217d9932ccc70f9aa2f Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Sun, 31 Jan 2010 18:58:32 -0500 Subject: [PATCH 04/12] Removed commented out code and fixed a bug where the pressed state was still set when you drag the mouse from outside the bounds of the header and let go. --- AppKit/CPTableHeaderView.j | 79 ++------------------------------------ 1 file changed, 3 insertions(+), 76 deletions(-) diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index 12eb5294b..30edea8a0 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -23,62 +23,14 @@ @import "CPTableColumn.j" @import "CPTableView.j" @import "CPView.j" -/*@import - -var _headerGradient = nil, - _selectedHeaderGradient = nil, - _pressedHeaderGradient = nil, - _selectedPressedHeaderGradient = nil, - supportsCanvasGradient = NO;*/ var CPThemeStatePressed = CPThemeState("pressed"); -// FIX ME: _CPTableColumnHeaderView has code for drawn gradients. -// We need to decide if we're going to draw it or just use images throughout. @implementation _CPTableColumnHeaderView : CPView { CPTextField _textField; } -/* -+ (void)initialize -{ - supportsCanvasGradient = CPFeatureIsCompatible(CPHTMLCanvasFeature); -} - -+ (CGGradient)headerGradient -{ - if (!_headerGradient) - _headerGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(),[1.0,1.0,1.0,1.0,0.929,0.929,0.929,1.0], [0.3,1], 2); - - return _headerGradient; -} - -+ (CGGradient)selectedHeaderGradient -{ - if (!_selectedHeaderGradient) - _selectedHeaderGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [0.804,0.851,0.918,1.0,0.655,0.718,0.8,1.0], [0.3,1], 2); - - return _selectedHeaderGradient; -} - -+ (CGGradient)pressedHeaderGradient -{ - if (!_pressedHeaderGradient) - _pressedHeaderGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(),[0.929,0.929,0.929,1.0,1.0,1.0,1.0,1.0], [0.3,1], 2); - - return _pressedHeaderGradient; -} - -+ (CGGradient)selectedPressedHeaderGradient -{ - if (!_selectedPressedHeaderGradient) - _selectedPressedHeaderGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [0.655,0.718,0.8,1.0,0.804,0.851,0.918,1.0], [0.3,1], 2); - - return _selectedPressedHeaderGradient; -} -*/ - - (void)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; @@ -87,9 +39,6 @@ var CPThemeStatePressed = CPThemeState("pressed"); _textField = [[CPTextField alloc] initWithFrame:[self bounds]]; [_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable]; [self addSubview:_textField]; - - //[self setValue:headerColor forThemeAttribute:@"background-color" inState:CPThemeStateNormal]; - //[self setValue:headerHighlightedColor forThemeAttribute:@"background-color" inState:CPThemeStateSelected]; } return self; @@ -128,28 +77,6 @@ var CPThemeStatePressed = CPThemeState("pressed"); { [_textField sizeToFit]; } -/* -- (void)drawRect:(CGRect)rect -{ - var context = [[CPGraphicsContext currentContext] graphicsPort], - bounds = [self bounds], - themeState = [self themeState]; - - if((themeState & CPThemeStateSelected) && (themeState & CPThemeStatePressed)) - gradient = [_CPTableColumnHeaderView selectedPressedHeaderGradient]; - else if (themeState == CPThemeStateSelected) - gradient = [_CPTableColumnHeaderView selectedHeaderGradient]; - else if (themeState == CPThemeStatePressed) - gradient = [_CPTableColumnHeaderView pressedHeaderGradient]; - else - gradient = [_CPTableColumnHeaderView headerGradient]; - - CGContextBeginPath(context); - CGContextAddRect(context, bounds); - CGContextDrawLinearGradient(context, gradient, CGPointMakeZero(), CGPointMake(0, CGRectGetHeight(bounds)), 0); - CGContextClosePath(context); -} -*/ @end @implementation CPTableHeaderView : CPView @@ -273,11 +200,11 @@ var CPThemeStatePressed = CPThemeState("pressed"); var location = [self convertPoint:[theEvent locationInWindow] fromView:nil], clickedColumn = [self columnAtPoint:location]; - if (clickedColumn == -1) - return; - [self _setPressedColumn:CPNotFound]; + if (clickedColumn == -1) + return; + if ([_tableView allowsColumnSelection]) { if ([theEvent modifierFlags] & CPCommandKeyMask) From 2dc0839d368f88ad3b2b9b37a2c017e29444b4c0 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 1 Feb 2010 00:58:30 -0500 Subject: [PATCH 05/12] Fixed bug where CPButtonBar would not display anything until resized. Closes issue #151. --- AppKit/CPButtonBar.j | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/AppKit/CPButtonBar.j b/AppKit/CPButtonBar.j index e0d66f78f..a66fb7b86 100644 --- a/AppKit/CPButtonBar.j +++ b/AppKit/CPButtonBar.j @@ -8,6 +8,16 @@ { } +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + [self setNeedsLayout]; + + return self; +} + + (CPString)themeClass { return @"button-bar"; From c2223e3942a463e9ec97d37b74096e4e691e996b Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 31 Jan 2010 23:06:23 -0800 Subject: [PATCH 06/12] Closes #429. This should actually resolve the issue by simply removing the potential race condition entirely. --- AppKit/Platform/DOM/CPPlatform.j | 14 ++++++-- AppKit/Platform/DOM/CPPlatformString.j | 40 +--------------------- AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 15 ++------ 3 files changed, 15 insertions(+), 54 deletions(-) diff --git a/AppKit/Platform/DOM/CPPlatform.j b/AppKit/Platform/DOM/CPPlatform.j index 60ac59129..e3a621fb8 100644 --- a/AppKit/Platform/DOM/CPPlatform.j +++ b/AppKit/Platform/DOM/CPPlatform.j @@ -24,7 +24,8 @@ CPPlatformDidClearBodyElementNotification = @"CPPlatformDidClearBodyElementNot CPPlatformWillClearBodyElementNotification = @"CPPlatformWillClearBodyElementNotification"; var screenNeedsInitialization = NO, - mainBodyElement = nil; + mainBodyElement = nil, + elementRemovalTest = new RegExp("\\bcpdontremove\\b", "g"); @implementation CPPlatform : CPBasePlatform { @@ -99,7 +100,16 @@ var screenNeedsInitialization = NO, var bodyElement = [self mainBodyElement]; // Get rid of any of the original contents of the page. - bodyElement.innerHTML = ""; + var children = bodyElement.childNodes, + length = children.length; + + while (length--) + { + var element = children[length]; + if (!element.className || element.className.match(elementRemovalTest) === null) + bodyElement.removeChild(element); + } + bodyElement.style.overflow = "hidden"; if (document.documentElement) diff --git a/AppKit/Platform/DOM/CPPlatformString.j b/AppKit/Platform/DOM/CPPlatformString.j index 371e41a0c..1cbe99477 100644 --- a/AppKit/Platform/DOM/CPPlatformString.j +++ b/AppKit/Platform/DOM/CPPlatformString.j @@ -33,25 +33,10 @@ var DOMSpanElement = nil, + (void)bootstrap { [self createDOMElements]; - - [[CPNotificationCenter defaultCenter] - addObserver:self - selector:@selector(platformDidClearBodyElement:) - name:CPPlatformDidClearBodyElementNotification - object:CPPlatform]; - - [[CPNotificationCenter defaultCenter] - addObserver:self - selector:@selector(platformWillClearBodyElement:) - name:CPPlatformWillClearBodyElementNotification - object:CPPlatform]; } + (void)createDOMElements { - if (DOMIFrameElement) - return; - DOMIFrameElement = document.createElement("iframe"); // necessary for Safari caching bug: DOMIFrameElement.name = "iframe_" + FLOOR(RAND() * 10000); @@ -63,6 +48,7 @@ var DOMSpanElement = nil, DOMIFrameElement.style.borderWidth = "0px"; DOMIFrameElement.style.overflow = "hidden"; DOMIFrameElement.style.zIndex = 100000000000; + DOMIFrameElement.className = "cpdontremove"; var bodyElement = [CPPlatform mainBodyElement]; @@ -89,27 +75,6 @@ var DOMSpanElement = nil, DOMDivElement.appendChild(DOMSpanElement); } -+ (void)removeDOMElements -{ - var iframe = DOMIFrameElement, - bodyElement = [CPPlatform mainBodyElement]; - - DOMIFrameElement = nil; - DOMSpanElement = nil; - - bodyElement.removeChild(iframe); -} - -+ (void)platformDidClearBodyElement:(CPNotification)aNotification -{ - [self createDOMElements]; -} - -+ (void)platformWillClearBodyElement:(CPNotification)aNotification -{ - [self removeDOMElements]; -} - + (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth { if (!aFont) @@ -120,9 +85,6 @@ var DOMSpanElement = nil, aFont = DefaultFont; } - if (!DOMIFrameElement) - [self createDOMElements]; - var style = DOMSpanElement.style; if (!aWidth) diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index 5c73c69cc..e6cff4912 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -239,6 +239,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMFocusElement.style.zIndex = "-1000"; _DOMFocusElement.style.opacity = "0"; _DOMFocusElement.style.filter = "alpha(opacity=0)"; + _DOMFocusElement.className = "cpdontremove"; _DOMBodyElement.appendChild(_DOMFocusElement); @@ -248,6 +249,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMPasteboardElement.style.position = "absolute"; _DOMPasteboardElement.style.top = "-10000px"; _DOMPasteboardElement.style.zIndex = "999"; + _DOMPasteboardElement.className = "cpdontremove"; _DOMBodyElement.appendChild(_DOMPasteboardElement); @@ -255,11 +257,6 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMPasteboardElement.blur(); } -- (void)platformDidClearBodyElement:(CPNotification)aNotification -{ - [self createDOMElements]; -} - - (void)registerDOMWindow { var theDocument = _DOMWindow.document; @@ -273,14 +270,6 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMBodyElement.webkitTouchCallout = "none"; [self createDOMElements]; - - if (window === _DOMWindow) - [[CPNotificationCenter defaultCenter] - addObserver:self - selector:@selector(platformDidClearBodyElement:) - name:CPPlatformDidClearBodyElementNotification - object:CPPlatform]; - [self _addLayers]; var theClass = [self class], From ecb88a87ad8a174dffcd415f2b48989f2ecd8cd1 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 1 Feb 2010 02:33:04 -0500 Subject: [PATCH 07/12] Added proper grid drawing for highlighted rows. Closing issues #369 Also fixing bug where top row would not draw its background when clipped --- AppKit/CPTableView.j | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 176166f80..5f787e0e8 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1823,7 +1823,10 @@ window.setTimeout(function(){ } - (void)_drawRect:(CGRect)aRect -{ +{ + // FIX ME: All three of these methods will likely need to be rewritten for 1.0 + // We've got grid drawing in highlightSelection and crap everywhere. + var exposedRect = [self _exposedRect]; [self drawBackgroundInClipRect:exposedRect]; @@ -1859,7 +1862,7 @@ window.setTimeout(function(){ // CGContextFillRect(context, CGRectIntersection(aRect, fillRect)); // console.profile("row-paint"); var exposedRows = [self rowsInRect:aRect], - firstRow = exposedRows.location, + firstRow = exposedRows.location -1, lastRow = CPMaxRange(exposedRows) - 1, colorIndex = MIN(exposedRows.length, colorCount), heightFilled = 0.0; @@ -2027,33 +2030,34 @@ window.setTimeout(function(){ CGContextBeginPath(context); gridStyleMask = [self gridStyleMask]; - for(var i=0; i < count2-1; i++) + for(var i=0; i < count2; i++) { - var rect = [self rectOfRow:indexes[i]], - minX = _CGRectGetMinX(rect) - 0.5, - maxX = _CGRectGetMaxX(rect) - 0.5, - minY = _CGRectGetMinY(rect) - 0.5, - maxY = _CGRectGetMaxY(rect) - 0.5; + var rect = objj_msgSend(self, rectSelector, indexes[i]), + minX = CGRectGetMinX(rect) - 0.5, + maxX = CGRectGetMaxX(rect) - 0.5, + minY = CGRectGetMinY(rect) - 0.5, + maxY = CGRectGetMaxY(rect) - 0.5; - //FIX ME: if there are vertical lines we need to make them white too... - /*if (gridStyleMask & CPTableViewSolidVerticalGridLineMask) + if ([_selectedRowIndexes count] >= 1 && gridStyleMask & CPTableViewSolidVerticalGridLineMask) { var exposedColumns = [self columnIndexesInRect:aRect], - columnIndexes = [], - exposedColumns2 = CPMakeRange([exposedColumns firstIndex], [exposedColumns lastIndex] - firstColumn + 1); - [exposedColumns getIndexes:columnIndexes maxCount:-1 inIndexRange:exposedColumns2], - columnCount = [exposedColumns count]; - - for(var c = 0; c < columnCount - 1; c++) + exposedColumnIndexes = [], + firstExposedColumn = [exposedColumns firstIndex], + exposedRange = CPMakeRange(firstExposedColumn, [exposedColumns lastIndex] - firstExposedColumn + 1); + [exposedColumns getIndexes:exposedColumnIndexes maxCount:-1 inIndexRange:exposedRange]; + var exposedColumnCount = [exposedColumnIndexes count]; + + for(var c = firstExposedColumn; c < exposedColumnCount; c++) { - var colRect = [self rectOfColumn:columnIndexes[c]], - colX = _CGRectGetMaxX(rect) - 0.5; - console.log("colX"); + //console.log(columnIndexes); + var colRect = [self rectOfColumn:exposedColumnIndexes[c]], + colX = CGRectGetMaxX(colRect) + 0.5; + //console.log(colX); CGContextMoveToPoint(context, colX, minY); CGContextAddLineToPoint(context, colX, maxY); } - }*/ + } CGContextMoveToPoint(context, minX, maxY); CGContextAddLineToPoint(context, maxX, maxY); From 146bff67665602f4cfaa0d1bca9135f8fa9bcb81 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 1 Feb 2010 03:27:03 -0500 Subject: [PATCH 08/12] Initial documentation of CPTableView --- AppKit/CPTableView.j | 158 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 142 insertions(+), 16 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 5f787e0e8..899539a3a 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -265,6 +265,11 @@ window.setTimeout(function(){ return self; } + +/*! + Sets the receiverŐs data source to a given object. + @param anObject The data source for the receiver. The object must implement the appropriate methods. +*/ - (void)setDataSource:(id)aDataSource { if (_dataSource === aDataSource) @@ -302,6 +307,9 @@ window.setTimeout(function(){ [self reloadData]; } +/*! + Returns the object that provides the data displayed by the receiver. +*/ - (id)dataSource { return _dataSource; @@ -309,6 +317,11 @@ window.setTimeout(function(){ //Loading Data +/*! + Reloads the data for only the specified rows and columns. + @param rowIndexes The indexes of the rows to update. + @param columnIndexes The indexes of the columns to update. +*/ - (void)reloadDataForRowIndexes:(CPIndexSet)rowIndexes columnIndexes:(CPIndexSet)columnIndexes { [self reloadData]; @@ -316,7 +329,10 @@ window.setTimeout(function(){ // [_previouslyExposedColumns removeIndexes:columnIndexes]; } - +/*! + Reloads the data for all rows and columns. + +*/ - (void)reloadData { if (!_dataSource) @@ -333,7 +349,10 @@ window.setTimeout(function(){ } //Target-action Behavior - +/*! + Sets the message sent to the target when the user double-clicks an uneditable cell or a column header to a given selector. + @param aSelector The message the receiver sends to its target when the user double-clicks an uneditable cell or a column header. +*/ - (void)setDoubleAction:(SEL)anAction { _doubleAction = anAction; @@ -370,6 +389,10 @@ window.setTimeout(function(){ return _allowsColumnResizing; } +/*! + Controls whether the user can select more than one row or column at a time. + @param aFlag YES to allow the user to select multiple rows or columns, otherwise NO. +*/ - (void)setAllowsMultipleSelection:(BOOL)shouldAllowMultipleSelection { _allowsMultipleSelection = !!shouldAllowMultipleSelection; @@ -380,6 +403,10 @@ window.setTimeout(function(){ return _allowsMultipleSelection; } +/*! + Controls whether the receiver allows zero rows or columns to be selected. + @param aFlag YES if an empty selection is allowed, otherwise NO. +*/ - (void)setAllowsEmptySelection:(BOOL)shouldAllowEmptySelection { _allowsEmptySelection = !!shouldAllowEmptySelection; @@ -390,6 +417,11 @@ window.setTimeout(function(){ return _allowsEmptySelection; } +/*! + Controls whether the user can select an entire column by clicking its header. + @param aFlag YES to allow the user to select columns, otherwise NO. +*/ + - (void)setAllowsColumnSelection:(BOOL)shouldAllowColumnSelection { _allowsColumnSelection = !!shouldAllowColumnSelection; @@ -438,13 +470,12 @@ window.setTimeout(function(){ return _rowHeight; } +/*! + Sets whether the receiver uses the standard alternating row colors for its background. + @param aFlag YES to specify standard alternating row colors for the background, NO to specify a solid color. +*/ - (void)setUsesAlternatingRowBackgroundColors:(BOOL)shouldUseAlternatingRowBackgroundColors { - // TODO:need to look at how one actually sets the alternating row, a tip at: - // http://forums.macnn.com/79/developer-center/228347/nstableview-alternating-row-colors/ - // otherwise this may not be feasible or may introduce an additional change req'd in CP - // we'd probably need to iterate through rowId % 2 == 0 and setBackgroundColor with - // whatever the alternating row color is. _usesAlternatingRowBackgroundColors = shouldUseAlternatingRowBackgroundColors; } @@ -453,6 +484,11 @@ window.setTimeout(function(){ return _usesAlternatingRowBackgroundColors; } +/*! + Sets the colors for the rows as they alternate. The number of colors can be arbitrary. By deafult these colors are white and light blue. + @param anArray an array of CPColors +*/ + - (void)setAlternatingRowBackgroundColors:(CPArray)alternatingRowBackgroundColors { if ([_alternatingRowBackgroundColors isEqual:alternatingRowBackgroundColors]) @@ -489,6 +525,11 @@ window.setTimeout(function(){ } } +/*! + Sets the highlight color for rows. By default this color is blue. + @param aColor a CPColor +*/ + - (void)setSelectionHightlightColor:(CPColor)aColor { _selectionHightlightColor = aColor; @@ -504,6 +545,10 @@ window.setTimeout(function(){ * - setIndicatorImage:inTableColumn: */ +/*! + Sets the grid color in the non highlighted state. + @param aColor a CPColor +*/ - (void)setGridColor:(CPColor)aColor { if (_gridColor === aColor) @@ -519,6 +564,11 @@ window.setTimeout(function(){ return _gridColor; } +/*! + Sets the grid style mask to specify if no grid lines, vertical grid lines, or horizontal grid lines should be displayed. + @param gridType The grid style mask. CPTableViewGridNone, CPTableViewSolidVerticalGridLineMask, CPTableViewSolidHorizontalGridLineMask +*/ + - (void)setGridStyleMask:(unsigned)aGrideStyleMask { if (_gridStyleMask === aGrideStyleMask) @@ -536,6 +586,10 @@ window.setTimeout(function(){ //Column Management +/*! + Adds a given column as the last column of the receiver. + @param aColumn The column to add to the receiver. +*/ - (void)addTableColumn:(CPTableColumn)aTableColumn { [_tableColumns addObject:aTableColumn]; @@ -549,6 +603,10 @@ window.setTimeout(function(){ [self setNeedsLayout]; } +/*! + Removes a given column from the receiver. + @param aTableColumn The column to remove from the receiver. +*/ - (void)removeTableColumn:(CPTableColumn)aTableColumn { if ([aTableColumn tableView] !== self) @@ -575,6 +633,12 @@ window.setTimeout(function(){ [self setNeedsLayout]; } + +/*! + Moves the column and heading at a given index to a new given index. + @param columnIndex The current index of the column to move. + @param newIndex The new index for the moved column. +*/ - (void)moveColumn:(unsigned)fromIndex toColumn:(unsigned)toIndex { fromIndex = +fromIndex; @@ -627,6 +691,12 @@ window.setTimeout(function(){ } //Selecting Columns and Rows + +/*! + Sets the column selection using indexes. + @param columns a CPIndexSet of columns to select + @param aFlag should extend the selection thereby retaining the previous selection +*/ - (void)selectColumnIndexes:(CPIndexSet)columns byExtendingSelection:(BOOL)shouldExtendSelection { // If we're out of range, just return @@ -655,6 +725,11 @@ window.setTimeout(function(){ [self _noteSelectionDidChange]; } +/*! + Sets the row selection using indexes. + @param rows a CPIndexSet of rows to select + @param aFlag should extend the selection thereby retaining the previous selection +*/ - (void)selectRowIndexes:(CPIndexSet)rows byExtendingSelection:(BOOL)shouldExtendSelection { if ([rows isEqualToIndexSet:_selectedRowIndexes] || (([rows firstIndex] != CPNotFound && [rows firstIndex] < 0) || [rows lastIndex] >= [self numberOfRows])) @@ -811,6 +886,10 @@ window.setTimeout(function(){ * - allowsTypeSelect * - setAllowsTypeSelect: */ + +/*! + Deselects all rows +*/ - (void)deselectAll { [self selectRowIndexes:[CPIndexSet indexSet] byExtendingSelection:NO]; @@ -958,6 +1037,11 @@ window.setTimeout(function(){ // Complexity: // O(1) +/*! + Returns a range of indices for the rows that lie wholly or partially within the vertical boundaries of a given rectangle. + @param aRect A rectangle in the coordinate system of the receiver. +*/ + - (CPRange)rowsInRect:(CGRect)aRect { // If we have no rows, then we won't intersect anything. @@ -988,6 +1072,11 @@ window.setTimeout(function(){ // Complexity: // O(lg Columns) if table view contains no hidden columns // O(Columns) if table view contains hidden columns + +/*! + Returns the indexes of the receiverŐs columns that intersect the specified rectangle. + @param aRect A rectangle in the coordinate system of the receiver. +*/ - (CPIndexSet)columnIndexesInRect:(CGRect)aRect { var column = MAX(0, [self columnAtPoint:_CGPointMake(aRect.origin.x, 0.0)]), @@ -1183,6 +1272,10 @@ window.setTimeout(function(){ } +/*! + Sets the column autoresizing style of the receiver to a given style. + @param aStyle The column autoresizing style for the receiver. CPTableViewNoColumnAutoresizing, CPTableViewUniformColumnAutoresizingStyle, CPTableViewLastColumnOnlyAutoresizingStyle, CPTableViewFirstColumnOnlyAutoresizingStyle +*/ - (void)setColumnAutoresizingStyle:(unsigned)style { //FIX ME: CPTableViewSequentialColumnAutoresizingStyle and CPTableViewReverseSequentialColumnAutoresizingStyle are not yet implemented @@ -1194,6 +1287,9 @@ window.setTimeout(function(){ return _columnAutoResizingStyle; } +/*! + Resizes the last column if thereŐs room so the receiver fits exactly within its enclosing clip view. +*/ - (void)sizeLastColumnToFit { var superview = [self superview]; @@ -1268,11 +1364,19 @@ window.setTimeout(function(){ * - scrollColumnToVisible: */ +/*! + Scrolls the receiver vertically in an enclosing NSClipView so the row specified by rowIndex is visible. + @param aRowIndex the index of the row to scroll to. +*/ - (void)scrollRowToVisible:(int)rowIndex { [self scrollRectToVisible:[self rectOfRow:rowIndex]]; } +/*! + Scrolls the receiver and header view horizontally in an enclosing NSClipView so the column specified by columnIndex is visible. + @param aColumnIndex the index of the column to scroll to. +*/ - (void)scrollColumnToVisible:(int)columnIndex { [self scrollRectToVisible:[self rectOfColumn:columnIndex]]; @@ -1432,6 +1536,11 @@ window.setTimeout(function(){ * - setVerticalMotionCanBeginDrag: * - verticalMotionCanBeginDrag */ +/*! + Returns whether the receiver allows dragging the rows at rowIndexes with a drag initiated at mousedDownPoint. + @param rowIndexes an index set of rows to be dragged + @param aPoint the point at which the mouse was clicked. +*/ - (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes atPoint:(CGPoint)mouseDownPoint { return YES; @@ -1503,8 +1612,8 @@ window.setTimeout(function(){ _dragOperationDefaultMask = mask; } -/* - this should be called inside tableView:validateDrop:... method +/*! + This should be called inside tableView:validateDrop:... method either drop on or above, specify the row as -1 to select the whole table for drop on */ @@ -1520,16 +1629,16 @@ window.setTimeout(function(){ _retargetedDropOperation = operation; } -/* - can be: +/*! + sets the feedback style for when the table is the destination of a drag operation + Can be: None Regular Source List - - FIX ME: this should vary up the highlight color, currently nothing is being done with it */ - (void)setDraggingDestinationFeedbackStyle:(CPTableViewDraggingDestinationFeedbackStyle)aStyle { + //FIX ME: this should vary up the highlight color, currently nothing is being done with it _destinationDragStyle = aStyle; } @@ -1538,6 +1647,10 @@ window.setTimeout(function(){ return _destinationDragStyle; } +/*! + Sets whether vertical motion is treated as a drag or selection change to flag. + @param aFlag If flag is NO then vertical motion will not start a drag. The default is YES. +*/ - (void)setVerticalMotionCanBeginDrag:(BOOL)aFlag { _verticalMotionCanDrag = aFlag; @@ -2130,12 +2243,17 @@ window.setTimeout(function(){ */ +/* + @ignore +*/ - (BOOL)tracksMouseOutsideOfFrame { return YES; } -/* ignore */ +/* + @ignore +*/ - (BOOL)startTrackingAt:(CGPoint)aPoint { var row = [self rowAtPoint:aPoint]; @@ -2169,6 +2287,9 @@ window.setTimeout(function(){ return YES; } +/* + @ignore +*/ - (void)trackMouse:(CPEvent)anEvent { // Prevent CPControl from eating the mouse events when we are in a drag session @@ -2178,7 +2299,9 @@ window.setTimeout(function(){ [CPApp sendEvent:anEvent]; } -/* ignore */ +/* + @ignore +*/ - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint { var row = [self rowAtPoint:aPoint]; @@ -2253,6 +2376,9 @@ window.setTimeout(function(){ return YES; } +/*! + @ignore +*/ - (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp { _isSelectingSession = NO; @@ -2315,7 +2441,7 @@ window.setTimeout(function(){ [self sendAction:_doubleAction to:_target]; } -/* +/*! @ignore */ - (CPDragOperation)draggingEntered:(id)sender From 050a132bd52b0be9a75f0dd8265470fb3ac75bdd Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 1 Feb 2010 03:40:09 -0500 Subject: [PATCH 09/12] Initial documentation of CPTableView. --- AppKit/CPTableView.j | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 899539a3a..062ab6594 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -122,6 +122,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; @end +/*! + @ingroup appkit + @class CPTableView + + CPTableView object displays record-oriented data in a table and allows the user to edit values and resize and rearrange columns. + A CPTableView requires you to set a dataSource which implements numberOfRowsInTableView: and tableView:objectValueForTableColumn:row: +*/ @implementation CPTableView : CPControl { id _dataSource; From 35a74563026c25d4d2c074e579a338daeeb048f1 Mon Sep 17 00:00:00 2001 From: cacaodev Date: Mon, 1 Feb 2010 11:51:50 +0100 Subject: [PATCH 10/12] Fixes rows drawing when alternatingRowBackgroundColors > 2. TableTest showing 3 row colors --- AppKit/CPTableView.j | 12 ++++-------- Tests/Manual/TableTest/AppController.j | 1 + 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 062ab6594..cdb0866bd 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1954,11 +1954,6 @@ window.setTimeout(function(){ [self highlightSelectionInClipRect:exposedRect]; } -- (void)drawRect:(CGRect)aRect -{ - [_tableDrawView display]; -} - - (void)drawBackgroundInClipRect:(CGRect)aRect { if (![self usesAlternatingRowBackgroundColors]) @@ -1982,20 +1977,21 @@ window.setTimeout(function(){ // CGContextFillRect(context, CGRectIntersection(aRect, fillRect)); // console.profile("row-paint"); var exposedRows = [self rowsInRect:aRect], - firstRow = exposedRows.location -1, + firstRow = exposedRows.location, lastRow = CPMaxRange(exposedRows) - 1, colorIndex = MIN(exposedRows.length, colorCount), heightFilled = 0.0; while (colorIndex--) { - var row = firstRow % colorCount + firstRow + colorIndex, + var row = firstRow - firstRow % colorCount + colorIndex, fillRect = nil; CGContextBeginPath(context); for (; row <= lastRow; row += colorCount) - CGContextAddRect(context, CGRectIntersection(aRect, fillRect = [self rectOfRow:row])); + if (row >= firstRow) + CGContextAddRect(context, CGRectIntersection(aRect, fillRect = [self rectOfRow:row])); if (row - colorCount === lastRow) heightFilled = _CGRectGetMaxY(fillRect); diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index eb4b7830a..98fb0d160 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -39,6 +39,7 @@ CPLogRegister(CPLogConsole); [tableView setAllowsMultipleSelection:YES]; [tableView setAllowsColumnSelection:YES]; [tableView setUsesAlternatingRowBackgroundColors:YES]; + [tableView setAlternatingRowBackgroundColors:[[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"], [CPColor colorWithHexString:@"f4e7ff"]]]; [tableView setGridStyleMask:CPTableViewSolidHorizontalGridLineMask | CPTableViewSolidVerticalGridLineMask]; // [tableView setBackgroundColor:[CPColor blueColor]]; From 775c1c1c8b9665ea0ccb8762545e6c93db2c76b5 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 1 Feb 2010 11:11:51 -0500 Subject: [PATCH 11/12] Fixed the outline view again... --- AppKit/CPTableView.j | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index cdb0866bd..bc12f321e 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -245,11 +245,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [_headerView setTableView:self]; _cornerView = [[_CPCornerView alloc] initWithFrame:CGRectMake(0, 0, [CPScroller scrollerWidth], CGRectGetHeight([_headerView frame]))]; - - +//FIX ME: This is disgusting! but used to fix a Safari bug where the outlineview breaks for whatever reason... +window.setTimeout(function(){ _selectedColumnIndexes = [CPIndexSet indexSet]; _selectedRowIndexes = [CPIndexSet indexSet]; -window.setTimeout(function(){ + self._draggedRowIndexes = [CPIndexSet indexSet]; self._verticalMotionCanDrag = YES; self._isSelectingSession = NO; From cc74f941c67233aa47a5802d9794dd8d42455763 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Mon, 1 Feb 2010 11:44:24 -0500 Subject: [PATCH 12/12] Better "fix" for Safari breaking the outlineview... This bug still needs a reduction though. --- AppKit/CPOutlineView.j | 236 +++++++++++++++++++++-------------------- AppKit/CPTableView.j | 36 +++---- 2 files changed, 138 insertions(+), 134 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 972d48d64..b38f754e4 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -618,140 +618,146 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ @end +// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever... var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem) { if (!anItem) return; - - // Get the existing info if it exists. - var itemInfosForItems = anOutlineView._itemInfosForItems, - dataSource = anOutlineView._outlineViewDataSource, - itemUID = [anItem UID], - itemInfo = itemInfosForItems[itemUID]; - - // If we're not in the tree, then just bail. - if (!itemInfo) - return []; - - // See if the item itself can be swapped out. - var parent = itemInfo.parent, - parentItemInfo = parent ? itemInfosForItems[[parent UID]] : anOutlineView._rootItemInfo, - parentChildren = parentItemInfo.children, - index = [parentChildren indexOfObjectIdenticalTo:anItem], - newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent]; - - if (anItem !== newItem) - { - itemInfosForItems[[anItem UID]] = nil; - itemInfosForItems[[newItem UID]] = itemInfo; - - parentChildren[index] = newItem; - anOutlineView._itemsForRows[itemInfo.row] = newItem; - } - - itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem]; - itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded; -} - -var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate) -{ - var itemInfosForItems = anOutlineView._itemInfosForItems, - dataSource = anOutlineView._outlineViewDataSource; - - if (!anItem) - var itemInfo = anOutlineView._rootItemInfo; - - else + with(anOutlineView) { // Get the existing info if it exists. - var itemUID = [anItem UID], + var itemInfosForItems = _itemInfosForItems, + dataSource = _outlineViewDataSource, + itemUID = [anItem UID], itemInfo = itemInfosForItems[itemUID]; - + // If we're not in the tree, then just bail. if (!itemInfo) return []; - - itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem]; - - // If we were previously expanded, but now no longer expandable, "de-expand". - // NOTE: we are *not* collapsing, thus no notification is posted. - if (!itemInfo.isExpandable && itemInfo.isExpanded) + + // See if the item itself can be swapped out. + var parent = itemInfo.parent, + parentItemInfo = parent ? itemInfosForItems[[parent UID]] : _rootItemInfo, + parentChildren = parentItemInfo.children, + index = [parentChildren indexOfObjectIdenticalTo:anItem], + newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent]; + + if (anItem !== newItem) { - itemInfo.isExpanded = NO; + itemInfosForItems[[anItem UID]] = nil; + itemInfosForItems[[newItem UID]] = itemInfo; + + parentChildren[index] = newItem; + _itemsForRows[itemInfo.row] = newItem; + } + + itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem]; + itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded; + } +} + +// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever... +var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate) +{ + with(anOutlineView) + { + var itemInfosForItems = _itemInfosForItems, + dataSource = _outlineViewDataSource; + + if (!anItem) + var itemInfo = _rootItemInfo; + + else + { + // Get the existing info if it exists. + var itemUID = [anItem UID], + itemInfo = itemInfosForItems[itemUID]; + + // If we're not in the tree, then just bail. + if (!itemInfo) + return []; + + itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem]; + + // If we were previously expanded, but now no longer expandable, "de-expand". + // NOTE: we are *not* collapsing, thus no notification is posted. + if (!itemInfo.isExpandable && itemInfo.isExpanded) + { + itemInfo.isExpanded = NO; + itemInfo.children = []; + } + } + + // The root item does not count as a descendant. + var weight = itemInfo.weight, + descendants = anItem ? [anItem] : []; + + if (itemInfo.isExpanded && (!(_implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) || + ![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem])) + { + var index = 0, + count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem], + level = itemInfo.level + 1; + itemInfo.children = []; - } - } - - // The root item does not count as a descendant. - var weight = itemInfo.weight, - descendants = anItem ? [anItem] : []; - - if (itemInfo.isExpanded && (!(anOutlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) || - ![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem])) - { - var index = 0, - count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem], - level = itemInfo.level + 1; - - itemInfo.children = []; - - for (; index < count; ++index) - { - var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem], - childItemInfo = itemInfosForItems[[childItem UID]]; - - if (!childItemInfo) + + for (; index < count; ++index) { - childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 }; - itemInfosForItems[[childItem UID]] = childItemInfo; + var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem], + childItemInfo = itemInfosForItems[[childItem UID]]; + + if (!childItemInfo) + { + childItemInfo = { isExpanded:NO, isExpandable:NO, children:[], weight:1 }; + itemInfosForItems[[childItem UID]] = childItemInfo; + } + + itemInfo.children[index] = childItem; + + var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES); + + childItemInfo.parent = anItem; + childItemInfo.level = level; + descendants = descendants.concat(childDescendants); } - - itemInfo.children[index] = childItem; - - var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES); - - childItemInfo.parent = anItem; - childItemInfo.level = level; - descendants = descendants.concat(childDescendants); } - } - - itemInfo.weight = descendants.length; - - if (!isIntermediate) - { - // row = -1 is the root item, so just go to row 0 since it is ignored. - var index = MAX(itemInfo.row, 0), - itemsForRows = anOutlineView._itemsForRows; - - descendants.unshift(index, weight); - - itemsForRows.splice.apply(itemsForRows, descendants); - - var count = itemsForRows.length; - - for (; index < count; ++index) - itemInfosForItems[[itemsForRows[index] UID]].row = index; - - var deltaWeight = itemInfo.weight - weight; - - if (deltaWeight !== 0) + + itemInfo.weight = descendants.length; + + if (!isIntermediate) { - var parent = itemInfo.parent; - - while (parent) + // row = -1 is the root item, so just go to row 0 since it is ignored. + var index = MAX(itemInfo.row, 0), + itemsForRows = _itemsForRows; + + descendants.unshift(index, weight); + + itemsForRows.splice.apply(itemsForRows, descendants); + + var count = itemsForRows.length; + + for (; index < count; ++index) + itemInfosForItems[[itemsForRows[index] UID]].row = index; + + var deltaWeight = itemInfo.weight - weight; + + if (deltaWeight !== 0) { - var parentItemInfo = itemInfosForItems[[parent UID]]; - - parentItemInfo.weight += deltaWeight; - parent = parentItemInfo.parent; + var parent = itemInfo.parent; + + while (parent) + { + var parentItemInfo = itemInfosForItems[[parent UID]]; + + parentItemInfo.weight += deltaWeight; + parent = parentItemInfo.parent; + } + + if (anItem) + _rootItemInfo.weight += deltaWeight; } - - if (anItem) - anOutlineView._rootItemInfo.weight += deltaWeight; } - } - + }//end of with return descendants; } diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index bc12f321e..74aeaffc6 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -190,14 +190,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; SEL _doubleAction; unsigned _columnAutoResizingStyle; -// BOOL _verticalMotionCanDrag; -// unsigned _destinationDragStyle; -// BOOL _isSelectingSession; -// CPIndexSet _draggedRowIndexes; -// _dropOperationDrawingView _dropOperationFeedbackView; -// CPDragOperation _dragOperationDefaultMask; -// int _retargetedDropRow; -// CPDragOperation _retargetedDropOperation; + BOOL _verticalMotionCanDrag; + unsigned _destinationDragStyle; + BOOL _isSelectingSession; + CPIndexSet _draggedRowIndexes; + _dropOperationDrawingView _dropOperationFeedbackView; + CPDragOperation _dragOperationDefaultMask; + int _retargetedDropRow; + CPDragOperation _retargetedDropOperation; } - (id)initWithFrame:(CGRect)aFrame @@ -245,23 +245,21 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [_headerView setTableView:self]; _cornerView = [[_CPCornerView alloc] initWithFrame:CGRectMake(0, 0, [CPScroller scrollerWidth], CGRectGetHeight([_headerView frame]))]; -//FIX ME: This is disgusting! but used to fix a Safari bug where the outlineview breaks for whatever reason... -window.setTimeout(function(){ + _selectedColumnIndexes = [CPIndexSet indexSet]; _selectedRowIndexes = [CPIndexSet indexSet]; - self._draggedRowIndexes = [CPIndexSet indexSet]; - self._verticalMotionCanDrag = YES; - self._isSelectingSession = NO; - self._retargetedDropRow = nil; - self._retargetedDropOperation = nil; - self._dragOperationDefaultMask = nil; - self._destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; - self._dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; + _draggedRowIndexes = [CPIndexSet indexSet]; + _verticalMotionCanDrag = YES; + _isSelectingSession = NO; + _retargetedDropRow = nil; + _retargetedDropOperation = nil; + _dragOperationDefaultMask = nil; + _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; + _dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; [self addSubview:_dropOperationFeedbackView]; [_dropOperationFeedbackView setHidden:YES]; [_dropOperationFeedbackView setTableView:self]; -},0); _tableDrawView = [[_CPTableDrawView alloc] initWithTableView:self]; [_tableDrawView setBackgroundColor:[CPColor clearColor]];