// // Copyright (c) 2015 Max Sokolov https://twitter.com/max_sokolov // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import UIKit import Foundation public typealias ReturnValue = AnyObject? internal enum ActionHandler { case actionBlock((data: ActionData) -> Void) case actionReturnBlock((data: ActionData) -> AnyObject?) func call(data: ActionData) -> AnyObject? { switch (self) { case .actionBlock(let closure): closure(data: data) return true case .actionReturnBlock(let closure): return closure(data: data) } } } /** Responsible for building cells of given type and passing items to them. */ public class TableRowBuilder : RowBuilder { private var actions = Dictionary>() private var items = [I]() public var reusableIdentifier: String public var estimatedRowHeight: Float public var numberOfRows: Int { get { return items.count } } public init(item: I, id: String, estimatedRowHeight: Float = 0) { reusableIdentifier = id self.estimatedRowHeight = estimatedRowHeight items.append(item) } public init(items: [I]? = nil, id: String, estimatedRowHeight: Float = 0) { reusableIdentifier = id self.estimatedRowHeight = estimatedRowHeight if items != nil { self.items.appendContentsOf(items!) } } // MARK: Items manipulation public func appendItems(items: [I]) { self.items.appendContentsOf(items) } public func clear() { items.removeAll() } // MARK: Chaining actions public func action(key: String, closure: (data: ActionData) -> Void) -> Self { actions[key] = .actionBlock(closure) return self } public func action(actionType: ActionType, closure: (data: ActionData) -> Void) -> Self { actions[actionType.key] = .actionBlock(closure) return self } public func action(actionType: ActionType, closure: (data: ActionData) -> ReturnValue) -> Self { actions[actionType.key] = .actionReturnBlock(closure) return self } // MARK: Triggers public func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { if let action = actions[actionType.key] { return action.call(ActionData(cell: cell as? C, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex)) } return nil } } /** Responsible for building configurable cells of given type and passing items to them. */ public class TableConfigurableRowBuilder : TableRowBuilder { public init(item: I, estimatedRowHeight: Float = 0) { super.init(item: item, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight) } public init(items: [I]? = nil, estimatedRowHeight: Float = 0) { super.init(items: items, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight) } public override func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { switch actionType { case .configure: (cell as? C)?.configureWithItem(items[itemIndex]) default: break } return super.triggerAction(actionType, cell: cell, indexPath: indexPath, itemIndex: itemIndex) } }