// // ServerPanelView.swift // PrivadoVPN // // Created by Juraldinio on 1/31/21. // Copyright © 2021 Privado LLC. All rights reserved. // import Foundation import AppKit protocol ServerPanelViewInput: AnyObject { func hide() func show(country: String, city: String, flag: String) func useHandCursor(enable: Bool) func countryCircle(isHighlited: Bool) } protocol ServerPanelViewOutput: AnyObject { func viewIsReady() func viewWillDisappear() func serverSelectRequired() } final class ServerPanelView: View { private enum Constants { enum LocalizedString { static let serverSelected = "serverlist.location.selected" } enum Image { static let map = "map.serverlist" static let arrow = "main-arrow" } enum Color { static let line = NSColor(red: 25, green: 33, blue: 71) static let header = NSColor(red: 61, green: 69, blue: 111) static let country = NSColor.white static let city = NSColor.white static let background = NSColor(red: 21, green: 25, blue: 53) } enum Font { // swiftlint:disable nesting enum Name { static let medium = PrivadoConstants.Font.medium static let black = PrivadoConstants.Font.bold static let light = PrivadoConstants.Font.light } enum Size { static let header: CGFloat = 12.0 static let country: CGFloat = 12.0 static let city: CGFloat = 12.0 } // swiftlint:enable nesting } enum Geometry { static let height: CGFloat = 110 static let headerWidth: CGFloat = 110 static let headerHeight: CGFloat = 16 static let headerLeading: CGFloat = 22 static let lineHeight: CGFloat = 2 static let mapImageWidth: CGFloat = 113 static let mapImageHeight: CGFloat = 65 static let mapBetweenLine: CGFloat = 6 static let arrowImageWidth: CGFloat = 7 static let arrowImageHeight: CGFloat = 12 static let arrowBetweenMap: CGFloat = 14 static let arrowTrailing: CGFloat = 21 static let countryTrailingMap: CGFloat = 21 static let cityTrailingMap: CGFloat = 21 static let cityTop: CGFloat = 5.0 } } private let output: ServerPanelViewOutput private var headerField: NSTextField? private var countryField: NSTextField? private var cityField: NSTextField? private var arrowView: ImageView? private var backView: View? private var countryImageView: ImageView? private var countryCircleImageView: ImageView? // MARK: - Init init(output: ServerPanelViewOutput) { self.output = output super.init(frame: .zero) self.isHidden = true self.translatesAutoresizingMaskIntoConstraints = false self.createUI() self.activateLayout() self.target = self self.action = #selector(self.onClick) } // MARK: - Lyfecycle override func viewDidMoveToSuperview() { super.viewDidMoveToSuperview() if self.superview.isExist { self.output.viewIsReady() } } override func removeFromSuperview() { self.output.viewWillDisappear() super.removeFromSuperview() } // MARK: - on methods @objc private func onClick() { self.output.serverSelectRequired() } // MARK: - Private private func createUI() { let backgroundView = View(frame: .zero) backgroundView.translatesAutoresizingMaskIntoConstraints = false backgroundView.viewBackgroundColor = NSColor(red: 105, green: 112, blue: 208) backgroundView.layer?.cornerRadius = 8 self.backView = backgroundView self.addSubview(backgroundView) let headerFont = NSFont(name: PrivadoConstants.Font.bold, size: 11) let headerField = self.initializeTextField(color: NSColor(red: 218, green: 219, blue: 243), font: headerFont, alignment: .left, backgroundExist: false) headerField.backgroundColor = .clear headerField.stringValue = NSLocalizedString(Constants.LocalizedString.serverSelected, comment: "") self.headerField = headerField backgroundView.addSubview(headerField) let countryImageView = ImageView(frame: .zero) countryImageView.translatesAutoresizingMaskIntoConstraints = false self.countryImageView = countryImageView backgroundView.addSubview(countryImageView) let countryCircleView = ImageView(frame: .zero) countryCircleView.translatesAutoresizingMaskIntoConstraints = false if let image = NSImage(named: "country-circle-disconnected") { countryCircleView.image = image } self.countryCircleImageView = countryCircleView backgroundView.addSubview(countryCircleView) let cityFont = NSFont(name: PrivadoConstants.Font.bold, size: 16) let cityField = self.initializeTextField(color: .white, font: cityFont, alignment: .left, backgroundExist: false) self.cityField = cityField backgroundView.addSubview(cityField) let countryFont = NSFont(name: PrivadoConstants.Font.semiBold, size: 13) let countryField = self.initializeTextField(color: .white, font: countryFont, alignment: .left, backgroundExist: false) self.countryField = countryField backgroundView.addSubview(countryField) let arrowView = self.initializeImageView(resource: Constants.Image.arrow) self.arrowView = arrowView backgroundView.addSubview(arrowView) } private func activateLayout() { guard let headerField = self.headerField , let backgroundView = self.backView , let countyImageView = self.countryImageView , let countryCircleView = self.countryCircleImageView , let countryField = self.countryField , let cityField = self.cityField , let arrowView = self.arrowView else { return } NSLayoutConstraint.activate([ self.heightAnchor.constraint(equalToConstant: Constants.Geometry.height), // backgroundView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20), backgroundView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20), backgroundView.topAnchor.constraint(equalTo: self.topAnchor), backgroundView.bottomAnchor.constraint(equalTo: self.bottomAnchor), // headerField.topAnchor.constraint(equalTo: backgroundView.topAnchor, constant: 20), headerField.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor, constant: 20), headerField.widthAnchor.constraint(equalToConstant: 133), headerField.heightAnchor.constraint(equalToConstant: 13), // countryCircleView.heightAnchor.constraint(equalToConstant: 48), countryCircleView.widthAnchor.constraint(equalToConstant: 48), countryCircleView.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor, constant: 20), countryCircleView.topAnchor.constraint(equalTo: headerField.bottomAnchor, constant: 13), // countyImageView.heightAnchor.constraint(equalToConstant: 30), countyImageView.widthAnchor.constraint(equalToConstant: 30), countyImageView.centerXAnchor.constraint(equalTo: countryCircleView.centerXAnchor), countyImageView.centerYAnchor.constraint(equalTo: countryCircleView.centerYAnchor), cityField.leadingAnchor.constraint(equalTo: countryCircleView.trailingAnchor, constant: 10), cityField.topAnchor.constraint(equalTo: headerField.bottomAnchor, constant: 17), countryField.leadingAnchor.constraint(equalTo: cityField.leadingAnchor), countryField.topAnchor.constraint(equalTo: cityField.bottomAnchor, constant: 7), arrowView.widthAnchor.constraint(equalToConstant: 22), arrowView.heightAnchor.constraint(equalToConstant: 22), arrowView.trailingAnchor.constraint(equalTo: backgroundView.trailingAnchor, constant: -20), arrowView.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor, constant: -33) ]) } } // MARK: - ServerPanelViewInput extension ServerPanelView: ServerPanelViewInput { func hide() { self.isHidden = true } func show(country: String, city: String, flag: String) { self.countryField?.stringValue = country self.cityField?.stringValue = city self.countryImageView?.image = NSImage(named: flag) self.isHidden = false } func useHandCursor(enable: Bool) { self.useHandCursor = enable self.arrowView?.isHidden = !enable } func countryCircle(isHighlited: Bool) { self.countryCircleImageView?.image = isHighlited ? NSImage(named: "country-circle-connected") : NSImage(named: "country-circle-disconnected") } }