RATreeView.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. //The MIT License (MIT)
  2. //
  3. //Copyright (c) 2013 Rafał Augustyniak
  4. //
  5. //Permission is hereby granted, free of charge, to any person obtaining a copy of
  6. //this software and associated documentation files (the "Software"), to deal in
  7. //the Software without restriction, including without limitation the rights to
  8. //use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  9. //the Software, and to permit persons to whom the Software is furnished to do so,
  10. //subject to the following conditions:
  11. //
  12. //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  14. //FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  15. //COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  16. //IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  17. //CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  18. //
  19. #import "RATreeView.h"
  20. #import "RATreeView+Enums.h"
  21. #import "RATreeView+Private.h"
  22. #import "RATreeView+UIScrollView.h"
  23. #import "RATreeNodeCollectionController.h"
  24. #import "RATreeNode.h"
  25. @interface RATreeView ()
  26. @property (strong, nonatomic) UITableView *tableView;
  27. @property (strong, nonatomic) RATreeNodeCollectionController *treeNodeCollectionController;
  28. @end
  29. @implementation RATreeView
  30. //Managing the Display of Content
  31. @dynamic contentOffset;
  32. @dynamic contentSize;
  33. @dynamic contentInset;
  34. //Managing Scrolling
  35. @dynamic scrollEnabled;
  36. @dynamic directionalLockEnabled;
  37. @dynamic scrollsToTop;
  38. @dynamic pagingEnabled;
  39. @dynamic bounces;
  40. @dynamic alwaysBounceVertical;
  41. @dynamic alwaysBounceHorizontal;
  42. @dynamic canCancelContentTouches;
  43. @dynamic delaysContentTouches;
  44. @dynamic decelerationRate;
  45. @dynamic dragging;
  46. @dynamic tracking;
  47. @dynamic decelerating;
  48. //Managing the Scroll Indicator
  49. @dynamic indicatorStyle;
  50. @dynamic scrollIndicatorInsets;
  51. @dynamic showsHorizontalScrollIndicator;
  52. @dynamic showsVerticalScrollIndicator;
  53. //- (void)flashScrollIndicators;
  54. //Zooming and Panning
  55. @dynamic panGestureRecognizer;
  56. @dynamic pinchGestureRecognizer;
  57. @dynamic zoomScale;
  58. @dynamic maximumZoomScale;
  59. @dynamic minimumZoomScale;
  60. @dynamic zoomBouncing;
  61. @dynamic zooming;
  62. @dynamic bouncesZoom;
  63. #pragma mark Initializing a TreeView Object
  64. - (id)init
  65. {
  66. return [self initWithFrame:CGRectMake(0, 0, 100, 100) style:RATreeViewStylePlain];
  67. }
  68. - (id)initWithFrame:(CGRect)frame
  69. {
  70. return [self initWithFrame:frame style:RATreeViewStylePlain];
  71. }
  72. - (id)initWithFrame:(CGRect)frame style:(RATreeViewStyle)style
  73. {
  74. self = [super initWithFrame:frame];
  75. if (self) {
  76. CGRect innerFrame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
  77. [self commonInitWithFrame:innerFrame style:style];
  78. }
  79. return self;
  80. }
  81. - (id)initWithCoder:(NSCoder *)aDecoder
  82. {
  83. self = [super initWithCoder:aDecoder];
  84. if (self) {
  85. CGRect innerFrame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
  86. [self commonInitWithFrame:innerFrame style:RATreeViewStylePlain];
  87. }
  88. return self;
  89. }
  90. - (void)commonInitWithFrame:(CGRect)frame style:(RATreeViewStyle)style
  91. {
  92. UITableViewStyle tableViewStyle = [RATreeView tableViewStyleForTreeViewStyle:style];
  93. UITableView *tableView = [[UITableView alloc] initWithFrame:frame style:tableViewStyle];
  94. tableView.delegate = (id<UITableViewDelegate>)self;
  95. tableView.dataSource = (id<UITableViewDataSource>)self;
  96. tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  97. tableView.backgroundColor = [UIColor clearColor];
  98. [self addSubview:tableView];
  99. [self setTableView:tableView];
  100. self.rowsExpandingAnimation = RATreeViewRowAnimationTop;
  101. self.rowsCollapsingAnimation = RATreeViewRowAnimationBottom;
  102. }
  103. #pragma mark Configuring a Tree View
  104. - (NSInteger)numberOfRows
  105. {
  106. return [self.tableView numberOfRowsInSection:0];
  107. }
  108. - (RATreeViewStyle)style
  109. {
  110. UITableViewStyle tableViewStyle = self.tableView.style;
  111. return [RATreeView treeViewStyleForTableViewStyle:tableViewStyle];
  112. }
  113. - (RATreeViewCellSeparatorStyle)separatorStyle
  114. {
  115. RATreeViewCellSeparatorStyle style = [RATreeView treeViewCellSeparatorStyleForTableViewSeparatorStyle:self.tableView.separatorStyle];
  116. return style;
  117. }
  118. - (void)setSeparatorStyle:(RATreeViewCellSeparatorStyle)separatorStyle
  119. {
  120. UITableViewCellSeparatorStyle tableViewSeparatorStyle = [RATreeView tableViewCellSeparatorStyleForTreeViewCellSeparatorStyle:separatorStyle];
  121. self.tableView.separatorStyle = tableViewSeparatorStyle;
  122. }
  123. - (UIColor *)separatorColor
  124. {
  125. return self.tableView.separatorColor;
  126. }
  127. - (void)setSeparatorColor:(UIColor *)separatorColor
  128. {
  129. self.tableView.separatorColor = separatorColor;
  130. }
  131. - (CGFloat)rowHeight
  132. {
  133. return self.tableView.rowHeight;
  134. }
  135. - (void)setRowHeight:(CGFloat)rowHeight
  136. {
  137. self.tableView.rowHeight = rowHeight;
  138. }
  139. - (CGFloat)estimatedRowHeight
  140. {
  141. return self.tableView.estimatedRowHeight;
  142. }
  143. - (void)setEstimatedRowHeight:(CGFloat)estimatedRowHeight
  144. {
  145. self.tableView.estimatedRowHeight = estimatedRowHeight;
  146. }
  147. - (UIEdgeInsets)separatorInset
  148. {
  149. return self.tableView.separatorInset;
  150. }
  151. - (void)setSeparatorInset:(UIEdgeInsets)separatorInset
  152. {
  153. self.tableView.separatorInset = separatorInset;
  154. }
  155. - (UIView *)backgroundView
  156. {
  157. return self.tableView.backgroundView;
  158. }
  159. - (void)setBackgroundView:(UIView *)backgroundView
  160. {
  161. self.tableView.backgroundView = backgroundView;
  162. }
  163. #pragma mark Expanding and Collapsing Rows
  164. - (void)expandRowForItem:(id)item
  165. {
  166. [self expandRowForItem:item withRowAnimation:self.rowsExpandingAnimation];
  167. }
  168. - (void)expandRowForItem:(id)item withRowAnimation:(RATreeViewRowAnimation)animation
  169. {
  170. NSInteger index = [self.treeNodeCollectionController indexForItem:item];
  171. RATreeNode *treeNode = [self.treeNodeCollectionController treeNodeForIndex:index];
  172. if (treeNode.expanded) {
  173. return;
  174. }
  175. [self expandCellForTreeNode:treeNode withRowAnimation:animation];
  176. }
  177. - (void)collapseRowForItem:(id)item
  178. {
  179. [self collapseRowForItem:item withRowAnimation:self.rowsCollapsingAnimation];
  180. }
  181. - (void)collapseRowForItem:(id)item withRowAnimation:(RATreeViewRowAnimation)animation
  182. {
  183. NSInteger index = [self.treeNodeCollectionController indexForItem:item];
  184. RATreeNode *treeNode = [self.treeNodeCollectionController treeNodeForIndex:index];
  185. [self collapseCellForTreeNode:treeNode withRowAnimation:animation];
  186. }
  187. #pragma mark Creating Table View Cells
  188. - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
  189. {
  190. [self.tableView registerNib:nib forCellReuseIdentifier:identifier];
  191. }
  192. - (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier
  193. {
  194. [self.tableView registerClass:cellClass forCellReuseIdentifier:identifier];
  195. }
  196. - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
  197. {
  198. return [self.tableView dequeueReusableCellWithIdentifier:identifier];
  199. }
  200. #pragma mark Accessing Header and Footer Views
  201. - (void)registerNib:(UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier
  202. {
  203. [self.tableView registerNib:nib forHeaderFooterViewReuseIdentifier:identifier];
  204. }
  205. - (void)registerClass:(Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier
  206. {
  207. [self.tableView registerClass:aClass forHeaderFooterViewReuseIdentifier:identifier];
  208. }
  209. - (id)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier
  210. {
  211. return [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:identifier];
  212. }
  213. - (UIView *)treeHeaderView
  214. {
  215. return self.tableView.tableHeaderView;
  216. }
  217. - (void)setTreeHeaderView:(UIView *)treeHeaderView
  218. {
  219. self.tableView.tableHeaderView = treeHeaderView;
  220. }
  221. - (UIView *)treeFooterView
  222. {
  223. return self.tableView.tableFooterView;
  224. }
  225. - (void)setTreeFooterView:(UIView *)treeFooterView
  226. {
  227. self.tableView.tableFooterView = treeFooterView;
  228. }
  229. #pragma mark Accessing Cells
  230. - (UITableViewCell *)cellForItem:(id)item
  231. {
  232. NSIndexPath *indexPath = [self indexPathForItem:item];
  233. return [self.tableView cellForRowAtIndexPath:indexPath];
  234. }
  235. - (NSArray *)visibleCells
  236. {
  237. return [self.tableView visibleCells];
  238. }
  239. #pragma mark Scrolling the TreeView
  240. - (void)scrollToRowForItem:(id)item atScrollPosition:(RATreeViewScrollPosition)scrollPosition animated:(BOOL)animated
  241. {
  242. NSIndexPath *indexPath = [self indexPathForItem:item];
  243. UITableViewScrollPosition tableViewScrollPosition = [RATreeView tableViewScrollPositionForTreeViewScrollPosition:scrollPosition];
  244. [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:tableViewScrollPosition animated:animated];
  245. }
  246. - (void)scrollToNearestSelectedRowAtScrollPosition:(RATreeViewScrollPosition)scrollPosition animated:(BOOL)animated
  247. {
  248. UITableViewScrollPosition tableViewScrollPosition = [RATreeView tableViewScrollPositionForTreeViewScrollPosition:scrollPosition];
  249. [self.tableView scrollToNearestSelectedRowAtScrollPosition:tableViewScrollPosition animated:animated];
  250. }
  251. #pragma mark Managing Selections
  252. - (id)itemForSelectedRow
  253. {
  254. NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
  255. return [self treeNodeForIndex:indexPath.row].item;
  256. }
  257. - (NSArray *)itemsForSelectedRows
  258. {
  259. NSMutableArray *items = [NSMutableArray array];
  260. NSArray *selectedRows = [self.tableView indexPathsForSelectedRows];
  261. for (NSIndexPath *indexPath in selectedRows) {
  262. id item = [self treeNodeForIndex:indexPath.row].item;
  263. [items addObject:item];
  264. }
  265. return [NSArray arrayWithArray:items];
  266. }
  267. - (void)selectRowForItem:(id)item animated:(BOOL)animated scrollPosition:(RATreeViewScrollPosition)scrollPosition
  268. {
  269. NSIndexPath *indexPath = [self indexPathForItem:item];
  270. UITableViewScrollPosition tableViewScrollPosition = [RATreeView tableViewScrollPositionForTreeViewScrollPosition:scrollPosition];
  271. [self.tableView selectRowAtIndexPath:indexPath animated:animated scrollPosition:tableViewScrollPosition];
  272. }
  273. - (void)deselectRowForItem:(id)item animated:(BOOL)animated
  274. {
  275. NSIndexPath *indexPath = [self indexPathForItem:item];
  276. [self.tableView deselectRowAtIndexPath:indexPath animated:animated];
  277. }
  278. - (BOOL)allowsSelection
  279. {
  280. return self.tableView.allowsSelection;
  281. }
  282. - (void)setAllowsSelection:(BOOL)allowsSelection
  283. {
  284. self.tableView.allowsSelection = allowsSelection;
  285. }
  286. - (BOOL)allowsMultipleSelection
  287. {
  288. return self.tableView.allowsMultipleSelection;
  289. }
  290. - (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection
  291. {
  292. self.tableView.allowsMultipleSelection = allowsMultipleSelection;
  293. }
  294. - (BOOL)allowsSelectionDuringEditing
  295. {
  296. return self.tableView.allowsSelectionDuringEditing;
  297. }
  298. - (void)setAllowsSelectionDuringEditing:(BOOL)allowsSelectionDuringEditing
  299. {
  300. self.tableView.allowsSelectionDuringEditing = allowsSelectionDuringEditing;
  301. }
  302. - (BOOL)allowsMultipleSelectionDuringEditing
  303. {
  304. return self.tableView.allowsMultipleSelectionDuringEditing;
  305. }
  306. - (void)setAllowsMultipleSelectionDuringEditing:(BOOL)allowsMultipleSelectionDuringEditing
  307. {
  308. self.tableView.allowsMultipleSelectionDuringEditing = allowsMultipleSelectionDuringEditing;
  309. }
  310. #pragma mark Managing the Editing of Tree Cells
  311. - (BOOL)isEditing
  312. {
  313. return self.tableView.isEditing;
  314. }
  315. - (void)setEditing:(BOOL)editing
  316. {
  317. self.tableView.editing = editing;
  318. }
  319. - (void)setEditing:(BOOL)editing animated:(BOOL)animated
  320. {
  321. [self.tableView setEditing:editing animated:animated];
  322. }
  323. #pragma mark Reloading the Tree View
  324. - (void)reloadData
  325. {
  326. [self setupTreeStructure];
  327. [self.tableView reloadData];
  328. }
  329. - (void)reloadRowsForItems:(NSArray *)items withRowAnimation:(RATreeViewRowAnimation)animation
  330. {
  331. NSMutableArray *indexes = [NSMutableArray array];
  332. UITableViewRowAnimation tableViewRowAnimation = [RATreeView tableViewRowAnimationForTreeViewRowAnimation:animation];
  333. for (id item in items) {
  334. NSIndexPath *indexPath = [self indexPathForItem:item];
  335. [indexes addObject:indexPath];
  336. }
  337. [self.tableView reloadRowsAtIndexPaths:indexes withRowAnimation:tableViewRowAnimation];
  338. }
  339. - (void)reloadRows
  340. {
  341. NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:0];
  342. [self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone];
  343. }
  344. #pragma mark UIScrollView
  345. - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
  346. {
  347. [self.tableView setContentOffset:contentOffset animated:animated];
  348. }
  349. - (void)scrollRectToVisible:(CGRect)visible animated:(BOOL)animated
  350. {
  351. [self.tableView scrollRectToVisible:visible animated:animated];
  352. }
  353. - (void)setZoomScale:(CGFloat)zoomScale animated:(BOOL)animated
  354. {
  355. [self.tableView setZoomScale:zoomScale animated:animated];
  356. }
  357. - (void)flashScrollIndicators
  358. {
  359. [self.tableView flashScrollIndicators];
  360. }
  361. - (void)zoomToRect:(CGRect)rect animated:(BOOL)animated
  362. {
  363. [self.tableView zoomToRect:rect animated:animated];
  364. }
  365. @end