diff --git a/Stylish/PropertyStylers.swift b/Stylish/PropertyStylers.swift index 2d80901..2af895f 100644 --- a/Stylish/PropertyStylers.swift +++ b/Stylish/PropertyStylers.swift @@ -124,8 +124,12 @@ public extension Style { /// Sets property value on UITextFields and subclasses typealias background = Stylish.PropertyStylers.UITextField.Background /// Sets property value on UITextFields and subclasses + typealias backgroundImageName = Stylish.PropertyStylers.UITextField.BackgroundImageName + /// Sets property value on UITextFields and subclasses typealias disabledBackground = Stylish.PropertyStylers.UITextField.DisabledBackground /// Sets property value on UITextFields and subclasses + typealias disabledBackgroundImageName = Stylish.PropertyStylers.UITextField.DisabledBackgroundImageName + /// Sets property value on UITextFields and subclasses typealias borderStyle = Stylish.PropertyStylers.UITextField.BorderStyle /// Sets property value on UITextFields and subclasses /// Sets property value on UITextFields and subclasses @@ -176,22 +180,38 @@ public extension Style { /// Sets property value on UIButtons and subclasses typealias imageForNormalState = Stylish.PropertyStylers.UIButton.ImageForNormalState /// Sets property value on UIButtons and subclasses + typealias imageNameForNormalState = Stylish.PropertyStylers.UIButton.ImageNameForNormalState + /// Sets property value on UIButtons and subclasses typealias imageForHighlightedState = Stylish.PropertyStylers.UIButton.ImageForHighlightedState /// Sets property value on UIButtons and subclasses + typealias imageNameForHighlightedState = Stylish.PropertyStylers.UIButton.ImageNameForHighlightedState + /// Sets property value on UIButtons and subclasses typealias imageForDisabledState = Stylish.PropertyStylers.UIButton.ImageForDisabledState /// Sets property value on UIButtons and subclasses + typealias imageNameForDisabledState = Stylish.PropertyStylers.UIButton.ImageNameForDisabledState + /// Sets property value on UIButtons and subclasses typealias backgroundImageForNormalState = Stylish.PropertyStylers.UIButton.BackgroundImageForNormalState /// Sets property value on UIButtons and subclasses + typealias backgroundImageNameForNormalState = Stylish.PropertyStylers.UIButton.BackgroundImageNameForNormalState + /// Sets property value on UIButtons and subclasses typealias backgroundImageForHighlightedState = Stylish.PropertyStylers.UIButton.BackgroundImageForHighlightedState /// Sets property value on UIButtons and subclasses + typealias backgroundImageNameForHighlightedState = Stylish.PropertyStylers.UIButton.BackgroundImageNameForHighlightedState + /// Sets property value on UIButtons and subclasses typealias backgroundImageForDisabledState = Stylish.PropertyStylers.UIButton.BackgroundImageForDisabledState + /// Sets property value on UIButtons and subclasses + typealias backgroundImageNameForDisabledState = Stylish.PropertyStylers.UIButton.BackgroundImageNameForDisabledState /// Sets property value on UIImageViews and subclasses typealias image = Stylish.PropertyStylers.UIImageView.Image + /// Sets property value on UIImageViews and subclasses + typealias imageName = Stylish.PropertyStylers.UIImageView.ImageName /// Specifies a URL to asynchronously download an image from, and then set as the UIImageView's image property typealias imageURL = Stylish.PropertyStylers.UIImageView.ImageURL /// Sets property value on UIImageViews and subclasses typealias highlightedImage = Stylish.PropertyStylers.UIImageView.HighlightedImage /// Sets property value on UIImageViews and subclasses + typealias highlightedImageName = Stylish.PropertyStylers.UIImageView.HighlightedImageName + /// Sets property value on UIImageViews and subclasses @available(iOS 11.0, *) typealias adjustsImageSizeForAccessibilityContentSizeCategory = Stylish.PropertyStylers.UIImageView.AdjustsImageSizeForAccessibilityContentSizeCategory /// Sets property value on UIImageViews and subclasses typealias animationDuration = Stylish.PropertyStylers.UIImageView.AnimationDuration @@ -200,7 +220,11 @@ public extension Style { /// Sets property value on UIImageViews and subclasses typealias animationImages = Stylish.PropertyStylers.UIImageView.AnimationImages /// Sets property value on UIImageViews and subclasses + typealias animationImageNames = Stylish.PropertyStylers.UIImageView.AnimationImageNames + /// Sets property value on UIImageViews and subclasses typealias highlightedAnimationImages = Stylish.PropertyStylers.UIImageView.HighlightedAnimationImages + /// Sets property value on UIImageViews and subclasses + typealias highlightedAnimationImageNames = Stylish.PropertyStylers.UIImageView.HighlightedAnimationImageNames /// When true, calls startAnimating() on target UIImageView, calls stopAnimating() when false typealias isAnimating = Stylish.PropertyStylers.UIImageView.IsAnimating } @@ -216,98 +240,98 @@ public extension Stylish.PropertyStylers { public struct BackgroundColor: PropertyStyler { public static var propertyKey: String { return "backgroundColor" } - public static func apply(value: UIColor?, to target: UIKit.UIView) { + public static func apply(value: UIColor?, to target: UIKit.UIView, using bundle: Bundle) { target.backgroundColor = value } } public struct ContentMode: PropertyStyler { public static var propertyKey: String { return "contentMode" } - public static func apply(value: UIKit.UIView.ContentMode?, to target: UIKit.UIView) { + public static func apply(value: UIKit.UIView.ContentMode?, to target: UIKit.UIView, using bundle: Bundle) { target.contentMode = value ?? .scaleToFill } } public struct CornerRadius: PropertyStyler { public static var propertyKey: String { return "cornerRadius" } - public static func apply(value: CGFloat?, to target: UIKit.UIView) { + public static func apply(value: CGFloat?, to target: UIKit.UIView, using bundle: Bundle) { target.layer.cornerRadius = value ?? 0 } } public struct CornerRadiusRatio: PropertyStyler { public static var propertyKey: String { return "cornerRadiusRatio" } - public static func apply(value: CGFloat?, to target: UIKit.UIView) { + public static func apply(value: CGFloat?, to target: UIKit.UIView, using bundle: Bundle) { target.layer.cornerRadius = (target.bounds.height * ( value ?? 0)) } } public struct IsUserInteractionEnabled: PropertyStyler { public static var propertyKey: String { return "isUserInteractionEnabled" } - public static func apply(value: Bool?, to target: UIKit.UIView) { + public static func apply(value: Bool?, to target: UIKit.UIView, using bundle: Bundle) { target.isUserInteractionEnabled = value ?? true } } public struct IsHidden: PropertyStyler { public static var propertyKey: String { return "isHidden" } - public static func apply(value: Bool?, to target: UIKit.UIView) { + public static func apply(value: Bool?, to target: UIKit.UIView, using bundle: Bundle) { target.isHidden = value ?? false } } public struct BorderColor: PropertyStyler { public static var propertyKey: String { return "borderColor" } - public static func apply(value: UIColor?, to target: UIKit.UIView) { + public static func apply(value: UIColor?, to target: UIKit.UIView, using bundle: Bundle) { target.layer.borderColor = value?.cgColor } } public struct BorderWidth: PropertyStyler { public static var propertyKey: String { return "borderWidth" } - public static func apply(value: CGFloat?, to target: UIKit.UIView) { + public static func apply(value: CGFloat?, to target: UIKit.UIView, using bundle: Bundle) { target.layer.borderWidth = value ?? 0 } } public struct Alpha: PropertyStyler { public static var propertyKey: String { return "alpha" } - public static func apply(value: CGFloat?, to target: UIKit.UIView) { + public static func apply(value: CGFloat?, to target: UIKit.UIView, using bundle: Bundle) { target.alpha = value ?? 1.0 } } public struct ClipsToBounds: PropertyStyler { public static var propertyKey: String { return "clipsToBounds" } - public static func apply(value: Bool?, to target: UIKit.UIView) { + public static func apply(value: Bool?, to target: UIKit.UIView, using bundle: Bundle) { target.clipsToBounds = value ?? false } } public struct MasksToBounds: PropertyStyler { public static var propertyKey: String { return "masksToBounds" } - public static func apply(value: Bool?, to target: UIKit.UIView) { + public static func apply(value: Bool?, to target: UIKit.UIView, using bundle: Bundle) { target.layer.masksToBounds = value ?? false } } public struct TintColor: PropertyStyler { public static var propertyKey: String { return "tintColor" } - public static func apply(value: UIColor?, to target: UIKit.UIView) { + public static func apply(value: UIColor?, to target: UIKit.UIView, using bundle: Bundle) { target.tintColor = value } } public struct LayoutMargins: PropertyStyler { public static var propertyKey: String { return "layoutMargins" } - public static func apply(value: UIEdgeInsets?, to target: UIKit.UIView) { + public static func apply(value: UIEdgeInsets?, to target: UIKit.UIView, using bundle: Bundle) { target.layoutMargins = value ?? UIKit.UIView().layoutMargins } } public struct ShadowColor: PropertyStyler { public static var propertyKey: String { return "shadowColor" } - public static func apply(value: UIColor?, to target: UIKit.UIView) { + public static func apply(value: UIColor?, to target: UIKit.UIView, using bundle: Bundle) { if let label = target as? UIKit.UILabel { label.shadowColor = value } else { @@ -318,7 +342,7 @@ public extension Stylish.PropertyStylers { public struct ShadowOffset: PropertyStyler { public static var propertyKey: String { return "shadowOffset" } - public static func apply(value: CGSize?, to target: UIKit.UIView) { + public static func apply(value: CGSize?, to target: UIKit.UIView, using bundle: Bundle) { if let label = target as? UIKit.UILabel { label.shadowOffset = value ?? .zero } else { @@ -329,14 +353,14 @@ public extension Stylish.PropertyStylers { public struct ShadowRadius: PropertyStyler { public static var propertyKey: String { return "shadowRadius" } - public static func apply(value: CGFloat?, to target: UIKit.UIView) { + public static func apply(value: CGFloat?, to target: UIKit.UIView, using bundle: Bundle) { target.layer.shadowRadius = value ?? 0 } } public struct ShadowOpacity: PropertyStyler { public static var propertyKey: String { return "shadowOpacity" } - public static func apply(value: Float?, to target: UIKit.UIView) { + public static func apply(value: Float?, to target: UIKit.UIView, using bundle: Bundle) { target.layer.shadowOpacity = value ?? 0 } } @@ -346,7 +370,7 @@ public extension Stylish.PropertyStylers { public struct IsEnabled: PropertyStyler { public static var propertyKey: String { return "isEnabled" } - public static func apply(value: Bool?, to target: UIKit.UIControl) { + public static func apply(value: Bool?, to target: UIKit.UIControl, using bundle: Bundle) { target.isEnabled = value ?? true } } @@ -356,7 +380,7 @@ public extension Stylish.PropertyStylers { public struct AdjustsFontSizeToFitWidth: PropertyStyler { public static var propertyKey: String { return "adjustsFontSizeToFitWidth" } - public static func apply(value: Bool?, to target: TextControl) { + public static func apply(value: Bool?, to target: TextControl, using bundle: Bundle) { switch target { case let label as UIKit.UILabel: label.adjustsFontSizeToFitWidth = value ?? false @@ -369,21 +393,21 @@ public extension Stylish.PropertyStylers { @available(iOS 10.0, *) public struct AdjustsFontForContentSizeCategory: PropertyStyler { public static var propertyKey: String { return "adjustsFontForContentSizeCategory" } - public static func apply(value: Bool?, to target: TextControl) { + public static func apply(value: Bool?, to target: TextControl, using bundle: Bundle) { target.adjustsFontForContentSizeCategory = value ?? false } } public struct TextAlignment: PropertyStyler { public static var propertyKey: String { return "textAlignment" } - public static func apply(value: NSTextAlignment?, to target: TextControl) { + public static func apply(value: NSTextAlignment?, to target: TextControl, using bundle: Bundle) { target.textAlignment = value ?? .left } } public struct Text: PropertyStyler { public static var propertyKey: String { return "text" } - public static func apply(value: String?, to target: TextControl) { + public static func apply(value: String?, to target: TextControl, using bundle: Bundle) { switch target { case let label as UIKit.UILabel: label.text = value @@ -397,7 +421,7 @@ public extension Stylish.PropertyStylers { public struct TextColor: PropertyStyler { public static var propertyKey: String { return "textColor" } - public static func apply(value: UIColor?, to target: TextControl) { + public static func apply(value: UIColor?, to target: TextControl, using bundle: Bundle) { switch target { case let label as UIKit.UILabel: label.textColor = value @@ -412,7 +436,7 @@ public extension Stylish.PropertyStylers { public struct Font: PropertyStyler { public static var propertyKey: String { return "font" } - public static func apply(value: UIFont?, to target: UIKit.UIView) { + public static func apply(value: UIFont?, to target: UIKit.UIView, using bundle: Bundle) { switch target { case let label as UIKit.UILabel: label.font = value @@ -429,7 +453,7 @@ public extension Stylish.PropertyStylers { public struct IsHighlighted: PropertyStyler { public static var propertyKey: String { return "isHighlighted" } - public static func apply(value: Bool?, to target: TextControl) { + public static func apply(value: Bool?, to target: TextControl, using bundle: Bundle) { switch target { case let label as UIKit.UILabel: label.isHighlighted = value ?? false @@ -445,49 +469,49 @@ public extension Stylish.PropertyStylers { public struct BaselineAdjustment: PropertyStyler { public static var propertyKey: String { return "baselineAdjustment" } - public static func apply(value: UIBaselineAdjustment?, to target: UIKit.UILabel) { + public static func apply(value: UIBaselineAdjustment?, to target: UIKit.UILabel, using bundle: Bundle) { target.baselineAdjustment = value ?? .alignBaselines } } public struct AllowsDefaultTighteningForTruncation: PropertyStyler { public static var propertyKey: String { return "allowsDefaultTighteningForTruncation" } - public static func apply(value: Bool?, to target: UIKit.UILabel) { + public static func apply(value: Bool?, to target: UIKit.UILabel, using bundle: Bundle) { target.allowsDefaultTighteningForTruncation = value ?? false } } public struct LineBreakMode: PropertyStyler { public static var propertyKey: String { return "lineBreakMode" } - public static func apply(value: NSLineBreakMode?, to target: UIKit.UILabel) { + public static func apply(value: NSLineBreakMode?, to target: UIKit.UILabel, using bundle: Bundle) { target.lineBreakMode = value ?? .byTruncatingTail } } public struct NumberOfLines: PropertyStyler { public static var propertyKey: String { return "numberOfLines" } - public static func apply(value: Int?, to target: UIKit.UILabel) { + public static func apply(value: Int?, to target: UIKit.UILabel, using bundle: Bundle) { target.numberOfLines = value ?? 1 } } public struct MinimumScaleFactor: PropertyStyler { public static var propertyKey: String { return "minimumScaleFactor" } - public static func apply(value: CGFloat?, to target: UIKit.UILabel) { + public static func apply(value: CGFloat?, to target: UIKit.UILabel, using bundle: Bundle) { target.minimumScaleFactor = value ?? 0.0 } } public struct PreferredMaxLayoutWidth: PropertyStyler { public static var propertyKey: String { return "preferredMaxLayoutWidth" } - public static func apply(value: CGFloat?, to target: UIKit.UILabel) { + public static func apply(value: CGFloat?, to target: UIKit.UILabel, using bundle: Bundle) { target.minimumScaleFactor = value ?? 0.0 } } public struct HighlightedTextColor: PropertyStyler { public static var propertyKey: String { return "highlightedTextColor" } - public static func apply(value: UIColor?, to target: UIKit.UILabel) { + public static func apply(value: UIColor?, to target: UIKit.UILabel, using bundle: Bundle) { target.highlightedTextColor = value } } @@ -497,7 +521,7 @@ public extension Stylish.PropertyStylers { public struct AllowsEditingTextAttributes: PropertyStyler { public static var propertyKey: String { return "allowsEditingTextAttributes" } - public static func apply(value: Bool?, to target: TextInputControl) { + public static func apply(value: Bool?, to target: TextInputControl, using bundle: Bundle) { switch target { case let textField as UIKit.UITextField: textField.allowsEditingTextAttributes = value ?? false @@ -510,42 +534,42 @@ public extension Stylish.PropertyStylers { public struct AutocapitalizationType: PropertyStyler { public static var propertyKey: String { return "autocapitalizationType" } - public static func apply(value: UITextAutocapitalizationType?, to target: TextInputControl) { + public static func apply(value: UITextAutocapitalizationType?, to target: TextInputControl, using bundle: Bundle) { target.autocapitalizationType = value ?? .sentences } } public struct AutocorrectionType: PropertyStyler { public static var propertyKey: String { return "autocorrectionType" } - public static func apply(value: UITextAutocorrectionType?, to target: TextInputControl) { + public static func apply(value: UITextAutocorrectionType?, to target: TextInputControl, using bundle: Bundle) { target.autocorrectionType = value ?? .default } } public struct EnablesReturnKeyAutomatically: PropertyStyler { public static var propertyKey: String { return "enablesReturnKeyAutomatically" } - public static func apply(value: Bool?, to target: TextInputControl) { + public static func apply(value: Bool?, to target: TextInputControl, using bundle: Bundle) { target.enablesReturnKeyAutomatically = value ?? false } } public struct ClearsOnInsertion: PropertyStyler { public static var propertyKey: String { return "clearsOnInsertion" } - public static func apply(value: Bool?, to target: TextInputControl) { + public static func apply(value: Bool?, to target: TextInputControl, using bundle: Bundle) { target.clearsOnInsertion = value ?? false } } public struct KeyboardAppearance: PropertyStyler { public static var propertyKey: String { return "keyboardAppearance" } - public static func apply(value: UIKeyboardAppearance?, to target: TextInputControl) { + public static func apply(value: UIKeyboardAppearance?, to target: TextInputControl, using bundle: Bundle) { target.keyboardAppearance = value ?? .default } } public struct SpellCheckingType: PropertyStyler { public static var propertyKey: String { return "spellCheckingType" } - public static func apply(value: UITextSpellCheckingType?, to target: TextInputControl) { + public static func apply(value: UITextSpellCheckingType?, to target: TextInputControl, using bundle: Bundle) { target.spellCheckingType = value ?? .default } } @@ -553,7 +577,7 @@ public extension Stylish.PropertyStylers { @available(iOS 11.0, *) public struct SmartDashesType: PropertyStyler { public static var propertyKey: String { return "smartDashesType" } - public static func apply(value: UITextSmartDashesType?, to target: TextInputControl) { + public static func apply(value: UITextSmartDashesType?, to target: TextInputControl, using bundle: Bundle) { target.smartDashesType = value ?? .default } } @@ -561,7 +585,7 @@ public extension Stylish.PropertyStylers { @available(iOS 11.0, *) public struct SmartInsertDeleteType: PropertyStyler { public static var propertyKey: String { return "smartInsertDeleteType" } - public static func apply(value: UITextSmartInsertDeleteType?, to target: TextInputControl) { + public static func apply(value: UITextSmartInsertDeleteType?, to target: TextInputControl, using bundle: Bundle) { target.smartInsertDeleteType = value ?? .default } } @@ -569,28 +593,28 @@ public extension Stylish.PropertyStylers { @available(iOS 11.0, *) public struct SmartQuotesType: PropertyStyler { public static var propertyKey: String { return "smartQuotesType" } - public static func apply(value: UITextSmartQuotesType?, to target: TextInputControl) { + public static func apply(value: UITextSmartQuotesType?, to target: TextInputControl, using bundle: Bundle) { target.smartQuotesType = value ?? .default } } public struct KeyboardType: PropertyStyler { public static var propertyKey: String { return "keyboardType" } - public static func apply(value: UIKeyboardType?, to target: TextInputControl) { + public static func apply(value: UIKeyboardType?, to target: TextInputControl, using bundle: Bundle) { target.keyboardType = value ?? .default } } public struct ReturnKeyType: PropertyStyler { public static var propertyKey: String { return "returnKeyType" } - public static func apply(value: UIReturnKeyType?, to target: TextInputControl) { + public static func apply(value: UIReturnKeyType?, to target: TextInputControl, using bundle: Bundle) { target.returnKeyType = value ?? .default } } public struct IsSecureTextEntry: PropertyStyler { public static var propertyKey: String { return "isSecureTextEntry" } - public static func apply(value: Bool?, to target: TextInputControl) { + public static func apply(value: Bool?, to target: TextInputControl, using bundle: Bundle) { target.isSecureTextEntry = value ?? false } } @@ -598,7 +622,7 @@ public extension Stylish.PropertyStylers { @available(iOS 10.0, *) public struct TextContentType: PropertyStyler { public static var propertyKey: String { return "textContentType" } - public static func apply(value: UITextContentType?, to target: TextInputControl) { + public static func apply(value: UITextContentType?, to target: TextInputControl, using bundle: Bundle) { target.textContentType = value } } @@ -608,63 +632,81 @@ public extension Stylish.PropertyStylers { public struct Background: PropertyStyler { public static var propertyKey: String { return "background" } - public static func apply(value: UIImage?, to target: UIKit.UITextField) { + public static func apply(value: UIImage?, to target: UIKit.UITextField, using bundle: Bundle) { target.background = value } } + public struct BackgroundImageName: PropertyStyler { + public static var propertyKey: String { return "backgroundImageName" } + public static func apply(value: String?, to target: UIKit.UITextField, using bundle: Bundle) { + if let name = value { + target.background = UIImage(named: name, in: bundle, compatibleWith: target.traitCollection) + } + } + } + public struct DisabledBackground: PropertyStyler { public static var propertyKey: String { return "disabledBackground" } - public static func apply(value: UIImage?, to target: UIKit.UITextField) { + public static func apply(value: UIImage?, to target: UIKit.UITextField, using bundle: Bundle) { target.disabledBackground = value } } + public struct DisabledBackgroundImageName: PropertyStyler { + public static var propertyKey: String { return "disabledBackgroundImageName" } + public static func apply(value: String?, to target: UIKit.UITextField, using bundle: Bundle) { + if let name = value { + target.disabledBackground = UIImage(named: name, in: bundle, compatibleWith: target.traitCollection) + } + } + } + public struct BorderStyle: PropertyStyler { public static var propertyKey: String { return "borderStyle" } - public static func apply(value: UIKit.UITextField.BorderStyle?, to target: UIKit.UITextField) { + public static func apply(value: UIKit.UITextField.BorderStyle?, to target: UIKit.UITextField, using bundle: Bundle) { target.borderStyle = value ?? .none } } public struct ClearButtonMode: PropertyStyler { public static var propertyKey: String { return "clearButtonMode" } - public static func apply(value: UIKit.UITextField.ViewMode?, to target: UIKit.UITextField) { + public static func apply(value: UIKit.UITextField.ViewMode?, to target: UIKit.UITextField, using bundle: Bundle) { target.clearButtonMode = value ?? .never } } public struct LeftViewMode: PropertyStyler { public static var propertyKey: String { return "leftViewMode" } - public static func apply(value: UIKit.UITextField.ViewMode?, to target: UIKit.UITextField) { + public static func apply(value: UIKit.UITextField.ViewMode?, to target: UIKit.UITextField, using bundle: Bundle) { target.leftViewMode = value ?? .never } } public struct RightViewMode: PropertyStyler { public static var propertyKey: String { return "rightViewMode" } - public static func apply(value: UIKit.UITextField.ViewMode?, to target: UIKit.UITextField) { + public static func apply(value: UIKit.UITextField.ViewMode?, to target: UIKit.UITextField, using bundle: Bundle) { target.rightViewMode = value ?? .never } } public struct MinimumFontSize: PropertyStyler { public static var propertyKey: String { return "minimumFontSize" } - public static func apply(value: CGFloat?, to target: UIKit.UITextField) { + public static func apply(value: CGFloat?, to target: UIKit.UITextField, using bundle: Bundle) { target.minimumFontSize = value ?? 0.0 } } public struct Placeholder: PropertyStyler { public static var propertyKey: String { return "placeholder" } - public static func apply(value: String?, to target: UIKit.UITextField) { + public static func apply(value: String?, to target: UIKit.UITextField, using bundle: Bundle) { target.placeholder = value } } public struct ClearsOnBeginEditing: PropertyStyler { public static var propertyKey: String { return "clearsOnBeginEditing" } - public static func apply(value: Bool?, to target: UIKit.UITextField) { + public static func apply(value: Bool?, to target: UIKit.UITextField, using bundle: Bundle) { target.clearsOnBeginEditing = value ?? false } } @@ -674,28 +716,28 @@ public extension Stylish.PropertyStylers { public struct IsEditable: PropertyStyler { public static var propertyKey: String { return "isEditable" } - public static func apply(value: Bool?, to target: UIKit.UITextView) { + public static func apply(value: Bool?, to target: UIKit.UITextView, using bundle: Bundle) { target.isEditable = value ?? false } } public struct IsSelectable: PropertyStyler { public static var propertyKey: String { return "isSelectable" } - public static func apply(value: Bool?, to target: UIKit.UITextView) { + public static func apply(value: Bool?, to target: UIKit.UITextView, using bundle: Bundle) { target.isSelectable = value ?? false } } public struct DataDetectorTypes: PropertyStyler { public static var propertyKey: String { return "dataDetectorTypes" } - public static func apply(value: UIDataDetectorTypes?, to target: UIKit.UITextView) { + public static func apply(value: UIDataDetectorTypes?, to target: UIKit.UITextView, using bundle: Bundle) { target.dataDetectorTypes = value ?? [] } } public struct TextContainerInset: PropertyStyler { public static var propertyKey: String { return "textContainerInset" } - public static func apply(value: UIEdgeInsets?, to target: UIKit.UITextView) { + public static func apply(value: UIEdgeInsets?, to target: UIKit.UITextView, using bundle: Bundle) { target.textContainerInset = value ?? UIKit.UITextView().textContainerInset } } @@ -705,147 +747,206 @@ public extension Stylish.PropertyStylers { public struct AdjustsImageWhenDisabled: PropertyStyler { public static var propertyKey: String { return "adjustsImageWhenDisabled" } - public static func apply(value: Bool?, to target: UIKit.UIButton) { + public static func apply(value: Bool?, to target: UIKit.UIButton, using bundle: Bundle) { target.adjustsImageWhenDisabled = value ?? true } } public struct AdjustsImageWhenHighlighted: PropertyStyler { public static var propertyKey: String { return "adjustsImageWhenHighlighted" } - public static func apply(value: Bool?, to target: UIKit.UIButton) { + public static func apply(value: Bool?, to target: UIKit.UIButton, using bundle: Bundle) { target.adjustsImageWhenHighlighted = value ?? true } } public struct ShowsTouchWhenHighlighted: PropertyStyler { public static var propertyKey: String { return "showsTouchWhenHighlighted" } - public static func apply(value: Bool?, to target: UIKit.UIButton) { + public static func apply(value: Bool?, to target: UIKit.UIButton, using bundle: Bundle) { target.showsTouchWhenHighlighted = value ?? false } } public struct ContentEdgeInsets: PropertyStyler { public static var propertyKey: String { return "contentEdgeInsets" } - public static func apply(value: UIEdgeInsets?, to target: UIKit.UIButton) { + public static func apply(value: UIEdgeInsets?, to target: UIKit.UIButton, using bundle: Bundle) { target.contentEdgeInsets = value ?? UIKit.UIButton().contentEdgeInsets } } public struct TitleEdgeInsets: PropertyStyler { public static var propertyKey: String { return "titleEdgeInsets" } - public static func apply(value: UIEdgeInsets?, to target: UIKit.UIButton) { + public static func apply(value: UIEdgeInsets?, to target: UIKit.UIButton, using bundle: Bundle) { target.titleEdgeInsets = value ?? UIKit.UIButton().titleEdgeInsets } } public struct ImageEdgeInsets: PropertyStyler { public static var propertyKey: String { return "imageEdgeInsets" } - public static func apply(value: UIEdgeInsets?, to target: UIKit.UIButton) { + public static func apply(value: UIEdgeInsets?, to target: UIKit.UIButton, using bundle: Bundle) { target.imageEdgeInsets = value ?? UIKit.UIButton().imageEdgeInsets } } public struct TitleForNormalState: PropertyStyler { public static var propertyKey: String { return "titleForNormalState" } - public static func apply(value: String?, to target: UIKit.UIButton) { + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { target.setTitle(value, for: .normal) } } public struct TitleForHighlightedState: PropertyStyler { public static var propertyKey: String { return "titleForHighlightedState" } - public static func apply(value: String?, to target: UIKit.UIButton) { + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { target.setTitle(value, for: .highlighted) } } public struct TitleForDisabledState: PropertyStyler { public static var propertyKey: String { return "titleForDisabledState" } - public static func apply(value: String?, to target: UIKit.UIButton) { + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { target.setTitle(value, for: .disabled) } } public struct TitleColorForNormalState: PropertyStyler { public static var propertyKey: String { return "titleColorForNormalState" } - public static func apply(value: UIColor?, to target: UIKit.UIButton) { + public static func apply(value: UIColor?, to target: UIKit.UIButton, using bundle: Bundle) { target.setTitleColor(value, for: .normal) } } public struct TitleColorForHighlightedState: PropertyStyler { public static var propertyKey: String { return "titleColorForHighlightedState" } - public static func apply(value: UIColor?, to target: UIKit.UIButton) { + public static func apply(value: UIColor?, to target: UIKit.UIButton, using bundle: Bundle) { target.setTitleColor(value, for: .highlighted) } } public struct TitleColorForDisabledState: PropertyStyler { public static var propertyKey: String { return "titleColorForDisabledState" } - public static func apply(value: UIColor?, to target: UIKit.UIButton) { + public static func apply(value: UIColor?, to target: UIKit.UIButton, using bundle: Bundle) { target.setTitleColor(value, for: .disabled) } } public struct ImageForNormalState: PropertyStyler { public static var propertyKey: String { return "imageForNormalState" } - public static func apply(value: UIImage?, to target: UIKit.UIButton) { + public static func apply(value: UIImage?, to target: UIKit.UIButton, using bundle: Bundle) { target.setImage(value, for: .normal) } - public let value: UIImage? - public init(value: UIImage?) { - self.value = value + } + + public struct ImageNameForNormalState: PropertyStyler { + public static var propertyKey: String { return "imageNameForNormalState" } + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { + if let name = value { + target.setImage(UIImage(named: name, in: bundle, compatibleWith: target.traitCollection), for: .normal) + } } } public struct ImageForHighlightedState: PropertyStyler { public static var propertyKey: String { return "imageForHighlightedState" } - public static func apply(value: UIImage?, to target: UIKit.UIButton) { + public static func apply(value: UIImage?, to target: UIKit.UIButton, using bundle: Bundle) { target.setImage(value, for: .highlighted) } } + public struct ImageNameForHighlightedState: PropertyStyler { + public static var propertyKey: String { return "imageNameForHighlightedState" } + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { + if let name = value { + target.setImage(UIImage(named: name, in: bundle, compatibleWith: target.traitCollection), for: .highlighted) + } + } + } + public struct ImageForDisabledState: PropertyStyler { public static var propertyKey: String { return "imageForDisabledState" } - public static func apply(value: UIImage?, to target: UIKit.UIButton) { + public static func apply(value: UIImage?, to target: UIKit.UIButton, using bundle: Bundle) { target.setImage(value, for: .disabled) } } + public struct ImageNameForDisabledState: PropertyStyler { + public static var propertyKey: String { return "imageNameForDisabledState" } + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { + if let name = value { + target.setImage(UIImage(named: name, in: bundle, compatibleWith: target.traitCollection), for: .disabled) + } + } + } + public struct BackgroundImageForNormalState: PropertyStyler { public static var propertyKey: String { return "backgroundImageForNormalState" } - public static func apply(value: UIImage?, to target: UIKit.UIButton) { + public static func apply(value: UIImage?, to target: UIKit.UIButton, using bundle: Bundle) { target.setBackgroundImage(value, for: .normal) } } + public struct BackgroundImageNameForNormalState: PropertyStyler { + public static var propertyKey: String { return "backgroundImageNameForNormalState" } + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { + if let name = value { + target.setBackgroundImage(UIImage(named: name, in: bundle, compatibleWith: target.traitCollection), for: .normal) + } + } + } + public struct BackgroundImageForHighlightedState: PropertyStyler { public static var propertyKey: String { return "backgroundImageForHighlightedState" } - public static func apply(value: UIImage?, to target: UIKit.UIButton) { + public static func apply(value: UIImage?, to target: UIKit.UIButton, using bundle: Bundle) { target.setBackgroundImage(value, for: .highlighted) } } + public struct BackgroundImageNameForHighlightedState: PropertyStyler { + public static var propertyKey: String { return "backgroundImageNameForHighlightedState" } + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { + if let name = value { + target.setBackgroundImage(UIImage(named: name, in: bundle, compatibleWith: target.traitCollection), for: .highlighted) + } + } + } + public struct BackgroundImageForDisabledState: PropertyStyler { public static var propertyKey: String { return "backgroundImageForDisabledState" } - public static func apply(value: UIImage?, to target: UIKit.UIButton) { + public static func apply(value: UIImage?, to target: UIKit.UIButton, using bundle: Bundle) { target.setBackgroundImage(value, for: .disabled) } } + + public struct BackgroundImageNameForDisabledState: PropertyStyler { + public static var propertyKey: String { return "backgroundImageNameForDisabledState" } + public static func apply(value: String?, to target: UIKit.UIButton, using bundle: Bundle) { + if let name = value { + target.setBackgroundImage(UIImage(named: name, in: bundle, compatibleWith: target.traitCollection), for: .disabled) + } + } + } } public class UIImageView: UIView { public struct Image: PropertyStyler { public static var propertyKey: String { return "image" } - public static func apply(value: UIImage?, to target: UIKit.UIImageView) { + public static func apply(value: UIImage?, to target: UIKit.UIImageView, using bundle: Bundle) { target.image = value } } + public struct ImageName: PropertyStyler { + public static var propertyKey: String { return "imageName" } + public static func apply(value: String?, to target: UIKit.UIImageView, using bundle: Bundle) { + if let name = value { + target.image = UIImage(named: name, in: bundle, compatibleWith: target.traitCollection) + } + } + } + public struct ImageURL: PropertyStyler { public static var propertyKey: String { return "imageURL" } - public static func apply(value: URL?, to target: UIKit.UIImageView) { + public static func apply(value: URL?, to target: UIKit.UIImageView, using bundle: Bundle) { if let url = value { #if TARGET_INTERFACE_BUILDER target.image = UIImage(named: "StylishPlaceholderImage", in: Bundle(for:StyleableUIView.self), compatibleWith: nil) @@ -868,50 +969,77 @@ public extension Stylish.PropertyStylers { public struct HighlightedImage: PropertyStyler { public static var propertyKey: String { return "highlightedImage" } - public static func apply(value: UIImage?, to target: UIKit.UIImageView) { + public static func apply(value: UIImage?, to target: UIKit.UIImageView, using bundle: Bundle) { target.highlightedImage = value } } + public struct HighlightedImageName: PropertyStyler { + public static var propertyKey: String { return "highlightedImageName" } + public static func apply(value: String?, to target: UIKit.UIImageView, using bundle: Bundle) { + if let name = value { + target.highlightedImage = UIImage(named: name, in: bundle, compatibleWith: target.traitCollection) + } + } + } + @available(iOS 11.0, *) public struct AdjustsImageSizeForAccessibilityContentSizeCategory: PropertyStyler { public static var propertyKey: String { return "adjustsImageSizeForAccessibilityContentSizeCategory" } - public static func apply(value: Bool?, to target: UIKit.UIImageView) { + public static func apply(value: Bool?, to target: UIKit.UIImageView, using bundle: Bundle) { target.adjustsImageSizeForAccessibilityContentSizeCategory = value ?? false } } public struct AnimationDuration: PropertyStyler { public static var propertyKey: String { return "animationDuration" } - public static func apply(value: Double?, to target: UIKit.UIImageView) { + public static func apply(value: Double?, to target: UIKit.UIImageView, using bundle: Bundle) { target.animationDuration = value ?? Double((target.animationImages ?? []).count) * 0.0333333 } } public struct AnimationRepeatCount: PropertyStyler { public static var propertyKey: String { return "animationRepeatCount" } - public static func apply(value: Int?, to target: UIKit.UIImageView) { + public static func apply(value: Int?, to target: UIKit.UIImageView, using bundle: Bundle) { target.animationRepeatCount = value ?? 0 } } public struct AnimationImages: PropertyStyler { public static var propertyKey: String { return "animationImages" } - public static func apply(value: UIImageArray?, to target: UIKit.UIImageView) { + public static func apply(value: UIImageArray?, to target: UIKit.UIImageView, using bundle: Bundle) { target.animationImages = value?.images } } + public struct AnimationImageNames: PropertyStyler { + public static var propertyKey: String { return "animationImageNames" } + public static func apply(value: StringArray?, to target: UIKit.UIImageView, using bundle: Bundle) { + if let names = value?.strings { + target.animationImages = names.compactMap{ UIImage(named: $0, in: bundle, compatibleWith: target.traitCollection) } + } + } + } + public struct HighlightedAnimationImages: PropertyStyler { public static var propertyKey: String { return "highlightedAnimationImages" } - public static func apply(value: UIImageArray?, to target: UIKit.UIImageView) { + public static func apply(value: UIImageArray?, to target: UIKit.UIImageView, using bundle: Bundle) { target.highlightedAnimationImages = value?.images } } + public struct HighlightedAnimationImageNames: PropertyStyler { + public static var propertyKey: String { return "highlightedAnimationImageNames" } + public static func apply(value: StringArray?, to target: UIKit.UIImageView, using bundle: Bundle) { + if let names = value?.strings { + target.highlightedAnimationImages = names.compactMap{ UIImage(named: $0, in: bundle, compatibleWith: target.traitCollection) } + } + } + } + public struct IsAnimating: PropertyStyler { public static var propertyKey: String { return "isAnimating" } - public static func apply(value: Bool?, to target: UIKit.UIImageView) { + public static func apply(value: Bool?, to target: UIKit.UIImageView, using bundle: Bundle) { if value == true { target.startAnimating() } else { target.stopAnimating() } } } @@ -928,7 +1056,7 @@ public struct ErrorStyle: Style { public struct UIViewStripedSubviewStyler: PropertyStyler { public static var propertyKey:String { return "stripedSubview" } private static let tag = 298529835 - public static func apply(value: UIColor?, to target: Styleable) { + public static func apply(value: UIColor?, to target: Styleable, using bundle: Bundle) { if let target = target as? UIView, let value = value { target.viewWithTag(tag)?.removeFromSuperview() let context = CIContext() diff --git a/Stylish/StylesheetParseableExtensions.swift b/Stylish/StylesheetParseableExtensions.swift index b782ed9..15c2e5c 100644 --- a/Stylish/StylesheetParseableExtensions.swift +++ b/Stylish/StylesheetParseableExtensions.swift @@ -47,6 +47,16 @@ extension String: StylesheetParseable { } } +public struct StringArray: StylesheetParseable { + public static func parse(from stylesheetValue: Any) -> StringArray? { + return StringArray(strings: (stylesheetValue as? [String]) ?? []) + } + public let strings: [String] + public init(strings: [String]) { + self.strings = strings + } +} + extension Double: StylesheetParseable { public static func parse(from stylesheetValue: Any) -> Double? { return stylesheetValue as? Double diff --git a/Stylish/Stylish.swift b/Stylish/Stylish.swift index 01c0446..97fcc55 100644 --- a/Stylish/Stylish.swift +++ b/Stylish/Stylish.swift @@ -39,12 +39,15 @@ public protocol Style { var propertyStylers: [AnyPropertyStyler] { get } } -/// The protocol a type must conform to in order to be used as a Stylesheet. A Stylesheet is simply a dictionary of Styles, each associated with a name +/// The protocol a type must conform to in order to be used as a Stylesheet. A Stylesheet is simply a dictionary of Styles, each associated with a name. A Stylesheet must also return the bundle it is associated with, in order for Styles / Property Stylers to know what bundle to retrieve images, colors, or other assets from public protocol Stylesheet: class { var styles: [String: Style] { get } + var bundle: Bundle { get } } extension Stylesheet { + /// The default implementation returns the Bundle that the Stylesheet class itself is a member of + public var bundle: Bundle { return Bundle(for: type(of: self)) } subscript(_ styleName: String) -> Style? { return styles[styleName] } @@ -59,12 +62,25 @@ public protocol PropertyStyler: AnyPropertyStylerType { associatedtype PropertyType: StylesheetParseable associatedtype TargetType static var propertyKey: String { get } - static func apply(value: PropertyType?, to target: TargetType) + static func apply(value: PropertyType?, to target: TargetType, using bundle: Bundle) } public extension PropertyStyler { public static func set(value: PropertyType?) -> AnyPropertyStyler { - return AnyPropertyStyler{ if let target = $0 as? TargetType { Self.apply(value: value, to: target) } } + return AnyPropertyStyler { + if let target = $0 as? TargetType { + Self.apply(value: value, to: target, using: $1) + } + } + } + + public static func set(value: @escaping (Bundle, UITraitCollection?) -> PropertyType?) -> AnyPropertyStyler { + return AnyPropertyStyler { + if let target = $0 as? TargetType { + let value = value($1, (target as? UITraitEnvironment)?.traitCollection) + Self.apply(value: value, to: target, using: $1) + } + } } } @@ -81,12 +97,12 @@ public extension PropertyStyler { /// Type-erased property styler, needed to hold arrays of them public struct AnyPropertyStyler { - private let propertyValueApplicator: (Styleable) -> () - internal init(propertyValueApplicator: @escaping (Styleable) -> ()) { + private let propertyValueApplicator: (Styleable, Bundle) -> () + internal init(propertyValueApplicator: @escaping (Styleable, Bundle) -> ()) { self.propertyValueApplicator = propertyValueApplicator } - internal func apply(to target: Styleable) { - propertyValueApplicator(target) + internal func apply(to target: Styleable, using bundle: Bundle) { + propertyValueApplicator(target, bundle) } } @@ -119,21 +135,21 @@ public func +(left: Stylesheet, right: Stylesheet) -> Stylesheet { /// A way to hold a reference to a Property Styler type itself, in a type-erased manner (for holding in arrays), and then creating a type-erased instance of the Property Styler Type as an AnyPropertyStyler on demand from either json data or an initial value. internal struct AnyPropertyStylerTypeWrapper { private let jsonInitializer:(String, Any) -> AnyPropertyStyler? - private let applicator: (Any?, Styleable) -> () + private let applicator: (Any?, Styleable, Bundle) -> () internal let propertyKey: String internal init(_ propertyStylerType: T.Type) { self.propertyKey = propertyStylerType.propertyKey - let applicator: (Any?, Styleable) -> () = { - value, target in + let applicator: (Any?, Styleable, Bundle) -> () = { + value, target, bundle in if let value = value as? T.PropertyType?, let target = target as? T.TargetType { - T.apply(value: value, to: target) + T.apply(value: value, to: target, using: bundle) } } self.jsonInitializer = { propertyName, propertyValue in guard propertyName == T.propertyKey else { return nil } - if propertyValue is NSNull { return AnyPropertyStyler { applicator(nil, $0) } } - if let parsedValue = T.PropertyType.parse(from: propertyValue) { return AnyPropertyStyler { applicator(parsedValue, $0) } } + if propertyValue is NSNull { return AnyPropertyStyler { applicator(nil, $0, $1) } } + if let parsedValue = T.PropertyType.parse(from: propertyValue) { return AnyPropertyStyler { applicator(parsedValue, $0, $1) } } return nil } self.applicator = applicator @@ -224,7 +240,7 @@ public struct Stylish { if hasInvalidStyleName { combinedStyle = combinedStyle + ErrorStyle() } #endif - applyStyle(combinedStyle, to: target) + applyStyle(combinedStyle, to: target, using: resolvedStylesheet) // Don't attempt the view hierarchy refresh if rendering in Interface Builder as an IBDesignable, since IB doesn't maintain the same kind of view hierarchy #if !TARGET_INTERFACE_BUILDER @@ -236,8 +252,8 @@ public struct Stylish { } /// Applies a single Style instance to the target Stylable object - public static func applyStyle(_ style: Style, to target: Styleable) { - style.propertyStylers.forEach { $0.apply(to: target) } + public static func applyStyle(_ style: Style, to target: Styleable, using stylesheet: Stylesheet?) { + style.propertyStylers.forEach { $0.apply(to: target, using: stylesheet?.bundle ?? Bundle.main) } } /// Refreshes the styles of all views in the app, in the event of a stylesheet change or update, etc. diff --git a/StylishExample/StylishExample/ProgressBar.swift b/StylishExample/StylishExample/ProgressBar.swift index b4433a3..700329e 100755 --- a/StylishExample/StylishExample/ProgressBar.swift +++ b/StylishExample/StylishExample/ProgressBar.swift @@ -42,21 +42,21 @@ import UIKit // 2. Create custom PropertyStylers that define a property key that can be read out of json, and a way to set the styleable properties of the ProgressBar component. These can be private to the type if you are only using JSON stylesheets and no code-created stylesheets struct ProgressColor: PropertyStyler { static var propertyKey: String { return "progressColor" } - static func apply(value: UIColor?, to target: ProgressBar) { + static func apply(value: UIColor?, to target: ProgressBar, using bundle: Bundle) { target.progressColor = value ?? .gray } } struct ProgressTrackColor: PropertyStyler { static var propertyKey: String { return "progressTrackColor" } - static func apply(value: UIColor?, to target: ProgressBar) { + static func apply(value: UIColor?, to target: ProgressBar, using bundle: Bundle) { target.trackColor = value ?? .white } } struct ProgressCornerRadiusRatio: PropertyStyler { static var propertyKey: String { return "progressCornerRadiusRatio" } - static func apply(value: CGFloat?, to target: ProgressBar) { + static func apply(value: CGFloat?, to target: ProgressBar, using bundle: Bundle) { target.progressCornerRadiusPercentage = value ?? 0 } } @@ -98,8 +98,8 @@ import UIKit var progressCornerRadiusPercentage:CGFloat = 0.0 { didSet { updateProgress() - trackView.layer.cornerRadius = layer.cornerRadius progressView.layer.cornerRadius = progressView.bounds.height * progressCornerRadiusPercentage + trackView.layer.cornerRadius = progressView.layer.cornerRadius } }