Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add segmented control style #6

Merged
merged 53 commits into from
Apr 3, 2019
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
4e6b164
make preference item icon optional
DivineDominion Nov 10, 2018
00386c2
add PreferencesStyle enum
DivineDominion Nov 10, 2018
ae725fc
change NSToolbarViewController style
DivineDominion Nov 10, 2018
d93446f
do not use icons in segmented controls
DivineDominion Nov 10, 2018
a8152a4
fix view controllers shrinking with every switch
DivineDominion Nov 10, 2018
0bfec58
replace force-casting with Preferenceable.viewController property
DivineDominion Nov 10, 2018
02d8acb
rename viewControllers parameter to preferences
DivineDominion Nov 10, 2018
9037a33
use custom PreferencesTabViewController and toolbar
DivineDominion Nov 10, 2018
2530d93
prevent transition to the same tab
DivineDominion Nov 10, 2018
f52226a
display window title for tabs toolbar
DivineDominion Nov 10, 2018
a8cb856
add tabs toolbar variant
DivineDominion Nov 10, 2018
c4d3873
fix subview layout not fitting the window
DivineDominion Nov 10, 2018
6f1dfe2
swallow user events during preference transitions
DivineDominion Nov 10, 2018
b3bdbaa
programmatically select initial toolbar tab item
DivineDominion Nov 10, 2018
fc8407b
disable unusable init(fromCoder:)
DivineDominion Nov 10, 2018
9c95112
add convenience window accessor
DivineDominion Nov 10, 2018
47d62a4
programmatically show a pane when showing the window
DivineDominion Nov 10, 2018
5537d80
lower macOS deployment target to 10.10
DivineDominion Nov 10, 2018
368a4bc
add preference identifier to make programmatic selections lightweight
DivineDominion Nov 10, 2018
4960082
make crossfading animation configurable
DivineDominion Nov 10, 2018
6793e2e
add NSToolbarItem representation for overflow menus
DivineDominion Dec 10, 2018
75f6d54
respect minimum window size during transitions
DivineDominion Dec 10, 2018
c348d09
fix outdated precondition message's method name
DivineDominion Dec 10, 2018
7d3840d
fix initial window size not respecting minSize
DivineDominion Dec 10, 2018
bc6df7a
make window animation work with Auto Layout views
DivineDominion Jan 10, 2019
bad2e6f
use live sizes of views
DivineDominion Jan 11, 2019
4f7f836
use fittingSize, ignoring IB view sizes
DivineDominion Jan 11, 2019
26d2789
use built-in transitioning and Auto Layout
DivineDominion Jan 11, 2019
01a0dcd
rename and put PausableWindow into its own file and add short doc string
DivineDominion Apr 2, 2019
6affa0b
fix SwiftLint warnings
DivineDominion Apr 2, 2019
93f1f85
shorten name of PreferencesSegmentedControlViewController
DivineDominion Apr 2, 2019
0cdad7c
use custom PreferenceIdentifier type instead of NSToolbarItem.Identifier
DivineDominion Apr 2, 2019
6196eaf
add convenience PreferenceIdentifier initializer
DivineDominion Apr 2, 2019
bf3ea85
rename Preferenceable to Preference
DivineDominion Apr 2, 2019
6563886
rename "crossfadeTransitions" to "animated"
DivineDominion Apr 2, 2019
95ce89f
rename showWindow to showPreference to convey it can be called anytime
DivineDominion Apr 2, 2019
e5f2a8b
provide fallback toolbar item image for easier segmented controls
DivineDominion Apr 2, 2019
71cbd6b
make PreferencesStyle changeable during runtime
DivineDominion Apr 2, 2019
43309fb
rename `Preference` to `PreferencePane` to reflect Apple HIG names
DivineDominion Apr 3, 2019
6c99459
rename PreferencesStyle.tabs to .toolbarItems
DivineDominion Apr 3, 2019
1e63cc0
rename the view controllers that implement style to match the 2 cases
DivineDominion Apr 3, 2019
9f16eda
restore example app's PreferencesStyle setting on relaunch
DivineDominion Apr 3, 2019
bef575e
disable PreferencesWindowController.init(window:)
DivineDominion Apr 3, 2019
133894e
make style changes private, relaunching sample app on style changes
DivineDominion Apr 3, 2019
224b4b4
rename showPreference(preferenceIdentifier:) to reflect the "pane" name
DivineDominion Apr 3, 2019
55c8f80
do not center toolbarItem preferences by default
DivineDominion Apr 3, 2019
c5945b2
keep window centered when switching segmented controls
DivineDominion Apr 3, 2019
da24b9d
fix AutoLayout issue when switching panes
DivineDominion Apr 3, 2019
7d0faa7
keep toolbar items centered on screen if they are centered in toolbar
DivineDominion Apr 3, 2019
b1504cd
rename "preferences" properties and parameters to "preferencePanes"
DivineDominion Apr 3, 2019
801a22e
properly pluralize showPreferences
DivineDominion Apr 3, 2019
e15ca47
adjust README for new API changes
DivineDominion Apr 3, 2019
08b75b3
rename showPreferences to show(preferencePane:) and add docstring
DivineDominion Apr 3, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion Example/AdvancedPreferenceViewController.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Cocoa
import Preferences

