Conversion to Swift3

This commit is contained in:
Charles Magahern
2017-05-13 00:40:03 -07:00
parent 687b45c73a
commit 091af0844a
16 changed files with 353 additions and 325 deletions

View File

@@ -247,7 +247,8 @@
TargetAttributes = { TargetAttributes = {
0C3CAEA31C3350C800B856AD = { 0C3CAEA31C3350C800B856AD = {
CreatedOnToolsVersion = 7.2; CreatedOnToolsVersion = 7.2;
DevelopmentTeam = FZ6BMA5HA9; DevelopmentTeam = 64S2YWUDC5;
LastSwiftMigration = 0810;
}; };
}; };
}; };
@@ -422,11 +423,15 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
INFOPLIST_FILE = "$(SRCROOT)/XIONControlPanel/SupportingFiles/Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/XIONControlPanel/SupportingFiles/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/Swift",
);
PRODUCT_BUNDLE_IDENTIFIER = com.xionsf.XIONControlPanel; PRODUCT_BUNDLE_IDENTIFIER = com.xionsf.XIONControlPanel;
PRODUCT_NAME = XION; PRODUCT_NAME = XION;
PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE = "";
SWIFT_OBJC_BRIDGING_HEADER = "XIONControlPanel/SupportingFiles/XIONControlPanel-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "XIONControlPanel/SupportingFiles/XIONControlPanel-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
}; };
name = Debug; name = Debug;
@@ -440,10 +445,15 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
INFOPLIST_FILE = "$(SRCROOT)/XIONControlPanel/SupportingFiles/Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/XIONControlPanel/SupportingFiles/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/Swift",
);
PRODUCT_BUNDLE_IDENTIFIER = com.xionsf.XIONControlPanel; PRODUCT_BUNDLE_IDENTIFIER = com.xionsf.XIONControlPanel;
PRODUCT_NAME = XION; PRODUCT_NAME = XION;
PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE = "";
SWIFT_OBJC_BRIDGING_HEADER = "XIONControlPanel/SupportingFiles/XIONControlPanel-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "XIONControlPanel/SupportingFiles/XIONControlPanel-Bridging-Header.h";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
}; };
name = Release; name = Release;

View File

