// // Styler.swift // MVMCoreUI // // Created by Kevin Christiano on 4/1/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // import Foundation import MVMCore public protocol VogueProtocol { } public protocol VogueViewProtocol { } public protocol VogueTextProtocol: VogueProtocol { func styleFont(_ font: UIFont) func styleTextColor(_ textColor: UIColor) } struct Padding { static let One: CGFloat = 6 static let Two: CGFloat = 12 static let Three: CGFloat = 18 static let Four: CGFloat = 24 static let Five: CGFloat = 30 static let Six: CGFloat = 36 static let Seven: CGFloat = 42 static let Eight: CGFloat = 48 static let Nine: CGFloat = 54 static let Ten: CGFloat = 60 static let TableCellParagraphSpace: CGFloat = 3 static let FooterLabelParagraphSpace: CGFloat = 4 static let WebViewInset: CGFloat = 8 static let HeightTableSeperatorHeight: CGFloat = 1 static let MFHeightForSwitch: CGFloat = 22 static let MFWidthForSwitch: CGFloat = 42 static let DisableOppacity: CGFloat = 0.5 static let PaymentMethodViewHeightWidthMultiplier: CGFloat = 0.55 static let MinCellHeight: CGFloat = 96 static let HeightIphone5: CGFloat = 568 static let DefaultOptionCellHeight: CGFloat = 120 static let PromoViewHeight: CGFloat = 41.9 static let BetweenFields: CGFloat = 24 static let LabelWithInternalButtonLineSpace: CGFloat = 2 static let PrimaryButtonTop: CGFloat = 36 struct Default { static let Standard: CGFloat = 24 static let HorizontalSpacing: CGFloat = 32 static let VerticalSpacing: CGFloat = 32 static let VerticalSpacing3: CGFloat = 24 } struct Horizontal { static let HeadlineWhiteView: CGFloat = 60 static let Large: CGFloat = 72 static let BetweenRelatedItems: CGFloat = 16 } struct Vertical { static let WhiteGrayView: CGFloat = 72 static let HeadlineAlternate: CGFloat = 48 } } public class Styler { enum MFViewBorder: Int { case top case left case bottom case right } enum MFTimeFormatUnit: Int { case mfTimeFormatColon = 0 //!{days} : {hour} : {minutes} : {seconds} case mfTimeFormatNormal = 1 // will end with days hours minutes seconds, when left days less than 2, it will change to 'day' } //-------------------------------------------------- // MARK: - Enum //-------------------------------------------------- public enum Style: String { case H1 case H2 case H3 case H32 case B1 case B2 case B3 case B20 func font(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 0 switch self { case .H1: size = genericScaling ? sizeFontGeneric(forCurrentDevice: size) : 40 return MFFonts.mfFont75Bd(size) case .H2: size = genericScaling ? sizeFontGeneric(forCurrentDevice: size) : 25 return MFFonts.mfFont75Bd(size) case .H3: size = genericScaling ? sizeFontGeneric(forCurrentDevice: size) : 18 return MFFonts.mfFont75Bd(size) case .H32: size = genericScaling ? sizeFontGeneric(forCurrentDevice: size) : 32 return MFFonts.mfFont75Bd(size) case .B1: size = genericScaling ? sizeFontGeneric(forCurrentDevice: size) : 13 return MFFonts.mfFont75Bd(size) case .B2: size = genericScaling ? sizeFontGeneric(forCurrentDevice: size) : 13 return MFFonts.mfFont55Rg(size) case .B3: size = genericScaling ? sizeFontGeneric(forCurrentDevice: size) : 11 return MFFonts.mfFont55Rg(size) case .B20: size = genericScaling ? sizeFontGeneric(forCurrentDevice: size) : 20 return MFFonts.mfFont55Rg(size) } } } public enum Tier { case primary case secondary case ternary case quaternary } //-------------------------------------------------- // MARK: - Functions //-------------------------------------------------- class func splitTextFieldWidth() -> CGFloat { return splitTextFieldWidth(forViewWidth: MVMCoreUISplitViewController.getDetailViewWidth()) } class func splitTextFieldWidth(forViewWidth width: CGFloat) -> CGFloat { return (width - CGFloat(PaddingOne)) / 2 - defaultHorizontalPaddingForApplicationWidth() } class func sizeObjectGeneric(forCurrentDevice size: CGFloat) -> MFSizeObject? { let sizeObject = MFSizeObject(standardSize: size, standardiPadPortraitSize: size * 1.3) sizeObject?.addLargerThanCustomSize(size * 1.4, forThreshold: MFSizeStandardiPadLandscapeThreshold) sizeObject?.addLargerThanCustomSize(size * 1.5, forThreshold: MFSizeiPadProLandscapeThreshold) return sizeObject } class func sizeFontGeneric(forCurrentDevice size: CGFloat) -> CGFloat { return sizeObjectGeneric(forCurrentDevice: size)?.getValueBasedOnApplicationWidth() ?? 0 } //-------------------------------------------------- // MARK: - Spacing //-------------------------------------------------- class func defaultHorizontalPaddingForApplicationWidth() -> CGFloat { return MFSizeObject(scalingStandardSize: PaddingDefaultHorizontalSpacing)?.getValueBasedOnApplicationWidth() ?? 0 } class func defaultVerticalPaddingForApplicationWidth() -> CGFloat { return MFSizeObject(scalingStandardSize: PaddingDefaultVerticalSpacing)?.getValueBasedOnApplicationWidth() ?? 0 } class func defaultHorizontalPadding(forSize size: CGFloat) -> CGFloat { return MFSizeObject(scalingStandardSize: PaddingDefaultHorizontalSpacing)?.getValueBased(onSize: size) ?? 0 } class func defaultVerticalPadding(forSize size: CGFloat) -> CGFloat { return MFSizeObject(scalingStandardSize: PaddingDefaultVerticalSpacing)?.getValueBased(onSize: size) ?? 0 } class func setDefaultMarginsFor(_ view: UIView?, size: CGFloat) { setDefaultMarginsFor(view, size: size, horizontal: true, vertical: false) } class func setDefaultMarginsFor(_ view: UIView?, size: CGFloat, horizontal: Bool, vertical: Bool) { let horizontalPadding: CGFloat = horizontal ? defaultHorizontalPadding(forSize: size) : 0 let verticalPadding: CGFloat = vertical ? PaddingDefaultVerticalSpacing3 : 0 DispatchQueue.main.async { MVMCoreUIUtility.setMarginsFor(view, leading: horizontalPadding, top: verticalPadding, trailing: horizontalPadding, bottom: verticalPadding) } } class func setMarginsFor(_ view: UIView?, size: CGFloat, defaultHorizontal horizontal: Bool, top: CGFloat, bottom: CGFloat) { let horizontalPadding: CGFloat = horizontal ? defaultHorizontalPadding(forSize: size) : 0 DispatchQueue.main.async { MVMCoreUIUtility.setMarginsFor(view, leading: horizontalPadding, top: top, trailing: horizontalPadding, bottom: bottom) } } //-------------------------------------------------- // MARK: - Fonts //-------------------------------------------------- class func fontH1(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 40 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontH2(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 25 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontH3(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 18 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontH32(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 32 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontB1(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 13 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontB2(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 13 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func fontB3(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 11 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func fontB20(_ genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 20 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } //-------------------------------------------------- // MARK: - Styles //-------------------------------------------------- class func styleLabel(_ label: VogueTextProtocol, withStyle style: Style, genericScaling: Bool) { switch style { case .H1: styleLabelH1(label, genericScaling: genericScaling) case .H2: styleLabelH2(label, genericScaling: genericScaling) case .H3: styleLabelH3(label, genericScaling: genericScaling) case .H32: styleLabelH32(label, genericScaling: genericScaling) case .B1: styleLabelB1(label, genericScaling: genericScaling) case .B2: styleLabelB2(label, genericScaling: genericScaling) case .B3: styleLabelB3(label, genericScaling: genericScaling) case .B20: styleLabelB20(label, genericScaling: genericScaling) } } class func styleLabel(_ label: UILabel, withStyle style: Style) { styleLabel(label, withStyle: style, genericScaling: true) } class func styleLabelH1(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.black) if let h1 = fontH1(genericScaling) { label.styleFont(h1) } } class func styleLabelH2(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.black) if let h2 = fontH2(genericScaling) { label.styleFont(h2) } } class func styleLabelH3(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.black) if let h3 = fontH3(genericScaling) { label.styleFont(h3) } } class func styleLabelH32(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.black) if let h32 = fontH32(genericScaling) { label.styleFont(h32) } } class func styleLabelB1(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.black) if let b1 = fontB1(genericScaling) { label.styleFont(b1) } } class func styleLabelB2(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.black) if let b2 = fontB2(genericScaling) { label.styleFont(b2) } } class func styleLabelB2(_ label: UILabel, size: CGFloat, genericScaling: Bool = true) { label.font = fontForBody(withSize: size, genericScaling: genericScaling) } class func styleLabelB3(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.mfBackgroundGray()) if let b3 = fontB3(genericScaling) { label.styleFont(b3) } } class func styleLabelB20(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.black) if let b20 = fontB20(genericScaling) { label.styleFont(b20) } } class func styleLabelTextStyle2(_ label: VogueTextProtocol, genericScaling: Bool = true) { label.styleTextColor(.mfBattleshipGrey()) if let b2 = fontB2(genericScaling) { label.styleFont(b2) } } class func fontForBody(withSize size: CGFloat, genericScaling: Bool) -> UIFont? { var size = size if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func fontForBody(withSize size: CGFloat, forWidth width: CGFloat) -> UIFont? { let size = sizeObjectGeneric(forCurrentDevice: size)?.getValueBased(onSize: width) ?? size return MFFonts.mfFont55Rg(size) } //-------------------------------------------------- // MARK: - 1.0 Fonts //-------------------------------------------------- class func font(forPlan genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 100 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func font(forBiggerHeadLine genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 48 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func font(forHeadlineSmall genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 15 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func font(forHeadlineSmall2 genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 16 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontForHeadlineSmall2(forWidth size: CGFloat) -> UIFont? { var pointSize: CGFloat = 16 pointSize = Styler.sizeObjectGeneric(forCurrentDevice: pointSize)!.getValueBased(onSize: size) return MFFonts.mfFont75Bd(pointSize) } class func fontB1(forWidth size: CGFloat) -> UIFont? { var pointSize: CGFloat = 13 pointSize = Styler.sizeObjectGeneric(forCurrentDevice: pointSize)!.getValueBased(onSize: size) return MFFonts.mfFont75Bd(pointSize) } //-------------------------------------------------- // MARK: - 1.0 Styles //-------------------------------------------------- class func styleFeedCardTitleLabel(_ label: UILabel) { label.font = Styler.fontForFeedCardTitle() label.textColor = .black } class func styleFeedCardTagLabel(_ label: UILabel) { label.font = Styler.fontB3() label.textColor = .mfBrownishGrey() } class func styleStandardSeparatorView(_ view: UIView) { view.backgroundColor = .mfBackgroundGray() } class func styleLabelHeadlineSmall(_ label: UILabel, genericScaling: Bool) { label.font = Styler.font(forHeadlineSmall: genericScaling) label.textColor = .black } class func styleFeedCardTitleLabel(_ label: UILabel, genericScaling: Bool) { label.font = Styler.font(forFeedCardTitle: genericScaling) label.textColor = UIColor.black } class func styleFeedCardTagLabel(_ label: UILabel, genericScaling: Bool) { label.font = Styler.fontB3(genericScaling) label.textColor = UIColor.mfBrownishGrey() } class func fontB2(forWidth size: CGFloat) -> UIFont? { var pointSize: CGFloat = 13 pointSize = Styler.sizeObjectGeneric(forCurrentDevice: pointSize)!.getValueBased(onSize: size) return MFFonts.mfFont55Rg(pointSize) } class func fontforChatText(_ genericScaling: Bool = false) -> UIFont? { var size: CGFloat = 14 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func font(forAccountLandingGreeting genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 16 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func font(forProgressBarBottomLabel genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 10 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func font(forFeedCardTitle genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 16 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func font(forPrimaryButton genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 14 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontForPrimaryButton(forWidth size: CGFloat) -> UIFont? { var pointSize: CGFloat = 14 pointSize = Styler.sizeObjectGeneric(forCurrentDevice: pointSize)!.getValueBased(onSize: size) return MFFonts.mfFont75Bd(pointSize) } class func font(forSmallButton genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 11 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontForSmallButton(forWidth size: CGFloat) -> UIFont? { var pointSize: CGFloat = 11 pointSize = Styler.sizeObjectGeneric(forCurrentDevice: pointSize)!.getValueBased(onSize: size) return MFFonts.mfFont75Bd(pointSize) } class func font(forTextField genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 16 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func font(forTextFieldUnderLabel genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 12 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func fontForUnreadMessage(onSupport genericScaling: Bool = false) -> UIFont? { var size: CGFloat = 10 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func font5GMessage(_ genericScaling: Bool) -> UIFont? { var size: CGFloat = 16 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func font5GMessage() -> UIFont? { return font5GMessage(true) } class func font(forHeadlineAlternative genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 24 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func fontForHeadlineAlternative(forWidth size: CGFloat) -> UIFont? { var pointSize: CGFloat = 24 pointSize = Styler.sizeObjectGeneric(forCurrentDevice: pointSize)!.getValueBased(onSize: size) return MFFonts.mfFont55Rg(pointSize) } class func fontH255(_ genericScaling: Bool) -> UIFont? { var size: CGFloat = 25 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func font(forLargeLoyaltyHeaderTitle genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 60 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func font(forLoyaltyTitleSmall genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 42 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func font(forLoyaltyMessage genericScaling: Bool = true) -> UIFont? { var size: CGFloat = 20 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont55Rg(size) } class func font(forPtPCard genericScaling: Bool) -> UIFont? { var size: CGFloat = 22 if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontForLabelWithTopLeftCircle(withSize size: CGFloat, genericScaling: Bool) -> UIFont? { var size = size if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFont75Bd(size) } class func fontOcratxtWitSize(_ size: CGFloat, genericScaling: Bool) -> UIFont? { var size = size if genericScaling { size = sizeFontGeneric(forCurrentDevice: size) } return MFFonts.mfFontOcratxt(size) } class func boldFont(forScaledSize size: CGFloat) -> UIFont { return MFFonts.mfFont75Bd(sizeFontGeneric(forCurrentDevice: size))! } class func regularFont(forScaledSize size: CGFloat) -> UIFont { return MFFonts.mfFont55Rg(sizeFontGeneric(forCurrentDevice: size))! } //-------------------------------------------------- // MARK: - 1.0 Attributed Strings Style //-------------------------------------------------- class func styleGetAttributedString(_ string: String?, withStyle style: String?) -> NSAttributedString { return styleGetAttributedString(string, withStyle: Styler.Style(rawValue: style!)!, genericScaling: true) } class func styleGetAttributedString(_ string: String?, withStyle style: Style, genericScaling: Bool) -> NSAttributedString { switch style { case .H1: return styleGetH1AttributedString(string, genericScaling: genericScaling) case .H2: return styleGetH2AttributedString(string, genericScaling: genericScaling) case .H3: return styleGetH3AttributedString(string, genericScaling: genericScaling) case .H32: return styleGetH32AttributedString(string, genericScaling: genericScaling) case .B1: return styleGetB1AttributedString(string, genericScaling: genericScaling) case .B2: return styleGetB2AttributedString(string, genericScaling: genericScaling) case .B3: return styleGetB3AttributedString(string, genericScaling: genericScaling) case .B20: return styleGetB20AttributedString(string, genericScaling: genericScaling) } } class func styleGetAttributedString(_ string: String?, font: UIFont, color: UIColor) -> NSAttributedString { var attributedString: NSAttributedString? = nil if let string = string, !string.isEmpty { attributedString = NSAttributedString(string: string, attributes: [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: color]) } else { attributedString = NSAttributedString(string: "") } return attributedString! } class func styleGetH1AttributedString(_ string: String?, genericScaling: Bool = true) -> NSAttributedString { return styleGetAttributedString(string, font: fontH1(genericScaling)!, color: .black) } class func styleGetH2AttributedString(_ string: String?, genericScaling: Bool = true) -> NSAttributedString { return styleGetAttributedString(string, font: fontH2(genericScaling)!, color: .black) } class func styleGetH3AttributedString(_ string: String?, genericScaling: Bool = true) -> NSAttributedString { return styleGetAttributedString(string, font: fontH3(genericScaling)!, color: .black) } class func styleGetH32AttributedString(_ string: String?, genericScaling: Bool = true) -> NSAttributedString { return styleGetAttributedString(string, font: fontH32(genericScaling)!, color: .black) } class func styleGetB1AttributedString(_ string: String?, genericScaling: Bool = true) -> NSAttributedString { return styleGetAttributedString(string, font: fontB1(genericScaling)!, color: .black) } class func styleGetB2AttributedString(_ string: String?, genericScaling: Bool = true) -> NSAttributedString { return styleGetAttributedString(string, font: fontB2(genericScaling)!, color: .black) } class func styleGetB3AttributedString(_ string: String?, genericScaling: Bool = true) -> NSAttributedString { return styleGetAttributedString(string, font: fontB3(genericScaling)!, color: .mfBattleshipGrey()) } class func styleGetB20AttributedString(_ string: String?, genericScaling: Bool = true) -> NSAttributedString { return styleGetAttributedString(string, font: fontB20(genericScaling)!, color: .black) } class func styleGetTopAlignedAttributeString(withLeftStringRightTop left: String?, center: String, rightString right: String?, withCenterStringFontSize fontSize: CGFloat, andColor color: UIColor) -> NSAttributedString { var left = left ?? "" var center = center var right = right ?? "" let text = "\(left)\(center)\(right)" let attribs = [NSAttributedString.Key.foregroundColor: color] var attributedText = NSMutableAttributedString(string: text, attributes: attribs) let centerRange = (text as NSString).range(of: center) let centerFont = MFFonts.mfFont75Bd(fontSize) let centerHeight = centerFont?.capHeight ?? 0.0 attributedText.addAttributes([NSAttributedString.Key.font: MFFonts.mfFont75Bd(fontSize) as Any], range: centerRange) let leftRange = (text as NSString).range(of: left) let leftFont = MFFonts.mfFont75Bd(fontSize * 0.34) let leftHeight = leftFont?.capHeight ?? 0.0 if let leftFont = leftFont { attributedText.addAttributes([NSAttributedString.Key.font: leftFont, NSAttributedString.Key.baselineOffset: NSNumber(value: Float(centerHeight - leftHeight))], range: leftRange) } let rightRange = NSRange(location: centerRange.location + centerRange.length, length: right.count ) let rightFont = MFFonts.mfFont75Bd(fontSize * 0.34) let offset = Float((centerFont?.pointSize ?? 0.0) - (centerFont?.capHeight ?? 0.0) + (rightFont?.pointSize ?? 0.0) / 2) if let rightFont = rightFont { attributedText.addAttributes([NSAttributedString.Key.font: rightFont, NSAttributedString.Key.baselineOffset: offset], range: rightRange) } return attributedText } class func styleGetAlignCenteredAttrituedString(_ string: inout NSMutableAttributedString?) { if let string = string, string.length > 0 { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = .center string.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: string.length)) } } class func styleGetBoldString(with inputFont: UIFont?, from inputString: String?) -> NSAttributedString? { let openingRange = (inputString as NSString?)?.range(of: "{") let closingRange = (inputString as NSString?)?.range(of: "}") let attrString = NSMutableAttributedString(string: inputString ?? "") if openingRange?.location != NSNotFound && closingRange?.location != NSNotFound { let boldLength = (closingRange?.location ?? 0) - (openingRange?.location ?? 0) if let inputFont = inputFont { attrString.setAttributes([NSAttributedString.Key.font: inputFont], range: NSRange(location: openingRange?.location ?? 0, length: boldLength)) } if let closingRange = closingRange { attrString.replaceCharacters(in: closingRange, with: "") } if let openingRange = openingRange { attrString.replaceCharacters(in: openingRange, with: "") } } return attrString } //-------------------------------------------------- // MARK: - Gradient Colors //-------------------------------------------------- class func gradientSpecialTicketGold() -> [AnyHashable] { return [UIColor(red: 0.72, green: 0.6, blue: 0.33, alpha: 1), UIColor(red: 1, green: 0.85, blue: 0.52, alpha: 1), UIColor(red: 1, green: 0.85, blue: 0.52, alpha: 1), UIColor(red: 1, green: 0.85, blue: 0.52, alpha: 1), UIColor(red: 0.6, green: 0.42, blue: 0.07, alpha: 1)] } class func gradientSpecialTicketGoldCGColor() -> [AnyHashable] { return [UIColor(red: 0.72, green: 0.6, blue: 0.33, alpha: 1).cgColor, UIColor(red: 1, green: 0.85, blue: 0.52, alpha: 1).cgColor, UIColor(red: 1, green: 0.85, blue: 0.52, alpha: 1).cgColor, UIColor(red: 1, green: 0.85, blue: 0.52, alpha: 1).cgColor, UIColor(red: 0.6, green: 0.42, blue: 0.07, alpha: 1).cgColor].compactMap { $0 } } class func styleGetLowCaseSpace(_ inputString: String?) -> String? { if (inputString?.count ?? 0) > 0 { let trimmedString = inputString?.lowercased().trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) return trimmedString } return "" } class func labelStrokeAttributes(_ color: UIColor?) -> [AnyHashable : Any]? { guard let color = color else { return nil } return [NSAttributedString.Key.strokeColor: color, NSAttributedString.Key.strokeWidth: -1.0] } class func mfStyleBlackPageControl(_ pageControl: UIPageControl?) { pageControl?.pageIndicatorTintColor = .mfLighterGray() pageControl?.currentPageIndicatorTintColor = .black } //-------------------------------------------------- // MARK: - Custom Styling Views //-------------------------------------------------- class func styleView(_ view: UIView, show border: MFViewBorder, with color: UIColor?, borderLineWidth: CGFloat, borderLineLength borderLineLengh: CGFloat) { let borderLine = UIView(frame: .zero) borderLine.translatesAutoresizingMaskIntoConstraints = false view.addSubview(borderLine) switch border { case .top: NSLayoutConstraint.constraintPinSubview(borderLine, pinTop: true, pinBottom: false, pinLeft: false, pinRight: false) NSLayoutConstraint.constraintPinView(borderLine, heightConstraint: true, heightConstant: borderLineWidth, widthConstraint: true, widthConstant: borderLineLengh) NSLayoutConstraint.constraintPinSubview(borderLine, pinCenterX: true, pinCenterY: false) case .left: NSLayoutConstraint.constraintPinSubview(borderLine, pinTop: false, pinBottom: false, pinLeft: true, pinRight: false) NSLayoutConstraint.constraintPinView(borderLine, heightConstraint: true, heightConstant: borderLineLengh, widthConstraint: true, widthConstant: borderLineWidth) NSLayoutConstraint.constraintPinSubview(borderLine, pinCenterX: false, pinCenterY: true) case .bottom: NSLayoutConstraint.constraintPinSubview(borderLine, pinTop: false, pinBottom: true, pinLeft: false, pinRight: false) NSLayoutConstraint.constraintPinView(borderLine, heightConstraint: true, heightConstant: borderLineWidth, widthConstraint: true, widthConstant: borderLineLengh) NSLayoutConstraint.constraintPinSubview(borderLine, pinCenterX: true, pinCenterY: false) case .right: NSLayoutConstraint.constraintPinSubview(borderLine, pinTop: false, pinBottom: false, pinLeft: false, pinRight: true) NSLayoutConstraint.constraintPinView(borderLine, heightConstraint: true, heightConstant: borderLineLengh, widthConstraint: true, widthConstant: borderLineWidth) NSLayoutConstraint.constraintPinSubview(borderLine, pinCenterX: false, pinCenterY: true) default: break } borderLine.backgroundColor = color } class func mfStylePageControl(_ pageControl: UIPageControl?) { pageControl?.pageIndicatorTintColor = .mfLighterGray() pageControl?.currentPageIndicatorTintColor = .mfRed() } class func styleTextField(_ textField: UITextField) { textField.font = fontForTextField() // As per AKQA /* If the length of the text field exceeds the amount of space, the size of the text drops down. So, the entire line of copy can be read. 16 point font size is the lowest recommended size. */ textField.minimumFontSize = 16 textField.adjustsFontSizeToFitWidth = true // default is NO. if YES, text will shrink to minFontSize along baseline } /* class func setGradientTo(_ label: UILabel, withColors colors: [AnyHashable]) { var textSize: CGSize? = nil if let font = UIFont(name: label.font.fontName, size: label.font.lineHeight) { textSize = label.text?.size(withAttributes: [NSAttributedString.Key.baselineOffset: 0, NSAttributedString.Key.font: font]) } let width = (textSize?.width ?? 0.0) > 1024 ? 1024 : textSize?.width ?? 0.0 // max 1024 due to Core Graphics limitations let height = (textSize?.height ?? 0.0) > 1024 ? 1024 : textSize?.height ?? 0.0 // max 1024 due to Core Graphics limitations // create a new bitmap image context UIGraphicsBeginImageContext(CGSize(width: width, height: height)) let context = UIGraphicsGetCurrentContext() // push context to make it current (need to do this manually because we are not drawing in a UIView) if let context = context { UIGraphicsPushContext(context) } var glossGradient: CGGradient? var rgbColorspace: CGColorSpace? let num_locations = colors.count var locations = [CGFloat](repeating: 0.0, count: colors.count) let components = [CGFloat](repeating: 0.0, count: colors.count * 4) var componentIndex = 0 for i in 0.. UIImage? { UIGraphicsBeginImageContextWithOptions(image?.size ?? CGSize.zero, _: true, _: 1.0) let imageRect = CGRect(x: 0, y: 0, width: image?.size.width ?? 0.0, height: image?.size.height ?? 0.0) // Draw the image with the luminosity blend mode. // On top of a white background, this will give a black and white image. image?.draw(in: imageRect, blendMode: .luminosity, alpha: 1.0) // Get the resulting image. let filteredImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return filteredImage } /* class func getCountTime(_ leftTime: Int, timeformat timeFormat: String?, time timeUnit: MFTimeFormatUnit, timeSuffix suffix: String?) -> String? { var seconds = leftTime % 60 var minutes = (leftTime / 60) % 60 var hours = (leftTime / 3600) % 24 let days = leftTime / 86400 guard let times = timeFormat?.components(separatedBy: ":") else { return nil } var timeString = "" if times.contains("DD") { timeString += String(format: "%02ld", days) if timeUnit == .mfTimeFormatNormal { let dayKey = (days <= 1) ? "CountDownDay" : "CountDownDays" let dayUnit = MVMCoreUIUtility.hardcodedString(withKey: dayKey) timeString += dayUnit! } else if timeUnit == MFTimeFormatColon && times?.last != "DD" { timeString += " : " } if times.last != "DD" && suffix != nil { timeString += suffix ?? "" } } if times.contains("HH") { if !times.contains("DD") { hours = leftTime / 3600 } timeString += String(format: "%02d", hours) if timeUnit == .mfTimeFormatNormal { let hourKey = (hours <= 1) ? "CountDownHour" : "CountDownHours" let hourUnit = MVMCoreUIUtility.hardcodedString(withKey: hourKey)! timeString += hourUnit } else if timeUnit == MFTimeFormatColon && times?.last != "HH" { timeString += " : " } if times.last != "HH" && suffix != nil { timeString += suffix ?? "" } } if times.contains("MM") { if !times.contains("HH") { if !times.contains("DD") { minutes = leftTime / 60 } else { minutes = (leftTime - days * 86400) / 60 } } timeString += String(format: "%02d", minutes) if times.contains("SS") { if !times.contains("MM") { if !times.contains("HH") { if !times.contains("DD") { seconds = leftTime } else { seconds = leftTime % 86400 } } else { seconds = leftTime % 3600 } } timeString += String(format: "%02d", seconds) if timeUnit == .mfTimeFormatNormal { let secondKey = (seconds <= 1) ? "CountDownSec" : "CountDownSecs" let secondUnit = MVMCoreUIUtility.hardcodedString(withKey: secondKey) timeString += secondUnit! } } return timeString } } */ }