// // 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) } // 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, 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) } } }