|
1 // |
|
2 // MGSplitViewController.h |
|
3 // MGSplitView |
|
4 // |
|
5 // Created by Matt Gemmell on 26/07/2010. |
|
6 // Copyright 2010 Instinctive Code. |
|
7 // |
|
8 |
|
9 #import <UIKit/UIKit.h> |
|
10 |
|
11 typedef enum _MGSplitViewDividerStyle { |
|
12 // These names have been chosen to be conceptually similar to those of NSSplitView on Mac OS X. |
|
13 MGSplitViewDividerStyleThin = 0, // Thin divider, like UISplitViewController (default). |
|
14 MGSplitViewDividerStylePaneSplitter = 1 // Thick divider, drawn with a grey gradient and a grab-strip. |
|
15 } MGSplitViewDividerStyle; |
|
16 |
|
17 @class MGSplitDividerView; |
|
18 @protocol MGSplitViewControllerDelegate; |
|
19 @interface MGSplitViewController : UIViewController <UIPopoverControllerDelegate> { |
|
20 BOOL _showsMasterInPortrait; |
|
21 BOOL _showsMasterInLandscape; |
|
22 float _splitWidth; |
|
23 id _delegate; |
|
24 BOOL _vertical; |
|
25 BOOL _masterBeforeDetail; |
|
26 NSMutableArray *_viewControllers; |
|
27 UIBarButtonItem *_barButtonItem; // To be compliant with wacky UISplitViewController behaviour. |
|
28 UIPopoverController *_hiddenPopoverController; // Popover used to hold the master view if it's not always visible. |
|
29 MGSplitDividerView *_dividerView; // View that draws the divider between the master and detail views. |
|
30 NSArray *_cornerViews; // Views to draw the inner rounded corners between master and detail views. |
|
31 float _splitPosition; |
|
32 BOOL _reconfigurePopup; |
|
33 MGSplitViewDividerStyle _dividerStyle; // Meta-setting which configures several aspects of appearance and behaviour. |
|
34 } |
|
35 |
|
36 @property (nonatomic, assign) IBOutlet id <MGSplitViewControllerDelegate> delegate; |
|
37 @property (nonatomic, assign) BOOL showsMasterInPortrait; // applies to both portrait orientations (default NO) |
|
38 @property (nonatomic, assign) BOOL showsMasterInLandscape; // applies to both landscape orientations (default YES) |
|
39 @property (nonatomic, assign, getter=isVertical) BOOL vertical; // if NO, split is horizontal, i.e. master above detail (default YES) |
|
40 @property (nonatomic, assign, getter=isMasterBeforeDetail) BOOL masterBeforeDetail; // if NO, master view is below/right of detail (default YES) |
|
41 @property (nonatomic, assign) float splitPosition; // starting position of split in pixels, relative to top/left (depending on .isVertical setting) if masterBeforeDetail is YES, else relative to bottom/right. |
|
42 @property (nonatomic, assign) float splitWidth; // width of split in pixels. |
|
43 @property (nonatomic, assign) BOOL allowsDraggingDivider; // whether to let the user drag the divider to alter the split position (default NO). |
|
44 |
|
45 @property (nonatomic, copy) NSArray *viewControllers; // array of UIViewControllers; master is at index 0, detail is at index 1. |
|
46 @property (nonatomic, retain) IBOutlet UIViewController *masterViewController; // convenience. |
|
47 @property (nonatomic, retain) IBOutlet UIViewController *detailViewController; // convenience. |
|
48 @property (nonatomic, retain) MGSplitDividerView *dividerView; // the view which draws the divider/split between master and detail. |
|
49 @property (nonatomic, assign) MGSplitViewDividerStyle dividerStyle; // style (and behaviour) of the divider between master and detail. |
|
50 |
|
51 @property (nonatomic, readonly, getter=isLandscape) BOOL landscape; // returns YES if this view controller is in either of the two Landscape orientations, else NO. |
|
52 |
|
53 // Actions |
|
54 - (IBAction)toggleSplitOrientation:(id)sender; // toggles split axis between vertical (left/right; default) and horizontal (top/bottom). |
|
55 - (IBAction)toggleMasterBeforeDetail:(id)sender; // toggles position of master view relative to detail view. |
|
56 - (IBAction)toggleMasterView:(id)sender; // toggles display of the master view in the current orientation. |
|
57 - (IBAction)showMasterPopover:(id)sender; // shows the master view in a popover spawned from the provided barButtonItem, if it's currently hidden. |
|
58 - (void)notePopoverDismissed; // should rarely be needed, because you should not change the popover's delegate. If you must, then call this when it's dismissed. |
|
59 |
|
60 // Conveniences for you, because I care. |
|
61 - (BOOL)isShowingMaster; |
|
62 - (void)setSplitPosition:(float)posn animated:(BOOL)animate; // Allows for animation of splitPosition changes. The property's regular setter is not animated. |
|
63 /* Note: splitPosition is the width (in a left/right split, or height in a top/bottom split) of the master view. |
|
64 It is relative to the appropriate side of the splitView, which can be any of the four sides depending on the values in isMasterBeforeDetail and isVertical: |
|
65 isVertical = YES, isMasterBeforeDetail = YES: splitPosition is relative to the LEFT edge. (Default) |
|
66 isVertical = YES, isMasterBeforeDetail = NO: splitPosition is relative to the RIGHT edge. |
|
67 isVertical = NO, isMasterBeforeDetail = YES: splitPosition is relative to the TOP edge. |
|
68 isVertical = NO, isMasterBeforeDetail = NO: splitPosition is relative to the BOTTOM edge. |
|
69 |
|
70 This implementation was chosen so you don't need to recalculate equivalent splitPositions if the user toggles masterBeforeDetail themselves. |
|
71 */ |
|
72 - (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle animated:(BOOL)animate; // Allows for animation of dividerStyle changes. The property's regular setter is not animated. |
|
73 - (NSArray *)cornerViews; |
|
74 /* |
|
75 -cornerViews returns an NSArray of two MGSplitCornersView objects, used to draw the inner corners. |
|
76 The first view is the "leading" corners (top edge of screen for left/right split, left edge of screen for top/bottom split). |
|
77 The second view is the "trailing" corners (bottom edge of screen for left/right split, right edge of screen for top/bottom split). |
|
78 Do NOT modify them, except to: |
|
79 1. Change their .cornerBackgroundColor |
|
80 2. Change their .cornerRadius |
|
81 */ |
|
82 |
|
83 @end |
|
84 |
|
85 |
|
86 @protocol MGSplitViewControllerDelegate |
|
87 |
|
88 @optional |
|
89 |
|
90 // Called when a button should be added to a toolbar for a hidden view controller. |
|
91 - (void)splitViewController:(MGSplitViewController*)svc |
|
92 willHideViewController:(UIViewController *)aViewController |
|
93 withBarButtonItem:(UIBarButtonItem*)barButtonItem |
|
94 forPopoverController: (UIPopoverController*)pc; |
|
95 |
|
96 // Called when the master view is shown again in the split view, invalidating the button and popover controller. |
|
97 - (void)splitViewController:(MGSplitViewController*)svc |
|
98 willShowViewController:(UIViewController *)aViewController |
|
99 invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem; |
|
100 |
|
101 // Called when the master view is shown in a popover, so the delegate can take action like hiding other popovers. |
|
102 - (void)splitViewController:(MGSplitViewController*)svc |
|
103 popoverController:(UIPopoverController*)pc |
|
104 willPresentViewController:(UIViewController *)aViewController; |
|
105 |
|
106 // Called when the split orientation will change (from vertical to horizontal, or vice versa). |
|
107 - (void)splitViewController:(MGSplitViewController*)svc willChangeSplitOrientationToVertical:(BOOL)isVertical; |
|
108 |
|
109 // Called when split position will change to the given pixel value (relative to left if split is vertical, or to top if horizontal). |
|
110 - (void)splitViewController:(MGSplitViewController*)svc willMoveSplitToPosition:(float)position; |
|
111 |
|
112 // Called before split position is changed to the given pixel value (relative to left if split is vertical, or to top if horizontal). |
|
113 // Note that viewSize is the current size of the entire split-view; i.e. the area enclosing the master, divider and detail views. |
|
114 - (float)splitViewController:(MGSplitViewController *)svc constrainSplitPosition:(float)proposedPosition splitViewSize:(CGSize)viewSize; |
|
115 |
|
116 @end |