mirror of
https://github.com/qvacua/vimr.git
synced 2024-12-25 06:43:24 +03:00
List all menu items
This commit is contained in:
parent
23ef772e2b
commit
27d4972c15
2
Cartfile
2
Cartfile
@ -10,6 +10,6 @@ github "sindresorhus/github-markdown-css" == 3.0.1
|
||||
github "httpswift/swifter" == 1.4.5
|
||||
github "a2/MessagePack.swift" == 3.0.0
|
||||
github "elegantchaos/DictionaryCoding" == 1.0.6
|
||||
github "Kentzo/ShortcutRecorder" == 2.17.2
|
||||
github "qvacua/ShortcutRecorder" "master"
|
||||
|
||||
github "Quick/Nimble" == 7.3.4
|
||||
|
@ -1,5 +1,4 @@
|
||||
github "IBM-Swift/BlueSocket" "1.0.44"
|
||||
github "Kentzo/ShortcutRecorder" "2.17.2"
|
||||
github "PureLayout/PureLayout" "v3.1.4"
|
||||
github "Quick/Nimble" "v7.3.4"
|
||||
github "ReactiveX/RxSwift" "4.4.1"
|
||||
@ -12,5 +11,6 @@ github "qvacua/CocoaMarkdown" "7756ad96d5fb390c66531004868e828bb54d3609"
|
||||
github "qvacua/RxMessagePort" "v0.0.5"
|
||||
github "qvacua/RxMsgpackRpc" "v0.0.7"
|
||||
github "qvacua/RxNeovimApi" "0.3.4"
|
||||
github "qvacua/ShortcutRecorder" "c978ce9bb482c31acfabe23baa2b075808a1fdd8"
|
||||
github "sindresorhus/github-markdown-css" "v3.0.1"
|
||||
github "sparkle-project/Sparkle" "1.21.3"
|
||||
|
@ -7,11 +7,14 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1929B02DAC94F0E47CFC8EA2 /* ShortcutsTableSubviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BCF66D08CC02A9233A88 /* ShortcutsTableSubviews.swift */; };
|
||||
1929B04CE8ECBD75CBBB0991 /* StringCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5D45C9792BBE76B8AFF /* StringCommonsTest.swift */; };
|
||||
1929B05B9D664052EC2D23EF /* FileOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BCE3E156C06EDF1F2806 /* FileOutlineView.swift */; };
|
||||
1929B083D2176A9C615B8807 /* ShortcutsPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BD256AA54518D37D6CBB /* ShortcutsPref.swift */; };
|
||||
1929B08C6230B9C5AB72DAF1 /* Pref128ToCurrentConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5046239709E33516F5C /* Pref128ToCurrentConverter.swift */; };
|
||||
1929B0E0C3BC59F52713D5A2 /* FoundationCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */; };
|
||||
1929B0F599D1F62C7BE53D2C /* HttpServerMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1DC584C89C477E83FA2 /* HttpServerMiddleware.swift */; };
|
||||
1929B148AA06340F22533377 /* ShortcutItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1E4B11A92D8DD171D93 /* ShortcutItem.swift */; };
|
||||
1929B1837C750CADB3A5BCB9 /* OpenQuicklyFileViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1558455B3A74D93EF2A /* OpenQuicklyFileViewRow.swift */; };
|
||||
1929B20CE35B43BB1CE023BA /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BC2F05E9A5C0DB039739 /* Theme.swift */; };
|
||||
1929B29B95AD176D57942E08 /* UiRootReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B457B9D0FA4D21F3751E /* UiRootReducer.swift */; };
|
||||
@ -25,6 +28,7 @@
|
||||
1929B462CD4935AFF6D69457 /* FileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7CB4863F80230C32D3C /* FileItem.swift */; };
|
||||
1929B4B00D7BB191A9A6532D /* HtmlPreviewToolReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE5AEA3D0980860EED50 /* HtmlPreviewToolReducer.swift */; };
|
||||
1929B4B70926DE113E6BF990 /* PreviewReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE37AA2843779CAFA76F /* PreviewReducer.swift */; };
|
||||
1929B4DD667E1E57EFA2AA57 /* ShortcutItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1E4B11A92D8DD171D93 /* ShortcutItem.swift */; };
|
||||
1929B4E54E2F13A7F5F2B682 /* BufferListReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B67A10E6BB2986B2416E /* BufferListReducer.swift */; };
|
||||
1929B4F0612224E594E89B92 /* AppearancePref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0FBFB766042CF06E463 /* AppearancePref.swift */; };
|
||||
1929B4FEE6EB56EF3F56B805 /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B34FC23D805A8B29E8F7 /* Context.swift */; };
|
||||
@ -56,6 +60,7 @@
|
||||
1929B990A143763A56CFCED0 /* PrefMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B364460D86F17E80943C /* PrefMiddleware.swift */; };
|
||||
1929BA715337FE26155B2071 /* BufferList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA43449BA41666CD55ED /* BufferList.swift */; };
|
||||
1929BA76A1D97D8226F7CFB1 /* Debouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B6AD3396160AA2C46919 /* Debouncer.swift */; };
|
||||
1929BA8E1A7C425E0E03EB40 /* ShortcutsTableSubviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BCF66D08CC02A9233A88 /* ShortcutsTableSubviews.swift */; };
|
||||
1929BAAD7336FDFF1F78E749 /* ScorerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF69B01107F358CF7EAD /* ScorerTest.swift */; };
|
||||
1929BAE4900D72A7877741B1 /* PrefWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE168F31344B69E61B62 /* PrefWindow.swift */; };
|
||||
1929BAFF1E011321D3186EE6 /* UiRoot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BD4149D5A25C82064DD8 /* UiRoot.swift */; };
|
||||
@ -296,6 +301,7 @@
|
||||
1929B14A5949FB64C4B2646F /* KeysPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeysPref.swift; sourceTree = "<group>"; };
|
||||
1929B1558455B3A74D93EF2A /* OpenQuicklyFileViewRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyFileViewRow.swift; sourceTree = "<group>"; };
|
||||
1929B1DC584C89C477E83FA2 /* HttpServerMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpServerMiddleware.swift; sourceTree = "<group>"; };
|
||||
1929B1E4B11A92D8DD171D93 /* ShortcutItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutItem.swift; sourceTree = "<group>"; };
|
||||
1929B34FC23D805A8B29E8F7 /* Context.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Context.swift; sourceTree = "<group>"; };
|
||||
1929B364460D86F17E80943C /* PrefMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefMiddleware.swift; sourceTree = "<group>"; };
|
||||
1929B365A6434354B568B04F /* FileMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileMonitor.swift; sourceTree = "<group>"; };
|
||||
@ -340,6 +346,8 @@
|
||||
1929BBE0A534F2F6009D31BE /* AdvencedPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvencedPref.swift; sourceTree = "<group>"; };
|
||||
1929BC2F05E9A5C0DB039739 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
|
||||
1929BCE3E156C06EDF1F2806 /* FileOutlineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileOutlineView.swift; sourceTree = "<group>"; };
|
||||
1929BCF66D08CC02A9233A88 /* ShortcutsTableSubviews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsTableSubviews.swift; sourceTree = "<group>"; };
|
||||
1929BD256AA54518D37D6CBB /* ShortcutsPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsPref.swift; sourceTree = "<group>"; };
|
||||
1929BD2CA8DD198A6BCDBCB7 /* ThemedTableSubviews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemedTableSubviews.swift; sourceTree = "<group>"; };
|
||||
1929BD4149D5A25C82064DD8 /* UiRoot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiRoot.swift; sourceTree = "<group>"; };
|
||||
1929BD83A13BF133741766CC /* MainWindowReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindowReducer.swift; sourceTree = "<group>"; };
|
||||
@ -593,6 +601,7 @@
|
||||
1929B5E773BDB3B4EE9D00C1 /* Reducers */,
|
||||
1929BFA93DC859DD76C46192 /* Middlewares */,
|
||||
1929BFC0A5A9C6DB09BE1368 /* Types.swift */,
|
||||
1929B1E4B11A92D8DD171D93 /* ShortcutItem.swift */,
|
||||
);
|
||||
name = UI;
|
||||
sourceTree = "<group>";
|
||||
@ -631,6 +640,8 @@
|
||||
1929BBE0A534F2F6009D31BE /* AdvencedPref.swift */,
|
||||
1929BB2AD21A10A0ECA66A5E /* ToolsPref.swift */,
|
||||
1929B14A5949FB64C4B2646F /* KeysPref.swift */,
|
||||
1929BD256AA54518D37D6CBB /* ShortcutsPref.swift */,
|
||||
1929BCF66D08CC02A9233A88 /* ShortcutsTableSubviews.swift */,
|
||||
);
|
||||
name = Preferences;
|
||||
sourceTree = "<group>";
|
||||
@ -1147,6 +1158,9 @@
|
||||
1929B8F498D1E7C53F572CE2 /* KeysPref.swift in Sources */,
|
||||
1929B5A2EE366F79ED32744C /* KeysPrefReducer.swift in Sources */,
|
||||
1929BB67CAAD4F6CBD38DF0A /* RxRedux.swift in Sources */,
|
||||
1929B083D2176A9C615B8807 /* ShortcutsPref.swift in Sources */,
|
||||
1929B4DD667E1E57EFA2AA57 /* ShortcutItem.swift in Sources */,
|
||||
1929B02DAC94F0E47CFC8EA2 /* ShortcutsTableSubviews.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1178,6 +1192,8 @@
|
||||
1929B8E90A1378E494D481E7 /* PrefUtilsTest.swift in Sources */,
|
||||
1929B20CE35B43BB1CE023BA /* Theme.swift in Sources */,
|
||||
1929B9318D32146D58BB38EC /* AppKitCommons.swift in Sources */,
|
||||
1929B148AA06340F22533377 /* ShortcutItem.swift in Sources */,
|
||||
1929BA8E1A7C425E0E03EB40 /* ShortcutsTableSubviews.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -9,6 +9,8 @@ import PureLayout
|
||||
import Sparkle
|
||||
import CocoaFontAwesome
|
||||
|
||||
let debugMenuItemIdentifier = NSUserInterfaceItemIdentifier("debug-menu-item")
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
|
||||
|
||||
@ -60,12 +62,41 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
||||
self.openNewMainWindowOnReactivation = initialAppState.openNewMainWindowOnReactivation
|
||||
self.useSnapshot = initialAppState.useSnapshotUpdate
|
||||
|
||||
let source = self.context.stateSource
|
||||
self.uiRoot = UiRoot(source: source, emitter: self.context.actionEmitter, state: initialAppState)
|
||||
|
||||
super.init()
|
||||
|
||||
NSUserNotificationCenter.default.delegate = self
|
||||
// FIXME: GH-611: https://github.com/qvacua/vimr/issues/611
|
||||
// Check whether FontAwesome can be loaded. If not, show a warning.
|
||||
// We don't know yet why this happens to some users.
|
||||
DispatchQueue.main.async {
|
||||
guard NSFont.fontAwesome(ofSize: 13) == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
let notification = NSUserNotification()
|
||||
notification.title = "FontAwesome could not be loaded."
|
||||
notification.subtitle = "Unfortunately we don't know yet what is causing this."
|
||||
notification.informativeText = """
|
||||
We use the FontAwesome font for icons in the tools, e.g. the file browser. Those icons are now shown as ?.
|
||||
You can track the progress on this issue at GitHub issue 611.
|
||||
"""
|
||||
NSUserNotificationCenter.default.deliver(notification)
|
||||
}
|
||||
}
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
let source = self.context.stateSource
|
||||
|
||||
// We want to build the menu items tree at some point, eg in the init() of
|
||||
// ShortcutsPref. We have to do that *after* the MainMenu.xib is loaded.
|
||||
// Therefore, we use optional var for the self.uiRoot. Ugly, but, well...
|
||||
self.uiRoot = UiRoot(
|
||||
source: source,
|
||||
emitter: self.context.actionEmitter,
|
||||
state: self.context.state
|
||||
)
|
||||
|
||||
source
|
||||
.observeOn(MainScheduler.instance)
|
||||
@ -86,30 +117,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
||||
}
|
||||
})
|
||||
.disposed(by: self.disposeBag)
|
||||
|
||||
// FIXME: GH-611: https://github.com/qvacua/vimr/issues/611
|
||||
// Check whether FontAwesome can be loaded. If not, show a warning.
|
||||
// We don't know yet why this happens to some users.
|
||||
DispatchQueue.main.async {
|
||||
guard NSFont.fontAwesome(ofSize: 13) == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
let notification = NSUserNotification()
|
||||
notification.title = "FontAwesome could not be loaded."
|
||||
notification.subtitle = "Unfortunately we don't know yet what is causing this."
|
||||
notification.informativeText = """
|
||||
We use the FontAwesome font for icons in the tools, e.g. the file browser. Those icons are now shown as ?.
|
||||
You can track the progress on this issue at GitHub issue 611.
|
||||
"""
|
||||
NSUserNotificationCenter.default.deliver(notification)
|
||||
}
|
||||
}
|
||||
|
||||
private let context: Context
|
||||
private let emit: (Action) -> Void
|
||||
|
||||
private let uiRoot: UiRoot
|
||||
private var uiRoot: UiRoot?
|
||||
|
||||
private var hasDirtyWindows = false
|
||||
private var hasMainWindows = false
|
||||
@ -151,9 +164,12 @@ extension AppDelegate {
|
||||
func applicationDidFinishLaunching(_: Notification) {
|
||||
self.launching = false
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG
|
||||
NSApp.mainMenu?.items.first { $0.identifier == debugMenuItemIdentifier }?.isHidden = false
|
||||
#endif
|
||||
|
||||
// GH-314 FIXME: Remove when finished.
|
||||
self.showPrefWindow(self)
|
||||
#endif
|
||||
}
|
||||
|
||||
func applicationOpenUntitledFile(_ sender: NSApplication) -> Bool {
|
||||
@ -186,7 +202,7 @@ extension AppDelegate {
|
||||
|
||||
if alert.runModal() == .alertSecondButtonReturn {
|
||||
self.updateMainWindowTemplateBeforeQuitting()
|
||||
self.uiRoot.prepareQuit()
|
||||
self.uiRoot?.prepareQuit()
|
||||
return .terminateNow
|
||||
}
|
||||
|
||||
@ -195,7 +211,7 @@ extension AppDelegate {
|
||||
|
||||
if self.hasMainWindows {
|
||||
self.updateMainWindowTemplateBeforeQuitting()
|
||||
self.uiRoot.prepareQuit()
|
||||
self.uiRoot?.prepareQuit()
|
||||
return .terminateNow
|
||||
}
|
||||
|
||||
@ -414,8 +430,6 @@ private enum VimRUrlAction: String {
|
||||
|
||||
private let updater = SUUpdater()
|
||||
|
||||
private let debugMenuItemIdentifier = NSUserInterfaceItemIdentifier("debug-menu-item")
|
||||
|
||||
// Keep in sync with QueryParamKey in the `vimr` Python script.
|
||||
private let filePrefix = "file="
|
||||
private let cwdPrefix = "cwd="
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" 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="13771"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="Application" customModule="VimR" customModuleProvider="target">
|
||||
@ -73,45 +73,45 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
||||
<menuItem title="New" keyEquivalent="n" identifier="com.qvacua.vimr.menuitems.file.new" id="Was-JA-tGl">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="New Tab" keyEquivalent="t" id="TX9-92-Oe2">
|
||||
<menuItem title="New Tab" keyEquivalent="t" identifier="com.qvacua.vimr.menuitems.file.new-tab" id="TX9-92-Oe2">
|
||||
<connections>
|
||||
<action selector="newTab:" target="-1" id="RfK-C0-Bu9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="t9v-Ee-SaA"/>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<menuItem title="Open…" keyEquivalent="o" identifier="com.qvacua.vimr.menuitems.file.open" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="zbe-h0-oBM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open In New Window…" keyEquivalent="o" id="c6W-bD-wRy">
|
||||
<menuItem title="Open In New Window…" keyEquivalent="o" identifier="com.qvacua.vimr.menuitems.file.open-in-new-window" id="c6W-bD-wRy">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="openInNewWindow:" target="-1" id="2ZC-Rl-rjR"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Quickly…" keyEquivalent="O" id="0V2-yi-P2z">
|
||||
<menuItem title="Open Quickly…" keyEquivalent="O" identifier="com.qvacua.vimr.menuitems.file.open-quickly" id="0V2-yi-P2z">
|
||||
<connections>
|
||||
<action selector="openQuickly:" target="-1" id="FSA-7W-F0m"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Lje-kE-tCa"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<menuItem title="Close" keyEquivalent="w" identifier="com.qvacua.vimr.menuitems.file.close" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save..." keyEquivalent="s" id="Pgi-pt-dWC">
|
||||
<menuItem title="Save..." keyEquivalent="s" identifier="com.qvacua.vimr.menuitems.file.save" id="Pgi-pt-dWC">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="Qhz-Mg-Anr"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="01H-3e-ZCV">
|
||||
<menuItem title="Save As…" keyEquivalent="S" identifier="com.qvacua.vimr.menuitems.file.save-as" id="01H-3e-ZCV">
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="-1" id="2iM-rb-3fJ"/>
|
||||
</connections>
|
||||
@ -123,39 +123,39 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<menuItem title="Undo" keyEquivalent="z" identifier="com.qvacua.vimr.menuitems.edit.undo" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<menuItem title="Redo" keyEquivalent="Z" identifier="com.qvacua.vimr.menuitems.edit.redo" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<menuItem title="Cut" keyEquivalent="x" identifier="com.qvacua.vimr.menuitems.edit.cut" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<menuItem title="Copy" keyEquivalent="c" identifier="com.qvacua.vimr.menuitems.edit.copy" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<menuItem title="Paste" keyEquivalent="v" identifier="com.qvacua.vimr.menuitems.edit.paste" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<menuItem title="Delete" identifier="com.qvacua.vimr.menuitems.edit.delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<menuItem title="Select All" keyEquivalent="a" identifier="com.qvacua.vimr.menuitems.edit.select-all" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
@ -171,17 +171,17 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="Wj0-kR-IJp">
|
||||
<items>
|
||||
<menuItem title="Reset To Default Size" keyEquivalent="0" id="dmv-1c-kFU">
|
||||
<menuItem title="Reset To Default Size" keyEquivalent="0" identifier="com.qvacua.vimr.menuitems.view.font.reset-to-default-size" id="dmv-1c-kFU">
|
||||
<connections>
|
||||
<action selector="resetFontSize:" target="-1" id="8Rb-Wd-iZH"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="FIs-h6-uga">
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" identifier="com.qvacua.vimr.menuitems.view.font.bigger" id="FIs-h6-uga">
|
||||
<connections>
|
||||
<action selector="makeFontBigger:" target="-1" id="FVE-Cp-LhT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="BHh-O4-8m0">
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" identifier="com.qvacua.vimr.menuitems.view.font.smaller" id="BHh-O4-8m0">
|
||||
<connections>
|
||||
<action selector="makeFontSmaller:" target="-1" id="nqo-sN-9tq"/>
|
||||
</connections>
|
||||
@ -190,7 +190,7 @@
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="NXP-NG-aHV"/>
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="Co5-Y0-sqo">
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" identifier="com.qvacua.vimr.menuitems.view.enter-full-screen" id="Co5-Y0-sqo">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="-1" id="b4d-vv-b5h"/>
|
||||
@ -203,25 +203,25 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Tools" id="7MO-P5-uU3">
|
||||
<items>
|
||||
<menuItem title="Toggle All Tools" keyEquivalent="\" id="Lb6-TZ-LgL">
|
||||
<menuItem title="Toggle All Tools" keyEquivalent="\" identifier="com.qvacua.vimr.menuitems.tools.toggle-all-tools" id="Lb6-TZ-LgL">
|
||||
<connections>
|
||||
<action selector="toggleAllTools:" target="-1" id="V97-0e-bES"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Toggle Tool Buttons" keyEquivalent="\" id="oK0-ZG-w1f">
|
||||
<menuItem title="Toggle Tool Buttons" keyEquivalent="\" identifier="com.qvacua.vimr.menuitems.tools.toggle-tool-buttons" id="oK0-ZG-w1f">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolButtons:" target="-1" id="bxj-O1-Vo9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="UAq-9D-Jex"/>
|
||||
<menuItem title="Toggle File Browser" keyEquivalent="1" id="PWx-V8-0cQ">
|
||||
<menuItem title="Toggle File Browser" keyEquivalent="1" identifier="com.qvacua.vimr.menuitems.tools.toggle-file-browser" id="PWx-V8-0cQ">
|
||||
<connections>
|
||||
<action selector="toggleFileBrowser:" target="-1" id="Ggq-4w-iN7"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="XHW-5e-Vad"/>
|
||||
<menuItem title="Focus Neovim View" keyEquivalent="." id="TtL-Gg-pCj">
|
||||
<menuItem title="Focus Neovim View" keyEquivalent="." identifier="com.qvacua.vimr.menuitems.tools.focus-neovim-view" id="TtL-Gg-pCj">
|
||||
<connections>
|
||||
<action selector="focusNvimView:" target="-1" id="obY-Kb-RxK"/>
|
||||
</connections>
|
||||
@ -233,19 +233,19 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<menuItem title="Minimize" keyEquivalent="m" identifier="com.qvacua.vimr.menuitems.window.minimize" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<menuItem title="Zoom" identifier="com.qvacua.vimr.menuitems.window.zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<menuItem title="Bring All to Front" identifier="com.qvacua.vimr.menuitems.window.bring-all-to-front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
|
||||
@ -276,7 +276,7 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||
<items>
|
||||
<menuItem title="VimR Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<menuItem title="VimR Help" keyEquivalent="?" identifier="com.qvacua.vimr.menuitems.help.vimr-help" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
|
@ -30,6 +30,7 @@ class PrefWindow: NSObject,
|
||||
ToolsPref(source: source, emitter: emitter, state: state),
|
||||
AppearancePref(source: source, emitter: emitter, state: state),
|
||||
KeysPref(source: source, emitter: emitter, state: state),
|
||||
ShortcutsPref(source: source, emitter: emitter, state: state),
|
||||
AdvancedPref(source: source, emitter: emitter, state: state),
|
||||
]
|
||||
|
||||
@ -119,6 +120,11 @@ class PrefWindow: NSObject,
|
||||
paneContainer.autoPinEdge(.left, to: .right, of: categoryScrollView)
|
||||
|
||||
self.currentPane = self.panes[0]
|
||||
|
||||
// GH-314 FIXME: Remove when finished.
|
||||
#if DEBUG
|
||||
self.categoryView.selectRowIndexes(IndexSet(integer: 4), byExtendingSelection: false)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
46
VimR/VimR/ShortcutItem.swift
Normal file
46
VimR/VimR/ShortcutItem.swift
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ShortcutItem: NSObject, Comparable {
|
||||
|
||||
static func <(lhs: ShortcutItem, rhs: ShortcutItem) -> Bool {
|
||||
return lhs.title < rhs.title
|
||||
}
|
||||
|
||||
@objc dynamic var title: String
|
||||
@objc dynamic var isLeaf: Bool
|
||||
|
||||
@objc dynamic var childrenCount: Int {
|
||||
return self.children?.count ?? -1
|
||||
}
|
||||
|
||||
var isContainer: Bool {
|
||||
return !self.isLeaf
|
||||
}
|
||||
|
||||
override var description: String {
|
||||
return "<ShortcutItem: \(title), " +
|
||||
"id: '\(self.item?.identifier?.rawValue ?? "")', " +
|
||||
"isLeaf: \(self.isLeaf), " +
|
||||
"childrenCount: \(self.children?.count ?? -1)" +
|
||||
">"
|
||||
}
|
||||
|
||||
let item: NSMenuItem?
|
||||
@objc dynamic var children: [ShortcutItem]?
|
||||
|
||||
init(
|
||||
title: String,
|
||||
isLeaf: Bool,
|
||||
item: NSMenuItem?
|
||||
) {
|
||||
self.title = title
|
||||
self.isLeaf = isLeaf
|
||||
self.item = item
|
||||
self.children = isLeaf ? nil : []
|
||||
}
|
||||
}
|
223
VimR/VimR/ShortcutsPref.swift
Normal file
223
VimR/VimR/ShortcutsPref.swift
Normal file
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
import PureLayout
|
||||
import RxSwift
|
||||
|
||||
class DummyItem {
|
||||
|
||||
let isGroup: Bool
|
||||
let text: String
|
||||
|
||||
init(_ text: String, _ isGroup: Bool) {
|
||||
self.isGroup = isGroup
|
||||
self.text = text
|
||||
}
|
||||
}
|
||||
|
||||
class ShortcutsPref: PrefPane,
|
||||
UiComponent,
|
||||
NSOutlineViewDelegate {
|
||||
|
||||
typealias StateType = AppState
|
||||
|
||||
enum Action {
|
||||
|
||||
case dummy
|
||||
}
|
||||
|
||||
@objc dynamic var content = [ShortcutItem]()
|
||||
|
||||
override var displayName: String {
|
||||
return "Shortcuts"
|
||||
}
|
||||
|
||||
override var pinToContainer: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
required init(
|
||||
source: Observable<StateType>,
|
||||
emitter: ActionEmitter,
|
||||
state: StateType
|
||||
) {
|
||||
self.emit = emitter.typedEmit()
|
||||
|
||||
super.init(frame: .zero)
|
||||
|
||||
self.addViews()
|
||||
self.updateViews()
|
||||
|
||||
self.initShortcutItems()
|
||||
if let children = self.shortcutItemsRoot.children {
|
||||
self.content.append(contentsOf: children)
|
||||
}
|
||||
|
||||
source
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onNext: { state in
|
||||
})
|
||||
.disposed(by: self.disposeBag)
|
||||
|
||||
initBindings()
|
||||
self.shortcutList.expandItem(nil, expandChildren: true)
|
||||
}
|
||||
|
||||
private let emit: (Action) -> Void
|
||||
private let disposeBag = DisposeBag()
|
||||
|
||||
private let shortcutList = NSOutlineView.standardOutlineView()
|
||||
private let shortcutScrollView = NSScrollView.standardScrollView()
|
||||
|
||||
private let treeController = NSTreeController()
|
||||
private let shortcutItemsRoot = ShortcutItem(
|
||||
title: "root", isLeaf: false, item: nil
|
||||
)
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func initBindings() {
|
||||
self.treeController.childrenKeyPath = "children"
|
||||
self.treeController.leafKeyPath = "isLeaf"
|
||||
self.treeController.countKeyPath = "childrenCount"
|
||||
self.treeController.objectClass = ShortcutItem.self
|
||||
self.treeController.avoidsEmptySelection = false
|
||||
self.treeController.preservesSelection = true
|
||||
self.treeController.sortDescriptors = [
|
||||
NSSortDescriptor(key: "title", ascending: true)
|
||||
]
|
||||
self.treeController.bind(.contentArray, to: self, withKeyPath: "content")
|
||||
self.shortcutList.bind(.content,
|
||||
to: self.treeController,
|
||||
withKeyPath: "arrangedObjects")
|
||||
self.shortcutList.bind(.selectionIndexPaths,
|
||||
to: self.treeController,
|
||||
withKeyPath: "selectionIndexPaths")
|
||||
}
|
||||
|
||||
private func initShortcutItems() {
|
||||
guard let mainMenu = NSApplication.shared.mainMenu else { return }
|
||||
let firstLevel = mainMenu.items
|
||||
.suffix(from: 1)
|
||||
.filter { $0.identifier != debugMenuItemIdentifier }
|
||||
|
||||
var queue = firstLevel.map {
|
||||
(
|
||||
parent: self.shortcutItemsRoot,
|
||||
shortcutItem: ShortcutItem(title: $0.title, isLeaf: false, item: $0)
|
||||
)
|
||||
}
|
||||
while (!queue.isEmpty) {
|
||||
guard let entry = queue.popLast() else { break }
|
||||
|
||||
if !entry.shortcutItem.isLeaf
|
||||
|| entry.shortcutItem.item?
|
||||
.identifier?
|
||||
.rawValue
|
||||
.hasPrefix("com.qvacua.vimr.menuitems.") == true {
|
||||
|
||||
entry.parent.children?.append(entry.shortcutItem)
|
||||
}
|
||||
|
||||
if entry.shortcutItem.isContainer,
|
||||
let childMenuItems = entry.shortcutItem.item?.submenu?.items {
|
||||
|
||||
let shortcutChildItems = childMenuItems
|
||||
.filter { !$0.title.isEmpty }
|
||||
.map { menuItem in
|
||||
(
|
||||
parent: entry.shortcutItem,
|
||||
shortcutItem: ShortcutItem(title: menuItem.title,
|
||||
isLeaf: !menuItem.hasSubmenu,
|
||||
item: menuItem)
|
||||
)
|
||||
}
|
||||
queue.append(contentsOf: shortcutChildItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func updateViews() {
|
||||
}
|
||||
|
||||
private func addViews() {
|
||||
let paneTitle = self.paneTitleTextField(title: "Shortcuts")
|
||||
|
||||
let shortcutList = self.shortcutList
|
||||
shortcutList.delegate = self
|
||||
|
||||
let shortcutScrollView = self.shortcutScrollView
|
||||
shortcutScrollView.documentView = shortcutList
|
||||
|
||||
self.addSubview(paneTitle)
|
||||
self.addSubview(shortcutScrollView)
|
||||
|
||||
paneTitle.autoPinEdge(toSuperviewEdge: .top, withInset: 18)
|
||||
paneTitle.autoPinEdge(toSuperviewEdge: .left, withInset: 18)
|
||||
paneTitle.autoPinEdge(
|
||||
toSuperviewEdge: .right, withInset: 18, relation: .greaterThanOrEqual
|
||||
)
|
||||
|
||||
shortcutScrollView.autoPinEdge(
|
||||
.top, to: .bottom, of: paneTitle, withOffset: 18
|
||||
)
|
||||
shortcutScrollView.autoPinEdge(.left, to: .left, of: paneTitle)
|
||||
shortcutScrollView.autoPinEdge(toSuperviewEdge: .right, withInset: 18)
|
||||
shortcutScrollView.autoPinEdge(toSuperviewEdge: .bottom, withInset: 18)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
extension ShortcutsPref {
|
||||
|
||||
@objc func isLeftOptionMetaAction(_ sender: NSButton) {
|
||||
self.emit(.dummy)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - NSOutlineViewDelegate
|
||||
extension ShortcutsPref {
|
||||
|
||||
func outlineView(
|
||||
_ outlineView: NSOutlineView,
|
||||
rowViewForItem item: Any
|
||||
) -> NSTableRowView? {
|
||||
let view = self.shortcutList.makeView(
|
||||
withIdentifier: NSUserInterfaceItemIdentifier("shortcut-row-view"),
|
||||
owner: self
|
||||
) as? ShortcutTableRow
|
||||
?? ShortcutTableRow(withIdentifier: "shortcut-row-view")
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
func outlineView(
|
||||
_: NSOutlineView,
|
||||
viewFor tableColumn: NSTableColumn?,
|
||||
item: Any
|
||||
) -> NSView? {
|
||||
let cellView = self.shortcutList.makeView(
|
||||
withIdentifier: NSUserInterfaceItemIdentifier("shortcut-cell-view"),
|
||||
owner: self
|
||||
) as? ShortcutTableCell
|
||||
?? ShortcutTableCell(withIdentifier: "shortcut-cell-view")
|
||||
|
||||
let repObj = (item as? NSTreeNode)?.representedObject
|
||||
guard let item = repObj as? ShortcutItem else {
|
||||
return nil
|
||||
}
|
||||
|
||||
cellView.text = item.title
|
||||
|
||||
return cellView
|
||||
}
|
||||
|
||||
func outlineView(_: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {
|
||||
return 24
|
||||
}
|
||||
}
|
87
VimR/VimR/ShortcutsTableSubviews.swift
Normal file
87
VimR/VimR/ShortcutsTableSubviews.swift
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ShortcutTableRow: NSTableRowView {
|
||||
|
||||
init(withIdentifier identifier: String) {
|
||||
super.init(frame: .zero)
|
||||
self.identifier = NSUserInterfaceItemIdentifier(identifier)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
class ShortcutTableCell: NSTableCellView {
|
||||
|
||||
static let font = NSFont.systemFont(ofSize: 13)
|
||||
|
||||
var isDir = false
|
||||
|
||||
var attributedText: NSAttributedString {
|
||||
get {
|
||||
return self.textField!.attributedStringValue
|
||||
}
|
||||
|
||||
set {
|
||||
self.textField?.attributedStringValue = newValue
|
||||
self.addTextField()
|
||||
}
|
||||
}
|
||||
|
||||
var text: String {
|
||||
get {
|
||||
return self.textField!.stringValue
|
||||
}
|
||||
|
||||
set {
|
||||
self.textField?.stringValue = newValue
|
||||
self.addTextField()
|
||||
}
|
||||
}
|
||||
|
||||
init(withIdentifier identifier: String) {
|
||||
super.init(frame: .zero)
|
||||
|
||||
self.identifier = NSUserInterfaceItemIdentifier(identifier)
|
||||
|
||||
self.textField = self._textField
|
||||
|
||||
let textField = self._textField
|
||||
textField.font = ShortcutTableCell.font
|
||||
textField.isBordered = false
|
||||
textField.isBezeled = false
|
||||
textField.allowsEditingTextAttributes = false
|
||||
textField.isEditable = false
|
||||
textField.usesSingleLineMode = true
|
||||
textField.drawsBackground = false
|
||||
}
|
||||
|
||||
func reset() -> ShortcutTableCell {
|
||||
self.text = ""
|
||||
self.removeAllSubviews()
|
||||
return self
|
||||
}
|
||||
|
||||
private func addTextField() {
|
||||
let textField = self._textField
|
||||
|
||||
textField.removeFromSuperview()
|
||||
self.addSubview(textField)
|
||||
|
||||
textField.autoPinEdgesToSuperviewEdges(
|
||||
with: NSEdgeInsets(top: 2, left: 4, bottom: 2, right: 2)
|
||||
)
|
||||
}
|
||||
|
||||
private let _textField = NSTextField(forAutoLayout: ())
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user