Implement the Feed Directory’s split view delegate.
This commit is contained in:
parent
f0f24c0a99
commit
7ae2345073
|
@ -38,7 +38,7 @@
|
|||
846E77411F6EF6A100A165E2 /* Database.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 846E77211F6EF5D100A165E2 /* Database.framework */; };
|
||||
846E77421F6EF6A100A165E2 /* Database.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 846E77211F6EF5D100A165E2 /* Database.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
84702AA41FA27AC0006B8943 /* MarkReadOrUnreadCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84702AA31FA27AC0006B8943 /* MarkReadOrUnreadCommand.swift */; };
|
||||
847C4C9C1FF44F790090D517 /* FeedListSplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847C4C9B1FF44F790090D517 /* FeedListSplitViewController.swift */; };
|
||||
847C4C9C1FF44F790090D517 /* FeedListSplitViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847C4C9B1FF44F790090D517 /* FeedListSplitViewDelegate.swift */; };
|
||||
848F6AE51FC29CFB002D422E /* FaviconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848F6AE41FC29CFA002D422E /* FaviconDownloader.swift */; };
|
||||
849A97431ED9EAA9007D329B /* AddFolderWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97421ED9EAA9007D329B /* AddFolderWindowController.swift */; };
|
||||
849A97531ED9EAC0007D329B /* AddFeedController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97511ED9EAC0007D329B /* AddFeedController.swift */; };
|
||||
|
@ -444,7 +444,7 @@
|
|||
846E77161F6EF5D000A165E2 /* Database.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Database.xcodeproj; path = Frameworks/Database/Database.xcodeproj; sourceTree = "<group>"; };
|
||||
846E77301F6EF5D600A165E2 /* Account.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Account.xcodeproj; path = Frameworks/Account/Account.xcodeproj; sourceTree = "<group>"; };
|
||||
84702AA31FA27AC0006B8943 /* MarkReadOrUnreadCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkReadOrUnreadCommand.swift; sourceTree = "<group>"; };
|
||||
847C4C9B1FF44F790090D517 /* FeedListSplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListSplitViewController.swift; sourceTree = "<group>"; };
|
||||
847C4C9B1FF44F790090D517 /* FeedListSplitViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListSplitViewDelegate.swift; sourceTree = "<group>"; };
|
||||
848F6AE41FC29CFA002D422E /* FaviconDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FaviconDownloader.swift; sourceTree = "<group>"; };
|
||||
849A97421ED9EAA9007D329B /* AddFolderWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddFolderWindowController.swift; sourceTree = "<group>"; };
|
||||
849A97511ED9EAC0007D329B /* AddFeedController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AddFeedController.swift; path = AddFeed/AddFeedController.swift; sourceTree = "<group>"; };
|
||||
|
@ -791,9 +791,9 @@
|
|||
children = (
|
||||
84B2FAA31FF47BAC009C4878 /* FeedListWindow.xib */,
|
||||
849A978C1ED9EE4D007D329B /* FeedListWindowController.swift */,
|
||||
847C4C9B1FF44F790090D517 /* FeedListSplitViewDelegate.swift */,
|
||||
84F204CD1FAACB660076E152 /* FeedListViewController.swift */,
|
||||
84F204DD1FAACB8B0076E152 /* FeedListTimelineViewController.swift */,
|
||||
847C4C9B1FF44F790090D517 /* FeedListSplitViewController.swift */,
|
||||
84513F8F1FAA63950023A1A9 /* FeedListControlsView.swift */,
|
||||
84B99C661FAE35E600ECDEDB /* FeedListTreeControllerDelegate.swift */,
|
||||
84B99C681FAE36B800ECDEDB /* FeedListFolder.swift */,
|
||||
|
@ -1444,7 +1444,7 @@
|
|||
84B99C6B1FAE370B00ECDEDB /* FeedListFeed.swift in Sources */,
|
||||
842611A01FCB72600086A189 /* FeaturedImageDownloader.swift in Sources */,
|
||||
849A97781ED9EC04007D329B /* TimelineCellLayout.swift in Sources */,
|
||||
847C4C9C1FF44F790090D517 /* FeedListSplitViewController.swift in Sources */,
|
||||
847C4C9C1FF44F790090D517 /* FeedListSplitViewDelegate.swift in Sources */,
|
||||
849A976C1ED9EBC8007D329B /* TimelineTableRowView.swift in Sources */,
|
||||
849A977B1ED9EC04007D329B /* UnreadIndicatorView.swift in Sources */,
|
||||
84B99C9D1FAE83C600ECDEDB /* DeleteFromSidebarCommand.swift in Sources */,
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
//
|
||||
// FeedListSplitViewController.swift
|
||||
// Evergreen
|
||||
//
|
||||
// Created by Brent Simmons on 12/27/17.
|
||||
// Copyright © 2017 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import DB5
|
||||
|
||||
final class FeedListSplitViewController: NSSplitViewController {
|
||||
|
||||
@IBOutlet var sidebarSplitViewItem: NSSplitViewItem!
|
||||
@IBOutlet var timelineSplitViewItem: NSSplitViewItem!
|
||||
|
||||
private var sidebarView: NSView {
|
||||
return sidebarSplitViewItem.viewController.view
|
||||
}
|
||||
|
||||
private var timelineView: NSView {
|
||||
return timelineSplitViewItem.viewController.view
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
||||
super.viewDidLoad()
|
||||
|
||||
sidebarView.translatesAutoresizingMaskIntoConstraints = false
|
||||
timelineView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
sidebarSplitViewItem.preferredThicknessFraction = NSSplitViewItem.unspecifiedDimension
|
||||
sidebarSplitViewItem.canCollapse = false
|
||||
timelineSplitViewItem.preferredThicknessFraction = NSSplitViewItem.unspecifiedDimension
|
||||
timelineSplitViewItem.canCollapse = false
|
||||
|
||||
let sidebarMinimumThickness = appDelegate.currentTheme.float(forKey: "FeedDirectory.sidebar.minimumThickness")
|
||||
sidebarSplitViewItem.minimumThickness = sidebarMinimumThickness
|
||||
let sidebarMaximumThickness = appDelegate.currentTheme.float(forKey: "FeedDirectory.sidebar.maximumThickness")
|
||||
timelineSplitViewItem.maximumThickness = sidebarMaximumThickness
|
||||
|
||||
let sidebarWidth = appDelegate.currentTheme.float(forKey: "FeedDirectory.sidebar.initialWidth")
|
||||
splitView.setPosition(sidebarWidth, ofDividerAt: 0)
|
||||
|
||||
let constraints = timelineView.constraintsAffectingLayout(for: .horizontal)
|
||||
print(constraints)
|
||||
}
|
||||
|
||||
// MARK: - NSSplitViewDelegate
|
||||
|
||||
override func splitView(_ splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool {
|
||||
|
||||
super.splitView(splitView, canCollapseSubview: subview)
|
||||
let constraints = timelineView.constraintsAffectingLayout(for: .horizontal)
|
||||
print(constraints)
|
||||
return false
|
||||
}
|
||||
|
||||
override func splitView(_ splitView: NSSplitView, shouldCollapseSubview subview: NSView, forDoubleClickOnDividerAt dividerIndex: Int) -> Bool {
|
||||
|
||||
super.splitView(splitView, shouldCollapseSubview: view, forDoubleClickOnDividerAt: dividerIndex)
|
||||
let constraints = timelineView.constraintsAffectingLayout(for: .horizontal)
|
||||
print(constraints)
|
||||
return false
|
||||
}
|
||||
|
||||
override func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool {
|
||||
|
||||
super.splitView(splitView, shouldHideDividerAt: dividerIndex)
|
||||
let constraints = timelineView.constraintsAffectingLayout(for: .horizontal)
|
||||
print(constraints)
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
//
|
||||
// FeedListSplitViewDelegate.swift
|
||||
// Evergreen
|
||||
//
|
||||
// Created by Brent Simmons on 12/27/17.
|
||||
// Copyright © 2017 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import DB5
|
||||
import RSCore
|
||||
|
||||
final class FeedListSplitViewDelegate: NSObject, NSSplitViewDelegate {
|
||||
|
||||
@IBOutlet weak var sidebarView: NSView?
|
||||
@IBOutlet weak var timelineView: NSView?
|
||||
@IBOutlet weak var splitView: NSSplitView?
|
||||
let sidebarMinimumThickness: CGFloat
|
||||
let sidebarMaximumThickness: CGFloat
|
||||
let sidebarBestWidth: CGFloat
|
||||
let timelineMinimumThickness: CGFloat
|
||||
|
||||
override init() {
|
||||
|
||||
sidebarMinimumThickness = appDelegate.currentTheme.float(forKey: "FeedDirectory.sidebar.minimumThickness")
|
||||
sidebarMaximumThickness = appDelegate.currentTheme.float(forKey: "FeedDirectory.sidebar.maximumThickness")
|
||||
sidebarBestWidth = appDelegate.currentTheme.float(forKey: "FeedDirectory.sidebar.bestWidth")
|
||||
timelineMinimumThickness = appDelegate.currentTheme.float(forKey: "FeedDirectory.timeline.minimumThickness")
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
// override func awakeFromNib() {
|
||||
//
|
||||
// let highestAllowedPriority = NSLayoutConstraint.Priority(rawValue: NSLayoutConstraint.Priority.dragThatCannotResizeWindow.rawValue - 1)
|
||||
// splitView?.setHoldingPriority(highestAllowedPriority, forSubviewAt: 0)
|
||||
// splitView?.setHoldingPriority(.defaultLow, forSubviewAt: 1)
|
||||
// }
|
||||
|
||||
// MARK: - NSSplitViewDelegate
|
||||
|
||||
func splitView(_ splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func splitView(_ splitView: NSSplitView, shouldCollapseSubview subview: NSView, forDoubleClickOnDividerAt dividerIndex: Int) -> Bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
|
||||
|
||||
return sidebarMinimumThickness
|
||||
}
|
||||
|
||||
func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
|
||||
|
||||
return sidebarMaximumThickness
|
||||
}
|
||||
|
||||
func splitView(_ splitView: NSSplitView, constrainSplitPosition proposedPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
|
||||
|
||||
if proposedPosition < sidebarMinimumThickness {
|
||||
return sidebarMinimumThickness
|
||||
}
|
||||
|
||||
// If proposedPosition makes timeline too small, then adjust.
|
||||
let proposedTimelineWidth = proposedTimelineThickness(splitView, proposedPosition)
|
||||
if proposedTimelineWidth < timelineMinimumThickness {
|
||||
return min(sidebarMaximumThickness, proposedPosition - (timelineMinimumThickness - proposedTimelineWidth))
|
||||
}
|
||||
|
||||
if proposedPosition > sidebarMaximumThickness {
|
||||
return sidebarMaximumThickness
|
||||
}
|
||||
|
||||
return proposedPosition
|
||||
}
|
||||
|
||||
// func splitView(_ splitView: NSSplitView, shouldAdjustSizeOfSubview view: NSView) -> Bool {
|
||||
//
|
||||
// guard let sidebarView = sidebarView, let timelineView = timelineView else {
|
||||
// assertionFailure("Expected sidebarView and timelineView as non-nil, but at least one is nil.")
|
||||
// return true
|
||||
// }
|
||||
//
|
||||
// if view === sidebarView {
|
||||
// if timelineView.frame.width <= timelineMinimumThickness {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// return true
|
||||
// }
|
||||
|
||||
func splitView(_ splitView: NSSplitView, resizeSubviewsWithOldSize oldSize: NSSize) {
|
||||
|
||||
guard let sidebarView = sidebarView, let timelineView = timelineView else {
|
||||
assertionFailure("Expected sidebarView and timelineView as non-nil, but at least one is nil.")
|
||||
return
|
||||
}
|
||||
|
||||
let splitViewFrame = splitView.frame
|
||||
let splitViewWidth = splitViewFrame.width
|
||||
let dividerThickness = splitView.dividerThickness
|
||||
|
||||
var sidebarViewFrame = sidebarView.frame
|
||||
sidebarViewFrame.size.height = splitViewFrame.height
|
||||
var timelineViewFrame = timelineView.frame
|
||||
timelineViewFrame.size.height = splitViewFrame.height
|
||||
|
||||
sidebarViewFrame.size.width = max(sidebarViewFrame.width, sidebarMinimumThickness)
|
||||
sidebarViewFrame.size.width = ceil(min(sidebarViewFrame.width, sidebarMaximumThickness))
|
||||
timelineViewFrame.size.width = floor(min(timelineViewFrame.width, timelineMinimumThickness))
|
||||
|
||||
let totalProposedWidth = sidebarViewFrame.width + dividerThickness + timelineViewFrame.width
|
||||
let difference = splitViewWidth - totalProposedWidth
|
||||
if difference < 0 {
|
||||
timelineViewFrame.size.width += difference
|
||||
if timelineViewFrame.width < 0 {
|
||||
timelineViewFrame.size.width = 0
|
||||
sidebarViewFrame.size.width += difference
|
||||
}
|
||||
}
|
||||
|
||||
sidebarView.rs_setFrameIfNotEqual(sidebarViewFrame)
|
||||
timelineView.rs_setFrameIfNotEqual(timelineViewFrame)
|
||||
}
|
||||
}
|
||||
|
||||
private extension FeedListSplitViewDelegate {
|
||||
|
||||
func proposedTimelineThickness(_ splitView: NSSplitView, _ proposedPosition: CGFloat) -> CGFloat {
|
||||
|
||||
return (splitView.frame.width - splitView.dividerThickness) - proposedPosition
|
||||
}
|
||||
|
||||
}
|
|
@ -25,11 +25,9 @@ final class FeedListViewController: NSViewController {
|
|||
|
||||
sidebarCellAppearance = SidebarCellAppearance(theme: appDelegate.currentTheme, fontSize: AppDefaults.shared.sidebarFontSize)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
||||
outlineView.needsLayout = true
|
||||
}
|
||||
|
||||
override func viewWillLayout() {
|
||||
super.viewWillLayout()
|
||||
}
|
||||
// MARK: - Notifications
|
||||
|
||||
@objc func faviconDidBecomeAvailable(_ note: Notification) {
|
||||
|
|
|
@ -41,18 +41,12 @@
|
|||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</searchFieldCell>
|
||||
</searchField>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="wey-fS-dNY">
|
||||
<rect key="frame" x="0.0" y="-2" width="128" height="5"/>
|
||||
</box>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="48" id="62f-Ja-njN"/>
|
||||
<constraint firstItem="wey-fS-dNY" firstAttribute="leading" secondItem="Sxr-eg-boM" secondAttribute="leading" id="8Ls-P9-pxs"/>
|
||||
<constraint firstItem="791-YX-E38" firstAttribute="centerY" secondItem="Sxr-eg-boM" secondAttribute="centerY" id="Z9W-jw-zkI"/>
|
||||
<constraint firstItem="791-YX-E38" firstAttribute="leading" secondItem="Sxr-eg-boM" secondAttribute="leading" constant="20" symbolic="YES" id="d50-xe-TO4"/>
|
||||
<constraint firstAttribute="trailing" secondItem="791-YX-E38" secondAttribute="trailing" constant="20" symbolic="YES" id="i0h-PY-4SC"/>
|
||||
<constraint firstAttribute="bottom" secondItem="wey-fS-dNY" secondAttribute="bottom" id="plH-tG-c0g"/>
|
||||
<constraint firstAttribute="trailing" secondItem="wey-fS-dNY" secondAttribute="trailing" id="xao-N6-CQq"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="OF2-9S-uq1">
|
||||
|
@ -160,9 +154,12 @@
|
|||
</customView>
|
||||
</subviews>
|
||||
<holdingPriorities>
|
||||
<real value="260"/>
|
||||
<real value="250"/>
|
||||
<real value="489"/>
|
||||
<real value="251"/>
|
||||
</holdingPriorities>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="foD-R8-nCX" id="8ds-kY-h3r"/>
|
||||
</connections>
|
||||
</splitView>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="6se-0m-JxY" customClass="FeedListControlsView" customModule="Evergreen" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="32"/>
|
||||
|
@ -214,6 +211,13 @@
|
|||
<outlet property="view" destination="OF2-9S-uq1" id="yfP-zX-T6z"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<customObject id="foD-R8-nCX" customClass="FeedListSplitViewDelegate" customModule="Evergreen" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="sidebarView" destination="fSs-xC-S8k" id="EPm-FO-BI3"/>
|
||||
<outlet property="splitView" destination="LmW-op-ndf" id="X2z-RD-rkV"/>
|
||||
<outlet property="timelineView" destination="asI-cc-kYO" id="sw2-Qf-oMo"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSActionTemplate" width="14" height="14"/>
|
||||
|
|
|
@ -133,12 +133,17 @@
|
|||
<dict>
|
||||
<key>sidebar</key>
|
||||
<dict>
|
||||
<key>initialWidth</key>
|
||||
<key>bestWidth</key>
|
||||
<integer>285</integer>
|
||||
<key>minimumThickness</key>
|
||||
<string>220</string>
|
||||
<integer>240</integer>
|
||||
<key>maximumThickness</key>
|
||||
<string>512</string>
|
||||
<integer>512</integer>
|
||||
</dict>
|
||||
<key>timeline</key>
|
||||
<dict>
|
||||
<key>minimumThickness</key>
|
||||
<integer>240</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
|
|
Loading…
Reference in New Issue