-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSSYSidebarController.h
144 lines (115 loc) · 6.21 KB
/
SSYSidebarController.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#import <AppKit/AppKit.h>
enum SSYSidebarControllerWhichEdge_enum {
SSYSidebarControllerWhichEdgeRight,
SSYSidebarControllerWhichEdgeLeft,
SSYSidebarControllerWhichEdgeBottom,
SSYSidebarControllerWhichEdgeTop
};
typedef enum SSYSidebarControllerWhichEdge_enum SSYSidebarControllerWhichEdge;
/*!
@brief SSYSidebarController toggles a *sidebar view* in a window between
completely collapsed and comletely expanded states, simultaneously adjusting,
as appropriate, the size and/or position of a sibling adjacent *main* view
and the window in which both views reside
@details
## Auto Layout
SSYSidebarController does not use Auto Layout. I have not thought much about
whether or not you could, for instance, use Auto Layout in the main and
sidebar views. The use case I had for writing SSYSidebarController were
to replace NSDrawer instances in a old pre Auto-Layout project.
## View Size Variability
Each time the sidebar is expanded, you may specify a minimum length (height
or width, depending on `whichEdge`) for the main view. If this is less than
its current length, SSYSidebarView will partially collapse the main view, down
to that minimum, before expanding the window.
The sidebar length (height or width, depending on `whichEdge`) is fixed during
-awakeFromNib. Attempting to change it may cause unexpected results. Its
other dimention (width or height) may be changed.
## Window Edges
The "sidebar" view can appear on any of the four window edges; in
other words it can also be a *topbar* or *bottombar*. But we call it a
*sidebar* in all cases. Think *side information* or *side controls*. You may
theoretically put sidebars on all four edges of a window, although I've only
tested one and two.
## Usage
Note that, unlike NSSplitViewController, SSYSidebarController does not inherit
from NSViewController. It actually controls not one view but two – the *main*
and the *sidebar* views. Typically, you instantiate one SSYSidebarController
in a xib or storyboard that contains the window, main view and sidebar view,
and the latter two should be connected to SSYSidebarController's outlets.
It is recommended to place the main view and sidebar view as siblings in a
window's content view, abutting one another and filling the content view in
the same way as they would when the sidebar is expanded. Nonetheless, your
window will initially appear with the sidebar collapsed, because
SSYSidebarController collapses it during its -awakeFromNib.
You may also instantiate SSYSidebarController in code.
## Relation to NSDrawer and NSSplitView
Since 2012 or so, NSDrawer has been dis-recommended by Apple. When
a window with a NSDrawer loads, a bunch of crap is logged to the Xcode
console, and also, sometimes, drawer content does not load. One solution is
to replace NSDrawer with NSSplitView and NSSplitViewController, but those
two are quite complicated to use, buggy. If you have obvious buttons in
your user interface for opening and closing the drawer, maybe you don't need
the draggable devider bar. In that case, you can simply put your drawer
contents in a sibling subview to the window's main view and instantiate a
SSYSidebarController in your window controller.
## Troubleshooting
If your views are not sizing as expected, think about their autoresize masks
("springs and struts" in Interface Builder), and those of their subviews.
*/
IB_DESIGNABLE
@interface SSYSidebarController : NSObject
@property (assign) IBOutlet NSView* mainView;
@property (assign) IBOutlet NSView* sidebarView;
/*!
@brief The length of the variable-length perimeter segment (width or
height) of the receiver's sidebar view, grabbed during -awakeFromNib, before
it is collapsed to 0.0.
@details You may need this for layout calculations, because the order in
which Cocoa sends -awakeFromNib to objects in a nib is indeterminate.
*/
@property (assign, readonly) CGFloat sidebarLength;
/*!
@details The values of this property must be one of the values of the enum
SSYSidebarControllerWhichEdge. Unfortunately, as of Xcode 8.2, Interface
Builder does not know how to show a control for enum types, and thus will not
show a control for an enum typed property in the Attributes Inspector. To
work around this limitation so that a control shows in Interface Builder, we
type this property as NSInteger. Sigh.
*/
@property (assign) IBInspectable NSInteger whichEdge;
/*!
@brief Initializes a SSYSidebarController instance and collapses the given
sidebar view so that only the given main view is visible
@details Typically, you instantiate SSYSidebarController in Interface Builder
and will not use this method. If instead you instantiate SSYSidebarController
in code, you will call this method, possibly from your in your window
controller's -awakeFromNib implementation.
@param mainView The main part of the window, which should be visible when
the window initially opens
@param sidebarView The auxiliary, aka "sidebar" or "drawer" view, which is
initially collapsed.
*/
- (instancetype)initWithMainView:(NSView*)mainView
sidebarView:(NSView*)sidebarView
whichEdge:(SSYSidebarControllerWhichEdge)whichEdge;
/*!
@brief Expands or collapses the sidebar view of the receiver
@details When expanding, borrows length from the main view as available and,
if that is not enough, makes the window bigger, and if would cause the window
to overflow the screen, moves the window enough in the opposite direction to
prevent that overflow. When collapsing, restores to the main view whatever
length was borrowed in the previous expanding. Does nothing if expandPort
is passed YES when the sidebar is already expanded, or NO when the sidebar is
already collapsed.
@param expandSidebar YES to expand the sidebar, NO to collapse
@param mainViewMinimum When expanding, the minimum length (width or
height) in the direction of the expanding, to which the main view may view
may be collapsed to accomodate the expansion of the sidebar view. Ignored
when collapsing.
@param animate YES to animate the expanding or collapsing
*/
- (void)expandSidebar:(BOOL)expand
mainViewMinimum:(CGFloat)mainViewMinimum
animate:(BOOL)animate ;
@end