mirror of
https://github.com/coteditor/CotEditor.git
synced 2024-09-11 11:25:57 +03:00
Add edited indicator to window tab (close #904)
This commit is contained in:
parent
8af486506c
commit
7796fed581
@ -5,6 +5,11 @@ Change Log
|
||||
4.4.0 (unreleased)
|
||||
--------------------------
|
||||
|
||||
### New Features
|
||||
|
||||
- Display a dot in the window tab if the document has unsaved changes.
|
||||
|
||||
|
||||
### Improvements
|
||||
|
||||
- Change the system requirement to __macOS 12 Moneterey and later__.
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="Lgm-sL-YIF">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="20037"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
@ -169,15 +168,17 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<customView toolTip="This style is customized." translatesAutoresizingMaskIntoConstraints="NO" id="cbJ-XK-bnG" customClass="DotView" customModule="CotEditor" customModuleProvider="target">
|
||||
<rect key="frame" x="5" y="4" width="4" height="4"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="4" id="KbQ-uH-zf8"/>
|
||||
<constraint firstAttribute="width" secondItem="cbJ-XK-bnG" secondAttribute="height" multiplier="1:1" id="ZE1-ZW-sTB"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="color" keyPath="color">
|
||||
<color key="value" name="tertiaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="dotLength">
|
||||
<real key="value" value="4"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<binding destination="9MN-yG-hHM" name="hidden" keyPath="objectValue.state" id="uBD-Ia-4YK">
|
||||
@ -188,7 +189,7 @@
|
||||
</connections>
|
||||
</customView>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="B3Y-Nj-FSx">
|
||||
<rect key="frame" x="12" y="0.0" width="265" height="16"/>
|
||||
<rect key="frame" x="14" y="0.0" width="263" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="7hV-jt-xSx">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
@ -201,11 +202,12 @@
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="B3Y-Nj-FSx" secondAttribute="bottom" id="4bc-8w-fDr"/>
|
||||
<constraint firstItem="cbJ-XK-bnG" firstAttribute="centerY" secondItem="9MN-yG-hHM" secondAttribute="centerY" constant="2" id="6NR-Dc-qjR"/>
|
||||
<constraint firstItem="B3Y-Nj-FSx" firstAttribute="top" secondItem="9MN-yG-hHM" secondAttribute="top" id="JKi-hq-c4N"/>
|
||||
<constraint firstItem="B3Y-Nj-FSx" firstAttribute="leading" secondItem="cbJ-XK-bnG" secondAttribute="trailing" constant="5" id="Rvk-hT-fMi"/>
|
||||
<constraint firstItem="cbJ-XK-bnG" firstAttribute="leading" secondItem="9MN-yG-hHM" secondAttribute="leading" constant="5" id="k20-HG-Pr3"/>
|
||||
<constraint firstAttribute="bottom" secondItem="cbJ-XK-bnG" secondAttribute="bottom" id="RH0-lJ-ZZL"/>
|
||||
<constraint firstItem="B3Y-Nj-FSx" firstAttribute="leading" secondItem="cbJ-XK-bnG" secondAttribute="trailing" id="Rvk-hT-fMi"/>
|
||||
<constraint firstItem="cbJ-XK-bnG" firstAttribute="leading" secondItem="9MN-yG-hHM" secondAttribute="leading" id="k20-HG-Pr3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="B3Y-Nj-FSx" secondAttribute="trailing" constant="2" id="loU-tZ-CZ0"/>
|
||||
<constraint firstItem="cbJ-XK-bnG" firstAttribute="top" secondItem="9MN-yG-hHM" secondAttribute="top" id="vdE-ic-WvJ"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="textField" destination="B3Y-Nj-FSx" id="qzD-8z-WxE"/>
|
||||
|
@ -74,6 +74,14 @@ final class DocumentWindowController: NSWindowController, NSWindowDelegate {
|
||||
window.setFrame(.init(origin: window.frame.origin, size: frameSize), display: false)
|
||||
}
|
||||
|
||||
// set edited indicator to window tab
|
||||
let dotView = DotView()
|
||||
dotView.isHidden = true
|
||||
dotView.color = .tertiaryLabelColor
|
||||
dotView.toolTip = "Document has unsaved changes".localized
|
||||
self.window?.tab.accessoryView = dotView
|
||||
NSLayoutConstraint(item: dotView, attribute: .height, relatedBy: .equal, toItem: dotView, attribute: .width, multiplier: 1, constant: 0).isActive = true
|
||||
|
||||
// observe opacity setting change
|
||||
if let window = self.window as? DocumentWindow {
|
||||
self.opacityObserver = UserDefaults.standard.publisher(for: .windowAlpha, initial: true)
|
||||
@ -125,6 +133,8 @@ final class DocumentWindowController: NSWindowController, NSWindowDelegate {
|
||||
|
||||
override func setDocumentEdited(_ dirtyFlag: Bool) {
|
||||
|
||||
self.window?.tab.accessoryView?.isHidden = !dirtyFlag
|
||||
|
||||
super.setDocumentEdited(self.isWhitepaper ? false : dirtyFlag)
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// © 2015-2018 1024jp
|
||||
// © 2015-2022 1024jp
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -23,14 +23,15 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import AppKit
|
||||
|
||||
@IBDesignable
|
||||
final class DotView: NSView {
|
||||
|
||||
// MARK: Inspectable Properties
|
||||
|
||||
@IBInspectable var color: NSColor = .labelColor
|
||||
@Invalidating(.display) @IBInspectable var color: NSColor = .labelColor
|
||||
@Invalidating(.display) @IBInspectable var dotLength: CGFloat = 4
|
||||
|
||||
|
||||
|
||||
@ -39,10 +40,18 @@ final class DotView: NSView {
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
|
||||
assert(self.dotLength <= self.bounds.width)
|
||||
assert(self.dotLength <= self.bounds.height)
|
||||
|
||||
let rect = NSRect(x: (self.bounds.width - self.dotLength) / 2,
|
||||
y: (self.bounds.height - self.dotLength) / 2,
|
||||
width: self.dotLength,
|
||||
height: self.dotLength)
|
||||
|
||||
NSGraphicsContext.saveGraphicsState()
|
||||
|
||||
self.color.setFill()
|
||||
NSBezierPath(ovalIn: self.bounds).fill()
|
||||
NSBezierPath(ovalIn: rect).fill()
|
||||
|
||||
NSGraphicsContext.restoreGraphicsState()
|
||||
}
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "Das Dokument enthält ungesicherte Änderungen.";
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "Syntaxstil";
|
||||
// tooltip
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "Document has unsaved changes";
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "Syntax Style";
|
||||
// tooltip
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "Document has unsaved changes"; // FIXME: added
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "Syntaxe";
|
||||
// tooltip
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "Document has unsaved changes"; // FIXME: added
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "Stile sintassi";
|
||||
// tooltip
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "書類に保存されていない変更があります";
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "シンタックス";
|
||||
// tooltip
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "Document has unsaved changes"; // FIXME: added
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "Estilo da Sintaxe";
|
||||
// tooltip
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "Document has unsaved changes"; // FIXME: added
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "Sözdizim Biçemi";
|
||||
// tooltip
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "Document has unsaved changes"; // FIXME: added
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "语法样式";
|
||||
// tooltip
|
||||
|
@ -220,6 +220,12 @@
|
||||
|
||||
|
||||
|
||||
/* MARK: Document Window */
|
||||
// tooltip for the "edited" indicator in window tab
|
||||
"Document has unsaved changes" = "Document has unsaved changes";
|
||||
|
||||
|
||||
|
||||
/* MARK: Toolbar */
|
||||
"Syntax Style" = "文法樣式";
|
||||
// tooltip
|
||||
|
Loading…
Reference in New Issue
Block a user