diff --git a/SimDirs.xcodeproj/project.pbxproj b/SimDirs.xcodeproj/project.pbxproj index e1db3ff..11ff922 100644 --- a/SimDirs.xcodeproj/project.pbxproj +++ b/SimDirs.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ C948814E1CD3EA5500209C09 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C948814D1CD3EA5500209C09 /* AppDelegate.swift */; }; C94881501CD3EA5500209C09 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C948814F1CD3EA5500209C09 /* Assets.xcassets */; }; C94881531CD3EA5500209C09 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = C94881511CD3EA5500209C09 /* MainMenu.xib */; }; + C9AE594A1CD4EAD80090655C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C9AE59481CD4EAD80090655C /* Main.storyboard */; }; + C9AE594C1CD4F1C70090655C /* SourceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9AE594B1CD4F1C70090655C /* SourceController.swift */; }; C9B7078A1A03A5C70001CB77 /* QSSimAppInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = C9B707891A03A5C70001CB77 /* QSSimAppInfo.m */; }; C9B707901A03A63E0001CB77 /* QSSimDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = C9B7078F1A03A63E0001CB77 /* QSSimDeviceInfo.m */; }; C9B707931A03B6C30001CB77 /* QSSimViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C9B707921A03B6C30001CB77 /* QSSimViewController.m */; }; @@ -52,6 +54,9 @@ C948814F1CD3EA5500209C09 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; C94881521CD3EA5500209C09 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; C94881541CD3EA5500209C09 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C9AE59491CD4EAD80090655C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + C9AE594B1CD4F1C70090655C /* SourceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceController.swift; sourceTree = ""; }; + C9AE594D1CD503850090655C /* CUINamedLayerStack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUINamedLayerStack.h; sourceTree = ""; }; C9B707881A03A5C70001CB77 /* QSSimAppInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QSSimAppInfo.h; sourceTree = ""; }; C9B707891A03A5C70001CB77 /* QSSimAppInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QSSimAppInfo.m; sourceTree = ""; }; C9B7078E1A03A63E0001CB77 /* QSSimDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QSSimDeviceInfo.h; sourceTree = ""; }; @@ -164,10 +169,12 @@ children = ( C9ECF8A21CD4CEC800499965 /* Model */, C9ECF8AE1CD4E13500499965 /* Support */, + C9ECF8B41CD4E96A00499965 /* UI */, C948814D1CD3EA5500209C09 /* AppDelegate.swift */, C9ECF8AB1CD4CF8400499965 /* Support.swift */, C948814F1CD3EA5500209C09 /* Assets.xcassets */, C94881511CD3EA5500209C09 /* MainMenu.xib */, + C9AE59481CD4EAD80090655C /* Main.storyboard */, C94881541CD3EA5500209C09 /* Info.plist */, ); path = SimDirs2; @@ -188,6 +195,7 @@ isa = PBXGroup; children = ( C9ECF8AF1CD4E13500499965 /* CUICatalog.h */, + C9AE594D1CD503850090655C /* CUINamedLayerStack.h */, C9ECF8B01CD4E14C00499965 /* SimDirs-Bridge.h */, ); path = Support; @@ -201,6 +209,14 @@ name = Frameworks; sourceTree = ""; }; + C9ECF8B41CD4E96A00499965 /* UI */ = { + isa = PBXGroup; + children = ( + C9AE594B1CD4F1C70090655C /* SourceController.swift */, + ); + path = UI; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -319,6 +335,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + C9AE594A1CD4EAD80090655C /* Main.storyboard in Resources */, C94881501CD3EA5500209C09 /* Assets.xcassets in Resources */, C94881531CD3EA5500209C09 /* MainMenu.xib in Resources */, ); @@ -353,6 +370,7 @@ files = ( C9ECF8A41CD4CEE300499965 /* SimPlatform.swift in Sources */, C9ECF8A61CD4CF1600499965 /* SimOSVersion.swift in Sources */, + C9AE594C1CD4F1C70090655C /* SourceController.swift in Sources */, C9ECF8AA1CD4CF5A00499965 /* SimApp.swift in Sources */, C948814E1CD3EA5500209C09 /* AppDelegate.swift in Sources */, C9ECF8A81CD4CF4000499965 /* SimDevice.swift in Sources */, @@ -387,6 +405,14 @@ name = MainMenu.xib; sourceTree = ""; }; + C9AE59481CD4EAD80090655C /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + C9AE59491CD4EAD80090655C /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/SimDirs/Base.lproj/MainMenu.xib b/SimDirs/Base.lproj/MainMenu.xib index 4625146..3525df6 100644 --- a/SimDirs/Base.lproj/MainMenu.xib +++ b/SimDirs/Base.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -122,7 +122,7 @@ - + @@ -142,9 +142,10 @@ + - + @@ -263,7 +264,7 @@ - + @@ -271,7 +272,7 @@ - + @@ -279,7 +280,7 @@ - + @@ -287,7 +288,7 @@ - + @@ -295,7 +296,7 @@ - + @@ -303,7 +304,7 @@ - + @@ -324,7 +325,7 @@ - + @@ -332,7 +333,7 @@ - + @@ -380,7 +381,7 @@ - + @@ -388,7 +389,7 @@ - + @@ -396,7 +397,7 @@ - + @@ -404,7 +405,7 @@ - + @@ -412,7 +413,7 @@ - + @@ -420,7 +421,7 @@ - + @@ -428,7 +429,7 @@ - + @@ -436,7 +437,7 @@ - + @@ -457,7 +458,7 @@ - + @@ -465,7 +466,7 @@ - + @@ -577,7 +578,7 @@ - - + + diff --git a/SimDirs2/Assets.xcassets/Contents.json b/SimDirs2/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/SimDirs2/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/SimDirs2/Assets.xcassets/default_icon.imageset/Contents.json b/SimDirs2/Assets.xcassets/default_icon.imageset/Contents.json new file mode 100644 index 0000000..1201a35 --- /dev/null +++ b/SimDirs2/Assets.xcassets/default_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "default_icon.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "defaultt_icon@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/SimDirs2/Assets.xcassets/default_icon.imageset/default_icon.png b/SimDirs2/Assets.xcassets/default_icon.imageset/default_icon.png new file mode 100644 index 0000000..f614703 Binary files /dev/null and b/SimDirs2/Assets.xcassets/default_icon.imageset/default_icon.png differ diff --git a/SimDirs2/Assets.xcassets/default_icon.imageset/defaultt_icon@2x.png b/SimDirs2/Assets.xcassets/default_icon.imageset/defaultt_icon@2x.png new file mode 100644 index 0000000..16a0748 Binary files /dev/null and b/SimDirs2/Assets.xcassets/default_icon.imageset/defaultt_icon@2x.png differ diff --git a/SimDirs2/Base.lproj/Main.storyboard b/SimDirs2/Base.lproj/Main.storyboard new file mode 100644 index 0000000..efda997 --- /dev/null +++ b/SimDirs2/Base.lproj/Main.storyboard @@ -0,0 +1,845 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SimDirs2/Base.lproj/MainMenu.xib b/SimDirs2/Base.lproj/MainMenu.xib index 163a1c7..8c82807 100644 --- a/SimDirs2/Base.lproj/MainMenu.xib +++ b/SimDirs2/Base.lproj/MainMenu.xib @@ -671,11 +671,421 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SimDirs2/Info.plist b/SimDirs2/Info.plist index f406a49..5d5ba0f 100644 --- a/SimDirs2/Info.plist +++ b/SimDirs2/Info.plist @@ -26,8 +26,8 @@ $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright Copyright © 2016 Quiet Spark. All rights reserved. - NSMainNibFile - MainMenu + NSMainStoryboardFile + Main NSPrincipalClass NSApplication diff --git a/SimDirs2/Model/SimApp.swift b/SimDirs2/Model/SimApp.swift index 7afb97f..fc02fcf 100644 --- a/SimDirs2/Model/SimApp.swift +++ b/SimDirs2/Model/SimApp.swift @@ -8,7 +8,7 @@ import Foundation -class SimApp { +class SimApp: OutlineProvider { let bundleID : String var name = "" var shortVersion = "" @@ -43,6 +43,11 @@ class SimApp { self.bundleID = bundleID } + func completeScan() { + self.refinePaths() + self.loadInfoPlist() + } + func updateFromLastLaunchMapInfo(launchBundleInfo: [String : AnyObject]) { self.bundlePath = launchBundleInfo["BundleContainer"] as? String self.sandboxPath = launchBundleInfo["Container"] as? String @@ -55,11 +60,6 @@ class SimApp { self.sandboxPath = compatInfo["sandboxPath"] as? String } - func completeInitialization() { - self.refinePaths() - self.loadInfoPlist() - } - func refinePaths() { guard let bundleURL = self.bundleURL else { return } let fileMgr = NSFileManager.defaultManager() @@ -83,21 +83,22 @@ class SimApp { func loadInfoPlist() { guard let bundleURL = self.bundleURL else { return } let infoPlistURL = bundleURL.URLByAppendingPathComponent("Info.plist") -// let assetFileURL = bundleURL.URLByAppendingPathComponent("Assets.car") if let plistInfo = NSPropertyListSerialization.propertyListWithURL(infoPlistURL) { self.name = plistInfo[String(kCFBundleNameKey)] as? String ?? "" self.shortVersion = plistInfo["CFBundleShortVersionString"] as? String ?? "" self.version = plistInfo[String(kCFBundleVersionKey)] as? String ?? "" - -// if assetFileURL.validPath { -// if let catalog = try? CUICatalog.init(URL: assetFileURL) { -//print("\(catalog.allImageNames)") -// } -// } if let bundleIcons = plistInfo["CFBundleIcons"] as? [String : AnyObject] { - if let primaryIcon = bundleIcons["CFBundlePrimaryIcon"] as? [String : AnyObject] { + let primaryIconValue = bundleIcons["CFBundlePrimaryIcon"].flatMap { item -> [String : AnyObject]? in + switch item { + case let dict as [String : AnyObject]: return dict + case let str as String: return ["CFBundleIconFiles" : [str]] + default: return nil + } + } + + if let primaryIcon = primaryIconValue { if let bundleIconFiles = primaryIcon["CFBundleIconFiles"] as? [String] { for iconName in bundleIconFiles { var iconURL = bundleURL.URLByAppendingPathComponent(iconName) @@ -108,25 +109,62 @@ class SimApp { iconURL = iconURL.URLByAppendingPathExtension("png") } - if let icon = NSImage(contentsOfURL: iconURL) { - if self.icon?.size.width ?? 0 < icon.size.width { - self.icon = icon +// .car files not yet working :/ + +// if !iconURL.validPath && !icon2XURL.validPath { // Believe this would only happen once per bundle +// let assetFileURL = bundleURL.URLByAppendingPathComponent("Assets.car") +// +// if assetFileURL.validPath { +// if let catalog = try? CUICatalog.init(URL: assetFileURL) { +// let catalogImages = catalog.imagesWithName(iconName) +// +// for catalogImage in catalogImages { +// if let namedImage = catalogImage as? CUINamedImage where !(namedImage is CUINamedLayerStack) { +// if self.icon?.size.width ?? 0 < namedImage.size.width { +// let imageRep = NSBitmapImageRep(CGImage: namedImage.image) +// +// imageRep.size = namedImage.size +// if let pngData = imageRep.representationUsingType(.NSPNGFileType, properties: [NSImageInterlaced : false]) where pngData.length > 0 { +// self.icon = NSImage(data: pngData) +// } +// self.icon = NSImage(CGImage: namedImage.image, size: namedImage.size) +// } +// } +// } +// } +// } +// } +// else { + if let icon = NSImage(contentsOfURL: iconURL) { + if self.icon?.size.width ?? 0 < icon.size.width { + self.icon = icon + } } - } - - if let icon = NSImage(contentsOfURL: icon2XURL) { - if self.icon?.size.width ?? 0 < icon.size.width { - self.icon = icon + + if let icon = NSImage(contentsOfURL: icon2XURL) { + if self.icon?.size.width ?? 0 < icon.size.width { + self.icon = icon + } } - } +// } } } } } if self.icon == nil { - self.icon = NSImage(named: "defaultIcon") + self.icon = NSImage(named: "default_icon") } } } + + // MARK: - OutlineProvider - + + var outlineTitle : String { return self.name } + var outlineImage : NSImage? { return self.icon } + var childCount : Int { return 0 } + + func childAtIndex(index: Int) -> OutlineProvider? { + return nil + } } diff --git a/SimDirs2/Model/SimDevice.swift b/SimDirs2/Model/SimDevice.swift index f626d80..ea28747 100644 --- a/SimDirs2/Model/SimDevice.swift +++ b/SimDirs2/Model/SimDevice.swift @@ -8,7 +8,7 @@ import Foundation -class SimDevice { +class SimDevice: OutlineProvider { let name : String let udid : String let baseURL : NSURL @@ -23,9 +23,17 @@ class SimDevice { self.gatherAppInfoFromAppState() // self.gatherAppInfoFromCaches() obsolete self.gatherAppInfoFromInstallLogs() - self.cleanupAndRefineAppList() } + func completeScan() { + self.apps = self.apps.filter { return $0.hasValidPaths } + + for app in self.apps { + app.completeScan() + } + self.apps.sortInPlace { $0.name < $1.name } + } + // LastLaunchServicesMap.plist seems to be the most reliable location to gather app info func gatherAppInfoFromLastLaunchMap() { let launchMapInfoURL = self.baseURL.URLByAppendingPathComponent("data/Library/MobileInstallation/LastLaunchServicesMap.plist") @@ -102,13 +110,13 @@ class SimDevice { } } - func cleanupAndRefineAppList() { - self.apps = self.apps.filter { return $0.hasValidPaths } - - for simApp in self.apps { - simApp.completeInitialization() - } - - // sort? + // MARK: - OutlineProvider - + + var outlineTitle : String { return self.name } + var outlineImage : NSImage? { return nil } + var childCount : Int { return self.apps.count } + + func childAtIndex(index: Int) -> OutlineProvider? { + return self.apps[index] } } diff --git a/SimDirs2/Model/SimOSVersion.swift b/SimDirs2/Model/SimOSVersion.swift index b1d0911..9ced382 100644 --- a/SimDirs2/Model/SimOSVersion.swift +++ b/SimDirs2/Model/SimOSVersion.swift @@ -8,7 +8,7 @@ import Foundation -class SimOSVersion { +class SimOSVersion: OutlineProvider { let name : String var devices = [SimDevice]() @@ -16,6 +16,13 @@ class SimOSVersion { self.name = name } + func completeScan() { + for device in self.devices { + device.completeScan() + } + self.devices.sortInPlace { $0.name < $1.name } + } + func updateWithDeviceInfo(deviceInfo: [String : AnyObject], baseURL: NSURL) { guard let deviceName = deviceInfo["name"] as? String else { return } guard let deviceUDID = deviceInfo["UDID"] as? String else { return } @@ -23,4 +30,14 @@ class SimOSVersion { self.devices.append(device) } + + // MARK: - OutlineProvider - + + var outlineTitle : String { return self.name } + var outlineImage : NSImage? { return nil } + var childCount : Int { return self.devices.count } + + func childAtIndex(index: Int) -> OutlineProvider? { + return self.devices[index] + } } diff --git a/SimDirs2/Model/SimPlatform.swift b/SimDirs2/Model/SimPlatform.swift index 77b60a4..420a1b5 100644 --- a/SimDirs2/Model/SimPlatform.swift +++ b/SimDirs2/Model/SimPlatform.swift @@ -8,7 +8,7 @@ import Foundation -class SimPlatform { +class SimPlatform: OutlineProvider { let name : String var osVersions = [SimOSVersion]() @@ -36,18 +36,39 @@ class SimPlatform { } } } - - return platforms + + for platform in platforms { + platform.completeScan() + } + + return platforms.sort { $0.name < $1.name } } init(runtimeComponents: [String], deviceInfo: [String : AnyObject]) { self.name = runtimeComponents[0] } + func completeScan() { + for osVersion in self.osVersions { + osVersion.completeScan() + } + self.osVersions.sortInPlace { $0.name > $1.name } + } + func updateWith(runtimeComponents: [String], deviceInfo: [String : AnyObject], baseURL: NSURL) { let versionID = "\(runtimeComponents[safe: 1] ?? "0").\(runtimeComponents[safe: 2] ?? "0")" let osVersion = self.osVersions.match({ $0.name == versionID }, orMake: { SimOSVersion(name: versionID, deviceInfo: deviceInfo) }) osVersion.updateWithDeviceInfo(deviceInfo, baseURL: baseURL) } + + // MARK: - OutlineProvider - + + var outlineTitle : String { return self.name } + var outlineImage : NSImage? { return nil } + var childCount : Int { return self.osVersions.count } + + func childAtIndex(index: Int) -> OutlineProvider? { + return self.osVersions[index] + } } diff --git a/SimDirs2/Support/CUINamedLayerStack.h b/SimDirs2/Support/CUINamedLayerStack.h new file mode 100644 index 0000000..0a2d92d --- /dev/null +++ b/SimDirs2/Support/CUINamedLayerStack.h @@ -0,0 +1,28 @@ +// +// CUINamedLayerStack.h +// SimDirs +// +// Created by Casey Fleser on 4/30/16. +// Copyright © 2016 Quiet Spark. All rights reserved. +// + +#import "CUICatalog.h" + +@interface CUINamedLayerStack : CUINamedImage + +@property(retain, nonatomic) NSArray *layers; // @synthesize layers=_layers; + +@property(readonly, nonatomic) struct CGImage *radiosityImage; +@property(readonly, nonatomic) struct CGImage *flattenedImage; +- (id)layerImageAtIndex:(unsigned long long)arg1; +@property(readonly, nonatomic) struct CGSize size; + +@end + +@interface CUINamedLayerImage : CUINamedImage + +@property(nonatomic) int blendMode; // @synthesize blendMode=_blendMode; +@property(nonatomic) double opacity; // @synthesize opacity=_opacity; +@property(nonatomic) struct CGRect frame; // @synthesize frame=_frame; + +@end diff --git a/SimDirs2/Support/SimDirs-Bridge.h b/SimDirs2/Support/SimDirs-Bridge.h index ad36776..a9c3b63 100644 --- a/SimDirs2/Support/SimDirs-Bridge.h +++ b/SimDirs2/Support/SimDirs-Bridge.h @@ -7,3 +7,4 @@ // #import "CUICatalog.h" +#import "CUINamedLayerStack.h" diff --git a/SimDirs2/UI/SourceController.swift b/SimDirs2/UI/SourceController.swift new file mode 100644 index 0000000..39039e4 --- /dev/null +++ b/SimDirs2/UI/SourceController.swift @@ -0,0 +1,111 @@ +// +// SourceController.swift +// SimDirs +// +// Created by Casey Fleser on 4/30/16. +// Copyright © 2016 Quiet Spark. All rights reserved. +// + +import Cocoa + +protocol OutlineProvider: AnyObject { + 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 { + var platforms = [SimPlatform]() + + override func viewDidLoad() { + super.viewDidLoad() + + self.rescan() + } + + func rescan() { + self.platforms = SimPlatform.scan() + } + + // MARK: - NSOutlineViewDataSource - + + func outlineView(outlineView: NSOutlineView, numberOfChildrenOfItem item: AnyObject?) -> Int { + return (item as? OutlineProvider)?.childCount ?? self.platforms.count + } + + func outlineView(outlineView: NSOutlineView, child index: Int, ofItem item: AnyObject?) -> AnyObject { + return (item as? OutlineProvider)?.childAtIndex(index) ?? self.platforms[index] + } + + func outlineView(outlineView: NSOutlineView, isItemExpandable item: AnyObject) -> Bool { + return (item as? OutlineProvider)?.expandable ?? (self.platforms.count > 0) + } + + // MARK: - NSOutlineViewDelegate - + + func outlineView(outlineView: NSOutlineView, viewForTableColumn tableColumn: NSTableColumn?, item: AnyObject) -> 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.makeViewWithIdentifier(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: AnyObject) -> CGFloat { + return (item as? OutlineProvider)?.outlineImage != nil ? 24.0 : 20.0 + } + + func outlineViewSelectionDidChange(notification: NSNotification) { + NSLog("boop") + } + +//- (void) outlineViewSelectionDidChange: (NSNotification *) inNotification +//{ +// NSInteger row = [self.locationOutline selectedRow]; +// BOOL selectedTab = NO; +// +// self.selectedDevice = nil; +// self.selectedApp = nil; +// +// if (row != -1) { +// id item = [self.locationOutline itemAtRow: row]; +// +// if ([item isKindOfClass: [QSSimDeviceInfo class]]) { +// self.selectedDevice = item; +// [self updateDeviceTabWithSelection]; +// +// [self.infoTabView selectTabViewItemWithIdentifier: @"device"]; +// selectedTab = YES; +// } +// if ([item isKindOfClass: [QSSimAppInfo class]]) { +// self.selectedApp = item; +// [self updateAppTabWithSelection]; +// +// [self.infoTabView selectTabViewItemWithIdentifier: @"app"]; +// selectedTab = YES; +// } +// } +// +// if (!selectedTab) { +// [self.infoTabView selectTabViewItemWithIdentifier: @"empty"]; +// } +//} +// +}