From a4c82739b648ac03b6311608a39bf06b5a41373b Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Thu, 21 Dec 2017 14:43:29 -0800 Subject: [PATCH] Implement next and previous subscription navigation. Also: on first-run, position and size the window a bit nicer. --- .../MainWindow/MainWindowController.swift | 26 ++++++- .../Sidebar/SidebarViewController.swift | 5 ++ .../RSCore/NSOutlineView+Extensions.swift | 67 +++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/Evergreen/MainWindow/MainWindowController.swift b/Evergreen/MainWindow/MainWindowController.swift index 2c4900ee2..556afab20 100644 --- a/Evergreen/MainWindow/MainWindowController.swift +++ b/Evergreen/MainWindow/MainWindowController.swift @@ -32,9 +32,21 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { if !AppDefaults.shared.showTitleOnMainWindow { window?.titleVisibility = .hidden } - + window?.setFrameUsingName(windowAutosaveName, force: true) - + if AppDefaults.shared.isFirstRun { + + if let window = window, let screen = window.screen { + let width: CGFloat = 1280.0 + let height: CGFloat = 768.0 + let insetX: CGFloat = 192.0 + let insetY: CGFloat = 96.0 + + window.setContentSize(NSSize(width: width, height: height)) + window.setFrameTopLeftPoint(NSPoint(x: insetX, y: screen.visibleFrame.maxY - insetY)) + } + } + detailSplitViewItem?.minimumThickness = 384 NotificationCenter.default.addObserver(self, selector: #selector(applicationWillTerminate(_:)), name: NSApplication.willTerminateNotification, object: nil) @@ -228,6 +240,16 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { sidebarViewController?.focus() } + + @IBAction func goToPreviousSubscription(_ sender: Any?) { + + sidebarViewController?.outlineView.selectPreviousRow(sender) + } + + @IBAction func goToNextSubscription(_ sender: Any?) { + + sidebarViewController?.outlineView.selectNextRow(sender) + } } // MARK: - Private diff --git a/Evergreen/MainWindow/Sidebar/SidebarViewController.swift b/Evergreen/MainWindow/Sidebar/SidebarViewController.swift index d5874943e..f1fd30060 100644 --- a/Evergreen/MainWindow/Sidebar/SidebarViewController.swift +++ b/Evergreen/MainWindow/Sidebar/SidebarViewController.swift @@ -202,6 +202,11 @@ import RSCore return proposedSelectionIndexes } + func outlineView(_ outlineView: NSOutlineView, shouldSelectItem item: Any) -> Bool { + + return !self.outlineView(outlineView, isGroupItem: item) + } + func outlineViewSelectionDidChange(_ notification: Notification) { // TODO: support multiple selection diff --git a/Frameworks/RSCore/RSCore/NSOutlineView+Extensions.swift b/Frameworks/RSCore/RSCore/NSOutlineView+Extensions.swift index 7bd4525e2..2c0f018f4 100755 --- a/Frameworks/RSCore/RSCore/NSOutlineView+Extensions.swift +++ b/Frameworks/RSCore/RSCore/NSOutlineView+Extensions.swift @@ -23,6 +23,62 @@ public extension NSOutlineView { } } + var firstSelectedRow: Int? { + + if selectionIsEmpty { + return nil + } + return selectedRowIndexes.first + } + + var lastSelectedRow: Int? { + + if selectionIsEmpty { + return nil + } + return selectedRowIndexes.last + } + + @IBAction func selectPreviousRow(_ sender: Any?) { + + guard var row = firstSelectedRow else { + return + } + + if row < 1 { + return + } + while true { + row -= 1 + if row < 0 { + return + } + if canSelect(row) { + rs_selectRowAndScrollToVisible(row) + return + } + } + } + + @IBAction func selectNextRow(_ sender: Any?) { + + // If no selectedRow, end up at first selectable row. + var row = lastSelectedRow ?? -1 + + while true { + row += 1 + if let _ = item(atRow: row) { + if canSelect(row) { + rs_selectRowAndScrollToVisible(row) + return + } + } + else { + return // if there are no more items, we’re out of rows + } + } + } + @IBAction func collapseSelectedRows(_ sender: Any?) { for item in selectedItems { @@ -97,4 +153,15 @@ public extension NSOutlineView { return delegate?.outlineView?(self, isGroupItem: item) ?? false } + + func canSelect(_ row: Int) -> Bool { + + guard let item = item(atRow: row) else { + return false + } + let isSelectable = delegate?.outlineView?(self, shouldSelectItem: item) ?? true + return isSelectable + } } + +