// // Button.swift // MVMCoreUI // // Created by Robinson, Blake on 12/18/19. // Copyright © 2019 Verizon Wireless. All rights reserved. // public typealias ButtonAction = (Button) -> () @objcMembers open class Button: UIButton, MFButtonProtocol, ModelMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public var model: MoleculeModelProtocol? public var actionModel: ActionModelProtocol? private var initialSetupPerformed = false private var buttonAction: ButtonAction? //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- public weak var buttonDelegate: ButtonDelegateProtocol? //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- public override init(frame: CGRect) { super.init(frame: .zero) initialSetup() } public convenience init() { self.init(frame: .zero) initialSetup() } public required init?(coder: NSCoder) { super.init(coder: coder) fatalError("Button does not support xib.") } //-------------------------------------------------- // MARK: - Setup //-------------------------------------------------- public func initialSetup() { if !initialSetupPerformed { initialSetupPerformed = true setupView() } } //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- public func addActionBlock( event: Event, _ buttonBlock: @escaping ButtonAction) { self.buttonAction = buttonBlock addTarget(self, action: #selector(callActionBlock(_:)), for: event) } func callActionBlock(_ sender: Button) { buttonAction?(self) } public func set(with actionModel: ActionModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { self.actionModel = actionModel buttonDelegate = delegateObject?.buttonDelegate addActionBlock(event: .touchUpInside) { [weak self] sender in guard let self = self else { return } if let data = try? actionModel.encode(using: JSONEncoder()), let actionMap = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.init()) as? [AnyHashable: Any], delegateObject?.buttonDelegate?.button?(self, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } } // MARK:- ModelMoleculeViewProtocol open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { self.model = model if let backgroundColor = model?.backgroundColor { self.backgroundColor = backgroundColor.uiColor } } open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { return model?.moleculeName } open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return nil } open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { return nil } } // MARK: - MVMCoreViewProtocol extension Button: MVMCoreViewProtocol { public func updateView(_ size: CGFloat) {} /// Will be called only once. public func setupView() { translatesAutoresizingMaskIntoConstraints = false insetsLayoutMarginsFromSafeArea = false titleLabel?.numberOfLines = 0 titleLabel?.lineBreakMode = .byWordWrapping } } // MARK: - MVMCoreUIMoleculeViewProtocol extension Button: MVMCoreUIMoleculeViewProtocol { public func reset() { backgroundColor = .clear } } // MARK: AppleGuidelinesProtocol extension Button: AppleGuidelinesProtocol { override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return Self.acceptablyOutsideBounds(point: point, bounds: bounds) } }