Create and use a SidebarGearMenuDelegate to show a menu when the gear menu in the sidebar is clicked.

This commit is contained in:
Brent Simmons 2018-01-28 16:09:18 -08:00
parent fb45ae11eb
commit 2d7d903bca
5 changed files with 101 additions and 5 deletions

View File

@ -119,6 +119,7 @@
84CC08061FF5D2E000C0C0ED /* FeedListSplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CC08051FF5D2E000C0C0ED /* FeedListSplitViewController.swift */; };
84CC88181FE59CBF00644329 /* SmartFeedsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CC88171FE59CBF00644329 /* SmartFeedsController.swift */; };
84D52E951FE588BB00D14F5B /* DetailStatusBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D52E941FE588BB00D14F5B /* DetailStatusBarView.swift */; };
84D5BA20201E8FB6009092BD /* SidebarGearMenuDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D5BA1F201E8FB6009092BD /* SidebarGearMenuDelegate.swift */; };
84DAEE301F86CAFE0058304B /* OPMLImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DAEE2F1F86CAFE0058304B /* OPMLImporter.swift */; };
84DAEE321F870B390058304B /* DockBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DAEE311F870B390058304B /* DockBadge.swift */; };
84E46C7D1F75EF7B005ECFB3 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E46C7C1F75EF7B005ECFB3 /* AppDefaults.swift */; };
@ -577,6 +578,7 @@
84CC08051FF5D2E000C0C0ED /* FeedListSplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListSplitViewController.swift; sourceTree = "<group>"; };
84CC88171FE59CBF00644329 /* SmartFeedsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartFeedsController.swift; sourceTree = "<group>"; };
84D52E941FE588BB00D14F5B /* DetailStatusBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailStatusBarView.swift; sourceTree = "<group>"; };
84D5BA1F201E8FB6009092BD /* SidebarGearMenuDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarGearMenuDelegate.swift; sourceTree = "<group>"; };
84DAEE2F1F86CAFE0058304B /* OPMLImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLImporter.swift; sourceTree = "<group>"; };
84DAEE311F870B390058304B /* DockBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DockBadge.swift; path = Evergreen/DockBadge.swift; sourceTree = "<group>"; };
84E46C7C1F75EF7B005ECFB3 /* AppDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDefaults.swift; path = Evergreen/AppDefaults.swift; sourceTree = "<group>"; };
@ -823,6 +825,7 @@
849A97631ED9EB96007D329B /* UnreadCountView.swift */,
845F52EC1FB2B9FC00C10BF0 /* FeedPasteboardWriter.swift */,
849A97821ED9EC63007D329B /* SidebarStatusBarView.swift */,
84D5BA1F201E8FB6009092BD /* SidebarGearMenuDelegate.swift */,
844B5B6A1FEA224000C7C76A /* Keyboard */,
845A29251FC928C7007B49E3 /* Cell */,
);
@ -1671,6 +1674,7 @@
849A976D1ED9EBC8007D329B /* TimelineTableView.swift in Sources */,
84D52E951FE588BB00D14F5B /* DetailStatusBarView.swift in Sources */,
84B99C671FAE35E600ECDEDB /* FeedListTreeControllerDelegate.swift in Sources */,
84D5BA20201E8FB6009092BD /* SidebarGearMenuDelegate.swift in Sources */,
84B99C691FAE36B800ECDEDB /* FeedListFolder.swift in Sources */,
84411E711FE5FBFA004B527F /* SmallIconProvider.swift in Sources */,
844B5B591FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift in Sources */,

View File

@ -393,6 +393,9 @@
<menuItem title="Item 2" id="8qw-qv-HEP"/>
<menuItem title="Item 3" id="V2t-4f-IAM"/>
</items>
<connections>
<outlet property="delegate" destination="f3Y-bi-SLk" id="bVa-Lg-nGG"/>
</connections>
</menu>
</popUpButtonCell>
</popUpButton>
@ -438,10 +441,16 @@
</constraints>
</view>
<connections>
<outlet property="gearMenuDelegate" destination="f3Y-bi-SLk" id="2on-6C-laM"/>
<outlet property="outlineView" destination="cnV-kg-Dn2" id="FVf-OT-E3h"/>
</connections>
</viewController>
<customObject id="Jih-JO-hIE" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
<customObject id="f3Y-bi-SLk" customClass="SidebarGearMenuDelegate" customModule="Evergreen" customModuleProvider="target">
<connections>
<outlet property="sidebarViewController" destination="XML-A3-pDn" id="Tw0-4c-1Go"/>
</connections>
</customObject>
<customObject id="h5K-zR-cUa" customClass="SidebarKeyboardDelegate" customModule="Evergreen" customModuleProvider="target">
<connections>
<outlet property="sidebarViewController" destination="XML-A3-pDn" id="kwd-Zc-HJm"/>
@ -677,7 +686,7 @@
<image name="markAllRead" width="11" height="9.5"/>
<image name="markRead" width="9.5" height="9.5"/>
<image name="newFolder" width="9.5" height="9.5"/>
<image name="nextUnread" width="9.5" height="9.5"/>
<image name="nextUnread" width="12" height="9.5"/>
<image name="openInBrowser" width="9.5" height="9.5"/>
<image name="star" width="9.5" height="9.5"/>
</resources>

