Fix layout

This commit is contained in:
Zhigang Fang
2017-10-26 00:18:08 +08:00
parent 6fee38436e
commit 01e2f7a139
3 changed files with 102 additions and 39 deletions

View File

@@ -3,7 +3,6 @@
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13196"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
<capability name="stacking Non-gravity area distributions on NSStackView" minToolsVersion="7.0" minSystemVersion="10.11"/>
</dependencies>
@@ -347,11 +346,11 @@
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController showSeguePresentationStyle="single" id="B8D-0N-5wS" customClass="FloatingPannel" customModule="FloatingToggl" customModuleProvider="target" sceneMemberID="viewController">
<window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA" customClass="NSPanel">
<window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="IQv-IB-iLA" customClass="NSPanel">
<windowStyleMask key="styleMask" titled="YES" resizable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES" fullSizeContentView="YES"/>
<windowCollectionBehavior key="collectionBehavior" moveToActiveSpace="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="585" y="830" width="480" height="100"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="95" y="73" width="426" height="100"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<connections>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
@@ -363,23 +362,23 @@
</windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="250"/>
<point key="canvasLocation" x="2" y="250"/>
</scene>
<!--View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="ViewController" customModule="FloatingToggl" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="580" height="60"/>
<rect key="frame" x="0.0" y="0.0" width="364" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView distribution="fill" orientation="horizontal" alignment="centerY" spacing="10" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wu7-dI-dhr">
<rect key="frame" x="20" y="0.0" width="560" height="60"/>
<stackView distribution="fill" orientation="horizontal" alignment="centerY" spacing="20" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wu7-dI-dhr">
<rect key="frame" x="20" y="0.0" width="324" height="60"/>
<subviews>
<textField horizontalHuggingPriority="247" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BPy-6c-wmT">
<rect key="frame" x="-2" y="20.5" width="438" height="19"/>
<textField horizontalHuggingPriority="249" verticalHuggingPriority="750" horizontalCompressionResistancePriority="999" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BPy-6c-wmT" customClass="AutoGrowTextField" customModule="FloatingToggl" customModuleProvider="target">
<rect key="frame" x="-2" y="20.5" width="197" height="19"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="200" id="Tug-Tb-Szc"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="100" id="Tug-Tb-Szc"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" placeholderString="What are you working on?" usesSingleLineMode="YES" id="Yb4-dr-ehw">
<font key="font" metaFont="system" size="15"/>
@@ -391,7 +390,7 @@
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="TdA-qV-FLw">
<rect key="frame" x="442" y="19.5" width="55" height="21"/>
<rect key="frame" x="211" y="19.5" width="55" height="21"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="1:17:28" id="7aI-t8-bK1">
<font key="font" size="15" name="HelveticaNeue"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@@ -399,10 +398,9 @@
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="kag-yT-y1V">
<rect key="frame" x="505" y="2.5" width="55" height="55"/>
<rect key="frame" x="284" y="2.5" width="40" height="55"/>
<constraints>
<constraint firstAttribute="height" constant="55" id="Gyb-XX-9Vm"/>
<constraint firstAttribute="width" secondItem="kag-yT-y1V" secondAttribute="height" id="Xf4-F1-gUv"/>
</constraints>
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="Stop" imagePosition="overlaps" alignment="center" inset="2" id="LaA-Fa-c8O">
<behavior key="behavior" pushIn="YES" changeContents="YES" lightByContents="YES"/>
@@ -430,7 +428,7 @@
</subviews>
<constraints>
<constraint firstItem="wu7-dI-dhr" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" constant="20" id="0Bk-A0-XKV"/>
<constraint firstAttribute="trailing" secondItem="wu7-dI-dhr" secondAttribute="trailing" id="LPI-zO-QJY"/>
<constraint firstAttribute="trailing" secondItem="wu7-dI-dhr" secondAttribute="trailing" constant="20" id="LPI-zO-QJY"/>
<constraint firstAttribute="bottom" secondItem="wu7-dI-dhr" secondAttribute="bottom" id="PMU-dI-y8Q"/>
<constraint firstItem="wu7-dI-dhr" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="fcA-No-1Cl"/>
</constraints>
@@ -443,7 +441,7 @@
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="655"/>
<point key="canvasLocation" x="-140.5" y="654"/>
</scene>
</scenes>
<resources>

View File

