From 0f98312d150bfcbcfd90267462fdaf88d8f82517 Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Sun, 17 Mar 2019 16:38:07 +0530 Subject: macOS: Tunnel detail: Make the Activate button part of the list view Signed-off-by: Roopesh Chander --- WireGuard/WireGuard/UI/macOS/View/ButtonRow.swift | 67 +++++++++++++++++++ .../TunnelDetailTableViewController.swift | 78 +++++++++++----------- 2 files changed, 106 insertions(+), 39 deletions(-) create mode 100644 WireGuard/WireGuard/UI/macOS/View/ButtonRow.swift (limited to 'WireGuard/WireGuard/UI/macOS') diff --git a/WireGuard/WireGuard/UI/macOS/View/ButtonRow.swift b/WireGuard/WireGuard/UI/macOS/View/ButtonRow.swift new file mode 100644 index 0000000..4d15f5e --- /dev/null +++ b/WireGuard/WireGuard/UI/macOS/View/ButtonRow.swift @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. + +import Cocoa + +class ButtonRow: NSView { + let button: NSButton = { + let button = NSButton() + button.title = "" + button.setButtonType(.momentaryPushIn) + button.bezelStyle = .rounded + return button + }() + + var buttonTitle: String { + get { return button.title } + set(value) { button.title = value } + } + + var isButtonEnabled: Bool { + get { return button.isEnabled } + set(value) { button.isEnabled = value } + } + + var buttonToolTip: String { + get { return button.toolTip ?? "" } + set(value) { button.toolTip = value } + } + + var onButtonClicked: (() -> Void)? + var observationToken: AnyObject? + + override var intrinsicContentSize: NSSize { + return NSSize(width: NSView.noIntrinsicMetric, height: button.intrinsicContentSize.height) + } + + init() { + super.init(frame: CGRect.zero) + + button.target = self + button.action = #selector(buttonClicked) + + addSubview(button) + button.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + button.centerYAnchor.constraint(equalTo: self.centerYAnchor), + button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 155), + button.widthAnchor.constraint(greaterThanOrEqualToConstant: 100) + ]) + } + + required init?(coder decoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func buttonClicked() { + onButtonClicked?() + } + + override func prepareForReuse() { + buttonTitle = "" + buttonToolTip = "" + onButtonClicked = nil + observationToken = nil + } +} diff --git a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift index fc747a8..9d77542 100644 --- a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift +++ b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift @@ -32,7 +32,7 @@ class TunnelDetailTableViewController: NSViewController { static let interfaceFields: [TunnelViewModel.InterfaceField] = [ .name, .status, .publicKey, .addresses, - .listenPort, .mtu, .dns + .listenPort, .mtu, .dns, .toggleStatus ] static let peerFields: [TunnelViewModel.PeerField] = [ @@ -51,16 +51,6 @@ class TunnelDetailTableViewController: NSViewController { return tableView }() - let toggleStatusButton: NSButton = { - let button = NSButton() - button.title = "" - button.setButtonType(.momentaryPushIn) - button.bezelStyle = .rounded - button.toolTip = "Toggle status (⌘T)" - button.widthAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true - return button - }() - let editButton: NSButton = { let button = NSButton() button.title = tr("Edit") @@ -114,9 +104,6 @@ class TunnelDetailTableViewController: NSViewController { tableView.dataSource = self tableView.delegate = self - toggleStatusButton.target = self - toggleStatusButton.action = #selector(handleToggleActiveStatusAction) - editButton.target = self editButton.action = #selector(handleEditTunnelAction) @@ -134,11 +121,9 @@ class TunnelDetailTableViewController: NSViewController { containerView.addLayoutGuide(bottomControlsContainer) containerView.addSubview(box) containerView.addSubview(scrollView) - containerView.addSubview(toggleStatusButton) containerView.addSubview(editButton) box.translatesAutoresizingMaskIntoConstraints = false scrollView.translatesAutoresizingMaskIntoConstraints = false - toggleStatusButton.translatesAutoresizingMaskIntoConstraints = false editButton.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ @@ -150,8 +135,6 @@ class TunnelDetailTableViewController: NSViewController { bottomControlsContainer.heightAnchor.constraint(equalToConstant: 32), scrollView.bottomAnchor.constraint(equalTo: bottomControlsContainer.topAnchor), bottomControlsContainer.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), - toggleStatusButton.leadingAnchor.constraint(equalTo: bottomControlsContainer.leadingAnchor), - bottomControlsContainer.bottomAnchor.constraint(equalTo: toggleStatusButton.bottomAnchor, constant: 0), editButton.trailingAnchor.constraint(equalTo: bottomControlsContainer.trailingAnchor), bottomControlsContainer.bottomAnchor.constraint(equalTo: editButton.bottomAnchor, constant: 0) ]) @@ -176,7 +159,7 @@ class TunnelDetailTableViewController: NSViewController { var interfaceSection = [(isVisible: Bool, modelRow: TableViewModelRow)]() for field in TunnelDetailTableViewController.interfaceFields { - let isStatus = field == .status + let isStatus = field == .status || field == .toggleStatus let isEmpty = tunnelViewModel.interfaceData[field].isEmpty interfaceSection.append((isVisible: isStatus || !isEmpty, modelRow: .interfaceFieldRow(field))) } @@ -204,26 +187,6 @@ class TunnelDetailTableViewController: NSViewController { } func updateStatus() { - let toggleStatusButtonText: String - switch tunnel.status { - case .waiting: - toggleStatusButtonText = tr("macToggleStatusButtonWaiting") - case .inactive: - toggleStatusButtonText = tr("macToggleStatusButtonActivate") - case .activating: - toggleStatusButtonText = tr("macToggleStatusButtonActivating") - case .active: - toggleStatusButtonText = tr("macToggleStatusButtonDeactivate") - case .deactivating: - toggleStatusButtonText = tr("macToggleStatusButtonDeactivating") - case .reasserting: - toggleStatusButtonText = tr("macToggleStatusButtonReasserting") - case .restarting: - toggleStatusButtonText = tr("macToggleStatusButtonRestarting") - } - toggleStatusButton.title = toggleStatusButtonText - let shouldBeEnabled = (tunnel.status == .active || tunnel.status == .inactive) - toggleStatusButton.isEnabled = shouldBeEnabled if tunnel.status == .active { startUpdatingRuntimeConfiguration() } else if tunnel.status == .inactive { @@ -392,6 +355,8 @@ extension TunnelDetailTableViewController: NSTableViewDelegate { case .interfaceFieldRow(let field): if field == .status { return statusCell() + } else if field == .toggleStatus { + return toggleStatusCell() } else { let cell: KeyValueRow = tableView.dequeueReusableCell() let localizedKeyString = modelRow.isTitleRow() ? modelRow.localizedSectionKeyString() : field.localizedUIString @@ -437,6 +402,22 @@ extension TunnelDetailTableViewController: NSTableViewDelegate { return cell } + func toggleStatusCell() -> NSView { + let cell: ButtonRow = tableView.dequeueReusableCell() + cell.buttonTitle = TunnelDetailTableViewController.localizedToggleStatusActionText(forStatus: tunnel.status) + cell.isButtonEnabled = (tunnel.status == .active || tunnel.status == .inactive) + cell.buttonToolTip = "Toggle status (⌘T)" + cell.onButtonClicked = { [weak self] in + self?.handleToggleActiveStatusAction() + } + cell.observationToken = tunnel.observe(\.status) { [weak cell] tunnel, _ in + guard let cell = cell else { return } + cell.buttonTitle = TunnelDetailTableViewController.localizedToggleStatusActionText(forStatus: tunnel.status) + cell.isButtonEnabled = (tunnel.status == .active || tunnel.status == .inactive) + } + return cell + } + private static func localizedStatusDescription(forStatus status: TunnelStatus) -> String { switch status { case .inactive: @@ -467,6 +448,25 @@ extension TunnelDetailTableViewController: NSTableViewDelegate { return NSImage(named: NSImage.statusNoneName) } } + + private static func localizedToggleStatusActionText(forStatus status: TunnelStatus) -> String { + switch status { + case .waiting: + return tr("macToggleStatusButtonWaiting") + case .inactive: + return tr("macToggleStatusButtonActivate") + case .activating: + return tr("macToggleStatusButtonActivating") + case .active: + return tr("macToggleStatusButtonDeactivate") + case .deactivating: + return tr("macToggleStatusButtonDeactivating") + case .reasserting: + return tr("macToggleStatusButtonReasserting") + case .restarting: + return tr("macToggleStatusButtonRestarting") + } + } } extension TunnelDetailTableViewController: TunnelEditViewControllerDelegate { -- cgit v1.2.3-59-g8ed1b