Create SidebarStatusBarView.

This commit is contained in:
Brent Simmons 2017-12-16 16:36:35 -08:00
parent 59f06ea764
commit f133b539ca
5 changed files with 196 additions and 216 deletions

View File

@ -52,7 +52,7 @@
849A977B1ED9EC04007D329B /* UnreadIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97751ED9EC04007D329B /* UnreadIndicatorView.swift */; };
849A977F1ED9EC42007D329B /* ArticleRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A977D1ED9EC42007D329B /* ArticleRenderer.swift */; };
849A97801ED9EC42007D329B /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A977E1ED9EC42007D329B /* DetailViewController.swift */; };
849A97831ED9EC63007D329B /* StatusBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97821ED9EC63007D329B /* StatusBarView.swift */; };
849A97831ED9EC63007D329B /* SidebarStatusBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97821ED9EC63007D329B /* SidebarStatusBarView.swift */; };
849A97851ED9ECCD007D329B /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97841ED9ECCD007D329B /* PreferencesWindowController.swift */; };
849A97891ED9ECEF007D329B /* ArticleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97871ED9ECEF007D329B /* ArticleStyle.swift */; };
849A978A1ED9ECEF007D329B /* ArticleStylesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97881ED9ECEF007D329B /* ArticleStylesManager.swift */; };
@ -451,7 +451,7 @@
849A97751ED9EC04007D329B /* UnreadIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnreadIndicatorView.swift; sourceTree = "<group>"; };
849A977D1ED9EC42007D329B /* ArticleRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArticleRenderer.swift; sourceTree = "<group>"; };
849A977E1ED9EC42007D329B /* DetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = "<group>"; };
849A97821ED9EC63007D329B /* StatusBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarView.swift; sourceTree = "<group>"; };
849A97821ED9EC63007D329B /* SidebarStatusBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SidebarStatusBarView.swift; sourceTree = "<group>"; };
849A97841ED9ECCD007D329B /* PreferencesWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PreferencesWindowController.swift; path = Evergreen/Preferences/PreferencesWindowController.swift; sourceTree = "<group>"; };
849A97871ED9ECEF007D329B /* ArticleStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArticleStyle.swift; sourceTree = "<group>"; };
849A97881ED9ECEF007D329B /* ArticleStylesManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArticleStylesManager.swift; sourceTree = "<group>"; };
@ -682,6 +682,7 @@
849A97611ED9EB96007D329B /* SidebarTreeControllerDelegate.swift */,
849A97631ED9EB96007D329B /* UnreadCountView.swift */,
845F52EC1FB2B9FC00C10BF0 /* FeedPasteboardWriter.swift */,
849A97821ED9EC63007D329B /* SidebarStatusBarView.swift */,
845A29251FC928C7007B49E3 /* Cell */,
);
path = Sidebar;
@ -727,7 +728,6 @@
849A97811ED9EC63007D329B /* Status Bar */ = {
isa = PBXGroup;
children = (
849A97821ED9EC63007D329B /* StatusBarView.swift */,
);
name = "Status Bar";
path = StatusBar;
@ -1391,7 +1391,7 @@
848F6AE51FC29CFB002D422E /* FaviconDownloader.swift in Sources */,
849A97981ED9EFAA007D329B /* Node-Extensions.swift in Sources */,
849A97531ED9EAC0007D329B /* AddFeedController.swift in Sources */,
849A97831ED9EC63007D329B /* StatusBarView.swift in Sources */,
849A97831ED9EC63007D329B /* SidebarStatusBarView.swift in Sources */,
84F2D5381FC22FCC00998D64 /* TodayFeedDelegate.swift in Sources */,
845213231FCA5B11003B6E93 /* ImageDownloader.swift in Sources */,
849A97431ED9EAA9007D329B /* AddFolderWindowController.swift in Sources */,

View File

@ -317,13 +317,13 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView appearanceType="aqua" borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="cJj-Wv-9ep">
<rect key="frame" x="0.0" y="0.0" width="166" height="300"/>
<rect key="frame" x="0.0" y="28" width="166" height="272"/>
<clipView key="contentView" drawsBackground="NO" id="2eU-Wz-F9g">
<rect key="frame" x="0.0" y="0.0" width="166" height="300"/>
<rect key="frame" x="0.0" y="0.0" width="166" height="272"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView appearanceType="aqua" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" rowHeight="24" rowSizeStyle="medium" viewBased="YES" floatsGroupRows="NO" indentationPerLevel="16" outlineTableColumn="ih9-mJ-EA7" id="cnV-kg-Dn2" customClass="SidebarOutlineView" customModule="Evergreen" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="167" height="300"/>
<rect key="frame" x="0.0" y="0.0" width="167" height="272"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -407,10 +407,63 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="HZs-Zf-G8s" customClass="SidebarStatusBarView" customModule="Evergreen" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="166" height="28"/>
<subviews>
<popUpButton translatesAutoresizingMaskIntoConstraints="NO" id="gZE-LB-FdW">
<rect key="frame" x="8" y="4" width="40" height="19"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="7UB-w9-Vc2"/>
</constraints>
<popUpButtonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" inset="2" pullsDown="YES" selectedItem="8Fv-OJ-wij" id="SM6-uZ-3Ag">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="BmH-U4-6EU">
<items>
<menuItem state="on" image="action" hidden="YES" id="8Fv-OJ-wij"/>
<menuItem title="Item 2" id="8qw-qv-HEP"/>
<menuItem title="Item 3" id="V2t-4f-IAM"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<progressIndicator hidden="YES" wantsLayer="YES" maxValue="100" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="y9c-Xf-2fS">
<rect key="frame" x="56" y="3" width="40" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="1Yw-ER-8pT"/>
</constraints>
</progressIndicator>
<textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="iyL-pW-cT6">
<rect key="frame" x="98" y="6" width="62" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="dVE-XG-mlU">
<font key="font" metaFont="system"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="y9c-Xf-2fS" firstAttribute="centerY" secondItem="HZs-Zf-G8s" secondAttribute="centerY" constant="1" id="5Du-sw-hBK"/>
<constraint firstItem="iyL-pW-cT6" firstAttribute="centerY" secondItem="HZs-Zf-G8s" secondAttribute="centerY" id="Hht-GZ-3Ls"/>
<constraint firstItem="iyL-pW-cT6" firstAttribute="leading" secondItem="y9c-Xf-2fS" secondAttribute="trailing" constant="4" id="TAM-VN-Syu"/>
<constraint firstItem="y9c-Xf-2fS" firstAttribute="leading" secondItem="gZE-LB-FdW" secondAttribute="trailing" constant="8" id="UZa-wq-vjU"/>
<constraint firstItem="gZE-LB-FdW" firstAttribute="leading" secondItem="HZs-Zf-G8s" secondAttribute="leading" constant="8" id="Uy1-2v-MRU"/>
<constraint firstItem="gZE-LB-FdW" firstAttribute="centerY" secondItem="HZs-Zf-G8s" secondAttribute="centerY" id="cwG-1N-9Ou"/>
<constraint firstAttribute="height" constant="28" id="xOq-XX-qcd"/>
</constraints>
<connections>
<outlet property="progressIndicator" destination="y9c-Xf-2fS" id="gaf-6e-siu"/>
<outlet property="progressLabel" destination="iyL-pW-cT6" id="Zpv-44-cfX"/>
</connections>
</customView>
</subviews>
<constraints>
<constraint firstItem="HZs-Zf-G8s" firstAttribute="top" secondItem="cJj-Wv-9ep" secondAttribute="bottom" id="0Zg-oW-o7U"/>
<constraint firstItem="cJj-Wv-9ep" firstAttribute="leading" secondItem="bJZ-bH-vgc" secondAttribute="leading" id="5Rs-9M-TKq"/>
<constraint firstAttribute="bottom" secondItem="cJj-Wv-9ep" secondAttribute="bottom" id="sZX-9Y-svy"/>
<constraint firstAttribute="trailing" secondItem="iyL-pW-cT6" secondAttribute="trailing" constant="8" id="Mnm-9S-Qpm"/>
<constraint firstAttribute="bottom" secondItem="HZs-Zf-G8s" secondAttribute="bottom" id="UN9-Wa-uxb"/>
<constraint firstAttribute="trailing" secondItem="HZs-Zf-G8s" secondAttribute="trailing" id="iNE-nb-QEB"/>
<constraint firstItem="HZs-Zf-G8s" firstAttribute="leading" secondItem="bJZ-bH-vgc" secondAttribute="leading" id="tPp-xB-CgB"/>
<constraint firstItem="cJj-Wv-9ep" firstAttribute="top" secondItem="bJZ-bH-vgc" secondAttribute="top" id="vAT-Wo-8fl"/>
<constraint firstAttribute="trailing" secondItem="cJj-Wv-9ep" secondAttribute="trailing" id="vo7-3F-Fd3"/>
</constraints>

View File

@ -95,19 +95,19 @@ final class DetailStatusBarView: NSView {
// MARK: Drawing
private let lineColor = NSColor(calibratedWhite: 0.65, alpha: 1.0)
private let lineColor = NSColor(calibratedWhite: 0.85, alpha: 1.0)
override func draw(_ dirtyRect: NSRect) {
backgroundColor.set()
dirtyRect.fill()
// let path = NSBezierPath()
// path.lineWidth = 1.0
// path.move(to: NSPoint(x: NSMinX(bounds), y: NSMinY(bounds) + 0.5))
// path.line(to: NSPoint(x: NSMaxX(bounds), y: NSMinY(bounds) + 0.5))
// lineColor.set()
// path.stroke()
let path = NSBezierPath()
path.lineWidth = 1.0
path.move(to: NSPoint(x: NSMinX(bounds), y: NSMinY(bounds) + 0.5))
path.line(to: NSPoint(x: NSMaxX(bounds), y: NSMinY(bounds) + 0.5))
lineColor.set()
path.stroke()
}
}

View File

@ -0,0 +1,128 @@
//
// SidebarStatusBarView.swift
// Evergreen
//
// Created by Brent Simmons on 9/17/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Cocoa
import RSCore
import Data
import RSWeb
import Account
final class SidebarStatusBarView: NSView {
@IBOutlet var progressIndicator: NSProgressIndicator!
@IBOutlet var progressLabel: NSTextField!
private var isAnimatingProgress = false {
didSet {
progressIndicator.isHidden = !isAnimatingProgress
progressLabel.isHidden = !isAnimatingProgress
}
}
override var isFlipped: Bool {
get {
return true
}
}
override func awakeFromNib() {
progressIndicator.isHidden = true
progressLabel.isHidden = true
let progressLabelFontSize = progressLabel.font?.pointSize ?? 13.0
progressLabel.font = NSFont.monospacedDigitSystemFont(ofSize: progressLabelFontSize, weight: NSFont.Weight.regular)
progressLabel.stringValue = ""
NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil)
}
// MARK: Notifications
@objc dynamic func progressDidChange(_ notification: Notification) {
let progress = AccountManager.shared.combinedRefreshProgress
updateProgressIndicator(progress)
updateProgressLabel(progress)
}
// MARK: Drawing
// private let lineColor = NSColor(calibratedWhite: 0.57, alpha: 1.0)
//
// override func draw(_ dirtyRect: NSRect) {
//
// let path = NSBezierPath()
// path.lineWidth = 1.0
// path.move(to: NSPoint(x: NSMinX(bounds), y: NSMinY(bounds) + 0.5))
// path.line(to: NSPoint(x: NSMaxX(bounds), y: NSMinY(bounds) + 0.5))
// lineColor.set()
// path.stroke()
// }
}
private extension SidebarStatusBarView {
// MARK: Progress
func stopProgressIfNeeded() {
if !isAnimatingProgress {
return
}
progressIndicator.stopAnimation(self)
isAnimatingProgress = false
progressIndicator.needsDisplay = true
}
func startProgressIfNeeded() {
if isAnimatingProgress {
return
}
isAnimatingProgress = true
progressIndicator.startAnimation(self)
}
func updateProgressIndicator(_ progress: CombinedRefreshProgress) {
if progress.isComplete {
stopProgressIfNeeded()
return
}
startProgressIfNeeded()
let maxValue = Double(progress.numberOfTasks)
if progressIndicator.maxValue != maxValue {
progressIndicator.maxValue = maxValue
}
let doubleValue = Double(progress.numberCompleted)
if progressIndicator.doubleValue != doubleValue {
progressIndicator.doubleValue = doubleValue
}
}
func updateProgressLabel(_ progress: CombinedRefreshProgress) {
if progress.isComplete {
progressLabel.stringValue = ""
return
}
let numberOfTasks = progress.numberOfTasks
let numberCompleted = progress.numberCompleted
let formatString = NSLocalizedString("%@ of %@", comment: "Status bar progress")
let s = NSString(format: formatString as NSString, NSNumber(value: numberCompleted), NSNumber(value: numberOfTasks))
progressLabel.stringValue = s as String
}
}

