// // EKProperty.swift // SwiftEntryKit // // Created by Daniel Huri on 4/19/18. // Copyright (c) 2018 huri000@gmail.com. All rights reserved. // import UIKit public struct EKProperty { /** Button content descriptor */ public struct ButtonContent { public typealias Action = () -> () /** Button title label content descriptor */ public var label: LabelContent /** Button background color */ public var backgroundColor: EKColor public var highlightedBackgroundColor: EKColor /** Content edge inset */ public var contentEdgeInset: CGFloat /** The display mode of the button */ public var displayMode: EKAttributes.DisplayMode /** Accessibility identifier that identifies the button */ public var accessibilityIdentifier: String? /** Action */ public var action: Action? public init(label: LabelContent, backgroundColor: EKColor, highlightedBackgroundColor: EKColor, contentEdgeInset: CGFloat = 5, displayMode: EKAttributes.DisplayMode = .inferred, accessibilityIdentifier: String? = nil, action: @escaping Action = {}) { self.label = label self.backgroundColor = backgroundColor self.highlightedBackgroundColor = highlightedBackgroundColor self.contentEdgeInset = contentEdgeInset self.displayMode = displayMode self.accessibilityIdentifier = accessibilityIdentifier self.action = action } public func backgroundColor(for traitCollection: UITraitCollection) -> UIColor { return backgroundColor.color(for: traitCollection, mode: displayMode) } public func highlightedBackgroundColor(for traitCollection: UITraitCollection) -> UIColor { return highlightedBackgroundColor.color(for: traitCollection, mode: displayMode) } public func highlighedLabelColor(for traitCollection: UITraitCollection) -> UIColor { return label.style.color.with(alpha: 0.8).color( for: traitCollection, mode: label.style.displayMode ) } } /** Label content descriptor */ public struct LabelContent { /** The text */ public var text: String /** The label's style */ public var style: LabelStyle /** The label's accessibility ideentifier */ public var accessibilityIdentifier: String? public init(text: String, style: LabelStyle, accessibilityIdentifier: String? = nil) { self.text = text self.style = style self.accessibilityIdentifier = accessibilityIdentifier } } /** Label style descriptor */ public struct LabelStyle { /** Font of the text */ public var font: UIFont /** Color of the text */ public var color: EKColor /** Text Alignment */ public var alignment: NSTextAlignment /** Number of lines */ public var numberOfLines: Int /** Display mode for the label */ public var displayMode: EKAttributes.DisplayMode public init(font: UIFont, color: EKColor, alignment: NSTextAlignment = .left, displayMode: EKAttributes.DisplayMode = .inferred, numberOfLines: Int = 0) { self.font = font self.color = color self.alignment = alignment self.displayMode = displayMode self.numberOfLines = numberOfLines } public func color(for traitCollection: UITraitCollection) -> UIColor { return color.color(for: traitCollection, mode: displayMode) } } /** Image View style descriptor */ public struct ImageContent { /** Repeated-reversed animation throughout the presentation of an image */ public enum TransformAnimation { case animate(duration: TimeInterval, options: UIView.AnimationOptions, transform: CGAffineTransform) case none } /** Tint color for the image/s */ public var tint: EKColor? /** The images */ public var images: [UIImage] /** Image sequence duration, if any */ public var imageSequenceAnimationDuration: TimeInterval /** Image View size - can be forced. If nil, then the image view hugs content and resists compression */ public var size: CGSize? /** Content mode */ public var contentMode: UIView.ContentMode /** Should the image be rounded */ public var makesRound: Bool /** Repeated-Reversed animation */ public var animation: TransformAnimation /** The display mode of the image */ public var displayMode: EKAttributes.DisplayMode /** Image accessibility identifier */ public var accessibilityIdentifier: String? public init(imageName: String, animation: TransformAnimation = .none, displayMode: EKAttributes.DisplayMode = .inferred, size: CGSize? = nil, contentMode: UIView.ContentMode = .scaleToFill, tint: EKColor? = nil, makesRound: Bool = false, accessibilityIdentifier: String? = nil) { let image = UIImage(named: imageName)! self.init(image: image, displayMode: displayMode, size: size, tint: tint, contentMode: contentMode, makesRound: makesRound, accessibilityIdentifier: accessibilityIdentifier) } public init(image: UIImage, animation: TransformAnimation = .none, displayMode: EKAttributes.DisplayMode = .inferred, size: CGSize? = nil, tint: EKColor? = nil, contentMode: UIView.ContentMode = .scaleToFill, makesRound: Bool = false, accessibilityIdentifier: String? = nil) { self.images = [image] self.size = size self.tint = tint self.displayMode = displayMode self.contentMode = contentMode self.makesRound = makesRound self.animation = animation self.imageSequenceAnimationDuration = 0 self.accessibilityIdentifier = accessibilityIdentifier } public init(images: [UIImage], imageSequenceAnimationDuration: TimeInterval = 1, displayMode: EKAttributes.DisplayMode = .inferred, animation: TransformAnimation = .none, size: CGSize? = nil, tint: EKColor? = nil, contentMode: UIView.ContentMode = .scaleToFill, makesRound: Bool = false, accessibilityIdentifier: String? = nil) { self.images = images self.size = size self.displayMode = displayMode self.tint = tint self.contentMode = contentMode self.makesRound = makesRound self.animation = animation self.imageSequenceAnimationDuration = imageSequenceAnimationDuration self.accessibilityIdentifier = accessibilityIdentifier } public init(imagesNames: [String], imageSequenceAnimationDuration: TimeInterval = 1, displayMode: EKAttributes.DisplayMode = .inferred, animation: TransformAnimation = .none, size: CGSize? = nil, tint: EKColor? = nil, contentMode: UIView.ContentMode = .scaleToFill, makesRound: Bool = false, accessibilityIdentifier: String? = nil) { let images = imagesNames.map { return UIImage(named: $0)! } self.init(images: images, imageSequenceAnimationDuration: imageSequenceAnimationDuration, displayMode: displayMode, animation: animation, size: size, tint: tint, contentMode: contentMode, makesRound: makesRound, accessibilityIdentifier: accessibilityIdentifier) } /** Quick thumbail property generator */ public static func thumb(with image: UIImage, edgeSize: CGFloat) -> ImageContent { return ImageContent(images: [image], size: CGSize(width: edgeSize, height: edgeSize), contentMode: .scaleAspectFill, makesRound: true) } /** Quick thumbail property generator */ public static func thumb(with imageName: String, edgeSize: CGFloat) -> ImageContent { return ImageContent(imagesNames: [imageName], size: CGSize(width: edgeSize, height: edgeSize), contentMode: .scaleAspectFill, makesRound: true) } public func tintColor(for traitCollection: UITraitCollection) -> UIColor? { return tint?.color(for: traitCollection, mode: displayMode) } } /** Text field content **/ public struct TextFieldContent { // NOTE: Intentionally a reference type class ContentWrapper { var text = "" } public weak var delegate: UITextFieldDelegate? public var keyboardType: UIKeyboardType public var isSecure: Bool public var leadingImage: UIImage! public var placeholder: LabelContent public var textStyle: LabelStyle public var tintColor: EKColor! public var displayMode: EKAttributes.DisplayMode public var bottomBorderColor: EKColor public var accessibilityIdentifier: String? let contentWrapper = ContentWrapper() public var textContent: String { set { contentWrapper.text = newValue } get { return contentWrapper.text } } public init(delegate: UITextFieldDelegate? = nil, keyboardType: UIKeyboardType = .default, placeholder: LabelContent, tintColor: EKColor? = nil, displayMode: EKAttributes.DisplayMode = .inferred, textStyle: LabelStyle, isSecure: Bool = false, leadingImage: UIImage? = nil, bottomBorderColor: EKColor = .clear, accessibilityIdentifier: String? = nil) { self.delegate = delegate self.keyboardType = keyboardType self.placeholder = placeholder self.textStyle = textStyle self.tintColor = tintColor self.displayMode = displayMode self.isSecure = isSecure self.leadingImage = leadingImage self.bottomBorderColor = bottomBorderColor self.accessibilityIdentifier = accessibilityIdentifier } public func tintColor(for traitCollection: UITraitCollection) -> UIColor? { return tintColor?.color(for: traitCollection, mode: displayMode) } public func bottomBorderColor(for traitCollection: UITraitCollection) -> UIColor? { return bottomBorderColor.color(for: traitCollection, mode: displayMode) } } /** Button bar content */ public struct ButtonBarContent { /** Button content array */ public var content: [ButtonContent] = [] /** The color of the separator */ public var separatorColor: EKColor /** Upper threshold for the number of buttons (*ButtonContent*) for horizontal distribution. Must be a positive value */ public var horizontalDistributionThreshold: Int /** Determines whether the buttons expands animately */ public var expandAnimatedly: Bool /** The height of each button. All are equally distributed in their axis */ public var buttonHeight: CGFloat /** The display mode of the button bar */ public var displayMode: EKAttributes.DisplayMode public init(with buttonContents: ButtonContent..., separatorColor: EKColor, horizontalDistributionThreshold: Int = 2, buttonHeight: CGFloat = 50, displayMode: EKAttributes.DisplayMode = .inferred, expandAnimatedly: Bool) { self.init(with: buttonContents, separatorColor: separatorColor, horizontalDistributionThreshold: horizontalDistributionThreshold, buttonHeight: buttonHeight, displayMode: displayMode, expandAnimatedly: expandAnimatedly) } public init(with buttonContents: [ButtonContent], separatorColor: EKColor, horizontalDistributionThreshold: Int = 2, buttonHeight: CGFloat = 50, displayMode: EKAttributes.DisplayMode = .inferred, expandAnimatedly: Bool) { guard horizontalDistributionThreshold > 0 else { fatalError("horizontalDistributionThreshold Must have a positive value!") } self.separatorColor = separatorColor self.horizontalDistributionThreshold = horizontalDistributionThreshold self.buttonHeight = buttonHeight self.displayMode = displayMode self.expandAnimatedly = expandAnimatedly content.append(contentsOf: buttonContents) } public func separatorColor(for traitCollection: UITraitCollection) -> UIColor { return separatorColor.color(for: traitCollection, mode: displayMode) } } /** Rating item content */ public struct EKRatingItemContent { public var title: EKProperty.LabelContent public var description: EKProperty.LabelContent public var unselectedImage: EKProperty.ImageContent public var selectedImage: EKProperty.ImageContent public var size: CGSize public init(title: EKProperty.LabelContent, description: EKProperty.LabelContent, unselectedImage: EKProperty.ImageContent, selectedImage: EKProperty.ImageContent, size: CGSize = CGSize(width: 50, height: 50)) { self.title = title self.description = description self.unselectedImage = unselectedImage self.selectedImage = selectedImage self.size = size } } }