Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reveal file in the middle of Project Navigator #1352

Merged
merged 7 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CodeEdit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@
DE513F54281DE5D0002260B9 /* TabBarXcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE513F53281DE5D0002260B9 /* TabBarXcode.swift */; };
DE6405A62817734700881FDF /* TabBarNative.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE6405A52817734700881FDF /* TabBarNative.swift */; };
DE6F77872813625500D00A76 /* TabBarDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE6F77862813625500D00A76 /* TabBarDivider.swift */; };
EC0870F72A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0870F62A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -842,6 +843,7 @@
DE513F53281DE5D0002260B9 /* TabBarXcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarXcode.swift; sourceTree = "<group>"; };
DE6405A52817734700881FDF /* TabBarNative.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarNative.swift; sourceTree = "<group>"; };
DE6F77862813625500D00A76 /* TabBarDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarDivider.swift; sourceTree = "<group>"; };
EC0870F62A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProjectNavigatorViewController+NSMenuDelegate.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -1037,6 +1039,7 @@
285FEC6F27FE4B9800E57D53 /* ProjectNavigatorTableViewCell.swift */,
285FEC7127FE4EEF00E57D53 /* ProjectNavigatorMenu.swift */,
D7DC4B75298FFBE900D6C83D /* ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift */,
EC0870F62A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift */,
);
path = OutlineView;
sourceTree = "<group>";
Expand Down Expand Up @@ -2720,6 +2723,7 @@
DE513F52281B672D002260B9 /* TabBarAccessory.swift in Sources */,
2813F93927ECC4C300E305E4 /* NavigatorSidebarView.swift in Sources */,
587B9E8A29301D8F00AC7927 /* GitHubIssue.swift in Sources */,
EC0870F72A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift in Sources */,
6CAAF69429BCD78600A1F48A /* (null) in Sources */,
DE513F54281DE5D0002260B9 /* TabBarXcode.swift in Sources */,
6C82D6C629C012AD00495C54 /* NSApp+openWindow.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// ProjectNavigatorViewController+NSMenuDelegate.swift
// CodeEdit
//
// Created by Dscyre Scotti on 6/23/23.
//

import SwiftUI

// MARK: - NSMenuDelegate
extension ProjectNavigatorViewController: NSMenuDelegate {

/// Once a menu gets requested by a `right click` setup the menu
///
/// If the right click happened outside a row this will result in no menu being shown.
/// - Parameter menu: The menu that got requested
func menuNeedsUpdate(_ menu: NSMenu) {
let row = outlineView.clickedRow
guard let menu = menu as? ProjectNavigatorMenu else { return }

if row == -1 {
menu.item = nil
} else {
if let item = outlineView.item(atRow: row) as? CEWorkspaceFile {
menu.item = item
menu.workspace = workspace
} else {
menu.item = nil
}
}
menu.update()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,23 @@ final class ProjectNavigatorViewController: NSViewController {
fatalError()
}

/// Forces to reveal the selected file through the command regardless of the auto reveal setting
@objc
func revealFile(_ sender: Any) {
updateSelection(itemID: workspace?.tabManager.activeTabGroup.selected?.id, forcesReveal: true)
}

/// Updates the selection of the ``outlineView`` whenever it changes.
///
/// Most importantly when the `id` changes from an external view.
/// - Parameter itemID: The id of the file or folder.
func updateSelection(itemID: String?) {
/// - Parameter forcesReveal: The boolean to indicates whether or not it should force to reveal the selected file.
func updateSelection(itemID: String?, forcesReveal: Bool = false) {
guard let itemID else {
outlineView.deselectRow(outlineView.selectedRow)
return
}

select(by: .codeEditor(itemID), from: content)
select(by: .codeEditor(itemID), from: content, forcesReveal: forcesReveal)
}

/// Expand or collapse the folder on double click
Expand Down Expand Up @@ -243,7 +249,6 @@ extension ProjectNavigatorViewController: NSOutlineViewDataSource {
}

// MARK: - NSOutlineViewDelegate

extension ProjectNavigatorViewController: NSOutlineViewDelegate {
func outlineView(
_ outlineView: NSOutlineView,
Expand Down Expand Up @@ -290,6 +295,10 @@ extension ProjectNavigatorViewController: NSOutlineViewDelegate {
else {
return
}
/// update outline selection only if the parent of selected item match with expanded item
guard item.parent === notification.userInfo?["NSObject"] as? CEWorkspaceFile else {
return
}
/// select active file under collapsed folder only if its parent is expanding
if outlineView.isItemExpanded(item.parent) {
updateSelection(itemID: item.id)
Expand All @@ -313,13 +322,14 @@ extension ProjectNavigatorViewController: NSOutlineViewDelegate {
/// - Parameters:
/// - id: the id of the item item
/// - collection: the array to search for
private func select(by id: TabBarItemID, from collection: [CEWorkspaceFile]) {
/// - forcesReveal: The boolean to indicates whether or not it should force to reveal the selected file.
private func select(by id: TabBarItemID, from collection: [CEWorkspaceFile], forcesReveal: Bool) {
guard let item = collection.find(by: id) else {
return
}
// If the user has set "Reveal file on selection change" to on, we need to reveal the item before
// selecting the row.
if Settings.shared.preferences.general.revealFileOnFocusChange {
// If the user has set "Reveal file on selection change" to on or it is forced to reveal,
// we need to reveal the item before selecting the row.
if Settings.shared.preferences.general.revealFileOnFocusChange || forcesReveal {
reveal(item)
}
let row = outlineView.row(forItem: item)
Expand Down Expand Up @@ -350,7 +360,21 @@ extension ProjectNavigatorViewController: NSOutlineViewDelegate {
alert.runModal()
return
} else {
let visibleRect = scrollView.contentView.visibleRect
let visibleRows = outlineView.rows(in: visibleRect)
guard !visibleRows.contains(row) else {
/// in case that the selected file is not fully visible (some parts are out of the visible rect),
/// `scrollRowToVisible(_:)` method brings the file where it can be fully visible.
outlineView.scrollRowToVisible(row)
return
}
let rowRect = outlineView.rect(ofRow: row)
let centerY = rowRect.midY - (visibleRect.height / 2)
let center = NSPoint(x: 0, y: centerY)
/// `scroll(_:)` method alone doesn't bring the selected file to the center in some cases.
/// calling `scrollRowToVisible(_:)` method before it makes the file reveal in the center more correctly.
outlineView.scrollRowToVisible(row)
outlineView.scroll(center)
}
}

Expand All @@ -363,29 +387,3 @@ extension ProjectNavigatorViewController: NSOutlineViewDelegate {
outlineView.expandItem(item)
}
}

// MARK: - NSMenuDelegate

extension ProjectNavigatorViewController: NSMenuDelegate {

/// Once a menu gets requested by a `right click` setup the menu
///
/// If the right click happened outside a row this will result in no menu being shown.
/// - Parameter menu: The menu that got requested
func menuNeedsUpdate(_ menu: NSMenu) {
let row = outlineView.clickedRow
guard let menu = menu as? ProjectNavigatorMenu else { return }

if row == -1 {
menu.item = nil
} else {
if let item = outlineView.item(atRow: row) as? CEWorkspaceFile {
menu.item = item
menu.workspace = workspace
} else {
menu.item = nil
}
}
menu.update()
}
}
8 changes: 6 additions & 2 deletions CodeEdit/Features/WindowCommands/NavigateCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,41 @@ struct NavigateCommands: Commands {
CommandMenu("Navigate") {
Group {
Button("Reveal in Project Navigator") {

NSApp.sendAction(#selector(ProjectNavigatorViewController.revealFile(_:)), to: nil, from: nil)
dscyrescotti marked this conversation as resolved.
Show resolved Hide resolved
}
.keyboardShortcut("j", modifiers: [.shift, .command])

Button("Reveal Changes in Navigator") {

}
.keyboardShortcut("m", modifiers: [.shift, .command])
.disabled(true)

Button("Open in Next Editor") {

}
.keyboardShortcut(",", modifiers: [.option, .command])
.disabled(true)

Button("Open in...") {

}
.disabled(true)

Divider()

}
.disabled(true)

Group {
Button("Show Previous Tab") {

}
.disabled(true)

Button("Show Next Tab") {

}
.disabled(true)

Divider()

Expand Down