diff --git a/OutlineViewTest/AppDelegate.swift b/OutlineViewTest/AppDelegate.swift
new file mode 100644
index 00000000..70213089
--- /dev/null
+++ b/OutlineViewTest/AppDelegate.swift
@@ -0,0 +1,169 @@
+//
+// AppDelegate.swift
+// OutlineViewTest
+//
+// Created by Tae Won Ha on 25/11/2016.
+// Copyright © 2016 Tae Won Ha. All rights reserved.
+//
+
+import Cocoa
+import PureLayout
+
+class Item {
+
+ let name: String
+ let children: [Item]
+
+ init(_ children: [Item]) {
+ self.name = Item.randomString(length: 75)
+ self.children = children
+ }
+
+ static func randomString(length: Int) -> String {
+
+ let letters: NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ let len = UInt32(letters.length)
+
+ var randomString = ""
+
+ for _ in 0 ..< length {
+ let rand = arc4random_uniform(len)
+ var nextChar = letters.character(at: Int(rand))
+ randomString += NSString(characters: &nextChar, length: 1) as String
+ }
+
+ return randomString + "-END"
+ }
+}
+
+@NSApplicationMain
+class AppDelegate: NSObject, NSOutlineViewDataSource, NSOutlineViewDelegate, NSApplicationDelegate {
+
+ @IBOutlet weak var window: NSWindow!
+
+ let outlineView = NSOutlineView.standardOutlineView()
+ let scrollView = NSScrollView.standardScrollView()
+
+ let data = Item([
+ Item([
+ Item([]),
+ Item([
+ Item([]), Item([]), Item([]),
+ ]),
+ ]), Item([
+ Item([]), Item([]), Item([]), Item([]),
+ ]),
+ Item([
+ Item([
+ Item([]), Item([]), Item([]), Item([]),
+ ]),
+
+ Item([
+ Item([]), Item([]),
+ ])
+
+ ]),
+ Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]), Item([]),
+ ])
+
+ func applicationDidFinishLaunching(_ aNotification: Notification) {
+ outlineView.dataSource = self
+ outlineView.delegate = self
+ outlineView.reloadData()
+
+ scrollView.documentView = outlineView
+ scrollView.borderType = .noBorder
+
+ let view = self.window.contentView!
+ view.addSubview(scrollView)
+ scrollView.autoPinEdgesToSuperviewEdges()
+ }
+
+ func outlineView(_: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
+ if item == nil {
+ return data.children.count
+ }
+
+ guard let a = item as? Item else {
+ return 0
+ }
+
+ return a.children.count
+ }
+
+ func adjustColumnWidth(for items: [Item], outlineViewLevel level: Int) {
+ let cellWidth = items.reduce(CGFloat(0)) { (curMaxWidth, item) in
+ let itemWidth = ImageAndTextTableCell.width(with: item.name)
+ if itemWidth > curMaxWidth {
+ return itemWidth
+ }
+
+ return curMaxWidth
+ }
+
+ let width = cellWidth + (CGFloat(level) * outlineView.indentationPerLevel)
+ let column = self.outlineView.outlineTableColumn!
+ guard column.minWidth < width else {
+ return
+ }
+
+ column.minWidth = width
+ column.maxWidth = width
+ }
+
+ func outlineView(_: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
+ let level = outlineView.level(forItem: item) + 2
+
+ if item == nil {
+ self.adjustColumnWidth(for: data.children, outlineViewLevel: level)
+ NSLog("nil: \(self.outlineView.level(forItem: nil))")
+ return data.children[index]
+ }
+
+
+ guard let a = item as? Item else {
+ preconditionFailure("Should not happen")
+ }
+
+ self.adjustColumnWidth(for: a.children, outlineViewLevel: level)
+ return a.children[index]
+ }
+
+ func outlineView(_: NSOutlineView, isItemExpandable item: Any) -> Bool {
+ return !(item as! Item).children.isEmpty
+ }
+
+ @objc(outlineView:objectValueForTableColumn:byItem:)
+ func outlineView(_: NSOutlineView, objectValueFor: NSTableColumn?, byItem item: Any?) -> Any? {
+ guard let a = item as? Item else {
+ return nil
+ }
+
+ return a
+ }
+
+ func outlineView(_: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {
+ return 20
+ }
+
+ @objc(outlineView:viewForTableColumn:item:)
+ func outlineView(_ view: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
+ guard let a = item as? Item else {
+ return nil
+ }
+
+ let cachedCell = view.make(withIdentifier: "row", owner: self)
+ let cell = cachedCell as? ImageAndTextTableCell ?? ImageAndTextTableCell(withIdentifier: "row")
+
+ cell.text = a.name
+
+ return cell
+ }
+
+ func outlineView(_ outlineView: NSOutlineView,
+ didAdd rowView: NSTableRowView,
+ forRow row: Int)
+ {
+ }
+}
+
diff --git a/OutlineViewTest/Assets.xcassets/AppIcon.appiconset/Contents.json b/OutlineViewTest/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..2db2b1c7
--- /dev/null
+++ b/OutlineViewTest/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,58 @@
+{
+ "images" : [
+ {
+ "idiom" : "mac",
+ "size" : "16x16",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "16x16",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "32x32",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "32x32",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "128x128",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "128x128",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "256x256",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "256x256",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "512x512",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "512x512",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/OutlineViewTest/Base.lproj/MainMenu.xib b/OutlineViewTest/Base.lproj/MainMenu.xib
new file mode 100644
index 00000000..dd6ae572
--- /dev/null
+++ b/OutlineViewTest/Base.lproj/MainMenu.xib
@@ -0,0 +1,694 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OutlineViewTest/Info.plist b/OutlineViewTest/Info.plist
new file mode 100644
index 00000000..27a22532
--- /dev/null
+++ b/OutlineViewTest/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ Copyright © 2016 Tae Won Ha. All rights reserved.
+ NSMainNibFile
+ MainMenu
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/VimR.xcodeproj/project.pbxproj b/VimR.xcodeproj/project.pbxproj
index c9acbf8f..1ec2b43f 100644
--- a/VimR.xcodeproj/project.pbxproj
+++ b/VimR.xcodeproj/project.pbxproj
@@ -76,6 +76,13 @@
4B705BA11DDF7639005F844B /* ToolPrefData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B705BA01DDF7639005F844B /* ToolPrefData.swift */; };
4B705BDA1DE04F83005F844B /* Pref38To128Converter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B705BD91DE04F83005F844B /* Pref38To128Converter.swift */; };
4B705C0E1DE2167A005F844B /* BufferListComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B705C0D1DE2167A005F844B /* BufferListComponent.swift */; };
+ 4B81B3CB1DE8827600ED1672 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B81B3CA1DE8827600ED1672 /* AppDelegate.swift */; };
+ 4B81B3CD1DE8827600ED1672 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4B81B3CC1DE8827600ED1672 /* Assets.xcassets */; };
+ 4B81B3D01DE8827600ED1672 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B81B3CE1DE8827600ED1672 /* MainMenu.xib */; };
+ 4B81B3D51DE8827E00ED1672 /* PureLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B401B131D0454DC00D99EDC /* PureLayout.framework */; };
+ 4B81B3D61DE8827E00ED1672 /* PureLayout.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B401B131D0454DC00D99EDC /* PureLayout.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 4B81B3D81DE8829500ED1672 /* ImageAndTextTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B22F7F11D7C6B9000929B0E /* ImageAndTextTableCell.swift */; };
+ 4B81B3D91DE882D500ED1672 /* AppKitCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70931D60E04200E12030 /* AppKitCommons.swift */; };
4B854A1D1D31447C00E08DE1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B854A1C1D31447C00E08DE1 /* main.m */; };
4B8AC0441DBCB3A2007CCC9B /* NeoVimObjectsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8AC0431DBCB3A1007CCC9B /* NeoVimObjectsExtensions.swift */; };
4B97E2CC1D33F53D00FC0660 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B97E2CE1D33F53D00FC0660 /* MainWindow.xib */; };
@@ -205,6 +212,17 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 4B81B3D71DE8827E00ED1672 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 4B81B3D61DE8827E00ED1672 /* PureLayout.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
4B854A061D3137B500E08DE1 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -304,6 +322,11 @@
4B705BA01DDF7639005F844B /* ToolPrefData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToolPrefData.swift; sourceTree = ""; };
4B705BD91DE04F83005F844B /* Pref38To128Converter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pref38To128Converter.swift; sourceTree = ""; };
4B705C0D1DE2167A005F844B /* BufferListComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferListComponent.swift; sourceTree = ""; };
+ 4B81B3C81DE8827600ED1672 /* OutlineViewTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OutlineViewTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B81B3CA1DE8827600ED1672 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 4B81B3CC1DE8827600ED1672 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 4B81B3CF1DE8827600ED1672 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
+ 4B81B3D11DE8827600ED1672 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
4B854A1A1D31447C00E08DE1 /* NeoVimServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NeoVimServer; sourceTree = BUILT_PRODUCTS_DIR; };
4B854A1C1D31447C00E08DE1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
4B8AC0431DBCB3A1007CCC9B /* NeoVimObjectsExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimObjectsExtensions.swift; sourceTree = ""; };
@@ -387,6 +410,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 4B81B3C51DE8827600ED1672 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4B81B3D51DE8827E00ED1672 /* PureLayout.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
4B854A171D31447C00E08DE1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -561,6 +592,17 @@
name = Tools;
sourceTree = "";
};
+ 4B81B3C91DE8827600ED1672 /* OutlineViewTest */ = {
+ isa = PBXGroup;
+ children = (
+ 4B81B3CA1DE8827600ED1672 /* AppDelegate.swift */,
+ 4B81B3CC1DE8827600ED1672 /* Assets.xcassets */,
+ 4B81B3CE1DE8827600ED1672 /* MainMenu.xib */,
+ 4B81B3D11DE8827600ED1672 /* Info.plist */,
+ );
+ path = OutlineViewTest;
+ sourceTree = "";
+ };
4B854A151D31444800E08DE1 /* resources */ = {
isa = PBXGroup;
children = (
@@ -666,6 +708,7 @@
4B56F2911D29903F00C1F92E /* SwiftNeoVimTests */,
4B854A1B1D31447C00E08DE1 /* NeoVimServer */,
4B6423A01D8EFE7500FC78C8 /* VimR-Workspace-Demo */,
+ 4B81B3C91DE8827600ED1672 /* OutlineViewTest */,
4B2A2BE61D0225840074CE9A /* Frameworks */,
4BEBA5061CFF374B00673FDF /* Products */,
);
@@ -680,6 +723,7 @@
4B56F2901D29903F00C1F92E /* SwiftNeoVimTests.xctest */,
4B854A1A1D31447C00E08DE1 /* NeoVimServer */,
4B64239F1D8EFE7500FC78C8 /* VimR-Workspace-Demo.app */,
+ 4B81B3C81DE8827600ED1672 /* OutlineViewTest.app */,
);
name = Products;
sourceTree = "";
@@ -819,6 +863,24 @@
productReference = 4B64239F1D8EFE7500FC78C8 /* VimR-Workspace-Demo.app */;
productType = "com.apple.product-type.application";
};
+ 4B81B3C71DE8827600ED1672 /* OutlineViewTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4B81B3D41DE8827600ED1672 /* Build configuration list for PBXNativeTarget "OutlineViewTest" */;
+ buildPhases = (
+ 4B81B3C41DE8827600ED1672 /* Sources */,
+ 4B81B3C51DE8827600ED1672 /* Frameworks */,
+ 4B81B3C61DE8827600ED1672 /* Resources */,
+ 4B81B3D71DE8827E00ED1672 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = OutlineViewTest;
+ productName = OutlineViewTest;
+ productReference = 4B81B3C81DE8827600ED1672 /* OutlineViewTest.app */;
+ productType = "com.apple.product-type.application";
+ };
4B854A191D31447C00E08DE1 /* NeoVimServer */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4B854A1E1D31447C00E08DE1 /* Build configuration list for PBXNativeTarget "NeoVimServer" */;
@@ -881,7 +943,7 @@
4BEBA4FD1CFF374B00673FDF /* Project object */ = {
isa = PBXProject;
attributes = {
- LastSwiftUpdateCheck = 0730;
+ LastSwiftUpdateCheck = 0810;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = "Tae Won Ha";
TargetAttributes = {
@@ -898,6 +960,10 @@
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 0800;
};
+ 4B81B3C71DE8827600ED1672 = {
+ CreatedOnToolsVersion = 8.1;
+ ProvisioningStyle = Automatic;
+ };
4B854A191D31447C00E08DE1 = {
CreatedOnToolsVersion = 7.3.1;
};
@@ -932,6 +998,7 @@
4B56F28F1D29903F00C1F92E /* SwiftNeoVimTests */,
4B854A191D31447C00E08DE1 /* NeoVimServer */,
4B64239E1D8EFE7500FC78C8 /* VimR-Workspace-Demo */,
+ 4B81B3C71DE8827600ED1672 /* OutlineViewTest */,
);
};
/* End PBXProject section */
@@ -961,6 +1028,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 4B81B3C61DE8827600ED1672 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4B81B3CD1DE8827600ED1672 /* Assets.xcassets in Resources */,
+ 4B81B3D01DE8827600ED1672 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
4BEBA5031CFF374B00673FDF /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1048,6 +1124,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 4B81B3C41DE8827600ED1672 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4B81B3D91DE882D500ED1672 /* AppKitCommons.swift in Sources */,
+ 4B81B3D81DE8829500ED1672 /* ImageAndTextTableCell.swift in Sources */,
+ 4B81B3CB1DE8827600ED1672 /* AppDelegate.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
4B854A161D31447C00E08DE1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1163,6 +1249,14 @@
name = MainMenu.xib;
sourceTree = "";
};
+ 4B81B3CE1DE8827600ED1672 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 4B81B3CF1DE8827600ED1672 /* Base */,
+ );
+ name = MainMenu.xib;
+ sourceTree = "";
+ };
4B97E2CE1D33F53D00FC0660 /* MainWindow.xib */ = {
isa = PBXVariantGroup;
children = (
@@ -1315,6 +1409,49 @@
};
name = Release;
};
+ 4B81B3D21DE8827600ED1672 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVES = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Carthage/Build/Mac",
+ );
+ INFOPLIST_FILE = OutlineViewTest/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ PRODUCT_BUNDLE_IDENTIFIER = com.qvacua.OutlineViewTest;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_VERSION = 3.0;
+ };
+ name = Debug;
+ };
+ 4B81B3D31DE8827600ED1672 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVES = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Carthage/Build/Mac",
+ );
+ INFOPLIST_FILE = OutlineViewTest/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ PRODUCT_BUNDLE_IDENTIFIER = com.qvacua.OutlineViewTest;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 3.0;
+ };
+ name = Release;
+ };
4B854A1F1D31447C00E08DE1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1559,6 +1696,14 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 4B81B3D41DE8827600ED1672 /* Build configuration list for PBXNativeTarget "OutlineViewTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4B81B3D21DE8827600ED1672 /* Debug */,
+ 4B81B3D31DE8827600ED1672 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
4B854A1E1D31447C00E08DE1 /* Build configuration list for PBXNativeTarget "NeoVimServer" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/VimR/AppKitCommons.swift b/VimR/AppKitCommons.swift
index 450d10a6..4fdb08c3 100644
--- a/VimR/AppKitCommons.swift
+++ b/VimR/AppKitCommons.swift
@@ -118,6 +118,7 @@ extension NSOutlineView {
static func configure(toStandard outlineView: NSOutlineView) {
let column = NSTableColumn(identifier: "name")
+ column.resizingMask = .autoresizingMask
column.isEditable = false
outlineView.addTableColumn(column)
diff --git a/VimR/FileBrowserComponent.swift b/VimR/FileBrowserComponent.swift
index 535d1b11..7728ddf0 100644
--- a/VimR/FileBrowserComponent.swift
+++ b/VimR/FileBrowserComponent.swift
@@ -90,7 +90,7 @@ class FileBrowserComponent: ViewComponent {
guard self.fileView.row(forItem: fileItem) > -1 else {
return
}
-
+
// FIXME: restore expanded states
self.fileView.reloadItem(fileItem, reloadChildren: true)
}
diff --git a/VimR/FileOutlineView.swift b/VimR/FileOutlineView.swift
index 6fb01c96..00a3eff3 100644
--- a/VimR/FileOutlineView.swift
+++ b/VimR/FileOutlineView.swift
@@ -4,6 +4,7 @@
*/
import Cocoa
+import PureLayout
import RxSwift
enum FileOutlineViewAction {
@@ -78,6 +79,28 @@ class FileOutlineView: NSOutlineView, Flow, NSOutlineViewDataSource, NSOutlineVi
self.doubleAction = #selector(FileOutlineView.doubleClickAction)
}
+
+ @IBAction func debug1(_ sender: Any?) {
+ let size = self.frame.size
+ self.setFrameSize(CGSize(width: 700, height: size.height))
+ }
+}
+
+extension FileOutlineView {
+
+ override func reloadItem(_ item: Any?, reloadChildren: Bool) {
+ NSLog("\(#function)")
+ super.reloadItem(item, reloadChildren: reloadChildren)
+
+ self.adjustFileViewWidth()
+ }
+
+ override func reloadItem(_ item: Any?) {
+ NSLog("\(#function)")
+ super.reloadItem(item)
+
+ self.adjustFileViewWidth()
+ }
}
// MARK: - NSOutlineViewDataSource
@@ -140,6 +163,82 @@ extension FileOutlineView {
// MARK: - NSOutlineViewDelegate
extension FileOutlineView {
+ fileprivate func adjustFileViewWidth() {
+ let indentationPerLevel = self.indentationPerLevel
+ let attrs = [NSFontAttributeName: ImageAndTextTableCell.font]
+
+ let maxWidth = (0 ..< self.numberOfRows).reduce(CGFloat(0)) { (curMaxWidth, idx) in
+ guard let cell = self.rowView(atRow: idx, makeIfNecessary: false)?.view(atColumn: 0) as? ImageAndTextTableCell
+ else {
+ return curMaxWidth
+ }
+
+ guard let item = self.item(atRow: idx) as? FileBrowserItem else {
+ return curMaxWidth
+ }
+
+ let level = CGFloat(self.level(forRow: idx) + 1)
+ let indentation = level * (indentationPerLevel + 20)
+ let name = item.fileItem.url.lastPathComponent
+ let textWidth = (name as NSString).size(withAttributes: attrs).width + indentation
+
+ let width = indentation + ImageAndTextTableCell.widthWithoutText + textWidth
+ return max(curMaxWidth, width)
+ }
+
+ let column = self.outlineTableColumn!
+ Swift.print("\(column.width) vs \(maxWidth)")
+ guard column.minWidth < maxWidth else {
+ return
+ }
+
+ column.minWidth = maxWidth
+ column.maxWidth = column.minWidth
+ (0 ..< self.numberOfRows).forEach {
+ self.rowView(atRow: $0, makeIfNecessary: false)?.needsDisplay = true
+ }
+ }
+
+// func outlineView(_ outlineView: NSOutlineView,
+// didAdd rowView: NSTableRowView,
+// forRow row: Int)
+// {
+// guard let cell = rowView.view(atColumn: 0) as? ImageAndTextTableCell else {
+// return
+// }
+// let column = self.outlineTableColumn!
+// DispatchUtils.gui {
+// let width = max(column.width, rowView.frame.width)
+// self.setFrameSize(CGSize(width: width, height:self.frame.height))
+//// column.minWidth = max(column.width, rowView.frame.width)
+//// column.maxWidth = column.minWidth
+//// column.width = column.minWidth
+//// rowView.needsDisplay = true
+// }
+//
+// NSLog("\(#function): \(rowView.frame.width) vs \(cell.intrinsicContentSize.width)")
+////
+//// let level = CGFloat(self.level(forRow: row) + 1)
+//// let indentation = level * self.indentationPerLevel
+//// let width = indentation + cell.intrinsicContentSize.width
+//// let height = cell.intrinsicContentSize.height
+////
+////// let column = self.outlineTableColumn!
+////// guard column.width < width else {
+////// return
+////// }
+////
+//// cell.configureForAutoLayout()
+//// cell.autoSetDimension(.width, toSize: width)
+//// cell.autoSetDimension(.height, toSize: height)
+//// cell.autoPinEdge(toSuperviewEdge: .left)
+//// cell.autoPinEdge(toSuperviewEdge: .right)
+//// Swift.print("\(cell.text): \(cell.frame.width)")
+////// column.width = width
+////// column.minWidth = width
+////// column.maxWidth = width
+// }
+
@objc(outlineView:viewForTableColumn:item:)
func outlineView(_: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
guard let fileBrowserItem = item as? FileBrowserItem else {
@@ -163,12 +262,16 @@ extension FileOutlineView {
if let item = notification.userInfo?["NSObject"] as? FileBrowserItem {
item.isExpanded = true
}
+
+ self.adjustFileViewWidth()
}
func outlineViewItemDidCollapse(_ notification: Notification) {
if let item = notification.userInfo?["NSObject"] as? FileBrowserItem {
item.isExpanded = false
}
+
+ self.adjustFileViewWidth()
}
}
diff --git a/VimR/ImageAndTextTableCell.swift b/VimR/ImageAndTextTableCell.swift
index a54bc565..23c43fec 100644
--- a/VimR/ImageAndTextTableCell.swift
+++ b/VimR/ImageAndTextTableCell.swift
@@ -14,16 +14,28 @@ class ImageAndTextTableCell: NSTableCellView {
fileprivate let _textField = NSTextField(forAutoLayout: ())
fileprivate let _imageView = NSImageView(forAutoLayout: ())
+ static func width(with text: String) -> CGFloat {
+ let attrStr = NSAttributedString(string: text,
+ attributes: [NSFontAttributeName: ImageAndTextTableCell.font])
+
+ return self.widthWithoutText + attrStr.size().width
+ }
+
+ override var intrinsicContentSize: CGSize {
+ return CGSize(width: ImageAndTextTableCell.widthWithoutText + self._textField.intrinsicContentSize.width,
+ height: max(self._textField.intrinsicContentSize.height, 16))
+ }
+
var attributedText: NSAttributedString {
get {
return self.textField!.attributedStringValue
}
-
+
set {
self.textField?.attributedStringValue = newValue
}
}
-
+
var text: String {
get {
return self.textField!.stringValue
@@ -46,7 +58,7 @@ class ImageAndTextTableCell: NSTableCellView {
init(withIdentifier identifier: String) {
super.init(frame: CGRect.zero)
-
+
self.identifier = identifier
self.textField = self._textField
@@ -70,13 +82,13 @@ class ImageAndTextTableCell: NSTableCellView {
imageView.autoPinEdge(toSuperviewEdge: .left, withInset: 2)
imageView.autoSetDimension(.width, toSize: 16)
imageView.autoSetDimension(.height, toSize: 16)
-
+
textField.autoPinEdge(toSuperviewEdge: .top, withInset: 2)
textField.autoPinEdge(toSuperviewEdge: .right, withInset: 2)
textField.autoPinEdge(toSuperviewEdge: .bottom, withInset: 2)
textField.autoPinEdge(.left, to: .right, of: imageView, withOffset: 4)
}
-
+
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}