diff --git a/Evergreen.xcodeproj/project.pbxproj b/Evergreen.xcodeproj/project.pbxproj index 33373535e..542de2252 100644 --- a/Evergreen.xcodeproj/project.pbxproj +++ b/Evergreen.xcodeproj/project.pbxproj @@ -88,8 +88,6 @@ 84F204CE1FAACB660076E152 /* FeedListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204CD1FAACB660076E152 /* FeedListViewController.swift */; }; 84F204DE1FAACB8B0076E152 /* FeedListTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DD1FAACB8B0076E152 /* FeedListTimelineViewController.swift */; }; 84F204E01FAACBB30076E152 /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; }; - 84F204E21FAAD4750076E152 /* TimelineTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204E11FAAD4750076E152 /* TimelineTableViewDelegate.swift */; }; - 84FB3A6F1FA6612C00EFC320 /* TimelineTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FB3A6E1FA6612C00EFC320 /* TimelineTableViewDataSource.swift */; }; 84FB9A2F1EDCD6C4003D53B9 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FB9A2D1EDCD6B8003D53B9 /* Sparkle.framework */; }; 84FB9A301EDCD6C4003D53B9 /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84FB9A2D1EDCD6B8003D53B9 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ @@ -456,8 +454,6 @@ 84F204CD1FAACB660076E152 /* FeedListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListViewController.swift; sourceTree = ""; }; 84F204DD1FAACB8B0076E152 /* FeedListTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListTimelineViewController.swift; sourceTree = ""; }; 84F204DF1FAACBB30076E152 /* ArticleArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleArray.swift; sourceTree = ""; }; - 84F204E11FAAD4750076E152 /* TimelineTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewDelegate.swift; sourceTree = ""; }; - 84FB3A6E1FA6612C00EFC320 /* TimelineTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewDataSource.swift; sourceTree = ""; }; 84FB9A2D1EDCD6B8003D53B9 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Frameworks/Vendor/Sparkle.framework; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -592,8 +588,6 @@ children = ( 849A976B1ED9EBC8007D329B /* TimelineViewController.swift */, 84F204DF1FAACBB30076E152 /* ArticleArray.swift */, - 84FB3A6E1FA6612C00EFC320 /* TimelineTableViewDataSource.swift */, - 84F204E11FAAD4750076E152 /* TimelineTableViewDelegate.swift */, 849A97691ED9EBC8007D329B /* TimelineTableRowView.swift */, 849A976A1ED9EBC8007D329B /* TimelineTableView.swift */, 849A976F1ED9EC04007D329B /* Cell */, @@ -1227,7 +1221,6 @@ 849A97431ED9EAA9007D329B /* AddFolderWindowController.swift in Sources */, 849A97921ED9EF65007D329B /* IndeterminateProgressWindowController.swift in Sources */, 849A97801ED9EC42007D329B /* DetailViewController.swift in Sources */, - 84F204E21FAAD4750076E152 /* TimelineTableViewDelegate.swift in Sources */, 849A976E1ED9EBC8007D329B /* TimelineViewController.swift in Sources */, 849A978D1ED9EE4D007D329B /* FeedListWindowController.swift in Sources */, 849A97771ED9EC04007D329B /* TimelineCellData.swift in Sources */, @@ -1241,7 +1234,6 @@ 849A97851ED9ECCD007D329B /* PreferencesWindowController.swift in Sources */, 849A977A1ED9EC04007D329B /* TimelineTableCellView.swift in Sources */, 849A97761ED9EC04007D329B /* TimelineCellAppearance.swift in Sources */, - 84FB3A6F1FA6612C00EFC320 /* TimelineTableViewDataSource.swift in Sources */, 849A97A21ED9F180007D329B /* FeedTitleDownloader.swift in Sources */, 849A977F1ED9EC42007D329B /* ArticleRenderer.swift in Sources */, ); diff --git a/Evergreen/Base.lproj/MainWindow.storyboard b/Evergreen/Base.lproj/MainWindow.storyboard index b7ee3296b..167cf04a7 100644 --- a/Evergreen/Base.lproj/MainWindow.storyboard +++ b/Evergreen/Base.lproj/MainWindow.storyboard @@ -1,7 +1,7 @@ - + - + @@ -504,6 +504,7 @@ + diff --git a/Evergreen/MainWindow/Timeline/TimelineTableViewDataSource.swift b/Evergreen/MainWindow/Timeline/TimelineTableViewDataSource.swift deleted file mode 100644 index 3dab3bc7c..000000000 --- a/Evergreen/MainWindow/Timeline/TimelineTableViewDataSource.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// TimelineTableViewDataSource.swift -// Evergreen -// -// Created by Brent Simmons on 10/29/17. -// Copyright © 2017 Ranchero Software. All rights reserved. -// - -import Cocoa - -@objc final class TimelineTableViewDataSource: NSObject, NSTableViewDataSource { - - private weak var timelineViewController: TimelineViewController? - - init(timelineViewController: TimelineViewController) { - - self.timelineViewController = timelineViewController - } - - // MARK: NSTableViewDataSource - - func numberOfRows(in tableView: NSTableView) -> Int { - - return timelineViewController?.articles.count ?? 0 - } - - func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { - - return timelineViewController?.articles.articleAtRow(row) ?? nil - } - -} diff --git a/Evergreen/MainWindow/Timeline/TimelineTableViewDelegate.swift b/Evergreen/MainWindow/Timeline/TimelineTableViewDelegate.swift deleted file mode 100644 index c08f0e6b2..000000000 --- a/Evergreen/MainWindow/Timeline/TimelineTableViewDelegate.swift +++ /dev/null @@ -1,112 +0,0 @@ -// -// TimelineTableViewDelegate.swift -// Evergreen -// -// Created by Brent Simmons on 11/1/17. -// Copyright © 2017 Ranchero Software. All rights reserved. -// - -import Cocoa -import Data - -@objc final class TimelineTableViewDelegate: NSObject, NSTableViewDelegate { - - private weak var timelineViewController: TimelineViewController? - - init(timelineViewController: TimelineViewController) { - - self.timelineViewController = timelineViewController - } - - // MARK: NSTableViewDelegate - - func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { - - guard let timelineViewController = timelineViewController else { - return nil - } - - let rowView: TimelineTableRowView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "timelineRow"), owner: self) as! TimelineTableRowView - rowView.cellAppearance = timelineViewController.cellAppearance - return rowView - } - - func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { - - guard let timelineViewController = timelineViewController else { - return nil - } - - let cell: TimelineTableCellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "timelineCell"), owner: self) as! TimelineTableCellView - cell.cellAppearance = timelineViewController.cellAppearance - - if let article = timelineViewController.articles.articleAtRow(row) { - configureTimelineCell(cell, article: article) - } - else { - makeTimelineCellEmpty(cell) - } - - return cell - } - - private func postTimelineSelectionDidChangeNotification(_ selectedArticle: Article?) { - - guard let timelineViewController = timelineViewController else { - return - } - - let appInfo = AppInfo() - if let article = selectedArticle { - appInfo.article = article - } - appInfo.view = timelineViewController.tableView - - NotificationCenter.default.post(name: .TimelineSelectionDidChange, object: timelineViewController, userInfo: appInfo.userInfo) - } - - func tableViewSelectionDidChange(_ notification: Notification) { - - guard let timelineViewController = timelineViewController, let tableView = timelineViewController.tableView else { - return - } - - tableView.redrawGrid() - - let selectedRow = tableView.selectedRow - if selectedRow < 0 || selectedRow == NSNotFound || tableView.numberOfSelectedRows != 1 { - postTimelineSelectionDidChangeNotification(nil) - return - } - - if let selectedArticle = timelineViewController.articles.articleAtRow(selectedRow) { - if (!selectedArticle.status.read) { - markArticles(Set([selectedArticle]), statusKey: .read, flag: true) - } - postTimelineSelectionDidChangeNotification(selectedArticle) - } - else { - postTimelineSelectionDidChangeNotification(nil) - } - } - -} - -private extension TimelineTableViewDelegate { - - func configureTimelineCell(_ cell: TimelineTableCellView, article: Article) { - - guard let timelineViewController = timelineViewController else { - return - } - - cell.objectValue = article - cell.cellData = TimelineCellData(article: article, appearance: timelineViewController.cellAppearance, showFeedName: timelineViewController.showFeedNames) - } - - func makeTimelineCellEmpty(_ cell: TimelineTableCellView) { - - cell.objectValue = nil - cell.cellData = emptyCellData - } -} diff --git a/Evergreen/MainWindow/Timeline/TimelineViewController.swift b/Evergreen/MainWindow/Timeline/TimelineViewController.swift index f87dca555..6beda8936 100644 --- a/Evergreen/MainWindow/Timeline/TimelineViewController.swift +++ b/Evergreen/MainWindow/Timeline/TimelineViewController.swift @@ -15,17 +15,6 @@ import Account class TimelineViewController: NSViewController, KeyboardDelegate { @IBOutlet var tableView: TimelineTableView! - var cellAppearance: TimelineCellAppearance! - var showFeedNames = false - - var articles = ArticleArray() { - didSet { - if articles != oldValue { - clearUndoableCommands() - tableView.reloadData() - } - } - } var selectedArticles: [Article] { get { @@ -34,16 +23,20 @@ class TimelineViewController: NSViewController, KeyboardDelegate { } private var undoableCommands = [UndoableCommand]() - - private lazy var tableViewDataSource: TimelineTableViewDataSource! = { - return TimelineTableViewDataSource(timelineViewController: self) - }() - - private lazy var tableViewDelegate: TimelineTableViewDelegate! = { - return TimelineTableViewDelegate(timelineViewController: self) - }() - + private var cellAppearance: TimelineCellAppearance! + private var showFeedNames = false private var didRegisterForNotifications = false + private let timelineFontSizeKVOKey = "values.{AppDefaults.Key.timelineFontSize}" + + private var articles = ArticleArray() { + didSet { + if articles != oldValue { + clearUndoableCommands() + tableView.reloadData() + } + } + } + private var fontSize: FontSize = AppDefaults.shared.timelineFontSize { didSet { fontSizeDidChange() @@ -67,14 +60,10 @@ class TimelineViewController: NSViewController, KeyboardDelegate { } } - private let timelineFontSizeKVOKey = "values.{AppDefaults.Key.timelineFontSize}" - override func viewDidLoad() { cellAppearance = TimelineCellAppearance(theme: currentTheme, fontSize: fontSize) - tableView.dataSource = tableViewDataSource - tableView.delegate = tableViewDelegate tableView.rowHeight = calculateRowHeight() tableView.target = self tableView.doubleAction = #selector(openArticleInBrowser(_:)) @@ -358,6 +347,94 @@ class TimelineViewController: NSViewController, KeyboardDelegate { } +// MARK: - NSTableViewDataSource + +extension TimelineViewController: NSTableViewDataSource { + + func numberOfRows(in tableView: NSTableView) -> Int { + + return articles.count + } + + func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { + + return articles.articleAtRow(row) ?? nil + } +} + +// MARK: - NSTableViewDelegate + +extension TimelineViewController: NSTableViewDelegate { + + func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { + + let rowView: TimelineTableRowView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "timelineRow"), owner: self) as! TimelineTableRowView + rowView.cellAppearance = cellAppearance + return rowView + } + + func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + + let cell: TimelineTableCellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "timelineCell"), owner: self) as! TimelineTableCellView + cell.cellAppearance = cellAppearance + + if let article = articles.articleAtRow(row) { + configureTimelineCell(cell, article: article) + } + else { + makeTimelineCellEmpty(cell) + } + + return cell + } + + func tableViewSelectionDidChange(_ notification: Notification) { + + tableView.redrawGrid() + + let selectedRow = tableView.selectedRow + if selectedRow < 0 || selectedRow == NSNotFound || tableView.numberOfSelectedRows != 1 { + postTimelineSelectionDidChangeNotification(nil) + return + } + + if let selectedArticle = articles.articleAtRow(selectedRow) { + if (!selectedArticle.status.read) { + markArticles(Set([selectedArticle]), statusKey: .read, flag: true) + } + postTimelineSelectionDidChangeNotification(selectedArticle) + } + else { + postTimelineSelectionDidChangeNotification(nil) + } + } + + private func postTimelineSelectionDidChangeNotification(_ selectedArticle: Article?) { + + let appInfo = AppInfo() + if let article = selectedArticle { + appInfo.article = article + } + appInfo.view = tableView + + NotificationCenter.default.post(name: .TimelineSelectionDidChange, object: self, userInfo: appInfo.userInfo) + } + + private func configureTimelineCell(_ cell: TimelineTableCellView, article: Article) { + + cell.objectValue = article + cell.cellData = TimelineCellData(article: article, appearance: cellAppearance, showFeedName: showFeedNames) + } + + private func makeTimelineCellEmpty(_ cell: TimelineTableCellView) { + + cell.objectValue = nil + cell.cellData = emptyCellData + } +} + +// MARK: - Private + private extension TimelineViewController { var hasAtLeastOneSelectedArticle: Bool {