mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-01 05:07:40 +00:00
183 lines
5.6 KiB
Swift
183 lines
5.6 KiB
Swift
/*
|
|
* Keyman is copyright (C) SIL Global. MIT License.
|
|
*
|
|
* Created by Shawn Schantz on 2026-02-24
|
|
*
|
|
* Object that represents a Keyman package
|
|
* KeymanPackage is immutable, but the state of the Keyboards in the keyboards array can change
|
|
*/
|
|
|
|
import Foundation
|
|
import AppKit
|
|
|
|
public class KeymanPackage: Identifiable, Hashable, Equatable {
|
|
static let defaultImage: NSImage? = {
|
|
var image: NSImage? = nil
|
|
if let imageUrl = Bundle.main.url(forResource: "SideImage", withExtension: "bmp") {
|
|
image = NSImage(contentsOf: imageUrl)
|
|
}
|
|
return image
|
|
}()
|
|
|
|
public let id: UUID
|
|
|
|
// the URL of the directory in which the package is contained
|
|
public let sourceDirectoryUrl: URL
|
|
// the URL of the kmp.json file for the package
|
|
|
|
public let keyboards: [Keyboard]
|
|
public let packageName: String
|
|
public let packageVersion: String
|
|
|
|
public let copyright: String?
|
|
public let jsonFileUrl: URL
|
|
public let readmeFileUrl: URL?
|
|
public let graphicFileUrl: URL?
|
|
public let graphicImage: NSImage?
|
|
|
|
/**
|
|
* create a KeymanPackage object using the PackageSource object created from the kmp.json
|
|
*/
|
|
init(packageSource: PackageSource) {
|
|
self.id = UUID()
|
|
self.packageName = packageSource.info.name.description
|
|
self.packageVersion = packageSource.info.version.description
|
|
self.copyright = packageSource.info.copyright?.description
|
|
self.sourceDirectoryUrl = packageSource.directoryUrl!
|
|
self.jsonFileUrl = packageSource.kmpJsonFileUrl!
|
|
|
|
if let readmeFilename = packageSource.readmeFilename {
|
|
let fileUrl = sourceDirectoryUrl.appendingPathComponent(readmeFilename)
|
|
self.readmeFileUrl = fileUrl
|
|
} else {
|
|
self.readmeFileUrl = nil
|
|
}
|
|
|
|
self.graphicFileUrl = KeymanPackage.buildGraphicFileUrl(source: packageSource)
|
|
self.graphicImage = KeymanPackage.loadImage(imageUrl: self.graphicFileUrl)
|
|
|
|
self.keyboards = KeymanPackage.buildKeyboardsArray(packageSource: packageSource)
|
|
}
|
|
|
|
/**
|
|
* build an array of Keyboard objects using the array of KeyboardSource object created from the kmp.json
|
|
*/
|
|
private static func buildKeyboardsArray (packageSource: PackageSource) -> [Keyboard] {
|
|
var keyboardsArray = [Keyboard]()
|
|
|
|
if let keyboards = packageSource.keyboards, let directoryUrl = packageSource.directoryUrl {
|
|
for keyboardSource in keyboards {
|
|
let keyboard = Keyboard(keyboardSource: keyboardSource, directoryUrl: directoryUrl)
|
|
keyboardsArray.append(keyboard)
|
|
}
|
|
}
|
|
|
|
return keyboardsArray
|
|
}
|
|
|
|
/**
|
|
* initializer that does not rely on package source -- provided to create unit test data
|
|
*/
|
|
public init(sourceDirectoryUrl: URL, keyboards: [Keyboard], packageName: String, packageVersion: String, copyright: String? = nil, jsonFileUrl: URL, readmeFileUrl: URL? = nil, graphicFileUrl: URL? = nil, graphicImage: NSImage? = nil) {
|
|
self.id = UUID()
|
|
self.sourceDirectoryUrl = sourceDirectoryUrl
|
|
self.keyboards = keyboards
|
|
self.packageName = packageName
|
|
self.packageVersion = packageVersion
|
|
self.copyright = copyright
|
|
self.jsonFileUrl = jsonFileUrl
|
|
self.readmeFileUrl = readmeFileUrl
|
|
self.graphicFileUrl = graphicFileUrl
|
|
self.graphicImage = graphicImage
|
|
}
|
|
|
|
/**
|
|
* find the keyboard with the specified key in the package and return its enabled state
|
|
*/
|
|
public func isKeyboardEnabled(keyboardKey: String) -> Bool {
|
|
var enabled = false
|
|
if let keyboard = self.keyboards.first(where: { $0.keyboardKey == keyboardKey }) {
|
|
enabled = keyboard.enabled
|
|
}
|
|
|
|
return enabled
|
|
}
|
|
|
|
/**
|
|
* find the keyboard with the specified key in the package and set its enabled state
|
|
*/
|
|
public func enableKeyboard(keyboardKey: String, enabled: Bool) {
|
|
let keyboard = self.keyboards.first(where: { $0.keyboardKey == keyboardKey })
|
|
if (keyboard != nil) {
|
|
keyboard!.enabled = enabled
|
|
}
|
|
}
|
|
|
|
/**
|
|
* get all the keys for enabled keyboards in the package
|
|
*/
|
|
public func getEnabledKeyboardsKeys() -> [String] {
|
|
var settingsKeyArray = [String]()
|
|
|
|
self.keyboards.forEach { keyboard in
|
|
if (keyboard.enabled) {
|
|
settingsKeyArray.append(keyboard.keyboardKey)
|
|
}
|
|
}
|
|
|
|
return settingsKeyArray
|
|
}
|
|
|
|
/**
|
|
* validate whether the package contain a kmx file for each of its keyboards
|
|
*/
|
|
public func validate() throws {
|
|
// if validateKmxFile throws an error, then the loop is stopped and the error is propagated
|
|
try self.keyboards.forEach { keyboard in
|
|
try keyboard.validateKmxFile()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* build the URL for the graphic file specified for the package
|
|
*/
|
|
static func buildGraphicFileUrl(source: PackageSource) -> URL? {
|
|
var fileUrl: URL? = nil
|
|
|
|
if let graphicFilename = source.graphicFilename {
|
|
fileUrl = source.directoryUrl!.appendingPathComponent(graphicFilename)
|
|
}
|
|
|
|
return fileUrl
|
|
}
|
|
|
|
/**
|
|
* create the image specified for the package
|
|
* if none specified, load the default image
|
|
*/
|
|
static func loadImage(imageUrl: URL?) -> NSImage? {
|
|
var packageImage: NSImage? = nil;
|
|
|
|
if let fileUrl = imageUrl, let image = NSImage(contentsOf: fileUrl) {
|
|
packageImage = image
|
|
} else {
|
|
packageImage = KeymanPackage.defaultImage
|
|
}
|
|
|
|
return packageImage
|
|
}
|
|
|
|
/**
|
|
* provided for Hashable conformance
|
|
*/
|
|
public func hash(into hasher: inout Hasher) {
|
|
hasher.combine(id) // only combine the unique ID
|
|
}
|
|
|
|
/**
|
|
* provided for Equatable conformance
|
|
*/
|
|
public static func == (lhs: KeymanPackage, rhs: KeymanPackage) -> Bool {
|
|
return lhs.id == rhs.id // only compare unique IDs
|
|
}
|
|
}
|