mvm_core_ui/MVMCoreUI/Molecules/MoleculeTableViewCell.swift
Pfeil, Scott Robert 400a51f0b5 remove spaces
2019-06-18 13:31:51 -04:00

228 lines
9.8 KiB
Swift

//
// MoleculeTableViewCell.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/18/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class MoleculeTableViewCell: UITableViewCell, MVMCoreUIMoleculeViewProtocol, MoleculeListCellProtocol {
open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)?
open var json: [AnyHashable: Any]?
// For the accessory view convenience.
public var caretView: CaretView?
private var caretViewWidthSizeObject: MFSizeObject?
private var caretViewHeightSizeObject: MFSizeObject?
// For separation between cells.
public var topSeparatorView: SeparatorView?
public var bottomSeparatorView: SeparatorView?
public enum SeparatorFrequency: String {
case All = "all"
case AllExceptTop = "allExceptTop"
case AllExceptBottom = "allExceptBottom"
case Between = "between"
}
// MARK: - Inits
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupView()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
// MARK: - MFViewProtocol
public func updateView(_ size: CGFloat) {
MFStyler.setDefaultMarginsFor(self, size: size, horizontal: true, vertical: true)
if #available(iOS 11.0, *) {
if accessoryView != nil {
// Smaller left margin if accessory view.
var margin = directionalLayoutMargins
margin.trailing = 16
contentView.directionalLayoutMargins = margin
} else {
contentView.directionalLayoutMargins = directionalLayoutMargins
}
topSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading)
bottomSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading)
} else {
if accessoryView != nil {
// Smaller left margin if accessory view.
var margin = layoutMargins
margin.right = 16
contentView.layoutMargins = margin
} else {
contentView.layoutMargins = layoutMargins
}
topSeparatorView?.setLeftAndRightPinConstant(layoutMargins.left)
bottomSeparatorView?.setLeftAndRightPinConstant(layoutMargins.left)
}
molecule?.updateView(size)
if let _ = accessoryView, let caretView = caretView, let widthObject = caretViewWidthSizeObject, let heightObject = caretViewHeightSizeObject {
caretView.frame = CGRect(x: 0, y: 0, width: widthObject.getValueBased(onSize: size), height: heightObject.getValueBased(onSize: size))
}
topSeparatorView?.updateView(size)
bottomSeparatorView?.updateView(size)
}
public func setupView() {
preservesSuperviewLayoutMargins = false
contentView.preservesSuperviewLayoutMargins = false
selectionStyle = .none
}
// MARK: - MVMCoreUIMoleculeViewProtocol
public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
self.json = json;
guard let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else {
return
}
if molecule == nil {
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) {
contentView.addSubview(moleculeView)
var standardConstraints = true
if let castView = moleculeView as? MVMCoreUIViewConstrainingProtocol {
standardConstraints = castView.useStandardConstraints?() ?? true
castView.shouldSetHorizontalMargins?(!standardConstraints)
castView.shouldSetVerticalMargins?(!standardConstraints)
}
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: standardConstraints).values))
if standardConstraints {
let constraint = contentView.heightAnchor.constraint(equalToConstant: 80)
constraint.priority = .defaultLow
constraint.isActive = true
}
molecule = moleculeView
}
} else {
molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
}
backgroundColor = molecule?.backgroundColor
// Add the caret if there is an action and it's not declared hidden.
if let _ = json.optionalDictionaryForKey("actionMap"), !json.boolForKey("hideArrow") {
addCaretViewAccessory()
} else {
accessoryView = nil
}
// override the separator
if let separator = json.optionalDictionaryForKey("separator") {
addSeparatorsIfNeeded()
bottomSeparatorView?.setWithJSON(separator, delegateObject: delegateObject, additionalData: additionalData)
}
}
public func reset() {
molecule?.reset?()
}
public static func estimatedHeight(forRow json: [AnyHashable: Any]?) -> CGFloat {
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule),
let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON, delegateObject: nil),
let estimatedHeightFor = theClass.estimatedHeight else {
return 80
}
return estimatedHeightFor(moleculeJSON)
}
public static func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
if let molecule = molecule?.optionalDictionaryForKey(KeyMolecule),
let moleculeName = molecule.optionalStringForKey(KeyMoleculeName),
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? AnyClass,
let castClass = moleculeClass as? MVMCoreUIMoleculeViewProtocol.Type,
let nameFunc = castClass.name {
return nameFunc(molecule, delegateObject)
} else {
return molecule?.optionalDictionaryForKey(KeyMolecule)?.optionalStringForKey(KeyMoleculeName)
}
}
// MARK: - Arrow
/// Adds the standard mvm style caret to the accessory view
public func addCaretViewAccessory() {
guard accessoryView == nil else {
return
}
let width: CGFloat = 6
let height: CGFloat = 10
caretView = CaretView(lineThickness: CaretView.thin)
caretView?.frame = CGRect(x: 0, y: 0, width: width, height: height)
caretViewWidthSizeObject = MFSizeObject(standardSize: width, standardiPadPortraitSize: 9)
caretViewHeightSizeObject = MFSizeObject(standardSize: height, standardiPadPortraitSize: 16)
accessoryView = caretView
}
// MARK: - MoleculeListCellProtocol
/// For when the separator between cells shows using json and frequency. Default is type: standard, frequency: allExceptTop.
public func setSeparatorWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, indexPath: IndexPath) {
addSeparatorsIfNeeded()
if let json = json {
topSeparatorView?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
bottomSeparatorView?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
if let separatorFrequencyString = json.optionalStringForKey("frequency"), let separatorFrequency = SeparatorFrequency(rawValue: separatorFrequencyString) {
setSeparatorFrequency(separatorFrequency, indexPath: indexPath)
}
} else {
topSeparatorView?.hide()
bottomSeparatorView?.setAsLight()
setSeparatorFrequency(MoleculeTableViewCell.SeparatorFrequency.AllExceptTop, indexPath: indexPath)
}
}
public func didSelectCell(atIndex indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
if let actionMap = json?.optionalDictionaryForKey("actionMap") {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
}
}
// MARK: - Separator
func addSeparatorsIfNeeded() {
if topSeparatorView == nil {
topSeparatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionTop)
topSeparatorView?.hide()
}
if bottomSeparatorView == nil {
bottomSeparatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot)
bottomSeparatorView?.hide()
}
}
/// For when the separator between cells shows.
public func setSeparatorFrequency(_ separatorFrequency: SeparatorFrequency, indexPath: IndexPath) {
switch separatorFrequency {
case .All:
if indexPath.row == 0 {
topSeparatorView?.show()
} else {
topSeparatorView?.hide()
}
bottomSeparatorView?.show()
case .AllExceptBottom:
topSeparatorView?.show()
bottomSeparatorView?.hide()
case .Between:
if indexPath.row == 0 {
topSeparatorView?.hide()
} else {
topSeparatorView?.show()
}
bottomSeparatorView?.hide()
case .AllExceptTop:
fallthrough
default:
topSeparatorView?.hide()
bottomSeparatorView?.show()
}
}
}