diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index e6eca162..4b0faceb 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -496,6 +496,8 @@ D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; }; D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; }; D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; }; + D2EAC0A02541EFFB00AA9495 /* LineDecorationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EAC09F2541EFFB00AA9495 /* LineDecorationView.swift */; }; + D2EAC0A42541F00F00AA9495 /* CarouselCollectionLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EAC0A32541F00F00AA9495 /* CarouselCollectionLayout.swift */; }; D2EC7BD52527B7A600F540AF /* MoleculeSectionHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */; }; D2EC7BD92527B7CF00F540AF /* MoleculeSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */; }; D2EC7BDD2527B83700F540AF /* SectionHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */; }; @@ -1007,6 +1009,8 @@ D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = ""; }; D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.swift; sourceTree = ""; }; D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = ""; }; + D2EAC09F2541EFFB00AA9495 /* LineDecorationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineDecorationView.swift; sourceTree = ""; }; + D2EAC0A32541F00F00AA9495 /* CarouselCollectionLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselCollectionLayout.swift; sourceTree = ""; }; D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionHeaderModel.swift; sourceTree = ""; }; D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionHeader.swift; sourceTree = ""; }; D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderFooterView.swift; sourceTree = ""; }; @@ -1413,12 +1417,11 @@ D22479902316A9CB003FCCF9 /* Organisms */ = { isa = PBXGroup; children = ( + D2EAC09E2541EFE200AA9495 /* Carousel */, D260105A23D0BB7100764D80 /* StackModelProtocol.swift */, D260106423D0CEA700764D80 /* StackModel.swift */, D260105C23D0BCD400764D80 /* Stack.swift */, D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */, - 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */, - D2A6390022CBB1820052ED1F /* Carousel.swift */, ); path = Organisms; sourceTree = ""; @@ -2142,6 +2145,17 @@ path = TopNotification; sourceTree = ""; }; + D2EAC09E2541EFE200AA9495 /* Carousel */ = { + isa = PBXGroup; + children = ( + 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */, + D2A6390022CBB1820052ED1F /* Carousel.swift */, + D2EAC09F2541EFFB00AA9495 /* LineDecorationView.swift */, + D2EAC0A32541F00F00AA9495 /* CarouselCollectionLayout.swift */, + ); + path = Carousel; + sourceTree = ""; + }; D2EC7BD22527A1E400F540AF /* HeadersAndFooters */ = { isa = PBXGroup; children = ( @@ -2326,6 +2340,7 @@ 0A6682B5243769C700AD3CA1 /* TextView.swift in Sources */, D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */, D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */, + D2EAC0A02541EFFB00AA9495 /* LineDecorationView.swift in Sources */, 0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */, AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */, AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */, @@ -2573,6 +2588,7 @@ 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */, BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */, 8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */, + D2EAC0A42541F00F00AA9495 /* CarouselCollectionLayout.swift in Sources */, AAE7270E24AC8B9300A3ED0E /* HeadersH2CaretLink.swift in Sources */, 0AD93A9F24C0AA5100E56A97 /* ImageView.swift in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Organisms/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift similarity index 99% rename from MVMCoreUI/Atomic/Organisms/Carousel.swift rename to MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index 1abab6e0..7f088b4c 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -16,11 +16,10 @@ public protocol CarouselPageControlProtocol { func scrollViewDidScroll(_ collectionView: UICollectionView) } - open class Carousel: View { public let collectionView: CollectionView = { - let layout = UICollectionViewFlowLayout() + let layout = CarouselCollectionLayout() layout.scrollDirection = .horizontal layout.minimumInteritemSpacing = 0 layout.minimumLineSpacing = 0 @@ -150,8 +149,9 @@ open class Carousel: View { guard let carouselModel = model as? CarouselModel else { return } accessibilityLabel = carouselModel.accessibilityText collectionView.backgroundColor = backgroundColor - collectionView.layer.borderColor = backgroundColor?.cgColor + collectionView.layer.borderColor = UIColor.black.cgColor collectionView.layer.borderWidth = (carouselModel.border ?? false) ? 1 : 0 + (collectionView.collectionViewLayout as? CarouselCollectionLayout)?.useLines = (carouselModel.border ?? false) backgroundColor = .white (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing = carouselModel.spacing ?? 0 @@ -375,7 +375,7 @@ extension Carousel: UICollectionViewDataSource { open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return molecules?.count ?? 0 } - + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let molecule = molecules?[indexPath.row], let moleculeInfo = getMoleculeInfo(with: molecule, delegateObject: nil) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselCollectionLayout.swift b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselCollectionLayout.swift new file mode 100644 index 00000000..09841c50 --- /dev/null +++ b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselCollectionLayout.swift @@ -0,0 +1,53 @@ +// +// CarouselCollectionLayout.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/22/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class CarouselCollectionLayout: UICollectionViewFlowLayout { + open var useLines = false + + public override init() { + super.init() + registerViews() + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + registerViews() + } + + open func registerViews() { + register(LineDecorationView.self, forDecorationViewOfKind: LineDecorationView.elementKind) + } + + open override func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { + // Lines are added between each item + guard useLines, + elementKind == LineDecorationView.elementKind else { return nil } + let attributes = UICollectionViewLayoutAttributes(forDecorationViewOfKind: elementKind, with: indexPath) + let itemFrame = layoutAttributesForItem(at: indexPath)?.frame ?? .zero + let width: CGFloat = 1.0 + attributes.frame = CGRect(x: itemFrame.maxX + ((minimumLineSpacing - width) / 2.0), y: 0, width: width, height: itemFrame.height) + return attributes + } + + open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { + guard let allAttributes = super.layoutAttributesForElements(in: rect) else { return nil } + guard useLines else { return allAttributes } + + // Add line decorators. + var newAttributes = allAttributes + allAttributes.forEach { (attributes) in + guard attributes.representedElementCategory == .cell, + let lineAttributes = layoutAttributesForDecorationView(ofKind: LineDecorationView.elementKind, at: attributes.indexPath), + rect.intersects(lineAttributes.frame) else { return } + newAttributes.append(lineAttributes) + } + return newAttributes + } +} diff --git a/MVMCoreUI/Atomic/Organisms/CarouselModel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift similarity index 100% rename from MVMCoreUI/Atomic/Organisms/CarouselModel.swift rename to MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/LineDecorationView.swift b/MVMCoreUI/Atomic/Organisms/Carousel/LineDecorationView.swift new file mode 100644 index 00000000..465f2219 --- /dev/null +++ b/MVMCoreUI/Atomic/Organisms/Carousel/LineDecorationView.swift @@ -0,0 +1,20 @@ +// +// LineDecorationView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/22/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +public class LineDecorationView : UICollectionReusableView { + static public let elementKind = "line" + + public override init(frame: CGRect) { + super.init(frame:frame) + backgroundColor = .black + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } +}