bwalkin / BWToolkit (http://brandonwalkin.com/bwtoolkit/)

BWToolkit is an Interface Builder plugin that contains commonly used UI elements and other objects designed to simplify development for the Mac.

Clone this repository (size: 1.5 MB): HTTPS / SSH
$ hg clone http://bitbucket.org/bwalkin/bwtoolkit/
commit 104: df308f70abee
parent 103: f164b18c9667
branch: default
Anchored button bar - Added support for multiple resizable bars in a split view and bars can now move any divider
Brandon Walkin
5 months ago

Changed (Δ1.8 KB):

raw changeset »

BWAnchoredButtonBar.m (72 lines added, 13 lines removed)

BWSplitView.h (1 lines added, 0 lines removed)

BWSplitView.m (1 lines added, 1 lines removed)

Up to file-list BWAnchoredButtonBar.m:

10
10
#import "NSColor+BWAdditions.h"
11
11
#import "NSView+BWAdditions.h"
12
12
#import "BWAnchoredButton.h"
13
#import "BWSplitView.h"
13
14
14
15
static NSColor *topLineColor, *bottomLineColor;
15
16
static NSColor *topColor, *middleTopColor, *middleBottomColor, *bottomColor;
@@ -24,6 +25,7 @@ static float scaleFactor = 0.0f;
24
25
- (void)drawLastButtonInsetInRect:(NSRect)rect;
25
26
- (BOOL)isInLastSubview;
26
27
- (NSSplitView *)splitView;
28
- (NSInteger)dividerIndexNearestToHandle;
27
29
@end
28
30
29
31
@implementation BWAnchoredButtonBar
@@ -94,7 +96,37 @@ static float scaleFactor = 0.0f;
94
96
	NSSplitView *splitView = [self splitView];
95
97
	
96
98
	if (splitView != nil && [splitView isVertical] && [self isResizable])
97
		[splitView setDelegate:self];
99
	{
100
		if ([splitView delegate] != nil && ([[splitView delegate] isKindOfClass:[BWAnchoredButtonBar class]] ||
101
											[splitView isKindOfClass:[BWSplitView class]] && [[(BWSplitView *)splitView secondaryDelegate] isKindOfClass:[BWAnchoredButtonBar class]]))
102
		{
103
			// There's already an Anchored Button Bar set as the delegate so we need to set ourself as the split view delegate on
104
			// the button bar. But since there can be multiple button bars, we need to set ourself as the delegate on the last
105
			// button bar of the delegate chain.
106
			
107
			BWAnchoredButtonBar *currentDelegate = [splitView isKindOfClass:[BWSplitView class]] ? [(BWSplitView *)splitView secondaryDelegate] : [splitView delegate];
108
			BWAnchoredButtonBar *lastDelegate = currentDelegate;
109
			
110
			while (currentDelegate != nil)
111
			{
112
				if ([currentDelegate splitViewDelegate] != nil && [[currentDelegate splitViewDelegate] isKindOfClass:[BWAnchoredButtonBar class]])
113
				{
114
					currentDelegate = [currentDelegate splitViewDelegate];
115
					lastDelegate = currentDelegate;
116
				}
117
				else
118
				{
119
					currentDelegate = nil;
120
				}				
121
			}
122
			
123
			[lastDelegate setSplitViewDelegate:self];
124
		}
125
		else
126
		{
127
			[splitView setDelegate:self];
128
		}
129
	}
98
130
		
99
131
	[self bwBringToFront];
100
132
}
@@ -200,6 +232,14 @@ static float scaleFactor = 0.0f;
200
232
	return NO;
