project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m
branchios-revival
changeset 11115 3729ac42189b
parent 8441 a00b0fa0dbd7
child 11217 e68b3e392091
equal deleted inserted replaced
11114:6a0bd9c6cc82 11115:3729ac42189b
     8 
     8 
     9 #import "MGSplitViewController.h"
     9 #import "MGSplitViewController.h"
    10 #import "MGSplitDividerView.h"
    10 #import "MGSplitDividerView.h"
    11 #import "MGSplitCornersView.h"
    11 #import "MGSplitCornersView.h"
    12 
    12 
    13 #define MG_DEFAULT_SPLIT_POSITION       320.0   // default width of master view in UISplitViewController.
    13 #define MG_DEFAULT_SPLIT_POSITION		320.0	// default width of master view in UISplitViewController.
    14 #define MG_DEFAULT_SPLIT_WIDTH          1.0     // default width of split-gutter in UISplitViewController.
    14 #define MG_DEFAULT_SPLIT_WIDTH			1.0		// default width of split-gutter in UISplitViewController.
    15 #define MG_DEFAULT_CORNER_RADIUS        5.0     // default corner-radius of overlapping split-inner corners on the master and detail views.
    15 #define MG_DEFAULT_CORNER_RADIUS		5.0		// default corner-radius of overlapping split-inner corners on the master and detail views.
    16 #define MG_DEFAULT_CORNER_COLOR         [UIColor blackColor]    // default color of intruding inner corners (and divider background).
    16 #define MG_DEFAULT_CORNER_COLOR			[UIColor blackColor]	// default color of intruding inner corners (and divider background).
    17 
    17 
    18 #define MG_PANESPLITTER_CORNER_RADIUS   0.0     // corner-radius of split-inner corners for MGSplitViewDividerStylePaneSplitter style.
    18 #define MG_PANESPLITTER_CORNER_RADIUS	0.0		// corner-radius of split-inner corners for MGSplitViewDividerStylePaneSplitter style.
    19 #define MG_PANESPLITTER_SPLIT_WIDTH     25.0    // width of split-gutter for MGSplitViewDividerStylePaneSplitter style.
    19 #define MG_PANESPLITTER_SPLIT_WIDTH		25.0	// width of split-gutter for MGSplitViewDividerStylePaneSplitter style.
    20 
    20 
    21 #define MG_MIN_VIEW_WIDTH               200.0   // minimum width a view is allowed to become as a result of changing the splitPosition.
    21 #define MG_MIN_VIEW_WIDTH				200.0	// minimum width a view is allowed to become as a result of changing the splitPosition.
    22 
    22 
    23 #define MG_ANIMATION_CHANGE_SPLIT_ORIENTATION   @"ChangeSplitOrientation"   // Animation ID for internal use.
    23 #define MG_ANIMATION_CHANGE_SPLIT_ORIENTATION	@"ChangeSplitOrientation"	// Animation ID for internal use.
    24 #define MG_ANIMATION_CHANGE_SUBVIEWS_ORDER      @"ChangeSubviewsOrder"  // Animation ID for internal use.
    24 #define MG_ANIMATION_CHANGE_SUBVIEWS_ORDER		@"ChangeSubviewsOrder"	// Animation ID for internal use.
    25 
       
    26 
    25 
    27 @interface MGSplitViewController (MGPrivateMethods)
    26 @interface MGSplitViewController (MGPrivateMethods)
    28 
    27 
    29 - (void)setup;
    28 - (void)setup;
    30 - (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation;
    29 - (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation;
    46 #pragma mark Orientation helpers
    45 #pragma mark Orientation helpers
    47 
    46 
    48 
    47 
    49 - (NSString *)nameOfInterfaceOrientation:(UIInterfaceOrientation)theOrientation
    48 - (NSString *)nameOfInterfaceOrientation:(UIInterfaceOrientation)theOrientation
    50 {
    49 {
    51     NSString *orientationName = nil;
    50 	NSString *orientationName = nil;
    52     switch (theOrientation) {
    51 	switch (theOrientation) {
    53         case UIInterfaceOrientationPortrait:
    52 		case UIInterfaceOrientationPortrait:
    54             orientationName = @"Portrait"; // Home button at bottom
    53 			orientationName = @"Portrait"; // Home button at bottom
    55             break;
    54 			break;
    56         case UIInterfaceOrientationPortraitUpsideDown:
    55 		case UIInterfaceOrientationPortraitUpsideDown:
    57             orientationName = @"Portrait (Upside Down)"; // Home button at top
    56 			orientationName = @"Portrait (Upside Down)"; // Home button at top
    58             break;
    57 			break;
    59         case UIInterfaceOrientationLandscapeLeft:
    58 		case UIInterfaceOrientationLandscapeLeft:
    60             orientationName = @"Landscape (Left)"; // Home button on left
    59 			orientationName = @"Landscape (Left)"; // Home button on left
    61             break;
    60 			break;
    62         case UIInterfaceOrientationLandscapeRight:
    61 		case UIInterfaceOrientationLandscapeRight:
    63             orientationName = @"Landscape (Right)"; // Home button on right
    62 			orientationName = @"Landscape (Right)"; // Home button on right
    64             break;
    63 			break;
    65         default:
    64 		default:
    66             break;
    65 			break;
    67     }
    66 	}
    68 
    67 	
    69     return orientationName;
    68 	return orientationName;
    70 }
    69 }
    71 
    70 
    72 
    71 
    73 - (BOOL)isLandscape
    72 - (BOOL)isLandscape
    74 {
    73 {
    75     return UIInterfaceOrientationIsLandscape(self.interfaceOrientation);
    74 	return UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]);
    76 }
    75 }
    77 
    76 
    78 
    77 
    79 - (BOOL)shouldShowMasterForInterfaceOrientation:(UIInterfaceOrientation)theOrientation
    78 - (BOOL)shouldShowMasterForInterfaceOrientation:(UIInterfaceOrientation)theOrientation
    80 {
    79 {
    81     // Returns YES if master view should be shown directly embedded in the splitview, instead of hidden in a popover.
    80 	// Returns YES if master view should be shown directly embedded in the splitview, instead of hidden in a popover.
    82     return ((UIInterfaceOrientationIsLandscape(theOrientation)) ? _showsMasterInLandscape : _showsMasterInPortrait);
    81 	return ((UIInterfaceOrientationIsLandscape(theOrientation)) ? _showsMasterInLandscape : _showsMasterInPortrait);
    83 }
    82 }
    84 
    83 
    85 
    84 
    86 - (BOOL)shouldShowMaster
    85 - (BOOL)shouldShowMaster
    87 {
    86 {
    88     return [self shouldShowMasterForInterfaceOrientation:self.interfaceOrientation];
    87 	return [self shouldShowMasterForInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
    89 }
    88 }
    90 
    89 
    91 
    90 
    92 - (BOOL)isShowingMaster
    91 - (BOOL)isShowingMaster
    93 {
    92 {
    94     return [self shouldShowMaster] && self.masterViewController && self.masterViewController.view && ([self.masterViewController.view superview] == self.view);
    93 	return [self shouldShowMaster] && self.masterViewController && self.masterViewController.view && ([self.masterViewController.view superview] == self.view);
    95 }
    94 }
    96 
    95 
    97 
    96 
    98 #pragma mark -
    97 #pragma mark -
    99 #pragma mark Setup and Teardown
    98 #pragma mark Setup and Teardown
   100 
    99 
   101 
   100 
   102 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
   101 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
   103 {
   102 {
   104     if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
   103 	if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
   105         [self setup];
   104 		[self setup];
   106     }
   105 	}
   107 
   106 	
   108     return self;
   107 	return self;
   109 }
   108 }
   110 
   109 
   111 
   110 
   112 - (id)initWithCoder:(NSCoder *)aDecoder
   111 - (id)initWithCoder:(NSCoder *)aDecoder
   113 {
   112 {
   114     if ((self = [super initWithCoder:aDecoder])) {
   113 	if ((self = [super initWithCoder:aDecoder])) {
   115         [self setup];
   114 		[self setup];
   116     }
   115 	}
   117 
   116 	
   118     return self;
   117 	return self;
   119 }
   118 }
   120 
   119 
   121 
   120 
   122 - (void)setup
   121 - (void)setup
   123 {
   122 {
   124     // Configure default behaviour.
   123 	// Configure default behaviour.
   125     _viewControllers = [[NSMutableArray alloc] initWithObjects:[NSNull null], [NSNull null], nil];
   124 	_viewControllers = [[NSMutableArray alloc] initWithObjects:[NSNull null], [NSNull null], nil];
   126     _splitWidth = MG_DEFAULT_SPLIT_WIDTH;
   125 	_splitWidth = MG_DEFAULT_SPLIT_WIDTH;
   127     _showsMasterInPortrait = NO;
   126 	_showsMasterInPortrait = NO;
   128     _showsMasterInLandscape = YES;
   127 	_showsMasterInLandscape = YES;
   129     _reconfigurePopup = NO;
   128 	_reconfigurePopup = NO;
   130     _vertical = YES;
   129 	_vertical = YES;
   131     _masterBeforeDetail = YES;
   130 	_masterBeforeDetail = YES;
   132     _splitPosition = MG_DEFAULT_SPLIT_POSITION;
   131 	_splitPosition = MG_DEFAULT_SPLIT_POSITION;
   133     CGRect divRect = self.view.bounds;
   132 	CGRect divRect = self.view.bounds;
   134     if ([self isVertical]) {
   133 	if ([self isVertical]) {
   135         divRect.origin.y = _splitPosition;
   134 		divRect.origin.y = _splitPosition;
   136         divRect.size.height = _splitWidth;
   135 		divRect.size.height = _splitWidth;
   137     } else {
   136 	} else {
   138         divRect.origin.x = _splitPosition;
   137 		divRect.origin.x = _splitPosition;
   139         divRect.size.width = _splitWidth;
   138 		divRect.size.width = _splitWidth;
   140     }
   139 	}
   141     _dividerView = [[MGSplitDividerView alloc] initWithFrame:divRect];
   140 	_dividerView = [[MGSplitDividerView alloc] initWithFrame:divRect];
   142     _dividerView.splitViewController = self;
   141 	_dividerView.splitViewController = self;
   143     _dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR;
   142 	_dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR;
   144     _dividerStyle = MGSplitViewDividerStyleThin;
   143 	_dividerStyle = MGSplitViewDividerStyleThin;
       
   144 
       
   145     // fix for iOS 6 layout
       
   146     self.view.autoresizesSubviews = NO;
   145 }
   147 }
   146 
   148 
   147 
   149 
   148 - (void)dealloc
   150 - (void)dealloc
   149 {
   151 {
   150     _delegate = nil;
   152 	_delegate = nil;
   151     [self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
   153 	_viewControllers = nil;
   152     [_viewControllers release];
   154 	[self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
   153     [_barButtonItem release];
   155     
   154     [_hiddenPopoverController release];
       
   155     [_dividerView release];
       
   156     [_cornerViews release];
       
   157 
       
   158     [super dealloc];
   156     [super dealloc];
   159 }
   157 }
   160 
   158 
   161 
   159 
   162 #pragma mark -
   160 #pragma mark -
   163 #pragma mark View management
   161 #pragma mark View management
   164 
   162 
   165 
   163 
   166 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
   164 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
   167 {
   165 {
       
   166     if (self.detailViewController)
       
   167     {
       
   168         return [self.detailViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
       
   169     }
       
   170 
   168     return YES;
   171     return YES;
   169 }
   172 }
   170 
   173 
   171 
   174 
   172 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
   175 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
   173 {
   176 {
   174     [self.masterViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
   177 	[self.masterViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
   175     [self.detailViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
   178 	[self.detailViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
   176 }
   179 }
   177 
   180 
   178 
   181 
   179 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
   182 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
   180 {
   183 {
   181     [self.masterViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
   184 	[self.masterViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
   182     [self.detailViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
   185 	[self.detailViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
   183 }
   186 }
   184 
   187 
   185 
   188 
   186 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
   189 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
   187                                          duration:(NSTimeInterval)duration
   190 										 duration:(NSTimeInterval)duration
   188 {
   191 {
   189     [self.masterViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
   192 	[self.masterViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
   190     [self.detailViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
   193 	[self.detailViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
   191 
   194 	
   192     // Hide popover.
   195 	// Hide popover.
   193     if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   196 	if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   194         [_hiddenPopoverController dismissPopoverAnimated:NO];
   197 		[_hiddenPopoverController dismissPopoverAnimated:NO];
       
   198 	}
       
   199 	
       
   200 	// Re-tile views.
       
   201 	_reconfigurePopup = YES;
       
   202 	[self layoutSubviewsForInterfaceOrientation:toInterfaceOrientation withAnimation:YES];
       
   203 }
       
   204 
       
   205 
       
   206 - (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation
       
   207 {
       
   208 	UIScreen *screen = [UIScreen mainScreen];
       
   209 	CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation.
       
   210 	CGRect appFrame = screen.applicationFrame;
       
   211 	
       
   212 	// Find status bar height by checking which dimension of the applicationFrame is narrower than screen bounds.
       
   213 	// Little bit ugly looking, but it'll still work even if they change the status bar height in future.
       
   214 	float statusBarHeight = MAX((fullScreenRect.size.width - appFrame.size.width), (fullScreenRect.size.height - appFrame.size.height));
       
   215     
       
   216     // In iOS 7 the status bar is transparent, so don't adjust for it.
       
   217     if (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0) {
       
   218         statusBarHeight = 0;
   195     }
   219     }
   196 
   220 	
   197     // Re-tile views.
   221 	float navigationBarHeight = 0;
   198     _reconfigurePopup = YES;
   222 	if ((self.navigationController)&&(!self.navigationController.navigationBarHidden)) {
   199     [self layoutSubviewsForInterfaceOrientation:toInterfaceOrientation withAnimation:YES];
   223 		navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
   200 }
   224 	}
   201 
   225 	
   202 
   226 	// Initially assume portrait orientation.
   203 - (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
   227 	float width = fullScreenRect.size.width;
   204 {
   228 	float height = fullScreenRect.size.height;
   205     [self.masterViewController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
   229 	
   206     [self.detailViewController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
   230     // Correct for orientation (only for iOS7.1 and earlier, since iOS8 it will do it automatically).
   207 }
   231 	if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1 && UIInterfaceOrientationIsLandscape(theOrientation)) {
   208 
   232 		width = height;
   209 
   233 		height = fullScreenRect.size.width;
   210 - (void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
   234 	}
   211 {
   235 	
   212     [self.masterViewController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
   236 	// Account for status bar, which always subtracts from the height (since it's always at the top of the screen).
   213     [self.detailViewController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
   237 	height -= statusBarHeight;
   214 }
   238 	height -= navigationBarHeight;
   215 
   239 	
   216 
   240 	return CGSizeMake(width, height);
   217 - (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration
       
   218 {
       
   219     [self.masterViewController willAnimateSecondHalfOfRotationFromInterfaceOrientation:fromInterfaceOrientation duration:duration];
       
   220     [self.detailViewController willAnimateSecondHalfOfRotationFromInterfaceOrientation:fromInterfaceOrientation duration:duration];
       
   221 }
       
   222 
       
   223 
       
   224 - (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation
       
   225 {
       
   226     UIScreen *screen = [UIScreen mainScreen];
       
   227     CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation.
       
   228     CGRect appFrame = screen.applicationFrame;
       
   229 
       
   230     // Find status bar height by checking which dimension of the applicationFrame is narrower than screen bounds.
       
   231     // Little bit ugly looking, but it'll still work even if they change the status bar height in future.
       
   232     float statusBarHeight = MAX((fullScreenRect.size.width - appFrame.size.width), (fullScreenRect.size.height - appFrame.size.height));
       
   233 
       
   234     // Initially assume portrait orientation.
       
   235     float width = fullScreenRect.size.width;
       
   236     float height = fullScreenRect.size.height;
       
   237 
       
   238     // Correct for orientation.
       
   239     if (UIInterfaceOrientationIsLandscape(theOrientation)) {
       
   240         width = height;
       
   241         height = fullScreenRect.size.width;
       
   242     }
       
   243 
       
   244     // Account for status bar, which always subtracts from the height (since it's always at the top of the screen).
       
   245     height -= statusBarHeight;
       
   246 
       
   247     return CGSizeMake(width, height);
       
   248 }
   241 }
   249 
   242 
   250 
   243 
   251 - (void)layoutSubviewsForInterfaceOrientation:(UIInterfaceOrientation)theOrientation withAnimation:(BOOL)animate
   244 - (void)layoutSubviewsForInterfaceOrientation:(UIInterfaceOrientation)theOrientation withAnimation:(BOOL)animate
   252 {
   245 {
   253     if (_reconfigurePopup) {
   246 	if (_reconfigurePopup) {
   254         [self reconfigureForMasterInPopover:![self shouldShowMasterForInterfaceOrientation:theOrientation]];
   247 		[self reconfigureForMasterInPopover:![self shouldShowMasterForInterfaceOrientation:theOrientation]];
   255     }
   248 	}
   256 
   249 	
   257     // Layout the master, detail and divider views appropriately, adding/removing subviews as needed.
   250 	// Layout the master, detail and divider views appropriately, adding/removing subviews as needed.
   258     // First obtain relevant geometry.
   251 	// First obtain relevant geometry.
   259     CGSize fullSize = [self splitViewSizeForOrientation:theOrientation];
   252 	CGSize fullSize = [self splitViewSizeForOrientation:theOrientation];
   260     float width = fullSize.width;
   253 	float width = fullSize.width;
   261     float height = fullSize.height;
   254 	float height = fullSize.height;
   262 
   255 	
   263     if (NO) { // Just for debugging.
   256 	if (NO) { // Just for debugging.
   264         NSLog(@"Target orientation is %@, dimensions will be %.0f x %.0f",
   257 		NSLog(@"Target orientation is %@, dimensions will be %.0f x %.0f", 
   265               [self nameOfInterfaceOrientation:theOrientation], width, height);
   258 			  [self nameOfInterfaceOrientation:theOrientation], width, height);
   266     }
   259 	}
   267 
   260 	
   268     // Layout the master, divider and detail views.
   261 	// Layout the master, divider and detail views.
   269     CGRect newFrame = CGRectMake(0, 0, width, height);
   262 	CGRect newFrame = CGRectMake(0, 0, width, height);
   270     UIViewController *controller;
   263 	UIViewController *controller;
   271     UIView *theView;
   264 	UIView *theView;
   272     BOOL shouldShowMaster = [self shouldShowMasterForInterfaceOrientation:theOrientation];
   265 	BOOL shouldShowMaster = [self shouldShowMasterForInterfaceOrientation:theOrientation];
   273     BOOL masterFirst = [self isMasterBeforeDetail];
   266 	BOOL masterFirst = [self isMasterBeforeDetail];
   274     if ([self isVertical]) {
   267 	if ([self isVertical]) {
   275         // Master on left, detail on right (or vice versa).
   268 		// Master on left, detail on right (or vice versa).
   276         CGRect masterRect, dividerRect, detailRect;
   269 		CGRect masterRect, dividerRect, detailRect;
   277         if (masterFirst) {
   270 		if (masterFirst) {
   278             if (!shouldShowMaster) {
   271 			if (!shouldShowMaster) {
   279                 // Move off-screen.
   272 				// Move off-screen.
   280                 newFrame.origin.x -= (_splitPosition + _splitWidth);
   273 				newFrame.origin.x -= (_splitPosition + _splitWidth);
   281             }
   274 			}
   282 
   275 			
   283             newFrame.size.width = _splitPosition;
   276 			newFrame.size.width = _splitPosition;
   284             masterRect = newFrame;
   277 			masterRect = newFrame;
   285 
   278 			
   286             newFrame.origin.x += newFrame.size.width;
   279 			newFrame.origin.x += newFrame.size.width;
   287             newFrame.size.width = _splitWidth;
   280 			newFrame.size.width = _splitWidth;
   288             dividerRect = newFrame;
   281 			dividerRect = newFrame;
   289 
   282 			
   290             newFrame.origin.x += newFrame.size.width;
   283 			newFrame.origin.x += newFrame.size.width;
   291             newFrame.size.width = width - newFrame.origin.x;
   284 			newFrame.size.width = width - newFrame.origin.x;
   292             detailRect = newFrame;
   285 			detailRect = newFrame;
   293 
   286 			
   294         } else {
   287 		} else {
   295             if (!shouldShowMaster) {
   288 			if (!shouldShowMaster) {
   296                 // Move off-screen.
   289 				// Move off-screen.
   297                 newFrame.size.width += (_splitPosition + _splitWidth);
   290 				newFrame.size.width += (_splitPosition + _splitWidth);
   298             }
   291 			}
   299 
   292 			
   300             newFrame.size.width -= (_splitPosition + _splitWidth);
   293 			newFrame.size.width -= (_splitPosition + _splitWidth);
   301             detailRect = newFrame;
   294 			detailRect = newFrame;
   302 
   295 			
   303             newFrame.origin.x += newFrame.size.width;
   296 			newFrame.origin.x += newFrame.size.width;
   304             newFrame.size.width = _splitWidth;
   297 			newFrame.size.width = _splitWidth;
   305             dividerRect = newFrame;
   298 			dividerRect = newFrame;
   306 
   299 			
   307             newFrame.origin.x += newFrame.size.width;
   300 			newFrame.origin.x += newFrame.size.width;
   308             newFrame.size.width = _splitPosition;
   301 			newFrame.size.width = _splitPosition;
   309             masterRect = newFrame;
   302 			masterRect = newFrame;
   310         }
   303 		}
   311 
   304 		
   312         // Position master.
   305 		// Position master.
   313         controller = self.masterViewController;
   306 		controller = self.masterViewController;
   314         if (controller && [controller isKindOfClass:[UIViewController class]])  {
   307 		if (controller && [controller isKindOfClass:[UIViewController class]])  {
   315             theView = controller.view;
   308 			theView = controller.view;
   316             if (theView) {
   309 			if (theView) {
   317                 theView.frame = masterRect;
   310 				theView.frame = masterRect;
   318                 if (!theView.superview) {
   311 				if (!theView.superview) {
   319                     [controller viewWillAppear:NO];
   312 					[controller viewWillAppear:NO];
   320                     [self.view addSubview:theView];
   313 					[self.view addSubview:theView];
   321                     [controller viewDidAppear:NO];
   314 					[controller viewDidAppear:NO];
   322                 }
   315 				}
   323             }
   316 			}
   324         }
   317 		}
   325 
   318 		
   326         // Position divider.
   319 		// Position divider.
   327         theView = _dividerView;
   320 		theView = _dividerView;
   328         theView.frame = dividerRect;
   321 		theView.frame = dividerRect;
   329         if (!theView.superview) {
   322 		if (!theView.superview) {
   330             [self.view addSubview:theView];
   323 			[self.view addSubview:theView];
   331         }
   324 		}
   332 
   325 		
   333         // Position detail.
   326 		// Position detail.
   334         controller = self.detailViewController;
   327 		controller = self.detailViewController;
   335         if (controller && [controller isKindOfClass:[UIViewController class]])  {
   328 		if (controller && [controller isKindOfClass:[UIViewController class]])  {
   336             theView = controller.view;
   329 			theView = controller.view;
   337             if (theView) {
   330 			if (theView) {
   338                 theView.frame = detailRect;
   331 				theView.frame = detailRect;
   339                 if (!theView.superview) {
   332 				if (!theView.superview) {
   340                     [self.view insertSubview:theView aboveSubview:self.masterViewController.view];
   333 					[self.view insertSubview:theView aboveSubview:self.masterViewController.view];
   341                 } else {
   334 				} else {
   342                     [self.view bringSubviewToFront:theView];
   335 					[self.view bringSubviewToFront:theView];
   343                 }
   336 				}
   344             }
   337 			}
   345         }
   338 		}
   346 
   339 		
   347     } else {
   340 	} else {
   348         // Master above, detail below (or vice versa).
   341 		// Master above, detail below (or vice versa).
   349         CGRect masterRect, dividerRect, detailRect;
   342 		CGRect masterRect, dividerRect, detailRect;
   350         if (masterFirst) {
   343 		if (masterFirst) {
   351             if (!shouldShowMaster) {
   344 			if (!shouldShowMaster) {
   352                 // Move off-screen.
   345 				// Move off-screen.
   353                 newFrame.origin.y -= (_splitPosition + _splitWidth);
   346 				newFrame.origin.y -= (_splitPosition + _splitWidth);
   354             }
   347 			}
   355 
   348 			
   356             newFrame.size.height = _splitPosition;
   349 			newFrame.size.height = _splitPosition;
   357             masterRect = newFrame;
   350 			masterRect = newFrame;
   358 
   351 			
   359             newFrame.origin.y += newFrame.size.height;
   352 			newFrame.origin.y += newFrame.size.height;
   360             newFrame.size.height = _splitWidth;
   353 			newFrame.size.height = _splitWidth;
   361             dividerRect = newFrame;
   354 			dividerRect = newFrame;
   362 
   355 			
   363             newFrame.origin.y += newFrame.size.height;
   356 			newFrame.origin.y += newFrame.size.height;
   364             newFrame.size.height = height - newFrame.origin.y;
   357 			newFrame.size.height = height - newFrame.origin.y;
   365             detailRect = newFrame;
   358 			detailRect = newFrame;
   366 
   359 			
   367         } else {
   360 		} else {
   368             if (!shouldShowMaster) {
   361 			if (!shouldShowMaster) {
   369                 // Move off-screen.
   362 				// Move off-screen.
   370                 newFrame.size.height += (_splitPosition + _splitWidth);
   363 				newFrame.size.height += (_splitPosition + _splitWidth);
   371             }
   364 			}
   372 
   365 			
   373             newFrame.size.height -= (_splitPosition + _splitWidth);
   366 			newFrame.size.height -= (_splitPosition + _splitWidth);
   374             detailRect = newFrame;
   367 			detailRect = newFrame;
   375 
   368 			
   376             newFrame.origin.y += newFrame.size.height;
   369 			newFrame.origin.y += newFrame.size.height;
   377             newFrame.size.height = _splitWidth;
   370 			newFrame.size.height = _splitWidth;
   378             dividerRect = newFrame;
   371 			dividerRect = newFrame;
   379 
   372 			
   380             newFrame.origin.y += newFrame.size.height;
   373 			newFrame.origin.y += newFrame.size.height;
   381             newFrame.size.height = _splitPosition;
   374 			newFrame.size.height = _splitPosition;
   382             masterRect = newFrame;
   375 			masterRect = newFrame;
   383         }
   376 		}
   384 
   377 		
   385         // Position master.
   378 		// Position master.
   386         controller = self.masterViewController;
   379 		controller = self.masterViewController;
   387         if (controller && [controller isKindOfClass:[UIViewController class]])  {
   380 		if (controller && [controller isKindOfClass:[UIViewController class]])  {
   388             theView = controller.view;
   381 			theView = controller.view;
   389             if (theView) {
   382 			if (theView) {
   390                 theView.frame = masterRect;
   383 				theView.frame = masterRect;
   391                 if (!theView.superview) {
   384 				if (!theView.superview) {
   392                     [controller viewWillAppear:NO];
   385 					[controller viewWillAppear:NO];
   393                     [self.view addSubview:theView];
   386 					[self.view addSubview:theView];
   394                     [controller viewDidAppear:NO];
   387 					[controller viewDidAppear:NO];
   395                 }
   388 				}
   396             }
   389 			}
   397         }
   390 		}
   398 
   391 		
   399         // Position divider.
   392 		// Position divider.
   400         theView = _dividerView;
   393 		theView = _dividerView;
   401         theView.frame = dividerRect;
   394 		theView.frame = dividerRect;
   402         if (!theView.superview) {
   395 		if (!theView.superview) {
   403             [self.view addSubview:theView];
   396 			[self.view addSubview:theView];
   404         }
   397 		}
   405 
   398 		
   406         // Position detail.
   399 		// Position detail.
   407         controller = self.detailViewController;
   400 		controller = self.detailViewController;
   408         if (controller && [controller isKindOfClass:[UIViewController class]])  {
   401 		if (controller && [controller isKindOfClass:[UIViewController class]])  {
   409             theView = controller.view;
   402 			theView = controller.view;
   410             if (theView) {
   403 			if (theView) {
   411                 theView.frame = detailRect;
   404 				theView.frame = detailRect;
   412                 if (!theView.superview) {
   405 				if (!theView.superview) {
   413                     [self.view insertSubview:theView aboveSubview:self.masterViewController.view];
   406 					[self.view insertSubview:theView aboveSubview:self.masterViewController.view];
   414                 } else {
   407 				} else {
   415                     [self.view bringSubviewToFront:theView];
   408 					[self.view bringSubviewToFront:theView];
   416                 }
   409 				}
   417             }
   410 			}
   418         }
   411 		}
   419     }
   412 	}
   420 
   413 	
   421     // Create corner views if necessary.
   414 	// Create corner views if necessary.
   422     MGSplitCornersView *leadingCorners; // top/left of screen in vertical/horizontal split.
   415 	MGSplitCornersView *leadingCorners = nil; // top/left of screen in vertical/horizontal split.
   423     MGSplitCornersView *trailingCorners; // bottom/right of screen in vertical/horizontal split.
   416 	MGSplitCornersView *trailingCorners = nil; // bottom/right of screen in vertical/horizontal split.
   424     if (!_cornerViews) {
   417 	if (!_cornerViews) {
   425         CGRect cornerRect = CGRectMake(0, 0, 10, 10); // arbitrary, will be resized below.
   418 		CGRect cornerRect = CGRectMake(0, 0, 10, 10); // arbitrary, will be resized below.
   426         leadingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect];
   419 		leadingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect];
   427         leadingCorners.splitViewController = self;
   420 		leadingCorners.splitViewController = self;
   428         leadingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR;
   421 		leadingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR;
   429         leadingCorners.cornerRadius = MG_DEFAULT_CORNER_RADIUS;
   422 		leadingCorners.cornerRadius = NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0 ? 0 : MG_DEFAULT_CORNER_RADIUS;
   430         trailingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect];
   423 		trailingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect];
   431         trailingCorners.splitViewController = self;
   424 		trailingCorners.splitViewController = self;
   432         trailingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR;
   425 		trailingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR;
   433         trailingCorners.cornerRadius = MG_DEFAULT_CORNER_RADIUS;
   426 		trailingCorners.cornerRadius = NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0 ? 0 : MG_DEFAULT_CORNER_RADIUS;
   434         _cornerViews = [[NSArray alloc] initWithObjects:leadingCorners, trailingCorners, nil];
   427 		_cornerViews = [[NSArray alloc] initWithObjects:leadingCorners, trailingCorners, nil];
   435         [leadingCorners release];
   428 		
   436         [trailingCorners release];
   429 	} else if ([_cornerViews count] == 2) {
   437 
   430 		leadingCorners = [_cornerViews objectAtIndex:0];
   438     } else if ([_cornerViews count] == 2) {
   431 		trailingCorners = [_cornerViews objectAtIndex:1];
   439         leadingCorners = [_cornerViews objectAtIndex:0];
   432 	}
   440         trailingCorners = [_cornerViews objectAtIndex:1];
   433 	
   441     }
   434 	// Configure and layout the corner-views.
   442 
   435 	leadingCorners.cornersPosition = (_vertical) ? MGCornersPositionLeadingVertical : MGCornersPositionLeadingHorizontal;
   443     // Configure and layout the corner-views.
   436 	trailingCorners.cornersPosition = (_vertical) ? MGCornersPositionTrailingVertical : MGCornersPositionTrailingHorizontal;
   444     leadingCorners.cornersPosition = (_vertical) ? MGCornersPositionLeadingVertical : MGCornersPositionLeadingHorizontal;
   437 	leadingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleBottomMargin : UIViewAutoresizingFlexibleRightMargin;
   445     trailingCorners.cornersPosition = (_vertical) ? MGCornersPositionTrailingVertical : MGCornersPositionTrailingHorizontal;
   438 	trailingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleTopMargin : UIViewAutoresizingFlexibleLeftMargin;
   446     leadingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleBottomMargin : UIViewAutoresizingFlexibleRightMargin;
   439 	
   447     trailingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleTopMargin : UIViewAutoresizingFlexibleLeftMargin;
   440 	float x, y, cornersWidth, cornersHeight;
   448 
   441 	CGRect leadingRect, trailingRect;
   449     float x, y, cornersWidth, cornersHeight;
   442 	float radius = leadingCorners.cornerRadius;
   450     CGRect leadingRect, trailingRect;
   443 	if (_vertical) { // left/right split
   451     float radius = leadingCorners.cornerRadius;
   444 		cornersWidth = (radius * 2.f) + _splitWidth;
   452     if (_vertical) { // left/right split
   445 		cornersHeight = radius;
   453         cornersWidth = (radius * 2.0) + _splitWidth;
   446 		x = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : width - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius;
   454         cornersHeight = radius;
   447 		y = 0;
   455         x = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : width - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius;
   448 		leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // top corners
   456         y = 0;
   449 		trailingRect = CGRectMake(x, (height - cornersHeight), cornersWidth, cornersHeight); // bottom corners
   457         leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // top corners
   450 		
   458         trailingRect = CGRectMake(x, (height - cornersHeight), cornersWidth, cornersHeight); // bottom corners
   451 	} else { // top/bottom split
   459 
   452 		x = 0;
   460     } else { // top/bottom split
   453 		y = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : height - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius;
   461         x = 0;
   454 		cornersWidth = radius;
   462         y = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : height - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius;
   455 		cornersHeight = (radius * 2.f) + _splitWidth;
   463         cornersWidth = radius;
   456 		leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // left corners
   464         cornersHeight = (radius * 2.0) + _splitWidth;
   457 		trailingRect = CGRectMake((width - cornersWidth), y, cornersWidth, cornersHeight); // right corners
   465         leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // left corners
   458 	}
   466         trailingRect = CGRectMake((width - cornersWidth), y, cornersWidth, cornersHeight); // right corners
   459 	
   467     }
   460 	leadingCorners.frame = leadingRect;
   468 
   461 	trailingCorners.frame = trailingRect;
   469     leadingCorners.frame = leadingRect;
   462 	
   470     trailingCorners.frame = trailingRect;
   463 	// Ensure corners are visible and frontmost.
   471 
   464 	if (!leadingCorners.superview) {
   472     // Ensure corners are visible and frontmost.
   465 		[self.view insertSubview:leadingCorners aboveSubview:self.detailViewController.view];
   473     if (!leadingCorners.superview) {
   466 		[self.view insertSubview:trailingCorners aboveSubview:self.detailViewController.view];
   474         [self.view insertSubview:leadingCorners aboveSubview:self.detailViewController.view];
   467 	} else {
   475         [self.view insertSubview:trailingCorners aboveSubview:self.detailViewController.view];
   468 		[self.view bringSubviewToFront:leadingCorners];
   476     } else {
   469 		[self.view bringSubviewToFront:trailingCorners];
   477         [self.view bringSubviewToFront:leadingCorners];
   470 	}
   478         [self.view bringSubviewToFront:trailingCorners];
       
   479     }
       
   480 }
   471 }
   481 
   472 
   482 
   473 
   483 - (void)layoutSubviewsWithAnimation:(BOOL)animate
   474 - (void)layoutSubviewsWithAnimation:(BOOL)animate
   484 {
   475 {
   485     [self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:animate];
   476 	[self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:animate];
   486 }
   477 }
   487 
   478 
   488 
   479 
   489 - (void)layoutSubviews
   480 - (void)layoutSubviews
   490 {
   481 {
   491     [self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:YES];
   482 	[self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:YES];
   492 }
   483 }
   493 
   484 
   494 
   485 
   495 - (void)viewWillAppear:(BOOL)animated
   486 - (void)viewWillAppear:(BOOL)animated
   496 {
   487 {
   497     [super viewWillAppear:animated];
   488 	[super viewWillAppear:animated];
   498 
   489 	
   499     if ([self isShowingMaster]) {
   490 	if ([self isShowingMaster]) {
   500         [self.masterViewController viewWillAppear:animated];
   491 		[self.masterViewController viewWillAppear:animated];
   501     }
   492 	}
   502     [self.detailViewController viewWillAppear:animated];
   493 	[self.detailViewController viewWillAppear:animated];
   503 
   494 	
   504     _reconfigurePopup = YES;
   495 	_reconfigurePopup = YES;
   505     [self layoutSubviews];
       
   506 }
   496 }
   507 
   497 
   508 
   498 
   509 - (void)viewDidAppear:(BOOL)animated
   499 - (void)viewDidAppear:(BOOL)animated
   510 {
   500 {
   511     [super viewDidAppear:animated];
   501 	[super viewDidAppear:animated];
   512 
   502 	
   513     if ([self isShowingMaster]) {
   503 	if ([self isShowingMaster]) {
   514         [self.masterViewController viewDidAppear:animated];
   504 		[self.masterViewController viewDidAppear:animated];
   515     }
   505 	}
   516     [self.detailViewController viewDidAppear:animated];
   506 	[self.detailViewController viewDidAppear:animated];
       
   507 	[self layoutSubviews];
   517 }
   508 }
   518 
   509 
   519 
   510 
   520 - (void)viewWillDisappear:(BOOL)animated
   511 - (void)viewWillDisappear:(BOOL)animated
   521 {
   512 {
   522     [super viewWillDisappear:animated];
   513 	[super viewWillDisappear:animated];
   523 
   514 	
   524     if ([self isShowingMaster]) {
   515 	if ([self isShowingMaster]) {
   525         [self.masterViewController viewWillDisappear:animated];
   516 		[self.masterViewController viewWillDisappear:animated];
   526     }
   517 	}
   527     [self.detailViewController viewWillDisappear:animated];
   518 	[self.detailViewController viewWillDisappear:animated];
   528 }
   519 }
   529 
   520 
   530 
   521 
   531 - (void)viewDidDisappear:(BOOL)animated
   522 - (void)viewDidDisappear:(BOOL)animated
   532 {
   523 {
   533     [super viewDidDisappear:animated];
   524 	[super viewDidDisappear:animated];
   534 
   525 	
   535     if ([self isShowingMaster]) {
   526 	if ([self isShowingMaster]) {
   536         [self.masterViewController viewDidDisappear:animated];
   527 		[self.masterViewController viewDidDisappear:animated];
   537     }
   528 	}
   538     [self.detailViewController viewDidDisappear:animated];
   529 	[self.detailViewController viewDidDisappear:animated];
   539 }
   530 }
   540 
   531 
   541 
   532 
   542 #pragma mark -
   533 #pragma mark -
   543 #pragma mark Popover handling
   534 #pragma mark Popover handling
   544 
   535 
   545 
   536 
   546 - (void)reconfigureForMasterInPopover:(BOOL)inPopover
   537 - (void)reconfigureForMasterInPopover:(BOOL)inPopover
   547 {
   538 {
   548     _reconfigurePopup = NO;
   539 	_reconfigurePopup = NO;
   549 
   540 	
   550     if ((inPopover && _hiddenPopoverController) || (!inPopover && !_hiddenPopoverController) || !self.masterViewController) {
   541 	if ((inPopover && _hiddenPopoverController) || (!inPopover && !_hiddenPopoverController) || !self.masterViewController) {
   551         // Nothing to do.
   542 		// Nothing to do.
   552         return;
   543 		return;
   553     }
   544 	}
   554 
   545 	
   555     if (inPopover && !_hiddenPopoverController && !_barButtonItem) {
   546 	if (inPopover && !_hiddenPopoverController && !_barButtonItem) {
   556         // Create and configure popover for our masterViewController.
   547 		// Create and configure popover for our masterViewController.
   557         [_hiddenPopoverController release];
   548 		_hiddenPopoverController = nil;
   558         _hiddenPopoverController = nil;
   549 		[self.masterViewController viewWillDisappear:NO];
   559         [self.masterViewController viewWillDisappear:NO];
   550 		_hiddenPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.masterViewController];
   560         _hiddenPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.masterViewController];
   551 		[self.masterViewController viewDidDisappear:NO];
   561         [self.masterViewController viewDidDisappear:NO];
   552 		
   562 
   553 		// Create and configure _barButtonItem.
   563         // Create and configure _barButtonItem.
   554 		_barButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Master", nil) 
   564         _barButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Master", nil)
   555 														  style:UIBarButtonItemStyleBordered 
   565                                                           style:UIBarButtonItemStyleBordered
   556 														 target:self 
   566                                                          target:self
   557 														 action:(self.togglesMasterPopover ? @selector(toggleMasterPopover:) : @selector(showMasterPopover:))];
   567                                                          action:@selector(showMasterPopover:)];
   558 		
   568 
   559 		// Inform delegate of this state of affairs.
   569         // Inform delegate of this state of affairs.
   560 		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willHideViewController:withBarButtonItem:forPopoverController:)]) {
   570         if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willHideViewController:withBarButtonItem:forPopoverController:)]) {
   561 			[(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self 
   571             [(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self
   562 																willHideViewController:self.masterViewController 
   572                                                                 willHideViewController:self.masterViewController
   563 																	 withBarButtonItem:_barButtonItem 
   573                                                                      withBarButtonItem:_barButtonItem
   564 																  forPopoverController:_hiddenPopoverController];
   574                                                                   forPopoverController:_hiddenPopoverController];
   565 		}
       
   566 		
       
   567 	} else if (!inPopover && _hiddenPopoverController && _barButtonItem) {
       
   568 		// I know this looks strange, but it fixes a bizarre issue with UIPopoverController leaving masterViewController's views in disarray.
       
   569         // It does also break stuff on iOS8, so we disable it.
       
   570         if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
       
   571             [_hiddenPopoverController presentPopoverFromRect:CGRectZero inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
   575         }
   572         }
   576 
   573 
   577     } else if (!inPopover && _hiddenPopoverController && _barButtonItem) {
   574 		// Remove master from popover and destroy popover, if it exists.
   578         // I know this looks strange, but it fixes a bizarre issue with UIPopoverController leaving masterViewController's views in disarray.
   575 		[_hiddenPopoverController dismissPopoverAnimated:NO];
   579         [_hiddenPopoverController presentPopoverFromRect:CGRectZero inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
   576 		_hiddenPopoverController = nil;
   580 
   577 		
   581         // Remove master from popover and destroy popover, if it exists.
   578 		// Inform delegate that the _barButtonItem will become invalid.
   582         [_hiddenPopoverController dismissPopoverAnimated:NO];
   579 		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willShowViewController:invalidatingBarButtonItem:)]) {
   583         [_hiddenPopoverController release];
   580 			[(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self 
   584         _hiddenPopoverController = nil;
   581 																willShowViewController:self.masterViewController 
   585 
   582 															 invalidatingBarButtonItem:_barButtonItem];
   586         // Inform delegate that the _barButtonItem will become invalid.
   583 		}
   587         if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willShowViewController:invalidatingBarButtonItem:)]) {
   584 		
   588             [(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self
   585 		// Destroy _barButtonItem.
   589                                                                 willShowViewController:self.masterViewController
   586 		_barButtonItem = nil;
   590                                                              invalidatingBarButtonItem:_barButtonItem];
   587 		
   591         }
   588 		// Move master view.
   592 
   589 		UIView *masterView = self.masterViewController.view;
   593         // Destroy _barButtonItem.
   590 		if (masterView && masterView.superview != self.view) {
   594         [_barButtonItem release];
   591 			[masterView removeFromSuperview];
   595         _barButtonItem = nil;
   592 		}
   596 
   593 	}
   597         // Move master view.
       
   598         UIView *masterView = self.masterViewController.view;
       
   599         if (masterView && masterView.superview != self.view) {
       
   600             [masterView removeFromSuperview];
       
   601         }
       
   602     }
       
   603 }
   594 }
   604 
   595 
   605 
   596 
   606 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
   597 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
   607 {
   598 {
   608     [self reconfigureForMasterInPopover:NO];
   599 	[self reconfigureForMasterInPopover:NO];
   609 }
   600 }
   610 
   601 
   611 
   602 
   612 - (void)notePopoverDismissed
   603 - (void)notePopoverDismissed
   613 {
   604 {
   614     [self popoverControllerDidDismissPopover:_hiddenPopoverController];
   605 	[self popoverControllerDidDismissPopover:_hiddenPopoverController];
   615 }
   606 }
   616 
   607 
   617 
   608 
   618 #pragma mark -
   609 #pragma mark -
   619 #pragma mark Animations
   610 #pragma mark Animations
   620 
   611 
   621 
   612 
   622 - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
   613 - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
   623 {
   614 {
   624     if (([animationID isEqualToString:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION] ||
   615 	if (([animationID isEqualToString:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION] || 
   625          [animationID isEqualToString:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER])
   616 		 [animationID isEqualToString:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER])
   626         && _cornerViews) {
   617 		&& _cornerViews) {
   627         for (UIView *corner in _cornerViews) {
   618 		for (UIView *corner in _cornerViews) {
   628             corner.hidden = NO;
   619 			corner.hidden = NO;
   629         }
   620 		}
   630         _dividerView.hidden = NO;
   621 		_dividerView.hidden = NO;
   631     }
   622 	}
   632 }
   623 }
   633 
   624 
   634 
   625 
   635 #pragma mark -
   626 #pragma mark -
   636 #pragma mark IB Actions
   627 #pragma mark IB Actions
   637 
   628 
   638 
   629 
   639 - (IBAction)toggleSplitOrientation:(id)sender
   630 - (IBAction)toggleSplitOrientation:(id)sender
   640 {
   631 {
   641     BOOL showingMaster = [self isShowingMaster];
   632 	BOOL showingMaster = [self isShowingMaster];
   642     if (showingMaster) {
   633 	if (showingMaster) {
   643         if (_cornerViews) {
   634 		if (_cornerViews) {
   644             for (UIView *corner in _cornerViews) {
   635 			for (UIView *corner in _cornerViews) {
   645                 corner.hidden = YES;
   636 				corner.hidden = YES;
   646             }
   637 			}
   647             _dividerView.hidden = YES;
   638 			_dividerView.hidden = YES;
   648         }
   639 		}
   649         [UIView beginAnimations:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION context:nil];
   640 		[UIView beginAnimations:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION context:nil];
   650         [UIView setAnimationDelegate:self];
   641 		[UIView setAnimationDelegate:self];
   651         [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
   642 		[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
   652     }
   643 	}
   653     self.vertical = (!self.vertical);
   644 	self.vertical = (!self.vertical);
   654     if (showingMaster) {
   645 	if (showingMaster) {
   655         [UIView commitAnimations];
   646 		[UIView commitAnimations];
   656     }
   647 	}
   657 }
   648 }
   658 
   649 
   659 
   650 
   660 - (IBAction)toggleMasterBeforeDetail:(id)sender
   651 - (IBAction)toggleMasterBeforeDetail:(id)sender
   661 {
   652 {
   662     BOOL showingMaster = [self isShowingMaster];
   653 	BOOL showingMaster = [self isShowingMaster];
   663     if (showingMaster) {
   654 	if (showingMaster) {
   664         if (_cornerViews) {
   655 		if (_cornerViews) {
   665             for (UIView *corner in _cornerViews) {
   656 			for (UIView *corner in _cornerViews) {
   666                 corner.hidden = YES;
   657 				corner.hidden = YES;
   667             }
   658 			}
   668             _dividerView.hidden = YES;
   659 			_dividerView.hidden = YES;
   669         }
   660 		}
   670         [UIView beginAnimations:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER context:nil];
   661 		[UIView beginAnimations:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER context:nil];
   671         [UIView setAnimationDelegate:self];
   662 		[UIView setAnimationDelegate:self];
   672         [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
   663 		[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
   673     }
   664 	}
   674     self.masterBeforeDetail = (!self.masterBeforeDetail);
   665 	self.masterBeforeDetail = (!self.masterBeforeDetail);
   675     if (showingMaster) {
   666 	if (showingMaster) {
   676         [UIView commitAnimations];
   667 		[UIView commitAnimations];
   677     }
   668 	}
   678 }
   669 }
   679 
   670 
   680 
   671 
   681 - (IBAction)toggleMasterView:(id)sender
   672 - (IBAction)toggleMasterView:(id)sender
   682 {
   673 {
   683     if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   674 	if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   684         [_hiddenPopoverController dismissPopoverAnimated:NO];
   675 		[_hiddenPopoverController dismissPopoverAnimated:NO];
   685     }
   676 	}
   686 
   677 	
   687     if (![self isShowingMaster]) {
   678 	if (![self isShowingMaster]) {
   688         // We're about to show the master view. Ensure it's in place off-screen to be animated in.
   679 		// We're about to show the master view. Ensure it's in place off-screen to be animated in.
   689         _reconfigurePopup = YES;
   680 		_reconfigurePopup = YES;
   690         [self reconfigureForMasterInPopover:NO];
   681 		[self reconfigureForMasterInPopover:NO];
   691         [self layoutSubviews];
   682 		[self layoutSubviews];
   692     }
   683 	}
   693 
   684 	
   694     // This action functions on the current primary orientation; it is independent of the other primary orientation.
   685 	// This action functions on the current primary orientation; it is independent of the other primary orientation.
   695     [UIView beginAnimations:@"toggleMaster" context:nil];
   686 	[UIView beginAnimations:@"toggleMaster" context:nil];
   696     if (self.isLandscape) {
   687 	if (self.isLandscape) {
   697         self.showsMasterInLandscape = !_showsMasterInLandscape;
   688 		self.showsMasterInLandscape = !_showsMasterInLandscape;
   698     } else {
   689 	} else {
   699         self.showsMasterInPortrait = !_showsMasterInPortrait;
   690 		self.showsMasterInPortrait = !_showsMasterInPortrait;
   700     }
   691 	}
   701     [UIView commitAnimations];
   692 	[UIView commitAnimations];
   702 }
   693 }
   703 
   694 
   704 
   695 
   705 - (IBAction)showMasterPopover:(id) sender
   696 - (void) setTogglesMasterPopover:(BOOL)flag {
   706 {
   697 
   707     if (_hiddenPopoverController && !(_hiddenPopoverController.popoverVisible)) {
   698 	togglesMasterPopover = flag;
   708         // Inform delegate.
   699 
   709         if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:popoverController:willPresentViewController:)]) {
   700 	if (!_barButtonItem)
   710             [(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self
   701 	return;
   711                                                                      popoverController:_hiddenPopoverController
   702 		
   712                                                              willPresentViewController:self.masterViewController];
   703 	_barButtonItem.action = flag ? @selector(toggleMasterPopover:) : @selector(showMasterPopover:);	
   713         }
   704 
   714 
   705 }
   715         // Show popover.
   706 
   716         [_hiddenPopoverController presentPopoverFromBarButtonItem:_barButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
   707 - (IBAction)toggleMasterPopover:(id)sender 
   717     }
   708 {
       
   709 
       
   710 	if (!_hiddenPopoverController)
       
   711 	return;
       
   712 	
       
   713 	if (_hiddenPopoverController.popoverVisible) {
       
   714 		
       
   715 		[self hideMasterPopover:sender];
       
   716 		
       
   717 	} else {
       
   718 	
       
   719 		[self showMasterPopover:sender];
       
   720 	
       
   721 	}
       
   722 
       
   723 }
       
   724 
       
   725 
       
   726 - (IBAction)showMasterPopover:(id)sender
       
   727 {
       
   728 	if (_hiddenPopoverController && !(_hiddenPopoverController.popoverVisible)) {
       
   729 		// Inform delegate.
       
   730 		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:popoverController:willPresentViewController:)]) {
       
   731 			[(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self 
       
   732 																	 popoverController:_hiddenPopoverController 
       
   733 															 willPresentViewController:self.masterViewController];
       
   734 		}
       
   735 		
       
   736 		// Show popover.
       
   737 		[_hiddenPopoverController presentPopoverFromBarButtonItem:(sender ? sender : _barButtonItem) permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
       
   738 	}
       
   739 }
       
   740 
       
   741 
       
   742 - (IBAction)hideMasterPopover:(id)sender 
       
   743 {
       
   744 
       
   745 	if(_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
       
   746 		
       
   747 		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:popoverController:willDismissViewController:)]) {
       
   748 		
       
   749 			[(NSObject <MGSplitViewControllerDelegate> *)_delegate splitViewController:self popoverController:_hiddenPopoverController willDismissViewController:self.masterViewController];
       
   750 		
       
   751 		}
       
   752 		
       
   753 		[_hiddenPopoverController dismissPopoverAnimated:YES];
       
   754 	
       
   755 	}
       
   756 
   718 }
   757 }
   719 
   758 
   720 
   759 
   721 #pragma mark -
   760 #pragma mark -
   722 #pragma mark Accessors and properties
   761 #pragma mark Accessors and properties
   723 
   762 
   724 
   763 
   725 - (id)delegate
   764 - (id)delegate
   726 {
   765 {
   727     return _delegate;
   766 	return _delegate;
   728 }
   767 }
   729 
   768 
   730 
   769 
   731 - (void)setDelegate:(id <MGSplitViewControllerDelegate>)newDelegate
   770 - (void)setDelegate:(id <MGSplitViewControllerDelegate>)newDelegate
   732 {
   771 {
   733     if (newDelegate != _delegate &&
   772 	if (newDelegate != _delegate && 
   734         (!newDelegate || [(NSObject *)newDelegate conformsToProtocol:@protocol(MGSplitViewControllerDelegate)])) {
   773 		(!newDelegate || [(NSObject *)newDelegate conformsToProtocol:@protocol(MGSplitViewControllerDelegate)])) {
   735         _delegate = newDelegate;
   774 		_delegate = newDelegate;
   736     }
   775 	}
   737 }
   776 }
   738 
   777 
   739 
   778 
   740 - (BOOL)showsMasterInPortrait
   779 - (BOOL)showsMasterInPortrait
   741 {
   780 {
   742     return _showsMasterInPortrait;
   781 	return _showsMasterInPortrait;
   743 }
   782 }
   744 
   783 
   745 
   784 
   746 - (void)setShowsMasterInPortrait:(BOOL)flag
   785 - (void)setShowsMasterInPortrait:(BOOL)flag
   747 {
   786 {
   748     if (flag != _showsMasterInPortrait) {
   787 	if (flag != _showsMasterInPortrait) {
   749         _showsMasterInPortrait = flag;
   788 		_showsMasterInPortrait = flag;
   750 
   789 		
   751         if (![self isLandscape]) { // i.e. if this will cause a visual change.
   790 		if (![self isLandscape]) { // i.e. if this will cause a visual change.
   752             if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   791 			if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   753                 [_hiddenPopoverController dismissPopoverAnimated:NO];
   792 				[_hiddenPopoverController dismissPopoverAnimated:NO];
   754             }
   793 			}
   755 
   794 			
   756             // Rearrange views.
   795 			// Rearrange views.
   757             _reconfigurePopup = YES;
   796 			_reconfigurePopup = YES;
   758             [self layoutSubviews];
   797 			[self layoutSubviews];
   759         }
   798 		}
   760     }
   799 	}
   761 }
   800 }
   762 
   801 
   763 
   802 
   764 - (BOOL)showsMasterInLandscape
   803 - (BOOL)showsMasterInLandscape
   765 {
   804 {
   766     return _showsMasterInLandscape;
   805 	return _showsMasterInLandscape;
   767 }
   806 }
   768 
   807 
   769 
   808 
   770 - (void)setShowsMasterInLandscape:(BOOL)flag
   809 - (void)setShowsMasterInLandscape:(BOOL)flag
   771 {
   810 {
   772     if (flag != _showsMasterInLandscape) {
   811 	if (flag != _showsMasterInLandscape) {
   773         _showsMasterInLandscape = flag;
   812 		_showsMasterInLandscape = flag;
   774 
   813 		
   775         if ([self isLandscape]) { // i.e. if this will cause a visual change.
   814 		if ([self isLandscape]) { // i.e. if this will cause a visual change.
   776             if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   815 			if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   777                 [_hiddenPopoverController dismissPopoverAnimated:NO];
   816 				[_hiddenPopoverController dismissPopoverAnimated:NO];
   778             }
   817 			}
   779 
   818 			
   780             // Rearrange views.
   819 			// Rearrange views.
   781             _reconfigurePopup = YES;
   820 			_reconfigurePopup = YES;
   782             [self layoutSubviews];
   821 			[self layoutSubviews];
   783         }
   822 		}
   784     }
   823 	}
   785 }
   824 }
   786 
   825 
   787 
   826 
   788 - (BOOL)isVertical
   827 - (BOOL)isVertical
   789 {
   828 {
   790     return _vertical;
   829 	return _vertical;
   791 }
   830 }
   792 
   831 
   793 
   832 
   794 - (void)setVertical:(BOOL)flag
   833 - (void)setVertical:(BOOL)flag
   795 {
   834 {
   796     if (flag != _vertical) {
   835 	if (flag != _vertical) {
   797         if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   836 		if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   798             [_hiddenPopoverController dismissPopoverAnimated:NO];
   837 			[_hiddenPopoverController dismissPopoverAnimated:NO];
   799         }
   838 		}
   800 
   839 		
   801         _vertical = flag;
   840 		_vertical = flag;
   802 
   841 		
   803         // Inform delegate.
   842 		// Inform delegate.
   804         if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willChangeSplitOrientationToVertical:)]) {
   843 		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willChangeSplitOrientationToVertical:)]) {
   805             [_delegate splitViewController:self willChangeSplitOrientationToVertical:_vertical];
   844 			[_delegate splitViewController:self willChangeSplitOrientationToVertical:_vertical];
   806         }
   845 		}
   807 
   846 		
   808         [self layoutSubviews];
   847 		[self layoutSubviews];
   809     }
   848 	}
   810 }
   849 }
   811 
   850 
   812 
   851 
   813 - (BOOL)isMasterBeforeDetail
   852 - (BOOL)isMasterBeforeDetail
   814 {
   853 {
   815     return _masterBeforeDetail;
   854 	return _masterBeforeDetail;
   816 }
   855 }
   817 
   856 
   818 
   857 
   819 - (void)setMasterBeforeDetail:(BOOL)flag
   858 - (void)setMasterBeforeDetail:(BOOL)flag
   820 {
   859 {
   821     if (flag != _masterBeforeDetail) {
   860 	if (flag != _masterBeforeDetail) {
   822         if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   861 		if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   823             [_hiddenPopoverController dismissPopoverAnimated:NO];
   862 			[_hiddenPopoverController dismissPopoverAnimated:NO];
   824         }
   863 		}
   825 
   864 		
   826         _masterBeforeDetail = flag;
   865 		_masterBeforeDetail = flag;
   827 
   866 		
   828         if ([self isShowingMaster]) {
   867 		if ([self isShowingMaster]) {
   829             [self layoutSubviews];
   868 			[self layoutSubviews];
   830         }
   869 		}
   831     }
   870 	}
   832 }
   871 }
   833 
   872 
   834 
   873 
   835 - (float)splitPosition
   874 - (float)splitPosition
   836 {
   875 {
   837     return _splitPosition;
   876 	return _splitPosition;
   838 }
   877 }
   839 
   878 
   840 
   879 
   841 - (void)setSplitPosition:(float)posn
   880 - (void)setSplitPosition:(float)posn
   842 {
   881 {
   843     // Check to see if delegate wishes to constrain the position.
   882 	// Check to see if delegate wishes to constrain the position.
   844     float newPosn = posn;
   883 	float newPosn = posn;
   845     BOOL constrained = NO;
   884 	BOOL constrained = NO;
   846     CGSize fullSize = [self splitViewSizeForOrientation:self.interfaceOrientation];
   885 	CGSize fullSize = [self splitViewSizeForOrientation:self.interfaceOrientation];
   847     if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:constrainSplitPosition:splitViewSize:)]) {
   886 	if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:constrainSplitPosition:splitViewSize:)]) {
   848         newPosn = [_delegate splitViewController:self constrainSplitPosition:newPosn splitViewSize:fullSize];
   887 		newPosn = [_delegate splitViewController:self constrainSplitPosition:newPosn splitViewSize:fullSize];
   849         constrained = YES; // implicitly trust delegate's response.
   888 		constrained = YES; // implicitly trust delegate's response.
   850 
   889 		
   851     } else {
   890 	} else {
   852         // Apply default constraints if delegate doesn't wish to participate.
   891 		// Apply default constraints if delegate doesn't wish to participate.
   853         float minPos = MG_MIN_VIEW_WIDTH;
   892 		float minPos = MG_MIN_VIEW_WIDTH;
   854         float maxPos = ((_vertical) ? fullSize.width : fullSize.height) - (MG_MIN_VIEW_WIDTH + _splitWidth);
   893 		float maxPos = (float) (((_vertical) ? fullSize.width : fullSize.height) - (MG_MIN_VIEW_WIDTH + _splitWidth));
   855         constrained = (newPosn != _splitPosition && newPosn >= minPos && newPosn <= maxPos);
   894 		constrained = (newPosn != _splitPosition && newPosn >= minPos && newPosn <= maxPos);
   856     }
   895 	}
   857 
   896 	
   858     if (constrained) {
   897 	if (constrained) {
   859         if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   898 		if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
   860             [_hiddenPopoverController dismissPopoverAnimated:NO];
   899 			[_hiddenPopoverController dismissPopoverAnimated:NO];
   861         }
   900 		}
   862 
   901 		
   863         _splitPosition = newPosn;
   902 		_splitPosition = newPosn;
   864 
   903 		
   865         // Inform delegate.
   904 		// Inform delegate.
   866         if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willMoveSplitToPosition:)]) {
   905 		if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willMoveSplitToPosition:)]) {
   867             [_delegate splitViewController:self willMoveSplitToPosition:_splitPosition];
   906 			[_delegate splitViewController:self willMoveSplitToPosition:_splitPosition];
   868         }
   907 		}
   869 
   908 		
   870         if ([self isShowingMaster]) {
   909 		if ([self isShowingMaster]) {
   871             [self layoutSubviews];
   910 			[self layoutSubviews];
   872         }
   911 		}
   873     }
   912 	}
   874 }
   913 }
   875 
   914 
   876 
   915 
   877 - (void)setSplitPosition:(float)posn animated:(BOOL)animate
   916 - (void)setSplitPosition:(float)posn animated:(BOOL)animate
   878 {
   917 {
   879     BOOL shouldAnimate = (animate && [self isShowingMaster]);
   918 	BOOL shouldAnimate = (animate && [self isShowingMaster]);
   880     if (shouldAnimate) {
   919 	if (shouldAnimate) {
   881         [UIView beginAnimations:@"SplitPosition" context:nil];
   920 		[UIView beginAnimations:@"SplitPosition" context:nil];
   882     }
   921 	}
   883     [self setSplitPosition:posn];
   922 	[self setSplitPosition:posn];
   884     if (shouldAnimate) {
   923 	if (shouldAnimate) {
   885         [UIView commitAnimations];
   924 		[UIView commitAnimations];
   886     }
   925 	}
   887 }
   926 }
   888 
   927 
   889 
   928 
   890 - (float)splitWidth
   929 - (float)splitWidth
   891 {
   930 {
   892     return _splitWidth;
   931 	return _splitWidth;
   893 }
   932 }
   894 
   933 
   895 
   934 
   896 - (void)setSplitWidth:(float)width
   935 - (void)setSplitWidth:(float)width
   897 {
   936 {
   898     if (width != _splitWidth && width >= 0) {
   937 	if (width != _splitWidth && width >= 0) {
   899         _splitWidth = width;
   938 		_splitWidth = width;
   900         if ([self isShowingMaster]) {
   939 		if ([self isShowingMaster]) {
   901             [self layoutSubviews];
   940 			[self layoutSubviews];
   902         }
   941 		}
   903     }
   942 	}
   904 }
   943 }
   905 
   944 
   906 
   945 
   907 - (NSArray *)viewControllers
   946 - (NSArray *)viewControllers
   908 {
   947 {
   909     return [[_viewControllers copy] autorelease];
   948 	return [_viewControllers copy];
   910 }
   949 }
   911 
   950 
   912 
   951 
   913 - (void)setViewControllers:(NSArray *)controllers
   952 - (void)setViewControllers:(NSArray *)controllers
   914 {
   953 {
   915     if (controllers != _viewControllers) {
   954 	if (controllers != _viewControllers) {
   916         for (UIViewController *controller in _viewControllers) {
   955 		for (UIViewController *controller in _viewControllers) {
   917             if ([controller isKindOfClass:[UIViewController class]]) {
   956 			if ([controller isKindOfClass:[UIViewController class]]) {
   918                 [controller.view removeFromSuperview];
   957 				[controller.view removeFromSuperview];
   919             }
   958 			}
   920         }
   959 		}
   921         [_viewControllers release];
   960 		_viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
   922         _viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
   961 		if (controllers && [controllers count] >= 2) {
   923         if (controllers && [controllers count] >= 2) {
   962 			self.masterViewController = [controllers objectAtIndex:0];
   924             self.masterViewController = [controllers objectAtIndex:0];
   963 			self.detailViewController = [controllers objectAtIndex:1];
   925             self.detailViewController = [controllers objectAtIndex:1];
   964 		} else {
   926         } else {
   965 			NSLog(@"Error: %@ requires 2 view-controllers. (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
   927             NSLog(@"Error: %@ requires 2 view-controllers. (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
   966 		}
   928         }
   967 		
   929 
   968 		[self layoutSubviews];
   930         [self layoutSubviews];
   969 	}
   931     }
       
   932 }
   970 }
   933 
   971 
   934 
   972 
   935 - (UIViewController *)masterViewController
   973 - (UIViewController *)masterViewController
   936 {
   974 {
   937     if (_viewControllers && [_viewControllers count] > 0) {
   975 	if (_viewControllers && [_viewControllers count] > 0) {
   938         NSObject *controller = [_viewControllers objectAtIndex:0];
   976 		UIViewController *controller = (UIViewController *)[_viewControllers objectAtIndex:0];
   939         if ([controller isKindOfClass:[UIViewController class]]) {
   977 		if ([controller isKindOfClass:[UIViewController class]]) {
   940             return [[controller retain] autorelease];
   978 			return controller;
   941         }
   979 		}
   942     }
   980 	}
   943 
   981 	
   944     return nil;
   982 	return nil;
   945 }
   983 }
   946 
   984 
   947 
   985 
   948 - (void)setMasterViewController:(UIViewController *)master
   986 - (void)setMasterViewController:(UIViewController *)master
   949 {
   987 {
   950     if (!_viewControllers) {
   988 	if (!_viewControllers) {
   951         _viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
   989 		_viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
   952     }
   990 	}
   953 
   991 	
   954     NSObject *newMaster = master;
   992 	NSObject *newMaster = master;
   955     if (!newMaster) {
   993 	if (!newMaster) {
   956         newMaster = [NSNull null];
   994 		newMaster = [NSNull null];
   957     }
   995 	}
   958 
   996 	
   959     BOOL changed = YES;
   997 	BOOL changed = YES;
   960     if ([_viewControllers count] > 0) {
   998 	if ([_viewControllers count] > 0) {
   961         if ([_viewControllers objectAtIndex:0] == newMaster) {
   999 		if ([_viewControllers objectAtIndex:0] == newMaster) {
   962             changed = NO;
  1000 			changed = NO;
   963         } else {
  1001 		} else {
   964             [_viewControllers replaceObjectAtIndex:0 withObject:newMaster];
  1002 			[_viewControllers replaceObjectAtIndex:0 withObject:newMaster];
   965         }
  1003 		}
   966 
  1004 		
   967     } else {
  1005 	} else {
   968         [_viewControllers addObject:newMaster];
  1006 		[_viewControllers addObject:newMaster];
   969     }
  1007 	}
   970 
  1008 	
   971     if (changed) {
  1009 	if (changed) {
   972         [self layoutSubviews];
  1010 		[self layoutSubviews];
   973     }
  1011 	}
   974 }
  1012 }
   975 
  1013 
   976 
  1014 
   977 - (UIViewController *)detailViewController
  1015 - (UIViewController *)detailViewController
   978 {
  1016 {
   979     if (_viewControllers && [_viewControllers count] > 1) {
  1017 	if (_viewControllers && [_viewControllers count] > 1) {
   980         NSObject *controller = [_viewControllers objectAtIndex:1];
  1018 		UIViewController *controller = (UIViewController *)[_viewControllers objectAtIndex:1];
   981         if ([controller isKindOfClass:[UIViewController class]]) {
  1019 		if ([controller isKindOfClass:[UIViewController class]]) {
   982             return [[controller retain] autorelease];
  1020 			return controller;
   983         }
  1021 		}
   984     }
  1022 	}
   985 
  1023 	
   986     return nil;
  1024 	return nil;
   987 }
  1025 }
   988 
  1026 
   989 
  1027 
   990 - (void)setDetailViewController:(UIViewController *)detail
  1028 - (void)setDetailViewController:(UIViewController *)detail
   991 {
  1029 {
   992     if (!_viewControllers) {
  1030 	if (!_viewControllers) {
   993         _viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
  1031 		_viewControllers = [[NSMutableArray alloc] initWithCapacity:2];
   994         [_viewControllers addObject:[NSNull null]];
  1032 		[_viewControllers addObject:[NSNull null]];
   995     }
  1033 	}
   996 
  1034 	
   997     BOOL changed = YES;
  1035 	BOOL changed = YES;
   998     if ([_viewControllers count] > 1) {
  1036 	if ([_viewControllers count] > 1) {
   999         if ([_viewControllers objectAtIndex:1] == detail) {
  1037 		if ([_viewControllers objectAtIndex:1] == detail) {
  1000             changed = NO;
  1038 			changed = NO;
  1001         } else {
  1039 		} else {
  1002             [_viewControllers replaceObjectAtIndex:1 withObject:detail];
  1040 			[_viewControllers replaceObjectAtIndex:1 withObject:detail];
  1003         }
  1041 		}
  1004 
  1042 		
  1005     } else {
  1043 	} else {
  1006         [_viewControllers addObject:detail];
  1044 		[_viewControllers addObject:detail];
  1007     }
  1045 	}
  1008 
  1046 	
  1009     if (changed) {
  1047 	if (changed) {
  1010         [self layoutSubviews];
  1048 		[self layoutSubviews];
  1011     }
  1049 	}
  1012 }
  1050 }
  1013 
  1051 
  1014 
  1052 
  1015 - (MGSplitDividerView *)dividerView
  1053 - (MGSplitDividerView *)dividerView
  1016 {
  1054 {
  1017     return [[_dividerView retain] autorelease];
  1055 	return _dividerView;
  1018 }
  1056 }
  1019 
  1057 
  1020 
  1058 
  1021 - (void)setDividerView:(MGSplitDividerView *)divider
  1059 - (void)setDividerView:(MGSplitDividerView *)divider
  1022 {
  1060 {
  1023     if (divider != _dividerView) {
  1061 	if (divider != _dividerView) {
  1024         [_dividerView removeFromSuperview];
  1062 		[_dividerView removeFromSuperview];
  1025         [_dividerView release];
  1063 		_dividerView = divider;
  1026         _dividerView = [divider retain];
  1064 		_dividerView.splitViewController = self;
  1027         _dividerView.splitViewController = self;
  1065 		_dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR;
  1028         _dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR;
  1066 		if ([self isShowingMaster]) {
  1029         if ([self isShowingMaster]) {
  1067 			[self layoutSubviews];
  1030             [self layoutSubviews];
  1068 		}
  1031         }
  1069 	}
  1032     }
       
  1033 }
  1070 }
  1034 
  1071 
  1035 
  1072 
  1036 - (BOOL)allowsDraggingDivider
  1073 - (BOOL)allowsDraggingDivider
  1037 {
  1074 {
  1038     if (_dividerView) {
  1075 	if (_dividerView) {
  1039         return _dividerView.allowsDragging;
  1076 		return _dividerView.allowsDragging;
  1040     }
  1077 	}
  1041 
  1078 	
  1042     return NO;
  1079 	return NO;
  1043 }
  1080 }
  1044 
  1081 
  1045 
  1082 
  1046 - (void)setAllowsDraggingDivider:(BOOL)flag
  1083 - (void)setAllowsDraggingDivider:(BOOL)flag
  1047 {
  1084 {
  1048     if (self.allowsDraggingDivider != flag && _dividerView) {
  1085 	if (self.allowsDraggingDivider != flag && _dividerView) {
  1049         _dividerView.allowsDragging = flag;
  1086 		_dividerView.allowsDragging = flag;
  1050     }
  1087 	}
  1051 }
  1088 }
  1052 
  1089 
  1053 
  1090 
  1054 - (MGSplitViewDividerStyle)dividerStyle
  1091 - (MGSplitViewDividerStyle)dividerStyle
  1055 {
  1092 {
  1056     return _dividerStyle;
  1093 	return _dividerStyle;
  1057 }
  1094 }
  1058 
  1095 
  1059 
  1096 
  1060 - (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle
  1097 - (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle
  1061 {
  1098 {
  1062     if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
  1099 	if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
  1063         [_hiddenPopoverController dismissPopoverAnimated:NO];
  1100 		[_hiddenPopoverController dismissPopoverAnimated:NO];
  1064     }
  1101 	}
  1065 
  1102 	
  1066     // We don't check to see if newStyle equals _dividerStyle, because it's a meta-setting.
  1103 	// We don't check to see if newStyle equals _dividerStyle, because it's a meta-setting.
  1067     // Aspects could have been changed since it was set.
  1104 	// Aspects could have been changed since it was set.
  1068     _dividerStyle = newStyle;
  1105 	_dividerStyle = newStyle;
  1069 
  1106 	
  1070     // Reconfigure general appearance and behaviour.
  1107 	// Reconfigure general appearance and behaviour.
  1071     float cornerRadius;
  1108 	float cornerRadius = 0.0f;
  1072     if (_dividerStyle == MGSplitViewDividerStyleThin) {
  1109 	if (_dividerStyle == MGSplitViewDividerStyleThin) {
  1073         cornerRadius = MG_DEFAULT_CORNER_RADIUS;
  1110 		cornerRadius = NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0 ? 0 : MG_DEFAULT_CORNER_RADIUS;
  1074         _splitWidth = MG_DEFAULT_SPLIT_WIDTH;
  1111 		_splitWidth = MG_DEFAULT_SPLIT_WIDTH;
  1075         self.allowsDraggingDivider = NO;
  1112 		self.allowsDraggingDivider = NO;
  1076 
  1113 		
  1077     } else if (_dividerStyle == MGSplitViewDividerStylePaneSplitter) {
  1114 	} else if (_dividerStyle == MGSplitViewDividerStylePaneSplitter) {
  1078         cornerRadius = MG_PANESPLITTER_CORNER_RADIUS;
  1115 		cornerRadius = MG_PANESPLITTER_CORNER_RADIUS;
  1079         _splitWidth = MG_PANESPLITTER_SPLIT_WIDTH;
  1116 		_splitWidth = MG_PANESPLITTER_SPLIT_WIDTH;
  1080         self.allowsDraggingDivider = YES;
  1117 		self.allowsDraggingDivider = YES;
  1081     }
  1118 	}
  1082 
  1119 	
  1083     // Update divider and corners.
  1120 	// Update divider and corners.
  1084     [_dividerView setNeedsDisplay];
  1121 	[_dividerView setNeedsDisplay];
  1085     if (_cornerViews) {
  1122 	if (_cornerViews) {
  1086         for (MGSplitCornersView *corner in _cornerViews) {
  1123 		for (MGSplitCornersView *corner in _cornerViews) {
  1087             corner.cornerRadius = cornerRadius;
  1124 			corner.cornerRadius = cornerRadius;
  1088         }
  1125 		}
  1089     }
  1126 	}
  1090 
  1127 	
  1091     // Layout all views.
  1128 	// Layout all views.
  1092     [self layoutSubviews];
  1129 	[self layoutSubviews];
  1093 }
  1130 }
  1094 
  1131 
  1095 
  1132 
  1096 - (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle animated:(BOOL)animate
  1133 - (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle animated:(BOOL)animate
  1097 {
  1134 {
  1098     BOOL shouldAnimate = (animate && [self isShowingMaster]);
  1135 	BOOL shouldAnimate = (animate && [self isShowingMaster]);
  1099     if (shouldAnimate) {
  1136 	if (shouldAnimate) {
  1100         [UIView beginAnimations:@"DividerStyle" context:nil];
  1137 		[UIView beginAnimations:@"DividerStyle" context:nil];
  1101     }
  1138 	}
  1102     [self setDividerStyle:newStyle];
  1139 	[self setDividerStyle:newStyle];
  1103     if (shouldAnimate) {
  1140 	if (shouldAnimate) {
  1104         [UIView commitAnimations];
  1141 		[UIView commitAnimations];
  1105     }
  1142 	}
  1106 }
  1143 }
  1107 
  1144 
  1108 
  1145 
  1109 - (NSArray *)cornerViews
  1146 - (NSArray *)cornerViews
  1110 {
  1147 {
  1111     if (_cornerViews) {
  1148 	if (_cornerViews) {
  1112         return [[_cornerViews retain] autorelease];
  1149 		return _cornerViews;
  1113     }
  1150 	}
  1114 
  1151 	
  1115     return nil;
  1152 	return nil;
  1116 }
  1153 }
  1117 
  1154 
  1118 
  1155 
  1119 @synthesize showsMasterInPortrait;
  1156 @synthesize showsMasterInPortrait;
  1120 @synthesize showsMasterInLandscape;
  1157 @synthesize showsMasterInLandscape;
  1121 @synthesize vertical;
  1158 @synthesize vertical;
  1122 @synthesize delegate;
  1159 @synthesize delegate;
  1123 @synthesize viewControllers;
  1160 @synthesize viewControllers = _viewControllers;
  1124 @synthesize masterViewController;
  1161 @synthesize masterViewController;
  1125 @synthesize detailViewController;
  1162 @synthesize detailViewController;
  1126 @synthesize dividerView;
  1163 @synthesize dividerView = _dividerView;
  1127 @synthesize splitPosition;
  1164 @synthesize splitPosition;
  1128 @synthesize splitWidth;
  1165 @synthesize splitWidth;
  1129 @synthesize allowsDraggingDivider;
  1166 @synthesize allowsDraggingDivider;
  1130 @synthesize dividerStyle;
  1167 @synthesize dividerStyle;
  1131 
  1168 
       
  1169 @synthesize togglesMasterPopover;
  1132 
  1170 
  1133 @end
  1171 @end