macOS: Replace NSSegmentedControl with NSPopUpButton and NSButton
Thereby avoiding the hacky way of showing the menus. Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
parent
b01d09dfb5
commit
98a967acc8
|
@ -21,32 +21,46 @@ class TunnelsListTableViewController: NSViewController {
|
||||||
return tableView
|
return tableView
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let buttonBar: NSSegmentedControl = {
|
let addButton: NSPopUpButton = {
|
||||||
let addButtonImage = NSImage(named: NSImage.addTemplateName)!
|
let imageItem = NSMenuItem(title: "", action: nil, keyEquivalent: "")
|
||||||
let removeButtonImage = NSImage(named: NSImage.removeTemplateName)!
|
imageItem.image = NSImage(named: NSImage.addTemplateName)!
|
||||||
let actionButtonImage = NSImage(named: NSImage.actionTemplateName)!
|
|
||||||
let buttonBar = NSSegmentedControl(images: [addButtonImage, removeButtonImage, actionButtonImage],
|
let menu = NSMenu()
|
||||||
trackingMode: .momentary, target: nil, action: #selector(buttonBarClicked(sender:)))
|
menu.addItem(imageItem)
|
||||||
buttonBar.segmentStyle = .smallSquare
|
menu.addItem(withTitle: tr("macMenuAddEmptyTunnel"), action: #selector(handleAddEmptyTunnelAction), keyEquivalent: "n")
|
||||||
buttonBar.segmentDistribution = .fit
|
menu.addItem(withTitle: tr("macMenuImportTunnels"), action: #selector(handleImportTunnelAction), keyEquivalent: "o")
|
||||||
buttonBar.setShowsMenuIndicator(true, forSegment: 0)
|
menu.autoenablesItems = false
|
||||||
buttonBar.setShowsMenuIndicator(false, forSegment: 1)
|
|
||||||
buttonBar.setShowsMenuIndicator(true, forSegment: 2)
|
let button = NSPopUpButton(frame: NSRect.zero, pullsDown: true)
|
||||||
return buttonBar
|
button.menu = menu
|
||||||
|
button.bezelStyle = .smallSquare
|
||||||
|
(button.cell as? NSPopUpButtonCell)?.arrowPosition = .arrowAtBottom
|
||||||
|
return button
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let addMenu: NSMenu = {
|
let removeButton: NSButton = {
|
||||||
let addMenu = NSMenu(title: "TunnelsListAdd")
|
let image = NSImage(named: NSImage.removeTemplateName)!
|
||||||
addMenu.addItem(withTitle: tr("macMenuAddEmptyTunnel"), action: #selector(handleAddEmptyTunnelAction), keyEquivalent: "n")
|
let button = NSButton(image: image, target: self, action: #selector(handleRemoveTunnelAction))
|
||||||
addMenu.addItem(withTitle: tr("macMenuImportTunnels"), action: #selector(handleImportTunnelAction), keyEquivalent: "o")
|
button.bezelStyle = .smallSquare
|
||||||
return addMenu
|
button.imagePosition = .imageOnly
|
||||||
|
return button
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let actionMenu: NSMenu = {
|
let actionButton: NSPopUpButton = {
|
||||||
let actionMenu = NSMenu(title: "TunnelsListAction")
|
let imageItem = NSMenuItem(title: "", action: nil, keyEquivalent: "")
|
||||||
actionMenu.addItem(withTitle: tr("macMenuExportLog"), action: #selector(handleExportLogAction), keyEquivalent: "")
|
imageItem.image = NSImage(named: NSImage.actionTemplateName)!
|
||||||
actionMenu.addItem(withTitle: tr("macMenuExportTunnels"), action: #selector(handleExportTunnelsAction), keyEquivalent: "")
|
|
||||||
return actionMenu
|
let menu = NSMenu()
|
||||||
|
menu.addItem(imageItem)
|
||||||
|
menu.addItem(withTitle: tr("macMenuExportLog"), action: #selector(handleExportLogAction), keyEquivalent: "")
|
||||||
|
menu.addItem(withTitle: tr("macMenuExportTunnels"), action: #selector(handleExportTunnelsAction), keyEquivalent: "")
|
||||||
|
menu.autoenablesItems = false
|
||||||
|
|
||||||
|
let button = NSPopUpButton(frame: NSRect.zero, pullsDown: true)
|
||||||
|
button.menu = menu
|
||||||
|
button.bezelStyle = .smallSquare
|
||||||
|
(button.cell as? NSPopUpButtonCell)?.arrowPosition = .arrowAtBottom
|
||||||
|
return button
|
||||||
}()
|
}()
|
||||||
|
|
||||||
init(tunnelsManager: TunnelsManager) {
|
init(tunnelsManager: TunnelsManager) {
|
||||||
|
@ -76,6 +90,16 @@ class TunnelsListTableViewController: NSViewController {
|
||||||
clipView.documentView = tableView
|
clipView.documentView = tableView
|
||||||
scrollView.contentView = clipView
|
scrollView.contentView = clipView
|
||||||
|
|
||||||
|
let buttonBar = NSStackView(views: [addButton, removeButton, actionButton])
|
||||||
|
buttonBar.orientation = .horizontal
|
||||||
|
buttonBar.spacing = -1
|
||||||
|
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
removeButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 26),
|
||||||
|
removeButton.topAnchor.constraint(equalTo: buttonBar.topAnchor),
|
||||||
|
removeButton.bottomAnchor.constraint(equalTo: buttonBar.bottomAnchor)
|
||||||
|
])
|
||||||
|
|
||||||
let fillerButton = FillerButton()
|
let fillerButton = FillerButton()
|
||||||
|
|
||||||
let containerView = NSView()
|
let containerView = NSView()
|
||||||
|
@ -104,9 +128,8 @@ class TunnelsListTableViewController: NSViewController {
|
||||||
containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 120)
|
containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 120)
|
||||||
])
|
])
|
||||||
|
|
||||||
buttonBar.target = self
|
addButton.menu?.items.forEach { $0.target = self }
|
||||||
addMenu.items.forEach { $0.target = self }
|
actionButton.menu?.items.forEach { $0.target = self }
|
||||||
actionMenu.items.forEach { $0.target = self }
|
|
||||||
|
|
||||||
view = containerView
|
view = containerView
|
||||||
}
|
}
|
||||||
|
@ -123,22 +146,6 @@ class TunnelsListTableViewController: NSViewController {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func buttonBarClicked(sender: AnyObject?) {
|
|
||||||
guard let buttonBar = sender as? NSSegmentedControl else { return }
|
|
||||||
// We have to resort to explicitly showing the menu instead of using NSSegmentedControl.setMenu()
|
|
||||||
// because we have a mix of menu and non-menu segments.
|
|
||||||
// See: http://openradar.appspot.com/radar?id=61419
|
|
||||||
if buttonBar.selectedSegment == 0 {
|
|
||||||
let segmentBottomLeft = NSPoint(x: 0, y: buttonBar.bounds.height + 2)
|
|
||||||
addMenu.popUp(positioning: nil, at: segmentBottomLeft, in: buttonBar)
|
|
||||||
} else if buttonBar.selectedSegment == 1 {
|
|
||||||
handleRemoveTunnelAction()
|
|
||||||
} else if buttonBar.selectedSegment == 2 {
|
|
||||||
let segmentBottomLeft = NSPoint(x: buttonBar.bounds.width * 0.66, y: buttonBar.bounds.height + 2)
|
|
||||||
actionMenu.popUp(positioning: nil, at: segmentBottomLeft, in: buttonBar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func handleAddEmptyTunnelAction() {
|
@objc func handleAddEmptyTunnelAction() {
|
||||||
let tunnelEditVC = TunnelEditViewController(tunnelsManager: tunnelsManager, tunnel: nil)
|
let tunnelEditVC = TunnelEditViewController(tunnelsManager: tunnelsManager, tunnel: nil)
|
||||||
tunnelEditVC.delegate = self
|
tunnelEditVC.delegate = self
|
||||||
|
@ -161,10 +168,10 @@ class TunnelsListTableViewController: NSViewController {
|
||||||
alert.addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleCancel"))
|
alert.addButton(withTitle: tr("macDeleteTunnelConfirmationAlertButtonTitleCancel"))
|
||||||
alert.beginSheetModal(for: window) { [weak self] response in
|
alert.beginSheetModal(for: window) { [weak self] response in
|
||||||
guard response == .alertFirstButtonReturn else { return }
|
guard response == .alertFirstButtonReturn else { return }
|
||||||
self?.buttonBar.setEnabled(false, forSegment: 1)
|
self?.removeButton.isEnabled = false
|
||||||
self?.tunnelsManager.remove(tunnel: selectedTunnel) { [weak self] error in
|
self?.tunnelsManager.remove(tunnel: selectedTunnel) { [weak self] error in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
defer { self.buttonBar.setEnabled(true, forSegment: 1) }
|
defer { self.removeButton.isEnabled = true }
|
||||||
if let error = error {
|
if let error = error {
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: self)
|
ErrorPresenter.showErrorAlert(error: error, from: self)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue