// // FolioReaderFontsMenu.swift // FolioReaderKit // // Created by Heberti Almeida on 27/08/15. // Copyright (c) 2015 Folio Reader. All rights reserved. // import UIKit public enum FolioReaderFont: Int { case andada = 0 case lato case lora case raleway public static func folioReaderFont(fontName: String) -> FolioReaderFont? { var font: FolioReaderFont? switch fontName { case "andada": font = .andada case "lato": font = .lato case "lora": font = .lora case "raleway": font = .raleway default: break } return font } public var cssIdentifier: String { switch self { case .andada: return "andada" case .lato: return "lato" case .lora: return "lora" case .raleway: return "raleway" } } } public enum SliderType: Int{ case font case margin case interline var paramText: String{ switch self { case .font: return "text" case .margin: return "margin" case .interline: return "interline" } } var leftImage: UIImage{ switch self { case .font: return #imageLiteral(resourceName: "reader_font-small") case .margin: return #imageLiteral(resourceName: "reader_margin-small") case .interline: return #imageLiteral(resourceName: "reader_leading-small") } } var rightImage: UIImage{ switch self { case .font: return #imageLiteral(resourceName: "reader_font-big") case .margin: return #imageLiteral(resourceName: "reader_margin-big") case .interline: return #imageLiteral(resourceName: "reader_leading-big") } } } public enum FolioReaderSliderParamSize: Int { case xs = 0 case s case m case l case xl public static func folioReaderParamSize(fontSizeStringRepresentation: String, sliderType: SliderType) -> FolioReaderSliderParamSize? { var paramSize: FolioReaderSliderParamSize? let paramText = sliderType.paramText switch fontSizeStringRepresentation { case "\(paramText)SizeOne": paramSize = .xs case "\(paramText)SizeTwo": paramSize = .s case "\(paramText)SizeThree": paramSize = .m case "\(paramText)SizeFour": paramSize = .l case "\(paramText)SizeFive": paramSize = .xl default: break } return paramSize } public func cssIdentifier(sliderType: SliderType) -> String { let paramText = sliderType.paramText switch self { case .xs: return "\(paramText)SizeOne" case .s: return "\(paramText)SizeTwo" case .m: return "\(paramText)SizeThree" case .l: return "\(paramText)SizeFour" case .xl: return "\(paramText)SizeFive" } } } class FolioReaderFontsMenu: UIViewController, SMSegmentViewDelegate, UIGestureRecognizerDelegate { var menuView: UIView! fileprivate var readerConfig: FolioReaderConfig fileprivate var folioReader: FolioReader init(folioReader: FolioReader, readerConfig: FolioReaderConfig) { self.readerConfig = readerConfig self.folioReader = folioReader super.init(nibName: nil, bundle: nil) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.view.backgroundColor = UIColor.clear // Tap gesture let tapGesture = UITapGestureRecognizer(target: self, action: #selector(FolioReaderFontsMenu.tapGesture)) tapGesture.numberOfTapsRequired = 1 tapGesture.delegate = self view.addGestureRecognizer(tapGesture) // Menu view // let visibleHeight: CGFloat = self.readerConfig.canChangeScrollDirection ? 222 : 170 let visibleHeight: CGFloat = self.readerConfig.canChangeScrollDirection ? 222 + 114 : 170 + 114 menuView = UIView(frame: CGRect(x: 0, y: view.frame.height-visibleHeight, width: view.frame.width, height: view.frame.height)) menuView.backgroundColor = self.folioReader.isNight(self.readerConfig.nightModeMenuBackground, UIColor.white) menuView.autoresizingMask = .flexibleWidth menuView.layer.shadowColor = UIColor.black.cgColor menuView.layer.shadowOffset = CGSize(width: 0, height: 0) menuView.layer.shadowOpacity = 0.3 menuView.layer.shadowRadius = 6 menuView.layer.shadowPath = UIBezierPath(rect: menuView.bounds).cgPath menuView.layer.rasterizationScale = UIScreen.main.scale menuView.layer.shouldRasterize = true view.addSubview(menuView) let normalColor = UIColor(white: 0.5, alpha: 0.7) let selectedColor = self.readerConfig.tintColor let sun = UIImage(readerImageNamed: "icon-sun") let moon = UIImage(readerImageNamed: "icon-moon") let fontSmall = UIImage(readerImageNamed: "icon-font-small") let fontBig = UIImage(readerImageNamed: "icon-font-big") let sunNormal = sun?.imageTintColor(normalColor)?.withRenderingMode(.alwaysOriginal) let moonNormal = moon?.imageTintColor(normalColor)?.withRenderingMode(.alwaysOriginal) let sunSelected = sun?.imageTintColor(selectedColor)?.withRenderingMode(.alwaysOriginal) let moonSelected = moon?.imageTintColor(selectedColor)?.withRenderingMode(.alwaysOriginal) // Day night mode let dayNight = SMSegmentView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 55), separatorColour: self.readerConfig.nightModeSeparatorColor, separatorWidth: 1, segmentProperties: [ keySegmentTitleFont: UIFont(name: "Avenir-Light", size: 17)!, keySegmentOnSelectionColour: UIColor.clear, keySegmentOffSelectionColour: UIColor.clear, keySegmentOnSelectionTextColour: selectedColor, keySegmentOffSelectionTextColour: normalColor, keyContentVerticalMargin: 17 as AnyObject ]) dayNight.delegate = self dayNight.tag = 1 dayNight.addSegmentWithTitle(self.readerConfig.localizedFontMenuDay, onSelectionImage: sunSelected, offSelectionImage: sunNormal) dayNight.addSegmentWithTitle(self.readerConfig.localizedFontMenuNight, onSelectionImage: moonSelected, offSelectionImage: moonNormal) dayNight.selectSegmentAtIndex(self.folioReader.nightMode.hashValue) menuView.addSubview(dayNight) // Separator let line = UIView(frame: CGRect(x: 0, y: dayNight.frame.height+dayNight.frame.origin.y, width: view.frame.width, height: 1)) line.backgroundColor = self.readerConfig.nightModeSeparatorColor menuView.addSubview(line) // Fonts adjust let fontName = SMSegmentView(frame: CGRect(x: 15, y: line.frame.height+line.frame.origin.y, width: view.frame.width-30, height: 55), separatorColour: UIColor.clear, separatorWidth: 0, segmentProperties: [ keySegmentOnSelectionColour: UIColor.clear, keySegmentOffSelectionColour: UIColor.clear, keySegmentOnSelectionTextColour: selectedColor, keySegmentOffSelectionTextColour: normalColor, keyContentVerticalMargin: 17 as AnyObject ]) fontName.delegate = self fontName.tag = 2 fontName.addSegmentWithTitle("Andada", onSelectionImage: nil, offSelectionImage: nil) fontName.addSegmentWithTitle("Lato", onSelectionImage: nil, offSelectionImage: nil) fontName.addSegmentWithTitle("Lora", onSelectionImage: nil, offSelectionImage: nil) fontName.addSegmentWithTitle("Raleway", onSelectionImage: nil, offSelectionImage: nil) // fontName.segments[0].titleFont = UIFont(name: "Andada-Regular", size: 18)! // fontName.segments[1].titleFont = UIFont(name: "Lato-Regular", size: 18)! // fontName.segments[2].titleFont = UIFont(name: "Lora-Regular", size: 18)! // fontName.segments[3].titleFont = UIFont(name: "Raleway-Regular", size: 18)! fontName.selectSegmentAtIndex(self.folioReader.currentFont.rawValue) menuView.addSubview(fontName) // Separator 2 let line2 = UIView(frame: CGRect(x: 0, y: fontName.frame.height+fontName.frame.origin.y, width: view.frame.width, height: 1)) line2.backgroundColor = self.readerConfig.nightModeSeparatorColor menuView.addSubview(line2) addSlider(sliderType: .font, topY: line2.frame.origin.y, selectedColor: selectedColor) addSlider(sliderType: .margin, topY: line2.frame.origin.y + 57, selectedColor: selectedColor) addSlider(sliderType: .interline, topY: line2.frame.origin.y + 114, selectedColor: selectedColor) // // Font slider size // let slider = HADiscreteSlider(frame: CGRect(x: 60, y: line2.frame.origin.y+2, width: view.frame.width-120, height: 55)) // slider.tickStyle = ComponentStyle.rounded // slider.tickCount = 5 // slider.tickSize = CGSize(width: 8, height: 8) // // slider.thumbStyle = ComponentStyle.rounded // slider.thumbSize = CGSize(width: 28, height: 28) // slider.thumbShadowOffset = CGSize(width: 0, height: 2) // slider.thumbShadowRadius = 3 // slider.thumbColor = selectedColor // // slider.backgroundColor = UIColor.clear // slider.tintColor = self.readerConfig.nightModeSeparatorColor // slider.minimumValue = 0 // slider.value = CGFloat(self.folioReader.currentFontSize.rawValue) // slider.addTarget(self, action: #selector(FolioReaderFontsMenu.sliderValueChanged(_:)), for: UIControlEvents.valueChanged) // // // Force remove fill color // slider.layer.sublayers?.forEach({ layer in // layer.backgroundColor = UIColor.clear.cgColor // }) // // menuView.addSubview(slider) // // // Font icons // let fontSmallView = UIImageView(frame: CGRect(x: 20, y: line2.frame.origin.y+14, width: 30, height: 30)) // fontSmallView.image = fontSmallNormal // fontSmallView.contentMode = UIViewContentMode.center // menuView.addSubview(fontSmallView) // // let fontBigView = UIImageView(frame: CGRect(x: view.frame.width-50, y: line2.frame.origin.y+14, width: 30, height: 30)) // fontBigView.image = fontBigNormal // fontBigView.contentMode = UIViewContentMode.center // menuView.addSubview(fontBigView) // Only continues if user can change scroll direction guard (self.readerConfig.canChangeScrollDirection == true) else { return } // Separator 3 // let line3 = UIView(frame: CGRect(x: 0, y: line2.frame.origin.y+56, width: view.frame.width, height: 1)) let line3 = UIView(frame: CGRect(x: 0, y: line2.frame.origin.y+171, width: view.frame.width, height: 1)) line3.backgroundColor = self.readerConfig.nightModeSeparatorColor menuView.addSubview(line3) let vertical = UIImage(readerImageNamed: "icon-menu-vertical") let horizontal = UIImage(readerImageNamed: "icon-menu-horizontal") let verticalNormal = vertical?.imageTintColor(normalColor)?.withRenderingMode(.alwaysOriginal) let horizontalNormal = horizontal?.imageTintColor(normalColor)?.withRenderingMode(.alwaysOriginal) let verticalSelected = vertical?.imageTintColor(selectedColor)?.withRenderingMode(.alwaysOriginal) let horizontalSelected = horizontal?.imageTintColor(selectedColor)?.withRenderingMode(.alwaysOriginal) // Layout direction let layoutDirection = SMSegmentView(frame: CGRect(x: 0, y: line3.frame.origin.y, width: view.frame.width, height: 55), separatorColour: self.readerConfig.nightModeSeparatorColor, separatorWidth: 1, segmentProperties: [ keySegmentTitleFont: UIFont(name: "Avenir-Light", size: 17)!, keySegmentOnSelectionColour: UIColor.clear, keySegmentOffSelectionColour: UIColor.clear, keySegmentOnSelectionTextColour: selectedColor, keySegmentOffSelectionTextColour: normalColor, keyContentVerticalMargin: 17 as AnyObject ]) layoutDirection.delegate = self layoutDirection.tag = 3 layoutDirection.addSegmentWithTitle(self.readerConfig.localizedLayoutVertical, onSelectionImage: verticalSelected, offSelectionImage: verticalNormal) layoutDirection.addSegmentWithTitle(self.readerConfig.localizedLayoutHorizontal, onSelectionImage: horizontalSelected, offSelectionImage: horizontalNormal) var scrollDirection = FolioReaderScrollDirection(rawValue: self.folioReader.currentScrollDirection) if scrollDirection == .defaultVertical && self.readerConfig.scrollDirection != .defaultVertical { scrollDirection = self.readerConfig.scrollDirection } switch scrollDirection ?? .vertical { case .vertical, .defaultVertical: layoutDirection.selectSegmentAtIndex(FolioReaderScrollDirection.vertical.rawValue) case .horizontal, .horizontalWithVerticalContent: layoutDirection.selectSegmentAtIndex(FolioReaderScrollDirection.horizontal.rawValue) } menuView.addSubview(layoutDirection) } func addSlider(sliderType: SliderType, topY: CGFloat, selectedColor: UIColor){ let normalColor = UIColor(white: 0.5, alpha: 0.7) // Font slider size let slider = HADiscreteSlider(frame: CGRect(x: 60, y: topY+2, width: view.frame.width-120, height: 55)) slider.tickStyle = ComponentStyle.rounded slider.tickCount = 5 slider.tickSize = CGSize(width: 8, height: 8) slider.thumbStyle = ComponentStyle.rounded slider.thumbSize = CGSize(width: 28, height: 28) slider.thumbShadowOffset = CGSize(width: 0, height: 2) slider.thumbShadowRadius = 3 slider.thumbColor = selectedColor slider.backgroundColor = UIColor.clear slider.tintColor = self.readerConfig.nightModeSeparatorColor slider.minimumValue = 0 slider.tag = sliderType.rawValue switch sliderType { case .font: slider.value = CGFloat(self.folioReader.currentFontSize.rawValue) case .margin: slider.value = CGFloat(self.folioReader.currentMarginSize.rawValue) case .interline: slider.value = CGFloat(self.folioReader.currentInterlineSize.rawValue) } slider.addTarget(self, action: #selector(FolioReaderFontsMenu.sliderValueChanged(_:)), for: UIControlEvents.valueChanged) // Force remove fill color slider.layer.sublayers?.forEach({ layer in layer.backgroundColor = UIColor.clear.cgColor }) menuView.addSubview(slider) // Font icons let fontSmallView = UIImageView(frame: CGRect(x: 20, y: topY+14, width: 30, height: 30)) fontSmallView.image = sliderType.leftImage.imageTintColor(normalColor) fontSmallView.contentMode = UIViewContentMode.center menuView.addSubview(fontSmallView) let fontBigView = UIImageView(frame: CGRect(x: view.frame.width-50, y: topY+14, width: 30, height: 30)) fontSmallView.image = sliderType.rightImage.imageTintColor(normalColor) fontBigView.contentMode = UIViewContentMode.center menuView.addSubview(fontBigView) } // MARK: - SMSegmentView delegate func segmentView(_ segmentView: SMSegmentView, didSelectSegmentAtIndex index: Int) { guard (self.folioReader.readerCenter?.currentPage) != nil else { return } if segmentView.tag == 1 { self.folioReader.nightMode = Bool(index == 1) UIView.animate(withDuration: 0.6, animations: { self.menuView.backgroundColor = (self.folioReader.nightMode ? self.readerConfig.nightModeBackground : UIColor.white) }) } else if segmentView.tag == 2 { self.folioReader.currentFont = FolioReaderFont(rawValue: index)! } else if segmentView.tag == 3 { guard self.folioReader.currentScrollDirection != index else { return } self.folioReader.currentScrollDirection = index } } // MARK: - Font slider changed @objc func sliderValueChanged(_ sender: HADiscreteSlider) { guard (self.folioReader.readerCenter?.currentPage != nil), let sliderType = SliderType(rawValue: sender.tag) else { return } switch sliderType { case .font: if let fontSize = FolioReaderSliderParamSize(rawValue: Int(sender.value)){ self.folioReader.currentFontSize = fontSize } case .margin: if let marginSize = FolioReaderSliderParamSize(rawValue: Int(sender.value)){ self.folioReader.currentMarginSize = marginSize } case .interline: if let interlineSize = FolioReaderSliderParamSize(rawValue: Int(sender.value)){ self.folioReader.currentInterlineSize = interlineSize } } } // MARK: - Gestures @objc func tapGesture() { dismiss() if (self.readerConfig.shouldHideNavigationOnTap == false) { self.folioReader.readerCenter?.showBars() } } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if gestureRecognizer is UITapGestureRecognizer && touch.view == view { return true } return false } // MARK: - Status Bar override var prefersStatusBarHidden : Bool { return (self.readerConfig.shouldHideNavigationOnTap == true) } }