Skip to content

Commit

Permalink
Refactor document open panel
Browse files Browse the repository at this point in the history
  • Loading branch information
1024jp committed Jan 19, 2025
1 parent 21da8c6 commit aaf9a8b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//
// ---------------------------------------------------------------------------
//
// © 2018-2024 1024jp
// © 2018-2025 1024jp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -28,10 +28,19 @@ import Observation
import AppKit.NSOpenPanel
import FileEncoding

@Observable final class OpenOptions: NSObject, NSOpenSavePanelDelegate {
@Observable final class OpenPanelModel: NSObject, NSOpenSavePanelDelegate {

var options: OpenOptions
let fileEncodings: [FileEncoding?]

fileprivate var isDirectory: Bool = false

var encoding: String.Encoding?
var isDirectory: Bool = false

init(options: OpenOptions = .init(), fileEncodings: [FileEncoding?]) {

self.options = options
self.fileEncodings = fileEncodings
}


func panelSelectionDidChange(_ sender: Any?) {
Expand All @@ -45,10 +54,8 @@ import FileEncoding

struct OpenPanelAccessory: View {

@State var options: OpenOptions

@State var model: OpenPanelModel
weak var openPanel: NSOpenPanel?
let fileEncodings: [FileEncoding?]

@State private var showsHiddenFiles = false

Expand All @@ -59,12 +66,12 @@ struct OpenPanelAccessory: View {

VStack(alignment: .center) {
Form {
Picker(String(localized: "Text encoding:", table: "OpenPanelAccessory"), selection: $options.encoding) {
Picker(String(localized: "Text encoding:", table: "OpenPanelAccessory"), selection: $model.options.encoding) {
Text("Automatic", tableName: "OpenPanelAccessory", comment: "menu item title for automatic encoding detection")
.tag(String.Encoding?.none)
Divider()

ForEach(Array(self.fileEncodings.enumerated()), id: \.offset) { (_, fileEncoding) in
ForEach(Array(self.model.fileEncodings.enumerated()), id: \.offset) { (_, fileEncoding) in
if let fileEncoding {
Text(fileEncoding.localizedName)
.tag(String.Encoding?.some(fileEncoding.encoding))
Expand All @@ -73,7 +80,7 @@ struct OpenPanelAccessory: View {
}
}
}
.disabled(self.options.isDirectory)
.disabled(self.model.isDirectory)

Toggle(String(localized: "Show invisible files", table: "OpenPanelAccessory", comment: "toggle button label"), isOn: $showsHiddenFiles)
.onChange(of: self.showsHiddenFiles) { (_, newValue) in
Expand All @@ -93,5 +100,7 @@ struct OpenPanelAccessory: View {
// MARK: - Preview

#Preview {
OpenPanelAccessory(options: .init(), fileEncodings: [.utf8])
@Previewable @State var model = OpenPanelModel(fileEncodings: [.utf8])

return OpenPanelAccessory(model: model)
}
4 changes: 3 additions & 1 deletion CotEditor/Sources/Document/Document.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ extension Document: EditorSource {

// [caution] This method may be called from a background thread due to concurrent-opening.

let openOptions = (DocumentController.shared as! DocumentController).openOptions

let lineEnding = LineEnding.allCases[safe: UserDefaults.standard[.lineEndCharCode]] ?? .lf
self.lineEnding = lineEnding

Expand All @@ -125,7 +127,7 @@ extension Document: EditorSource {

// use the encoding selected by the user in the open panel, if exists
self.fileEncoding = EncodingManager.shared.defaultEncoding
self.readingEncoding = (DocumentController.shared as! DocumentController).accessorySelectedEncoding
self.readingEncoding = openOptions?.encoding

// observe for inconsistent line endings
self.lineEndingScanner = .init(textStorage: self.textStorage, lineEnding: lineEnding)
Expand Down
20 changes: 13 additions & 7 deletions CotEditor/Sources/Document/DocumentController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// ---------------------------------------------------------------------------
//
// © 2004-2007 nakamuxu
// © 2014-2024 1024jp
// © 2014-2025 1024jp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -36,12 +36,18 @@ protocol AdditionalDocumentPreparing: NSDocument {
}


struct OpenOptions {

var encoding: String.Encoding?
}


final class DocumentController: NSDocumentController {

// MARK: Public Properties

@Published private(set) var currentSyntaxName: String?
private(set) var accessorySelectedEncoding: String.Encoding?
private(set) var openOptions: OpenOptions?


// MARK: Private Properties
Expand Down Expand Up @@ -106,7 +112,7 @@ final class DocumentController: NSDocumentController {
let (document, documentWasAlreadyOpen) = try await super.openDocument(withContentsOf: url, display: false)

// invalidate encoding that was set in the open panel
self.accessorySelectedEncoding = nil
self.openOptions = nil

if let transientDocument, let document = document as? Document {
self.replaceTransientDocument(transientDocument, with: document)
Expand Down Expand Up @@ -183,20 +189,20 @@ final class DocumentController: NSDocumentController {

override func beginOpenPanel(_ openPanel: NSOpenPanel, forTypes inTypes: [String]?) async -> Int {

let options = OpenOptions()
let accessory = OpenPanelAccessory(options: options, openPanel: openPanel, fileEncodings: EncodingManager.shared.fileEncodings)
let model = OpenPanelModel(fileEncodings: EncodingManager.shared.fileEncodings)
let accessory = OpenPanelAccessory(model: model, openPanel: openPanel)
let accessoryView = NSHostingView(rootView: accessory)
accessoryView.sizingOptions = .intrinsicContentSize

openPanel.delegate = options
openPanel.delegate = model
openPanel.canChooseDirectories = true
openPanel.accessoryView = accessoryView
openPanel.isAccessoryViewDisclosed = true

let result = await super.beginOpenPanel(openPanel, forTypes: inTypes)

if result == NSApplication.ModalResponse.OK.rawValue {
self.accessorySelectedEncoding = options.encoding
self.openOptions = model.options
}

return result
Expand Down

0 comments on commit aaf9a8b

Please sign in to comment.