Add outline view (#756)

This commit is contained in:
1024jp 2018-02-27 12:48:44 +09:00
parent 282372e43f
commit fab3162926
20 changed files with 928 additions and 3 deletions

View File

@ -5,6 +5,12 @@ Change Log
unreleased
--------------------------
### New Features
- Add outline menu to side bar.
- [ ] Outline trigger
- [ ] menu item for outline view
### Improvements
- When “Indent with Tab key” is on, reduce indent level of the current line with Shift+Tab even when nothing is selected.

View File

@ -249,6 +249,7 @@
<tabViewController showSeguePresentationStyle="single" tabStyle="unspecified" id="7te-2x-zAq" customClass="SidebarViewController" customModule="CotEditor" customModuleProvider="target" sceneMemberID="viewController">
<tabViewItems>
<tabViewItem label="Document Inspector" image="DocumentTemplate" id="Kfj-q6-61N"/>
<tabViewItem label="Outline" image="OutlineTemplate" id="hyM-2j-hen"/>
<tabViewItem label="Incompatible Characters" image="ConflictsTemplate" id="JZo-ok-Dks"/>
</tabViewItems>
<viewControllerTransitionOptions key="transitionOptions" allowUserInteraction="YES"/>
@ -263,8 +264,10 @@
</tabView>
<connections>
<outlet property="documentInspectorTabViewItem" destination="Kfj-q6-61N" id="WFA-8N-DmT"/>
<outlet property="outlineTabViewItem" destination="hyM-2j-hen" id="EFV-Ay-pkJ"/>
<outlet property="incompatibleCharactersTabViewItem" destination="JZo-ok-Dks" id="QRQ-Sy-61p"/>
<segue destination="2Hh-Pq-vvo" kind="relationship" relationship="tabItems" id="dgq-BX-Slv"/>
<segue destination="US1-1U-VH8" kind="relationship" relationship="tabItems" id="4Zo-YO-63m"/>
<segue destination="ry4-rh-ZBT" kind="relationship" relationship="tabItems" id="XUT-Cm-0nR"/>
</connections>
</tabViewController>
@ -278,7 +281,7 @@
<controllerPlaceholder storyboardName="DocumentInspectorView" id="2Hh-Pq-vvo" userLabel="Document Inspector View Controller" sceneMemberID="viewController"/>
<customObject id="Eo9-v0-LrD" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1178" y="1100"/>
<point key="canvasLocation" x="1178" y="1067"/>
</scene>
<!--Incompatible Characters View Controller-->
<scene sceneID="Wud-vX-9dR">
@ -286,7 +289,15 @@
<controllerPlaceholder storyboardName="IncompatibleCharactersView" id="ry4-rh-ZBT" userLabel="Incompatible Characters View Controller" sceneMemberID="viewController"/>
<customObject id="fzj-JB-SfU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1191" y="1157"/>
<point key="canvasLocation" x="1191" y="1192"/>
</scene>
<!--Outline View Controller-->
<scene sceneID="0hV-Dj-Fqy">
<objects>
<controllerPlaceholder storyboardName="OutlineView" id="US1-1U-VH8" userLabel="Outline View Controller" sceneMemberID="viewController"/>
<customObject id="muC-U5-1Gw" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1139" y="1128"/>
</scene>
<!--Document View Controller-->
<scene sceneID="og9-Gf-wXr">
@ -423,9 +434,10 @@
<image name="IncompatibleChars" width="24" height="24"/>
<image name="InvisibleChars_On" width="24" height="24"/>
<image name="LockedTemplate" width="16" height="16"/>
<image name="OutlineTemplate" width="15" height="15"/>
<image name="PageGuide_On" width="24" height="24"/>
<image name="Print" width="24" height="24"/>
<image name="RTL_On" width="128" height="128"/>
<image name="RTL_On" width="24" height="24"/>
<image name="RecolorAll" width="24" height="24"/>
<image name="Share" width="24" height="24"/>
<image name="ShiftLeft" width="24" height="24"/>

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="Wry-M9-Gep">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
<capability name="system font weights other than Regular or Bold" minToolsVersion="7.0"/>
</dependencies>
<scenes>
<!--Outline View Controller-->
<scene sceneID="Ms1-wa-Rxd">
<objects>
<viewController id="Wry-M9-Gep" customClass="OutlineViewController" customModule="CotEditor" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="DQy-qv-3Fk">
<rect key="frame" x="0.0" y="0.0" width="220" height="400"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" setsMaxLayoutWidthAtFirstLayout="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="w9Z-gJ-Amp">
<rect key="frame" x="10" y="378" width="44" height="14"/>
<textFieldCell key="cell" controlSize="small" sendsActionOnEndEditing="YES" title="Outline" id="RyV-wo-tpY">
<font key="font" metaFont="systemSemibold" size="11"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<scrollView autohidesScrollers="YES" horizontalLineScroll="20" horizontalPageScroll="10" verticalLineScroll="20" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sdS-LF-zK0">
<rect key="frame" x="12" y="12" width="196" height="358"/>
<clipView key="contentView" id="kw3-JE-21n">
<rect key="frame" x="1" y="0.0" width="194" height="357"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="14" headerView="meP-Ke-T4s" viewBased="YES" outlineTableColumn="CSX-H0-nFf" id="LBW-lW-4ux">
<rect key="frame" x="0.0" y="0.0" width="195" height="334"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="4" height="6"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="title" width="191" minWidth="40" maxWidth="1000" id="CSX-H0-nFf">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Title">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" controlSize="small" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="rwF-t2-tPJ">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="nfz-SY-V76">
<rect key="frame" x="2" y="3" width="191" height="14"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField identifier="title" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="F1F-V6-xxG">
<rect key="frame" x="0.0" y="0.0" width="191" height="14"/>
<textFieldCell key="cell" controlSize="small" lineBreakMode="truncatingTail" selectable="YES" sendsActionOnEndEditing="YES" title="Item Title" id="opH-Sc-iu8">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="nfz-SY-V76" name="value" keyPath="objectValue" id="Wmn-db-d8D"/>
<binding destination="nfz-SY-V76" name="toolTip" keyPath="objectValue.string" id="Jng-gN-6Eo"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="F1F-V6-xxG" secondAttribute="trailing" constant="2" id="LRq-Qi-FwQ"/>
<constraint firstAttribute="bottom" secondItem="F1F-V6-xxG" secondAttribute="bottom" id="SYM-2C-9ij"/>
<constraint firstItem="F1F-V6-xxG" firstAttribute="leading" secondItem="nfz-SY-V76" secondAttribute="leading" constant="2" id="WCg-Yf-ZCN"/>
<constraint firstItem="F1F-V6-xxG" firstAttribute="top" secondItem="nfz-SY-V76" secondAttribute="top" id="eeZ-K4-Lmi"/>
</constraints>
<connections>
<outlet property="textField" destination="F1F-V6-xxG" id="zDm-83-cq9"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
<connections>
<action selector="selectOutlineItem:" target="Wry-M9-Gep" id="M8Z-Ke-Y9M"/>
<outlet property="dataSource" destination="Wry-M9-Gep" id="5Yi-fx-IY7"/>
<outlet property="delegate" destination="Wry-M9-Gep" id="HXz-PH-YAE"/>
</connections>
</outlineView>
</subviews>
</clipView>
<scroller key="horizontalScroller" verticalHuggingPriority="750" horizontal="YES" id="Vh9-uN-jKp">
<rect key="frame" x="1" y="341" width="194" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="pN6-MO-ePX">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" id="meP-Ke-T4s">
<rect key="frame" x="0.0" y="0.0" width="195" height="23"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="sdS-LF-zK0" secondAttribute="bottom" constant="12" id="1gf-5N-7G7"/>
<constraint firstItem="w9Z-gJ-Amp" firstAttribute="top" secondItem="DQy-qv-3Fk" secondAttribute="top" constant="8" id="XMM-ho-3L6"/>
<constraint firstItem="sdS-LF-zK0" firstAttribute="leading" secondItem="DQy-qv-3Fk" secondAttribute="leading" constant="12" id="XaZ-Pz-RxG"/>
<constraint firstItem="w9Z-gJ-Amp" firstAttribute="leading" secondItem="DQy-qv-3Fk" secondAttribute="leading" constant="12" id="f5I-Dp-Sqh"/>
<constraint firstAttribute="trailing" secondItem="sdS-LF-zK0" secondAttribute="trailing" constant="12" id="iIm-zW-8W4"/>
<constraint firstItem="sdS-LF-zK0" firstAttribute="top" secondItem="w9Z-gJ-Amp" secondAttribute="bottom" constant="8" symbolic="YES" id="uzb-KU-oYK"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="w9Z-gJ-Amp" secondAttribute="trailing" constant="12" id="yzP-e0-vAT"/>
</constraints>
</view>
<connections>
<outlet property="outlineView" destination="LBW-lW-4ux" id="obz-UQ-pIL"/>
</connections>
</viewController>
<customObject id="yJT-Xy-p5x" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="90" y="55"/>
</scene>
</scenes>
</document>

View File

@ -568,6 +568,10 @@
2AE73F41203D2FBB00D8903B /* NSLayoutManager+Range.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE73F3F203D2FBB00D8903B /* NSLayoutManager+Range.swift */; };
2AE73F43203E753C00D8903B /* NSTextView+Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE73F42203E753C00D8903B /* NSTextView+Selection.swift */; };
2AE73F44203E753C00D8903B /* NSTextView+Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE73F42203E753C00D8903B /* NSTextView+Selection.swift */; };
2AE7A8D620450C0000830830 /* OutlineView.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2AE7A8D420450C0000830830 /* OutlineView.storyboard */; };
2AE7A8D720450C0000830830 /* OutlineView.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2AE7A8D420450C0000830830 /* OutlineView.storyboard */; };
2AE7A8D920450FE600830830 /* OutlineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE7A8D820450FE600830830 /* OutlineViewController.swift */; };
2AE7A8DA20450FE600830830 /* OutlineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE7A8D820450FE600830830 /* OutlineViewController.swift */; };
2AEC48331E641E4F00FB0F89 /* Snippet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AEC48321E641E4F00FB0F89 /* Snippet.swift */; };
2AEC48341E641E4F00FB0F89 /* Snippet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AEC48321E641E4F00FB0F89 /* Snippet.swift */; };
2AEC69C41D41A1BE0089F96F /* EditorTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AEC69C31D41A1BE0089F96F /* EditorTextView.swift */; };
@ -1198,6 +1202,13 @@
2AE73F3C2039A29300D8903B /* URL+ExtendedAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+ExtendedAttribute.swift"; sourceTree = "<group>"; };
2AE73F3F203D2FBB00D8903B /* NSLayoutManager+Range.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutManager+Range.swift"; sourceTree = "<group>"; };
2AE73F42203E753C00D8903B /* NSTextView+Selection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTextView+Selection.swift"; sourceTree = "<group>"; };
2AE7A8D520450C0000830830 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/OutlineView.storyboard; sourceTree = "<group>"; };
2AE7A8D820450FE600830830 /* OutlineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutlineViewController.swift; sourceTree = "<group>"; };
2AE7A8DC2045205A00830830 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/OutlineView.strings; sourceTree = "<group>"; };
2AE7A8DE2045205B00830830 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/OutlineView.strings"; sourceTree = "<group>"; };
2AE7A8E02045205C00830830 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/OutlineView.strings; sourceTree = "<group>"; };
2AE7A8E22045205D00830830 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/OutlineView.strings; sourceTree = "<group>"; };
2AE7A8E42045205E00830830 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/OutlineView.strings; sourceTree = "<group>"; };
2AEC48321E641E4F00FB0F89 /* Snippet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Snippet.swift; sourceTree = "<group>"; };
2AEC69C31D41A1BE0089F96F /* EditorTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorTextView.swift; sourceTree = "<group>"; };
2AED466F1E425CD200751C45 /* TextFind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFind.swift; sourceTree = "<group>"; };
@ -1777,6 +1788,7 @@
children = (
2A6602CE1D05BD72003E8D87 /* DocumentWindow.storyboard */,
2A4144BA201397D70061F653 /* DocumentInspectorView.storyboard */,
2AE7A8D420450C0000830830 /* OutlineView.storyboard */,
2A4144B6201397150061F653 /* IncompatibleCharactersView.storyboard */,
2A5F7CA31D152589001D83BC /* EditorView.storyboard */,
);
@ -2059,6 +2071,7 @@
children = (
2AAB4BFE1D2444930049A68B /* SidebarViewController.swift */,
2AAB4BF81D2435AC0049A68B /* DocumentInspectorViewController.swift */,
2AE7A8D820450FE600830830 /* OutlineViewController.swift */,
2AAB4BFB1D2437EA0049A68B /* IncompatibleCharactersViewController.swift */,
);
name = Sidebar;
@ -2343,6 +2356,7 @@
2A6F0D6E1B5500E100C2D03C /* PrintPanelAccessory.xib in Resources */,
2A5DBE571B5D2DAD00F8CB13 /* SyntaxTermsEditView.xib in Resources */,
2A6F0D751B5500E100C2D03C /* SyntaxMappingConflictView.xib in Resources */,
2AE7A8D720450C0000830830 /* OutlineView.storyboard in Resources */,
2A6F0D781B5500E100C2D03C /* ColorCodePanelAccessory.xib in Resources */,
2A6F0D7C1B5500E100C2D03C /* UnicodePanel.xib in Resources */,
2A5DBE5C1B5D2DBD00F8CB13 /* SyntaxInfoEditView.xib in Resources */,
@ -2409,6 +2423,7 @@
2A3A75A919E77E87001DAB88 /* SyntaxInfoEditView.xib in Resources */,
2AE73ECC2035223100D8903B /* Credits.css in Resources */,
2A7CF1591C4F569B0015FF2F /* FindPreferencesView.xib in Resources */,
2AE7A8D620450C0000830830 /* OutlineView.storyboard in Resources */,
2A3A75AC19E77E87001DAB88 /* SyntaxValidationView.xib in Resources */,
2588E9CE07C4851C0060021D /* ProgressView.xib in Resources */,
2A10D1201E713BE60027192A /* PrintPane.storyboard in Resources */,
@ -2738,6 +2753,7 @@
2A4257B41D2309AB0086DAAD /* OpacityPanelController.swift in Sources */,
2A64F2431D256FCB001B229F /* MenuKeyBindingManager.swift in Sources */,
2A17A3141D2D16F1001DD717 /* WindowContentViewController.swift in Sources */,
2AE7A8DA20450FE600830830 /* OutlineViewController.swift in Sources */,
2AD616D01D3E67160016EFB6 /* ODBEditorSuite.swift in Sources */,
2A7646E81D48EAF200350674 /* SettingManager.swift in Sources */,
2A1856061D47E7FF008FA79E /* NSTextView+TextReplacement.swift in Sources */,
@ -2872,6 +2888,7 @@
2A5D13481D1FEF9900D38E6A /* FindPanelFieldViewController.swift in Sources */,
2AD616CF1D3E67160016EFB6 /* ODBEditorSuite.swift in Sources */,
2A6FD9DB1D38F93300A59784 /* EditorTextView+Indenting.swift in Sources */,
2AE7A8D920450FE600830830 /* OutlineViewController.swift in Sources */,
2AF073F41D34076A00770BA6 /* CharacterPopoverController.swift in Sources */,
2A7646E71D48EAF200350674 /* SettingManager.swift in Sources */,
2A5D13131D1EE8FF00D38E6A /* HUDController.swift in Sources */,
@ -3620,6 +3637,19 @@
name = Credits.css;
sourceTree = "<group>";
};
2AE7A8D420450C0000830830 /* OutlineView.storyboard */ = {
isa = PBXVariantGroup;
children = (
2AE7A8D520450C0000830830 /* Base */,
2AE7A8DC2045205A00830830 /* ja */,
2AE7A8DE2045205B00830830 /* zh-Hans */,
2AE7A8E02045205C00830830 /* de */,
2AE7A8E22045205D00830830 /* it */,
2AE7A8E42045205E00830830 /* pt */,
);
name = OutlineView.storyboard;
sourceTree = "<group>";
};
2AF5C3BC1A55072E00C972B5 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "OutlineTemplate.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "SelectedOutlineTemplate.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,222 @@
//
// OutlineViewController.swift
//
// CotEditor
// https://coteditor.com
//
// Created by 1024jp on 2018-02-27.
//
// ---------------------------------------------------------------------------
//
// © 2018 1024jp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Cocoa
/// outilneView column identifiers
private extension NSUserInterfaceItemIdentifier {
static let title = NSUserInterfaceItemIdentifier("title")
}
final class OutlineViewController: NSViewController {
// MARK: Private Properties
private var documentObserver: NSObjectProtocol?
private var syntaxStyleObserver: NSObjectProtocol?
@IBOutlet private weak var outlineView: NSOutlineView?
// MARK: -
// MARK: View Controller Methods
override var representedObject: Any? {
didSet {
self.observeDocument()
self.observeSyntaxStyle()
self.outlineView?.reloadData()
}
}
// MARK: Actions
/// item in outlineView was clicked
@IBAction func selectOutlineItem(_ outlineView: NSOutlineView) {
self.selectOutlineItem(at: outlineView.clickedRow)
}
// MARK: Private Methods
/// current outline items
private var outlineItems: [OutlineItem] {
return self.document?.syntaxStyle.outlineItems ?? []
}
/// current outline items
private var document: Document? {
return self.representedObject as? Document
}
/// select current outline item in textView
private func selectOutlineItem(at row: Int) {
guard let item = self.outlineItems[safe: row] else { return }
let range = item.range
// abandon if text became shorter than range to select
guard
let textView = self.document?.textView,
textView.string.nsRange.upperBound >= range.upperBound
else { return }
textView.selectedRange = range
textView.scrollRangeToVisible(range)
textView.showFindIndicator(for: range)
}
/// update document observation for syntax style
private func observeDocument() {
if let observer = self.documentObserver {
NotificationCenter.default.removeObserver(observer)
}
guard let document = self.document else { return }
self.documentObserver = NotificationCenter.default.addObserver(forName: Document.didChangeSyntaxStyleNotification, object: document, queue: .main) { [weak self] (notification) in
self?.observeSyntaxStyle()
self?.outlineView?.reloadData()
}
}
/// update syntax style observation for outline menus
private func observeSyntaxStyle() {
if let observer = self.syntaxStyleObserver {
NotificationCenter.default.removeObserver(observer)
}
guard let syntaxStyle = self.document?.syntaxStyle else { return }
self.syntaxStyleObserver = NotificationCenter.default.addObserver(forName: SyntaxStyle.didUpdateOutlineNotification, object: syntaxStyle, queue: .main) { [weak self] (notification) in
self?.outlineView?.reloadData()
}
}
}
extension OutlineViewController: NSOutlineViewDelegate {
/// selection changed
func outlineViewSelectionDidChange(_ notification: Notification) {
guard let outlineView = notification.object as? NSOutlineView else { return }
self.selectOutlineItem(at: outlineView.selectedRow)
}
}
extension OutlineViewController: NSOutlineViewDataSource {
/// return number of child items
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
return self.outlineItems.count
}
/// return if item is expandable
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
return false
}
/// return child items
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
return self.outlineItems[index]
}
/// return suitable item for cell to display
func outlineView(_ outlineView: NSOutlineView, objectValueFor tableColumn: NSTableColumn?, byItem item: Any?) -> Any? {
guard
let identifier = tableColumn?.identifier,
let outlineItem = item as? OutlineItem
else { return nil }
switch identifier {
case .title:
let font: NSFont = outlineView.font ?? .systemFont(ofSize: NSFont.smallSystemFontSize)
return outlineItem.attributedTitle(for: font)
default:
return nil
}
}
}
// MARK: -
private extension OutlineItem {
func attributedTitle(for baseFont: NSFont) -> NSAttributedString {
var font = baseFont
var attributes: [NSAttributedStringKey: Any] = [:]
if self.style.contains(.bold) {
font = NSFontManager.shared.convert(font, toHaveTrait: .boldFontMask)
}
if self.style.contains(.italic) {
font = NSFontManager.shared.convert(font, toHaveTrait: .italicFontMask)
}
if self.style.contains(.underline) {
attributes[.underlineStyle] = NSUnderlineStyle.styleSingle.rawValue
}
attributes[.font] = font
return NSAttributedString(string: self.title, attributes: attributes)
}
}

