Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

197 lines (143 sloc) 5.723 kB
//
// DBListSplitter.m
//
// Created by Dave Batton, August 2006.
// http://www.Mere-Mortal-Software.com/
//
// Copyright 2006 by Dave Batton. Some rights reserved.
// http://creativecommons.org/licenses/by/2.5/
//
// This class draws a horizontal splitter like the one seen in Apple Mail (Tiger), below the message list and above the message detail view. It subclasses KFSplitView from Ken Ferry so that the splitter remembers where it was last left. It also allows the splitter to expand and collapse when double-clicked. The splitter thickness is reduced a bit and a background image and dimple are drawn in the splitter.
//
// Assumes the DBListSplitViewBar and DBListSplitViewDimple images are available.
//
#define MIN_TOP_VIEW_HEIGHT 90
#define MIN_BOTTOM_VIEW_HEIGHT 60
#import "DBListSplitView.h"
@implementation DBListSplitView
-(void)awakeFromNib
{
[self setDelegate:self];
bottomSubview = [[self subviews] objectAtIndex:1];
bar = [NSImage imageNamed:@"DBListSplitViewBar.tiff"];
[bar setFlipped:YES];
grip = [NSImage imageNamed:@"DBListSplitViewDimple.tiff"];
[grip setFlipped:YES];
}
- (float)dividerThickness
{
return (8);
}
- (void)drawDividerInRect:(NSRect)aRect
{
// Create a canvas
NSImage *canvas = [[[NSImage alloc] initWithSize:aRect.size] autorelease];
// Draw bar and grip onto the canvas
NSRect canvasRect = NSMakeRect(0, 0, [canvas size].width, [canvas size].height);
NSRect gripRect = canvasRect;
gripRect.origin.x = (NSMidX(canvasRect) - ([grip size].width/2));
gripRect.origin.y = (NSMidY(canvasRect) - ([grip size].height/2));
[canvas lockFocus];
[bar setSize:aRect.size];
[bar drawInRect:canvasRect fromRect:canvasRect operation:NSCompositeSourceOver fraction:1.0];
[grip drawInRect:gripRect fromRect:canvasRect operation:NSCompositeSourceOver fraction:1.0];
[canvas unlockFocus];
// Draw canvas to divider bar
[self lockFocus];
[canvas drawInRect:aRect fromRect:canvasRect operation:NSCompositeSourceOver fraction:1.0];
[self unlockFocus];
}
#pragma mark -
#pragma mark KFSplitView Delegate Methods
- (void)splitView:(id)sender didDoubleClickInDivider:(int)index
{
BOOL currentState;
switch (index) {
case 0:
currentState = [self isSubviewCollapsed:bottomSubview];
[self setSubview:bottomSubview isCollapsed:!currentState];
[self resizeSubviewsWithOldSize:[self bounds].size];
break;
}
}
- (float)splitView:(id)sender constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(int)offset
{
return proposedMax - MIN_BOTTOM_VIEW_HEIGHT; // How close the splitter can get to the bottom.
}
- (float)splitView:(id)sender constrainMinCoordinate:(float)proposedMin ofSubviewAt:(int)offset
{
return proposedMin + MIN_TOP_VIEW_HEIGHT; // How close the splitter can get to the top.
}
- (BOOL)splitView:(id)sender canCollapseSubview:(NSView *)subview
{
return (subview == bottomSubview);
}
// This delegate method is mostly copied from the KFSplitView example application. It allows the subview to collapse and then expand to its original position when double-clicked a second time.
- (void)splitView:(id)sender resizeSubviewsWithOldSize:(NSSize)oldSize
{
// It's our responsibility to set the frame rectangles of all uncollapsed subviews.
int i, numSubviews, numDividers;
float heightTotal, splitViewWidth, splitViewHeight, newSubviewHeight;
float curYAxisPos, dividerThickness, scaleFactor, availableSpace;
float minimumFirstSubviewHeight;
id subview, subviews;
// setup
subviews = [sender subviews];
numSubviews = [subviews count];
numDividers = numSubviews - 1;
splitViewWidth = [sender frame].size.width;
splitViewHeight = [sender frame].size.height;
dividerThickness = [sender dividerThickness];
minimumFirstSubviewHeight = 90;
// tabulate the total space taken up by uncollapsed subviews other than the first
heightTotal = 0;
for (i = 1; i < numSubviews; i++)
{
subview = [subviews objectAtIndex:i];
if (![sender isSubviewCollapsed:subview])
{
heightTotal += [subview frame].size.height;
}
}
// if the uncollapsed subviews (not counting the first) take up too much space then
// we have to scale them
availableSpace = splitViewHeight - minimumFirstSubviewHeight - numDividers*dividerThickness;
if (heightTotal > availableSpace)
{
if (availableSpace < 0)
{
scaleFactor = 0;
}
else
{
scaleFactor = availableSpace / heightTotal;
}
}
else
{
scaleFactor = 1;
}
// we walk up the Y-axis, setting subview frames as we go
curYAxisPos = splitViewHeight;
for (i = numSubviews - 1; i >0; i--)
{
subview = [subviews objectAtIndex:i];
if (![sender isSubviewCollapsed:subview])
{
// expanded subviews need to have their origin set correctly and
// their size scaled.
newSubviewHeight = floor([subview frame].size.height*scaleFactor);
curYAxisPos -= newSubviewHeight;
[subview setFrame:NSMakeRect(0, curYAxisPos, splitViewWidth, newSubviewHeight)];
}
// account for the divider taking up space
curYAxisPos -= dividerThickness;
}
// the first subview subview's height is whatever's left over
subview = [subviews objectAtIndex:0];
[subview setFrame:NSMakeRect(0, 0, splitViewWidth, curYAxisPos)];
// if we wanted error checking, we could call adjustSubviews. It would
// only change something if we messed up and didn't really tile the split view correctly.
// [sender adjustSubviews];
}
@end
Jump to Line
Something went wrong with that request. Please try again.