@@ -7,9 +7,12 @@
//
import Cocoa
import RxSwift
class FloatingPannel: NSWindowController {
let disposebag = DisposeBag()
override func windowDidLoad() {
super.windowDidLoad()
guard let panel = self.window as? NSPanel else {
@@ -19,6 +22,15 @@ class FloatingPannel: NSWindowController {
panel.isFloatingPanel = true
panel.titleVisibility = .hidden
panel.titlebarAppearsTransparent = true
}
override func mouseEntered(with event: NSEvent) {
super.mouseEntered(with: event)
}
override func mouseExited(with event: NSEvent) {
super.mouseEntered(with: event)
}
}

View File

@@ -104,6 +104,8 @@ class TogglViewModel {
let input = Variable<String>("")
let active = Variable<Bool>(NSApplication.shared.isActive)
private let disposeBag = DisposeBag()
var completions: Driver<[String]> {
@@ -132,6 +134,23 @@ class TogglViewModel {
self?.keychain.delete(tokenKey)
}
}).disposed(by: self.disposeBag)
Observable.merge([
NotificationCenter.default.rx
.notification(NSApplication.didBecomeActiveNotification)
.map({_ in true}),
NotificationCenter.default.rx
.notification(NSApplication.willResignActiveNotification)
.map({_ in false})
]).bind(to: self.active).disposed(by: self.disposeBag)
self.active.asDriver()
.distinctUntilChanged()
.filter({$0})
.map({_ in ()})
.drive(refresh)
.disposed(by: self.disposeBag)
token.asDriver().flatMapLatest({ token -> Driver<TimeEntry?> in
if let token = token {
return self.refresh.asDriver(onErrorJustReturn: ()).startWith(()).flatMapLatest({_ in
@@ -143,9 +162,11 @@ class TogglViewModel {
return Driver<TimeEntry?>.just(nil)
}).debug().drive(current).disposed(by: self.disposeBag)
token.asDriver().flatMapLatest({ token -> Driver<User?> in
token.asDriver().flatMapLatest({[weak self] token -> Driver<User?> in
if let token = token {
return Endpoint<User>.me.request(with: token).map(Optional.some).asDriver(onErrorJustReturn: nil)
return self?.current.asDriver().flatMapLatest({ _ in
Endpoint<User>.me.request(with: token).map(Optional.some).asDriver(onErrorJustReturn: nil)
}) ?? .just(nil)
}
return Driver<User?>.just(nil)
}).debug().drive(user).disposed(by: self.disposeBag)
@@ -178,6 +199,17 @@ class TogglViewModel {
}
class AutoGrowTextField: NSTextField {
override var intrinsicContentSize: NSSize {
self.isEditable = false
defer {
self.isEditable = true
}
return super.intrinsicContentSize
}
}
class ViewController: NSViewController {
@@ -276,19 +308,33 @@ class ViewController: NSViewController {
self?.timerLabel.stringValue = text
}).disposed(by: self.disposeBag)
viewModel.current.asDriver().distinctUntilChanged({
($0 == nil) == ($1 == nil)
}).drive(onNext: {[weak self] current in
let text = current?.description ?? ""
self?.inputLabel.stringValue = text
self?.viewModel.input.value = text
self?.inputLabel.currentEditor()?.selectedRange.length = 0
self?.inputLabel.window?.makeFirstResponder(nil)
viewModel.current.asDriver().drive(onNext: {[weak self] current in
self?.timerLabel.isHidden = current == nil
self?.actionButton.isHidden = current == nil
if let current = current {
let text = current.description ?? "Untitled"
self?.inputLabel.stringValue = text
self?.viewModel.input.value = text
self?.isShowingRecentEntries = false
self?.inputLabel.window?.makeFirstResponder(nil)
} else {
self?.inputLabel.stringValue = ""
self?.viewModel.input.value = ""
}
self?.placeCursorAtTheEnd()
self?.resizeWindow()
}).disposed(by: self.disposeBag)
}
var trackingRect: NSView.TrackingRectTag?
override func viewDidLayout() {
super.viewDidLayout()
if let t = trackingRect {
view.removeTrackingRect(t)
}
trackingRect = view.addTrackingRect(view.bounds, owner: self, userData: nil, assumeInside: false)
}
override func viewDidAppear() {
super.viewDidAppear()
if viewModel.token.value == nil {
@@ -305,6 +351,8 @@ class ViewController: NSViewController {
if newValue {
guard !recentItems.isEmpty else { return }
guard inputLabel.currentEditor()?.selectedRange.length == 0 else { return }
recentItemVC.show(relativeTo: .zero, of: self.view, preferredEdge: .minY)
} else {
recentItemVC.close()
@@ -312,6 +360,13 @@ class ViewController: NSViewController {
}
}
func resizeWindow() {
guard let window = self.view.window else { return }
let minSize = self.view.fittingSize
window.setFrame(NSRect(origin: window.frame.origin, size: minSize), display: true)
}
@IBAction func presentRecentEntries(_ sender: NSMenuItem) {
self.isShowingRecentEntries = !self.isShowingRecentEntries
}
@@ -320,6 +375,13 @@ class ViewController: NSViewController {
self.viewModel.stopTimer()
}
func placeCursorAtTheEnd() {
guard let editor = self.inputLabel.currentEditor() else { return }
let string = self.inputLabel.stringValue as NSString
editor.selectedRange = NSRange(location: string.length, length: 0)
}
func presentSetToken() {
let alert = NSAlert()
alert.alertStyle = .informational
@@ -379,7 +441,7 @@ extension ViewController: NSTextFieldDelegate {
inputLabel.stringValue = recentItems[self.selectedRow]
viewModel.input.value = recentItems[self.selectedRow]
isShowingRecentEntries = false
inputLabel.currentEditor()?.selectedRange.length = 0
self.placeCursorAtTheEnd()
}
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
@@ -393,18 +455,9 @@ extension ViewController: NSTextFieldDelegate {
selectedRow = selectedRow + 1
isShowingRecentEntries = true
case #selector(textView.insertTab(_:)):
if recentItems.count > 1 {
selectedRow = selectedRow + 1
isShowingRecentEntries = true
} else if recentItems.count == 1 {
insertSelection()
}
insertSelection()
case #selector(textView.insertNewline(_:)):
if isShowingRecentEntries {
insertSelection()
} else {
self.viewModel.startTimer()
}
self.viewModel.startTimer()
default:
return false
}
@@ -414,7 +467,6 @@ extension ViewController: NSTextFieldDelegate {
override func controlTextDidChange(_ obj: Notification) {
self.viewModel.input.value = inputLabel.stringValue
}
}
extension ViewController: NSTableViewDelegate, NSTableViewDataSource {
@@ -433,6 +485,7 @@ extension ViewController: NSTableViewDelegate, NSTableViewDataSource {
textField.drawsBackground = false
textField.isEditable = false
textField.isSelectable = false
textField.usesSingleLineMode = true
cell.addSubview(textField)
cell.textField = textField
cell.identifier = ViewController.identity