From 1e67404748af16ef0283ccd651356693b444cf78 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Fri, 3 Apr 2020 12:03:13 -0400 Subject: [PATCH 01/13] add new tabs --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 + .../HorizontalCombinationViews/Tabs.swift | 343 ++++++++++++++++++ .../TabsModel.swift | 36 +- .../Molecules/Items/TabsTableViewCell.swift | 38 +- 5 files changed, 395 insertions(+), 27 deletions(-) create mode 100644 MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 49ac139e..914b4afc 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -173,6 +173,7 @@ 94CA227F24058534002D6750 /* VerizonNHGeTX-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */; }; 94F217B623E0BF6100A47C06 /* PrimaryButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; + 94F6516D2437954100631BF9 /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94F6516C2437954100631BF9 /* Tabs.swift */; }; 94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; }; AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; }; @@ -566,6 +567,7 @@ 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = ""; }; 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrimaryButtonView.h; sourceTree = ""; }; 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; sourceTree = ""; }; + 94F6516C2437954100631BF9 /* Tabs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = ""; }; 94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = ""; }; 94FB966123D797DA003D482B /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = ""; }; AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePayments.swift; sourceTree = ""; }; @@ -1169,6 +1171,7 @@ D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */, D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */, D28A837E23CCA96400DFE4FC /* TabsModel.swift */, + 94F6516C2437954100631BF9 /* Tabs.swift */, 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */, 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, ); @@ -2042,6 +2045,7 @@ 01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */, 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, + 94F6516D2437954100631BF9 /* Tabs.swift in Sources */, 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 438f652b..08cbd301 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -85,6 +85,7 @@ import Foundation // Horizontal Combination Molecules MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: Tabs.self, viewModelClass: TabsModel.self) // Vertical Combination Molecules MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift new file mode 100644 index 00000000..d49cd414 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -0,0 +1,343 @@ +// +// Tabs.swift +// MVMCoreUI +// +// Created by Ryan on 2/7/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objc public protocol TabsDelegate { + func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool + func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) +} + +@objcMembers open class Tabs: View, MVMCoreUIViewConstrainingProtocol { + + public var tabsModel: TabsModel? { + get { return model as? TabsModel } + } + + var delegateObject: MVMCoreUIDelegateObject? + var additionalData: [AnyHashable: Any]? + + let layout = UICollectionViewFlowLayout() + public var collectionView: UICollectionView? + + let bottomScrollView = UIScrollView(frame: .zero) + let bottomContentView = View() + let bottomLine = View() + var bottomLineLeftConstraint: NSLayoutConstraint? + var bottomLineWidthConstraint: NSLayoutConstraint? + + //delegate + public var delegate: TabsDelegate? + + //control var + public var heightConstraint: NSLayoutConstraint? + public var selectedIndex: Int = 0 + public var paddingBeforeFirstTab: Bool = true + + //constant + let TabCellId = "TabCell" + public let sectionPadding: CGFloat = 20.0 + public let cellSpacing: CGFloat = 34.0 + public let cellHeight: CGFloat = 34.0 + public let bottomLineHeight: CGFloat = 4.0 + public let bottomLineWidth: CGFloat = 32.0 + public let tabsHeight: CGFloat = 38.0 + public let bottomLineMovingTime: TimeInterval = 0.2 + + //------------------------------------------------- + // MARK:- Layout Views + //------------------------------------------------- + + open override func reset() { + super.reset() + heightConstraint?.constant = tabsHeight + selectedIndex = 0 + paddingBeforeFirstTab = true + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + } + + open override func setupView() { + super.setupView() + backgroundColor = .white + setupCollectionView() + setupBottomLine() + setupConstraints() + } + + func setupCollectionView () { + layout.scrollDirection = .horizontal + layout.minimumLineSpacing = cellSpacing + + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) + collectionView.translatesAutoresizingMaskIntoConstraints = false + collectionView.register(TabItemCell.self, forCellWithReuseIdentifier: TabCellId) + collectionView.backgroundColor = .clear + collectionView.showsVerticalScrollIndicator = false + collectionView.showsHorizontalScrollIndicator = false + collectionView.dataSource = self + collectionView.delegate = self + addSubview(collectionView) + self.collectionView = collectionView + } + + func setupBottomLine() { + bottomScrollView.translatesAutoresizingMaskIntoConstraints = false + bottomScrollView.delegate = self + addSubview(bottomScrollView) + bottomScrollView.addSubview(bottomContentView) + bottomLine.backgroundColor = .mfTomatoRed() + bottomContentView.addSubview(bottomLine) + bringSubviewToFront(bottomScrollView) + } + + func setupConstraints() { + //collection view + NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView) + + //bottom lines + NSLayoutConstraint.constraintPinSubview(bottomScrollView, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true) + bottomScrollView.heightAnchor.constraint(equalToConstant: bottomLineHeight).isActive = true + NSLayoutConstraint.constraintPinSubview(bottomLine, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) + bottomLine.heightAnchor.constraint(equalToConstant: bottomLineHeight).isActive = true + bottomLineLeftConstraint = bottomLine.leftAnchor.constraint(equalTo: bottomContentView.leftAnchor) + bottomLineLeftConstraint?.isActive = true + bottomLineWidthConstraint = bottomLine.widthAnchor.constraint(equalToConstant: bottomLineWidth) + bottomLineWidthConstraint?.isActive = true + NSLayoutConstraint.constraintPinSubview(toSuperview: bottomContentView) + + //height + heightConstraint = heightAnchor.constraint(equalToConstant: tabsHeight) + heightConstraint?.isActive = true + } + + //------------------------------------------------- + // MARK:- Control Methods + //------------------------------------------------- + + public func pinHeight(_ height: CGFloat) { + heightConstraint?.constant = height + setNeedsLayout() + layoutIfNeeded() + } + + public func selectIndex(_ index: Int, animated: Bool) { + guard let _ = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { + selectedIndex = index + return + } + MVMCoreDispatchUtility.performBlock(onMainThread: { + let currentIndex = self.selectedIndex + self.selectedIndex = index + self.deselect(indexPath: IndexPath(row: currentIndex, section: 0)) + self.selectItem(atIndexPath: IndexPath(row: index, section: 0), animated: animated) + }) + } + + public func reloadData() { + collectionView?.reloadData() + } + + //------------------------------------------------- + // MARK:- Molecule Setup + //------------------------------------------------- + + override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + self.delegateObject = delegateObject + self.additionalData = additionalData + self.selectedIndex = tabsModel?.selectedIndex ?? 0 + self.bottomLine.backgroundColor = tabsModel?.selectedColor.uiColor + reloadData() + } +} + +//------------------------------------------------- +// MARK:- Collection View Methods +//------------------------------------------------- + +extension Tabs: UICollectionViewDataSource { + public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return tabsModel?.tabs.count ?? 0 + } + + public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let labelModel = tabsModel?.tabs[indexPath.row].label, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else { + return UICollectionViewCell() + } + cell.updateCell(labelModel: labelModel, indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel) + return cell + } +} + +extension Tabs: UICollectionViewDelegateFlowLayout { + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + guard let labelModel = tabsModel?.tabs[indexPath.row].label else { + return .zero + } + return CGSize(width: getLabelWidth(labelModel).width, height: cellHeight) + } + + func getLabelWidth(_ labelModel: LabelModel?) -> CGSize { + guard let labelModel = labelModel else { return .zero} + let label = Label() + label.set(with: labelModel, nil, nil) + return label.intrinsicContentSize + } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { + if !paddingBeforeFirstTab && section == 0 { + return .zero + } else { + return UIEdgeInsets(top: 0, left: sectionPadding, bottom: 0, right: 0) + } + } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + return sectionPadding + } + + public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + return delegate?.shouldSelectItem(indexPath, tabs: self) ?? true + } + + public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + selectIndex(indexPath.row, animated: true) + } + + public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { + guard let tabCell = cell as? TabItemCell else { return } + if indexPath.row == selectedIndex { + moveBottomLine(toIndex: indexPath, animated: false, cell: tabCell) + } + } + + func deselect(indexPath:IndexPath) { + collectionView?.deselectItem(at: indexPath, animated: false) + collectionView?.reloadItems(at: [indexPath]) + } + + func selectItem(atIndexPath indexPath: IndexPath, animated: Bool) { + + guard let collect = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { return } + + collect.selectItem(at: indexPath, animated: animated, scrollPosition: .centeredHorizontally) + guard let tabCell = collect.cellForItem(at: indexPath) as? TabItemCell, let tabsModel = self.tabsModel else { return } + self.moveBottomLine(toIndex: indexPath, animated: animated, cell: tabCell) + tabCell.label.textColor = tabsModel.selectedColor.uiColor + tabCell.updateAccessibility(indexPath: indexPath, selected: true, tabsModel: tabsModel) + tabCell.setNeedsDisplay() + tabCell.setNeedsLayout() + tabCell.layoutIfNeeded() + self.delegate?.didSelectItem(indexPath, tabs: self) + } +} + + +extension Tabs: UIScrollViewDelegate { + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + guard let offsetX = collectionView?.contentOffset.x else { return } + bottomScrollView.setContentOffset(CGPoint(x: offsetX, y: bottomScrollView.contentOffset.y), animated: false) + } +} + + +//------------------------------------------------- +// MARK:- Bottom Line Methods +//------------------------------------------------- +extension Tabs { + func moveBottomLine(toIndex indexPath: IndexPath, animated: Bool, cell: TabItemCell) { + guard let collect = self.collectionView else {return} + + let size = collectionView(collect, layout: layout, sizeForItemAt: indexPath) + let barWidth = max(size.width, bottomLineWidth) + let animationBlock = { + [weak self] in + let x = cell.frame.origin.x + self?.bottomLineWidthConstraint?.constant = barWidth + self?.bottomLineLeftConstraint?.constant = x + (size.width - barWidth) / 2.0 + self?.bottomContentView.layoutIfNeeded() + } + if animated { + UIView.animate(withDuration: bottomLineMovingTime, animations: animationBlock) + } else { + animationBlock() + } + } + + public func progress(fromIndex: Int, toIndex: Int, progressPercentage percent: CGFloat) { + guard let _ = collectionView else { return } + MVMCoreDispatchUtility.performBlock(onMainThread: { + self.setBottomLine(fromIndex: IndexPath(row: fromIndex, section: 0), toIndex: IndexPath(row: toIndex, section: 0), percent: percent) + }) + } + + func setBottomLine(fromIndex: IndexPath, toIndex: IndexPath, percent: CGFloat) { + guard let fromCell = collectionView?.cellForItem(at: fromIndex) as? TabItemCell, let toCell = collectionView?.cellForItem(at: toIndex) as? TabItemCell else { + return + } + let fromWidth = getLabelWidth(fromCell.labelModel).width + let toWidth = getLabelWidth(toCell.labelModel).width + let finalWidth = (toWidth - fromWidth) * percent + fromWidth + bottomLineWidthConstraint?.constant = finalWidth + let xDifference = toCell.frame.origin.x - fromCell.frame.origin.x + let finalX = xDifference * percent + fromCell.frame.origin.x + bottomLineLeftConstraint?.constant = finalX + bottomContentView.layoutIfNeeded() + } +} + + + +@objcMembers public class TabItemCell: UICollectionViewCell { + public let label = Label() + public var labelModel: LabelModel? + + override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupView() + } + + func setupView() { + contentView.addSubview(label) + NSLayoutConstraint.constraintPinSubview(label, pinTop: false, pinBottom: false, pinLeft: true, pinRight: true) + label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true + label.baselineAdjustment = .alignCenters + } + + public func updateCell(labelModel: LabelModel, indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) { + label.reset() + label.set(with: labelModel, delegateObject, additionalData) + self.labelModel = labelModel + if selected, let selectedColor = tabsModel?.selectedColor { + label.textColor = selectedColor.uiColor + } + updateAccessibility(indexPath: indexPath, selected: selected, tabsModel: tabsModel) + } + + public func updateAccessibility(indexPath: IndexPath, selected: Bool, tabsModel: TabsModel?) { + //Accessibility + isAccessibilityElement = false + contentView.isAccessibilityElement = true + let accKey = selected ? "toptabbar_tab_selected" : "AccTab" + let accLabel = "\(label.text ?? "") \(MVMCoreUIUtility.hardcodedString(withKey: accKey) ?? "")" + let accOrder = String(format: MVMCoreUIUtility.hardcodedString(withKey: "AccTabIndex") ?? "", indexPath.row + 1, tabsModel?.tabs.count ?? 0) + contentView.accessibilityLabel = "\(accLabel) \(accOrder)" + contentView.accessibilityHint = selected ? nil : MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint") + } +} + + diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index 8b69c590..d663a703 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -11,7 +11,7 @@ import UIKit public class TabsModel: MoleculeModelProtocol { public static var identifier: String = "tabs" public var backgroundColor: Color? - public var tabs: [LabelModel] + public var tabs: [TabItemModel] public var selectedColor = Color(uiColor: .mfTomatoRed()) // Must be capped to 0...(tabs.count - 1) @@ -25,13 +25,13 @@ public class TabsModel: MoleculeModelProtocol { case moleculeName } - public init(with tabs: [LabelModel]) { + public init(with tabs: [TabItemModel]) { self.tabs = tabs } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - tabs = try typeContainer.decode([LabelModel].self, forKey: .tabs) + tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) { selectedColor = color @@ -50,3 +50,33 @@ public class TabsModel: MoleculeModelProtocol { try container.encode(selectedIndex, forKey: .selectedIndex) } } + + + +public class TabItemModel: Codable { + var label: LabelModel + var action: ActionModelProtocol? + + init(label: LabelModel) { + self.label = label + } + + private enum CodingKeys: String, CodingKey { + case label + case action + } + + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + label = try typeContainer.decode(LabelModel.self, forKey: .label) + action = try typeContainer.decodeModelIfPresent(codingKey: .action) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModel(label, forKey: .label) + try container.encodeModelIfPresent(action, forKey: .action) + } + +} diff --git a/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift index 16794eb1..f9ed4243 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/TabsTableViewCell.swift @@ -12,7 +12,7 @@ import UIKit var tabsListItemModel: TabsListItemModel? { return listItemModel as? TabsListItemModel } - let tabs = TopTabbar(frame: .zero) + let tabs = Tabs(frame: .zero) var delegateObject: MVMCoreUIDelegateObject? var previousTabIndex = 0 @@ -22,7 +22,6 @@ import UIKit tabs.paddingBeforeFirstTab = false tabs.translatesAutoresizingMaskIntoConstraints = false tabs.delegate = self - tabs.datasource = self contentView.addSubview(tabs) NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: tabs, useMargins: true).values)) @@ -39,7 +38,9 @@ import UIKit public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) self.delegateObject = delegateObject - tabs.reloadData() + if let tabsModel = tabsListItemModel?.tabs { + tabs.set(with: tabsModel, delegateObject, additionalData) + } } public override func reset() { @@ -53,33 +54,22 @@ import UIKit } } -extension TabsTableViewCell: TopTabbarDelegate { - public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool { +extension TabsTableViewCell: TabsDelegate { + public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool { if let model = tabsListItemModel { - let molecules = model.molecules[topTabbar.selectedIndex] - delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: index < tabs.selectedIndex ? .right : .left) + let molecules = model.molecules[tabs.selectedIndex] + delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: indexPath.row < tabs.selectedIndex ? .right : .left) } previousTabIndex = tabs.selectedIndex return true } - public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) { - guard let model = tabsListItemModel, - let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) else { return } - let molecules = model.molecules[index] - delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right) - } -} - -extension TabsTableViewCell: TopTabbarDataSource { - public func number(ofTopTabbarItems topTabbar: TopTabbar) -> Int { - return tabsListItemModel?.tabs.tabs.count ?? 0 - } - - public func topTabbar(_ topTabbar: TopTabbar, titleForItemAt index: Int) -> String? { - guard let title = tabsListItemModel?.tabs.tabs[index].text else { - return "Select" + public func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) { + let index = indexPath.row + if let model = tabsListItemModel, index < model.molecules.count { + let molecules = model.molecules[index] + delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right) } - return title } } + From a34b3509a14ed15110d520baac518ae26d82260d Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Apr 2020 12:13:03 -0400 Subject: [PATCH 02/13] adding behavior logic for selecting by server. --- MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift | 9 +++++++-- .../Atomic/Atoms/TextFields/TextEntryFieldModel.swift | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index f95c918d..3dd2337b 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -308,13 +308,13 @@ import UIKit guard let model = model as? TextEntryFieldModel else { return } model.updateUI = { [weak self] in - MVMCoreDispatchUtility.performBlock(onMainThread: { + DispatchQueue.main.async { guard let self = self else { return } if self.isSelected { self.updateValidation(model.isValid ?? true) } - }) + } } self.delegateObject = delegateObject @@ -339,6 +339,11 @@ import UIKit uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate setupTextFieldToolbar() + + if isSelected && !model.wasInitiallySelected { + textEntryFieldModel?.wasInitiallySelected = true + startEditing() + } } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift index 491e9891..46d84484 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift @@ -31,6 +31,7 @@ public var enabledTextColor: Color = Color(uiColor: .mvmBlack) public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3) public var type: EntryType? + public var wasInitiallySelected: Bool = false //-------------------------------------------------- // MARK: - Keys From aca32d14f7bdd7a7e13a4b798061efec2ed9f4e2 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Apr 2020 14:48:20 -0400 Subject: [PATCH 03/13] going back to orgiinal func --- MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 3dd2337b..27ecf3ad 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -308,13 +308,13 @@ import UIKit guard let model = model as? TextEntryFieldModel else { return } model.updateUI = { [weak self] in - DispatchQueue.main.async { + MVMCoreDispatchUtility.performBlock(onMainThread: { guard let self = self else { return } if self.isSelected { self.updateValidation(model.isValid ?? true) } - } + }) } self.delegateObject = delegateObject From 0defd2916a218195cf05f43eb2953690893057cc Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Apr 2020 15:30:56 -0400 Subject: [PATCH 04/13] revised selectabel --- MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift | 8 +++++--- MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift | 1 + MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift | 3 +-- .../Atomic/Atoms/TextFields/TextEntryFieldModel.swift | 1 - 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 6bb82fe1..b1a3e43e 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -257,11 +257,13 @@ import UIKit if let isLocked = model.locked { self.isLocked = isLocked - } else if let isSelected = model.selected { - self.isSelected = isSelected + } else if (model.selected ?? false) && !model.wasInitiallySelected { + + model.wasInitiallySelected = true + self.isSelected = true } } - + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 115 } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index 337d847d..9be330a3 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -30,6 +30,7 @@ import Foundation public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? + public var wasInitiallySelected: Bool = false public var isValid: Bool? { didSet { updateUI?() } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 27ecf3ad..57c9dae9 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -340,8 +340,7 @@ import UIKit observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate setupTextFieldToolbar() - if isSelected && !model.wasInitiallySelected { - textEntryFieldModel?.wasInitiallySelected = true + if isSelected { startEditing() } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift index 46d84484..491e9891 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift @@ -31,7 +31,6 @@ public var enabledTextColor: Color = Color(uiColor: .mvmBlack) public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3) public var type: EntryType? - public var wasInitiallySelected: Bool = false //-------------------------------------------------- // MARK: - Keys From da097cc726fac622309e76892ae0842a4b42cbc7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Apr 2020 16:19:51 -0400 Subject: [PATCH 05/13] setting values back to model --- .../Atoms/TextFields/DigitEntryField.swift | 22 ++++++++++++++++++- .../Atomic/Atoms/TextFields/EntryField.swift | 4 ++++ .../Atoms/TextFields/EntryFieldModel.swift | 5 ++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 8ae4365f..bf20ecde 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -76,6 +76,10 @@ import UIKit public var digitBoxes: [DigitBox] = [] private var selectedDigitBox: DigitBox? + public var digitEntryModel: DigitEntryFieldModel? { + return model as? DigitEntryFieldModel + } + //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- @@ -234,6 +238,19 @@ import UIKit layoutIfNeeded() } + public override func reset() { + super.reset() + + accessibilityElements = nil + switchFieldsAutomatically = false + selectedDigitBox = nil + text = "" + digitBoxes.forEach { + $0.removeFromSuperview() + } + digitBoxes = [] + } + //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- @@ -326,7 +343,7 @@ import UIKit } public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - + guard let model = model as? DigitEntryFieldModel else { return } numberOfDigits = model.digits @@ -378,12 +395,14 @@ extension DigitEntryField { // One character, switch old value with new, select next textfield textField.text = string + digitEntryModel?.text = text selectNextDigitField(textField, clear: false) return false } else if replacementLength == 0 && oldLength == 1 { // Non empty cell, clear and stay. textField.text = "" + digitEntryModel?.text = text return false } @@ -410,6 +429,7 @@ extension DigitEntryField { if !switchFieldsAutomatically { textField.text = "" + digitEntryModel?.text = text } proprietorTextDelegate?.textFieldDidBeginEditing?(textField) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index b1a3e43e..33672685 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -60,6 +60,7 @@ import UIKit self.titleLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3 self.feedbackLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3 self.entryFieldContainer.isEnabled = enabled + self.entryFieldModel?.enabled = enabled } } @@ -69,6 +70,7 @@ import UIKit set (error) { self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback self.entryFieldContainer.showError = error + self.entryFieldModel?.showError = error } } @@ -77,6 +79,7 @@ import UIKit get { return entryFieldContainer.isLocked } set (locked) { self.entryFieldContainer.isLocked = locked + self.entryFieldModel?.locked = locked } } @@ -85,6 +88,7 @@ import UIKit get { return entryFieldContainer.isSelected } set (selected) { self.entryFieldContainer.isSelected = selected + self.entryFieldModel?.selected = selected } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index 9be330a3..e902ae22 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -10,7 +10,6 @@ import Foundation @objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol { - //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -24,6 +23,7 @@ import Foundation public var feedback: String? public var errorMessage: String? public var enabled: Bool = true + public var showError: Bool? public var locked: Bool? public var selected: Bool? public var text: String? @@ -52,6 +52,7 @@ import Foundation case errorMessage case locked case selected + case showError case text case fieldKey case groupName @@ -94,6 +95,7 @@ import Foundation text = try typeContainer.decodeIfPresent(String.self, forKey: .text) baseValue = text fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName } @@ -107,6 +109,7 @@ import Foundation try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(text, forKey: .text) try container.encodeIfPresent(locked, forKey: .locked) + try container.encodeIfPresent(showError, forKey: .showError) try container.encodeIfPresent(selected, forKey: .selected) try container.encodeIfPresent(errorMessage, forKey: .errorMessage) try container.encode(enabled, forKey: .enabled) From ac1c856124d35a3242b8cde4ed90bba906d8abd5 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 27 Apr 2020 10:10:25 -0400 Subject: [PATCH 06/13] improvements made to digit field --- .../Atomic/Atoms/TextFields/DigitBox.swift | 33 ++++++++----------- .../Atoms/TextFields/DigitEntryField.swift | 6 ++-- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitBox.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitBox.swift index 1134a80f..9e860116 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitBox.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitBox.swift @@ -24,7 +24,7 @@ import UIKit textField.setContentCompressionResistancePriority(.required, for: .vertical) textField.setContentCompressionResistancePriority(.required, for: .horizontal) textField.textAlignment = .center - textField.font = MFStyler.fontForTextField() + textField.font = Styler.Font.RegularBodyLarge.getFont() textField.keyboardType = .numberPad return textField }() @@ -48,11 +48,11 @@ import UIKit DispatchQueue.main.async { [weak self] in guard let self = self else { return } - self.borderStrokeColor = error ? .mfPumpkin() : .mfSilver() + self.borderStrokeColor = error ? .mvmOrange : .mvmCoolGray3 let barHeight: CGFloat = self.showError ? 4 : 1 self.bottomBar?.frame = CGRect(x: 0, y: self.bounds.height - barHeight, width: self.bounds.width, height: barHeight) - self.bottomBar?.backgroundColor = self.showError ? UIColor.mfPumpkin().cgColor : UIColor.black.cgColor + self.bottomBar?.backgroundColor = self.showError ? UIColor.mvmOrange.cgColor : UIColor.mvmBlack.cgColor self.setNeedsDisplay() self.layoutIfNeeded() @@ -97,29 +97,24 @@ import UIKit open override func setupView() { super.setupView() - - guard constraints.isEmpty else { return } - - translatesAutoresizingMaskIntoConstraints = false - backgroundColor = .clear - + addSubview(digitField) digitField.delegate = self digitField.didDeleteDelegate = self - NSLayoutConstraint.activate([ - digitField.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne), - digitField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: PaddingOne), - bottomAnchor.constraint(equalTo: digitField.bottomAnchor, constant: PaddingOne), - trailingAnchor.constraint(equalTo: digitField.trailingAnchor, constant: PaddingOne), - digitField.centerYAnchor.constraint(equalTo: centerYAnchor), - digitField.centerXAnchor.constraint(equalTo: centerXAnchor)]) - widthConstraint = widthAnchor.constraint(equalToConstant: DigitBox.size.width) widthConstraint?.isActive = true heightConstraint = heightAnchor.constraint(equalToConstant: DigitBox.size.height) heightConstraint?.isActive = true + NSLayoutConstraint.activate([ + digitField.topAnchor.constraint(equalTo: topAnchor, constant: Padding.Three), + digitField.leadingAnchor.constraint(equalTo: leadingAnchor), + bottomAnchor.constraint(equalTo: digitField.bottomAnchor, constant: Padding.Three), + trailingAnchor.constraint(equalTo: digitField.trailingAnchor), + digitField.centerYAnchor.constraint(equalTo: centerYAnchor) + ]) + if let bottomBar = bottomBar { layer.addSublayer(bottomBar) } @@ -146,7 +141,7 @@ import UIKit super.reset() backgroundColor = .clear - digitField.font = MFStyler.fontForTextField() + digitField.font = Styler.Font.RegularBodyLarge.getFont() } //-------------------------------------------------- @@ -186,7 +181,7 @@ import UIKit sizeObject?.performBlockBase(onSize: size) widthConstraint?.constant = width heightConstraint?.constant = height - digitField.font = MFFonts.mfFont55Rg(pointSize) + digitField.font = MFFonts.mfFontDSRegular(pointSize) previousSize = size } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index bf20ecde..50faacf9 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -228,14 +228,14 @@ import UIKit //-------------------------------------------------- @objc open override func updateView(_ size: CGFloat) { - super.updateView(size) - + entryFieldContainer.disableAllBorders = true if !self.digitBoxes.isEmpty { self.digitBoxes.forEach { $0.updateView(size) } } - layoutIfNeeded() + + super.updateView(size) } public override func reset() { From 6fec6b53f29ef37443ae046bdf146bd8eb129847 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Mon, 27 Apr 2020 13:00:42 -0400 Subject: [PATCH 07/13] update legacy font --- MVMCoreUI/Utility/MFFonts.m | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 533b3a87..99ad05c4 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -84,15 +84,19 @@ NSString * const DS55Rg = @"NHaasGroteskDSStd-55Rg"; + (nonnull UIFont *)mfFont75Bd:(CGFloat)size { - [self loadMVMFonts]; - UIFont *font = [UIFont fontWithName:DS75Bd size:size]; - return font ?: [UIFont boldSystemFontOfSize:size]; + if (size >= 15) { + return [MFFonts mfFontDSBold:size]; + } else { + return [MFFonts mfFontTXBold:size]; + } } + (nonnull UIFont *)mfFont55Rg:(CGFloat)size { - [self loadMVMFonts]; - UIFont *font = [UIFont fontWithName:DS55Rg size:size]; - return font ?: [UIFont systemFontOfSize:size]; + if (size >= 15) { + return [MFFonts mfFontDSRegular:size]; + } else { + return [MFFonts mfFontTXRegular:size]; + } } + (nullable UIFont *)mfFontOcratxt:(CGFloat)size { From 320976e5ae836762535bc6fb7b360b838030e40e Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Mon, 27 Apr 2020 14:09:37 -0400 Subject: [PATCH 08/13] weak delegate --- MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift | 2 +- .../Atomic/Molecules/HorizontalCombinationViews/Tabs.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 6bb82fe1..03454d06 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -41,7 +41,7 @@ import UIKit // MARK: - Delegate //-------------------------------------------------- - weak var delegateObject: MVMCoreUIDelegateObject? + var delegateObject: MVMCoreUIDelegateObject? //-------------------------------------------------- // MARK: - Stored Properties diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index d49cd414..6caa6a03 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -32,7 +32,7 @@ import UIKit var bottomLineWidthConstraint: NSLayoutConstraint? //delegate - public var delegate: TabsDelegate? + weak public var delegate: TabsDelegate? //control var public var heightConstraint: NSLayoutConstraint? @@ -93,7 +93,7 @@ import UIKit bottomScrollView.delegate = self addSubview(bottomScrollView) bottomScrollView.addSubview(bottomContentView) - bottomLine.backgroundColor = .mfTomatoRed() + bottomLine.backgroundColor = .mvmRed bottomContentView.addSubview(bottomLine) bringSubviewToFront(bottomScrollView) } From 3b23101710b802566ad4492832e6c8a4f943fa27 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Mon, 27 Apr 2020 15:22:40 -0400 Subject: [PATCH 09/13] update tabs model --- .../HorizontalCombinationViews/Tabs.swift | 53 ++++++------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index 6caa6a03..dc8b9cae 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -31,6 +31,8 @@ import UIKit var bottomLineLeftConstraint: NSLayoutConstraint? var bottomLineWidthConstraint: NSLayoutConstraint? + private var widthLabel = Label() + //delegate weak public var delegate: TabsDelegate? @@ -186,11 +188,14 @@ extension Tabs: UICollectionViewDelegateFlowLayout { return CGSize(width: getLabelWidth(labelModel).width, height: cellHeight) } + //pre calculate the width of the collection cell + //when user select tabs, it will reload related collectionview, if we use autosize, it would relayout the width, need to keep the cell width constant. func getLabelWidth(_ labelModel: LabelModel?) -> CGSize { guard let labelModel = labelModel else { return .zero} - let label = Label() - label.set(with: labelModel, nil, nil) - return label.intrinsicContentSize + widthLabel.set(with: labelModel, nil, nil) + let cgSize = widthLabel.intrinsicContentSize + widthLabel.reset() + return cgSize } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { @@ -244,6 +249,10 @@ extension Tabs: UICollectionViewDelegateFlowLayout { extension Tabs: UIScrollViewDelegate { public func scrollViewDidScroll(_ scrollView: UIScrollView) { + /*bottomScrollview is subview of self, it's not belongs to collectionview. + When collectionview is scrolling, bottomScrollView will stay without moving + Adding collectionview's offset to bottomScrollView, will make the bottomScrollview looks like scrolling with the selected tab item. + */ guard let offsetX = collectionView?.contentOffset.x else { return } bottomScrollView.setContentOffset(CGPoint(x: offsetX, y: bottomScrollView.contentOffset.y), animated: false) } @@ -272,46 +281,14 @@ extension Tabs { animationBlock() } } - - public func progress(fromIndex: Int, toIndex: Int, progressPercentage percent: CGFloat) { - guard let _ = collectionView else { return } - MVMCoreDispatchUtility.performBlock(onMainThread: { - self.setBottomLine(fromIndex: IndexPath(row: fromIndex, section: 0), toIndex: IndexPath(row: toIndex, section: 0), percent: percent) - }) - } - - func setBottomLine(fromIndex: IndexPath, toIndex: IndexPath, percent: CGFloat) { - guard let fromCell = collectionView?.cellForItem(at: fromIndex) as? TabItemCell, let toCell = collectionView?.cellForItem(at: toIndex) as? TabItemCell else { - return - } - let fromWidth = getLabelWidth(fromCell.labelModel).width - let toWidth = getLabelWidth(toCell.labelModel).width - let finalWidth = (toWidth - fromWidth) * percent + fromWidth - bottomLineWidthConstraint?.constant = finalWidth - let xDifference = toCell.frame.origin.x - fromCell.frame.origin.x - let finalX = xDifference * percent + fromCell.frame.origin.x - bottomLineLeftConstraint?.constant = finalX - bottomContentView.layoutIfNeeded() - } } - - -@objcMembers public class TabItemCell: UICollectionViewCell { +@objcMembers public class TabItemCell: CollectionViewCell { public let label = Label() public var labelModel: LabelModel? - override init(frame: CGRect) { - super.init(frame: frame) - setupView() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - setupView() - } - - func setupView() { + public override func setupView() { + super.setupView() contentView.addSubview(label) NSLayoutConstraint.constraintPinSubview(label, pinTop: false, pinBottom: false, pinLeft: true, pinRight: true) label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true From af3c373d0a3cad0f7dc526150aa54ab0c31484f1 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Mon, 27 Apr 2020 16:38:08 -0400 Subject: [PATCH 10/13] update acc before do animation --- MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m index 6fc7121f..bc45656e 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m @@ -301,11 +301,12 @@ [weakSelf.viewToLayout layoutIfNeeded]; }; + //accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed + weakSelf.accessibilityElements = @[weakSelf.buttonView]; + weakSelf.shortView.isAccessibilityElement = NO; + weakSelf.buttonView.label.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"],weakSelf.buttonView.label.accessibilityLabel]; + void(^completion)(void) = ^(void) { - //accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed - weakSelf.accessibilityElements = @[weakSelf.buttonView]; - weakSelf.shortView.isAccessibilityElement = NO; - weakSelf.buttonView.label.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"],weakSelf.buttonView.label.accessibilityLabel]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf.buttonView.label); [operation markAsFinished]; }; From 587b3bb6f3381fe11f2d478bb071046f3feeb59c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 28 Apr 2020 11:08:44 -0400 Subject: [PATCH 11/13] BGImage --- MVMCoreUI.xcodeproj/project.pbxproj | 46 +++++++++------- MVMCoreUI/Atomic/MoleculeObjectMapping.swift | 1 + .../Molecules/Items/ListItemModel.swift | 7 ++- .../OtherContainers/BGImageMolecule.swift | 25 +++++++++ .../BGImageMoleculeModel.swift | 52 +++++++++++++++++++ .../ModuleMolecule.swift | 0 .../ModuleMoleculeModel.swift | 0 .../OtherContainers}/MoleculeContainer.swift | 0 .../MoleculeContainerModel.swift | 2 +- .../MoleculeContainerProtocol.swift | 0 .../{ => OtherContainers}/Scroller.swift | 0 .../{ => OtherContainers}/ScrollerModel.swift | 0 MVMCoreUI/BaseClasses/TableViewCell.swift | 2 + .../Views/{Container => }/Container.swift | 0 .../{Container => }/ContainerHelper.swift | 0 .../{Container => }/ContainerModel.swift | 0 .../{Container => }/ContainerProtocol.swift | 0 17 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMolecule.swift create mode 100644 MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMoleculeModel.swift rename MVMCoreUI/Atomic/Molecules/{ => OtherContainers}/ModuleMolecule.swift (100%) rename MVMCoreUI/Atomic/Molecules/{ => OtherContainers}/ModuleMoleculeModel.swift (100%) rename MVMCoreUI/{Containers/Views => Atomic/Molecules/OtherContainers}/MoleculeContainer.swift (100%) rename MVMCoreUI/{Containers/Views => Atomic/Molecules/OtherContainers}/MoleculeContainerModel.swift (92%) rename MVMCoreUI/{Containers/Views => Atomic/Molecules/OtherContainers}/MoleculeContainerProtocol.swift (100%) rename MVMCoreUI/Atomic/Molecules/{ => OtherContainers}/Scroller.swift (100%) rename MVMCoreUI/Atomic/Molecules/{ => OtherContainers}/ScrollerModel.swift (100%) rename MVMCoreUI/Containers/Views/{Container => }/Container.swift (100%) rename MVMCoreUI/Containers/Views/{Container => }/ContainerHelper.swift (100%) rename MVMCoreUI/Containers/Views/{Container => }/ContainerModel.swift (100%) rename MVMCoreUI/Containers/Views/{Container => }/ContainerProtocol.swift (100%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2bee8ecf..1f45fe14 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -277,6 +277,8 @@ D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; }; D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; }; D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; + D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253BB9B245874F8002DE544 /* BGImageMolecule.swift */; }; + D253BB9E2458751F002DE544 /* BGImageMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253BB9D2458751F002DE544 /* BGImageMoleculeModel.swift */; }; D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; }; D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; }; D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105823D0A92900764D80 /* ContainerProtocol.swift */; }; @@ -730,6 +732,8 @@ D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = ""; }; D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = ""; }; D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; + D253BB9B245874F8002DE544 /* BGImageMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageMolecule.swift; sourceTree = ""; }; + D253BB9D2458751F002DE544 /* BGImageMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageMoleculeModel.swift; sourceTree = ""; }; D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = ""; }; D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = ""; }; D260105823D0A92900764D80 /* ContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerProtocol.swift; sourceTree = ""; }; @@ -1017,10 +1021,10 @@ isa = PBXGroup; children = ( 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */, - D29E28DE23D740FC00ACEA85 /* Container */, - D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */, - 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */, - D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, + D260105823D0A92900764D80 /* ContainerProtocol.swift */, + D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */, + 014AA72223C501E2006F3E93 /* ContainerModel.swift */, + D243859823A16B1800332775 /* Container.swift */, ); path = Views; sourceTree = ""; @@ -1483,6 +1487,22 @@ path = TwoColumn; sourceTree = ""; }; + D253BB9A24587023002DE544 /* OtherContainers */ = { + isa = PBXGroup; + children = ( + D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */, + 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */, + D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, + D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */, + D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, + 012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */, + D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, + D253BB9D2458751F002DE544 /* BGImageMoleculeModel.swift */, + D253BB9B245874F8002DE544 /* BGImageMolecule.swift */, + ); + path = OtherContainers; + sourceTree = ""; + }; D260105723CF9CC500764D80 /* Doughnut */ = { isa = PBXGroup; children = ( @@ -1606,6 +1626,7 @@ D29DF10E21E67A77003B2FB9 /* Molecules */ = { isa = PBXGroup; children = ( + D253BB9A24587023002DE544 /* OtherContainers */, D22B38E923F4E07800490EF6 /* DesignedComponents */, D22479912316A9EF003FCCF9 /* Items */, D224798F2316A99F003FCCF9 /* LeftRightViews */, @@ -1617,10 +1638,6 @@ D2A514662213885800345BFB /* MoleculeHeaderView.swift */, 012A88EB238F084D00FE3DA1 /* FooterModel.swift */, D274CA322236A78900B01B62 /* FooterView.swift */, - 012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */, - D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, - D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */, - D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, D260105723CF9CC500764D80 /* Doughnut */, D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */, ); @@ -1916,17 +1933,6 @@ path = StringAndMoleculeStack; sourceTree = ""; }; - D29E28DE23D740FC00ACEA85 /* Container */ = { - isa = PBXGroup; - children = ( - 014AA72223C501E2006F3E93 /* ContainerModel.swift */, - D260105823D0A92900764D80 /* ContainerProtocol.swift */, - D243859823A16B1800332775 /* Container.swift */, - D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */, - ); - path = Container; - sourceTree = ""; - }; D2B18B7D236090D500A9AEDC /* BaseClasses */ = { isa = PBXGroup; children = ( @@ -2377,6 +2383,7 @@ AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */, 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */, 8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */, + D253BB9E2458751F002DE544 /* BGImageMoleculeModel.swift in Sources */, 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */, BBAA4F03243D8E3B005AAD5F /* RadioBoxes.swift in Sources */, @@ -2400,6 +2407,7 @@ D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */, 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */, + D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */, AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */, diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index b8ffb9e6..58ad387c 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -125,6 +125,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: BGImageMolecule.self, viewModelClass: BGImageMoleculeModel.self) // Other Molecules MoleculeObjectMapping.shared()?.register(viewClass: DoughnutChartView.self, viewModelClass: DoughnutChartModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift index 8fdb4d77..81b896f0 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift @@ -45,8 +45,11 @@ import Foundation if useVerticalMargins == nil { useVerticalMargins = true } - if style == nil { - style = "standard" + if topPadding == nil { + topPadding = 24 + } + if bottomPadding == nil { + bottomPadding = 24 } } diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMolecule.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMolecule.swift new file mode 100644 index 00000000..89eedfe3 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMolecule.swift @@ -0,0 +1,25 @@ +// +// BGImageMolecule.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/28/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class BGImageMolecule: MoleculeContainer { + + let image = MFLoadImageView(pinnedEdges: .all) + + public override func setupView() { + super.setupView() + insertSubview(image, at: 0) + NSLayoutConstraint.constraintPinSubview(toSuperview: image) + } + + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + image.setOptional(with: (model as? BGImageMoleculeModel)?.image, delegateObject, additionalData) + super.set(with: model, delegateObject, additionalData) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMoleculeModel.swift new file mode 100644 index 00000000..83b5931d --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMoleculeModel.swift @@ -0,0 +1,52 @@ +// +// BGImageMoleculeModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/28/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class BGImageMoleculeModel: MoleculeContainerModel { + public override class var identifier: String { + return "bgImageContainer" + } + public var image: ImageViewModel + + open override func setDefaults() { + if useHorizontalMargins == nil { + useHorizontalMargins = true + } + if useVerticalMargins == nil { + useVerticalMargins = true + } + if topPadding == nil { + topPadding = PaddingDefaultVerticalSpacing3 + } + if bottomPadding == nil { + bottomPadding = PaddingDefaultVerticalSpacing3 + } + } + + private enum CodingKeys: String, CodingKey { + case image + } + + public init(_ image: ImageViewModel, molecule: MoleculeModelProtocol) { + self.image = image + super.init(with: molecule) + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + image = try typeContainer.decode(ImageViewModel.self, forKey:.image) + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(image, forKey: .image) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/ModuleMolecule.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/ModuleMolecule.swift rename to MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMolecule.swift diff --git a/MVMCoreUI/Atomic/Molecules/ModuleMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/ModuleMoleculeModel.swift rename to MVMCoreUI/Atomic/Molecules/OtherContainers/ModuleMoleculeModel.swift diff --git a/MVMCoreUI/Containers/Views/MoleculeContainer.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift similarity index 100% rename from MVMCoreUI/Containers/Views/MoleculeContainer.swift rename to MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainer.swift diff --git a/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift similarity index 92% rename from MVMCoreUI/Containers/Views/MoleculeContainerModel.swift rename to MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift index 86693823..30b5e95e 100644 --- a/MVMCoreUI/Containers/Views/MoleculeContainerModel.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerModel.swift @@ -8,7 +8,7 @@ import Foundation -public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol { +open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol { public class var identifier: String { return "container" } diff --git a/MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift similarity index 100% rename from MVMCoreUI/Containers/Views/MoleculeContainerProtocol.swift rename to MVMCoreUI/Atomic/Molecules/OtherContainers/MoleculeContainerProtocol.swift diff --git a/MVMCoreUI/Atomic/Molecules/Scroller.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/Scroller.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/Scroller.swift rename to MVMCoreUI/Atomic/Molecules/OtherContainers/Scroller.swift diff --git a/MVMCoreUI/Atomic/Molecules/ScrollerModel.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/ScrollerModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Molecules/ScrollerModel.swift rename to MVMCoreUI/Atomic/Molecules/OtherContainers/ScrollerModel.swift diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index 30f9df22..b549b6d0 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -148,6 +148,7 @@ import UIKit preservesSuperviewLayoutMargins = false contentView.insetsLayoutMarginsFromSafeArea = false contentView.preservesSuperviewLayoutMargins = false + styleStandard() } //TODO: ModelProtocol, Change to model @@ -183,6 +184,7 @@ import UIKit open func reset() { molecule?.reset() + styleStandard() backgroundColor = .white } diff --git a/MVMCoreUI/Containers/Views/Container/Container.swift b/MVMCoreUI/Containers/Views/Container.swift similarity index 100% rename from MVMCoreUI/Containers/Views/Container/Container.swift rename to MVMCoreUI/Containers/Views/Container.swift diff --git a/MVMCoreUI/Containers/Views/Container/ContainerHelper.swift b/MVMCoreUI/Containers/Views/ContainerHelper.swift similarity index 100% rename from MVMCoreUI/Containers/Views/Container/ContainerHelper.swift rename to MVMCoreUI/Containers/Views/ContainerHelper.swift diff --git a/MVMCoreUI/Containers/Views/Container/ContainerModel.swift b/MVMCoreUI/Containers/Views/ContainerModel.swift similarity index 100% rename from MVMCoreUI/Containers/Views/Container/ContainerModel.swift rename to MVMCoreUI/Containers/Views/ContainerModel.swift diff --git a/MVMCoreUI/Containers/Views/Container/ContainerProtocol.swift b/MVMCoreUI/Containers/Views/ContainerProtocol.swift similarity index 100% rename from MVMCoreUI/Containers/Views/Container/ContainerProtocol.swift rename to MVMCoreUI/Containers/Views/ContainerProtocol.swift From b850bb844c59c9546c28220fc8ca5978f55723e2 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 28 Apr 2020 11:16:51 -0400 Subject: [PATCH 12/13] open --- .../Atomic/Molecules/OtherContainers/BGImageMolecule.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMolecule.swift b/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMolecule.swift index 89eedfe3..385df5d3 100644 --- a/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMolecule.swift +++ b/MVMCoreUI/Atomic/Molecules/OtherContainers/BGImageMolecule.swift @@ -12,13 +12,13 @@ open class BGImageMolecule: MoleculeContainer { let image = MFLoadImageView(pinnedEdges: .all) - public override func setupView() { + open override func setupView() { super.setupView() insertSubview(image, at: 0) NSLayoutConstraint.constraintPinSubview(toSuperview: image) } - public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { image.setOptional(with: (model as? BGImageMoleculeModel)?.image, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData) } From e5ab2545793afe57977154e51bb18b2e30cc32cb Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 28 Apr 2020 14:14:26 -0400 Subject: [PATCH 13/13] revised how fields clear themselves --- .../Atomic/Atoms/TextFields/DigitEntryField.swift | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 50faacf9..628c7cde 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -35,6 +35,7 @@ import UIKit digitBoxes.append(newDigitBox) } + self.digitBoxes.forEach { $0.removeFromSuperview() } self.digitBoxes = digitBoxes guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize() else { return } @@ -228,7 +229,7 @@ import UIKit //-------------------------------------------------- @objc open override func updateView(_ size: CGFloat) { - + entryFieldContainer.disableAllBorders = true if !self.digitBoxes.isEmpty { @@ -245,10 +246,7 @@ import UIKit switchFieldsAutomatically = false selectedDigitBox = nil text = "" - digitBoxes.forEach { - $0.removeFromSuperview() - } - digitBoxes = [] + digitBoxes.forEach { $0.digitField.text = "" } } //-------------------------------------------------- @@ -358,7 +356,7 @@ import UIKit $0.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate, action: #selector(observingDelegate.dismissFieldInput)) } - + super.set(with: model, delegateObject, additionalData) }