201
233
}
202
234
235
- (NSInteger)dividerIndexNearestToHandle
236
{
237
	if ([self isInLastSubview])
238
		return self.splitView.subviews.count - 2;
239
		
240
	return [[[self splitView] subviews] indexOfObject:[self superview]];
241
}
242
203
243
- (NSSplitView *)splitView
204
244
{
205
245
	NSSplitView *splitView = nil;
@@ -260,25 +300,44 @@ static float scaleFactor = 0.0f;
260
300
	return wasBorderedBar;
261
301
}
262
302
303
- (void)dealloc
304
{
305
	NSSplitView *splitView = [self splitView];
306
	
307
	if ([splitView delegate] == self)
308
		[splitView setDelegate:nil];
309
	
310
	[super dealloc];
311
}
312
263
313
#pragma mark NSSplitView Delegate Methods
264
314
265
315
// Add the resize handle rect to the split view hot zone
266
316
- (NSRect)splitView:(NSSplitView *)aSplitView additionalEffectiveRectOfDividerAtIndex:(NSInteger)dividerIndex
267
{
268
	if ([splitViewDelegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
269
		return [splitViewDelegate splitView:aSplitView additionalEffectiveRectOfDividerAtIndex:dividerIndex];
317
{	
318
	if (dividerIndex == [self dividerIndexNearestToHandle])
319
	{
320
		NSRect paddedHandleRect;
321
		paddedHandleRect.origin.y = [aSplitView frame].size.height - [self frame].origin.y - [self bounds].size.height;
322
323
		// Note: Assumes button bar is nested directly in a split view subview
324
		if (self.handleIsRightAligned)
325
			paddedHandleRect.origin.x = NSMinX([[self superview] frame]);
326
		else
327
			paddedHandleRect.origin.x = NSMaxX([[self superview] frame]) - 15;
270
328
	
271
	NSRect paddedHandleRect;
272
	paddedHandleRect.origin.y = [aSplitView frame].size.height - [self frame].origin.y - [self bounds].size.height;
273
	paddedHandleRect.origin.x = NSMaxX([self bounds]) - 15;
329
		paddedHandleRect.size.width = 15;
330
		paddedHandleRect.size.height = [self bounds].size.height;
274
331
	
275
	if (self.handleIsRightAligned)
276
		paddedHandleRect.origin.x = [aSplitView frame].size.width - [self bounds].size.width;
332
		return paddedHandleRect;
333
	}
334
	else
335
	{
336
		if ([splitViewDelegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
337
			return [splitViewDelegate splitView:aSplitView additionalEffectiveRectOfDividerAtIndex:dividerIndex];
338
	}
277
339
	
278
	paddedHandleRect.size.width = 15;
279
	paddedHandleRect.size.height = [self bounds].size.height;
280
	
281
	return paddedHandleRect;
340
	return NSZeroRect;
282
341
}
283
342
284
343
// Remaining delegate methods. They test for an implementation by the splitViewDelegate (otherwise perform default behavior)

Up to file-list BWSplitView.h:

28
28
@property (retain) NSMutableDictionary *resizableSubviewPreferredProportion, *nonresizableSubviewPreferredSize;
29
29
@property (retain) NSArray *stateForLastPreferredCalculations;
30
30
@property (retain) NSButton *toggleCollapseButton;
31
@property (assign) id secondaryDelegate;
31
32
@property BOOL collapsibleSubviewCollapsed;
32
33
@property int collapsiblePopupSelection;
33
34
@property BOOL dividerCanCollapse;

Up to file-list BWSplitView.m:

@@ -54,7 +54,7 @@ static float scaleFactor = 1.0f;
54
54
55
55
@synthesize color, colorIsEnabled, checkboxIsEnabled, minValues, maxValues, minUnits, maxUnits, collapsiblePopupSelection, dividerCanCollapse, collapsibleSubviewCollapsed;
56
56
@synthesize resizableSubviewPreferredProportion, nonresizableSubviewPreferredSize, stateForLastPreferredCalculations;
57
@synthesize toggleCollapseButton;
57
@synthesize toggleCollapseButton, secondaryDelegate;
58
58
59
59
+ (void)initialize;
60
60
{