View File

@ -9,6 +9,7 @@
import AppKit
import Data
import Account
import RSCore
extension MainWindowController {
@ -38,10 +39,18 @@ extension MainWindowController {
@objc func openHomePageFromContextualMenu(_ sender: Any?) {
guard let menuItem = sender as? NSMenuItem, let urlString = menuItem.representedObject as? String else {
return
}
Browser.open(urlString, inBackground: false)
}
@objc func copyStringFromContextualMenu(_ sender: Any?) {
@objc func copyURLFromContextualMenu(_ sender: Any?) {
guard let menuItem = sender as? NSMenuItem, let urlString = menuItem.representedObject as? String else {
return
}
URLPasteboardWriter.write(urlString: urlString, to: NSPasteboard.general)
}
@objc func markObjectsReadFromContextualMenu(_ sender: Any?) {
@ -76,11 +85,11 @@ private extension MainWindowController {
menu.addItem(NSMenuItem.separator())
}
let copyFeedURLItem = menuItem(NSLocalizedString("Copy Feed URL", comment: "Command"), #selector(copyStringFromContextualMenu(_:)), feed.url)
let copyFeedURLItem = menuItem(NSLocalizedString("Copy Feed URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), feed.url)
menu.addItem(copyFeedURLItem)
if let homePageURL = feed.homePageURL {
let item = menuItem(NSLocalizedString("Copy Home Page URL", comment: "Command"), #selector(copyStringFromContextualMenu(_:)), homePageURL)
let item = menuItem(NSLocalizedString("Copy Home Page URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), homePageURL)
menu.addItem(item)
}
menu.addItem(NSMenuItem.separator())
@ -100,11 +109,18 @@ private extension MainWindowController {
menu.addItem(NSMenuItem.separator())
}
menu.addItem(renameMenuItem(folder))
menu.addItem(deleteMenuItem([folder]))
return menu.numberOfItems > 0 ? menu : nil
}
func menuForMultipleObjects(_ objects: [Any]) -> NSMenu? {
guard allObjectsAreFeedsAndOrFolders(objects) else {
return nil
}
let menu = NSMenu(title: "")
if anyObjectInArrayHasNonZeroUnreadCount(objects) {
@ -112,6 +128,7 @@ private extension MainWindowController {
menu.addItem(NSMenuItem.separator())
}
menu.addItem(deleteMenuItem(objects))
return menu.numberOfItems > 0 ? menu : nil
}
@ -143,6 +160,21 @@ private extension MainWindowController {
return false
}
func allObjectsAreFeedsAndOrFolders(_ objects: [Any]) -> Bool {
for object in objects {
if !objectIsFeedOrFolder(object) {
return false
}
}
return true
}
func objectIsFeedOrFolder(_ object: Any) -> Bool {
return object is Feed || object is Folder
}
func menuItem(_ title: String, _ action: Selector, _ representedObject: Any) -> NSMenuItem {
let item = NSMenuItem(title: title, action: action, keyEquivalent: "")

View File

@ -0,0 +1,39 @@
//
// SidebarGearMenuDelegate.swift
// Evergreen
//
// Created by Brent Simmons on 1/28/18.
// Copyright © 2018 Ranchero Software. All rights reserved.
//
import AppKit
@objc final class SidebarGearMenuDelegate: NSObject, NSMenuDelegate {
@IBOutlet weak var sidebarViewController: SidebarViewController?
public func menuNeedsUpdate(_ menu: NSMenu) {
guard let sidebarViewController = sidebarViewController else {
return
}
// Save the first item, since its the gear icon itself.
guard let gearMenuItem = menu.item(at: 0) else {
assertionFailure("Expected sidebar gear menu to have at least one item.")
return
}
menu.removeAllItems()
menu.addItem(gearMenuItem)
guard let contextualMenu = sidebarViewController.contextualMenuForSelectedObjects() else {
return
}
let items = contextualMenu.items
contextualMenu.removeAllItems()
for menuItem in items {
menu.addItem(menuItem)
}
}
}

View File

@ -6,7 +6,7 @@
// Copyright © 2015 Ranchero Software, LLC. All rights reserved.
//
import Cocoa
import AppKit
import RSTree
import Data
import Account
@ -15,6 +15,8 @@ import RSCore
@objc class SidebarViewController: NSViewController, NSOutlineViewDelegate, NSOutlineViewDataSource, UndoableCommandRunner {
@IBOutlet var outlineView: SidebarOutlineView!
@IBOutlet var gearMenuDelegate: SidebarGearMenuDelegate!
let treeControllerDelegate = SidebarTreeControllerDelegate()
lazy var treeController: TreeController = {
TreeController(delegate: treeControllerDelegate)
@ -189,6 +191,16 @@ import RSCore
window.makeFirstResponderUnlessDescendantIsFirstResponder(outlineView)
}
// MARK: Contextual Menu
func contextualMenuForSelectedObjects() -> NSMenu? {
guard let mainWindowController = view.window?.windowController as? MainWindowController else {
return nil
}
return mainWindowController.menu(for: selectedObjects)
}
// MARK: NSOutlineViewDelegate
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {