From c2633987c3bc98c94981c599ac63e8a081ab605c Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Sun, 6 Jan 2019 18:51:06 +0530 Subject: macOS: Tunnel edit view Signed-off-by: Roopesh Chander --- WireGuard/WireGuard.xcodeproj/project.pbxproj | 4 + WireGuard/WireGuard/Base.lproj/Localizable.strings | 9 +- .../WireGuard/UI/macOS/View/KeyValueRow.swift | 23 +++- .../TunnelDetailTableViewController.swift | 7 +- .../ViewController/TunnelEditViewController.swift | 125 +++++++++++++++++++++ 5 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj index b132fdd..402fb29 100644 --- a/WireGuard/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard/WireGuard.xcodeproj/project.pbxproj @@ -119,6 +119,7 @@ 6FBA104621D7EBFA0051C35F /* TunnelsListTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FBA104521D7EBFA0051C35F /* TunnelsListTableViewController.swift */; }; 6FCD99AA21E0E14700BA4C82 /* NoTunnelsDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FCD99A821E0E0C700BA4C82 /* NoTunnelsDetailViewController.swift */; }; 6FCD99AF21E0EA1700BA4C82 /* ImportPanelPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */; }; + 6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */; }; 6FDB3C3B21DCF47400A0C0BF /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */; }; 6FDB3C3C21DCF6BB00A0C0BF /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; }; 6FDEF7E421846C1A00D8FBF6 /* libwg-go.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FDEF7E321846C1A00D8FBF6 /* libwg-go.a */; }; @@ -274,6 +275,7 @@ 6FBA104521D7EBFA0051C35F /* TunnelsListTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelsListTableViewController.swift; sourceTree = ""; }; 6FCD99A821E0E0C700BA4C82 /* NoTunnelsDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoTunnelsDetailViewController.swift; sourceTree = ""; }; 6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportPanelPresenter.swift; sourceTree = ""; }; + 6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditViewController.swift; sourceTree = ""; }; 6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = ""; }; 6FDEF7E321846C1A00D8FBF6 /* libwg-go.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libwg-go.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 6FDEF7E52185EFAF00D8FBF6 /* QRScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRScanViewController.swift; sourceTree = ""; }; @@ -512,6 +514,7 @@ 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */, 6FDB3C3A21DCF47400A0C0BF /* TunnelDetailTableViewController.swift */, 6FCD99A821E0E0C700BA4C82 /* NoTunnelsDetailViewController.swift */, + 6FCD99B021E0EDA900BA4C82 /* TunnelEditViewController.swift */, ); path = ViewController; sourceTree = ""; @@ -1078,6 +1081,7 @@ 6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */, 6FB1BDD821D50F5300A991BF /* WireGuardResult.swift in Sources */, 6FB1BDD921D50F5300A991BF /* LocalizationHelper.swift in Sources */, + 6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */, 6FB1BDCA21D50F1700A991BF /* x25519.c in Sources */, 6FB1BDCB21D50F1700A991BF /* Curve25519.swift in Sources */, 6FB1BDBB21D50F0200A991BF /* Localizable.strings in Sources */, diff --git a/WireGuard/WireGuard/Base.lproj/Localizable.strings b/WireGuard/WireGuard/Base.lproj/Localizable.strings index ecbc087..8cae396 100644 --- a/WireGuard/WireGuard/Base.lproj/Localizable.strings +++ b/WireGuard/WireGuard/Base.lproj/Localizable.strings @@ -244,10 +244,15 @@ "macButtonImportTunnels" = "Import tunnel(s) from file"; -// Mac detail view fields +// Mac detail/edit view fields -"macDetailFieldKey (%@)" = "%@:"; +"macFieldKey (%@)" = "%@:"; // Mac status display "macStatus (%@)" = "Status: %@"; + +// Mac editing config + +"macEditDiscard" = "Discard"; +"macEditSave" = "Save"; diff --git a/WireGuard/WireGuard/UI/macOS/View/KeyValueRow.swift b/WireGuard/WireGuard/UI/macOS/View/KeyValueRow.swift index 4e9fa7d..cdf682c 100644 --- a/WireGuard/WireGuard/UI/macOS/View/KeyValueRow.swift +++ b/WireGuard/WireGuard/UI/macOS/View/KeyValueRow.swift @@ -3,7 +3,7 @@ import Cocoa -class KeyValueRow: NSView { +class EditableKeyValueRow: NSView { let keyLabel: NSTextField = { let keyLabel = NSTextField() keyLabel.isEditable = false @@ -18,12 +18,9 @@ class KeyValueRow: NSView { let valueLabel: NSTextField = { let valueLabel = NSTextField() - valueLabel.isEditable = false valueLabel.isSelectable = true - valueLabel.isBordered = false valueLabel.maximumNumberOfLines = 1 valueLabel.lineBreakMode = .byTruncatingTail - valueLabel.backgroundColor = .clear return valueLabel }() @@ -46,6 +43,11 @@ class KeyValueRow: NSView { } } + override var intrinsicContentSize: NSSize { + let height = max(keyLabel.intrinsicContentSize.height, valueLabel.intrinsicContentSize.height) + return NSSize(width: NSView.noIntrinsicMetric, height: height) + } + init() { super.init(frame: CGRect.zero) @@ -74,3 +76,16 @@ class KeyValueRow: NSView { isKeyInBold = false } } + +class KeyValueRow: EditableKeyValueRow { + override init() { + super.init() + valueLabel.isEditable = false + valueLabel.isBordered = false + valueLabel.backgroundColor = .clear + } + + required init?(coder decoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift index 8e7db43..9e84e12 100644 --- a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift +++ b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift @@ -191,7 +191,8 @@ class TunnelDetailTableViewController: NSViewController { } @objc func editButtonClicked() { - print("editButtonClicked") + let tunnelEditVC = TunnelEditViewController(tunnelsManager: tunnelsManager, tunnel: tunnel) + presentAsSheet(tunnelEditVC) } @objc func statusCheckboxToggled(sender: AnyObject?) { @@ -217,14 +218,14 @@ extension TunnelDetailTableViewController: NSTableViewDelegate { case .interfaceFieldRow(let field): let cell: KeyValueRow = tableView.dequeueReusableCell() let localizedKeyString = modelRow.isTitleRow() ? modelRow.localizedSectionKeyString() : field.localizedUIString - cell.key = tr(format: "macDetailFieldKey (%@)", localizedKeyString) + cell.key = tr(format: "macFieldKey (%@)", localizedKeyString) cell.value = tunnelViewModel.interfaceData[field] cell.isKeyInBold = modelRow.isTitleRow() return cell case .peerFieldRow(let peerData, let field): let cell: KeyValueRow = tableView.dequeueReusableCell() let localizedKeyString = modelRow.isTitleRow() ? modelRow.localizedSectionKeyString() : field.localizedUIString - cell.key = tr(format: "macDetailFieldKey (%@)", localizedKeyString) + cell.key = tr(format: "macFieldKey (%@)", localizedKeyString) cell.value = peerData[field] cell.isKeyInBold = modelRow.isTitleRow() return cell diff --git a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift new file mode 100644 index 0000000..52b80f6 --- /dev/null +++ b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018 WireGuard LLC. All Rights Reserved. + +import Cocoa + +class TunnelEditViewController: NSViewController { + + let nameRow: EditableKeyValueRow = { + let nameRow = EditableKeyValueRow() + nameRow.key = tr(format: "macFieldKey (%@)", TunnelViewModel.InterfaceField.name.localizedUIString) + return nameRow + }() + + let publicKeyRow: KeyValueRow = { + let publicKeyRow = KeyValueRow() + publicKeyRow.key = tr(format: "macFieldKey (%@)", TunnelViewModel.InterfaceField.publicKey.localizedUIString) + return publicKeyRow + }() + + let textView: NSTextView = { + let textView = NSTextView() + let minWidth: CGFloat = 120 + let minHeight: CGFloat = 60 + textView.minSize = NSSize(width: 0, height: minHeight) + textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude) + textView.autoresizingMask = .width + textView.isHorizontallyResizable = true + if let textContainer = textView.textContainer { + textContainer.size = NSSize(width: minWidth, height: CGFloat.greatestFiniteMagnitude) + textContainer.widthTracksTextView = true + } + NSLayoutConstraint.activate([ + textView.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth), + textView.heightAnchor.constraint(greaterThanOrEqualToConstant: minHeight) + ]) + return textView + }() + + let scrollView: NSScrollView = { + let scrollView = NSScrollView() + scrollView.hasVerticalScroller = true + scrollView.borderType = .bezelBorder + return scrollView + }() + + let discardButton: NSButton = { + let button = NSButton() + button.title = tr("macEditDiscard") + button.setButtonType(.momentaryPushIn) + button.bezelStyle = .rounded + return button + }() + + let saveButton: NSButton = { + let button = NSButton() + button.title = tr("macEditSave") + button.setButtonType(.momentaryPushIn) + button.bezelStyle = .rounded + return button + }() + + let tunnelsManager: TunnelsManager + let tunnel: TunnelContainer? + + init(tunnelsManager: TunnelsManager, tunnel: TunnelContainer?) { + self.tunnelsManager = tunnelsManager + self.tunnel = tunnel + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func loadView() { + if let tunnel = tunnel, let tunnelConfiguration = tunnel.tunnelConfiguration { + nameRow.value = tunnel.name + publicKeyRow.value = tunnelConfiguration.interface.publicKey.base64EncodedString() + textView.string = tunnelConfiguration.asWgQuickConfig() + } + + scrollView.documentView = textView + + saveButton.target = self + saveButton.action = #selector(saveButtonClicked) + + discardButton.target = self + discardButton.action = #selector(discardButtonClicked) + + let margin: CGFloat = 20 + let internalSpacing: CGFloat = 10 + + let editorStackView = NSStackView(views: [nameRow, publicKeyRow, scrollView]) + editorStackView.orientation = .vertical + editorStackView.setHuggingPriority(.defaultHigh, for: .horizontal) + editorStackView.spacing = internalSpacing + + let buttonRowStackView = NSStackView() + buttonRowStackView.setViews([discardButton, saveButton], in: .trailing) + buttonRowStackView.orientation = .horizontal + buttonRowStackView.spacing = internalSpacing + + let containerView = NSStackView(views: [editorStackView, buttonRowStackView]) + containerView.orientation = .vertical + containerView.edgeInsets = NSEdgeInsets(top: margin, left: margin, bottom: margin, right: margin) + containerView.setHuggingPriority(.defaultHigh, for: .horizontal) + containerView.spacing = internalSpacing + + NSLayoutConstraint.activate([ + containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 180), + containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 240) + ]) + containerView.frame = NSRect(x: 0, y: 0, width: 480, height: 320) + + self.view = containerView + } + + @objc func saveButtonClicked() { + print("saveButtonClicked") + } + + @objc func discardButtonClicked() { + dismiss(self) + } +} -- cgit v1.2.3-59-g8ed1b