LeadKit/TIBottomSheet/Sources/BottomSheet/Views/ModalHeaderView.swift

182 lines
6.6 KiB
Swift

//
// Copyright (c) 2023 Touch Instinct
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the Software), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import TIUIElements
import TIUIKitCore
import UIKit
open class ModalHeaderView: BaseInitializableView, AppearanceConfigurable {
// MARK: - Nested Types
public enum State {
case hidden
case presented(Appearance)
}
public enum ContentViewState {
case none
case buttonLeft(BaseButtonStyle)
case buttonRight(BaseButtonStyle)
case buttons(left: BaseButtonStyle, right: BaseButtonStyle)
case custom(view: UIView, appearance: UIView.BaseWrappedAppearance<UIView.DefaultWrappedLayout>)
}
// MARK: - Public properties
public let leftButton = StatefulButton()
public let rightButton = StatefulButton()
public var leftButtonConstraints: SubviewConstraints?
public var rightButtonConstraints: SubviewConstraints?
public var customViewConstraints: SubviewConstraints?
// MARK: - BaseInitializableView
open override func addViews() {
super.addViews()
addSubviews(leftButton, rightButton)
}
open override func configureLayout() {
super.configureLayout()
[leftButton, rightButton]
.forEach { $0.translatesAutoresizingMaskIntoConstraints = false }
let leftButtonConstraints = SubviewConstraints(
centerYConstraint: leftButton.centerYAnchor.constraint(equalTo: centerYAnchor),
leadingConstraint: leftButton.leadingAnchor.constraint(equalTo: leadingAnchor),
topConstraint: leftButton.topAnchor.constraint(equalTo: topAnchor),
bottomConstraint: leftButton.bottomAnchor.constraint(equalTo: bottomAnchor))
let rightButtonConstraints = SubviewConstraints(
centerYConstraint: rightButton.centerYAnchor.constraint(equalTo: centerYAnchor),
topConstraint: rightButton.topAnchor.constraint(equalTo: topAnchor),
trailingConstraint: rightButton.trailingAnchor.constraint(equalTo: trailingAnchor),
bottomConstraint: rightButton.bottomAnchor.constraint(equalTo: bottomAnchor))
self.leftButtonConstraints = leftButtonConstraints
self.rightButtonConstraints = rightButtonConstraints
NSLayoutConstraint.activate(leftButtonConstraints.constraints + rightButtonConstraints.constraints)
}
// MARK: - AppearanceConfigurable
open func configure(appearance: Appearance) {
configureUIView(appearance: appearance)
configureContentView(state: appearance.contentViewState)
}
open func configureContentView(state: ContentViewState) {
var leftButtonStyle: BaseButtonStyle?
var rightButtonStyle: BaseButtonStyle?
switch state {
case let .buttonLeft(style):
leftButtonStyle = style
case let .buttonRight(style):
rightButtonStyle = style
case let .buttons(left, right):
leftButtonStyle = left
rightButtonStyle = right
case let .custom(view, appearance):
configureCustomView(view, withLayout: appearance.layout)
view.configureUIView(appearance: appearance)
default:
break
}
configure(buttonStyle: leftButtonStyle, forButton: leftButton, constraints: leftButtonConstraints)
configure(buttonStyle: rightButtonStyle, forButton: rightButton, constraints: rightButtonConstraints)
}
// MARK: - Private methods
private func configureCustomView(_ view: UIView, withLayout layout: WrappedViewLayout) {
addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
let customViewConstraints = SubviewConstraints(
centerXConstraint: view.centerXAnchor.constraint(equalTo: centerXAnchor),
centerYConstraint: view.centerYAnchor.constraint(equalTo: centerYAnchor),
leadingConstraint: view.leadingAnchor.constraint(equalTo: leadingAnchor),
topConstraint: view.topAnchor.constraint(equalTo: topAnchor),
trailingConstraint: view.trailingAnchor.constraint(equalTo: trailingAnchor),
bottomConstraint: view.bottomAnchor.constraint(equalTo: bottomAnchor))
self.customViewConstraints = customViewConstraints
NSLayoutConstraint.deactivate(customViewConstraints.centerConstraints)
Self.configure(layout: layout, constraints: customViewConstraints)
}
private func configure(buttonStyle: BaseButtonStyle?,
forButton button: StatefulButton,
constraints: SubviewConstraints?) {
guard let buttonStyle else {
button.isHidden = true
return
}
button.isHidden = false
if let layout = buttonStyle.appearance[.normal]?.layout, let constraints {
UIView.configure(layout: layout, constraints: constraints)
}
button.apply(style: buttonStyle)
}
}
// MARK: - Appearance
extension ModalHeaderView {
public final class Appearance: UIView.BaseWrappedAppearance<UIView.DefaultWrappedLayout>, WrappedViewAppearance {
public static var defaultAppearance: Self {
.init()
}
public var contentViewState: ContentViewState
public init(layout: UIView.DefaultWrappedLayout = .defaultLayout,
backgroundColor: UIColor = .clear,
border: UIViewBorder = .init(),
shadow: UIViewShadow? = nil,
contentViewState: ContentViewState = .none) {
self.contentViewState = contentViewState
super.init(layout: layout, backgroundColor: backgroundColor, border: border, shadow: shadow)
}
}
}