| // Copyright 2016 The Tulsi Authors. All rights reserved. |
| // |
| // 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 |
| // |
| // http://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 |
| |
| |
| /// Convenience subclass of NSOpenPanel that acts as its own delegate and applies a filtering |
| /// function for -panel:shouldEnableURL:. |
| class FilteredOpenPanel: NSOpenPanel, NSOpenSavePanelDelegate { |
| typealias FilterFunc = (_ sender: FilteredOpenPanel, _ shouldEnableURL: URL) -> Bool |
| |
| var filterFunc: FilterFunc? = nil |
| |
| static func filteredOpenPanel(_ filter: FilterFunc?) -> FilteredOpenPanel { |
| let panel = FilteredOpenPanel() |
| panel.filterFunc = filter |
| panel.delegate = panel |
| return panel |
| } |
| |
| /// Creates a filtered NSOpenPanel that accepts any non-package directories and any files whose |
| /// last path component is in the given array of names. |
| static func filteredOpenPanelAcceptingNonPackageDirectoriesAndFilesNamed(_ names: [String]) -> FilteredOpenPanel { |
| return filteredOpenPanel(filterNonPackageDirectoriesOrFilesMatchingNames(names)) |
| } |
| |
| // MARK: - NSOpenSavePanelDelegate |
| |
| func panel(_ sender: Any, shouldEnable url: URL) -> Bool { |
| return filterFunc?(self, url) ?? true |
| } |
| |
| // MARK: - Internal methods |
| |
| static func filterNonPackageDirectoriesOrFilesMatchingNames(_ validFiles: [String]) -> FilterFunc { |
| return { (sender: AnyObject, url: URL) -> Bool in |
| var isDir: AnyObject? |
| var isPackage: AnyObject? |
| do { |
| try (url as NSURL).getResourceValue(&isDir, forKey: URLResourceKey.isDirectoryKey) |
| try (url as NSURL).getResourceValue(&isPackage, forKey: URLResourceKey.isPackageKey) |
| if let isDir = isDir as? NSNumber, let isPackage = isPackage as? NSNumber, !isPackage.boolValue { |
| if isDir.boolValue { return true } |
| return validFiles.contains(url.lastPathComponent) |
| } |
| } catch _ { |
| // Treat any exception as an invalid URL. |
| } |
| return false |
| } |
| } |
| } |
| |