Skip to content

Instantly share code, notes, and snippets.

@jayrhynas
Last active April 20, 2020 12:57
Show Gist options
  • Save jayrhynas/75831a5edea1ab3b8330cc2d84de050a to your computer and use it in GitHub Desktop.
Save jayrhynas/75831a5edea1ab3b8330cc2d84de050a to your computer and use it in GitHub Desktop.
import AppKit
struct Icon {}
struct Canvas {}
protocol ToolController {
var icon: Icon { get }
var name: String { get }
func apply(/*...*/)
}
@dynamicMemberLookup
enum Tool: CaseIterable {
case pen
case brush
case fill
case text
private static var toolCache = DefaultDictionary<Tool, ToolController> { tool in
switch tool {
case .pen: return PenToolController()
case .brush: return BrushToolController()
case .fill: return FillToolController()
case .text: return TextToolController()
}
}
subscript<T>(dynamicMember keyPath: KeyPath<ToolController, T>) -> T {
Self.toolCache[self][keyPath: keyPath]
}
/*
private static let toolCache = [Tool: ToolController](uniqueKeysWithValues: Tool.allCases.map { tool in
switch tool {
case .pen: return (tool, PenToolController())
case .brush: return (tool, BrushToolController())
case .fill: return (tool, FillToolController())
case .text: return (tool, TextToolController())
}
})
subscript<T>(dynamicMember keyPath: KeyPath<ToolController, T>) -> T {
Self.toolCache[self]![keyPath: keyPath]
}
*/
}
struct DefaultDictionary<Key: Hashable, Value> {
private var storage: [Key: Value] = [:]
let getDefault: (Key) -> Value
init(getDefault: @escaping (Key) -> Value) {
self.getDefault = getDefault
}
subscript(_ key: Key) -> Value {
mutating get {
if let value = storage[key] {
return value
}
let value = getDefault(key)
storage[key] = value
return value
}
}
}
class PenToolController: ToolController {
var icon: Icon { Icon() }
var name: String { "Pen" }
func apply() {}
}
class BrushToolController: ToolController {
var icon: Icon { Icon() }
var name: String { "Brush" }
func apply() {}
}
class FillToolController: ToolController {
var icon: Icon { Icon() }
var name: String { "Fill" }
func apply() {}
}
class TextToolController: ToolController {
var icon: Icon { Icon() }
var name: String { "Text" }
func apply() {}
}
print(Tool.pen.name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment