This repository has been archived by the owner on Jun 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 50
/
PSBaseTreeGraphView.h
289 lines (176 loc) · 10 KB
/
PSBaseTreeGraphView.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
//
// PSBaseTreeGraphView.h
// PSTreeGraphView
//
// Created by Ed Preston on 7/25/10.
// Copyright 2010 Preston Software. All rights reserved.
//
//
// This is a port of the sample code from Max OS X to iOS (iPad).
//
// WWDC 2010 Session 141, “Crafting Custom Cocoa Views”
//
#import <UIKit/UIKit.h>
/// A TreeGraph's nodes may be connected by either "direct" or "orthogonal" lines.
typedef enum PSTreeGraphConnectingLineStyle : NSUInteger {
PSTreeGraphConnectingLineStyleDirect = 0,
PSTreeGraphConnectingLineStyleOrthogonal = 1,
} PSTreeGraphConnectingLineStyle;
/// A TreeGraph's orientation may be either "horizontal" or "vertical".
typedef enum PSTreeGraphOrientationStyle : NSUInteger {
PSTreeGraphOrientationStyleHorizontal = 0,
PSTreeGraphOrientationStyleVertical = 1,
PSTreeGraphOrientationStyleHorizontalFlipped = 2,
PSTreeGraphOrientationStyleVerticalFlipped = 3,
} PSTreeGraphOrientationStyle;
@class PSBaseSubtreeView;
@protocol PSTreeGraphModelNode;
@protocol PSTreeGraphDelegate;
@interface PSBaseTreeGraphView : UIView <UIKeyInput>
#pragma mark - Delegate
@property (nonatomic, weak) id <PSTreeGraphDelegate> delegate;
#pragma mark - Parent Resize Notification
/// Use this method to keep the view in sync for now.
- (void) parentClipViewDidResize:(id)object;
#pragma mark - Creating Instances
/// Initializes a new TreeGraph instance. (TreeGraph's designated initializer is the same as
/// UIView's: -initWithFrame:.) The TreeGraph has default appearance properties and layout
/// metrics, but to have a usable TreeGraph with actual content, you need to specify a
/// nodeViewNibName and a modelRoot.
- (id) initWithFrame:(CGRect)frame;
#pragma mark - Connection to Model
/// The root of the model node tree that the TreeGraph is being asked to display. (The modelRoot
/// may have ancestor nodes, but TreeGraph will ignore them and treat modelRoot as the root.) May
/// be set to nil, in which case the TreeGraph displays no content. The modelRoot object, and all
/// of its desdendants as exposed through recursive application of the "-childModelNodes" accessor
/// to traverse the model tree, must conform to the TreeGraphModelNode protocol declared in
/// TreeGraphModelNode.h
@property (nonatomic, strong) id <PSTreeGraphModelNode> modelRoot;
#pragma mark - Root SubtreeView Access
/// A TreeGraph builds the tree it displays using recursively nested SubtreeView instances. This
/// read-only accessor provides a way to get the rootmost SubtreeView (the one that corresponds
/// to the modelRoot model node).
@property (nonatomic, readonly) PSBaseSubtreeView *rootSubtreeView;
#pragma mark - Node View Nib Specification
/// The name of the .nib file from which to instantiate node views. (This API design assumes that
/// all node views should be instantiated from the same .nib. If a tree of heterogeneous nodes
/// was desired, we could switch to a different mechanism for identifying the .nib to instantiate.)
/// Must specify a "View" .nib file, whose File's Owner is a SubtreeView, or the TreeGraph will be
/// unable to instantiate node views.
@property (nonatomic, copy) NSString *nodeViewNibName;
#pragma mark - Selection State
/// The unordered set of model nodes that are currently selected in the TreeGraph. When no nodes
/// are selected, this is an empty NSSet. It will never be nil (and attempting to set it to nil
/// will raise an exception). Every member of this set must be a descendant of the TreeGraph's
/// modelRoot (or modelRoot itself). If any member is not, TreeGraph will raise an exception.
@property (nonatomic, copy) NSSet *selectedModelNodes;
/// Convenience accessor that returns the selected node, if exactly one node is currently
/// selected. Returns nil if zero, or more than one, nodes are currently selected.
@property (nonatomic, readonly) id <PSTreeGraphModelNode> singleSelectedModelNode;
/// Returns the bounding box of the selectedModelNodes. The bounding box takes only the selected
/// nodes into account, disregarding any descendants they might have.
@property (nonatomic, readonly) CGRect selectionBounds;
#pragma mark - Node Hit-Testing
/// Returns the model node under the given point, which must be expressed in the TreeGraph's
/// interior (bounds) coordinate space. If there is a collapsed subtree at the given point,
/// returns the model node at the root of the collapsed subtree. If there is no model node
/// at the given point, returns nil.
- (id <PSTreeGraphModelNode> ) modelNodeAtPoint:(CGPoint)p;
#pragma mark - Sizing and Layout
/// A TreeGraph's minimumFrameSize is the size needed to accommodate its content (as currently
/// laid out) and margins. Changes to the TreeGraph's content, layout, or margins will update
/// this. When a TreeGraph is the documentView of an UIScrollView, its actual frame may be larger
/// than its minimumFrameSize, since we automatically expand the TreeGraph to always be at least
/// as large as the UIScrollView's clip area (contentView) to provide a nicer user experience.
@property (nonatomic, assign) CGSize minimumFrameSize;
/// If YES, and if the TreeGraph is the documentView of an UIScrollView, the TreeGraph will
/// automatically resize itself as needed to ensure that it always at least fills the content
/// area of its enclosing UIScrollView. If NO, or if the TreeGraph is not the documentView of
/// an UIScrollView, the TreeGraph's size is determined only by its content and margins.
@property (nonatomic, assign) BOOL resizesToFillEnclosingScrollView;
/// The style for tree graph orientation
/// @note See the TreeGraphOrientationStyle enumeration.
@property (nonatomic, assign) PSTreeGraphOrientationStyle treeGraphOrientation;
/// Is the TreeGraph flipped
/// Flipped means the graph is drawn with the branches to the left or top and the root node
/// to the right or bottom. Default is NO
@property (nonatomic, assign) BOOL treeGraphFlipped;
/// Returns YES if the tree needs relayout.
- (BOOL) needsGraphLayout;
/// Marks the tree as needing relayout.
- (void) setNeedsGraphLayout;
/// Performs graph layout, if the tree is marked as needing it. Returns the size computed for the
/// tree (not including contentMargin).
- (CGSize) layoutGraphIfNeeded;
/// Collapses the root node, if it is currently expanded.
- (void) collapseRoot;
/// Expands the root node, if it is currently collapsed.
- (void) expandRoot;
/// Toggles the expansion state of the TreeGraph's selectedModelNodes, expanding those that are
/// currently collapsed, and collapsing those that are currently expanded.
- (IBAction) toggleExpansionOfSelectedModelNodes:(id)sender;
/// Returns the bounding box of the node views that represent the specified modelNodes. Model
/// nodes that aren't part of the displayed tree, or are part of a collapsed subtree, are ignored
/// and don't contribute to the returned bounding box. The bounding box takes only the specified
/// nodes into account, disregarding any descendants they might have.
- (CGRect) boundsOfModelNodes:(NSSet *)modelNodes;
#pragma mark - Scrolling
/// Does a [self scrollRectToVisible:] with the bounding box of the specified model nodes.
- (void) scrollModelNodesToVisible:(NSSet *)modelNodes animated:(BOOL)animated;
/// Does a [self scrollRectToVisible:] with the bounding box of the selected model nodes.
- (void) scrollSelectedModelNodesToVisibleAnimated:(BOOL)animated;
#pragma mark - Animation Support
/// Whether the TreeGraph animates layout operations. Defaults to YES. If set to NO, layout
/// jumpst instantaneously to the tree's new state.
@property (nonatomic, assign) BOOL animatesLayout;
/// Used to temporarily suppress layout animation during event tracking. Layout animation happens
/// only if animatesLayout is YES and this is NO.
@property (nonatomic, assign) BOOL layoutAnimationSuppressed;
#pragma mark - Layout Metrics
/// The amount of padding to leave between the displayed tree and each of the
/// four edges of the TreeGraph's bounds.
@property (nonatomic, assign) CGFloat contentMargin;
/// The horizonal spacing between each parent node and its child nodes.
@property (nonatomic, assign) CGFloat parentChildSpacing;
/// The vertical spacing betwen sibling nodes.
@property (nonatomic, assign) CGFloat siblingSpacing;
#pragma mark - Styling
// The fill color for the TreeGraph's content area.
// @property(copy) UIColor *backgroundColor;
/// The stroke color for node connecting lines.
@property (nonatomic, retain) UIColor *connectingLineColor;
/// The width for node connecting lines.
@property (nonatomic, assign) CGFloat connectingLineWidth;
/// The style for node connecting lines.
/// @note See the PSTreeGraphConnectingLineStyle enumeration.
@property (nonatomic, assign) PSTreeGraphConnectingLineStyle connectingLineStyle;
/// Defaults to NO. If YES, a stroked outline is shown around each of the TreeGraph's
/// SubtreeViews. This can be helpful for visualizing the TreeGraph's structure and layout.
@property (nonatomic, assign) BOOL showsSubtreeFrames;
#pragma mark - Input and Navigation
/// Custom input view for navigation.
///
/// By default, this control supports a hardware keyboard unless this property is assigned
/// to another input view.
///
/// More Info:
///
/// A placeholder view is created to so the default keyboard is not presented to the user.
/// When a hardware keyboard is attached, touching the TreeGraph makes it first responder
/// and certain keyboard shortcuts become available for navigation. ie. the space bar
/// expands and collapses the current selection. The following keys; w, a, s, d, navigate
/// relative to the graph.
///
/// Custom navigation can be added by assigning a custom UIView to inputView, and linking
/// it up to some of the actions below.
@property (nonatomic, retain) IBOutlet UIView *inputView;
// Model relative navigation
- (void) moveToSiblingByRelativeIndex:(NSInteger)relativeIndex;
- (IBAction) moveToParent:(id)sender;
- (IBAction) moveToNearestChild:(id)sender;
// Graph relative navigation
- (IBAction) moveUp:(id)sender;
- (IBAction) moveDown:(id)sender;
- (IBAction) moveLeft:(id)sender;
- (IBAction) moveRight:(id)sender;
@end