Fix #475: Add status bar to EditView hiearchy

This makes the status bar a part of the edit view hierachy, causing it to no longer block the edit view.
This commit is contained in:
Dung Le 2019-12-01 17:01:34 +07:00
parent 89b87397a8
commit 8a8a1e0d8b
4 changed files with 58 additions and 41 deletions

View File

@ -82,7 +82,9 @@ class EditViewController: NSViewController, EditViewDataSource, FindDelegate, Sc
@IBOutlet weak var editContainerView: EditContainerView!
@IBOutlet var editView: EditView!
@IBOutlet weak var shadowView: ShadowView!
@IBOutlet weak var statusBar: StatusBar!
@IBOutlet weak var statusBarHeight: NSLayoutConstraint!
@IBOutlet weak var editViewHeight: NSLayoutConstraint!
@IBOutlet weak var editViewWidth: NSLayoutConstraint!
@ -227,8 +229,6 @@ class EditViewController: NSViewController, EditViewDataSource, FindDelegate, Sc
var hoverEvent: NSEvent?
let statusBar = StatusBar(frame: .zero)
// Popover that manages hover views.
lazy var infoPopover: NSPopover = {
let popover = NSPopover()
@ -245,6 +245,7 @@ class EditViewController: NSViewController, EditViewDataSource, FindDelegate, Sc
override func viewDidLoad() {
super.viewDidLoad()
statusBar.delegate = self
shadowView.wantsLayer = true
editView.dataSource = self
editContainerView.contextMenu = contextMenu
@ -272,14 +273,7 @@ class EditViewController: NSViewController, EditViewDataSource, FindDelegate, Sc
func setupStatusBar() {
statusBar.hasUnifiedTitlebar = unifiedTitlebar
self.view.addSubview(statusBar)
NSLayoutConstraint.activate([
statusBar.heightAnchor.constraint(equalToConstant: statusBar.statusBarHeight),
statusBar.leadingAnchor.constraint(equalTo: editView.leadingAnchor),
statusBar.trailingAnchor.constraint(equalTo: editView.trailingAnchor),
statusBar.bottomAnchor.constraint(equalTo: editView.bottomAnchor)
])
hideStatusBar()
}
func updateGutterWidth() {
@ -494,10 +488,12 @@ class EditViewController: NSViewController, EditViewDataSource, FindDelegate, Sc
override func uppercaseWord(_ sender: Any?) {
xiView.uppercase()
self.showStatusBar()
}
override func lowercaseWord(_ sender: Any?) {
xiView.lowercase()
self.hideStatusBar()
}
override func capitalizeWord(_ sender: Any?) {

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -61,27 +61,36 @@
</constraints>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="hEG-a6-BYd">
<rect key="frame" x="0.0" y="255" width="465" height="15"/>
<rect key="frame" x="0.0" y="231" width="465" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="O02-Lc-5gg" customClass="MarkerBar" customModule="XiEditor" customModuleProvider="target">
<rect key="frame" x="465" y="0.0" width="15" height="255"/>
<rect key="frame" x="465" y="0.0" width="15" height="231"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Tjs-fk-d3S" customClass="StatusBar" customModule="XiEditor" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="480" height="0.0"/>
<constraints>
<constraint firstAttribute="height" id="DO3-dq-Ibg"/>
</constraints>
</customView>
</subviews>
<constraints>
<constraint firstItem="x8W-KD-KOP" firstAttribute="leading" secondItem="q1P-kd-995" secondAttribute="leading" id="0m0-0O-Llk"/>
<constraint firstItem="x8W-KD-KOP" firstAttribute="top" secondItem="q1P-kd-995" secondAttribute="top" id="4lN-9b-wSx"/>
<constraint firstAttribute="trailing" secondItem="q1P-kd-995" secondAttribute="trailing" id="5IG-vx-2rb"/>
<constraint firstItem="Tjs-fk-d3S" firstAttribute="leading" secondItem="3ye-5b-Ab2" secondAttribute="leading" id="Cav-5o-0ue"/>
<constraint firstAttribute="bottom" secondItem="Tjs-fk-d3S" secondAttribute="bottom" id="F95-nZ-7H5"/>
<constraint firstItem="Qwv-ci-fVA" firstAttribute="leading" secondItem="q1P-kd-995" secondAttribute="leading" id="Pyq-kX-0wa"/>
<constraint firstItem="x8W-KD-KOP" firstAttribute="bottom" secondItem="q1P-kd-995" secondAttribute="bottom" id="Qak-2E-Fy6"/>
<constraint firstItem="Qwv-ci-fVA" firstAttribute="top" secondItem="q1P-kd-995" secondAttribute="top" id="Qwh-xz-kUZ"/>
<constraint firstItem="Qwv-ci-fVA" firstAttribute="bottom" secondItem="q1P-kd-995" secondAttribute="bottom" id="Sdy-8S-2NP"/>
<constraint firstItem="Tjs-fk-d3S" firstAttribute="top" secondItem="q1P-kd-995" secondAttribute="bottom" id="ZnH-DY-sje"/>
<constraint firstItem="x8W-KD-KOP" firstAttribute="trailing" secondItem="q1P-kd-995" secondAttribute="trailing" id="dL4-Ba-yMB"/>
<constraint firstItem="q1P-kd-995" firstAttribute="top" secondItem="3ye-5b-Ab2" secondAttribute="top" id="gHb-9s-5Ki"/>
<constraint firstItem="q1P-kd-995" firstAttribute="top" secondItem="3ye-5b-Ab2" secondAttribute="top" id="gWG-JW-SJf"/>
<constraint firstItem="q1P-kd-995" firstAttribute="leading" secondItem="3ye-5b-Ab2" secondAttribute="leading" id="kaS-IB-LV9"/>
<constraint firstAttribute="bottom" secondItem="q1P-kd-995" secondAttribute="bottom" id="ngA-1s-M67"/>
<constraint firstAttribute="trailing" secondItem="Tjs-fk-d3S" secondAttribute="trailing" id="kg5-PT-wI0"/>
<constraint firstItem="Qwv-ci-fVA" firstAttribute="trailing" secondItem="q1P-kd-995" secondAttribute="trailing" id="w93-aW-WKu"/>
</constraints>
</view>
@ -92,6 +101,8 @@
<outlet property="editViewWidth" destination="1Gd-zC-FVY" id="DtT-d0-KdH"/>
<outlet property="scrollView" destination="Qwv-ci-fVA" id="4cE-10-pSP"/>
<outlet property="shadowView" destination="x8W-KD-KOP" id="mme-7Z-x1H"/>
<outlet property="statusBar" destination="Tjs-fk-d3S" id="MX5-p8-dzb"/>
<outlet property="statusBarHeight" destination="DO3-dq-Ibg" id="JwM-iA-km2"/>
<segue destination="9Ak-VM-8lJ" kind="modal" identifier="UserInputSegue" id="GqW-PV-ZCy"/>
</connections>
</viewController>
@ -121,7 +132,7 @@ DQ
</connections>
</button>
<textField hidden="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Di9-5Q-3Ia">
<rect key="frame" x="20" y="20" width="275" height="22"/>
<rect key="frame" x="20" y="20" width="275" height="21"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="zlO-6u-liO">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -142,7 +153,7 @@ Gw
</connections>
</button>
<comboBox hidden="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AHD-SX-Tuj">
<rect key="frame" x="21" y="16" width="277" height="26"/>
<rect key="frame" x="21" y="16" width="277" height="25"/>
<comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" completes="NO" numberOfVisibleItems="5" id="nnP-RF-Vev">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -303,7 +314,7 @@ Gw
</subviews>
<visibilityPriorities>
<integer value="1000"/>
<real value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
@ -386,7 +397,7 @@ Gw
<rect key="frame" x="4" y="-1" width="32" height="19"/>
<buttonCell key="cell" type="roundRect" title="+" bezelStyle="roundedRect" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="8uK-5I-cZg">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system" size="16"/>
<font key="font" metaFont="label" size="16"/>
</buttonCell>
<connections>
<action selector="addSearchField:" target="uoL-yg-E2H" id="0zi-0Z-ZCs"/>
@ -396,7 +407,7 @@ Gw
<rect key="frame" x="38" y="-1" width="31" height="19"/>
<buttonCell key="cell" type="roundRect" title="-" bezelStyle="roundedRect" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="0dQ-No-w5x">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system" size="16"/>
<font key="font" metaFont="label" size="16"/>
</buttonCell>
<connections>
<action selector="removeSearchField:" target="uoL-yg-E2H" id="9Wq-QC-w07"/>

View File

@ -15,6 +15,11 @@
import Foundation
import Cocoa
protocol StatusBarDelegate: class {
func showStatusBar()
func hideStatusBar()
}
enum StatusItemAlignment: String {
case left = "left"
case right = "right"
@ -52,6 +57,8 @@ class StatusItem: NSTextField {
}
class StatusBar: NSView {
weak var delegate: StatusBarDelegate?
var currentItems = [String : StatusItem]()
var hiddenItems: [StatusItem] {
@ -80,8 +87,9 @@ class StatusBar: NSView {
var backgroundColor: NSColor = NSColor.windowBackgroundColor
var itemTextColor: NSColor = NSColor.labelColor
var borderColor: NSColor = NSColor.systemGray
static let statusBarHeight: CGFloat = 20
let statusBarPadding: CGFloat = 10
let statusBarHeight: CGFloat = 24
let firstItemMargin: CGFloat = 5
// Difference (in points) to compensate for when status bar is resized
@ -96,21 +104,12 @@ class StatusBar: NSView {
}
override var isFlipped: Bool {
return true;
return true
}
override init(frame frameRect: NSRect) {
super.init(frame: .zero)
self.translatesAutoresizingMaskIntoConstraints = false
self.isHidden = true
updateStatusBarVisibility()
required init?(coder: NSCoder) {
super.init(coder: coder)
}
@available(*, unavailable)
required init?(coder decoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// Adds a status bar item.
func addStatusItem(_ item: StatusItem) {
if let existingItem = currentItems[item.key] {
@ -219,14 +218,16 @@ class StatusBar: NSView {
func updateStatusBarVisibility() {
if !currentItems.isEmpty {
self.hideTimer?.invalidate()
self.isHidden = false
delegate?.showStatusBar()
} else if !self.isHidden {
// Wait a moment before hiding the bar to avoid blinking in the case
// that a single item is added and removed repeatedly in rapid succession.
if #available(OSX 10.12, *) {
hideTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in self.isHidden = true }
hideTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in
self.delegate?.hideStatusBar()
}
} else {
self.isHidden = true
delegate?.hideStatusBar()
}
}
}
@ -285,5 +286,14 @@ class StatusBar: NSView {
path.line(to: CGPoint(x: dirtyRect.maxX, y: dirtyRect.minY))
path.stroke()
}
}
extension EditViewController: StatusBarDelegate {
func showStatusBar() {
statusBarHeight.constant = StatusBar.statusBarHeight
}
func hideStatusBar() {
statusBarHeight.constant = 0
}
}

@ -1 +1 @@
Subproject commit a58509934eeab8dc10a0ccf8b68b6d10c78a856c
Subproject commit a4c82f26056bebd05627565beb0089e7ca14e1d1