Skip to content

Commit

Permalink
Merge branch 'master' of github.com:FireHawkDigital/CardParts into da…
Browse files Browse the repository at this point in the history
…rkmode

* 'master' of github.com:FireHawkDigital/CardParts: (23 commits)
  spacing formatting in podspec
  Bumping version to 3.1.3
  Update CardPartHistogramView.swift
  Bmping version to 3.1.2
  Fix wrong layout on iPad modal presentation
  Update CardParts.podspec
  Update CardPartHistogramView.swift (intuit#253)
  Bump podspec (intuit#251)
  Adding dynamic support of height in CardPartPagedView (intuit#244)
  Bump podspec (intuit#250)
  Update RxCocoa/Swift/DataSource/Gesture (intuit#243)
  Update CardParts.podspec (intuit#241)
  Card Parts Bottom Sheet View Controller (intuit#240)
  Update CardParts.podspec (intuit#238)
  Card part attributed text patch (intuit#237)
  Create card part switch component (intuit#236)
  Add loadspecificcards to README
  Update CardParts.podspec (intuit#233)
  Adding a capability to load specific cards added to collection view (intuit#232)
  Update CardParts.podspec (intuit#231)
  ...
  • Loading branch information
bevbomb committed Sep 2, 2020
2 parents 45fabd5 + 1a2965e commit 1bffda3
Show file tree
Hide file tree
Showing 25 changed files with 2,231 additions and 52 deletions.
11 changes: 5 additions & 6 deletions CardParts.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Pod::Spec.new do |s|
s.name = 'CardParts'
s.version = '2.24.1'
s.version = '3.1.3'
s.platform = :ios
s.summary = 'iOS Card UI framework.'

Expand All @@ -28,9 +28,8 @@ CardParts is an iOS Card UI framework that uses MVVM and automatic data binding
s.swift_version = '5.0'
s.source_files = 'CardParts/src/**/*'

s.dependency 'RxSwift', '~> 4.5'
s.dependency 'RxCocoa', '~> 4.5'
s.dependency 'RxDataSources', '~> 3.1'
s.dependency 'RxGesture', '~> 2.2'

s.dependency 'RxSwift', '~> 5.0'
s.dependency 'RxCocoa', '~> 5.0'
s.dependency 'RxDataSources', '~> 4.0'
s.dependency 'RxGesture', '~> 3.0'
end
30 changes: 10 additions & 20 deletions CardParts/src/Classes/Card Parts/CardPartAttributedTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -208,30 +208,20 @@ public class CardPartAttributedTextView: UIView, CardPartView {
func setDefaultsForType(_ type: CardPartAttributedTextType) {
switch type {
case .small:
DispatchQueue.main.async { [weak self] in
self?.font = CardParts.theme.smallAttributedTextFont
self?.textColor = CardParts.theme.smallAttributedTextColor
}
font = CardParts.theme.smallAttributedTextFont
textColor = CardParts.theme.smallAttributedTextColor
case .normal:
DispatchQueue.main.async { [weak self] in
self?.font = CardParts.theme.normalAttributedTextFont
self?.textColor = CardParts.theme.normalAttributedTextColor
}
font = CardParts.theme.normalAttributedTextFont
textColor = CardParts.theme.normalAttributedTextColor
case .title:
DispatchQueue.main.async { [weak self] in
self?.font = CardParts.theme.titleAttributedTextFont
self?.textColor = CardParts.theme.titleAttributedTextColor
}
font = CardParts.theme.titleAttributedTextFont
textColor = CardParts.theme.titleAttributedTextColor
case .header:
DispatchQueue.main.async { [weak self] in
self?.font = CardParts.theme.headerAttributedTextFont
self?.textColor = CardParts.theme.headerAttributedTextColor
}
font = CardParts.theme.headerAttributedTextFont
textColor = CardParts.theme.headerAttributedTextColor
case .detail:
DispatchQueue.main.async { [weak self] in
self?.font = CardParts.theme.detailAttributedTextFont
self?.textColor = CardParts.theme.detailAttributedTextColor
}
font = CardParts.theme.detailAttributedTextFont
textColor = CardParts.theme.detailAttributedTextColor
}
}

Expand Down
66 changes: 46 additions & 20 deletions CardParts/src/Classes/Card Parts/CardPartHistogramView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ public enum HistogramLine {
case lines(bottom:Bool,middle:Bool,top:Bool)
}

public enum Distribution {
case fill
case equalSpacing
}

public class CardPartHistogramView: UIView, CardPartView {

public var margins: UIEdgeInsets = CardParts.theme.cardPartMargins
Expand All @@ -27,24 +32,38 @@ public class CardPartHistogramView: UIView, CardPartView {
private var animated:Bool = false

/// width of each of the bar item
public var width:CGFloat = 20 {
didSet {
setupChartPresenter()
}
}
public var width:CGFloat = 20

/// spacing between the items
public var spacing:CGFloat = 10 {
public var spacing:CGFloat = 10

/// top space of histogram
public var topSpace:CGFloat = 40

/// bottom space of histogram
public var bottomSpace:CGFloat = 40

/// corner radius of each of the bar item
public var cornerRadius:CGFloat = 4

/// distribution of histogram
public var distribution:Distribution = .fill

/// should show horizontal lines
public var shouldShowHorizontalLines:Bool = false

/// is scroll enabled
public var isScrollEnabled:Bool = true {
didSet {
setupChartPresenter()
scrollView.isScrollEnabled = isScrollEnabled
}
}

/// shows all three lines of the bar graph
public var histogramLines:HistogramLine = HistogramLine.lines(bottom: true, middle: true, top: true)

/// Responsible for compute all positions and frames of all elements represent on the bar chart
private var presenter:CardPartBarChart = CardPartBarChart(barWidth: 20, space: 10)
private var presenter:CardPartBarChart = CardPartBarChart(barWidth: 20, space: 10, topSpace: 40, bottomSpace: 40)

/// height for the histogram to render
public var intrinsicHeight:CGFloat = 450
Expand All @@ -57,7 +76,9 @@ public class CardPartHistogramView: UIView, CardPartView {
scrollView.contentSize = CGSize(width: presenter.computeContentWidth(), height: self.intrinsicHeight)
mainLayer.frame = CGRect(x: 0, y: 0, width: scrollView.contentSize.width, height: scrollView.contentSize.height)

showHorizontalLines()
if shouldShowHorizontalLines {
showHorizontalLines()
}

for (index, entry) in barEntries.enumerated() {
showEntry(index: index, entry: entry, animated: animated, oldEntry: oldValue.safeValue(at: index))
Expand Down Expand Up @@ -89,17 +110,14 @@ public class CardPartHistogramView: UIView, CardPartView {
])
}

/// configures width and spacing betweent the bar items
private func setupChartPresenter() {
self.presenter = CardPartBarChart(barWidth: self.width, space: self.spacing)
}

override public func layoutSubviews() {
super.layoutSubviews()
self.updateDataEntries(dataEntries: presenter.dataEntries, animated: false)
}

public func updateDataEntries(dataEntries: [DataEntry], animated: Bool) {
let space = self.distribution == .equalSpacing ? computeSpacing(dataEntries: dataEntries) : self.spacing
self.presenter = CardPartBarChart(barWidth: self.width, space: space, topSpace: self.topSpace, bottomSpace: self.bottomSpace)
self.animated = animated
self.presenter.dataEntries = dataEntries
self.barEntries = self.presenter.computeBarEntries(viewHeight: self.frame.height)
Expand All @@ -110,7 +128,7 @@ public class CardPartHistogramView: UIView, CardPartView {
let cgColor = entry.data.color.cgColor

// Show the main bar
mainLayer.addRectangleLayer(frame: entry.barFrame, color: cgColor, animated: animated, oldFrame: oldEntry?.barFrame, cornerRadius: 4.0)
mainLayer.addRectangleLayer(frame: entry.barFrame, color: cgColor, animated: animated, oldFrame: oldEntry?.barFrame, cornerRadius: self.cornerRadius)
}

private func showHorizontalLines() {
Expand Down Expand Up @@ -139,7 +157,13 @@ public class CardPartHistogramView: UIView, CardPartView {
mainLayer.addLineLayer(lineSegment: line.segment, color: UIColor.darkGray.cgColor, width: line.width, isDashed: line.isDashed, animated: false, oldSegment: nil)
}
}
}
}

func computeSpacing(dataEntries: [DataEntry]) -> CGFloat {
scrollView.layoutIfNeeded()
let divideCount = dataEntries.count > 1 ? (CGFloat(dataEntries.count) - 1) : 1
return (scrollView.bounds.width - (CGFloat(dataEntries.count) * width)) / divideCount
}
}

/// configures bar width , spacing , data entries and of each of those.
Expand All @@ -151,19 +175,21 @@ public class CardPartBarChart {
public var space:CGFloat = 10

/// space at the bottom of the bar to show the title
private let bottomSpace: CGFloat = 40.0
public var bottomSpace: CGFloat = 40.0

/// space at the top of each bar to show the value
private let topSpace: CGFloat = 40.0
public var topSpace: CGFloat = 40.0

/// Line padding
private var linePadding:CGFloat = 6.5

var dataEntries: [DataEntry] = []

init(barWidth:CGFloat, space: CGFloat) {
init(barWidth:CGFloat, space: CGFloat, topSpace: CGFloat, bottomSpace: CGFloat) {
self.barWidth = barWidth
self.space = space
self.topSpace = topSpace
self.bottomSpace = bottomSpace
}

/// width of the entire bars
Expand All @@ -175,7 +201,7 @@ public class CardPartBarChart {
var result:[CardPartBarEntry] = []
for (index, entry) in dataEntries.enumerated() {
let entryHeight = CGFloat(entry.height) * (viewHeight - bottomSpace - topSpace)
let xPosition:CGFloat = space + CGFloat(index) * (barWidth + space)
let xPosition:CGFloat = CGFloat(index) * (barWidth + space)
let yPosition:CGFloat = viewHeight - bottomSpace - entryHeight
let origin = CGPoint(x: xPosition, y: yPosition)
let barEntry = CardPartBarEntry(origin: origin, barWidth: barWidth, barHeight: entryHeight, space: space, data: entry)
Expand Down
14 changes: 14 additions & 0 deletions CardParts/src/Classes/Card Parts/CardPartMultiSliderView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// CardPartMultiSliderView.swift
// CardParts
//
// Created by bcarreon1 on 1/30/20.
//

import Foundation
import RxSwift
import RxCocoa

public class CardPartMultiSliderView : CardPartMultiSlider, CardPartView {
public var margins: UIEdgeInsets = CardParts.theme.cardPartMargins
}
24 changes: 23 additions & 1 deletion CardParts/src/Classes/Card Parts/CardPartPagedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,16 @@ public class CardPartPagedView: UIView, CardPartView {
}
}

public var height: CGFloat {
didSet{
self.updateConstraints()
}
}

public var delegate: CardPartPagedViewDelegate?

fileprivate var pageControl: UIPageControl
fileprivate var scrollView: UIScrollView
fileprivate var height: CGFloat

public init(withPages pages: [CardPartStackView], andHeight height: CGFloat) {

Expand Down Expand Up @@ -90,6 +95,23 @@ public class CardPartPagedView: UIView, CardPartView {

super.updateConstraints()
}

public func moveToPage(_ page: Int) {
guard page <= pageControl.numberOfPages - 1 else { return }

UIView.animate(withDuration: 1.0) {[weak self] in

guard let this = self else { return }

let currentOffset = this.scrollView.contentOffset
this.scrollView.contentOffset = CGPoint(x: this.getPosition(for: page), y: currentOffset.y)
this.pageControl.currentPage = page
}
}

private func getPosition(for page: Int) -> CGFloat {
return self.scrollView.frame.size.width * CGFloat(integerLiteral: page)
}

fileprivate func updatePageControl() {

Expand Down
10 changes: 10 additions & 0 deletions CardParts/src/Classes/Card Parts/CardPartSwitchView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//
// CardPartSwitchView.swift
// CardParts
//
// Created by bcarreon1 on 2/25/20.
//

public class CardPartSwitchView: UISwitch, CardPartView {
public var margins: UIEdgeInsets = CardParts.theme.cardPartMargins
}
119 changes: 119 additions & 0 deletions CardParts/src/Classes/CardPartMultiSlider+Drag.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// CardPartMultiSlider+Drag.swift
// CardPartMultiSlider
//
// Created by Brian Carreon on 25.10.2018.
//

import UIKit

extension CardPartMultiSlider: UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}

@objc open func didDrag(_ panGesture: UIPanGestureRecognizer) {
switch panGesture.state {
case .began:
// determine thumb to drag
let location = panGesture.location(in: slideView)
draggedThumbIndex = closestThumb(point: location)
case .ended, .cancelled, .failed:
sendActions(for: .touchUpInside) // no bounds check for now (.touchUpInside vs .touchUpOutside)
if !isContinuous { sendActions(for: [.valueChanged, .primaryActionTriggered]) }
default:
break
}
guard draggedThumbIndex >= 0 else { return }

let slideViewLength = slideView.bounds.size(in: orientation)
var targetPosition = panGesture.location(in: slideView).coordinate(in: orientation)
let stepSizeInView = (snapStepSize / (maximumValue - minimumValue)) * slideViewLength

// snap translation to stepSizeInView
if snapStepSize > 0 {
let translationSnapped = panGesture.translation(in: slideView).coordinate(in: orientation).rounded(stepSizeInView)
if 0 == Int(translationSnapped) { return }
panGesture.setTranslation(.zero, in: slideView)
}

// don't cross prev/next thumb and total range
targetPosition = boundedDraggedThumbPosition(targetPosition: targetPosition, stepSizeInView: stepSizeInView)

// change corresponding value
updateDraggedThumbValue(relativeValue: targetPosition / slideViewLength)

UIView.animate(withDuration: 0.1) {
self.updateDraggedThumbPositionAndLabel()
self.layoutIfNeeded()
}

if isContinuous { sendActions(for: [.valueChanged, .primaryActionTriggered]) }
}

/// adjusted position that doesn't cross prev/next thumb and total range
private func boundedDraggedThumbPosition(targetPosition: CGFloat, stepSizeInView: CGFloat) -> CGFloat {
var delta = snapStepSize > 0 ? stepSizeInView : thumbViews[draggedThumbIndex].frame.size(in: orientation) / 2
delta = keepsDistanceBetweenThumbs ? delta : 0
if orientation == .horizontal { delta = -delta }
let bottomLimit = draggedThumbIndex > 0
? thumbViews[draggedThumbIndex - 1].center.coordinate(in: orientation) - delta
: slideView.bounds.bottom(in: orientation)
let topLimit = draggedThumbIndex < thumbViews.count - 1
? thumbViews[draggedThumbIndex + 1].center.coordinate(in: orientation) + delta
: slideView.bounds.top(in: orientation)
if orientation == .vertical {
return min(bottomLimit, max(targetPosition, topLimit))
} else {
return max(bottomLimit, min(targetPosition, topLimit))
}
}

private func updateDraggedThumbValue(relativeValue: CGFloat) {
var newValue = relativeValue * (maximumValue - minimumValue)
if orientation == .vertical {
newValue = maximumValue - newValue
} else {
newValue += minimumValue
}
newValue = newValue.rounded(snapStepSize)
guard newValue != value[draggedThumbIndex] else { return }
isSettingValue = true
value[draggedThumbIndex] = newValue
isSettingValue = false
}

private func updateDraggedThumbPositionAndLabel() {
positionThumbView(draggedThumbIndex)
if draggedThumbIndex < valueLabels.count {
updateValueLabel(draggedThumbIndex)
if isValueLabelRelative && draggedThumbIndex + 1 < valueLabels.count {
updateValueLabel(draggedThumbIndex + 1)
}
}
}

private func closestThumb(point: CGPoint) -> Int {
var closest = -1
var minimumDistance = CGFloat.greatestFiniteMagnitude
let pointCoordinate = point.coordinate(in: orientation)
for i in 0 ..< thumbViews.count {
guard !disabledThumbIndices.contains(i) else { continue }
let thumbCoordinate = thumbViews[i].center.coordinate(in: orientation)
let distance = abs(pointCoordinate - thumbCoordinate)
if distance > minimumDistance { break }
if i > 0 && closest == i - 1 && thumbViews[i].center == thumbViews[i - 1].center { // overlapping thumbs
let greaterSign: CGFloat = orientation == .vertical ? -1 : 1
if greaterSign * thumbCoordinate < greaterSign * pointCoordinate {
closest = i
}
break
}
minimumDistance = distance
if distance < thumbViews[i].diagonalSize {
closest = i
}
}
return closest
}
}
Loading

0 comments on commit 1bffda3

Please sign in to comment.