From c1fe45cbcd42ec934c6da8c9c71dbcc013ba775f Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 14 Mar 2010 12:32:52 -0700 Subject: [PATCH] Add a way to tell a CPSplitView about a button bar for a specific divider index, which mitigates the need to use additional effective rect delegate method when using a split view + button bar. --- AppKit/CPButtonBar.j | 44 +++++++++++++++++++++----- AppKit/CPSplitView.j | 73 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 104 insertions(+), 13 deletions(-) diff --git a/AppKit/CPButtonBar.j b/AppKit/CPButtonBar.j index 580b9ce82..daf2e9518 100644 --- a/AppKit/CPButtonBar.j +++ b/AppKit/CPButtonBar.j @@ -33,6 +33,17 @@ return button; } ++ (CPString)themeClass +{ + return @"button-bar"; +} + ++ (id)themeAttributes +{ + return [CPDictionary dictionaryWithObjects:[CGInsetMake(0.0, 0.0, 0.0, 0.0), CGSizeMakeZero(), [CPNull null], [CPNull null], [CPNull null]] + forKeys:[@"resize-control-inset", @"resize-control-size", @"resize-control-color", @"bezel-color", @"button-bezel-color"]]; +} + - (id)initWithFrame:(CGRect)aFrame { self = [super initWithFrame:aFrame]; @@ -46,15 +57,24 @@ return self; } -+ (CPString)themeClass +- (void)awakeFromCib { - return @"button-bar"; -} + var view = [self superview], + subview = self; -+ (id)themeAttributes -{ - return [CPDictionary dictionaryWithObjects:[CGInsetMake(0.0, 0.0, 0.0, 0.0), CGSizeMakeZero(), [CPNull null], [CPNull null], [CPNull null]] - forKeys:[@"resize-control-inset", @"resize-control-size", @"resize-control-color", @"bezel-color", @"button-bezel-color"]]; + while (view) + { + if ([view isKindOfClass:[CPSplitView class]]) + { + var viewIndex = [[view subviews] indexOfObject:subview]; + [view setButtonBar:self forDividerAtIndex:viewIndex]; + + break; + } + + subview = view; + view = [view superview]; + } } - (void)setButtons:(CPArray)buttons @@ -117,6 +137,16 @@ return _resizeControlIsLeftAligned; } +- (CGRect)resizeControlFrame +{ + var inset = [self currentValueForThemeAttribute:@"resize-control-inset"], + size = [self currentValueForThemeAttribute:@"resize-control-size"], + currentSize = [self bounds], + leftOrigin = _resizeControlIsLeftAligned ? 0 : currentSize.size.width - size.width - inset.right - inset.left; + + return CGRectMake(leftOrigin, 0, size.width + inset.left + inset.right, size.height + inset.top + inset.bottom); +} + - (CGRect)rectForEphemeralSubviewNamed:(CPString)aName { if (aName === "resize-control-view") diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index 6974c25e0..a0a42b44e 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +@import "CPButtonBar.j" @import "CPImage.j" @import "CPView.j" @@ -55,6 +56,8 @@ var CPSplitViewHorizontalImage = nil, int _drawingDivider; BOOL _needsResizeSubviews; + + CPArray _buttonBars; } /* @@ -77,6 +80,7 @@ var CPSplitViewHorizontalImage = nil, _currentDivider = CPNotFound; _DOMDividerElements = []; + _buttonBars = []; [self _setVertical:YES]; } @@ -279,15 +283,25 @@ var CPSplitViewHorizontalImage = nil, var frame = [_subviews[anIndex] frame], startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent], effectiveRect = [self effectiveRectOfDividerAtIndex:anIndex], + buttonBar = _buttonBars[anIndex], + buttonBarRect = null, additionalRect = null; - + + if (buttonBar != null) + { + buttonBarRect = [buttonBar resizeControlFrame]; + buttonBarRect.origin = [self convertPoint:buttonBarRect.origin fromView:buttonBar]; + } + if ([_delegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)]) effectiveRect = [_delegate splitView:self effectiveRect:effectiveRect forDrawnRect:effectiveRect ofDividerAtIndex:anIndex]; if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)]) additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex]; - return CGRectContainsPoint(effectiveRect, aPoint) || (additionalRect && CGRectContainsPoint(additionalRect, aPoint)); + return CGRectContainsPoint(effectiveRect, aPoint) || + (additionalRect && CGRectContainsPoint(additionalRect, aPoint)) || + (buttonBarRect && CGRectContainsPoint(buttonBarRect, aPoint)); } - (CPView)hitTest:(CGPoint)aPoint @@ -553,6 +567,47 @@ var CPSplitViewHorizontalImage = nil, object:self]; } +/*! + Set the button bar who's resize control should act as a control for this splitview. + Each divider can have at most one button bar assigned to it, and that button bar must be + a subview of one of the split view's subviews. + + Calling this method with nil as the button bar will remove any currently assigned button bar + for the divider at that index. Indexes will not be adjusted as new subviews are added, so you + should usually call this method after adding all the desired subviews to the split view. + + This method will automatically configure the hasResizeControl and resizeControlIsLeftAligned + parameters of the button bar, and will override any currently set values. +*/ +- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex +{ + if (!aButtonBar) + { + _buttonBars[dividerIndex] = nil; + return; + } + + var view = [aButtonBar superview], + subview = aButtonBar; + + while (view && view !== self) + { + subview = view; + view = [view superview]; + } + + if (view !== self) + [CPException raise:CPInvalidArgumentException + reason:@"CPSplitView button bar must be a subview of the split view."]; + + var viewIndex = [[self subviews] indexOfObject:subview]; + + [aButtonBar setHasResizeControl:YES]; + [aButtonBar setResizeControlIsLeftAligned:dividerIndex < viewIndex]; + + _buttonBars[dividerIndex] = aButtonBar; +} + - (void)_postNotificationWillResize { [[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification object:self]; @@ -567,7 +622,8 @@ var CPSplitViewHorizontalImage = nil, var CPSplitViewDelegateKey = "CPSplitViewDelegateKey", CPSplitViewIsVerticalKey = "CPSplitViewIsVerticalKey", - CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey"; + CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey", + CPSplitViewButtonBarsKey = "CPSplitViewButtonBarsKey"; @implementation CPSplitView (CPCoding) @@ -584,8 +640,10 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey", _currentDivider = CPNotFound; _DOMDividerElements = []; + + _buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || []; - _delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];; + _delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey]; _isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey]; [self _setVertical:[aCoder decodeBoolForKey:CPSplitViewIsVerticalKey]]; @@ -601,9 +659,12 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey", - (void)encodeWithCoder:(CPCoder)aCoder { [super encodeWithCoder:aCoder]; - + + //FIXME how should we handle this? + //[aCoder encodeObject:_buttonBars forKey:CPSplitViewButtonBarsKey]; + [aCoder encodeConditionalObject:_delegate forKey:CPSplitViewDelegateKey]; - + [aCoder encodeBool:_isVertical forKey:CPSplitViewIsVerticalKey]; [aCoder encodeBool:_isPaneSplitter forKey:CPSplitViewIsPaneSplitterKey]; }