vds_ios/VDS/Components/Tilelet/TileletGroup/TileletGroup.swift
Matt Bruce 2e519eee28 updated flow
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2024-10-09 16:30:57 -05:00

188 lines
6.7 KiB
Swift

//
// TileletGroup.swift
// VDS
//
// Created by Matt Bruce on 10/8/24.
//
import Foundation
import UIKit
import VDSCoreTokens
import Combine
open class TileletGroup: View {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
/// CollectionView to show the rows and columns
private lazy var matrixView = SelfSizingCollectionView(frame: .zero, collectionViewLayout: flowLayout).with {
$0.register(TileletGroupCellItem.self, forCellWithReuseIdentifier: TileletGroupCellItem.Identifier)
$0.dataSource = self
$0.delegate = self
$0.translatesAutoresizingMaskIntoConstraints = false
$0.allowsSelection = false
$0.showsVerticalScrollIndicator = false
$0.showsHorizontalScrollIndicator = false
$0.isAccessibilityElement = true
$0.backgroundColor = .clear
}
/// Custom flow layout to manage the height of the cells
private lazy var flowLayout = TileletGroupFlowLayout().with {
$0.delegate = self
$0.scrollDirection = .horizontal
}
/// Parameter to show the all table rows
private var rows: [[Tilelet]] = [] { didSet { setNeedsUpdate() } }
//--------------------------------------------------
// MARK: - Enums
//--------------------------------------------------
/// Enums used to define the padding for the cell edge spacing.
public enum Padding: String, CaseIterable {
case standard, compact
private func value() -> CGFloat {
switch self {
case .standard:
return UIDevice.isIPad ? 40.0 : VDSLayout.space3X
case .compact:
return UIDevice.isIPad ? VDSLayout.space6X : VDSLayout.space3X
}
}
func horizontalValue() -> CGFloat { value() }
func verticalValue() -> CGFloat { value() }
}
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
/// Parameter to set the padding for the cell
open var padding: Padding = .standard { didSet { setNeedsUpdate() } }
/// An object containing number of Button components per row for iPhones
open var rowQuantityPhone: Int = 2 { didSet { updateRows() } }
/// An object containing number of Button components per row for iPads
open var rowQuantityTablet: Int = 4 { didSet { updateRows() } }
/// An object containing number of Button components per row
open var rowQuantity: Int { UIDevice.isIPad ? rowQuantityTablet : rowQuantityPhone }
open var tilelets: [Tilelet] = [] { didSet { updateRows() } }
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
///Called upon initializing the table view
open override func setup() {
super.setup()
addSubview(matrixView)
matrixView.pinToSuperView()
}
/// Will update the table view, when called becasue of any changes in component parameters
open override func updateView() {
super.updateView()
flowLayout.verticalPadding = padding.verticalValue()
flowLayout.horizontalPadding = padding.horizontalValue()
matrixView.reloadData()
matrixView.collectionViewLayout.invalidateLayout()
}
open override func setDefaults() {
super.setDefaults()
padding = .standard
rows = [[]]
}
func updateRows() {
var tempRows: [[Tilelet]] = []
for i in stride(from: 0, to: tilelets.count, by: rowQuantity) {
let endIndex = min(i + rowQuantity, tilelets.count)
let row = Array(tilelets[i..<endIndex])
tempRows.append(row)
}
rows = tempRows
}
}
extension TileletGroup: UICollectionViewDelegate, UICollectionViewDataSource, TiletGroupCollectionViewLayoutDataDelegate {
//--------------------------------------------------
// MARK: - UICollectionViewDelegate & UICollectionViewDataSource
//--------------------------------------------------
public func numberOfSections(in collectionView: UICollectionView) -> Int {
return rows.count
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return rows[section].count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TileletGroupCellItem.Identifier, for: indexPath) as? TileletGroupCellItem else { return UICollectionViewCell() }
let currentItem = rows[indexPath.section][indexPath.row]
cell.updateCell(component: currentItem)
// let rowColors: (UIColor,UIColor) = indexPath.section % 2 == 0 ? (.green, .yellow) : (.blue, .brown)
// cell.backgroundColor = indexPath.row % 2 == 0 ? rowColors.0 : rowColors.1
return cell
}
//--------------------------------------------------
// MARK: - TableCollectionViewLayoutDataDelegate
//--------------------------------------------------
internal func collectionView(_ collectionView: UICollectionView, dataForItemAt indexPath: IndexPath) -> Tilelet {
return rows[indexPath.section][indexPath.row]
}
}
final class TileletGroupCellItem: UICollectionViewCell {
/// Identifier for TableCellItem
static let Identifier: String = String(describing: TileletGroupCellItem.self)
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
/// Main view which holds the content of the cell
private let containerView = View()
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
override init(frame: CGRect) {
super.init(frame: frame)
setupCell()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupCell()
}
private func setupCell() {
contentView.backgroundColor = .clear
addSubview(containerView)
containerView.pinToSuperView()
}
//--------------------------------------------------
// MARK: - Public Methods
//--------------------------------------------------
public func updateCell(component: Tilelet) {
containerView.subviews.forEach({ $0.removeFromSuperview() })
containerView.addSubview(component)
component.pinToSuperView()
}
}