View File

@ -1,201 +0,0 @@
//
// StatusBarView.swift
// Evergreen
//
// Created by Brent Simmons on 9/17/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Cocoa
import RSCore
import Data
import RSWeb
import Account
final class StatusBarView: NSView {
@IBOutlet var progressIndicator: NSProgressIndicator!
@IBOutlet var progressLabel: NSTextField!
@IBOutlet var urlLabel: NSTextField!
private var isAnimatingProgress = false
private var article: Article? {
didSet {
updateURLLabel()
}
}
private var mouseoverLink: String? {
didSet {
updateURLLabel()
}
}
override var isFlipped: Bool {
get {
return true
}
}
override func awakeFromNib() {
let progressLabelFontSize = progressLabel.font?.pointSize ?? 13.0
progressLabel.font = NSFont.monospacedDigitSystemFont(ofSize: progressLabelFontSize, weight: NSFont.Weight.regular)
progressLabel.stringValue = ""
NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(timelineSelectionDidChange(_:)), name: .TimelineSelectionDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(mouseDidEnterLink(_:)), name: .MouseDidEnterLink, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(mouseDidExitLink(_:)), name: .MouseDidExitLink, object: nil)
}
// MARK: Notifications
@objc dynamic func progressDidChange(_ notification: Notification) {
let progress = AccountManager.shared.combinedRefreshProgress
updateProgressIndicator(progress)
updateProgressLabel(progress)
}
@objc dynamic func mouseDidEnterLink(_ notification: Notification) {
guard let appInfo = AppInfo.pullFromUserInfo(notification.userInfo) else {
return
}
guard let window = window, let notificationWindow = appInfo.view?.window, window === notificationWindow else {
return
}
guard let link = appInfo.url else {
return
}
mouseoverLink = link
}
@objc dynamic func mouseDidExitLink(_ notification: Notification) {
guard let appInfo = AppInfo.pullFromUserInfo(notification.userInfo) else {
return
}
guard let window = window, let notificationWindow = appInfo.view?.window, window === notificationWindow else {
return
}
mouseoverLink = nil
}
// MARK: Notifications
@objc dynamic func timelineSelectionDidChange(_ note: Notification) {
let timelineView = note.appInfo?.view
if timelineView?.window === self.window {
mouseoverLink = nil
article = note.appInfo?.article
}
}
// MARK: Drawing
private let lineColor = NSColor(calibratedWhite: 0.57, alpha: 1.0)
override func draw(_ dirtyRect: NSRect) {
let path = NSBezierPath()
path.lineWidth = 1.0
path.move(to: NSPoint(x: NSMinX(bounds), y: NSMinY(bounds) + 0.5))
path.line(to: NSPoint(x: NSMaxX(bounds), y: NSMinY(bounds) + 0.5))
lineColor.set()
path.stroke()
}
}
private extension StatusBarView {
// MARK: URL Label
func updateURLLabel() {
needsLayout = true
guard let article = article else {
setURLLabel("")
return
}
if let mouseoverLink = mouseoverLink, !mouseoverLink.isEmpty {
setURLLabel(mouseoverLink)
return
}
if let s = article.preferredLink {
setURLLabel(s)
}
else {
setURLLabel("")
}
}
func setURLLabel(_ link: String) {
urlLabel.stringValue = (link as NSString).rs_stringByStrippingHTTPOrHTTPSScheme()
}
// MARK: Progress
func stopProgressIfNeeded() {
if !isAnimatingProgress {
return
}
progressIndicator.stopAnimation(self)
isAnimatingProgress = false
progressIndicator.needsDisplay = true
}
func startProgressIfNeeded() {
if isAnimatingProgress {
return
}
isAnimatingProgress = true
progressIndicator.startAnimation(self)
}
func updateProgressIndicator(_ progress: CombinedRefreshProgress) {
if progress.isComplete {
stopProgressIfNeeded()
return
}
startProgressIfNeeded()
let maxValue = Double(progress.numberOfTasks)
if progressIndicator.maxValue != maxValue {
progressIndicator.maxValue = maxValue
}
let doubleValue = Double(progress.numberCompleted)
if progressIndicator.doubleValue != doubleValue {
progressIndicator.doubleValue = doubleValue
}
}
func updateProgressLabel(_ progress: CombinedRefreshProgress) {
if progress.isComplete {
progressLabel.stringValue = ""
return
}
let numberOfTasks = progress.numberOfTasks
let numberCompleted = progress.numberCompleted
let formatString = NSLocalizedString("%@ of %@", comment: "Status bar progress")
let s = NSString(format: formatString as NSString, NSNumber(value: numberCompleted), NSNumber(value: numberOfTasks))
progressLabel.stringValue = s as String
}
}