mirror of
https://github.com/averello/SimDirs.git
synced 2026-02-06 20:26:15 +01:00
191 lines
6.8 KiB
Swift
191 lines
6.8 KiB
Swift
//
|
|
// SourceController.swift
|
|
// SimDirs
|
|
//
|
|
// Created by Casey Fleser on 4/30/16.
|
|
// Copyright © 2016 Quiet Spark. All rights reserved.
|
|
//
|
|
|
|
import Cocoa
|
|
|
|
protocol OutlineProvider {
|
|
var outlineTitle : String { get }
|
|
var outlineImage : NSImage? { get }
|
|
var childCount : Int { get }
|
|
|
|
func childAtIndex(_ index: Int) -> OutlineProvider?
|
|
}
|
|
|
|
extension OutlineProvider {
|
|
var expandable : Bool { return self.childCount > 0 }
|
|
}
|
|
|
|
class SourceController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate {
|
|
@IBOutlet weak var outlineView : NSOutlineView!
|
|
@IBOutlet weak var displayTypeView: NSSegmentedControl!
|
|
@IBOutlet weak var installedSwitch: NSSwitch!
|
|
|
|
enum DisplayType {
|
|
case versions(platforms: [SimPlatform])
|
|
case devices([SimDevice])
|
|
case apps([SimApp])
|
|
}
|
|
|
|
private var displayType: DisplayType = .versions(platforms: []) {
|
|
didSet {
|
|
self.outlineView.reloadData()
|
|
}
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
let (platforms, _, _) = self.prepareModel()
|
|
self.displayType = .versions(platforms: platforms)
|
|
}
|
|
|
|
private func prepareModel() -> (platforms: [SimPlatform], devices: [SimDevice], apps: [SimApp]) {
|
|
var platforms = SimPlatform.scan()
|
|
var devices = platforms.flatMap{ platform -> [SimDevice] in
|
|
platform.osVersions.flatMap { os -> [SimDevice] in
|
|
os.devices.map { device -> SimDevice in
|
|
let new = device.copy() as! SimDevice
|
|
new.name = "\(os.outlineTitle) - \(device.name)"
|
|
return new
|
|
}
|
|
}
|
|
}
|
|
let apps = platforms.flatMap{ platform -> [SimApp] in
|
|
platform.osVersions.flatMap { os -> [SimApp] in
|
|
os.devices.flatMap { device -> [SimApp] in
|
|
device.apps.map { app -> SimApp in
|
|
let new = app.copy() as! SimApp
|
|
new.displayName = new.outlineTitle + " - \(device.outlineTitle) - \(os.outlineTitle)"
|
|
return new
|
|
}
|
|
}
|
|
}
|
|
}.sorted { a,b in a.modificationDate ?? Date.distantPast > b.modificationDate ?? Date.distantPast }
|
|
if installedSwitch.state == .on {
|
|
platforms = platforms.compactMap { platform -> SimPlatform?
|
|
in
|
|
let new = platform.copy() as! SimPlatform
|
|
new.osVersions = platform.osVersions.compactMap { os -> SimOSVersion? in
|
|
let new = os.copy() as! SimOSVersion
|
|
new.devices = os.devices.filter { $0.expandable }
|
|
return new.devices.isEmpty ? nil : new
|
|
}
|
|
return new.osVersions.isEmpty ? nil : new
|
|
}
|
|
devices = devices
|
|
.filter { $0.expandable }
|
|
}
|
|
return (platforms, devices, apps)
|
|
}
|
|
|
|
// MARK: - NSOutlineViewDataSource -
|
|
|
|
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
|
|
switch self.displayType {
|
|
case .versions(let platforms):
|
|
return (item as? OutlineProvider)?.childCount ?? platforms.count
|
|
case .devices(let devices):
|
|
return (item as? OutlineProvider)?.childCount ?? devices.count
|
|
case .apps(let apps):
|
|
return (item as? OutlineProvider)?.childCount ?? apps.count
|
|
}
|
|
}
|
|
|
|
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
|
|
switch self.displayType {
|
|
case .versions(let platforms):
|
|
return (item as? OutlineProvider)?.childAtIndex(index) ?? platforms[index]
|
|
case .devices(let devices):
|
|
return (item as? OutlineProvider)?.childAtIndex(index) ?? devices[index]
|
|
case .apps(let apps):
|
|
return (item as? OutlineProvider)?.childAtIndex(index) ?? apps[index]
|
|
}
|
|
}
|
|
|
|
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
|
|
switch self.displayType {
|
|
case .versions(let platforms):
|
|
return (item as? OutlineProvider)?.expandable ?? (platforms.count > 0)
|
|
case .devices(let devices):
|
|
return (item as? OutlineProvider)?.expandable ?? (devices.count > 0)
|
|
case .apps(let apps):
|
|
return (item as? OutlineProvider)?.expandable ?? (apps.count > 0)
|
|
}
|
|
}
|
|
|
|
// MARK: - NSOutlineViewDelegate -
|
|
|
|
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
|
|
var view : NSTableCellView? = nil
|
|
var title = ""
|
|
var image : NSImage? = nil
|
|
|
|
if let outlineProvider = item as? OutlineProvider {
|
|
title = outlineProvider.outlineTitle
|
|
image = outlineProvider.outlineImage
|
|
}
|
|
|
|
if let outlineCell = outlineView.makeView(withIdentifier: convertToNSUserInterfaceItemIdentifier(image != nil ? "ImageCell" : "TextCell"), owner: self) as? NSTableCellView {
|
|
outlineCell.textField?.stringValue = title
|
|
outlineCell.imageView?.image = image
|
|
view = outlineCell
|
|
}
|
|
|
|
return view
|
|
}
|
|
|
|
func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {
|
|
return (item as? OutlineProvider)?.outlineImage != nil ? 24.0 : 20.0
|
|
}
|
|
|
|
func outlineViewSelectionDidChange(_ notification: Notification) {
|
|
if let thing = (self.parent as? NSSplitViewController)?.splitViewItems[safe: 1]?.viewController as? DetailController {
|
|
var selectedItem : AnyObject? = nil
|
|
let row = self.outlineView.selectedRow
|
|
|
|
if row != NSNotFound {
|
|
selectedItem = self.outlineView.item(atRow: row) as AnyObject?
|
|
}
|
|
|
|
thing.selectedItem = selectedItem
|
|
}
|
|
}
|
|
|
|
// MARK: - Interaction -
|
|
|
|
@IBAction private func displayTypeChanged(_ sender: NSSegmentedControl) {
|
|
self.update()
|
|
}
|
|
|
|
@IBAction func installedFilterChanged(_ sender: NSSwitch) {
|
|
self.update()
|
|
}
|
|
|
|
@IBAction func rescan(_ sender: AnyObject?) {
|
|
self.update()
|
|
}
|
|
|
|
private func update() {
|
|
let (platforms, devices, apps) = self.prepareModel()
|
|
switch self.displayTypeView.selectedSegment {
|
|
case 0:
|
|
self.displayType = .versions(platforms: platforms)
|
|
case 1:
|
|
self.displayType = .devices(devices)
|
|
case 2:
|
|
self.displayType = .apps(apps)
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// Helper function inserted by Swift 4.2 migrator.
|
|
fileprivate func convertToNSUserInterfaceItemIdentifier(_ input: String) -> NSUserInterfaceItemIdentifier {
|
|
return NSUserInterfaceItemIdentifier(rawValue: input)
|
|
}
|