// // SideMenuController.swift // PrivadoVPN // // Created by Murad Shabanov on 14.03.2022. // Copyright © 2022 Privado LLC. All rights reserved. // import Foundation protocol SideMenuControllerOutput: AnyObject { func sideMenuBottomItem(at index: Int) -> SideMenuItem func bottomItemscount() -> Int func itemSelectedAt(index: Int) } protocol SideMenuControllerInput: AnyObject { func reloadBottomItems() } final class SideMenuController: NSViewController, SideMenuControllerInput { enum Constants { static let columnIdentifier = NSUserInterfaceItemIdentifier("SideMenuItemList") static let cellIdentifier = NSUserInterfaceItemIdentifier("SideMenuItemCell") enum Image { static let privado: String = "sidemenu-privado" } } private var privadoLogoView: ImageView private let privadoLogoSeparator: View private let bottomItemsView: NSTableView private let ouput: SideMenuControllerOutput init(output: SideMenuControllerOutput) { self.ouput = output self.bottomItemsView = NSTableView() self.privadoLogoView = ImageView(frame: .zero) self.privadoLogoSeparator = View(frame: .zero) super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func loadView() { let view = NSView(frame: .zero) view.wantsLayer = true view.translatesAutoresizingMaskIntoConstraints = false view.layer?.backgroundColor = NSColor(red: 29, green: 33, blue: 91).cgColor self.view = view } override func viewDidLoad() { super.viewDidLoad() self.configureUI() self.layoutView() } override func viewDidAppear() { if let superview = self.view.superview { NSLayoutConstraint.activate([ self.view.leadingAnchor.constraint(equalTo: superview.leadingAnchor), self.view.bottomAnchor.constraint(equalTo: superview.bottomAnchor), self.view.heightAnchor.constraint(equalToConstant: 550), self.view.widthAnchor.constraint(equalToConstant: 60) ]) } } private func configureUI() { if let logoImage = NSImage(named: Constants.Image.privado) { let logoView = ImageView(image: logoImage) logoView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(logoView) self.privadoLogoView = logoView } self.privadoLogoSeparator.translatesAutoresizingMaskIntoConstraints = false self.privadoLogoSeparator.viewBackgroundColor = NSColor(red: 130, green: 136, blue: 216) self.view.addSubview(self.privadoLogoSeparator) let column = NSTableColumn(identifier: Constants.columnIdentifier) column.isEditable = false self.bottomItemsView.addTableColumn(column) self.bottomItemsView.translatesAutoresizingMaskIntoConstraints = false self.bottomItemsView.selectionHighlightStyle = .none self.bottomItemsView.backgroundColor = .clear self.bottomItemsView.focusRingType = .none self.bottomItemsView.rowSizeStyle = .custom self.bottomItemsView.cornerView = NSView() self.bottomItemsView.allowsMultipleSelection = false self.bottomItemsView.delegate = self self.bottomItemsView.dataSource = self self.view.addSubview(self.bottomItemsView) } private func layoutView() { NSLayoutConstraint.activate([ self.bottomItemsView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: -15), self.bottomItemsView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), self.bottomItemsView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), self.privadoLogoView.widthAnchor.constraint(equalToConstant: 30), self.privadoLogoView.heightAnchor.constraint(equalToConstant: 30), self.privadoLogoView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 20), self.privadoLogoView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 15), self.privadoLogoSeparator.topAnchor.constraint(equalTo: self.privadoLogoView.bottomAnchor, constant: 20), self.privadoLogoSeparator.heightAnchor.constraint(equalToConstant: 1), self.privadoLogoSeparator.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 10), self.privadoLogoSeparator.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -10) ]) } func reloadBottomItems() { self.bottomItemsView.reloadData() } } extension SideMenuController: NSTableViewDelegate { func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { guard tableView.tableColumns[safe: 0] == tableColumn , tableColumn.isExist else { return nil } tableView.makeView(withIdentifier: Constants.cellIdentifier, owner: nil) let item = self.ouput.sideMenuBottomItem(at: row) let cell = BottomItemCell(frame: .zero) cell.isHoverEnabled = true cell.update(with: item.image, lineIsVisible: row != 0, type: item.type) return cell } func tableViewSelectionDidChange(_ notification: Notification) { let selectedRow = self.bottomItemsView.selectedRow self.ouput.itemSelectedAt(index: selectedRow) self.bottomItemsView.deselectRow(selectedRow) } func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { return 60 } } extension SideMenuController: NSTableViewDataSource { func numberOfRows(in tableView: NSTableView) -> Int { return self.ouput.bottomItemscount() } }