project_files/HedgewarsMobile/MGSplitViewController.m
changeset 6659 a6030b32b222
parent 6658 2cccf6b2b89d
child 6660 99ecc7e17c4f
--- a/project_files/HedgewarsMobile/MGSplitViewController.m	Thu Feb 09 18:59:46 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1133 +0,0 @@
-//
-//  MGSplitViewController.m
-//  MGSplitView
-//
-//  Created by Matt Gemmell on 26/07/2010.
-//  Copyright 2010 Instinctive Code.
-//
-
-#import "MGSplitViewController.h"
-#import "MGSplitDividerView.h"
-#import "MGSplitCornersView.h"
-
-#define MG_DEFAULT_SPLIT_POSITION		320.0	// default width of master view in UISplitViewController.
-#define MG_DEFAULT_SPLIT_WIDTH			1.0		// default width of split-gutter in UISplitViewController.
-#define MG_DEFAULT_CORNER_RADIUS		5.0		// default corner-radius of overlapping split-inner corners on the master and detail views.
-#define MG_DEFAULT_CORNER_COLOR			[UIColor blackColor]	// default color of intruding inner corners (and divider background).
-
-#define MG_PANESPLITTER_CORNER_RADIUS	0.0		// corner-radius of split-inner corners for MGSplitViewDividerStylePaneSplitter style.
-#define MG_PANESPLITTER_SPLIT_WIDTH		25.0	// width of split-gutter for MGSplitViewDividerStylePaneSplitter style.
-
-#define MG_MIN_VIEW_WIDTH				200.0	// minimum width a view is allowed to become as a result of changing the splitPosition.
-
-#define MG_ANIMATION_CHANGE_SPLIT_ORIENTATION	@"ChangeSplitOrientation"	// Animation ID for internal use.
-#define MG_ANIMATION_CHANGE_SUBVIEWS_ORDER		@"ChangeSubviewsOrder"	// Animation ID for internal use.
-
-
-@interface MGSplitViewController (MGPrivateMethods)
-
-- (void)setup;
-- (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation;
-- (void)layoutSubviews;
-- (void)layoutSubviewsWithAnimation:(BOOL)animate;
-- (void)layoutSubviewsForInterfaceOrientation:(UIInterfaceOrientation)theOrientation withAnimation:(BOOL)animate;
-- (BOOL)shouldShowMasterForInterfaceOrientation:(UIInterfaceOrientation)theOrientation;
-- (BOOL)shouldShowMaster;
-- (NSString *)nameOfInterfaceOrientation:(UIInterfaceOrientation)theOrientation;
-- (void)reconfigureForMasterInPopover:(BOOL)inPopover;
-
-@end
-
-
-@implementation MGSplitViewController
-
-
-#pragma mark -
-#pragma mark Orientation helpers
-
-
-- (NSString *)nameOfInterfaceOrientation:(UIInterfaceOrientation)theOrientation
-{
-	NSString *orientationName = nil;
-	switch (theOrientation) {
-		case UIInterfaceOrientationPortrait:
-			orientationName = @"Portrait"; // Home button at bottom
-			break;
-		case UIInterfaceOrientationPortraitUpsideDown:
-			orientationName = @"Portrait (Upside Down)"; // Home button at top
-			break;
-		case UIInterfaceOrientationLandscapeLeft:
-			orientationName = @"Landscape (Left)"; // Home button on left
-			break;
-		case UIInterfaceOrientationLandscapeRight:
-			orientationName = @"Landscape (Right)"; // Home button on right
-			break;
-		default:
-			break;
-	}
-	
-	return orientationName;
-}
-
-
-- (BOOL)isLandscape
-{
-	return UIInterfaceOrientationIsLandscape(self.interfaceOrientation);
-}
-
-
-- (BOOL)shouldShowMasterForInterfaceOrientation:(UIInterfaceOrientation)theOrientation
-{
-	// Returns YES if master view should be shown directly embedded in the splitview, instead of hidden in a popover.
-	return ((UIInterfaceOrientationIsLandscape(theOrientation)) ? _showsMasterInLandscape : _showsMasterInPortrait);
-}
-
-
-- (BOOL)shouldShowMaster
-{
-	return [self shouldShowMasterForInterfaceOrientation:self.interfaceOrientation];
-}
-
-
-- (BOOL)isShowingMaster
-{
-	return [self shouldShowMaster] && self.masterViewController && self.masterViewController.view && ([self.masterViewController.view superview] == self.view);
-}
-
-
-#pragma mark -
-#pragma mark Setup and Teardown
-
-
-- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
-{
-	if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
-		[self setup];
-	}
-	
-	return self;
-}
-
-
-- (id)initWithCoder:(NSCoder *)aDecoder
-{
-	if ((self = [super initWithCoder:aDecoder])) {
-		[self setup];
-	}
-	
-	return self;
-}
-
-
-- (void)setup
-{
-	// Configure default behaviour.
-	_viewControllers = [[NSMutableArray alloc] initWithObjects:[NSNull null], [NSNull null], nil];
-	_splitWidth = MG_DEFAULT_SPLIT_WIDTH;
-	_showsMasterInPortrait = NO;
-	_showsMasterInLandscape = YES;
-	_reconfigurePopup = NO;
-	_vertical = YES;
-	_masterBeforeDetail = YES;
-	_splitPosition = MG_DEFAULT_SPLIT_POSITION;
-	CGRect divRect = self.view.bounds;
-	if ([self isVertical]) {
-		divRect.origin.y = _splitPosition;
-		divRect.size.height = _splitWidth;
-	} else {
-		divRect.origin.x = _splitPosition;
-		divRect.size.width = _splitWidth;
-	}
-	_dividerView = [[MGSplitDividerView alloc] initWithFrame:divRect];
-	_dividerView.splitViewController = self;
-	_dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR;
-	_dividerStyle = MGSplitViewDividerStyleThin;
-}
-
-
-- (void)dealloc
-{
-	_delegate = nil;
-	[self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
-	[_viewControllers release];
-	[_barButtonItem release];
-	[_hiddenPopoverController release];
-	[_dividerView release];
-	[_cornerViews release];
-	
-	[super dealloc];
-}
-
-
-#pragma mark -
-#pragma mark View management
-
-
-- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-{
-    return YES;
-}
-
-
-- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
-{
-	[self.masterViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
-	[self.detailViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
-}
-
-
-- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
-{
-	[self.masterViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
-	[self.detailViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
-}
-
-
-- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
-										 duration:(NSTimeInterval)duration
-{
-	[self.masterViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
-	[self.detailViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
-	
-	// Hide popover.
-	if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
-		[_hiddenPopoverController dismissPopoverAnimated:NO];
-	}
-	
-	// Re-tile views.
-	_reconfigurePopup = YES;
-	[self layoutSubviewsForInterfaceOrientation:toInterfaceOrientation withAnimation:YES];
-}
-
-
-- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
-{
-	[self.masterViewController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
-	[self.detailViewController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
-}
-
-
-- (void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
-{
-	[self.masterViewController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
-	[self.detailViewController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
-}
-
-
-- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration
-{
-	[self.masterViewController willAnimateSecondHalfOfRotationFromInterfaceOrientation:fromInterfaceOrientation duration:duration];
-	[self.detailViewController willAnimateSecondHalfOfRotationFromInterfaceOrientation:fromInterfaceOrientation duration:duration];
-}
-
-
-- (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation
-{
-	UIScreen *screen = [UIScreen mainScreen];
-	CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation.
-	CGRect appFrame = screen.applicationFrame;
-	
-	// Find status bar height by checking which dimension of the applicationFrame is narrower than screen bounds.
-	// Little bit ugly looking, but it'll still work even if they change the status bar height in future.
-	float statusBarHeight = MAX((fullScreenRect.size.width - appFrame.size.width), (fullScreenRect.size.height - appFrame.size.height));
-	
-	// Initially assume portrait orientation.
-	float width = fullScreenRect.size.width;
-	float height = fullScreenRect.size.height;
-	
-	// Correct for orientation.
-	if (UIInterfaceOrientationIsLandscape(theOrientation)) {
-		width = height;
-		height = fullScreenRect.size.width;
-	}
-	
-	// Account for status bar, which always subtracts from the height (since it's always at the top of the screen).
-	height -= statusBarHeight;
-	
-	return CGSizeMake(width, height);
-}
-
-
-- (void)layoutSubviewsForInterfaceOrientation:(UIInterfaceOrientation)theOrientation withAnimation:(BOOL)animate
-{
-	if (_reconfigurePopup) {
-		[self reconfigureForMasterInPopover:![self shouldShowMasterForInterfaceOrientation:theOrientation]];
-	}
-	
-	// Layout the master, detail and divider views appropriately, adding/removing subviews as needed.
-	// First obtain relevant geometry.
-	CGSize fullSize = [self splitViewSizeForOrientation:theOrientation];
-	float width = fullSize.width;
-	float height = fullSize.height;
-	
-	if (NO) { // Just for debugging.
-		NSLog(@"Target orientation is %@, dimensions will be %.0f x %.0f", 
-			  [self nameOfInterfaceOrientation:theOrientation], width, height);
-	}
-	
-	// Layout the master, divider and detail views.
-	CGRect newFrame = CGRectMake(0, 0, width, height);
-	UIViewController *controller;
-	UIView *theView;
-	BOOL shouldShowMaster = [self shouldShowMasterForInterfaceOrientation:theOrientation];
-	BOOL masterFirst = [self isMasterBeforeDetail];
-	if ([self isVertical]) {
-		// Master on left, detail on right (or vice versa).
-		CGRect masterRect, dividerRect, detailRect;
-		if (masterFirst) {
-			if (!shouldShowMaster) {
-				// Move off-screen.
-				newFrame.origin.x -= (_splitPosition + _splitWidth);
-			}
-			
-			newFrame.size.width = _splitPosition;
-			masterRect = newFrame;
-			
-			newFrame.origin.x += newFrame.size.width;
-			newFrame.size.width = _splitWidth;
-			dividerRect = newFrame;
-			
-			newFrame.origin.x += newFrame.size.width;
-			newFrame.size.width = width - newFrame.origin.x;
-			detailRect = newFrame;
-			
-		} else {
-			if (!shouldShowMaster) {
-				// Move off-screen.
-				newFrame.size.width += (_splitPosition + _splitWidth);
-			}
-			
-			newFrame.size.width -= (_splitPosition + _splitWidth);
-			detailRect = newFrame;
-			
-			newFrame.origin.x += newFrame.size.width;
-			newFrame.size.width = _splitWidth;
-			dividerRect = newFrame;
-			
-			newFrame.origin.x += newFrame.size.width;
-			newFrame.size.width = _splitPosition;
-			masterRect = newFrame;
-		}
-		
-		// Position master.
-		controller = self.masterViewController;
-		if (controller && [controller isKindOfClass:[UIViewController class]])  {
-			theView = controller.view;
-			if (theView) {
-				theView.frame = masterRect;
-				if (!theView.superview) {
-					[controller viewWillAppear:NO];
-					[self.view addSubview:theView];
-					[controller viewDidAppear:NO];
-				}
-			}
-		}
-		
-		// Position divider.
-		theView = _dividerView;
-		theView.frame = dividerRect;
-		if (!theView.superview) {
-			[self.view addSubview:theView];
-		}
-		
-		// Position detail.
-		controller = self.detailViewController;
-		if (controller && [controller isKindOfClass:[UIViewController class]])  {
-			theView = controller.view;
-			if (theView) {
-				theView.frame = detailRect;
-				if (!theView.superview) {
-					[self.view insertSubview:theView aboveSubview:self.masterViewController.view];
-				} else {
-					[self.view bringSubviewToFront:theView];
-				}
-			}
-		}
-		
-	} else {
-		// Master above, detail below (or vice versa).
-		CGRect masterRect, dividerRect, detailRect;
-		if (masterFirst) {
-			if (!shouldShowMaster) {
-				// Move off-screen.
-				newFrame.origin.y -= (_splitPosition + _splitWidth);
-			}
-			
-			newFrame.size.height = _splitPosition;
-			masterRect = newFrame;
-			
-			newFrame.origin.y += newFrame.size.height;
-			newFrame.size.height = _splitWidth;
-			dividerRect = newFrame;
-			
-			newFrame.origin.y += newFrame.size.height;
-			newFrame.size.height = height - newFrame.origin.y;
-			detailRect = newFrame;
-			
-		} else {
-			if (!shouldShowMaster) {
-				// Move off-screen.
-				newFrame.size.height += (_splitPosition + _splitWidth);
-			}
-			
-			newFrame.size.height -= (_splitPosition + _splitWidth);
-			detailRect = newFrame;
-			
-			newFrame.origin.y += newFrame.size.height;
-			newFrame.size.height = _splitWidth;
-			dividerRect = newFrame;
-			
-			newFrame.origin.y += newFrame.size.height;
-			newFrame.size.height = _splitPosition;
-			masterRect = newFrame;
-		}
-		
-		// Position master.
-		controller = self.masterViewController;
-		if (controller && [controller isKindOfClass:[UIViewController class]])  {
-			theView = controller.view;
-			if (theView) {
-				theView.frame = masterRect;
-				if (!theView.superview) {
-					[controller viewWillAppear:NO];
-					[self.view addSubview:theView];
-					[controller viewDidAppear:NO];
-				}
-			}
-		}
-		
-		// Position divider.
-		theView = _dividerView;
-		theView.frame = dividerRect;
-		if (!theView.superview) {
-			[self.view addSubview:theView];
-		}
-		
-		// Position detail.
-		controller = self.detailViewController;
-		if (controller && [controller isKindOfClass:[UIViewController class]])  {
-			theView = controller.view;
-			if (theView) {
-				theView.frame = detailRect;
-				if (!theView.superview) {
-					[self.view insertSubview:theView aboveSubview:self.masterViewController.view];
-				} else {
-					[self.view bringSubviewToFront:theView];
-				}
-			}
-		}
-	}
-	
-	// Create corner views if necessary.
-	MGSplitCornersView *leadingCorners; // top/left of screen in vertical/horizontal split.
-	MGSplitCornersView *trailingCorners; // bottom/right of screen in vertical/horizontal split.
-	if (!_cornerViews) {
-		CGRect cornerRect = CGRectMake(0, 0, 10, 10); // arbitrary, will be resized below.
-		leadingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect];
-		leadingCorners.splitViewController = self;
-		leadingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR;
-		leadingCorners.cornerRadius = MG_DEFAULT_CORNER_RADIUS;
-		trailingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect];
-		trailingCorners.splitViewController = self;
-		trailingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR;
-		trailingCorners.cornerRadius = MG_DEFAULT_CORNER_RADIUS;
-		_cornerViews = [[NSArray alloc] initWithObjects:leadingCorners, trailingCorners, nil];
-		[leadingCorners release];
-		[trailingCorners release];
-		
-	} else if ([_cornerViews count] == 2) {
-		leadingCorners = [_cornerViews objectAtIndex:0];
-		trailingCorners = [_cornerViews objectAtIndex:1];
-	}
-	
-	// Configure and layout the corner-views.
-	leadingCorners.cornersPosition = (_vertical) ? MGCornersPositionLeadingVertical : MGCornersPositionLeadingHorizontal;
-	trailingCorners.cornersPosition = (_vertical) ? MGCornersPositionTrailingVertical : MGCornersPositionTrailingHorizontal;
-	leadingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleBottomMargin : UIViewAutoresizingFlexibleRightMargin;
-	trailingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleTopMargin : UIViewAutoresizingFlexibleLeftMargin;
-	
-	float x, y, cornersWidth, cornersHeight;
-	CGRect leadingRect, trailingRect;
-	float radius = leadingCorners.cornerRadius;
-	if (_vertical) { // left/right split
-		cornersWidth = (radius * 2.0) + _splitWidth;
-		cornersHeight = radius;
-		x = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : width - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius;
-		y = 0;
-		leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // top corners
-		trailingRect = CGRectMake(x, (height - cornersHeight), cornersWidth, cornersHeight); // bottom corners
-		
-	} else { // top/bottom split
-		x = 0;
-		y = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : height - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius;
-		cornersWidth = radius;
-		cornersHeight = (radius * 2.0) + _splitWidth;
-		leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // left corners
-		trailingRect = CGRectMake((width - cornersWidth), y, cornersWidth, cornersHeight); // right corners
-	}
-	
-	leadingCorners.frame = leadingRect;
-	trailingCorners.frame = trailingRect;
-	
-	// Ensure corners are visible and frontmost.
-	if (!leadingCorners.superview) {
-		[self.view insertSubview:leadingCorners aboveSubview:self.detailViewController.view];
-		[self.view insertSubview:trailingCorners aboveSubview:self.detailViewController.view];
-	} else {
-		[self.view bringSubviewToFront:leadingCorners];
-		[self.view bringSubviewToFront:trailingCorners];
-	}
-}
-
-
-- (void)layoutSubviewsWithAnimation:(BOOL)animate
-{
-	[self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:animate];
-}
-
-
-- (void)layoutSubviews
-{
-	[self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:YES];
-}
-
-
-- (void)viewWillAppear:(BOOL)animated
-{
-	[super viewWillAppear:animated];
-	
-	if ([self isShowingMaster]) {
-		[self.masterViewController viewWillAppear:animated];
-	}
-	[self.detailViewController viewWillAppear:animated];
-	
-	_reconfigurePopup = YES;
-	[self layoutSubviews];
-}
-
-
-- (void)viewDidAppear:(BOOL)animated
-{
-	[super viewDidAppear:animated];
-	
-	if ([self isShowingMaster]) {
-		[self.masterViewController viewDidAppear:animated];
-	}
-	[self.detailViewController viewDidAppear:animated];
-}
-
-
-- (void)viewWillDisappear:(BOOL)animated
-{
-	[super viewWillDisappear:animated];
-	
-	if ([self isShowingMaster]) {
-		[self.masterViewController viewWillDisappear:animated];
-	}
-	[self.detailViewController viewWillDisappear:animated];
-}
-
-
-- (void)viewDidDisappear:(BOOL)animated
-{
-	[super viewDidDisappear:animated];
-	
-	if ([self isShowingMaster]) {
-		[self.masterViewController viewDidDisappear:animated];
-	}
-	[self.detailViewController viewDidDisappear:animated];
-}
-
-
-#pragma mark -
-#pragma mark Popover handling
-
-
-- (void)reconfigureForMasterInPopover:(BOOL)inPopover
-{
-	_reconfigurePopup = NO;
-	
-	if ((inPopover && _hiddenPopoverController) || (!inPopover && !_hiddenPopoverController) || !self.masterViewController) {
-		// Nothing to do.
-		return;
-	}
-	
-	if (inPopover && !_hiddenPopoverController && !_barButtonItem) {
-		// Create and configure popover for our masterViewController.
-		[_hiddenPopoverController release];
-		_hiddenPopoverController = nil;
-		[self.masterViewController viewWillDisappear:NO];
-		_hiddenPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.masterViewController];
-		[self.masterViewController viewDidDisappear:NO];
-		
-		// Create and configure _barButtonItem.
-		_barButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Master", nil) 
-														  style:UIBarButtonItemStyleBordered 
-														 target:self 
-														 action:@selector(showMasterPopover:)];
-		
-		// Inform delegate of this state of affairs.
-		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willHideViewController:withBarButtonItem:forPopoverController:)]) {
-			[(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self 
-																willHideViewController:self.masterViewController 
-																	 withBarButtonItem:_barButtonItem 
-																  forPopoverController:_hiddenPopoverController];
-		}
-		
-	} else if (!inPopover && _hiddenPopoverController && _barButtonItem) {
-		// I know this looks strange, but it fixes a bizarre issue with UIPopoverController leaving masterViewController's views in disarray.
-		[_hiddenPopoverController presentPopoverFromRect:CGRectZero inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
-		
-		// Remove master from popover and destroy popover, if it exists.
-		[_hiddenPopoverController dismissPopoverAnimated:NO];
-		[_hiddenPopoverController release];
-		_hiddenPopoverController = nil;
-		
-		// Inform delegate that the _barButtonItem will become invalid.
-		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willShowViewController:invalidatingBarButtonItem:)]) {
-			[(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self 
-																willShowViewController:self.masterViewController 
-															 invalidatingBarButtonItem:_barButtonItem];
-		}
-		
-		// Destroy _barButtonItem.
-		[_barButtonItem release];
-		_barButtonItem = nil;
-		
-		// Move master view.
-		UIView *masterView = self.masterViewController.view;
-		if (masterView && masterView.superview != self.view) {
-			[masterView removeFromSuperview];
-		}
-	}
-}
-
-
-- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
-{
-	[self reconfigureForMasterInPopover:NO];
-}
-
-
-- (void)notePopoverDismissed
-{
-	[self popoverControllerDidDismissPopover:_hiddenPopoverController];
-}
-
-
-#pragma mark -
-#pragma mark Animations
-
-
-- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
-{
-	if (([animationID isEqualToString:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION] || 
-		 [animationID isEqualToString:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER])
-		&& _cornerViews) {
-		for (UIView *corner in _cornerViews) {
-			corner.hidden = NO;
-		}
-		_dividerView.hidden = NO;
-	}
-}
-
-
-#pragma mark -
-#pragma mark IB Actions
-
-
-- (IBAction)toggleSplitOrientation:(id)sender
-{
-	BOOL showingMaster = [self isShowingMaster];
-	if (showingMaster) {
-		if (_cornerViews) {
-			for (UIView *corner in _cornerViews) {
-				corner.hidden = YES;
-			}
-			_dividerView.hidden = YES;
-		}
-		[UIView beginAnimations:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION context:nil];
-		[UIView setAnimationDelegate:self];
-		[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
-	}
-	self.vertical = (!self.vertical);
-	if (showingMaster) {
-		[UIView commitAnimations];
-	}
-}
-
-
-- (IBAction)toggleMasterBeforeDetail:(id)sender
-{
-	BOOL showingMaster = [self isShowingMaster];
-	if (showingMaster) {
-		if (_cornerViews) {
-			for (UIView *corner in _cornerViews) {
-				corner.hidden = YES;
-			}
-			_dividerView.hidden = YES;
-		}
-		[UIView beginAnimations:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER context:nil];
-		[UIView setAnimationDelegate:self];
-		[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
-	}
-	self.masterBeforeDetail = (!self.masterBeforeDetail);
-	if (showingMaster) {
-		[UIView commitAnimations];
-	}
-}
-
-
-- (IBAction)toggleMasterView:(id)sender
-{
-	if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
-		[_hiddenPopoverController dismissPopoverAnimated:NO];
-	}
-	
-	if (![self isShowingMaster]) {
-		// We're about to show the master view. Ensure it's in place off-screen to be animated in.
-		_reconfigurePopup = YES;
-		[self reconfigureForMasterInPopover:NO];
-		[self layoutSubviews];
-	}
-	
-	// This action functions on the current primary orientation; it is independent of the other primary orientation.
-	[UIView beginAnimations:@"toggleMaster" context:nil];
-	if (self.isLandscape) {
-		self.showsMasterInLandscape = !_showsMasterInLandscape;
-	} else {
-		self.showsMasterInPortrait = !_showsMasterInPortrait;
-	}
-	[UIView commitAnimations];
-}
-
-
-- (IBAction)showMasterPopover:(id)sender
-{
-	if (_hiddenPopoverController && !(_hiddenPopoverController.popoverVisible)) {
-		// Inform delegate.
-		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:popoverController:willPresentViewController:)]) {
-			[(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self 
-																	 popoverController:_hiddenPopoverController 
-															 willPresentViewController:self.masterViewController];
-		}
-		
-		// Show popover.
-		[_hiddenPopoverController presentPopoverFromBarButtonItem:_barButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
-	}
-}
-
-
-#pragma mark -
-#pragma mark Accessors and properties
-
-
-- (id)delegate
-{
-	return _delegate;
-}
-
-
-- (void)setDelegate:(id <MGSplitViewControllerDelegate>)newDelegate
-{
-	if (newDelegate != _delegate && 
-		(!newDelegate || [(NSObject *)newDelegate conformsToProtocol:@protocol(MGSplitViewControllerDelegate)])) {
-		_delegate = newDelegate;
-	}
-}
-
-
-- (BOOL)showsMasterInPortrait
-{
-	return _showsMasterInPortrait;
-}
-
-
-- (void)setShowsMasterInPortrait:(BOOL)flag
-{
-	if (flag != _showsMasterInPortrait) {
-		_showsMasterInPortrait = flag;
-		
-		if (![self isLandscape]) { // i.e. if this will cause a visual change.
-			if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
-				[_hiddenPopoverController dismissPopoverAnimated:NO];
-			}
-			
-			// Rearrange views.
-			_reconfigurePopup = YES;
-			[self layoutSubviews];
-		}
-	}
-}
-
-
-- (BOOL)showsMasterInLandscape
-{
-	return _showsMasterInLandscape;
-}
-
-
-- (void)setShowsMasterInLandscape:(BOOL)flag
-{
-	if (flag != _showsMasterInLandscape) {
-		_showsMasterInLandscape = flag;
-		
-		if ([self isLandscape]) { // i.e. if this will cause a visual change.
-			if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
-				[_hiddenPopoverController dismissPopoverAnimated:NO];
-			}
-			
-			// Rearrange views.
-			_reconfigurePopup = YES;
-			[self layoutSubviews];
-		}
-	}
-}
-
-
-- (BOOL)isVertical
-{
-	return _vertical;
-}
-
-
-- (void)setVertical:(BOOL)flag
-{
-	if (flag != _vertical) {
-		if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
-			[_hiddenPopoverController dismissPopoverAnimated:NO];
-		}
-		
-		_vertical = flag;
-		
-		// Inform delegate.
-		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willChangeSplitOrientationToVertical:)]) {
-			[_delegate splitViewController:self willChangeSplitOrientationToVertical:_vertical];
-		}
-		
-		[self layoutSubviews];
-	}
-}
-
-
-- (BOOL)isMasterBeforeDetail
-{
-	return _masterBeforeDetail;
-}
-
-
-- (void)setMasterBeforeDetail:(BOOL)flag
-{
-	if (flag != _masterBeforeDetail) {
-		if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
-			[_hiddenPopoverController dismissPopoverAnimated:NO];
-		}
-		
-		_masterBeforeDetail = flag;
-		
-		if ([self isShowingMaster]) {
-			[self layoutSubviews];
-		}
-	}
-}
-
-
-- (float)splitPosition
-{
-	return _splitPosition;
-}
-
-
-- (void)setSplitPosition:(float)posn
-{
-	// Check to see if delegate wishes to constrain the position.
-	float newPosn = posn;
-	BOOL constrained = NO;
-	CGSize fullSize = [self splitViewSizeForOrientation:self.interfaceOrientation];
-	if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:constrainSplitPosition:splitViewSize:)]) {
-		newPosn = [_delegate splitViewController:self constrainSplitPosition:newPosn splitViewSize:fullSize];
-		constrained = YES; // implicitly trust delegate's response.
-		
-	} else {
-		// Apply default constraints if delegate doesn't wish to participate.
-		float minPos = MG_MIN_VIEW_WIDTH;
-		float maxPos = ((_vertical) ? fullSize.width : fullSize.height) - (MG_MIN_VIEW_WIDTH + _splitWidth);
-		constrained = (newPosn != _splitPosition && newPosn >= minPos && newPosn <= maxPos);
-	}
-	
-	if (constrained) {
-		if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
-			[_hiddenPopoverController dismissPopoverAnimated:NO];
-		}
-		
-		_splitPosition = newPosn;
-		
-		// Inform delegate.
-		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willMoveSplitToPosition:)]) {
-			[_delegate splitViewController:self willMoveSplitToPosition:_splitPosition];
-		}
-		
-		if ([self isShowingMaster]) {
-			[self layoutSubviews];
-		}
-	}
-}
-
-
-- (void)setSplitPosition:(float)posn animated:(BOOL)animate
-{
-	BOOL shouldAnimate = (animate && [self isShowingMaster]);
-	if (shouldAnimate) {
-		[UIView beginAnimations:@"SplitPosition" context:nil];
-	}
-	[self setSplitPosition:posn];
-	if (shouldAnimate) {
-		[UIView commitAnimations];
-	}
-}
-
-
-- (float)splitWidth
-{
-	return _splitWidth;
-}
-
-
-- (void)setSplitWidth:(float)width
-{
-	if (width != _splitWidth && width >= 0) {
-		_splitWidth = width;
-		if ([self isShowingMaster]) {
-			[self layoutSubviews];
-		}
-	}
-}
-
-
-- (NSArray *)viewControllers
-{
-	return [[_viewControllers copy] autorelease];
-}
-
-
-- (void)setViewControllers:(NSArray *)controllers
-{
-	if (controllers != _viewControllers) {
-		for (UIViewController *controller in _viewControllers) {
-			if ([controller isKindOfClass:[UIViewController class]]) {
-				[controller.view removeFromSuperview];
-			}
-		}
-		[_viewControllers release];
-		_viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
-		if (controllers && [controllers count] >= 2) {
-			self.masterViewController = [controllers objectAtIndex:0];
-			self.detailViewController = [controllers objectAtIndex:1];
-		} else {
-			NSLog(@"Error: %@ requires 2 view-controllers. (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
-		}
-		
-		[self layoutSubviews];
-	}
-}
-
-
-- (UIViewController *)masterViewController
-{
-	if (_viewControllers && [_viewControllers count] > 0) {
-		NSObject *controller = [_viewControllers objectAtIndex:0];
-		if ([controller isKindOfClass:[UIViewController class]]) {
-			return [[controller retain] autorelease];
-		}
-	}
-	
-	return nil;
-}
-
-
-- (void)setMasterViewController:(UIViewController *)master
-{
-	if (!_viewControllers) {
-		_viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
-	}
-	
-	NSObject *newMaster = master;
-	if (!newMaster) {
-		newMaster = [NSNull null];
-	}
-	
-	BOOL changed = YES;
-	if ([_viewControllers count] > 0) {
-		if ([_viewControllers objectAtIndex:0] == newMaster) {
-			changed = NO;
-		} else {
-			[_viewControllers replaceObjectAtIndex:0 withObject:newMaster];
-		}
-		
-	} else {
-		[_viewControllers addObject:newMaster];
-	}
-	
-	if (changed) {
-		[self layoutSubviews];
-	}
-}
-
-
-- (UIViewController *)detailViewController
-{
-	if (_viewControllers && [_viewControllers count] > 1) {
-		NSObject *controller = [_viewControllers objectAtIndex:1];
-		if ([controller isKindOfClass:[UIViewController class]]) {
-			return [[controller retain] autorelease];
-		}
-	}
-	
-	return nil;
-}
-
-
-- (void)setDetailViewController:(UIViewController *)detail
-{
-	if (!_viewControllers) {
-		_viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
-		[_viewControllers addObject:[NSNull null]];
-	}
-	
-	BOOL changed = YES;
-	if ([_viewControllers count] > 1) {
-		if ([_viewControllers objectAtIndex:1] == detail) {
-			changed = NO;
-		} else {
-			[_viewControllers replaceObjectAtIndex:1 withObject:detail];
-		}
-		
-	} else {
-		[_viewControllers addObject:detail];
-	}
-	
-	if (changed) {
-		[self layoutSubviews];
-	}
-}
-
-
-- (MGSplitDividerView *)dividerView
-{
-	return [[_dividerView retain] autorelease];
-}
-
-
-- (void)setDividerView:(MGSplitDividerView *)divider
-{
-	if (divider != _dividerView) {
-		[_dividerView removeFromSuperview];
-		[_dividerView release];
-		_dividerView = [divider retain];
-		_dividerView.splitViewController = self;
-		_dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR;
-		if ([self isShowingMaster]) {
-			[self layoutSubviews];
-		}
-	}
-}
-
-
-- (BOOL)allowsDraggingDivider
-{
-	if (_dividerView) {
-		return _dividerView.allowsDragging;
-	}
-	
-	return NO;
-}
-
-
-- (void)setAllowsDraggingDivider:(BOOL)flag
-{
-	if (self.allowsDraggingDivider != flag && _dividerView) {
-		_dividerView.allowsDragging = flag;
-	}
-}
-
-
-- (MGSplitViewDividerStyle)dividerStyle
-{
-	return _dividerStyle;
-}
-
-
-- (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle
-{
-	if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
-		[_hiddenPopoverController dismissPopoverAnimated:NO];
-	}
-	
-	// We don't check to see if newStyle equals _dividerStyle, because it's a meta-setting.
-	// Aspects could have been changed since it was set.
-	_dividerStyle = newStyle;
-	
-	// Reconfigure general appearance and behaviour.
-	float cornerRadius;
-	if (_dividerStyle == MGSplitViewDividerStyleThin) {
-		cornerRadius = MG_DEFAULT_CORNER_RADIUS;
-		_splitWidth = MG_DEFAULT_SPLIT_WIDTH;
-		self.allowsDraggingDivider = NO;
-		
-	} else if (_dividerStyle == MGSplitViewDividerStylePaneSplitter) {
-		cornerRadius = MG_PANESPLITTER_CORNER_RADIUS;
-		_splitWidth = MG_PANESPLITTER_SPLIT_WIDTH;
-		self.allowsDraggingDivider = YES;
-	}
-	
-	// Update divider and corners.
-	[_dividerView setNeedsDisplay];
-	if (_cornerViews) {
-		for (MGSplitCornersView *corner in _cornerViews) {
-			corner.cornerRadius = cornerRadius;
-		}
-	}
-	
-	// Layout all views.
-	[self layoutSubviews];
-}
-
-
-- (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle animated:(BOOL)animate
-{
-	BOOL shouldAnimate = (animate && [self isShowingMaster]);
-	if (shouldAnimate) {
-		[UIView beginAnimations:@"DividerStyle" context:nil];
-	}
-	[self setDividerStyle:newStyle];
-	if (shouldAnimate) {
-		[UIView commitAnimations];
-	}
-}
-
-
-- (NSArray *)cornerViews
-{
-	if (_cornerViews) {
-		return [[_cornerViews retain] autorelease];
-	}
-	
-	return nil;
-}
-
-
-@synthesize showsMasterInPortrait;
-@synthesize showsMasterInLandscape;
-@synthesize vertical;
-@synthesize delegate;
-@synthesize viewControllers;
-@synthesize masterViewController;
-@synthesize detailViewController;
-@synthesize dividerView;
-@synthesize splitPosition;
-@synthesize splitWidth;
-@synthesize allowsDraggingDivider;
-@synthesize dividerStyle;
-
-
-@end