transitioning logical view model separation

This commit is contained in:
Kevin G Christiano 2020-03-02 15:52:02 -05:00
parent 3e3b7dac79
commit b00485c81a
4 changed files with 54 additions and 85 deletions

View File

@ -36,7 +36,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
/// The types of indicators that can appear.
public enum IndicatorType: String {
case bar
case bars
case numeric
case hybrid // bar & numeric
}
@ -77,29 +77,10 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
}
}
/// The maxmum count of pages before the indicatorView forces a Numeric Indicator in place of Bar.
public var hybridThreshold: Int = 5
/// Set this closure to perform an action when a different indicator was selected.
/// Passes through oldInde and newIndex, respectively.
public var indicatorTouchAction: ((CarouselPageControlProtocol) -> ())?
/// Allows sendActions() to trigger even if index is already at min/max index.
public var alwaysSendAction = false
/// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false
public var accessibilityHasSlidesInsteadOfPage = false
public var isAnimated = true
/// Will hide this control if page count is 1.
public var hidesForSinglePage = false {
didSet { isHidden = hidesForSinglePage && numberOfPages <= 1 }
}
/// If true, then index will wraparound, otherwise it will stop paging at min/max index.
public var allowIndexWraparound = false
public override var isEnabled: Bool {
didSet {
isUserInteractionEnabled = isEnabled
@ -117,10 +98,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
public var currentIndex: Int {
get { return _currentIndex }
set (newIndex) {
if !allowIndexWraparound {
guard _currentIndex != newIndex else { return }
}
previousIndex = _currentIndex
_currentIndex = newIndex
performAction()
@ -138,7 +116,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
guard _numberOfPages != newTotal else { return }
_numberOfPages = newTotal
isHidden = hidesForSinglePage && newTotal <= 1
isHidden = carouselIndicatorModel?.hidesForSinglePage ?? false && newTotal <= 1
if isBarIndicator() {
(indicatorView as? BarsIndicatorView)?.generateBars()
@ -148,14 +126,14 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
}
}
public var disabledIndicatorColor: UIColor = .mvmCoolGray3
private var _indicatorTintColor: UIColor = .black
public var disabledIndicatorColor: UIColor {
return carouselIndicatorModel?.disabledIndicatorColor.uiColor ?? .mvmCoolGray3
}
public var indicatorTintColor: UIColor {
get { return _indicatorTintColor }
get { return carouselIndicatorModel?.indicatorColor.uiColor ?? .black }
set (newColor) {
_indicatorTintColor = newColor
carouselIndicatorModel?.indicatorColor = Color(uiColor: newColor)
if isBarIndicator(), let barIndicator = indicatorView as? BarsIndicatorView {
for (i, barTuple) in barIndicator.barReferences.enumerated() where i != currentIndex {
@ -175,7 +153,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
carouselIndicatorModel?.currentIndicatorColor = Color(uiColor: newColor)
if isBarIndicator() {
if let barIndicator = indicatorView as? BarsIndicatorView {
if let barIndicator = indicatorView as? BarsIndicatorView, !barIndicator.barReferences.isEmpty {
barIndicator.barReferences[currentIndex].view.backgroundColor = newColor
}
}
@ -219,10 +197,6 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
assignIndicatorView()
setupGestures()
if let accessibleValue = MVMCoreUIUtility.hardcodedString(withKey: accessibilityHasSlidesInsteadOfPage ? "MVMCoreUIPageControlslides_currentpage_index" : "MVMCoreUIPageControl_currentpage_index") {
accessibilityValue = String(format: accessibleValue, currentIndex + 1, numberOfPages)
}
}
//--------------------------------------------------
@ -293,7 +267,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
indicatorView?.updateUI(previousIndex: previousIndex,
newIndex: currentIndex,
totalCount: numberOfPages,
isAnimated: isAnimated)
isAnimated: carouselIndicatorModel?.isAnimated ?? true)
}
public func performAction() {
@ -306,20 +280,21 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
func assignIndicatorView() {
switch indicatorType {
case .bar:
case .bars:
indicatorView = BarsIndicatorView()
case .numeric:
indicatorView = NumericIndicatorView()
case .hybrid:
indicatorView = numberOfPages >= hybridThreshold ? NumericIndicatorView() : BarsIndicatorView()
indicatorView = numberOfPages >= carouselIndicatorModel?.hybridThreshold ?? 0 ? NumericIndicatorView() : BarsIndicatorView()
}
}
/// Convenience to determine if current view is displaying bars.
func isBarIndicator() -> Bool {
return indicatorType == .bar || indicatorType == .hybrid && numberOfPages <= hybridThreshold
return indicatorType == .bars || indicatorType == .hybrid && numberOfPages <= carouselIndicatorModel?.hybridThreshold ?? 5
}
public func scrollViewDidScroll(_ collectionView: UICollectionView) { }
@ -328,18 +303,20 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
open override func set(with model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
// super.setWithModel(model, delegateObject, additionalData)
// super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? CarouselIndicatorModel else { return }
indicatorType = IndicatorType(rawValue: model.type ?? "") ?? .hybrid
indicatorType = IndicatorType(rawValue: model.type) ?? .hybrid
backgroundColor = model.backgroundColor?.uiColor
// barsColor = model.barsColor
// pageIndicatorTintColor
// currentPageIndicatorTintColor
currentIndicatorColor = model.currentIndicatorColor.uiColor
indicatorTintColor = model.indicatorColor.uiColor
isEnabled = model.isEnabled
if let accessibleValue = MVMCoreUIUtility.hardcodedString(withKey: model.accessibilityHasSlidesInsteadOfPage ? "MVMCoreUIPageControlslides_currentpage_index" : "MVMCoreUIPageControl_currentpage_index") {
accessibilityValue = String(format: accessibleValue, currentIndex + 1, numberOfPages)
}
}
//--------------------------------------------------
@ -358,8 +335,8 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
func accessibilityAdjust(toPage index: Int) {
if (index < numberOfPages && index >= 0) || alwaysSendAction {
isAnimated = false
if (index < numberOfPages && index >= 0) || carouselIndicatorModel?.alwaysSendAction ?? false {
carouselIndicatorModel?.isAnimated = false
previousIndex = currentIndex
currentIndex = index
performAction()

View File

@ -21,20 +21,22 @@ public class CarouselIndicatorModel: CarouselPagingModelProtocol {
public var backgroundColor: Color?
public var moleculeName: String?
public var type: String = "hybrid"
/// The maxmum count of pages before the indicatorView forces a Numeric Indicator in place of Bar.
public var hybridThreshold: Int = 5
public var barsColor: Color?
public var currentBarColor: Color?
public var currentIndex: Int = 0
public var numberOfPages: Int = 0
public var alwaysSendEvent: Bool = false
public var isAnimated: Bool = true
public var hidesForSinglePage: Bool = false
/// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false
public var accessibilityHasSlidesInsteadOfPage: Bool = false
public var isEnabled: Bool = false
public var isEnabled: Bool = true
public var disabledIndicatorColor: Color = Color(uiColor: .mvmCoolGray3)
public var indicatorTintColor: Color = Color(uiColor: .mvmBlack)
public var indicatorColor: Color = Color(uiColor: .mvmBlack)
public var currentIndicatorColor: Color = Color(uiColor: .mvmBlack)
public var position: Float?
public var padding: Float?
/// Allows sendActions() to trigger even if index is already at min/max index.
public var alwaysSendAction = false
//--------------------------------------------------
// MARK: - Keys
@ -45,18 +47,16 @@ public class CarouselIndicatorModel: CarouselPagingModelProtocol {
case backgroundColor
case type
case hybridThreshold
case barsColor
case currentBarColor
case currentIndex
case numberOfPages
case alwaysSendEvent
case alwaysSendAction
case isAnimated
case hidesForSinglePage
case accessibilityHasSlidesInsteadOfPage
case isEnabled
case disabledIndicatorColor
case indicatorTintColor
case indicatorColor
case currentIndicatorColor
case padding
}
//--------------------------------------------------
@ -66,12 +66,8 @@ public class CarouselIndicatorModel: CarouselPagingModelProtocol {
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName)
currentBarColor = try typeContainer.decodeIfPresent(Color.self, forKey: .currentBarColor)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
barsColor = try typeContainer.decodeIfPresent(Color.self, forKey: .barsColor)
barsColor = try typeContainer.decodeIfPresent(Color.self, forKey: .barsColor)
currentBarColor = try typeContainer.decodeIfPresent(Color.self, forKey: .currentBarColor)
if let type = try typeContainer.decodeIfPresent(String.self, forKey: .type) {
self.type = type
}
@ -80,16 +76,16 @@ public class CarouselIndicatorModel: CarouselPagingModelProtocol {
self.hybridThreshold = hybridThreshold
}
if let currentIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .currentIndex) {
self.currentIndex = currentIndex
}
if let numberOfPages = try typeContainer.decodeIfPresent(Int.self, forKey: .numberOfPages) {
self.numberOfPages = numberOfPages
}
if let alwaysSendEvent = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysSendEvent) {
self.alwaysSendEvent = alwaysSendEvent
if let alwaysSendAction = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysSendAction) {
self.alwaysSendAction = alwaysSendAction
}
if let padding = try typeContainer.decodeIfPresent(Float.self, forKey: .padding) {
self.padding = padding
}
if let isAnimated = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAnimated) {
@ -112,8 +108,8 @@ public class CarouselIndicatorModel: CarouselPagingModelProtocol {
self.disabledIndicatorColor = disabledIndicatorColor
}
if let indicatorTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .indicatorTintColor) {
self.indicatorTintColor = indicatorTintColor
if let indicatorColor = try typeContainer.decodeIfPresent(Color.self, forKey: .indicatorColor) {
self.indicatorColor = indicatorColor
}
if let currentIndicatorColor = try typeContainer.decodeIfPresent(Color.self, forKey: .currentIndicatorColor) {
@ -125,21 +121,17 @@ public class CarouselIndicatorModel: CarouselPagingModelProtocol {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(barsColor, forKey: .barsColor)
try container.encodeIfPresent(currentBarColor, forKey: .currentBarColor)
try container.encodeIfPresent(type, forKey: .type)
try container.encodeIfPresent(hybridThreshold, forKey: .hybridThreshold)
try container.encodeIfPresent(barsColor, forKey: .barsColor)
try container.encodeIfPresent(currentBarColor, forKey: .currentBarColor)
try container.encodeIfPresent(currentIndex, forKey: .currentIndex)
try container.encodeIfPresent(numberOfPages, forKey: .numberOfPages)
try container.encodeIfPresent(alwaysSendEvent, forKey: .alwaysSendEvent)
try container.encodeIfPresent(alwaysSendAction, forKey: .alwaysSendAction)
try container.encodeIfPresent(isAnimated, forKey: .isAnimated)
try container.encodeIfPresent(hidesForSinglePage, forKey: .hidesForSinglePage)
try container.encodeIfPresent(accessibilityHasSlidesInsteadOfPage, forKey: .accessibilityHasSlidesInsteadOfPage)
try container.encodeIfPresent(isEnabled, forKey: .isEnabled)
try container.encodeIfPresent(disabledIndicatorColor, forKey: .disabledIndicatorColor)
try container.encodeIfPresent(indicatorTintColor, forKey: .indicatorTintColor)
try container.encodeIfPresent(indicatorColor, forKey: .indicatorColor)
try container.encodeIfPresent(currentIndicatorColor, forKey: .currentIndicatorColor)
try container.encodeIfPresent(padding, forKey: .padding)
}
}

View File

@ -10,5 +10,5 @@ import Foundation
public protocol CarouselPagingModelProtocol: MoleculeModelProtocol {
var position: Float? { get }
var padding: Float? { get }
}

View File

@ -176,7 +176,7 @@ open class Carousel: View {
pagingView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(molecule, delegateObject, false) as? (UIView & CarouselPageControlProtocol)
}
addPaging(view: pagingView, position: (CGFloat(molecule?.position ?? 20)))
addPaging(view: pagingView, padding: (CGFloat(molecule?.padding ?? 20)))
}
/// Registers the cells with the collection view
@ -221,7 +221,7 @@ open class Carousel: View {
}
/// Adds a paging view. Centers it horizontally with the collection view. The position is the vertical distance from the center of the page view to the bottom of the collection view.
open func addPaging(view: (UIView & CarouselPageControlProtocol)?, position: CGFloat) {
open func addPaging(view: (UIView & CarouselPageControlProtocol)?, padding: CGFloat) {
pagingView?.removeFromSuperview()
bottomPin?.isActive = false
@ -234,7 +234,7 @@ open class Carousel: View {
addSubview(pagingView)
pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: pagingView.bottomAnchor, constant: position).isActive = true
collectionView.bottomAnchor.constraint(equalTo: pagingView.bottomAnchor, constant: padding).isActive = true
bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor)
bottomPin?.priority = .defaultLow
bottomPin?.isActive = true