final class AdvancedPreferenceViewController: NSViewController, Preferenceable {
final class AdvancedPreferenceViewController: NSViewController, PreferencePane {
let preferencePaneIdentifier: PreferencePaneIdentifier = .advanced
let toolbarItemTitle = "Advanced"
let toolbarItemIcon = NSImage(named: NSImage.advancedName)!

Expand Down
19 changes: 12 additions & 7 deletions Example/AdvancedPreferenceViewController.xib
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14313.18"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
Expand All @@ -13,20 +13,25 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="c22-O7-iKe">
<rect key="frame" x="0.0" y="0.0" width="580" height="380"/>
<customView misplaced="YES" id="c22-O7-iKe">
<rect key="frame" x="0.0" y="0.0" width="485" height="380"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bc0-pc-Sw8">
<rect key="frame" x="244" y="178" width="92" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textField horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bc0-pc-Sw8">
<rect key="frame" x="198" y="178" width="89" height="24"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Advanced" id="2Ht-pt-tsZ">
<font key="font" metaFont="system" size="20"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="bc0-pc-Sw8" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="200" id="0an-7b-VLp"/>
<constraint firstAttribute="trailing" secondItem="bc0-pc-Sw8" secondAttribute="trailing" constant="200" id="4gj-WO-sBw"/>
<constraint firstItem="bc0-pc-Sw8" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" constant="178" id="YGc-8e-maw"/>
<constraint firstAttribute="bottom" secondItem="bc0-pc-Sw8" secondAttribute="bottom" constant="178" id="rkd-zg-yQS"/>
</constraints>
</customView>
</objects>
</document>
46 changes: 38 additions & 8 deletions Example/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,56 @@
import Cocoa
import Preferences

extension PreferencePaneIdentifier {
static let general = PreferencePaneIdentifier("general")
static let advanced = PreferencePaneIdentifier("advanced")
}

@NSApplicationMain
final class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet private var window: NSWindow!

let preferencesWindowController = PreferencesWindowController(
viewControllers: [
GeneralPreferenceViewController(),
AdvancedPreferenceViewController()
]
)
var preferencesStyle: PreferencesStyle {
get {
return PreferencesStyle.preferencesStyleFromUserDefaults()
}
set(newPreferencesStyle) {
newPreferencesStyle.storeInUserDefaults()
}
}

lazy var preferences: [PreferencePane] = [
GeneralPreferenceViewController(),
AdvancedPreferenceViewController()
]
lazy var preferencesWindowController = PreferencesWindowController(preferences: self.preferences, style: self.preferencesStyle, animated: true)

func applicationWillFinishLaunching(_ notification: Notification) {
window.orderOut(self)
}

func applicationDidFinishLaunching(_ notification: Notification) {
preferencesWindowController.showWindow()
preferencesWindowController.showPreference(preferencePane: .advanced)
}

@IBAction private func preferencesMenuItemActionHandler(_ sender: NSMenuItem) {
preferencesWindowController.showWindow()
preferencesWindowController.showPreference()
}

@IBAction private func switchStyle(_ sender: Any) {
self.preferencesStyle = (self.preferencesStyle == .segmentedControl)
? .toolbarItems
: .segmentedControl
relaunch()
}
}

private func relaunch() {
let appBundleIdentifier = Bundle.main.bundleIdentifier!
NSWorkspace.shared.launchApplication(
withBundleIdentifier: appBundleIdentifier,
options: NSWorkspace.LaunchOptions.newInstance,
additionalEventParamDescriptor: nil,
launchIdentifier: nil)
NSApp.terminate(nil)
}
7 changes: 4 additions & 3 deletions Example/GeneralPreferenceViewController.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Cocoa
import Preferences

final class GeneralPreferenceViewController: NSViewController, Preferenceable {
let toolbarItemTitle = "General"
let toolbarItemIcon = NSImage(named: NSImage.preferencesGeneralName)!
final class GeneralPreferenceViewController: NSViewController, PreferencePane {
let preferencePaneIdentifier: PreferencePaneIdentifier = .general
let toolbarItemTitle = "General"
let toolbarItemIcon = NSImage(named: NSImage.preferencesGeneralName)!

override var nibName: NSNib.Name? {
return "GeneralPreferenceViewController"
Expand Down
30 changes: 24 additions & 6 deletions Example/GeneralPreferenceViewController.xib
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14313.18"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
Expand All @@ -14,19 +14,37 @@
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="c22-O7-iKe">
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<rect key="frame" x="0.0" y="0.0" width="666" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Xc1-oC-jbN">
<rect key="frame" x="204" y="124" width="72" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textField horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Xc1-oC-jbN">
<rect key="frame" x="298" y="124" width="70" height="24"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="General" id="kEa-Ts-PrR">
<font key="font" metaFont="system" size="20"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AeJ-us-BJO">
<rect key="frame" x="241" y="88" width="185" height="32"/>
<buttonCell key="cell" type="push" title="Switch Preference Style" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="pPv-HR-smI">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switchStyle:" target="-1" id="mbG-7D-LUH"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="AeJ-us-BJO" firstAttribute="centerX" secondItem="Xc1-oC-jbN" secondAttribute="centerX" id="0D5-yt-qbT"/>
<constraint firstItem="AeJ-us-BJO" firstAttribute="top" secondItem="Xc1-oC-jbN" secondAttribute="bottom" constant="8" id="PDh-Co-vOC"/>
<constraint firstAttribute="bottom" secondItem="Xc1-oC-jbN" secondAttribute="bottom" constant="124" id="Ygh-kW-pw7"/>
<constraint firstAttribute="trailing" secondItem="Xc1-oC-jbN" secondAttribute="trailing" constant="300" id="dPQ-fn-EVx"/>
<constraint firstItem="Xc1-oC-jbN" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" constant="124" id="obX-e4-hYJ"/>
<constraint firstItem="Xc1-oC-jbN" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="300" id="sQd-RT-oXo"/>
</constraints>
<point key="canvasLocation" x="55" y="154"/>
</customView>
</objects>
</document>
39 changes: 39 additions & 0 deletions Example/PreferencesStyle+UserDefaults.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Foundation
import Preferences

// Helpers to write styles to and read them from UserDefaults.

extension PreferencesStyle: RawRepresentable {
public var rawValue: Int {
switch self {
case .toolbarItems:
return 0
case .segmentedControl:
return 1
}
}

public init?(rawValue: Int) {
switch rawValue {
case 0:
self = .toolbarItems
case 1:
self = .segmentedControl
default:
return nil
}
}
}

extension PreferencesStyle {
static var userDefaultsKey: String { return "preferencesStyle" }

static func preferencesStyleFromUserDefaults(_ userDefaults: UserDefaults = .standard) -> PreferencesStyle {
return PreferencesStyle(rawValue: userDefaults.integer(forKey: PreferencesStyle.userDefaultsKey))
?? .toolbarItems
}

func storeInUserDefaults(_ userDefaults: UserDefaults = .standard) {
userDefaults.set(self.rawValue, forKey: PreferencesStyle.userDefaultsKey)
}
}