@@ -14,35 +14,35 @@ class AppDelegate: UIResponder, UIApplicationDelegate
var window: UIWindow? var window: UIWindow?
var mainViewController: MainViewController = MainViewController() var mainViewController: MainViewController = MainViewController()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{ {
application.statusBarHidden = true application.isStatusBarHidden = true
self.window = UIWindow(frame: UIScreen.mainScreen().bounds) self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = self.mainViewController self.window?.rootViewController = self.mainViewController
self.window?.makeKeyAndVisible() self.window?.makeKeyAndVisible()
return true return true
} }
func applicationDidBecomeActive(application: UIApplication) func applicationDidBecomeActive(_ application: UIApplication)
{ {
self.mainViewController.viewDidAppear(false) self.mainViewController.viewDidAppear(false)
} }
func applicationDidEnterBackground(application: UIApplication) func applicationDidEnterBackground(_ application: UIApplication)
{ {
self.mainViewController.viewDidDisappear(false) self.mainViewController.viewDidDisappear(false)
} }
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask
{ {
var mask: UIInterfaceOrientationMask = .Portrait var mask: UIInterfaceOrientationMask = .portrait
if (UIDevice.currentDevice().userInterfaceIdiom == .Phone) { if (UIDevice.current.userInterfaceIdiom == .phone) {
mask = UIInterfaceOrientationMask.Portrait mask = UIInterfaceOrientationMask.portrait
} else { } else {
mask = UIInterfaceOrientationMask.All mask = UIInterfaceOrientationMask.all
} }
return mask return mask

View File

@@ -10,15 +10,15 @@ import UIKit
class MainViewController: UIViewController, SwitchesViewControllerDelegate class MainViewController: UIViewController, SwitchesViewControllerDelegate
{ {
private var _server: WemoServer fileprivate var _server: WemoServer
private var _visualizationController: VisualizationViewController = VisualizationViewController() fileprivate var _visualizationController: VisualizationViewController = VisualizationViewController()
private var _switchesController: SwitchesViewController = SwitchesViewController() fileprivate var _switchesController: SwitchesViewController = SwitchesViewController()
private var _headerView: HeaderView = HeaderView() fileprivate var _headerView: HeaderView = HeaderView()
private var _updateDevices: Bool = false fileprivate var _updateDevices: Bool = false
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
{ {
let url = NSURL(string: "http://midna.xionsf.com:5000") let url = URL(string: "http://midna.xionsf.com:5000")
_server = WemoServer(url!) _server = WemoServer(url!)
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
@@ -35,7 +35,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
{ {
super.viewDidLoad() super.viewDidLoad()
self.view.backgroundColor = UIColor.blackColor() self.view.backgroundColor = UIColor.black
self.addChildViewController(_visualizationController) self.addChildViewController(_visualizationController)
self.view.addSubview(_visualizationController.view) self.view.addSubview(_visualizationController.view)
@@ -46,7 +46,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
self.view.addSubview(_headerView) self.view.addSubview(_headerView)
_updateConnectivityStatus(.Disconnected) _updateConnectivityStatus(.disconnected)
} }
override func viewDidLayoutSubviews() override func viewDidLayoutSubviews()
@@ -64,7 +64,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
) )
let bodyBounds = CGRect( let bodyBounds = CGRect(
x: 0.0, x: 0.0,
y: CGRectGetMaxY(headerBounds), y: headerBounds.maxY,
width: bounds.size.width, width: bounds.size.width,
height: bounds.size.height - headerBounds.size.height height: bounds.size.height - headerBounds.size.height
) )
@@ -81,8 +81,8 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
var switchesOriginX: CGFloat = 0.0 var switchesOriginX: CGFloat = 0.0
var switchesWidth: CGFloat = 0.0 var switchesWidth: CGFloat = 0.0
if (horizontalSizeClass == .Regular) { if (horizontalSizeClass == .regular) {
switchesOriginX = CGRectGetMaxX(visualizationFrame) switchesOriginX = visualizationFrame.maxX
switchesWidth = bodyBounds.size.width - visualizationFrame.size.width switchesWidth = bodyBounds.size.width - visualizationFrame.size.width
} else { } else {
switchesOriginX = 0.0 switchesOriginX = 0.0
@@ -98,32 +98,32 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
_switchesController.view.frame = switchesControllerFrame _switchesController.view.frame = switchesControllerFrame
} }
override func viewDidAppear(animated: Bool) override func viewDidAppear(_ animated: Bool)
{ {
super.viewDidAppear(animated) super.viewDidAppear(animated)
_headerView.xionLogoView.beginAnimating() _headerView.xionLogoView.beginAnimating()
if (!_server.connected) { if (!_server.connected) {
_updateConnectivityStatus(.Connecting) _updateConnectivityStatus(.connecting)
_server.connect { (error: NSError?) -> Void in _server.connect { (error: Error?) -> Void in
if (error == nil) { if (error == nil) {
self._reloadDevices() self._reloadDevices()
self._startUpdatingDevices() self._startUpdatingDevices()
} else { } else {
self._updateConnectivityStatus(.Error) self._updateConnectivityStatus(.error)
} }
} }
} }
} }
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
{ {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) super.viewWillTransition(to: size, with: coordinator)
_updateSizeClassPresentation() _updateSizeClassPresentation()
} }
override func prefersStatusBarHidden() -> Bool override var prefersStatusBarHidden : Bool
{ {
return true return true
} }
@@ -141,12 +141,12 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
// MARK: SwitchesViewControllerDelegate // MARK: SwitchesViewControllerDelegate
func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice]) func switchesViewControllerDidToggleDevices(_ controller: SwitchesViewController, devices: [WemoDevice])
{ {
_updateVisualization(true) _updateVisualization(true)
for device in devices { for device in devices {
_server.toggleDevice(device, state: device.state, completion: { (error: NSError?) -> Void in }) _server.toggleDevice(device, state: device.state, completion: { (error: Error?) -> Void in })
} }
} }
@@ -155,18 +155,18 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
internal func _updateSizeClassPresentation() internal func _updateSizeClassPresentation()
{ {
let horizontalSizeClass = self.traitCollection.horizontalSizeClass let horizontalSizeClass = self.traitCollection.horizontalSizeClass
if (horizontalSizeClass == .Regular) { if (horizontalSizeClass == .regular) {
_visualizationController.view.hidden = false _visualizationController.view.isHidden = false
} else { } else {
_visualizationController.view.hidden = true _visualizationController.view.isHidden = true
} }
} }
internal func _updateVisualization(animated: Bool) internal func _updateVisualization(_ animated: Bool)
{ {
var activatedDevicesCount = 0 var activatedDevicesCount = 0
for device in self.devices { for device in self.devices {
if (device.state == .On) { if (device.state == .on) {
activatedDevicesCount += 1 activatedDevicesCount += 1
} }
} }
@@ -177,9 +177,9 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
} }
} }
internal func _updateConnectivityStatus(status: ConnectionStatus) internal func _updateConnectivityStatus(_ status: ConnectionStatus)
{ {
dispatch_async(dispatch_get_main_queue()) { () -> Void in DispatchQueue.main.async { () -> Void in
self._headerView.connectionStatusView.connectivityStatus = status self._headerView.connectionStatusView.connectivityStatus = status
self._headerView.setNeedsLayout() self._headerView.setNeedsLayout()
self._visualizationController.connectionStatus = status self._visualizationController.connectionStatus = status
@@ -188,14 +188,14 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
internal func _reloadDevices() internal func _reloadDevices()
{ {
_server.fetchDevices({ (devices: [WemoDevice], error: NSError?) -> Void in _server.fetchDevices({ (devices: [WemoDevice], error: Error?) -> Void in
dispatch_async(dispatch_get_main_queue()) { () -> Void in DispatchQueue.main.async { () -> Void in
if (error == nil) { if (error == nil) {
self.devices = devices self.devices = devices
self._updateConnectivityStatus(.Connected) self._updateConnectivityStatus(.connected)
} else { } else {
self.devices = [] self.devices = []
self._updateConnectivityStatus(.Error) self._updateConnectivityStatus(.error)
} }
} }
}) })
@@ -205,8 +205,8 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
{ {
_updateDevices = true _updateDevices = true
let interval = dispatch_time(DISPATCH_TIME_NOW, Int64(10 * Double(NSEC_PER_SEC))) let interval = DispatchTime.now() + Double(Int64(10 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
dispatch_after(interval, dispatch_get_main_queue()) { () -> Void in DispatchQueue.main.asyncAfter(deadline: interval) { () -> Void in
if (self._updateDevices) { if (self._updateDevices) {
self._reloadDevices() self._reloadDevices()
self._startUpdatingDevices() self._startUpdatingDevices()

View File

@@ -12,12 +12,12 @@ import UIKit
protocol SwitchesViewControllerDelegate: class protocol SwitchesViewControllerDelegate: class
{ {
func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice]) func switchesViewControllerDidToggleDevices(_ controller: SwitchesViewController, devices: [WemoDevice])
} }
extension SwitchesViewControllerDelegate extension SwitchesViewControllerDelegate
{ {
func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice]) {} func switchesViewControllerDidToggleDevices(_ controller: SwitchesViewController, devices: [WemoDevice]) {}
} }
class SwitchesViewController: UIViewController, class SwitchesViewController: UIViewController,
@@ -25,25 +25,25 @@ class SwitchesViewController: UIViewController,
UICollectionViewDelegateFlowLayout UICollectionViewDelegateFlowLayout
{ {
weak var delegate: SwitchesViewControllerDelegate? weak var delegate: SwitchesViewControllerDelegate?
private var _collectionView: UICollectionView = UICollectionView(frame: CGRectZero, fileprivate var _collectionView: UICollectionView = UICollectionView(frame: CGRect.zero,
collectionViewLayout: UICollectionViewFlowLayout()) collectionViewLayout: UICollectionViewFlowLayout())
private var _currentDevicesHash: Int = 0 fileprivate var _currentDevicesHash: Int = 0
static private let collectionViewDeviceSwitchCellReuseIdentifier = "DeviceSwitchReuseID" static fileprivate let collectionViewDeviceSwitchCellReuseIdentifier = "DeviceSwitchReuseID"
static private let collectionViewActionCellReuseIdentifier = "ActionCellReuseID" static fileprivate let collectionViewActionCellReuseIdentifier = "ActionCellReuseID"
static private let collectionViewCellsSpacing: CGFloat = 5.0 static fileprivate let collectionViewCellsSpacing: CGFloat = 5.0
private enum ActionCell: Int fileprivate enum ActionCell: Int
{ {
case AllOn case allOn
case AllOff case allOff
func name() -> String func name() -> String
{ {
switch self { switch self {
case .AllOn: case .allOn:
return "All On" return "All On"
case .AllOff: case .allOff:
return "All Off" return "All Off"
} }
} }
@@ -62,15 +62,15 @@ class SwitchesViewController: UIViewController,
let deviceCellReuseID = SwitchesViewController.collectionViewDeviceSwitchCellReuseIdentifier let deviceCellReuseID = SwitchesViewController.collectionViewDeviceSwitchCellReuseIdentifier
let actionCellReuseID = SwitchesViewController.collectionViewActionCellReuseIdentifier let actionCellReuseID = SwitchesViewController.collectionViewActionCellReuseIdentifier
let layout = _collectionView.collectionViewLayout as! UICollectionViewFlowLayout let layout = _collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.scrollDirection = .Vertical layout.scrollDirection = .vertical
layout.minimumInteritemSpacing = SwitchesViewController.collectionViewCellsSpacing layout.minimumInteritemSpacing = SwitchesViewController.collectionViewCellsSpacing
layout.minimumLineSpacing = SwitchesViewController.collectionViewCellsSpacing layout.minimumLineSpacing = SwitchesViewController.collectionViewCellsSpacing
_collectionView.backgroundColor = UIColor.blackColor() _collectionView.backgroundColor = UIColor.black
_collectionView.delegate = self _collectionView.delegate = self
_collectionView.dataSource = self _collectionView.dataSource = self
_collectionView.registerClass(WemoDeviceCellView.self, forCellWithReuseIdentifier: deviceCellReuseID) _collectionView.register(WemoDeviceCellView.self, forCellWithReuseIdentifier: deviceCellReuseID)
_collectionView.registerClass(WemoActionCellView.self, forCellWithReuseIdentifier: actionCellReuseID) _collectionView.register(WemoActionCellView.self, forCellWithReuseIdentifier: actionCellReuseID)
self.view.addSubview(_collectionView) self.view.addSubview(_collectionView)
self.devices = [] self.devices = []
@@ -91,36 +91,36 @@ class SwitchesViewController: UIViewController,
didSet didSet
{ {
// sort devices by name // sort devices by name
self.devices.sortInPlace({ (d1: WemoDevice, d2: WemoDevice) -> Bool in self.devices.sort(by: { (d1: WemoDevice, d2: WemoDevice) -> Bool in
return (d1.name.compare(d2.name) == .OrderedAscending) return (d1.name.compare(d2.name) == .orderedAscending)
}) })
let hash = self.devices.reduce(0, combine: {$0 ^ $1.hashValue}) let hash = self.devices.reduce(0, {$0 ^ $1.hashValue})
if (hash != _currentDevicesHash) { if (hash != _currentDevicesHash) {
let previousSet = NSOrderedSet(array: oldValue) let previousSet = NSOrderedSet(array: oldValue)
let newSet = NSOrderedSet(array: self.devices) let newSet = NSOrderedSet(array: self.devices)
var insertedIndexPaths: [NSIndexPath] = [] var insertedIndexPaths: [IndexPath] = []
var updatedIndexPaths: [NSIndexPath] = [] var updatedIndexPaths: [IndexPath] = []
var deletedIndexPaths: [NSIndexPath] = [] var deletedIndexPaths: [IndexPath] = []
// if we have devices now and we didn't before, or vice versa, // if we have devices now and we didn't before, or vice versa,
// we need to update the action cells // we need to update the action cells
if ((oldValue.count == 0 && self.devices.count != 0) || (self.devices.count == 0 && oldValue.count != 0)) { if ((oldValue.count == 0 && self.devices.count != 0) || (self.devices.count == 0 && oldValue.count != 0)) {
for actionCellIdx in 0 ..< ActionCell.count { for actionCellIdx in 0 ..< ActionCell.count {
let actionCellIndexPath = NSIndexPath(forItem: actionCellIdx, inSection: 0) let actionCellIndexPath = IndexPath(item: actionCellIdx, section: 0)
updatedIndexPaths.append(actionCellIndexPath) updatedIndexPaths.append(actionCellIndexPath)
} }
} }
// find deletes and updates // find deletes and updates
for (idx, device) in previousSet.enumerate() { for (idx, device) in previousSet.enumerated() {
let itemIndex = idx + ActionCell.count let itemIndex = idx + ActionCell.count
let curIndexPath = NSIndexPath(forItem: itemIndex, inSection: 0) let curIndexPath = IndexPath(item: itemIndex, section: 0)
if (!newSet.containsObject(device)) { if (!newSet.contains(device)) {
deletedIndexPaths.append(curIndexPath) deletedIndexPaths.append(curIndexPath)
} else if (idx < newSet.count) { } else if (idx < newSet.count) {
let deviceInNewSet = newSet.objectAtIndex(idx) as! WemoDevice let deviceInNewSet = newSet.object(at: idx) as! WemoDevice
if (deviceInNewSet != (device as! WemoDevice)) { if (deviceInNewSet != (device as! WemoDevice)) {
updatedIndexPaths.append(curIndexPath) updatedIndexPaths.append(curIndexPath)
} }
@@ -128,19 +128,19 @@ class SwitchesViewController: UIViewController,
} }
// find insertions // find insertions
for (idx, device) in newSet.enumerate() { for (idx, device) in newSet.enumerated() {
if (!previousSet.containsObject(device)) { if (!previousSet.contains(device)) {
let itemIndex = idx + ActionCell.count let itemIndex = idx + ActionCell.count
let insertedIndexPath = NSIndexPath(forItem: itemIndex, inSection: 0) let insertedIndexPath = IndexPath(item: itemIndex, section: 0)
insertedIndexPaths.append(insertedIndexPath) insertedIndexPaths.append(insertedIndexPath)
} }
} }
UIView.performWithoutAnimation { () -> Void in UIView.performWithoutAnimation { () -> Void in
self._collectionView.performBatchUpdates({ () -> Void in self._collectionView.performBatchUpdates({ () -> Void in
self._collectionView.deleteItemsAtIndexPaths(deletedIndexPaths) self._collectionView.deleteItems(at: deletedIndexPaths)
self._collectionView.reloadItemsAtIndexPaths(updatedIndexPaths) self._collectionView.reloadItems(at: updatedIndexPaths)
self._collectionView.insertItemsAtIndexPaths(insertedIndexPaths) self._collectionView.insertItems(at: insertedIndexPaths)
}, completion: nil) }, completion: nil)
} }
@@ -151,46 +151,47 @@ class SwitchesViewController: UIViewController,
// MARK: UICollectionView // MARK: UICollectionView
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{ {
return self.devices.count + ActionCell.count return self.devices.count + ActionCell.count
} }
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{ {
if (indexPath.item < ActionCell.count) { if (indexPath.item < ActionCell.count) {
let reuseID = SwitchesViewController.collectionViewActionCellReuseIdentifier let reuseID = SwitchesViewController.collectionViewActionCellReuseIdentifier
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseID, forIndexPath: indexPath) as! WemoActionCellView let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseID, for: indexPath) as! WemoActionCellView
cell.textLabel.text = ActionCell(rawValue: indexPath.item)?.name().uppercaseString cell.textLabel.text = ActionCell(rawValue: indexPath.item)?.name().uppercased()
cell.enabled = (self.devices.count > 0) cell.enabled = (self.devices.count > 0)
return cell return cell
} else { } else {
let reuseID = SwitchesViewController.collectionViewDeviceSwitchCellReuseIdentifier let reuseID = SwitchesViewController.collectionViewDeviceSwitchCellReuseIdentifier
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseID, forIndexPath: indexPath) as! WemoDeviceCellView let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseID, for: indexPath) as! WemoDeviceCellView
let device = _deviceAtIndexPath(indexPath) let device = _deviceAtIndexPath(indexPath)
cell.deviceName = device.name cell.deviceName = device.name
cell.toggled = (device.state == .On) cell.toggled = (device.state == .on)
cell.ordinal = indexPath.item - ActionCell.count + 1 cell.ordinal = indexPath.item - ActionCell.count + 1
return cell return cell
} }
} }
func collectionView(collectionView: UICollectionView, func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout, layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize sizeForItemAt indexPath: IndexPath) -> CGSize
{ {
let spacing = SwitchesViewController.collectionViewCellsSpacing let spacing = SwitchesViewController.collectionViewCellsSpacing
let bounds = collectionView.bounds let bounds = collectionView.bounds
var cellsPerRow: CGFloat = 0.0 var cellsPerRow: CGFloat = 0.0
switch (self.traitCollection.horizontalSizeClass) { switch (self.traitCollection.horizontalSizeClass) {
case .Regular, .Compact where (bounds.size.width >= 400.0): case .regular where (bounds.size.width >= 400.0),
.compact where (bounds.size.width >= 400.0):
cellsPerRow = 3.0 cellsPerRow = 3.0
break break
case .Compact: case .compact:
cellsPerRow = 2.0 cellsPerRow = 2.0
default: default:
cellsPerRow = 2.0 cellsPerRow = 2.0
@@ -204,18 +205,18 @@ class SwitchesViewController: UIViewController,
} }
} }
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{ {
if (indexPath.item < ActionCell.count) { if (indexPath.item < ActionCell.count) {
let tappedActionCell = ActionCell(rawValue: indexPath.item) let tappedActionCell = ActionCell(rawValue: indexPath.item)
var currentDelay: NSTimeInterval = 0.0 var currentDelay: TimeInterval = 0.0
for i in ActionCell.count ..< collectionView.numberOfItemsInSection(indexPath.section) { for i in ActionCell.count ..< collectionView.numberOfItems(inSection: indexPath.section) {
if let cell = collectionView.cellForItemAtIndexPath(NSIndexPath(forItem: i, inSection: indexPath.section)) as? WemoDeviceCellView { if let cell = collectionView.cellForItem(at: IndexPath(item: i, section: indexPath.section)) as? WemoDeviceCellView {
let animOptions = UIViewAnimationOptions([.AllowUserInteraction]) let animOptions = UIViewAnimationOptions([.allowUserInteraction])
UIView.animateWithDuration(0.3, delay: currentDelay, options: animOptions, animations: { UIView.animate(withDuration: 0.3, delay: currentDelay, options: animOptions, animations: {
cell.toggled = (tappedActionCell == .AllOn) cell.toggled = (tappedActionCell == .allOn)
}, completion: nil) }, completion: nil)
currentDelay += 0.05 currentDelay += 0.05
@@ -223,22 +224,22 @@ class SwitchesViewController: UIViewController,
} }
for device in self.devices { for device in self.devices {
device.state = (tappedActionCell == .AllOn ? .On : .Off) device.state = (tappedActionCell == .allOn ? .on : .off)
} }
self.delegate?.switchesViewControllerDidToggleDevices(self, devices: self.devices) self.delegate?.switchesViewControllerDidToggleDevices(self, devices: self.devices)
} else { } else {
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! WemoDeviceCellView let cell = collectionView.cellForItem(at: indexPath) as! WemoDeviceCellView
cell.toggled = !cell.toggled cell.toggled = !cell.toggled
let device = _deviceAtIndexPath(indexPath) let device = _deviceAtIndexPath(indexPath)
device.state = (cell.toggled ? .On : .Off) device.state = (cell.toggled ? .on : .off)
self.delegate?.switchesViewControllerDidToggleDevices(self, devices: [device]) self.delegate?.switchesViewControllerDidToggleDevices(self, devices: [device])
} }
} }
func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool
{ {
if (indexPath.item < ActionCell.count) { if (indexPath.item < ActionCell.count) {
return (self.devices.count > 0) return (self.devices.count > 0)
@@ -247,7 +248,7 @@ class SwitchesViewController: UIViewController,
} }
} }
func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool
{ {
if (indexPath.item < ActionCell.count) { if (indexPath.item < ActionCell.count) {
return (self.devices.count > 0) return (self.devices.count > 0)
@@ -258,7 +259,7 @@ class SwitchesViewController: UIViewController,
// MARK: Internal // MARK: Internal
internal func _deviceAtIndexPath(indexPath: NSIndexPath) -> WemoDevice internal func _deviceAtIndexPath(_ indexPath: IndexPath) -> WemoDevice
{ {
let deviceIdx = indexPath.item - ActionCell.count let deviceIdx = indexPath.item - ActionCell.count
let device = self.devices[deviceIdx] let device = self.devices[deviceIdx]

View File

@@ -11,31 +11,32 @@ import Foundation
import GLKit import GLKit
import SceneKit import SceneKit
import UIKit import UIKit
import SceneKit
let π = CGFloat(M_PI) let π = CGFloat(Double.pi)
class VisualizationViewController: UIViewController class VisualizationViewController: UIViewController
{ {
private var _scene: SCNScene = SCNScene() fileprivate var _scene: SCNScene = SCNScene()
private var _sceneView: SCNView? fileprivate var _sceneView: SCNView?
private var _cameraNode: SCNNode = SCNNode() fileprivate var _cameraNode: SCNNode = SCNNode()
private var _lightNode: SCNNode = SCNNode() fileprivate var _lightNode: SCNNode = SCNNode()
private var _cubletsNode: SCNNode = SCNNode() fileprivate var _cubletsNode: SCNNode = SCNNode()
private var _cublets: [SCNNode] = [] fileprivate var _cublets: [SCNNode] = []
private var _percentActivated: Float = 0.0 fileprivate var _percentActivated: Float = 0.0
static private let cubletsDimensions = 5 static fileprivate let cubletsDimensions = 5
static private let cubletsSize = 1.0 static fileprivate let cubletsSize = 1.0
static private let cubletsSpacing = 2.0 static fileprivate let cubletsSpacing = 2.0
static private let rotationAnimationKey = "RotationAnimation" static fileprivate let rotationAnimationKey = "RotationAnimation"
// MARK: Overrides // MARK: Overrides
override func loadView() override func loadView()
{ {
let opts = [SCNPreferredRenderingAPIKey : SCNRenderingAPI.OpenGLES2.rawValue] let opts = [SCNView.Option.preferredRenderingAPI.rawValue : SCNRenderingAPI.openGLES2]
let view = SCNView(frame: UIScreen.mainScreen().bounds, options: opts) let view = SCNView(frame: UIScreen.main.bounds, options: opts)
view.backgroundColor = UIColor.blackColor() view.backgroundColor = UIColor.black
view.scene = _scene view.scene = _scene
view.allowsCameraControl = false view.allowsCameraControl = false
@@ -55,13 +56,13 @@ class VisualizationViewController: UIViewController
_beginModelResetTimer() _beginModelResetTimer()
} }
override func viewDidAppear(animated: Bool) override func viewDidAppear(_ animated: Bool)
{ {
super.viewDidAppear(animated) super.viewDidAppear(animated)
_sceneView?.play(nil) _sceneView?.play(nil)
} }
override func viewDidDisappear(animated: Bool) override func viewDidDisappear(_ animated: Bool)
{ {
super.viewDidDisappear(animated) super.viewDidDisappear(animated)
_sceneView?.stop(nil) _sceneView?.stop(nil)
@@ -69,17 +70,17 @@ class VisualizationViewController: UIViewController
// MARK: API // MARK: API
var connectionStatus: ConnectionStatus = .Disconnected var connectionStatus: ConnectionStatus = .disconnected
{ {
didSet didSet
{ {
switch (self.connectionStatus) { switch (self.connectionStatus) {
case .Disconnected, .Connecting, .Error: case .disconnected, .connecting, .error:
_cubletsNode.paused = true _cubletsNode.isPaused = true
_lightNode.light?.color = UIColor(white: 0.3, alpha: 1.0) _lightNode.light?.color = UIColor(white: 0.3, alpha: 1.0)
case .Connected: case .connected:
_cubletsNode.paused = false _cubletsNode.isPaused = false
_lightNode.light?.color = UIColor.whiteColor() _lightNode.light?.color = UIColor.white
} }
} }
} }
@@ -97,7 +98,7 @@ class VisualizationViewController: UIViewController
} }
} }
func setPercentActivated(percentage: Float, animated: Bool) func setPercentActivated(_ percentage: Float, animated: Bool)
{ {
let cubletsCount = _cublets.count let cubletsCount = _cublets.count
let cubletsToActivate = UInt(percentage * Float(cubletsCount)) let cubletsToActivate = UInt(percentage * Float(cubletsCount))
@@ -124,8 +125,8 @@ class VisualizationViewController: UIViewController
let rotCoeff = CGFloat(arc4random() % 2 == 0 ? -1.0 : 1.0) let rotCoeff = CGFloat(arc4random() % 2 == 0 ? -1.0 : 1.0)
let rotAngle = CGFloat(rotCoeff * π / 4.0) let rotAngle = CGFloat(rotCoeff * π / 4.0)
let rotAction = SCNAction.rotateByAngle(rotAngle, aroundAxis: rotAxis, duration: 0.8) let rotAction = SCNAction.rotate(by: rotAngle, around: rotAxis, duration: 0.8)
rotAction.timingMode = .Linear rotAction.timingMode = .linear
rotAction.timingFunction = { (t: Float) -> Float in rotAction.timingFunction = { (t: Float) -> Float in
return min(((log10(4.0 * (t + 0.03)) + 1.0) / 1.5), 1.0) return min(((log10(4.0 * (t + 0.03)) + 1.0) / 1.5), 1.0)
} }
@@ -134,7 +135,7 @@ class VisualizationViewController: UIViewController
// smooth transition // smooth transition
let longTermAnimKey = VisualizationViewController.rotationAnimationKey let longTermAnimKey = VisualizationViewController.rotationAnimationKey
let newLongTermRotAction = _createLongTermRotationAnimation((rotCoeff * 2.0 * π), rotAxis) let newLongTermRotAction = _createLongTermRotationAnimation((rotCoeff * 2.0 * π), rotAxis)
_cubletsNode.removeActionForKey(longTermAnimKey) _cubletsNode.removeAction(forKey: longTermAnimKey)
let actionSeq = SCNAction.sequence([rotAction, newLongTermRotAction]) let actionSeq = SCNAction.sequence([rotAction, newLongTermRotAction])
_cubletsNode.runAction(actionSeq, forKey: longTermAnimKey) _cubletsNode.runAction(actionSeq, forKey: longTermAnimKey)
@@ -166,8 +167,8 @@ class VisualizationViewController: UIViewController
internal func _setupLights() internal func _setupLights()
{ {
let light = SCNLight() let light = SCNLight()
light.type = SCNLightTypeOmni light.type = SCNLight.LightType.omni
light.color = UIColor.whiteColor() light.color = UIColor.white
_lightNode = SCNNode() _lightNode = SCNNode()
_lightNode.light = light _lightNode.light = light
@@ -178,7 +179,7 @@ class VisualizationViewController: UIViewController
internal func _setupModel() internal func _setupModel()
{ {
_cubletsNode.enumerateChildNodesUsingBlock { $0.0.removeFromParentNode() } _cubletsNode.enumerateChildNodes { $0.0.removeFromParentNode() }
_cublets.removeAll() _cublets.removeAll()
let sz = Float(VisualizationViewController.cubletsSize) let sz = Float(VisualizationViewController.cubletsSize)
@@ -191,7 +192,7 @@ class VisualizationViewController: UIViewController
// setup material and geometry. each node needs its own material for the activation effect. // setup material and geometry. each node needs its own material for the activation effect.
let geom = SCNBox(width: CGFloat(sz), height: CGFloat(sz), length: CGFloat(sz), chamferRadius: 0.0) let geom = SCNBox(width: CGFloat(sz), height: CGFloat(sz), length: CGFloat(sz), chamferRadius: 0.0)
let material = SCNMaterial() let material = SCNMaterial()
material.diffuse.contents = UIColor.whiteColor() material.diffuse.contents = UIColor.white
material.transparency = 0.75 material.transparency = 0.75
// generate nodes for each cublet // generate nodes for each cublet
@@ -216,7 +217,7 @@ class VisualizationViewController: UIViewController
} }
_cubletsNode.position = SCNVector3Zero _cubletsNode.position = SCNVector3Zero
if (_cubletsNode.parentNode == nil) { if (_cubletsNode.parent == nil) {
_scene.rootNode.addChildNode(_cubletsNode) _scene.rootNode.addChildNode(_cubletsNode)
} }
} }
@@ -232,8 +233,8 @@ class VisualizationViewController: UIViewController
internal func _setupEffects() internal func _setupEffects()
{ {
let techniqueURL = NSBundle.mainBundle().URLForResource("CubletsTechnique", withExtension: "plist") let techniqueURL = Bundle.main.url(forResource: "CubletsTechnique", withExtension: "plist")
let techniqueDict = NSDictionary(contentsOfURL: techniqueURL!) as! [String : AnyObject] let techniqueDict = NSDictionary(contentsOf: techniqueURL!) as! [String : AnyObject]
let technique = SCNTechnique(dictionary: techniqueDict) let technique = SCNTechnique(dictionary: techniqueDict)
_sceneView?.technique = technique _sceneView?.technique = technique
@@ -244,8 +245,8 @@ class VisualizationViewController: UIViewController
/* since this visualization is running all the time, trigonometric functions begin /* since this visualization is running all the time, trigonometric functions begin
malfunctioning at very large numbers. just reload the model every 24 hours so we malfunctioning at very large numbers. just reload the model every 24 hours so we
don't have to see it */ don't have to see it */
let reloadModelTime = dispatch_time(DISPATCH_TIME_NOW, Int64(60 * 60 * 24 * NSEC_PER_SEC)) let reloadModelTime = DispatchTime.now() + Double(Int64(60 * 60 * 24 * NSEC_PER_SEC)) / Double(NSEC_PER_SEC)
dispatch_after(reloadModelTime, dispatch_get_main_queue()) { [weak self] in DispatchQueue.main.asyncAfter(deadline: reloadModelTime) { [weak self] in
if let strongSelf = self { if let strongSelf = self {
strongSelf._cubletsNode.removeFromParentNode() strongSelf._cubletsNode.removeFromParentNode()
strongSelf._cubletsNode = SCNNode() strongSelf._cubletsNode = SCNNode()
@@ -263,25 +264,25 @@ class VisualizationViewController: UIViewController
} }
} }
internal func _setCubletActivated(cublet: SCNNode, activated: Bool) internal func _setCubletActivated(_ cublet: SCNNode, activated: Bool)
{ {
let material = cublet.geometry?.firstMaterial let material = cublet.geometry?.firstMaterial
material?.diffuse.contents = (activated ? UIColor.redColor() : UIColor.whiteColor()) material?.diffuse.contents = (activated ? UIColor.red : UIColor.white)
} }
internal func _setAnimationSpeed(speed: CGFloat) internal func _setAnimationSpeed(_ speed: CGFloat)
{ {
let key = VisualizationViewController.rotationAnimationKey let key = VisualizationViewController.rotationAnimationKey
if let action = _cubletsNode.actionForKey(key) { if let action = _cubletsNode.action(forKey: key) {
_cubletsNode.removeActionForKey(key) _cubletsNode.removeAction(forKey: key)
action.speed = speed action.speed = speed
_cubletsNode.runAction(action, forKey: key) _cubletsNode.runAction(action, forKey: key)
} }
} }
internal func _createLongTermRotationAnimation(rotAngle: CGFloat, _ rotAxis: SCNVector3) -> SCNAction internal func _createLongTermRotationAnimation(_ rotAngle: CGFloat, _ rotAxis: SCNVector3) -> SCNAction
{ {
return SCNAction.repeatActionForever(SCNAction.rotateByAngle(rotAngle, aroundAxis: rotAxis, duration: 40.0)) return SCNAction.repeatForever(SCNAction.rotate(by: rotAngle, around: rotAxis, duration: 40.0))
} }
} }

View File

@@ -10,40 +10,46 @@ import Foundation
enum ConnectionStatus enum ConnectionStatus
{ {
case Disconnected case disconnected
case Connecting case connecting
case Connected case connected
case Error case error
}
enum ConnectionError : Error
{
case unknown
case serverUnavailable
} }
class WemoServer class WemoServer
{ {
private(set) var baseURL: NSURL fileprivate(set) var baseURL: URL
private(set) var connected: Bool = false fileprivate(set) var connected: Bool = false
private var _urlSession: NSURLSession fileprivate var _urlSession: URLSession
private var _errorStream: StandardErrorOutputStream = StandardErrorOutputStream() fileprivate var _errorStream: StandardErrorOutputStream = StandardErrorOutputStream()
private var _operationQueue: NSOperationQueue = NSOperationQueue() fileprivate var _operationQueue: OperationQueue = OperationQueue()
init(_ url: NSURL) init(_ url: URL)
{ {
self.baseURL = url self.baseURL = url
let config = NSURLSessionConfiguration.defaultSessionConfiguration() let config = URLSessionConfiguration.default
_urlSession = NSURLSession(configuration: config) _urlSession = URLSession(configuration: config)
_operationQueue.maxConcurrentOperationCount = 1 _operationQueue.maxConcurrentOperationCount = 1
} }
func connect(completion: (NSError?) -> Void) func connect(_ completion: @escaping (Error?) -> Void)
{ {
if (!self.connected) { if (!self.connected) {
let op = ConnectOperation(baseURL: self.baseURL, session: _urlSession) let op = ConnectOperation(baseURL: self.baseURL, session: _urlSession)
weak var weakOp = op weak var weakOp = op
op.completionBlock = { op.completionBlock = {
guard let strongOp = weakOp else { completion(nil) ; return } guard let strongOp = weakOp else { completion(nil) ; return }
if (strongOp.error != nil) { if let error = strongOp.error {
self._logError("Error connecting to server", error: strongOp.error!) self._logError("Error connecting to server", error: error)
} else { } else {
self.connected = true self.connected = true
} }
@@ -56,68 +62,68 @@ class WemoServer
} }
} }
func disconnect(completion: (NSError?) -> Void) func disconnect(_ completion: (Error?) -> Void)
{ {
self.connected = false self.connected = false
completion(nil) completion(nil)
} }
func fetchDevices(completion: ([WemoDevice], NSError?) -> Void) func fetchDevices(_ completion: @escaping ([WemoDevice], Error?) -> Void)
{ {
if (self.connected) { if (self.connected) {
let op = FetchDevicesOperation(baseURL: self.baseURL, session: _urlSession) let op = FetchDevicesOperation(baseURL: self.baseURL, session: _urlSession)
weak var weakOp = op weak var weakOp = op
op.completionBlock = { op.completionBlock = {
guard let strongOp = weakOp else { completion([], nil) ; return } guard let strongOp = weakOp else { completion([], nil) ; return }
if (strongOp.error != nil) { if let error = strongOp.error {
self._logError("Error fetching devices", error: strongOp.error!) self._logError("Error fetching devices", error: error)
} }
completion(strongOp.devices, strongOp.error) completion(strongOp.devices, strongOp.error)
} }
_operationQueue.addOperation(op) _operationQueue.addOperation(op)
} else { } else {
let err = NSError.xionError(.ConnectionError) let err = ConnectionError.serverUnavailable
completion([], err) completion([], err)
} }
} }
func toggleDevice(device: WemoDevice, state: WemoDevice.State, completion: (NSError?) -> Void) func toggleDevice(_ device: WemoDevice, state: WemoDevice.State, completion: @escaping (Error?) -> Void)
{ {
if (self.connected) { if (self.connected) {
let op = ToggleDeviceOperation(baseURL: self.baseURL, session: _urlSession, device: device, state: state) let op = ToggleDeviceOperation(baseURL: self.baseURL, session: _urlSession, device: device, state: state)
weak var weakOp = op weak var weakOp = op
op.completionBlock = { op.completionBlock = {
guard let strongOp = weakOp else { completion(nil) ; return } guard let strongOp = weakOp else { completion(nil) ; return }
if (strongOp.error != nil) { if let error = strongOp.error {
self._logError("Error toggling device", error: strongOp.error!) self._logError("Error toggling device", error: error)
} }
completion(strongOp.error) completion(strongOp.error)
} }
_operationQueue.addOperation(op) _operationQueue.addOperation(op)
} else { } else {
let err = NSError.xionError(.ConnectionError) let err = ConnectionError.serverUnavailable
completion(err) completion(err)
} }
} }
// MARK: Internal // MARK: Internal
internal func _logError(description: String, error: NSError) internal func _logError(_ description: String, error: Error)
{ {
print("ERROR: \(description) \(error)", toStream: &_errorStream) print("ERROR: \(description) \(error)", to: &_errorStream)
} }
} }
internal class WemoOperation : NSOperation internal class WemoOperation : Operation
{ {
var baseURL: NSURL var baseURL: URL
var session: NSURLSession var session: URLSession
internal(set) var error: NSError? internal(set) var error: Error?
init(baseURL: NSURL, session: NSURLSession) init(baseURL: URL, session: URLSession)
{ {
self.baseURL = baseURL self.baseURL = baseURL
self.session = session self.session = session
@@ -129,16 +135,14 @@ internal class ConnectOperation : WemoOperation
override func main() override func main()
{ {
let semaphore = Semaphore(value: 0) let semaphore = Semaphore(value: 0)
let url = self.baseURL.URLByAppendingPathComponent("api/environment") let url = self.baseURL.appendingPathComponent("api/environment")
let request = NSMutableURLRequest(URL: url) var request = URLRequest(url: url)
request.HTTPMethod = "POST" request.httpMethod = "POST"
let task = self.session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in let task = self.session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
if (error != nil) { self.error = error
self.error = NSError.xionError(.ConnectionError, underlying: error!)
}
semaphore.signal() semaphore.signal()
} })
task.resume() task.resume()
semaphore.wait() semaphore.wait()
} }
@@ -151,24 +155,24 @@ internal class FetchDevicesOperation : WemoOperation
override func main() override func main()
{ {
let semaphore = Semaphore(value: 0) let semaphore = Semaphore(value: 0)
let url = self.baseURL.URLByAppendingPathComponent("api/environment") let url = self.baseURL.appendingPathComponent("api/environment")
let task = self.session.dataTaskWithURL(url) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in let task = self.session.dataTask(with: url, completionHandler: { (data: Data?, response: URLResponse?, error: NSError?) -> Void in
if (data != nil) { if (data != nil) {
self.devices = self._parseDevices(data!) self.devices = self._parseDevices(data!)
} else { } else {
self.error = NSError.xionError(.ConnectionError, underlying: error) self.error = NSError.xionError(.connectionError, underlying: error)
} }
semaphore.signal() semaphore.signal()
} } as! (Data?, URLResponse?, Error?) -> Void)
task.resume() task.resume()
semaphore.wait() semaphore.wait()
} }
internal func _parseDevices(data: NSData) -> [WemoDevice] internal func _parseDevices(_ data: Data) -> [WemoDevice]
{ {
var devices: [WemoDevice] = [] var devices: [WemoDevice] = []
if let responseDict = (try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as? NSDictionary) { if let responseDict = (try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions()) as? NSDictionary) {
for responseObj in (responseDict?.allValues)! { for responseObj in (responseDict?.allValues)! {
if let responseDict = responseObj as? NSDictionary { if let responseDict = responseObj as? NSDictionary {
let device = WemoDevice(responseDict) let device = WemoDevice(responseDict)
@@ -186,7 +190,7 @@ internal class ToggleDeviceOperation : WemoOperation
var device: WemoDevice var device: WemoDevice
var state: WemoDevice.State var state: WemoDevice.State
init(baseURL: NSURL, session: NSURLSession, device: WemoDevice, state: WemoDevice.State) init(baseURL: URL, session: URLSession, device: WemoDevice, state: WemoDevice.State)
{ {
self.device = device self.device = device
self.state = state self.state = state
@@ -196,15 +200,13 @@ internal class ToggleDeviceOperation : WemoOperation
override func main() override func main()
{ {
let semaphore = Semaphore(value: 0) let semaphore = Semaphore(value: 0)
let stateArg = (self.state == .On ? "on" : "off") let stateArg = (self.state == .on ? "on" : "off")
let url = self.baseURL.URLByAppendingPathComponent("api/device/\(self.device.name)").URLByAppendingRequestParameters(["state" : stateArg]) let url = self.baseURL.appendingPathComponent("api/device/\(self.device.name)").URLByAppendingRequestParameters(["state" : stateArg])
let request = NSMutableURLRequest(URL: url!) var request = URLRequest(url: url!)
request.HTTPMethod = "POST" request.httpMethod = "POST"
let task = self.session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in let task = self.session.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if (error != nil) { self.error = error
self.error = NSError.xionError(.ConnectionError, underlying: error)
}
semaphore.signal() semaphore.signal()
} }
task.resume() task.resume()

View File

@@ -12,20 +12,20 @@ class WemoDevice: Hashable
{ {
enum State enum State
{ {
case Off case off
case On case on
} }
enum Type enum DeviceType
{ {
case Switch case `switch`
} }
var name: String = "" var name: String = ""
var host: String = "" var host: String = ""
var model: String = "" var model: String = ""
var state: State = .Off var state: State = .off
var type: Type = .Switch var type: DeviceType = .switch
var serial: String = "" var serial: String = ""
init() init()
@@ -46,13 +46,13 @@ class WemoDevice: Hashable
} }
if let state = dict["state"] as? NSNumber { if let state = dict["state"] as? NSNumber {
switch (state.integerValue) { switch (state.intValue) {
case 0: case 0:
self.state = .Off self.state = .off
case 1: case 1:
self.state = .On self.state = .on
default: default:
self.state = .Off self.state = .off
} }
} }

View File

@@ -10,22 +10,31 @@ import Foundation
enum XIONErrorCode: Int enum XIONErrorCode: Int
{ {
case Unknown case unknown
case ConnectionError case connectionError
}
struct XIONError : Error
{
enum ErrorCode
{
case unknown
case connectionError
}
} }
extension NSError extension NSError
{ {
private static let XIONErrorDomain = "com.xionsf.controlpanel" fileprivate static let XIONErrorDomain = "com.xionsf.controlpanel"
class func xionError(code: XIONErrorCode) -> NSError class func xionError(_ code: XIONErrorCode) -> NSError
{ {
return self.xionError(code, userInfo: nil) return self.xionError(code, userInfo: nil)
} }
class func xionError(code: XIONErrorCode, underlying: NSError?) -> NSError class func xionError(_ code: XIONErrorCode, underlying: NSError?) -> NSError
{ {
var userInfo: [NSObject : AnyObject]? = nil var userInfo: [AnyHashable: Any]? = nil
if (underlying != nil) { if (underlying != nil) {
userInfo = [ userInfo = [
NSUnderlyingErrorKey : underlying! NSUnderlyingErrorKey : underlying!
@@ -35,7 +44,7 @@ extension NSError
return self.xionError(code, userInfo: userInfo) return self.xionError(code, userInfo: userInfo)
} }
class func xionError(code: XIONErrorCode, userInfo: [NSObject : AnyObject]?) -> NSError class func xionError(_ code: XIONErrorCode, userInfo: [AnyHashable: Any]?) -> NSError
{ {
return NSError(domain: XIONErrorDomain, code: code.rawValue, userInfo: userInfo) return NSError(domain: XIONErrorDomain, code: code.rawValue, userInfo: userInfo)
} }

View File

@@ -7,22 +7,22 @@
import Foundation import Foundation
extension NSURL extension URL
{ {
var requestParameters: [String : String]? var requestParameters: [String : String]?
{ {
get get
{ {
let urlComponents = self.absoluteString.componentsSeparatedByString("/") let urlComponents = self.absoluteString.components(separatedBy: "/")
let paramsString = urlComponents[urlComponents.count - 1] let paramsString = urlComponents[urlComponents.count - 1]
let parameterComponents = paramsString.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "&?")) let parameterComponents = paramsString.components(separatedBy: CharacterSet(charactersIn: "&?"))
var dict: Dictionary<String, String> = Dictionary() var dict: Dictionary<String, String> = Dictionary()
for paramPair in parameterComponents { for paramPair in parameterComponents {
let kvPair = paramPair.componentsSeparatedByString("=") let kvPair = paramPair.components(separatedBy: "=")
if (kvPair.count == 2 && kvPair[0].characters.count > 0) { if (kvPair.count == 2 && kvPair[0].characters.count > 0) {
let key = kvPair[0].stringByRemovingPercentEncoding! let key = kvPair[0].removingPercentEncoding!
let value = kvPair[1].stringByRemovingPercentEncoding! let value = kvPair[1].removingPercentEncoding!
dict[key] = value dict[key] = value
} }
} }
@@ -31,7 +31,7 @@ extension NSURL
} }
} }
func URLByAppendingRequestParameters(params: [String : String]) -> NSURL? func URLByAppendingRequestParameters(_ params: [String : String]) -> URL?
{ {
var paramsString = "" var paramsString = ""
@@ -43,14 +43,14 @@ extension NSURL
delim = "&" delim = "&"
} }
let keyParam = key.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) let keyParam = key.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
let valueParam = value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) let valueParam = value.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
paramsString += "\(delim)\(keyParam!)=\(valueParam!)" paramsString += "\(delim)\(keyParam!)=\(valueParam!)"
} }
var absoluteString = self.absoluteString var absoluteString = self.absoluteString
absoluteString += paramsString absoluteString += paramsString
return NSURL(string: absoluteString) return URL(string: absoluteString)
} }
} }

View File

@@ -10,11 +10,11 @@ import Foundation
class Semaphore class Semaphore
{ {
private var _semaphore: dispatch_semaphore_t fileprivate var _semaphore: DispatchSemaphore
init(value: Int) init(value: Int)
{ {
_semaphore = dispatch_semaphore_create(value) _semaphore = DispatchSemaphore(value: value)
} }
func wait() func wait()
@@ -22,18 +22,21 @@ class Semaphore
self.wait(nil) self.wait(nil)
} }
func wait(untilDate: NSDate?) func wait(_ untilDate: Date?)
{ {
var time: dispatch_time_t = DISPATCH_TIME_FOREVER var time: DispatchTime = DispatchTime.distantFuture
if (untilDate != nil) { if let untilDate = untilDate {
time = UInt64(untilDate!.timeIntervalSinceNow) * NSEC_PER_SEC time = .now() + .milliseconds(Int(untilDate.timeIntervalSinceNow * 1000))
} }
dispatch_semaphore_wait(_semaphore, time) let result = _semaphore.wait(timeout: time)
if (result != .success) {
print("semaphore timed out")
}
} }
func signal() func signal()
{ {
dispatch_semaphore_signal(_semaphore) _semaphore.signal()
} }
} }

View File

@@ -8,11 +8,11 @@
import Foundation import Foundation
class StandardErrorOutputStream: OutputStreamType class StandardErrorOutputStream: TextOutputStream
{ {
func write(string: String) func write(_ string: String)
{ {
let stderr = NSFileHandle.fileHandleWithStandardError() let stderr = FileHandle.standardError
stderr.writeData(string.dataUsingEncoding(NSUTF8StringEncoding)!) stderr.write(string.data(using: String.Encoding.utf8)!)
} }
} }

View File

@@ -10,25 +10,25 @@ import UIKit
class ConnectionStatusView: UIView class ConnectionStatusView: UIView
{ {
private var _connectivityStatus: ConnectionStatus = .Disconnected fileprivate var _connectivityStatus: ConnectionStatus = .disconnected
private var _japaneseLabel: UILabel = UILabel() fileprivate var _japaneseLabel: UILabel = UILabel()
private var _englishLabel: UILabel = UILabel() fileprivate var _englishLabel: UILabel = UILabel()
static private let labelsVMargin: CGFloat = 5.0 static fileprivate let labelsVMargin: CGFloat = 5.0
override init(frame: CGRect) override init(frame: CGRect)
{ {
super.init(frame: frame) super.init(frame: frame)
_japaneseLabel.font = UIFont(name: "Orbitron-Medium", size: 24.0) _japaneseLabel.font = UIFont(name: "Orbitron-Medium", size: 24.0)
_japaneseLabel.textColor = UIColor.whiteColor() _japaneseLabel.textColor = UIColor.white
self.addSubview(_japaneseLabel) self.addSubview(_japaneseLabel)
_englishLabel.font = UIFont(name: "Orbitron-Medium", size: 16.0) _englishLabel.font = UIFont(name: "Orbitron-Medium", size: 16.0)
_englishLabel.textColor = UIColor.whiteColor() _englishLabel.textColor = UIColor.white
self.addSubview(_englishLabel) self.addSubview(_englishLabel)
self.connectivityStatus = .Disconnected self.connectivityStatus = .disconnected
} }
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
@@ -38,7 +38,7 @@ class ConnectionStatusView: UIView
// MARK: Overrides // MARK: Overrides
override func sizeThatFits(size: CGSize) -> CGSize override func sizeThatFits(_ size: CGSize) -> CGSize
{ {
let labelsVMargin = ConnectionStatusView.labelsVMargin let labelsVMargin = ConnectionStatusView.labelsVMargin
let jpLabelSize = _japaneseLabel.sizeThatFits(size) let jpLabelSize = _japaneseLabel.sizeThatFits(size)
@@ -67,7 +67,7 @@ class ConnectionStatusView: UIView
_englishLabel.frame = CGRect( _englishLabel.frame = CGRect(
x: rint(bounds.size.width / 2.0 - enLabelSize.width / 2.0), x: rint(bounds.size.width / 2.0 - enLabelSize.width / 2.0),
y: CGRectGetMaxY(_japaneseLabel.frame) + labelsVMargin, y: _japaneseLabel.frame.maxY + labelsVMargin,
width: enLabelSize.width, width: enLabelSize.width,
height: enLabelSize.height height: enLabelSize.height
) )
@@ -87,30 +87,30 @@ class ConnectionStatusView: UIView
_connectivityStatus = newStatus _connectivityStatus = newStatus
switch (_connectivityStatus) { switch (_connectivityStatus) {
case .Disconnected: case .disconnected:
_japaneseLabel.text = "非直結" _japaneseLabel.text = "非直結"
_japaneseLabel.textColor = UIColor.redColor() _japaneseLabel.textColor = UIColor.red
_englishLabel.text = "offline" _englishLabel.text = "offline"
_englishLabel.textColor = UIColor.redColor() _englishLabel.textColor = UIColor.red
case .Connecting: case .connecting:
_japaneseLabel.text = "接続中" _japaneseLabel.text = "接続中"
_japaneseLabel.textColor = UIColor.yellowColor() _japaneseLabel.textColor = UIColor.yellow
_englishLabel.text = "connecting..." _englishLabel.text = "connecting..."
_englishLabel.textColor = UIColor.yellowColor() _englishLabel.textColor = UIColor.yellow
case .Connected: case .connected:
_japaneseLabel.text = "直結" _japaneseLabel.text = "直結"
_japaneseLabel.textColor = UIColor.greenColor() _japaneseLabel.textColor = UIColor.green
_englishLabel.text = "online" _englishLabel.text = "online"
_englishLabel.textColor = UIColor.greenColor() _englishLabel.textColor = UIColor.green
case .Error: case .error:
_japaneseLabel.text = "過失" _japaneseLabel.text = "過失"
_japaneseLabel.textColor = UIColor.redColor() _japaneseLabel.textColor = UIColor.red
_englishLabel.text = "error" _englishLabel.text = "error"
_englishLabel.textColor = UIColor.redColor() _englishLabel.textColor = UIColor.red
} }
self.setNeedsLayout() self.setNeedsLayout()

View File

@@ -15,24 +15,24 @@ class HeaderView: UIView
var xionLogoView: XIONLogoView = XIONLogoView() var xionLogoView: XIONLogoView = XIONLogoView()
var connectionStatusView: ConnectionStatusView = ConnectionStatusView() var connectionStatusView: ConnectionStatusView = ConnectionStatusView()
private var _xionTitleLabel: UILabel = UILabel() fileprivate var _xionTitleLabel: UILabel = UILabel()
private var _xionJapaneseLabel: UILabel = UILabel() fileprivate var _xionJapaneseLabel: UILabel = UILabel()
override init(frame: CGRect) override init(frame: CGRect)
{ {
super.init(frame: frame) super.init(frame: frame)
self.backgroundColor = UIColor.blackColor() self.backgroundColor = UIColor.black
self.addSubview(self.xionLogoView) self.addSubview(self.xionLogoView)
_xionTitleLabel.font = UIFont(name: "Orbitron-Medium", size: 16.0) _xionTitleLabel.font = UIFont(name: "Orbitron-Medium", size: 16.0)
_xionTitleLabel.text = "XION arcade system control panel" _xionTitleLabel.text = "XION arcade system control panel"
_xionTitleLabel.textColor = UIColor.whiteColor() _xionTitleLabel.textColor = UIColor.white
self.addSubview(_xionTitleLabel) self.addSubview(_xionTitleLabel)
_xionJapaneseLabel.font = UIFont(name: "Orbitron-Medium", size: 12.0) _xionJapaneseLabel.font = UIFont(name: "Orbitron-Medium", size: 12.0)
_xionJapaneseLabel.text = "ザイーオンゲームセンターのシステム制御プログラム" _xionJapaneseLabel.text = "ザイーオンゲームセンターのシステム制御プログラム"
_xionJapaneseLabel.textColor = UIColor.whiteColor() _xionJapaneseLabel.textColor = UIColor.white
self.addSubview(_xionJapaneseLabel) self.addSubview(_xionJapaneseLabel)
self.addSubview(self.connectionStatusView) self.addSubview(self.connectionStatusView)
@@ -59,12 +59,12 @@ class HeaderView: UIView
) )
self.xionLogoView.frame = logoFrame self.xionLogoView.frame = logoFrame
if (self.traitCollection.horizontalSizeClass == .Compact) { if (self.traitCollection.horizontalSizeClass == .compact) {
_xionTitleLabel.hidden = true _xionTitleLabel.isHidden = true
_xionJapaneseLabel.hidden = true _xionJapaneseLabel.isHidden = true
} else { } else {
_xionTitleLabel.hidden = false _xionTitleLabel.isHidden = false
_xionJapaneseLabel.hidden = false _xionJapaneseLabel.isHidden = false
let titleJPVerticalMargin: CGFloat = 5.0 let titleJPVerticalMargin: CGFloat = 5.0
let titleLabelSize = _xionTitleLabel.sizeThatFits(bounds.size) let titleLabelSize = _xionTitleLabel.sizeThatFits(bounds.size)
@@ -72,7 +72,7 @@ class HeaderView: UIView
let totalLabelsHeight = titleLabelSize.height + titleJPVerticalMargin + jpLabelSize.height let totalLabelsHeight = titleLabelSize.height + titleJPVerticalMargin + jpLabelSize.height
let titleFrame = CGRect( let titleFrame = CGRect(
x: CGRectGetMaxX(logoFrame) + hpadding * 2.0, x: logoFrame.maxX + hpadding * 2.0,
y: rint(bounds.size.height / 2.0 - totalLabelsHeight / 2.0), y: rint(bounds.size.height / 2.0 - totalLabelsHeight / 2.0),
width: titleLabelSize.width, width: titleLabelSize.width,
height: titleLabelSize.height height: titleLabelSize.height
@@ -81,7 +81,7 @@ class HeaderView: UIView
let jpTitleFrame = CGRect( let jpTitleFrame = CGRect(
x: titleFrame.origin.x, x: titleFrame.origin.x,
y: CGRectGetMaxY(titleFrame) + titleJPVerticalMargin, y: titleFrame.maxY + titleJPVerticalMargin,
width: jpLabelSize.width, width: jpLabelSize.width,
height: jpLabelSize.height + 2.0 height: jpLabelSize.height + 2.0
) )

View File

@@ -10,22 +10,22 @@ import UIKit
class SwitchIndicatorView: UIView class SwitchIndicatorView: UIView
{ {
private var _status: Bool = false fileprivate var _status: Bool = false
private var _foregroundColor: UIColor = UIColor.whiteColor() fileprivate var _foregroundColor: UIColor = UIColor.white
private var _outerCircleLayer: CAShapeLayer = CAShapeLayer() fileprivate var _outerCircleLayer: CAShapeLayer = CAShapeLayer()
private var _offSymbolLayer: CAShapeLayer = CAShapeLayer() fileprivate var _offSymbolLayer: CAShapeLayer = CAShapeLayer()
private var _onSymbolLayer: CAShapeLayer = CAShapeLayer() fileprivate var _onSymbolLayer: CAShapeLayer = CAShapeLayer()
static private var lineWidth: CGFloat = 2.0 static fileprivate var lineWidth: CGFloat = 2.0
override init(frame: CGRect) override init(frame: CGRect)
{ {
super.init(frame: frame) super.init(frame: frame)
_outerCircleLayer.fillColor = UIColor.clearColor().CGColor _outerCircleLayer.fillColor = UIColor.clear.cgColor
_outerCircleLayer.lineWidth = SwitchIndicatorView.lineWidth _outerCircleLayer.lineWidth = SwitchIndicatorView.lineWidth
_offSymbolLayer.fillColor = UIColor.clearColor().CGColor _offSymbolLayer.fillColor = UIColor.clear.cgColor
_offSymbolLayer.lineWidth = SwitchIndicatorView.lineWidth _offSymbolLayer.lineWidth = SwitchIndicatorView.lineWidth
self.layer.addSublayer(_outerCircleLayer) self.layer.addSublayer(_outerCircleLayer)
@@ -33,7 +33,7 @@ class SwitchIndicatorView: UIView
self.layer.addSublayer(_onSymbolLayer) self.layer.addSublayer(_onSymbolLayer)
self.status = false self.status = false
self.foregroundColor = UIColor.whiteColor() self.foregroundColor = UIColor.white
} }
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
@@ -52,7 +52,7 @@ class SwitchIndicatorView: UIView
_offSymbolLayer.frame = bounds _offSymbolLayer.frame = bounds
_onSymbolLayer.frame = bounds _onSymbolLayer.frame = bounds
_outerCircleLayer.path = CGPathCreateWithEllipseInRect(bounds, nil) _outerCircleLayer.path = CGPath(ellipseIn: bounds, transform: nil)
let innerSize = CGSize(width: rint(bounds.size.width / 2.0), height: rint(bounds.size.height / 2.0)) let innerSize = CGSize(width: rint(bounds.size.width / 2.0), height: rint(bounds.size.height / 2.0))
let innerBounds = CGRect( let innerBounds = CGRect(
@@ -61,7 +61,7 @@ class SwitchIndicatorView: UIView
width: innerSize.width, width: innerSize.width,
height: innerSize.height height: innerSize.height
) )
_offSymbolLayer.path = CGPathCreateWithEllipseInRect(innerBounds, nil) _offSymbolLayer.path = CGPath(ellipseIn: innerBounds, transform: nil)
let onSymbolSize = CGSize(width: lineWidth, height: innerSize.height) let onSymbolSize = CGSize(width: lineWidth, height: innerSize.height)
let onSymbolRect = CGRect( let onSymbolRect = CGRect(
@@ -70,7 +70,7 @@ class SwitchIndicatorView: UIView
width: onSymbolSize.width, width: onSymbolSize.width,
height: onSymbolSize.height height: onSymbolSize.height
) )
_onSymbolLayer.path = CGPathCreateWithRect(onSymbolRect, nil) _onSymbolLayer.path = CGPath(rect: onSymbolRect, transform: nil)
} }
// MARK: API // MARK: API
@@ -85,8 +85,8 @@ class SwitchIndicatorView: UIView
set(status) set(status)
{ {
_status = status _status = status
_offSymbolLayer.hidden = _status _offSymbolLayer.isHidden = _status
_onSymbolLayer.hidden = !_status _onSymbolLayer.isHidden = !_status
} }
} }
@@ -100,9 +100,9 @@ class SwitchIndicatorView: UIView
set(color) set(color)
{ {
_foregroundColor = color _foregroundColor = color
_outerCircleLayer.strokeColor = _foregroundColor.CGColor _outerCircleLayer.strokeColor = _foregroundColor.cgColor
_offSymbolLayer.strokeColor = _foregroundColor.CGColor _offSymbolLayer.strokeColor = _foregroundColor.cgColor
_onSymbolLayer.fillColor = _foregroundColor.CGColor _onSymbolLayer.fillColor = _foregroundColor.cgColor
} }
} }
} }

View File

@@ -8,12 +8,12 @@
import UIKit import UIKit
public class WemoCellView: UICollectionViewCell open class WemoCellView: UICollectionViewCell
{ {
private var _selectionOverlayView: UIView = UIView() fileprivate var _selectionOverlayView: UIView = UIView()
static private var disabledBackgroundColor = UIColor(white: 0.2, alpha: 1.0) static fileprivate var disabledBackgroundColor = UIColor(white: 0.2, alpha: 1.0)
static private var enabledBackgroundColor = UIColor(red: 0.0, green: 0.8, blue: 0.0, alpha: 1.0) static fileprivate var enabledBackgroundColor = UIColor(red: 0.0, green: 0.8, blue: 0.0, alpha: 1.0)
override init(frame: CGRect) override init(frame: CGRect)
{ {
@@ -21,7 +21,7 @@ public class WemoCellView: UICollectionViewCell
self.contentView.backgroundColor = WemoCellView.disabledBackgroundColor self.contentView.backgroundColor = WemoCellView.disabledBackgroundColor
_selectionOverlayView.backgroundColor = UIColor.clearColor() _selectionOverlayView.backgroundColor = UIColor.clear
self.contentView.addSubview(_selectionOverlayView) self.contentView.addSubview(_selectionOverlayView)
} }
@@ -32,7 +32,7 @@ public class WemoCellView: UICollectionViewCell
// MARK: Overrides // MARK: Overrides
override public func layoutSubviews() override open func layoutSubviews()
{ {
super.layoutSubviews() super.layoutSubviews()
@@ -40,29 +40,30 @@ public class WemoCellView: UICollectionViewCell
_selectionOverlayView.frame = bounds _selectionOverlayView.frame = bounds
} }
override public var highlighted: Bool { override open var isHighlighted: Bool {
didSet didSet
{ {
if (self.highlighted) { if (self.isHighlighted) {
_selectionOverlayView.backgroundColor = UIColor(white: 0.8, alpha: 1.0) _selectionOverlayView.backgroundColor = UIColor(white: 0.8, alpha: 1.0)
} else { } else {
let animOptions = UIViewAnimationOptions([.AllowUserInteraction]) let animOptions = UIViewAnimationOptions([.allowUserInteraction])
UIView.animateWithDuration(1.0, delay: 0.0, options: animOptions, animations: { UIView.animate(withDuration: 1.0, delay: 0.0, options: animOptions, animations: {
self._selectionOverlayView.backgroundColor = UIColor.clearColor() self._selectionOverlayView.backgroundColor = UIColor.clear
}, completion: nil) }, completion: nil)
} }
} }
} }
} }
public class WemoDeviceCellView: WemoCellView { open class WemoDeviceCellView: WemoCellView
private var _ordinal: Int = 0 {
private var _nameLabel: UILabel = UILabel() fileprivate var _ordinal: Int = 0
private var _ordinalLabel: UILabel = UILabel() fileprivate var _nameLabel: UILabel = UILabel()
private var _indicator: SwitchIndicatorView = SwitchIndicatorView() fileprivate var _ordinalLabel: UILabel = UILabel()
fileprivate var _indicator: SwitchIndicatorView = SwitchIndicatorView()
static private var disabledAnnotationsColor = UIColor.darkGrayColor() static fileprivate var disabledAnnotationsColor = UIColor.darkGray
static private var enabledAnnotationsColor = UIColor.blackColor() static fileprivate var enabledAnnotationsColor = UIColor.black
override init(frame: CGRect) override init(frame: CGRect)
{ {
@@ -72,7 +73,7 @@ public class WemoDeviceCellView: WemoCellView {
_nameLabel.numberOfLines = 3 _nameLabel.numberOfLines = 3
_nameLabel.allowsDefaultTighteningForTruncation = true _nameLabel.allowsDefaultTighteningForTruncation = true
_nameLabel.adjustsFontSizeToFitWidth = true _nameLabel.adjustsFontSizeToFitWidth = true
_nameLabel.textColor = UIColor.whiteColor() _nameLabel.textColor = UIColor.white
self.contentView.addSubview(_nameLabel) self.contentView.addSubview(_nameLabel)
_ordinalLabel.font = UIFont(name: "Orbitron-Medium", size: 21.0) _ordinalLabel.font = UIFont(name: "Orbitron-Medium", size: 21.0)
@@ -91,7 +92,7 @@ public class WemoDeviceCellView: WemoCellView {
// MARK: Overrides // MARK: Overrides
override public func layoutSubviews() override open func layoutSubviews()
{ {
super.layoutSubviews() super.layoutSubviews()
@@ -128,7 +129,7 @@ public class WemoDeviceCellView: WemoCellView {
{ {
didSet didSet
{ {
_nameLabel.text = self.deviceName.uppercaseString _nameLabel.text = self.deviceName.uppercased()
self.setNeedsLayout() self.setNeedsLayout()
} }
} }
@@ -167,7 +168,8 @@ public class WemoDeviceCellView: WemoCellView {
} }
} }
public class WemoActionCellView: WemoCellView { open class WemoActionCellView: WemoCellView
{
var textLabel: UILabel = UILabel() var textLabel: UILabel = UILabel()
override init(frame: CGRect) override init(frame: CGRect)
@@ -175,8 +177,8 @@ public class WemoActionCellView: WemoCellView {
super.init(frame: frame) super.init(frame: frame)
self.textLabel.font = UIFont(name: "Orbitron-Medium", size: 21.0) self.textLabel.font = UIFont(name: "Orbitron-Medium", size: 21.0)
self.textLabel.textColor = UIColor.whiteColor() self.textLabel.textColor = UIColor.white
self.textLabel.textAlignment = .Center self.textLabel.textAlignment = .center
self.addSubview(self.textLabel) self.addSubview(self.textLabel)
} }
@@ -185,7 +187,7 @@ public class WemoActionCellView: WemoCellView {
fatalError("unsupported") fatalError("unsupported")
} }
override public func layoutSubviews() override open func layoutSubviews()
{ {
super.layoutSubviews() super.layoutSubviews()
self.textLabel.frame = self.bounds self.textLabel.frame = self.bounds
@@ -196,9 +198,9 @@ public class WemoActionCellView: WemoCellView {
didSet didSet
{ {
if (enabled) { if (enabled) {
self.textLabel.textColor = UIColor.whiteColor() self.textLabel.textColor = UIColor.white
} else { } else {
self.textLabel.textColor = UIColor.darkGrayColor() self.textLabel.textColor = UIColor.darkGray
} }
} }
} }

View File

@@ -10,24 +10,24 @@ import UIKit
class XIONLogoView: UIView class XIONLogoView: UIView
{ {
private var _xionLogoImageView: UIImageView = UIImageView() fileprivate var _xionLogoImageView: UIImageView = UIImageView()
private var _logoInnerRingImageView: UIImageView = UIImageView() fileprivate var _logoInnerRingImageView: UIImageView = UIImageView()
private var _logoOuterRingImageView: UIImageView = UIImageView() fileprivate var _logoOuterRingImageView: UIImageView = UIImageView()
override init(frame: CGRect) override init(frame: CGRect)
{ {
super.init(frame: frame) super.init(frame: frame)
self.backgroundColor = UIColor.blackColor() self.backgroundColor = UIColor.black
_xionLogoImageView.image = UIImage(named: "XIONLogoWithRing") _xionLogoImageView.image = UIImage(named: "XIONLogoWithRing")
_xionLogoImageView.contentMode = .ScaleAspectFit _xionLogoImageView.contentMode = .scaleAspectFit
_logoInnerRingImageView.image = UIImage(named: "XIONLogoInnerRing") _logoInnerRingImageView.image = UIImage(named: "XIONLogoInnerRing")
_logoInnerRingImageView.contentMode = .ScaleAspectFit _logoInnerRingImageView.contentMode = .scaleAspectFit
_logoOuterRingImageView.image = UIImage(named: "XIONLogoOuterRing") _logoOuterRingImageView.image = UIImage(named: "XIONLogoOuterRing")
_logoOuterRingImageView.contentMode = .ScaleAspectFit _logoOuterRingImageView.contentMode = .scaleAspectFit
self.addSubview(_logoOuterRingImageView) self.addSubview(_logoOuterRingImageView)
self.addSubview(_logoInnerRingImageView) self.addSubview(_logoInnerRingImageView)
@@ -55,7 +55,7 @@ class XIONLogoView: UIView
{ {
self.stopAnimating() self.stopAnimating()
let duration: NSTimeInterval = 20.0 let duration: TimeInterval = 20.0
let clockwiseAnim = CABasicAnimation(keyPath: "transform.rotation") let clockwiseAnim = CABasicAnimation(keyPath: "transform.rotation")
clockwiseAnim.fromValue = 0.0 clockwiseAnim.fromValue = 0.0
@@ -69,8 +69,8 @@ class XIONLogoView: UIView
counterClockwiseAnim.duration = duration counterClockwiseAnim.duration = duration
counterClockwiseAnim.repeatCount = Float.infinity counterClockwiseAnim.repeatCount = Float.infinity
_logoInnerRingImageView.layer.addAnimation(clockwiseAnim, forKey: "LogoClockwiseAnimation") _logoInnerRingImageView.layer.add(clockwiseAnim, forKey: "LogoClockwiseAnimation")
_logoOuterRingImageView.layer.addAnimation(counterClockwiseAnim, forKey: "LogoCounterclockwiseAnimation") _logoOuterRingImageView.layer.add(counterClockwiseAnim, forKey: "LogoCounterclockwiseAnimation")
} }
func stopAnimating() func stopAnimating()