From 9e0a98a75daaba9582d9c0181db196faa034c02a Mon Sep 17 00:00:00 2001 From: SchlaubiSchlump Date: Tue, 29 Dec 2020 01:43:52 +0100 Subject: [PATCH] Initial version --- .gitignore | 166 +++++++++++++ LICENSE | 165 +++++++++++++ Package.swift | 31 +++ README.md | 70 ++++++ Sources/SuggestionPopup/KeyCodes.swift | 22 ++ .../LocationSearchCompleter.swift | 69 ++++++ .../SearchCompleter/SearchCompleter.swift | 227 ++++++++++++++++++ .../SearchCompleter/Suggestion.swift | 27 +++ .../ViewController/SuggestionListView.swift | 75 ++++++ .../SuggestionListViewController.swift | 181 ++++++++++++++ .../SuggestionTableCellView.swift | 137 +++++++++++ .../SuggestionTableRowView.swift | 66 +++++ .../WindowController/SuggestionWindow.swift | 63 +++++ .../SuggestionWindowController.swift | 169 +++++++++++++ Tests/LinuxMain.swift | 7 + .../SuggestionPopupTests.swift | 15 ++ .../XCTestManifests.swift | 9 + screenshot.png | Bin 0 -> 87532 bytes 18 files changed, 1499 insertions(+) create mode 100755 .gitignore create mode 100644 LICENSE create mode 100644 Package.swift create mode 100644 README.md create mode 100644 Sources/SuggestionPopup/KeyCodes.swift create mode 100644 Sources/SuggestionPopup/SearchCompleter/LocationSearchCompleter.swift create mode 100644 Sources/SuggestionPopup/SearchCompleter/SearchCompleter.swift create mode 100644 Sources/SuggestionPopup/SearchCompleter/Suggestion.swift create mode 100644 Sources/SuggestionPopup/ViewController/SuggestionListView.swift create mode 100644 Sources/SuggestionPopup/ViewController/SuggestionListViewController.swift create mode 100644 Sources/SuggestionPopup/ViewController/SuggestionTableCellView.swift create mode 100644 Sources/SuggestionPopup/ViewController/SuggestionTableRowView.swift create mode 100644 Sources/SuggestionPopup/WindowController/SuggestionWindow.swift create mode 100644 Sources/SuggestionPopup/WindowController/SuggestionWindowController.swift create mode 100644 Tests/LinuxMain.swift create mode 100644 Tests/SuggestionPopupTests/SuggestionPopupTests.swift create mode 100644 Tests/SuggestionPopupTests/XCTestManifests.swift create mode 100644 screenshot.png diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..e3d789b --- /dev/null +++ b/.gitignore @@ -0,0 +1,166 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Apple Owned files +*.dmg +*.dmg.signature +.DS_Store +.swiftpm/* + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + + +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..153d416 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..d1f9bc7 --- /dev/null +++ b/Package.swift @@ -0,0 +1,31 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "SuggestionPopup", + platforms: [ + .macOS(.v10_12) + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "SuggestionPopup", + targets: ["SuggestionPopup"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "SuggestionPopup", + dependencies: []), + .testTarget( + name: "SuggestionPopupTests", + dependencies: ["SuggestionPopup"]), + ] +) diff --git a/README.md b/README.md new file mode 100644 index 0000000..7f3e7a8 --- /dev/null +++ b/README.md @@ -0,0 +1,70 @@ +# SuggestionPopup + +[![License: GNU Affero General Public license version 3](https://img.shields.io/badge/License-LGPLv3-blue.svg)](https://opensource.org/licenses/lgpl-3.0) + +This is a suggestion popup implementation similar to the one used by the `Maps.app` on macOS 10.15. It is provided under the GNU Lesser General Public License v3.0. I only tested it on macOS 10.15. MacOS 10.13-11.0 could work. I will test this in the future and make it compatible, if required. This software is still in beta. + + + +Usage: +If you just one to have a simple location search, things are easy: + +``` Swift +// Keep a reference to the search completer in memory. +var searchCompleter: LocationSearchCompleter! +... +// Somewhere in your constructor create a LocationSearchCompleter with +// your textField. You can still use the textField delegate ! +self.searchCompleter = LocationSearchCompleter(searchField: searchField) +``` + +If you want a custom search things are a little bit more difficult. + +``` Swift +// Create or implement a new class based on NSObject which conforms +// to the `Suggestion` protocol. A simple new class could look like +// this: +class SimpleSuggestion: NSObject, Suggestion { + init(title: String = "", subtitle: String = "", image: NSImage? = nil) { + self.title = title + self.subtitle = subtitle + self.image = image + } + + var title: String = "" + var subtitle: String = "" + var image: NSImage? + var highlightedTitleRanges: [Range] = [] + var highlightedSubtitleRanges: [Range] = [] +} +// Most of the times it might be easier to just extend your existing class. +// Take a look at the `LocationSearchCompleter` to see a simple example. + + +// Create a new subclass of the SearchCompleter class +class SimpleSearchCompleter: SearchCompleter { + + // This is called on `init`. It is just for your convenience. + // Place all initial setup code here. + override func setup() { + + } + + // Override this function to prepare your search. If your search + // is compute intensive, use a background thread here and call + // `setSuggestions` on completion. You might show a progress spinner + // in this case. For a simple search, just place your code here + // and end the function with a `setSuggestions` call. + override func prepareSuggestions(for searchString: String) { + //self.showSpinner() + super. prepareSuggestions(for: searchString) + } + + // Call this function to show the search result. You might override + // it to hide the progress spinner. + override func setSuggestions(_ suggestions: [Suggestion]) { + //self.hideSpinner() + super.setSuggestions(suggestions) + } +} +``` diff --git a/Sources/SuggestionPopup/KeyCodes.swift b/Sources/SuggestionPopup/KeyCodes.swift new file mode 100644 index 0000000..bdaba8d --- /dev/null +++ b/Sources/SuggestionPopup/KeyCodes.swift @@ -0,0 +1,22 @@ +// +// KeyCodes.swift +// Popup +// +// Created by David Klopp on 27.12.20. +// + +import AppKit + +enum KeyCodes: UInt16 { + case `return` = 36 + case tab = 48 + case arrowLeft = 123 + case arrowRight = 124 + case arrowDown = 125 + case arrowUp = 126 +} + +/// Define a class to be able to handle key events. +protocol KeyResponder { + func processKeys(with theEvent: NSEvent) -> NSEvent? +} diff --git a/Sources/SuggestionPopup/SearchCompleter/LocationSearchCompleter.swift b/Sources/SuggestionPopup/SearchCompleter/LocationSearchCompleter.swift new file mode 100644 index 0000000..f36172b --- /dev/null +++ b/Sources/SuggestionPopup/SearchCompleter/LocationSearchCompleter.swift @@ -0,0 +1,69 @@ +// +// LocationSearchController.swift +// Popup +// +// Created by David Klopp on 26.12.20. +// + +import AppKit +import MapKit + + +extension MKLocalSearchCompletion: Suggestion { + // Highlight the matched string inside the title. + public var highlightedTitleRanges: [Range] { + return self.titleHighlightRanges.compactMap { Range($0.rangeValue) } + } + + // Highlight the matched string inside the subtitle. + public var highlightedSubtitleRanges: [Range] { + return self.subtitleHighlightRanges.compactMap { Range($0.rangeValue) } + } + + // We don't show any Image. + public var image: NSImage? { + return nil + } + +} + +/// A simple search completer which searches for locations. +public final class LocationSearchCompleter: SearchCompleter { + /// Search completer to find a location based on a string. + private var searchCompleter = MKLocalSearchCompleter() + + // Setup the search completer. + public override func setup() { + if #available(OSX 10.15, *) { + self.searchCompleter.resultTypes = .address + } else { + self.searchCompleter.filterType = .locationsOnly + } + self.searchCompleter.delegate = self + } + + // Prepare the search results and show the spinner. + public override func prepareSuggestions(for searchString: String) { + // Show a progress spinner. + self.showSpinner() + // Cancel any running search request. + if self.searchCompleter.isSearching { + self.searchCompleter.cancel() + } + // Start a search. + self.searchCompleter.queryFragment = searchString + } + + // Show the results and hide the spinner. + public override func setSuggestions(_ suggestions: [Suggestion]) { + self.hideSpinner() + super.setSuggestions(suggestions) + } +} + +extension LocationSearchCompleter: MKLocalSearchCompleterDelegate { + /// Called when the searchCompleter finished loading the search results. + public func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) { + self.setSuggestions(self.searchCompleter.results) + } +} diff --git a/Sources/SuggestionPopup/SearchCompleter/SearchCompleter.swift b/Sources/SuggestionPopup/SearchCompleter/SearchCompleter.swift new file mode 100644 index 0000000..0b40897 --- /dev/null +++ b/Sources/SuggestionPopup/SearchCompleter/SearchCompleter.swift @@ -0,0 +1,227 @@ +// +// AutocompleteSearchController.swift +// Popup +// +// Created by David Klopp on 26.12.20. +// + +// TODO: +// Bug 2: Sometimes the text entry is broken when removing characters +// Bug 3: Hovering over a cell while deleting breaks the deleting mechanism. (This is the same as bug 2) + +import AppKit + +open class SearchCompleter: NSObject, KeyResponder { + /// The main searchField instance. + public weak var searchField: NSTextField! + + /// Window events. + public var onShow: SuggestionShowAction? + public var onHide: SuggestionHideAction? + public var onSelect: SuggestionSelectAction? + public var onHighlight: SuggestionHighlightAction? { + get { return self.windowController.onHighlight } + set { self.windowController.onHighlight = newValue } + } + + /// The main window controller. + var windowController: SuggestionWindowController! + + /// A reference to the textDidChange observer. + private var textDidChangeObserver: NSObjectProtocol? + + /// A reference to the window didResignKey observer. + private var lostFocusObserver: Any? + + /// The internal monitor to capture key events. + private var localKeyEventMonitor: Any? + + /// The internal monitor to capture mouse events. + private var localMouseDownEventMonitor: Any? + + // MARK: - Constructor + + public init(searchField: NSTextField) { + super.init() + self.searchField = searchField + self.windowController = SuggestionWindowController(searchField: searchField) + self.setup() + + // Listen for text changes inside the textField. + self.registerTextFieldNotifications() + self.registerFocusNotifications() + + // Add and remove the key and mouse events depending on whether the window is visible. + self.windowController.onShow = { [weak self] in + self?.registerKeyEvents() + self?.registerMouseEvents() + self?.onShow?() + } + self.windowController.onHide = { [weak self] in + self?.unregisterKeyEvents() + self?.unregisterMouseEvents() + self?.onHide?() + } + self.windowController.onSelect = { [weak self] in + self?.windowController.hide() + self?.onSelect?($0, $1) + } + } + + // MARK: - Destructor + + deinit { + self.unregisterTextFieldNotifications() + self.unregisterFocusNotifications() + } + + // MARK: - KeyEvents + + /// Handle key up and down events. + private func registerKeyEvents() { + self.localKeyEventMonitor = NSEvent.addLocalMonitorForEvents( + matching: [.keyDown, .keyUp]) { [weak self] (event) -> NSEvent? in + // If the current searchField is the first responder, we capture the event. + guard let firstResponder = self?.searchField?.window?.firstResponder else { return event } + if firstResponder == self?.searchField.currentEditor() { + return self?.processKeys(with: event) + } + return event + } + } + + /// Remove the key event monitor. + private func unregisterKeyEvents() { + if let eventMonitor = self.localKeyEventMonitor { + NSEvent.removeMonitor(eventMonitor) + } + self.localKeyEventMonitor = nil + } + + /// Return the event, to allow other classes to handle the event or nil to capture it. + func processKeys(with theEvent: NSEvent) -> NSEvent? { + // Check if this controller can handle the event. + if let keyEvent = KeyCodes(rawValue: theEvent.keyCode) { + switch keyEvent { + case .return: + // Hide the window. + self.windowController.hide() + case .tab: + // Do not capture the tab event. We still want to be able to change the focus. + self.windowController.hide() + default: + break + } + } + // Check if the window controller can handle the event. + return self.windowController != nil ? self.windowController?.processKeys(with: theEvent) : theEvent + } + + // MARK: - Mouse Events + + /// Handle mouse clickes inside and outside the window. + private func registerMouseEvents() { + self.localMouseDownEventMonitor = NSEvent.addLocalMonitorForEvents( + matching: [.leftMouseDown, .rightMouseDown, .otherMouseDown]) { [weak self] (event) -> NSEvent? in + // Make sure the event has a window. + guard let eventWindow = event.window, let window = self?.windowController.window else { return event } + let isSuggestionWindow = eventWindow == window + let clickedInsideContentView = eventWindow.contentView?.hitTest(event.locationInWindow) != nil + let clickedInsideTextField = self?.searchField.hitTest(event.locationInWindow) != nil + + // If the event window was clicked outside its toolbar then dismiss the popup. + if !isSuggestionWindow && clickedInsideContentView && !clickedInsideTextField { + self?.windowController.hide() + } + return event + } + } + + /// Remove the mouse click monitor. + private func unregisterMouseEvents() { + if let eventMonitor = self.localMouseDownEventMonitor { + NSEvent.removeMonitor(eventMonitor) + } + self.localMouseDownEventMonitor = nil + } + + // MARK: - TextField + + private func registerTextFieldNotifications() { + self.textDidChangeObserver = NotificationCenter.default.addObserver( + forName: NSTextField.textDidChangeNotification, + object: self.searchField, queue: .main) { [weak self] _ in + + let text = self?.searchField.stringValue ?? "" + if text.isEmpty { + // Hide window + self?.windowController.hide() + } else { + self?.prepareSuggestions(for: text) + // Show the autocomplete window and start a progress spinner. + self?.windowController.show() + } + } + } + + private func unregisterTextFieldNotifications() { + if let observer = self.textDidChangeObserver { + NotificationCenter.default.removeObserver(observer) + } + self.textDidChangeObserver = nil + } + + // MARK: - Focus + + private func registerFocusNotifications() { + // If the suggestion window looses focus we dismiss it. + guard let window = self.windowController.window else { return } + self.lostFocusObserver = NotificationCenter.default.addObserver(forName: NSWindow.didResignKeyNotification, + object: window, + queue: nil) { [weak self] _ in + self?.windowController.hide() + } + } + + private func unregisterFocusNotifications() { + if let observer = self.lostFocusObserver { + NotificationCenter.default.removeObserver(observer) + } + self.lostFocusObserver = nil + } + + // MARK: - Public Methods + + /// Show the spinner to indicate work. + public func showSpinner() { + let window = self.windowController.window as? SuggestionWindow + window?.showSpinner() + } + + /// Hide the spinner to indicate the work is finished. + public func hideSpinner() { + let window = self.windowController.window as? SuggestionWindow + window?.hideSpinner() + } + + // MARK: - Override + + /// Override this function to perform initial setup. + open func setup() { + + } + + /// This function is called when the textField text changes. Prepare your search results here. + open func prepareSuggestions(for searchString: String) { + + } + + /// Use this function to update the search results. + open func setSuggestions(_ suggestions: [Suggestion]) { + self.windowController.setSuggestions(suggestions) + // If we don't have any suggestions hide the window. + if suggestions.isEmpty { + self.windowController.hide() + } + } +} diff --git a/Sources/SuggestionPopup/SearchCompleter/Suggestion.swift b/Sources/SuggestionPopup/SearchCompleter/Suggestion.swift new file mode 100644 index 0000000..ef3eb99 --- /dev/null +++ b/Sources/SuggestionPopup/SearchCompleter/Suggestion.swift @@ -0,0 +1,27 @@ +// +// AutocompleteMatch.swift +// Popup +// +// Created by David Klopp on 26.12.20. +// + +import AppKit + +public typealias SuggestionSelectAction = ((String, Suggestion) -> Void) +public typealias SuggestionHighlightAction = ((String, Suggestion?) -> Void) +public typealias SuggestionShowAction = (() -> Void) +public typealias SuggestionHideAction = (() -> Void) + +/// Your class must conform to this protocol to be displayed in the suggestion list. +public protocol Suggestion: NSObject { + /// The main title. + var title: String { get } + /// The subtitle below the title. + var subtitle: String { get } + /// The image to the left. + var image: NSImage? { get } + /// Optional range to highlight inside the title. + var highlightedTitleRanges: [Range] { get } + /// Optional range to highlight inside the subtitle. + var highlightedSubtitleRanges: [Range] { get } +} diff --git a/Sources/SuggestionPopup/ViewController/SuggestionListView.swift b/Sources/SuggestionPopup/ViewController/SuggestionListView.swift new file mode 100644 index 0000000..54485a3 --- /dev/null +++ b/Sources/SuggestionPopup/ViewController/SuggestionListView.swift @@ -0,0 +1,75 @@ +// +// AutocompleteContentView.swift +// Popup +// +// Created by David Klopp on 26.12.20. +// + +import AppKit + +class SuggestionListView: NSScrollView { + /// The main table view. + var tableView: NSTableView! + /// The main table view column. + var column: NSTableColumn! + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + + // Setup the tableView. + self.tableView = NSTableView(frame: .zero) + if #available(OSX 11.0, *) { + self.tableView.style = .fullWidth + } + self.tableView.selectionHighlightStyle = NSTableView.SelectionHighlightStyle.regular + self.tableView.backgroundColor = .clear + self.tableView.rowSizeStyle = NSTableView.RowSizeStyle.custom + self.tableView.rowHeight = 36.0 + self.tableView.intercellSpacing = NSSize(width: 5.0, height: 0.0) + self.tableView.headerView = nil + + // Add a table column. + self.column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: "text")) + self.column.isEditable = false + self.tableView.addTableColumn(self.column) + + // Setup the scrollView. + self.drawsBackground = false + self.documentView = self.tableView + self.hasVerticalScroller = true + self.hasHorizontalScroller = false + self.automaticallyAdjustsContentInsets = false + self.contentInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + } + + required init?(coder: NSCoder) { + fatalError("InitWithCoder not supported.") + } + + // MARK: - Layout + + override func layout() { + super.layout() + self.tableView.frame.size.width = self.frame.width + self.column.width = self.tableView.frame.width + } + + // MARK: - Helper + + func selectPreviousRow() { + let row = self.tableView.selectedRow + if row > 0 { + self.tableView.selectRowIndexes([row-1], byExtendingSelection: false) + self.tableView.scrollRowToVisible(row-1) + } else { + self.tableView.selectRowIndexes([], byExtendingSelection: false) + } + } + + func selectNextRow() { + let row = self.tableView.selectedRow + guard row < self.tableView.numberOfRows-1 else { return } + self.tableView.selectRowIndexes([row+1], byExtendingSelection: false) + self.tableView.scrollRowToVisible(row+1) + } +} diff --git a/Sources/SuggestionPopup/ViewController/SuggestionListViewController.swift b/Sources/SuggestionPopup/ViewController/SuggestionListViewController.swift new file mode 100644 index 0000000..f6408aa --- /dev/null +++ b/Sources/SuggestionPopup/ViewController/SuggestionListViewController.swift @@ -0,0 +1,181 @@ +// +// AutocompleteContentViewController.swift +// Popup +// +// Created by David Klopp on 26.12.20. +// + +import AppKit + +let kMaxResults = 5 +let kCellIdentifier = NSUserInterfaceItemIdentifier(rawValue: "AutocompleteCell") + +class SuggestionListViewController: NSViewController, KeyResponder { + /// The main tableView with all search results. + var contentView: SuggestionListView! + /// The list with all suggestions. + var suggestions: [Suggestion] = [] + /// The progress spinner when loading results. + private var spinner: NSProgressIndicator! + /// The target and action to perform when a cell is selected. + var target: AnyObject? + var action: Selector? + + /// Override loadView to load our custom content view. + override func loadView() { + // Create a container view that contains the effect view and the content view. + let containerView = NSView() + + // Add the effect view. + let effectView = NSVisualEffectView(frame: containerView.bounds) + effectView.autoresizingMask = [.height, .width] + effectView.isEmphasized = false + effectView.state = .active + if #available(OSX 10.14, *) { + effectView.material = .underWindowBackground + } else { + effectView.material = .titlebar + } + effectView.blendingMode = .behindWindow + containerView.addSubview(effectView) + + // Add the content view. + self.contentView = SuggestionListView(frame: containerView.bounds) + self.contentView.autoresizingMask = [.height, .width] + self.contentView.isHidden = false + self.contentView.tableView.dataSource = self + self.contentView.tableView.delegate = self + containerView.addSubview(contentView) + + // Handle the tableView click events. + self.contentView.tableView.target = self + self.contentView.tableView.action = #selector(performActionForSelectedCell(_:)) + + // Add the progress spinner. + self.spinner = NSProgressIndicator(frame: .zero) + self.spinner.style = .spinning + self.spinner.isHidden = true + containerView.addSubview(self.spinner) + + // Apply a corner radius to the view. + containerView.wantsLayer = true + containerView.layer?.cornerRadius = 5.0 + + self.view = containerView + } + + override func viewDidLayout() { + super.viewDidLayout() + // Update the spinner. Autoresizing is not powerfull enough. + let pad: CGFloat = 8.0 + let size = self.view.bounds.height - pad*2 + self.spinner.frame = CGRect(x: pad, y: pad, width: size, height: size) + } + + // MARK: - Spinner + + func showSpinner() { + self.spinner.startAnimation(nil) + self.spinner.isHidden = false + self.contentView.isHidden = true + } + + func hideSpinner() { + self.spinner.stopAnimation(nil) + self.spinner.isHidden = true + self.contentView.isHidden = false + } + + // MARK: - Results + + func setSuggestions(_ suggestions: [Suggestion]) { + self.suggestions = suggestions + self.contentView.tableView.reloadData() + } + + // MARK: - Helper + + /// Get the current suggested content size. + func getSuggestedWindowSize() -> CGSize { + guard let tableView = self.contentView.tableView else { return .zero } + + let numberOfRows = min(tableView.numberOfRows, kMaxResults) + let rowHeight = tableView.rowHeight + let spacing = tableView.intercellSpacing + var frame = self.view.frame + frame.size.height = (rowHeight + spacing.height) * CGFloat(numberOfRows) + return frame.size + } + + // MARK: - Key events + + func processKeys(with theEvent: NSEvent) -> NSEvent? { + let keyUp: Bool = theEvent.type == .keyUp + + if let keyEvent = KeyCodes(rawValue: theEvent.keyCode) { + switch keyEvent { + case .arrowUp: + if !keyUp { + self.contentView.selectPreviousRow() + } + // Capture this event. + return nil + case .arrowDown: + if !keyUp { + self.contentView.selectNextRow() + } + // Capture this event. + return nil + case .return: + // Perform the action for the currently selected cell. + self.performActionForSelectedCell() + return nil + default: + break + } + } + + return theEvent + } + + // MARK: - Click + + @objc func performActionForSelectedCell(_ sender: AnyObject? = nil) { + let selectedRow = self.contentView.tableView.selectedRow + if selectedRow >= 0 && selectedRow < self.suggestions.count { + let suggestion = self.suggestions[selectedRow] + _ = self.target?.perform(self.action, with: suggestion) + } + } +} + + +extension SuggestionListViewController: NSTableViewDataSource { + func numberOfRows(in tableView: NSTableView) -> Int { + return self.suggestions.count + } +} + +extension SuggestionListViewController: NSTableViewDelegate { + func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { + return SuggestionTableRowView(tableView: tableView, row: row) + } + + func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + var cellView = tableView.makeView(withIdentifier: kCellIdentifier, owner: self) as? SuggestionTableCellView + if cellView == nil { + let cellFrame = CGRect(x: 0, y: 0, width: tableView.frame.width, height: tableView.rowHeight) + cellView = SuggestionTableCellView(frame: cellFrame) + cellView?.identifier = kCellIdentifier + } + // Assign the new values and update the cell. + cellView?.image = self.suggestions[row].image + cellView?.title = self.suggestions[row].title + cellView?.subtitle = self.suggestions[row].subtitle + cellView?.highlightedTitleRanges = self.suggestions[row].highlightedTitleRanges + cellView?.highlightedSubtitleRanges = self.suggestions[row].highlightedSubtitleRanges + cellView?.update() + + return cellView + } +} diff --git a/Sources/SuggestionPopup/ViewController/SuggestionTableCellView.swift b/Sources/SuggestionPopup/ViewController/SuggestionTableCellView.swift new file mode 100644 index 0000000..2bd3b11 --- /dev/null +++ b/Sources/SuggestionPopup/ViewController/SuggestionTableCellView.swift @@ -0,0 +1,137 @@ +// +// AutocompleteTableCellView.swift +// Popup +// +// Created by David Klopp on 26.12.20. +// + +import AppKit + +class SuggestionTableCellView: NSTableCellView { + /// The cells title. + var title: String = "" + + /// The cells subtitle. + var subtitle: String = "" + + /// The cells imageView. + var image: NSImage? { + get { self.imageView?.image } + set { self.imageView?.image = newValue } + } + + /// The parts of the title to highlight. + var highlightedTitleRanges: [Range] = [] + + /// The parts of the subtitle to highlight. + var highlightedSubtitleRanges: [Range] = [] + + /// A reference to the enclosing row view. + var isHighlighted: Bool = false { + didSet { self.update() } + } + + // MARK: - Constructor + + private func setup() { + // Add the textField + let textField = NSTextField(frame: .zero) + textField.isBezeled = false + textField.drawsBackground = false + textField.isEditable = false + textField.isSelectable = false + textField.maximumNumberOfLines = 2 + self.textField = textField + + // Add the imageViw + let imageView = NSImageView() + self.imageView = imageView + + self.addSubview(imageView) + self.addSubview(textField) + } + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + self.setup() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + self.setup() + } + + // MARK: - Reuse + + override func prepareForReuse() { + super.prepareForReuse() + self.image = nil + self.isHighlighted = false + } + + // MARK: - Layout + + override func layout() { + super.layout() + self.update() + } + + /// Update the title and subtitle text and color. + func update() { + // Create a concatenated string with title and subtitle. + let str = self.title + (self.subtitle.isEmpty ? "" : ("\n" + self.subtitle)) + let mutableAttriStr = NSMutableAttributedString(string: str) + + // The range of the title and subtitle string. + let titleRange = NSRange(location: 0, length: self.title.count) + let subtitleRange = NSRange(location: self.title.count + 1, length: self.subtitle.count) + // The paragraph style to use. + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineBreakMode = .byTruncatingTail + // The text color to use. + let titleFontSize = NSFont.systemFontSize + let titleColor: NSColor = self.isHighlighted ? .white : .labelColor + let subtitleFontSize = NSFont.labelFontSize + let subtitleColor: NSColor = self.isHighlighted ? .white : .secondaryLabelColor + + // Update the attributes string. + mutableAttriStr.addAttributes([.paragraphStyle: paragraphStyle, + .font: NSFont.systemFont(ofSize: titleFontSize), + .foregroundColor: titleColor], range: titleRange) + mutableAttriStr.addAttributes([.paragraphStyle: paragraphStyle, + .font: NSFont.systemFont(ofSize: subtitleFontSize), + .foregroundColor: subtitleColor], range: subtitleRange) + + // Update the title and subtitle highlight. + self.highlightedTitleRanges.forEach { + let range = NSMakeRange($0.startIndex, $0.count) + mutableAttriStr.addAttribute(.font, value: NSFont.boldSystemFont(ofSize: titleFontSize), range: range) + } + self.highlightedSubtitleRanges.forEach { + let range = NSMakeRange(subtitleRange.location + $0.startIndex, $0.count) + mutableAttriStr.addAttribute(.font, value: NSFont.boldSystemFont(ofSize: subtitleFontSize), range: range) + } + + // Layout the subviews. + let pad: CGFloat = 3 + var remainingWidth = self.frame.width + var frame: CGRect = .zero + + // If the imageView needs to be visible. + if self.image != nil { + let size = self.frame.height - pad*2 + frame = CGRect(x: pad, y: pad, width: size, height: size) + remainingWidth -= frame.maxX + self.imageView?.frame = frame + } + + // Center the textField vertically inside the cell + let textHeight = mutableAttriStr.size().height + frame = CGRect(x: 0, y: 0, width: remainingWidth, height: textHeight) + frame.origin.y = (self.frame.height-textHeight)/2.0 + frame.origin.x = self.frame.size.width - remainingWidth + pad + self.textField?.frame = frame + // Update the string. + self.textField?.attributedStringValue = mutableAttriStr + } +} diff --git a/Sources/SuggestionPopup/ViewController/SuggestionTableRowView.swift b/Sources/SuggestionPopup/ViewController/SuggestionTableRowView.swift new file mode 100644 index 0000000..9025937 --- /dev/null +++ b/Sources/SuggestionPopup/ViewController/SuggestionTableRowView.swift @@ -0,0 +1,66 @@ +// +// AutoCompleteTableRowView.swift +// Popup +// +// Created by David Klopp on 27.12.20. +// + +import AppKit + +class SuggestionTableRowView: NSTableRowView { + /// Reference to the parent table view. + weak var tableView: NSTableView? + /// The row number. + var row: Int + + /// Inform the cell if it should be highlighted. + override var isSelected: Bool { + didSet { + guard self.numberOfColumns > 0 else { return } + // Update the cells highlight state. + let cellView = self.view(atColumn: 0) as? SuggestionTableCellView + cellView?.isHighlighted = self.isSelected + } + } + + /// Always use a blue highlight for the cells. + override var isEmphasized: Bool { + get { return true } + set {} + } + + // MARK: - Constructor + + init(tableView: NSTableView, row: Int) { + self.tableView = tableView + self.row = row + super.init(frame: .zero) + } + + required init?(coder: NSCoder) { + fatalError("InitWithCoder not available.") + } + + // MARK: - Hover + + override func updateTrackingAreas() { + super.updateTrackingAreas() + // Define the traking area to execute the mouseEntered and mouseExited events. + for trackingArea in self.trackingAreas { + self.removeTrackingArea(trackingArea) + } + let options: NSTrackingArea.Options = [.mouseMoved, .mouseEnteredAndExited, .activeInActiveApp] + let trackingArea = NSTrackingArea(rect: self.bounds, options: options, owner: self, userInfo: nil) + self.addTrackingArea(trackingArea) + } + + override func mouseMoved(with event: NSEvent) { + super.mouseMoved(with: event) + self.tableView?.selectRowIndexes([row], byExtendingSelection: false) + } + + override func mouseExited(with event: NSEvent) { + super.mouseExited(with: event) + self.tableView?.selectRowIndexes([], byExtendingSelection: false) + } +} diff --git a/Sources/SuggestionPopup/WindowController/SuggestionWindow.swift b/Sources/SuggestionPopup/WindowController/SuggestionWindow.swift new file mode 100644 index 0000000..99a7dd3 --- /dev/null +++ b/Sources/SuggestionPopup/WindowController/SuggestionWindow.swift @@ -0,0 +1,63 @@ +// +// AutocompleteWindow.swift +// Popup +// +// Created by David Klopp on 26.12.20. +// + +import AppKit + +class SuggestionWindow: NSWindow { + + // MARK: - Constructor + + /// Create a bordless, transparent window which hosts the popup. + init() { + super.init(contentRect: .zero, styleMask: .borderless, backing: .buffered, defer: true) + // Configure the window + self.hasShadow = true + self.backgroundColor = .clear + self.isOpaque = false + self.isMovable = false + self.isMovableByWindowBackground = false + // Assign the contentViewController. + self.contentViewController = SuggestionListViewController() + } + + // MARK: - Spinner + + func showSpinner() { + // Use a fixed height. + var size = self.frame.size + size.height = 40 + self.setContentSize(size) + let contentViewController = self.contentViewController as? SuggestionListViewController + contentViewController?.showSpinner() + } + + func hideSpinner() { + let contentViewController = self.contentViewController as? SuggestionListViewController + contentViewController?.hideSpinner() + } + + // MARK: - Results + + func setSuggestions(_ suggestions: [Suggestion]) { + let contentViewController = self.contentViewController as? SuggestionListViewController + // Update the results. + contentViewController?.setSuggestions(suggestions) + // Update the content size. + let contentSize = contentViewController?.getSuggestedWindowSize() ?? .zero + let topLeftPoint = CGPoint(x: self.frame.minX, y: self.frame.maxY) + self.setContentSize(contentSize) + self.setFrameTopLeftPoint(topLeftPoint) + } +} + +// MARK: - Accessibility +extension SuggestionWindow { + /// We ignore this window for accessibility. + override func isAccessibilityElement() -> Bool { + return false + } +} diff --git a/Sources/SuggestionPopup/WindowController/SuggestionWindowController.swift b/Sources/SuggestionPopup/WindowController/SuggestionWindowController.swift new file mode 100644 index 0000000..bd2f54b --- /dev/null +++ b/Sources/SuggestionPopup/WindowController/SuggestionWindowController.swift @@ -0,0 +1,169 @@ +// +// AutoCompleteWindowController.swift +// Popup +// +// Created by David Klopp on 26.12.20. +// +import AppKit + +class SuggestionWindowController: NSWindowController, KeyResponder { + /// The textfield instance to manage. + private weak var searchField: NSTextField! + + /// A referenc to the searchFields parent window. + private var parentWindow: NSWindow? { return self.searchField.window } + + /// The currently entered search query. + private var searchQuery: String = "" + + /// A reference to the textDidChange observer. + private var textDidChangeObserver: NSObjectProtocol? + + /// A reference to the tableView selection change observer. + private var selecionChangedObserver: NSObjectProtocol? + + /// Callback handlers. + var onShow: SuggestionShowAction? + var onHide: SuggestionHideAction? + var onHighlight: SuggestionHighlightAction? + var onSelect: SuggestionSelectAction? + + // MARK: - Constructor + + init(searchField: NSTextField) { + self.searchField = searchField + let window = SuggestionWindow() + window.hidesOnDeactivate = false + + super.init(window: window) + + // Handle the cell selection. + let contentViewController = self.contentViewController as? SuggestionListViewController + contentViewController?.target = self + contentViewController?.action = #selector(self.selectedSuggestion(_:)) + + // Listen for text changes inside the textField. + self.registerNotifications() + } + + + // MARK: - Destructor + + deinit { + if let observer = self.textDidChangeObserver { + NotificationCenter.default.removeObserver(observer) + } + if let observer = self.selecionChangedObserver { + NotificationCenter.default.removeObserver(observer) + } + self.textDidChangeObserver = nil + self.selecionChangedObserver = nil + } + + // MARK: - TextField + + private func registerNotifications() { + let center = NotificationCenter.default + + self.textDidChangeObserver = center.addObserver(forName: NSTextField.textDidChangeNotification, + object: self.searchField, + queue: .main) { [weak self] _ in + // Save the current search query. + self?.searchQuery = self?.searchField.stringValue ?? "" + } + + // Listen for tableView cell highlighting. + guard let contentViewController = self.contentViewController as? SuggestionListViewController else { + return + } + let tableView = contentViewController.contentView.tableView + self.selecionChangedObserver = center.addObserver(forName: NSTableView.selectionDidChangeNotification, + object: tableView, + queue: .main) { [weak self] notification in + guard let row = tableView?.selectedRow, let queryString = self?.searchQuery else { return } + + let editor = self?.searchField.currentEditor() as? NSTextView + var suggestion: Suggestion? + if row >= 0 { + // Cell selected, display the suggestion. + suggestion = contentViewController.suggestions[row] + let title = suggestion!.title + + // If the search string matches the start of the title, highlight the remaining part, + // otherwise highlight the complete title. + self?.searchField.stringValue = title + let range = NSMakeRange(title.starts(with: queryString) ? queryString.count : 0, title.count) + editor?.setSelectedRange(range) + + } else { + // Cell was deselected. Reset the search query and clear the seletion. + self?.searchField.stringValue = queryString + editor?.moveToEndOfLine(nil) + } + self?.onHighlight?(queryString, suggestion) + } + } + + required init?(coder: NSCoder) { + fatalError("InitWithCoder not supported.") + } + + // MARK: - Selection + + @objc private func selectedSuggestion(_ suggestion: AnyObject) { + guard let suggestion = suggestion as? Suggestion else { return } + self.onSelect?(self.searchQuery, suggestion) + } + + // MARK: - Show / Hide + + /// Show the window. + /// - Return: True if the window can be shown, false otherwise. + @discardableResult + func show() -> Bool { + // Make sure the searchField is inside the view hierachy. + guard let window = self.window, !window.isVisible, + let parentWindow = self.parentWindow, + let searchFieldParent = self.searchField.superview else { return false } + // The window has the same width as the searchField. + var frame = window.frame + frame.size.width = self.searchField.frame.width + // Position the window directly below the searchField. + var location = searchFieldParent.convert(self.searchField.frame.origin, to: nil) + location = parentWindow.convertToScreen(CGRect(x: location.x, y: location.y, width: 0, height: 0)).origin + location.y -= 5 + // Apply the frame and position. + window.setContentSize(frame.size) + window.setFrameTopLeftPoint(location) + // Show the window + parentWindow.addChildWindow(window, ordered: .above) + self.onShow?() + return true + } + + /// Hide the window. + @discardableResult + func hide() -> Bool { + guard let window = self.window, window.isVisible else { return false } + window.parent?.removeChildWindow(window) + window.orderOut(nil) + self.onHide?() + return true + } + + // MARK: - Results + + func setSuggestions(_ suggestions: [Suggestion]) { + guard let window = self.window as? SuggestionWindow else { return } + window.setSuggestions(suggestions) + } + + // MARK: - Key Events + + /// Return the event, to allow other classes to handle the event or nil to capture it. + func processKeys(with theEvent: NSEvent) -> NSEvent? { + // Check if the window's contentViewController can handle the event. + let viewController = self.contentViewController as? KeyResponder + return viewController != nil ? viewController?.processKeys(with: theEvent) : theEvent + } +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift new file mode 100644 index 0000000..ba23566 --- /dev/null +++ b/Tests/LinuxMain.swift @@ -0,0 +1,7 @@ +import XCTest + +import SuggestionPopupTests + +var tests = [XCTestCaseEntry]() +tests += SuggestionPopupTests.allTests() +XCTMain(tests) diff --git a/Tests/SuggestionPopupTests/SuggestionPopupTests.swift b/Tests/SuggestionPopupTests/SuggestionPopupTests.swift new file mode 100644 index 0000000..ceccd7d --- /dev/null +++ b/Tests/SuggestionPopupTests/SuggestionPopupTests.swift @@ -0,0 +1,15 @@ +import XCTest +@testable import SuggestionPopup + +final class SuggestionPopupTests: XCTestCase { + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + //XCTAssertEqual(SuggestionPopup().text, "Hello, World!") + } + + static var allTests = [ + ("testExample", testExample), + ] +} diff --git a/Tests/SuggestionPopupTests/XCTestManifests.swift b/Tests/SuggestionPopupTests/XCTestManifests.swift new file mode 100644 index 0000000..5a0d34c --- /dev/null +++ b/Tests/SuggestionPopupTests/XCTestManifests.swift @@ -0,0 +1,9 @@ +import XCTest + +#if !canImport(ObjectiveC) +public func allTests() -> [XCTestCaseEntry] { + return [ + testCase(SuggestionPopupTests.allTests), + ] +} +#endif diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..078eb9dc8973e1d9d61070c0a88d0aa70958ce9a GIT binary patch literal 87532 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