Create and use a SidebarGearMenuDelegate to show a menu when the gear menu in the sidebar is clicked.
This commit is contained in:
parent
fb45ae11eb
commit
2d7d903bca
@ -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 */,
|
||||
|
@ -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>
|
||||
|
@ -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: "")
|
||||
|
39
Evergreen/MainWindow/Sidebar/SidebarGearMenuDelegate.swift
Normal file
39
Evergreen/MainWindow/Sidebar/SidebarGearMenuDelegate.swift
Normal 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 it’s 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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? {
|
||||
|
Loading…
x
Reference in New Issue
Block a user