View File

@ -38,6 +38,7 @@ final class SidebarViewController: NSTabViewController {
enum TabIndex: Int {
case documentInspector
case outline
case incompatibleCharacters
}
@ -51,6 +52,7 @@ final class SidebarViewController: NSTabViewController {
// MARK: Private Properties
@IBOutlet private weak var documentInspectorTabViewItem: NSTabViewItem?
@IBOutlet private weak var outlineTabViewItem: NSTabViewItem?
@IBOutlet private weak var incompatibleCharactersTabViewItem: NSTabViewItem?
@ -77,6 +79,7 @@ final class SidebarViewController: NSTabViewController {
guard let document = representedObject as? Document else { return }
self.documentInspectorTabViewItem?.viewController?.representedObject = document.analyzer
self.outlineTabViewItem?.viewController?.representedObject = document
self.incompatibleCharactersTabViewItem?.viewController?.representedObject = document.incompatibleCharacterScanner
}
}

View File

@ -27,6 +27,8 @@
/* Class = "NSTabViewItem"; label = "Document Inspector"; ObjectID = "Kfj-q6-61N"; */
"Kfj-q6-61N.label" = "Dokument-Informationen";
/* Class = "NSTabViewItem"; label = "Outline"; ObjectID = "hyM-2j-hen"; */
"hyM-2j-hen.label" = "Gliederung";
/* Class = "NSTabViewItem"; label = "Incompatible Characters"; ObjectID = "JZo-ok-Dks"; */
"JZo-ok-Dks.label" = "Inkompatible Zeichen";

View File

@ -0,0 +1,31 @@
//
// OutlineView.swift (German)
//
// CotEditor
// https://coteditor.com
//
// Created by 1024jp on 2018-02-27.
//
// ---------------------------------------------------------------------------
//
// © 2018 1024jp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/* Class = "NSTableColumn"; headerCell.title = "Title"; ObjectID = "CSX-H0-nFf"; */
"CSX-H0-nFf.headerCell.title" = "Titel";
/* Class = "NSTextFieldCell"; title = "Outline"; ObjectID = "RyV-wo-tpY"; */
"RyV-wo-tpY.title" = "Gliederung";

View File

@ -28,6 +28,8 @@
/* Class = "NSTabViewItem"; label = "Document Inspector"; ObjectID = "Kfj-q6-61N"; */
"Kfj-q6-61N.label" = "Ispettore del documento";
/* Class = "NSTabViewItem"; label = "Outline"; ObjectID = "hyM-2j-hen"; */
"hyM-2j-hen.label" = "Outline"; // FIXME: added
/* Class = "NSTabViewItem"; label = "Incompatible Characters"; ObjectID = "JZo-ok-Dks"; */
"JZo-ok-Dks.label" = "Caratteri incompatibili";

View File

@ -0,0 +1,31 @@
//
// OutlineView.swift (Italian)
//
// CotEditor
// https://coteditor.com
//
// Created by 1024jp on 2018-02-27.
//
// ---------------------------------------------------------------------------
//
// © 2018 1024jp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/* Class = "NSTableColumn"; headerCell.title = "Title"; ObjectID = "CSX-H0-nFf"; */
"CSX-H0-nFf.headerCell.title" = "Title"; // FIXME: added
/* Class = "NSTextFieldCell"; title = "Outline"; ObjectID = "RyV-wo-tpY"; */
"RyV-wo-tpY.title" = "Outline"; // FIXME: added

View File

@ -27,6 +27,8 @@
/* Class = "NSTabViewItem"; label = "Document Inspector"; ObjectID = "Kfj-q6-61N"; */
"Kfj-q6-61N.label" = "書類情報";
/* Class = "NSTabViewItem"; label = "Outline"; ObjectID = "hyM-2j-hen"; */
"hyM-2j-hen.label" = "アウトライン";
/* Class = "NSTabViewItem"; label = "Incompatible Characters"; ObjectID = "JZo-ok-Dks"; */
"JZo-ok-Dks.label" = "非互換文字";

View File

@ -0,0 +1,30 @@
//
// OutlineView.swift (Japanese)
//
// CotEditor
// https://coteditor.com
//
// Created by 1024jp on 2018-02-27.
//
// ---------------------------------------------------------------------------
//
// © 2018 1024jp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/* Class = "NSTableColumn"; headerCell.title = "Title"; ObjectID = "CSX-H0-nFf"; */
"CSX-H0-nFf.headerCell.title" = "タイトル";
/* Class = "NSTextFieldCell"; title = "Outline"; ObjectID = "RyV-wo-tpY"; */
"RyV-wo-tpY.title" = "アウトライン";

View File

@ -26,6 +26,8 @@
/* Class = "NSTabViewItem"; label = "Document Inspector"; ObjectID = "Kfj-q6-61N"; */
"Kfj-q6-61N.label" = "Inspetor do Documento";
/* Class = "NSTabViewItem"; label = "Outline"; ObjectID = "hyM-2j-hen"; */
"hyM-2j-hen.label" = "Outline"; // FIXME: added
/* Class = "NSTabViewItem"; label = "Incompatible Characters"; ObjectID = "JZo-ok-Dks"; */
"JZo-ok-Dks.label" = "Caracteres Incompatíveis";

View File

@ -0,0 +1,31 @@
//
// OutlineView.swift (Portuguese)
//
// CotEditor
// https://coteditor.com
//
// Created by 1024jp on 2018-02-27.
//
// ---------------------------------------------------------------------------
//
// © 2018 1024jp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/* Class = "NSTableColumn"; headerCell.title = "Title"; ObjectID = "CSX-H0-nFf"; */
"CSX-H0-nFf.headerCell.title" = "Title"; // FIXME: added
/* Class = "NSTextFieldCell"; title = "Outline"; ObjectID = "RyV-wo-tpY"; */
"RyV-wo-tpY.title" = "Outline"; // FIXME: added

View File

@ -28,6 +28,8 @@
/* Class = "NSTabViewItem"; label = "Document Inspector"; ObjectID = "Kfj-q6-61N"; */
"Kfj-q6-61N.label" = "文稿信息";
/* Class = "NSTabViewItem"; label = "Outline"; ObjectID = "hyM-2j-hen"; */
"hyM-2j-hen.label" = "Outline"; // FIXME: added
/* Class = "NSTabViewItem"; label = "Incompatible Characters"; ObjectID = "JZo-ok-Dks"; */
"JZo-ok-Dks.label" = "不兼容字符";

View File

@ -0,0 +1,31 @@
//
// OutlineView.swift (Simplified Chinese)
//
// CotEditor
// https://coteditor.com
//
// Created by 1024jp on 2018-02-27.
//
// ---------------------------------------------------------------------------
//
// © 2018 1024jp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/* Class = "NSTableColumn"; headerCell.title = "Title"; ObjectID = "CSX-H0-nFf"; */
"CSX-H0-nFf.headerCell.title" = "Title"; // FIXME: added
/* Class = "NSTextFieldCell"; title = "Outline"; ObjectID = "RyV-wo-tpY"; */
"RyV-wo-tpY.title" = "Outline"; // FIXME: added