Conversion to Swift3
This commit is contained in:
@@ -14,35 +14,35 @@ class AppDelegate: UIResponder, UIApplicationDelegate
|
||||
var window: UIWindow?
|
||||
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?.makeKeyAndVisible()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(application: UIApplication)
|
||||
func applicationDidBecomeActive(_ application: UIApplication)
|
||||
{
|
||||
self.mainViewController.viewDidAppear(false)
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(application: UIApplication)
|
||||
func applicationDidEnterBackground(_ application: UIApplication)
|
||||
{
|
||||
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) {
|
||||
mask = UIInterfaceOrientationMask.Portrait
|
||||
if (UIDevice.current.userInterfaceIdiom == .phone) {
|
||||
mask = UIInterfaceOrientationMask.portrait
|
||||
} else {
|
||||
mask = UIInterfaceOrientationMask.All
|
||||
mask = UIInterfaceOrientationMask.all
|
||||
}
|
||||
|
||||
return mask
|
||||
|
||||
@@ -10,15 +10,15 @@ import UIKit
|
||||
|
||||
class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
{
|
||||
private var _server: WemoServer
|
||||
private var _visualizationController: VisualizationViewController = VisualizationViewController()
|
||||
private var _switchesController: SwitchesViewController = SwitchesViewController()
|
||||
private var _headerView: HeaderView = HeaderView()
|
||||
private var _updateDevices: Bool = false
|
||||
fileprivate var _server: WemoServer
|
||||
fileprivate var _visualizationController: VisualizationViewController = VisualizationViewController()
|
||||
fileprivate var _switchesController: SwitchesViewController = SwitchesViewController()
|
||||
fileprivate var _headerView: HeaderView = HeaderView()
|
||||
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!)
|
||||
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
@@ -35,7 +35,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.view.backgroundColor = UIColor.blackColor()
|
||||
self.view.backgroundColor = UIColor.black
|
||||
|
||||
self.addChildViewController(_visualizationController)
|
||||
self.view.addSubview(_visualizationController.view)
|
||||
@@ -46,7 +46,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
|
||||
self.view.addSubview(_headerView)
|
||||
|
||||
_updateConnectivityStatus(.Disconnected)
|
||||
_updateConnectivityStatus(.disconnected)
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
@@ -64,7 +64,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
)
|
||||
let bodyBounds = CGRect(
|
||||
x: 0.0,
|
||||
y: CGRectGetMaxY(headerBounds),
|
||||
y: headerBounds.maxY,
|
||||
width: bounds.size.width,
|
||||
height: bounds.size.height - headerBounds.size.height
|
||||
)
|
||||
@@ -81,8 +81,8 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
|
||||
var switchesOriginX: CGFloat = 0.0
|
||||
var switchesWidth: CGFloat = 0.0
|
||||
if (horizontalSizeClass == .Regular) {
|
||||
switchesOriginX = CGRectGetMaxX(visualizationFrame)
|
||||
if (horizontalSizeClass == .regular) {
|
||||
switchesOriginX = visualizationFrame.maxX
|
||||
switchesWidth = bodyBounds.size.width - visualizationFrame.size.width
|
||||
} else {
|
||||
switchesOriginX = 0.0
|
||||
@@ -98,32 +98,32 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
_switchesController.view.frame = switchesControllerFrame
|
||||
}
|
||||
|
||||
override func viewDidAppear(animated: Bool)
|
||||
override func viewDidAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
_headerView.xionLogoView.beginAnimating()
|
||||
|
||||
if (!_server.connected) {
|
||||
_updateConnectivityStatus(.Connecting)
|
||||
_server.connect { (error: NSError?) -> Void in
|
||||
_updateConnectivityStatus(.connecting)
|
||||
_server.connect { (error: Error?) -> Void in
|
||||
if (error == nil) {
|
||||
self._reloadDevices()
|
||||
self._startUpdatingDevices()
|
||||
} 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()
|
||||
}
|
||||
|
||||
override func prefersStatusBarHidden() -> Bool
|
||||
override var prefersStatusBarHidden : Bool
|
||||
{
|
||||
return true
|
||||
}
|
||||
@@ -141,12 +141,12 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
|
||||
// MARK: SwitchesViewControllerDelegate
|
||||
|
||||
func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice])
|
||||
func switchesViewControllerDidToggleDevices(_ controller: SwitchesViewController, devices: [WemoDevice])
|
||||
{
|
||||
_updateVisualization(true)
|
||||
|
||||
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()
|
||||
{
|
||||
let horizontalSizeClass = self.traitCollection.horizontalSizeClass
|
||||
if (horizontalSizeClass == .Regular) {
|
||||
_visualizationController.view.hidden = false
|
||||
if (horizontalSizeClass == .regular) {
|
||||
_visualizationController.view.isHidden = false
|
||||
} else {
|
||||
_visualizationController.view.hidden = true
|
||||
_visualizationController.view.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
internal func _updateVisualization(animated: Bool)
|
||||
internal func _updateVisualization(_ animated: Bool)
|
||||
{
|
||||
var activatedDevicesCount = 0
|
||||
for device in self.devices {
|
||||
if (device.state == .On) {
|
||||
if (device.state == .on) {
|
||||
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.setNeedsLayout()
|
||||
self._visualizationController.connectionStatus = status
|
||||
@@ -188,14 +188,14 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
|
||||
internal func _reloadDevices()
|
||||
{
|
||||
_server.fetchDevices({ (devices: [WemoDevice], error: NSError?) -> Void in
|
||||
dispatch_async(dispatch_get_main_queue()) { () -> Void in
|
||||
_server.fetchDevices({ (devices: [WemoDevice], error: Error?) -> Void in
|
||||
DispatchQueue.main.async { () -> Void in
|
||||
if (error == nil) {
|
||||
self.devices = devices
|
||||
self._updateConnectivityStatus(.Connected)
|
||||
self._updateConnectivityStatus(.connected)
|
||||
} else {
|
||||
self.devices = []
|
||||
self._updateConnectivityStatus(.Error)
|
||||
self._updateConnectivityStatus(.error)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -205,8 +205,8 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate
|
||||
{
|
||||
_updateDevices = true
|
||||
|
||||
let interval = dispatch_time(DISPATCH_TIME_NOW, Int64(10 * Double(NSEC_PER_SEC)))
|
||||
dispatch_after(interval, dispatch_get_main_queue()) { () -> Void in
|
||||
let interval = DispatchTime.now() + Double(Int64(10 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
|
||||
DispatchQueue.main.asyncAfter(deadline: interval) { () -> Void in
|
||||
if (self._updateDevices) {
|
||||
self._reloadDevices()
|
||||
self._startUpdatingDevices()
|
||||
|
||||
@@ -12,12 +12,12 @@ import UIKit
|
||||
|
||||
protocol SwitchesViewControllerDelegate: class
|
||||
{
|
||||
func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice])
|
||||
func switchesViewControllerDidToggleDevices(_ controller: SwitchesViewController, devices: [WemoDevice])
|
||||
}
|
||||
|
||||
extension SwitchesViewControllerDelegate
|
||||
{
|
||||
func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice]) {}
|
||||
func switchesViewControllerDidToggleDevices(_ controller: SwitchesViewController, devices: [WemoDevice]) {}
|
||||
}
|
||||
|
||||
class SwitchesViewController: UIViewController,
|
||||
@@ -25,25 +25,25 @@ class SwitchesViewController: UIViewController,
|
||||
UICollectionViewDelegateFlowLayout
|
||||
{
|
||||
weak var delegate: SwitchesViewControllerDelegate?
|
||||
private var _collectionView: UICollectionView = UICollectionView(frame: CGRectZero,
|
||||
fileprivate var _collectionView: UICollectionView = UICollectionView(frame: CGRect.zero,
|
||||
collectionViewLayout: UICollectionViewFlowLayout())
|
||||
private var _currentDevicesHash: Int = 0
|
||||
fileprivate var _currentDevicesHash: Int = 0
|
||||
|
||||
static private let collectionViewDeviceSwitchCellReuseIdentifier = "DeviceSwitchReuseID"
|
||||
static private let collectionViewActionCellReuseIdentifier = "ActionCellReuseID"
|
||||
static private let collectionViewCellsSpacing: CGFloat = 5.0
|
||||
static fileprivate let collectionViewDeviceSwitchCellReuseIdentifier = "DeviceSwitchReuseID"
|
||||
static fileprivate let collectionViewActionCellReuseIdentifier = "ActionCellReuseID"
|
||||
static fileprivate let collectionViewCellsSpacing: CGFloat = 5.0
|
||||
|
||||
private enum ActionCell: Int
|
||||
fileprivate enum ActionCell: Int
|
||||
{
|
||||
case AllOn
|
||||
case AllOff
|
||||
case allOn
|
||||
case allOff
|
||||
|
||||
func name() -> String
|
||||
{
|
||||
switch self {
|
||||
case .AllOn:
|
||||
case .allOn:
|
||||
return "All On"
|
||||
case .AllOff:
|
||||
case .allOff:
|
||||
return "All Off"
|
||||
}
|
||||
}
|
||||
@@ -62,15 +62,15 @@ class SwitchesViewController: UIViewController,
|
||||
let deviceCellReuseID = SwitchesViewController.collectionViewDeviceSwitchCellReuseIdentifier
|
||||
let actionCellReuseID = SwitchesViewController.collectionViewActionCellReuseIdentifier
|
||||
let layout = _collectionView.collectionViewLayout as! UICollectionViewFlowLayout
|
||||
layout.scrollDirection = .Vertical
|
||||
layout.scrollDirection = .vertical
|
||||
layout.minimumInteritemSpacing = SwitchesViewController.collectionViewCellsSpacing
|
||||
layout.minimumLineSpacing = SwitchesViewController.collectionViewCellsSpacing
|
||||
|
||||
_collectionView.backgroundColor = UIColor.blackColor()
|
||||
_collectionView.backgroundColor = UIColor.black
|
||||
_collectionView.delegate = self
|
||||
_collectionView.dataSource = self
|
||||
_collectionView.registerClass(WemoDeviceCellView.self, forCellWithReuseIdentifier: deviceCellReuseID)
|
||||
_collectionView.registerClass(WemoActionCellView.self, forCellWithReuseIdentifier: actionCellReuseID)
|
||||
_collectionView.register(WemoDeviceCellView.self, forCellWithReuseIdentifier: deviceCellReuseID)
|
||||
_collectionView.register(WemoActionCellView.self, forCellWithReuseIdentifier: actionCellReuseID)
|
||||
self.view.addSubview(_collectionView)
|
||||
|
||||
self.devices = []
|
||||
@@ -91,36 +91,36 @@ class SwitchesViewController: UIViewController,
|
||||
didSet
|
||||
{
|
||||
// sort devices by name
|
||||
self.devices.sortInPlace({ (d1: WemoDevice, d2: WemoDevice) -> Bool in
|
||||
return (d1.name.compare(d2.name) == .OrderedAscending)
|
||||
self.devices.sort(by: { (d1: WemoDevice, d2: WemoDevice) -> Bool in
|
||||
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) {
|
||||
let previousSet = NSOrderedSet(array: oldValue)
|
||||
let newSet = NSOrderedSet(array: self.devices)
|
||||
var insertedIndexPaths: [NSIndexPath] = []
|
||||
var updatedIndexPaths: [NSIndexPath] = []
|
||||
var deletedIndexPaths: [NSIndexPath] = []
|
||||
var insertedIndexPaths: [IndexPath] = []
|
||||
var updatedIndexPaths: [IndexPath] = []
|
||||
var deletedIndexPaths: [IndexPath] = []
|
||||
|
||||
// if we have devices now and we didn't before, or vice versa,
|
||||
// we need to update the action cells
|
||||
if ((oldValue.count == 0 && self.devices.count != 0) || (self.devices.count == 0 && oldValue.count != 0)) {
|
||||
for actionCellIdx in 0 ..< ActionCell.count {
|
||||
let actionCellIndexPath = NSIndexPath(forItem: actionCellIdx, inSection: 0)
|
||||
let actionCellIndexPath = IndexPath(item: actionCellIdx, section: 0)
|
||||
updatedIndexPaths.append(actionCellIndexPath)
|
||||
}
|
||||
}
|
||||
|
||||
// find deletes and updates
|
||||
for (idx, device) in previousSet.enumerate() {
|
||||
for (idx, device) in previousSet.enumerated() {
|
||||
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)
|
||||
} 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)) {
|
||||
updatedIndexPaths.append(curIndexPath)
|
||||
}
|
||||
@@ -128,19 +128,19 @@ class SwitchesViewController: UIViewController,
|
||||
}
|
||||
|
||||
// find insertions
|
||||
for (idx, device) in newSet.enumerate() {
|
||||
if (!previousSet.containsObject(device)) {
|
||||
for (idx, device) in newSet.enumerated() {
|
||||
if (!previousSet.contains(device)) {
|
||||
let itemIndex = idx + ActionCell.count
|
||||
let insertedIndexPath = NSIndexPath(forItem: itemIndex, inSection: 0)
|
||||
let insertedIndexPath = IndexPath(item: itemIndex, section: 0)
|
||||
insertedIndexPaths.append(insertedIndexPath)
|
||||
}
|
||||
}
|
||||
|
||||
UIView.performWithoutAnimation { () -> Void in
|
||||
self._collectionView.performBatchUpdates({ () -> Void in
|
||||
self._collectionView.deleteItemsAtIndexPaths(deletedIndexPaths)
|
||||
self._collectionView.reloadItemsAtIndexPaths(updatedIndexPaths)
|
||||
self._collectionView.insertItemsAtIndexPaths(insertedIndexPaths)
|
||||
self._collectionView.deleteItems(at: deletedIndexPaths)
|
||||
self._collectionView.reloadItems(at: updatedIndexPaths)
|
||||
self._collectionView.insertItems(at: insertedIndexPaths)
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
@@ -151,46 +151,47 @@ class SwitchesViewController: UIViewController,
|
||||
|
||||
// MARK: UICollectionView
|
||||
|
||||
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
||||
{
|
||||
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) {
|
||||
let reuseID = SwitchesViewController.collectionViewActionCellReuseIdentifier
|
||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseID, forIndexPath: indexPath) as! WemoActionCellView
|
||||
cell.textLabel.text = ActionCell(rawValue: indexPath.item)?.name().uppercaseString
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseID, for: indexPath) as! WemoActionCellView
|
||||
cell.textLabel.text = ActionCell(rawValue: indexPath.item)?.name().uppercased()
|
||||
cell.enabled = (self.devices.count > 0)
|
||||
|
||||
return cell
|
||||
} else {
|
||||
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)
|
||||
cell.deviceName = device.name
|
||||
cell.toggled = (device.state == .On)
|
||||
cell.toggled = (device.state == .on)
|
||||
cell.ordinal = indexPath.item - ActionCell.count + 1
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView,
|
||||
func collectionView(_ collectionView: UICollectionView,
|
||||
layout collectionViewLayout: UICollectionViewLayout,
|
||||
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
|
||||
sizeForItemAt indexPath: IndexPath) -> CGSize
|
||||
{
|
||||
let spacing = SwitchesViewController.collectionViewCellsSpacing
|
||||
let bounds = collectionView.bounds
|
||||
var cellsPerRow: CGFloat = 0.0
|
||||
|
||||
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
|
||||
break
|
||||
case .Compact:
|
||||
case .compact:
|
||||
cellsPerRow = 2.0
|
||||
default:
|
||||
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) {
|
||||
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) {
|
||||
if let cell = collectionView.cellForItemAtIndexPath(NSIndexPath(forItem: i, inSection: indexPath.section)) as? WemoDeviceCellView {
|
||||
let animOptions = UIViewAnimationOptions([.AllowUserInteraction])
|
||||
for i in ActionCell.count ..< collectionView.numberOfItems(inSection: indexPath.section) {
|
||||
if let cell = collectionView.cellForItem(at: IndexPath(item: i, section: indexPath.section)) as? WemoDeviceCellView {
|
||||
let animOptions = UIViewAnimationOptions([.allowUserInteraction])
|
||||
|
||||
UIView.animateWithDuration(0.3, delay: currentDelay, options: animOptions, animations: {
|
||||
cell.toggled = (tappedActionCell == .AllOn)
|
||||
UIView.animate(withDuration: 0.3, delay: currentDelay, options: animOptions, animations: {
|
||||
cell.toggled = (tappedActionCell == .allOn)
|
||||
}, completion: nil)
|
||||
|
||||
currentDelay += 0.05
|
||||
@@ -223,22 +224,22 @@ class SwitchesViewController: UIViewController,
|
||||
}
|
||||
|
||||
for device in self.devices {
|
||||
device.state = (tappedActionCell == .AllOn ? .On : .Off)
|
||||
device.state = (tappedActionCell == .allOn ? .on : .off)
|
||||
}
|
||||
|
||||
self.delegate?.switchesViewControllerDidToggleDevices(self, devices: self.devices)
|
||||
} else {
|
||||
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! WemoDeviceCellView
|
||||
let cell = collectionView.cellForItem(at: indexPath) as! WemoDeviceCellView
|
||||
cell.toggled = !cell.toggled
|
||||
|
||||
let device = _deviceAtIndexPath(indexPath)
|
||||
device.state = (cell.toggled ? .On : .Off)
|
||||
device.state = (cell.toggled ? .on : .off)
|
||||
|
||||
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) {
|
||||
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) {
|
||||
return (self.devices.count > 0)
|
||||
@@ -258,7 +259,7 @@ class SwitchesViewController: UIViewController,
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal func _deviceAtIndexPath(indexPath: NSIndexPath) -> WemoDevice
|
||||
internal func _deviceAtIndexPath(_ indexPath: IndexPath) -> WemoDevice
|
||||
{
|
||||
let deviceIdx = indexPath.item - ActionCell.count
|
||||
let device = self.devices[deviceIdx]
|
||||
|
||||
@@ -11,31 +11,32 @@ import Foundation
|
||||
import GLKit
|
||||
import SceneKit
|
||||
import UIKit
|
||||
import SceneKit
|
||||
|
||||
let π = CGFloat(M_PI)
|
||||
let π = CGFloat(Double.pi)
|
||||
|
||||
class VisualizationViewController: UIViewController
|
||||
{
|
||||
private var _scene: SCNScene = SCNScene()
|
||||
private var _sceneView: SCNView?
|
||||
private var _cameraNode: SCNNode = SCNNode()
|
||||
private var _lightNode: SCNNode = SCNNode()
|
||||
private var _cubletsNode: SCNNode = SCNNode()
|
||||
private var _cublets: [SCNNode] = []
|
||||
private var _percentActivated: Float = 0.0
|
||||
fileprivate var _scene: SCNScene = SCNScene()
|
||||
fileprivate var _sceneView: SCNView?
|
||||
fileprivate var _cameraNode: SCNNode = SCNNode()
|
||||
fileprivate var _lightNode: SCNNode = SCNNode()
|
||||
fileprivate var _cubletsNode: SCNNode = SCNNode()
|
||||
fileprivate var _cublets: [SCNNode] = []
|
||||
fileprivate var _percentActivated: Float = 0.0
|
||||
|
||||
static private let cubletsDimensions = 5
|
||||
static private let cubletsSize = 1.0
|
||||
static private let cubletsSpacing = 2.0
|
||||
static private let rotationAnimationKey = "RotationAnimation"
|
||||
static fileprivate let cubletsDimensions = 5
|
||||
static fileprivate let cubletsSize = 1.0
|
||||
static fileprivate let cubletsSpacing = 2.0
|
||||
static fileprivate let rotationAnimationKey = "RotationAnimation"
|
||||
|
||||
// MARK: Overrides
|
||||
|
||||
override func loadView()
|
||||
{
|
||||
let opts = [SCNPreferredRenderingAPIKey : SCNRenderingAPI.OpenGLES2.rawValue]
|
||||
let view = SCNView(frame: UIScreen.mainScreen().bounds, options: opts)
|
||||
view.backgroundColor = UIColor.blackColor()
|
||||
let opts = [SCNView.Option.preferredRenderingAPI.rawValue : SCNRenderingAPI.openGLES2]
|
||||
let view = SCNView(frame: UIScreen.main.bounds, options: opts)
|
||||
view.backgroundColor = UIColor.black
|
||||
view.scene = _scene
|
||||
view.allowsCameraControl = false
|
||||
|
||||
@@ -55,13 +56,13 @@ class VisualizationViewController: UIViewController
|
||||
_beginModelResetTimer()
|
||||
}
|
||||
|
||||
override func viewDidAppear(animated: Bool)
|
||||
override func viewDidAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidAppear(animated)
|
||||
_sceneView?.play(nil)
|
||||
}
|
||||
|
||||
override func viewDidDisappear(animated: Bool)
|
||||
override func viewDidDisappear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidDisappear(animated)
|
||||
_sceneView?.stop(nil)
|
||||
@@ -69,17 +70,17 @@ class VisualizationViewController: UIViewController
|
||||
|
||||
// MARK: API
|
||||
|
||||
var connectionStatus: ConnectionStatus = .Disconnected
|
||||
var connectionStatus: ConnectionStatus = .disconnected
|
||||
{
|
||||
didSet
|
||||
{
|
||||
switch (self.connectionStatus) {
|
||||
case .Disconnected, .Connecting, .Error:
|
||||
_cubletsNode.paused = true
|
||||
case .disconnected, .connecting, .error:
|
||||
_cubletsNode.isPaused = true
|
||||
_lightNode.light?.color = UIColor(white: 0.3, alpha: 1.0)
|
||||
case .Connected:
|
||||
_cubletsNode.paused = false
|
||||
_lightNode.light?.color = UIColor.whiteColor()
|
||||
case .connected:
|
||||
_cubletsNode.isPaused = false
|
||||
_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 cubletsToActivate = UInt(percentage * Float(cubletsCount))
|
||||
@@ -124,8 +125,8 @@ class VisualizationViewController: UIViewController
|
||||
let rotCoeff = CGFloat(arc4random() % 2 == 0 ? -1.0 : 1.0)
|
||||
let rotAngle = CGFloat(rotCoeff * π / 4.0)
|
||||
|
||||
let rotAction = SCNAction.rotateByAngle(rotAngle, aroundAxis: rotAxis, duration: 0.8)
|
||||
rotAction.timingMode = .Linear
|
||||
let rotAction = SCNAction.rotate(by: rotAngle, around: rotAxis, duration: 0.8)
|
||||
rotAction.timingMode = .linear
|
||||
rotAction.timingFunction = { (t: Float) -> Float in
|
||||
return min(((log10(4.0 * (t + 0.03)) + 1.0) / 1.5), 1.0)
|
||||
}
|
||||
@@ -134,7 +135,7 @@ class VisualizationViewController: UIViewController
|
||||
// smooth transition
|
||||
let longTermAnimKey = VisualizationViewController.rotationAnimationKey
|
||||
let newLongTermRotAction = _createLongTermRotationAnimation((rotCoeff * 2.0 * π), rotAxis)
|
||||
_cubletsNode.removeActionForKey(longTermAnimKey)
|
||||
_cubletsNode.removeAction(forKey: longTermAnimKey)
|
||||
|
||||
let actionSeq = SCNAction.sequence([rotAction, newLongTermRotAction])
|
||||
_cubletsNode.runAction(actionSeq, forKey: longTermAnimKey)
|
||||
@@ -166,8 +167,8 @@ class VisualizationViewController: UIViewController
|
||||
internal func _setupLights()
|
||||
{
|
||||
let light = SCNLight()
|
||||
light.type = SCNLightTypeOmni
|
||||
light.color = UIColor.whiteColor()
|
||||
light.type = SCNLight.LightType.omni
|
||||
light.color = UIColor.white
|
||||
|
||||
_lightNode = SCNNode()
|
||||
_lightNode.light = light
|
||||
@@ -178,7 +179,7 @@ class VisualizationViewController: UIViewController
|
||||
|
||||
internal func _setupModel()
|
||||
{
|
||||
_cubletsNode.enumerateChildNodesUsingBlock { $0.0.removeFromParentNode() }
|
||||
_cubletsNode.enumerateChildNodes { $0.0.removeFromParentNode() }
|
||||
_cublets.removeAll()
|
||||
|
||||
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.
|
||||
let geom = SCNBox(width: CGFloat(sz), height: CGFloat(sz), length: CGFloat(sz), chamferRadius: 0.0)
|
||||
let material = SCNMaterial()
|
||||
material.diffuse.contents = UIColor.whiteColor()
|
||||
material.diffuse.contents = UIColor.white
|
||||
material.transparency = 0.75
|
||||
|
||||
// generate nodes for each cublet
|
||||
@@ -216,7 +217,7 @@ class VisualizationViewController: UIViewController
|
||||
}
|
||||
|
||||
_cubletsNode.position = SCNVector3Zero
|
||||
if (_cubletsNode.parentNode == nil) {
|
||||
if (_cubletsNode.parent == nil) {
|
||||
_scene.rootNode.addChildNode(_cubletsNode)
|
||||
}
|
||||
}
|
||||
@@ -232,8 +233,8 @@ class VisualizationViewController: UIViewController
|
||||
|
||||
internal func _setupEffects()
|
||||
{
|
||||
let techniqueURL = NSBundle.mainBundle().URLForResource("CubletsTechnique", withExtension: "plist")
|
||||
let techniqueDict = NSDictionary(contentsOfURL: techniqueURL!) as! [String : AnyObject]
|
||||
let techniqueURL = Bundle.main.url(forResource: "CubletsTechnique", withExtension: "plist")
|
||||
let techniqueDict = NSDictionary(contentsOf: techniqueURL!) as! [String : AnyObject]
|
||||
let technique = SCNTechnique(dictionary: techniqueDict)
|
||||
|
||||
_sceneView?.technique = technique
|
||||
@@ -244,8 +245,8 @@ class VisualizationViewController: UIViewController
|
||||
/* 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
|
||||
don't have to see it */
|
||||
let reloadModelTime = dispatch_time(DISPATCH_TIME_NOW, Int64(60 * 60 * 24 * NSEC_PER_SEC))
|
||||
dispatch_after(reloadModelTime, dispatch_get_main_queue()) { [weak self] in
|
||||
let reloadModelTime = DispatchTime.now() + Double(Int64(60 * 60 * 24 * NSEC_PER_SEC)) / Double(NSEC_PER_SEC)
|
||||
DispatchQueue.main.asyncAfter(deadline: reloadModelTime) { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf._cubletsNode.removeFromParentNode()
|
||||
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
|
||||
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
|
||||
if let action = _cubletsNode.actionForKey(key) {
|
||||
_cubletsNode.removeActionForKey(key)
|
||||
if let action = _cubletsNode.action(forKey: key) {
|
||||
_cubletsNode.removeAction(forKey: key)
|
||||
|
||||
action.speed = speed
|
||||
_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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,40 +10,46 @@ import Foundation
|
||||
|
||||
enum ConnectionStatus
|
||||
{
|
||||
case Disconnected
|
||||
case Connecting
|
||||
case Connected
|
||||
case Error
|
||||
case disconnected
|
||||
case connecting
|
||||
case connected
|
||||
case error
|
||||
}
|
||||
|
||||
enum ConnectionError : Error
|
||||
{
|
||||
case unknown
|
||||
case serverUnavailable
|
||||
}
|
||||
|
||||
class WemoServer
|
||||
{
|
||||
private(set) var baseURL: NSURL
|
||||
private(set) var connected: Bool = false
|
||||
fileprivate(set) var baseURL: URL
|
||||
fileprivate(set) var connected: Bool = false
|
||||
|
||||
private var _urlSession: NSURLSession
|
||||
private var _errorStream: StandardErrorOutputStream = StandardErrorOutputStream()
|
||||
private var _operationQueue: NSOperationQueue = NSOperationQueue()
|
||||
fileprivate var _urlSession: URLSession
|
||||
fileprivate var _errorStream: StandardErrorOutputStream = StandardErrorOutputStream()
|
||||
fileprivate var _operationQueue: OperationQueue = OperationQueue()
|
||||
|
||||
init(_ url: NSURL)
|
||||
init(_ url: URL)
|
||||
{
|
||||
self.baseURL = url
|
||||
|
||||
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
|
||||
_urlSession = NSURLSession(configuration: config)
|
||||
let config = URLSessionConfiguration.default
|
||||
_urlSession = URLSession(configuration: config)
|
||||
|
||||
_operationQueue.maxConcurrentOperationCount = 1
|
||||
}
|
||||
|
||||
func connect(completion: (NSError?) -> Void)
|
||||
func connect(_ completion: @escaping (Error?) -> Void)
|
||||
{
|
||||
if (!self.connected) {
|
||||
let op = ConnectOperation(baseURL: self.baseURL, session: _urlSession)
|
||||
weak var weakOp = op
|
||||
op.completionBlock = {
|
||||
guard let strongOp = weakOp else { completion(nil) ; return }
|
||||
if (strongOp.error != nil) {
|
||||
self._logError("Error connecting to server", error: strongOp.error!)
|
||||
if let error = strongOp.error {
|
||||
self._logError("Error connecting to server", error: error)
|
||||
} else {
|
||||
self.connected = true
|
||||
}
|
||||
@@ -56,68 +62,68 @@ class WemoServer
|
||||
}
|
||||
}
|
||||
|
||||
func disconnect(completion: (NSError?) -> Void)
|
||||
func disconnect(_ completion: (Error?) -> Void)
|
||||
{
|
||||
self.connected = false
|
||||
completion(nil)
|
||||
}
|
||||
|
||||
func fetchDevices(completion: ([WemoDevice], NSError?) -> Void)
|
||||
func fetchDevices(_ completion: @escaping ([WemoDevice], Error?) -> Void)
|
||||
{
|
||||
if (self.connected) {
|
||||
let op = FetchDevicesOperation(baseURL: self.baseURL, session: _urlSession)
|
||||
weak var weakOp = op
|
||||
op.completionBlock = {
|
||||
guard let strongOp = weakOp else { completion([], nil) ; return }
|
||||
if (strongOp.error != nil) {
|
||||
self._logError("Error fetching devices", error: strongOp.error!)
|
||||
if let error = strongOp.error {
|
||||
self._logError("Error fetching devices", error: error)
|
||||
}
|
||||
|
||||
completion(strongOp.devices, strongOp.error)
|
||||
}
|
||||
_operationQueue.addOperation(op)
|
||||
} else {
|
||||
let err = NSError.xionError(.ConnectionError)
|
||||
let err = ConnectionError.serverUnavailable
|
||||
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) {
|
||||
let op = ToggleDeviceOperation(baseURL: self.baseURL, session: _urlSession, device: device, state: state)
|
||||
weak var weakOp = op
|
||||
op.completionBlock = {
|
||||
guard let strongOp = weakOp else { completion(nil) ; return }
|
||||
if (strongOp.error != nil) {
|
||||
self._logError("Error toggling device", error: strongOp.error!)
|
||||
if let error = strongOp.error {
|
||||
self._logError("Error toggling device", error: error)
|
||||
}
|
||||
|
||||
completion(strongOp.error)
|
||||
}
|
||||
_operationQueue.addOperation(op)
|
||||
} else {
|
||||
let err = NSError.xionError(.ConnectionError)
|
||||
let err = ConnectionError.serverUnavailable
|
||||
completion(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 session: NSURLSession
|
||||
var baseURL: URL
|
||||
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.session = session
|
||||
@@ -129,16 +135,14 @@ internal class ConnectOperation : WemoOperation
|
||||
override func main()
|
||||
{
|
||||
let semaphore = Semaphore(value: 0)
|
||||
let url = self.baseURL.URLByAppendingPathComponent("api/environment")
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "POST"
|
||||
let url = self.baseURL.appendingPathComponent("api/environment")
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
|
||||
let task = self.session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
|
||||
if (error != nil) {
|
||||
self.error = NSError.xionError(.ConnectionError, underlying: error!)
|
||||
}
|
||||
let task = self.session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
|
||||
self.error = error
|
||||
semaphore.signal()
|
||||
}
|
||||
})
|
||||
task.resume()
|
||||
semaphore.wait()
|
||||
}
|
||||
@@ -151,24 +155,24 @@ internal class FetchDevicesOperation : WemoOperation
|
||||
override func main()
|
||||
{
|
||||
let semaphore = Semaphore(value: 0)
|
||||
let url = self.baseURL.URLByAppendingPathComponent("api/environment")
|
||||
let task = self.session.dataTaskWithURL(url) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
|
||||
let url = self.baseURL.appendingPathComponent("api/environment")
|
||||
let task = self.session.dataTask(with: url, completionHandler: { (data: Data?, response: URLResponse?, error: NSError?) -> Void in
|
||||
if (data != nil) {
|
||||
self.devices = self._parseDevices(data!)
|
||||
} else {
|
||||
self.error = NSError.xionError(.ConnectionError, underlying: error)
|
||||
self.error = NSError.xionError(.connectionError, underlying: error)
|
||||
}
|
||||
semaphore.signal()
|
||||
}
|
||||
} as! (Data?, URLResponse?, Error?) -> Void)
|
||||
task.resume()
|
||||
semaphore.wait()
|
||||
}
|
||||
|
||||
internal func _parseDevices(data: NSData) -> [WemoDevice]
|
||||
internal func _parseDevices(_ data: Data) -> [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)! {
|
||||
if let responseDict = responseObj as? NSDictionary {
|
||||
let device = WemoDevice(responseDict)
|
||||
@@ -186,7 +190,7 @@ internal class ToggleDeviceOperation : WemoOperation
|
||||
var device: WemoDevice
|
||||
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.state = state
|
||||
@@ -196,15 +200,13 @@ internal class ToggleDeviceOperation : WemoOperation
|
||||
override func main()
|
||||
{
|
||||
let semaphore = Semaphore(value: 0)
|
||||
let stateArg = (self.state == .On ? "on" : "off")
|
||||
let url = self.baseURL.URLByAppendingPathComponent("api/device/\(self.device.name)").URLByAppendingRequestParameters(["state" : stateArg])
|
||||
let request = NSMutableURLRequest(URL: url!)
|
||||
request.HTTPMethod = "POST"
|
||||
let stateArg = (self.state == .on ? "on" : "off")
|
||||
let url = self.baseURL.appendingPathComponent("api/device/\(self.device.name)").URLByAppendingRequestParameters(["state" : stateArg])
|
||||
var request = URLRequest(url: url!)
|
||||
request.httpMethod = "POST"
|
||||
|
||||
let task = self.session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
|
||||
if (error != nil) {
|
||||
self.error = NSError.xionError(.ConnectionError, underlying: error)
|
||||
}
|
||||
let task = self.session.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
|
||||
self.error = error
|
||||
semaphore.signal()
|
||||
}
|
||||
task.resume()
|
||||
|
||||
@@ -12,20 +12,20 @@ class WemoDevice: Hashable
|
||||
{
|
||||
enum State
|
||||
{
|
||||
case Off
|
||||
case On
|
||||
case off
|
||||
case on
|
||||
}
|
||||
|
||||
enum Type
|
||||
enum DeviceType
|
||||
{
|
||||
case Switch
|
||||
case `switch`
|
||||
}
|
||||
|
||||
var name: String = ""
|
||||
var host: String = ""
|
||||
var model: String = ""
|
||||
var state: State = .Off
|
||||
var type: Type = .Switch
|
||||
var state: State = .off
|
||||
var type: DeviceType = .switch
|
||||
var serial: String = ""
|
||||
|
||||
init()
|
||||
@@ -46,13 +46,13 @@ class WemoDevice: Hashable
|
||||
}
|
||||
|
||||
if let state = dict["state"] as? NSNumber {
|
||||
switch (state.integerValue) {
|
||||
switch (state.intValue) {
|
||||
case 0:
|
||||
self.state = .Off
|
||||
self.state = .off
|
||||
case 1:
|
||||
self.state = .On
|
||||
self.state = .on
|
||||
default:
|
||||
self.state = .Off
|
||||
self.state = .off
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,22 +10,31 @@ import Foundation
|
||||
|
||||
enum XIONErrorCode: Int
|
||||
{
|
||||
case Unknown
|
||||
case ConnectionError
|
||||
case unknown
|
||||
case connectionError
|
||||
}
|
||||
|
||||
struct XIONError : Error
|
||||
{
|
||||
enum ErrorCode
|
||||
{
|
||||
case unknown
|
||||
case connectionError
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
userInfo = [
|
||||
NSUnderlyingErrorKey : underlying!
|
||||
@@ -35,7 +44,7 @@ extension NSError
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -7,22 +7,22 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
extension NSURL
|
||||
extension URL
|
||||
{
|
||||
var requestParameters: [String : String]?
|
||||
{
|
||||
get
|
||||
{
|
||||
let urlComponents = self.absoluteString.componentsSeparatedByString("/")
|
||||
let urlComponents = self.absoluteString.components(separatedBy: "/")
|
||||
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()
|
||||
|
||||
for paramPair in parameterComponents {
|
||||
let kvPair = paramPair.componentsSeparatedByString("=")
|
||||
let kvPair = paramPair.components(separatedBy: "=")
|
||||
if (kvPair.count == 2 && kvPair[0].characters.count > 0) {
|
||||
let key = kvPair[0].stringByRemovingPercentEncoding!
|
||||
let value = kvPair[1].stringByRemovingPercentEncoding!
|
||||
let key = kvPair[0].removingPercentEncoding!
|
||||
let value = kvPair[1].removingPercentEncoding!
|
||||
dict[key] = value
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ extension NSURL
|
||||
}
|
||||
}
|
||||
|
||||
func URLByAppendingRequestParameters(params: [String : String]) -> NSURL?
|
||||
func URLByAppendingRequestParameters(_ params: [String : String]) -> URL?
|
||||
{
|
||||
var paramsString = ""
|
||||
|
||||
@@ -43,14 +43,14 @@ extension NSURL
|
||||
delim = "&"
|
||||
}
|
||||
|
||||
let keyParam = key.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
|
||||
let valueParam = value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
|
||||
let keyParam = key.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
|
||||
let valueParam = value.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
|
||||
paramsString += "\(delim)\(keyParam!)=\(valueParam!)"
|
||||
}
|
||||
|
||||
var absoluteString = self.absoluteString
|
||||
absoluteString += paramsString
|
||||
|
||||
return NSURL(string: absoluteString)
|
||||
return URL(string: absoluteString)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import Foundation
|
||||
|
||||
class Semaphore
|
||||
{
|
||||
private var _semaphore: dispatch_semaphore_t
|
||||
fileprivate var _semaphore: DispatchSemaphore
|
||||
|
||||
init(value: Int)
|
||||
{
|
||||
_semaphore = dispatch_semaphore_create(value)
|
||||
_semaphore = DispatchSemaphore(value: value)
|
||||
}
|
||||
|
||||
func wait()
|
||||
@@ -22,18 +22,21 @@ class Semaphore
|
||||
self.wait(nil)
|
||||
}
|
||||
|
||||
func wait(untilDate: NSDate?)
|
||||
func wait(_ untilDate: Date?)
|
||||
{
|
||||
var time: dispatch_time_t = DISPATCH_TIME_FOREVER
|
||||
if (untilDate != nil) {
|
||||
time = UInt64(untilDate!.timeIntervalSinceNow) * NSEC_PER_SEC
|
||||
var time: DispatchTime = DispatchTime.distantFuture
|
||||
if let untilDate = untilDate {
|
||||
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()
|
||||
{
|
||||
dispatch_semaphore_signal(_semaphore)
|
||||
_semaphore.signal()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
class StandardErrorOutputStream: OutputStreamType
|
||||
class StandardErrorOutputStream: TextOutputStream
|
||||
{
|
||||
func write(string: String)
|
||||
func write(_ string: String)
|
||||
{
|
||||
let stderr = NSFileHandle.fileHandleWithStandardError()
|
||||
stderr.writeData(string.dataUsingEncoding(NSUTF8StringEncoding)!)
|
||||
let stderr = FileHandle.standardError
|
||||
stderr.write(string.data(using: String.Encoding.utf8)!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,25 +10,25 @@ import UIKit
|
||||
|
||||
class ConnectionStatusView: UIView
|
||||
{
|
||||
private var _connectivityStatus: ConnectionStatus = .Disconnected
|
||||
private var _japaneseLabel: UILabel = UILabel()
|
||||
private var _englishLabel: UILabel = UILabel()
|
||||
fileprivate var _connectivityStatus: ConnectionStatus = .disconnected
|
||||
fileprivate var _japaneseLabel: 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)
|
||||
{
|
||||
super.init(frame: frame)
|
||||
|
||||
_japaneseLabel.font = UIFont(name: "Orbitron-Medium", size: 24.0)
|
||||
_japaneseLabel.textColor = UIColor.whiteColor()
|
||||
_japaneseLabel.textColor = UIColor.white
|
||||
self.addSubview(_japaneseLabel)
|
||||
|
||||
_englishLabel.font = UIFont(name: "Orbitron-Medium", size: 16.0)
|
||||
_englishLabel.textColor = UIColor.whiteColor()
|
||||
_englishLabel.textColor = UIColor.white
|
||||
self.addSubview(_englishLabel)
|
||||
|
||||
self.connectivityStatus = .Disconnected
|
||||
self.connectivityStatus = .disconnected
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder)
|
||||
@@ -38,7 +38,7 @@ class ConnectionStatusView: UIView
|
||||
|
||||
// MARK: Overrides
|
||||
|
||||
override func sizeThatFits(size: CGSize) -> CGSize
|
||||
override func sizeThatFits(_ size: CGSize) -> CGSize
|
||||
{
|
||||
let labelsVMargin = ConnectionStatusView.labelsVMargin
|
||||
let jpLabelSize = _japaneseLabel.sizeThatFits(size)
|
||||
@@ -67,7 +67,7 @@ class ConnectionStatusView: UIView
|
||||
|
||||
_englishLabel.frame = CGRect(
|
||||
x: rint(bounds.size.width / 2.0 - enLabelSize.width / 2.0),
|
||||
y: CGRectGetMaxY(_japaneseLabel.frame) + labelsVMargin,
|
||||
y: _japaneseLabel.frame.maxY + labelsVMargin,
|
||||
width: enLabelSize.width,
|
||||
height: enLabelSize.height
|
||||
)
|
||||
@@ -87,30 +87,30 @@ class ConnectionStatusView: UIView
|
||||
_connectivityStatus = newStatus
|
||||
|
||||
switch (_connectivityStatus) {
|
||||
case .Disconnected:
|
||||
case .disconnected:
|
||||
_japaneseLabel.text = "非直結"
|
||||
_japaneseLabel.textColor = UIColor.redColor()
|
||||
_japaneseLabel.textColor = UIColor.red
|
||||
|
||||
_englishLabel.text = "offline"
|
||||
_englishLabel.textColor = UIColor.redColor()
|
||||
case .Connecting:
|
||||
_englishLabel.textColor = UIColor.red
|
||||
case .connecting:
|
||||
_japaneseLabel.text = "接続中"
|
||||
_japaneseLabel.textColor = UIColor.yellowColor()
|
||||
_japaneseLabel.textColor = UIColor.yellow
|
||||
|
||||
_englishLabel.text = "connecting..."
|
||||
_englishLabel.textColor = UIColor.yellowColor()
|
||||
case .Connected:
|
||||
_englishLabel.textColor = UIColor.yellow
|
||||
case .connected:
|
||||
_japaneseLabel.text = "直結"
|
||||
_japaneseLabel.textColor = UIColor.greenColor()
|
||||
_japaneseLabel.textColor = UIColor.green
|
||||
|
||||
_englishLabel.text = "online"
|
||||
_englishLabel.textColor = UIColor.greenColor()
|
||||
case .Error:
|
||||
_englishLabel.textColor = UIColor.green
|
||||
case .error:
|
||||
_japaneseLabel.text = "過失"
|
||||
_japaneseLabel.textColor = UIColor.redColor()
|
||||
_japaneseLabel.textColor = UIColor.red
|
||||
|
||||
_englishLabel.text = "error"
|
||||
_englishLabel.textColor = UIColor.redColor()
|
||||
_englishLabel.textColor = UIColor.red
|
||||
}
|
||||
|
||||
self.setNeedsLayout()
|
||||
|
||||
@@ -15,24 +15,24 @@ class HeaderView: UIView
|
||||
var xionLogoView: XIONLogoView = XIONLogoView()
|
||||
var connectionStatusView: ConnectionStatusView = ConnectionStatusView()
|
||||
|
||||
private var _xionTitleLabel: UILabel = UILabel()
|
||||
private var _xionJapaneseLabel: UILabel = UILabel()
|
||||
fileprivate var _xionTitleLabel: UILabel = UILabel()
|
||||
fileprivate var _xionJapaneseLabel: UILabel = UILabel()
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
super.init(frame: frame)
|
||||
|
||||
self.backgroundColor = UIColor.blackColor()
|
||||
self.backgroundColor = UIColor.black
|
||||
self.addSubview(self.xionLogoView)
|
||||
|
||||
_xionTitleLabel.font = UIFont(name: "Orbitron-Medium", size: 16.0)
|
||||
_xionTitleLabel.text = "XION arcade system control panel"
|
||||
_xionTitleLabel.textColor = UIColor.whiteColor()
|
||||
_xionTitleLabel.textColor = UIColor.white
|
||||
self.addSubview(_xionTitleLabel)
|
||||
|
||||
_xionJapaneseLabel.font = UIFont(name: "Orbitron-Medium", size: 12.0)
|
||||
_xionJapaneseLabel.text = "ザイーオンゲームセンターのシステム制御プログラム"
|
||||
_xionJapaneseLabel.textColor = UIColor.whiteColor()
|
||||
_xionJapaneseLabel.textColor = UIColor.white
|
||||
self.addSubview(_xionJapaneseLabel)
|
||||
|
||||
self.addSubview(self.connectionStatusView)
|
||||
@@ -59,12 +59,12 @@ class HeaderView: UIView
|
||||
)
|
||||
self.xionLogoView.frame = logoFrame
|
||||
|
||||
if (self.traitCollection.horizontalSizeClass == .Compact) {
|
||||
_xionTitleLabel.hidden = true
|
||||
_xionJapaneseLabel.hidden = true
|
||||
if (self.traitCollection.horizontalSizeClass == .compact) {
|
||||
_xionTitleLabel.isHidden = true
|
||||
_xionJapaneseLabel.isHidden = true
|
||||
} else {
|
||||
_xionTitleLabel.hidden = false
|
||||
_xionJapaneseLabel.hidden = false
|
||||
_xionTitleLabel.isHidden = false
|
||||
_xionJapaneseLabel.isHidden = false
|
||||
|
||||
let titleJPVerticalMargin: CGFloat = 5.0
|
||||
let titleLabelSize = _xionTitleLabel.sizeThatFits(bounds.size)
|
||||
@@ -72,7 +72,7 @@ class HeaderView: UIView
|
||||
let totalLabelsHeight = titleLabelSize.height + titleJPVerticalMargin + jpLabelSize.height
|
||||
|
||||
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),
|
||||
width: titleLabelSize.width,
|
||||
height: titleLabelSize.height
|
||||
@@ -81,7 +81,7 @@ class HeaderView: UIView
|
||||
|
||||
let jpTitleFrame = CGRect(
|
||||
x: titleFrame.origin.x,
|
||||
y: CGRectGetMaxY(titleFrame) + titleJPVerticalMargin,
|
||||
y: titleFrame.maxY + titleJPVerticalMargin,
|
||||
width: jpLabelSize.width,
|
||||
height: jpLabelSize.height + 2.0
|
||||
)
|
||||
|
||||
@@ -10,22 +10,22 @@ import UIKit
|
||||
|
||||
class SwitchIndicatorView: UIView
|
||||
{
|
||||
private var _status: Bool = false
|
||||
private var _foregroundColor: UIColor = UIColor.whiteColor()
|
||||
private var _outerCircleLayer: CAShapeLayer = CAShapeLayer()
|
||||
private var _offSymbolLayer: CAShapeLayer = CAShapeLayer()
|
||||
private var _onSymbolLayer: CAShapeLayer = CAShapeLayer()
|
||||
fileprivate var _status: Bool = false
|
||||
fileprivate var _foregroundColor: UIColor = UIColor.white
|
||||
fileprivate var _outerCircleLayer: CAShapeLayer = CAShapeLayer()
|
||||
fileprivate var _offSymbolLayer: 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)
|
||||
{
|
||||
super.init(frame: frame)
|
||||
|
||||
_outerCircleLayer.fillColor = UIColor.clearColor().CGColor
|
||||
_outerCircleLayer.fillColor = UIColor.clear.cgColor
|
||||
_outerCircleLayer.lineWidth = SwitchIndicatorView.lineWidth
|
||||
|
||||
_offSymbolLayer.fillColor = UIColor.clearColor().CGColor
|
||||
_offSymbolLayer.fillColor = UIColor.clear.cgColor
|
||||
_offSymbolLayer.lineWidth = SwitchIndicatorView.lineWidth
|
||||
|
||||
self.layer.addSublayer(_outerCircleLayer)
|
||||
@@ -33,7 +33,7 @@ class SwitchIndicatorView: UIView
|
||||
self.layer.addSublayer(_onSymbolLayer)
|
||||
|
||||
self.status = false
|
||||
self.foregroundColor = UIColor.whiteColor()
|
||||
self.foregroundColor = UIColor.white
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder)
|
||||
@@ -52,7 +52,7 @@ class SwitchIndicatorView: UIView
|
||||
_offSymbolLayer.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 innerBounds = CGRect(
|
||||
@@ -61,7 +61,7 @@ class SwitchIndicatorView: UIView
|
||||
width: innerSize.width,
|
||||
height: innerSize.height
|
||||
)
|
||||
_offSymbolLayer.path = CGPathCreateWithEllipseInRect(innerBounds, nil)
|
||||
_offSymbolLayer.path = CGPath(ellipseIn: innerBounds, transform: nil)
|
||||
|
||||
let onSymbolSize = CGSize(width: lineWidth, height: innerSize.height)
|
||||
let onSymbolRect = CGRect(
|
||||
@@ -70,7 +70,7 @@ class SwitchIndicatorView: UIView
|
||||
width: onSymbolSize.width,
|
||||
height: onSymbolSize.height
|
||||
)
|
||||
_onSymbolLayer.path = CGPathCreateWithRect(onSymbolRect, nil)
|
||||
_onSymbolLayer.path = CGPath(rect: onSymbolRect, transform: nil)
|
||||
}
|
||||
|
||||
// MARK: API
|
||||
@@ -85,8 +85,8 @@ class SwitchIndicatorView: UIView
|
||||
set(status)
|
||||
{
|
||||
_status = status
|
||||
_offSymbolLayer.hidden = _status
|
||||
_onSymbolLayer.hidden = !_status
|
||||
_offSymbolLayer.isHidden = _status
|
||||
_onSymbolLayer.isHidden = !_status
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,9 +100,9 @@ class SwitchIndicatorView: UIView
|
||||
set(color)
|
||||
{
|
||||
_foregroundColor = color
|
||||
_outerCircleLayer.strokeColor = _foregroundColor.CGColor
|
||||
_offSymbolLayer.strokeColor = _foregroundColor.CGColor
|
||||
_onSymbolLayer.fillColor = _foregroundColor.CGColor
|
||||
_outerCircleLayer.strokeColor = _foregroundColor.cgColor
|
||||
_offSymbolLayer.strokeColor = _foregroundColor.cgColor
|
||||
_onSymbolLayer.fillColor = _foregroundColor.cgColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
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 private var enabledBackgroundColor = UIColor(red: 0.0, green: 0.8, blue: 0.0, alpha: 1.0)
|
||||
static fileprivate var disabledBackgroundColor = UIColor(white: 0.2, alpha: 1.0)
|
||||
static fileprivate var enabledBackgroundColor = UIColor(red: 0.0, green: 0.8, blue: 0.0, alpha: 1.0)
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
@@ -21,7 +21,7 @@ public class WemoCellView: UICollectionViewCell
|
||||
|
||||
self.contentView.backgroundColor = WemoCellView.disabledBackgroundColor
|
||||
|
||||
_selectionOverlayView.backgroundColor = UIColor.clearColor()
|
||||
_selectionOverlayView.backgroundColor = UIColor.clear
|
||||
self.contentView.addSubview(_selectionOverlayView)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class WemoCellView: UICollectionViewCell
|
||||
|
||||
// MARK: Overrides
|
||||
|
||||
override public func layoutSubviews()
|
||||
override open func layoutSubviews()
|
||||
{
|
||||
super.layoutSubviews()
|
||||
|
||||
@@ -40,29 +40,30 @@ public class WemoCellView: UICollectionViewCell
|
||||
_selectionOverlayView.frame = bounds
|
||||
}
|
||||
|
||||
override public var highlighted: Bool {
|
||||
override open var isHighlighted: Bool {
|
||||
didSet
|
||||
{
|
||||
if (self.highlighted) {
|
||||
if (self.isHighlighted) {
|
||||
_selectionOverlayView.backgroundColor = UIColor(white: 0.8, alpha: 1.0)
|
||||
} else {
|
||||
let animOptions = UIViewAnimationOptions([.AllowUserInteraction])
|
||||
UIView.animateWithDuration(1.0, delay: 0.0, options: animOptions, animations: {
|
||||
self._selectionOverlayView.backgroundColor = UIColor.clearColor()
|
||||
let animOptions = UIViewAnimationOptions([.allowUserInteraction])
|
||||
UIView.animate(withDuration: 1.0, delay: 0.0, options: animOptions, animations: {
|
||||
self._selectionOverlayView.backgroundColor = UIColor.clear
|
||||
}, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class WemoDeviceCellView: WemoCellView {
|
||||
private var _ordinal: Int = 0
|
||||
private var _nameLabel: UILabel = UILabel()
|
||||
private var _ordinalLabel: UILabel = UILabel()
|
||||
private var _indicator: SwitchIndicatorView = SwitchIndicatorView()
|
||||
open class WemoDeviceCellView: WemoCellView
|
||||
{
|
||||
fileprivate var _ordinal: Int = 0
|
||||
fileprivate var _nameLabel: UILabel = UILabel()
|
||||
fileprivate var _ordinalLabel: UILabel = UILabel()
|
||||
fileprivate var _indicator: SwitchIndicatorView = SwitchIndicatorView()
|
||||
|
||||
static private var disabledAnnotationsColor = UIColor.darkGrayColor()
|
||||
static private var enabledAnnotationsColor = UIColor.blackColor()
|
||||
static fileprivate var disabledAnnotationsColor = UIColor.darkGray
|
||||
static fileprivate var enabledAnnotationsColor = UIColor.black
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
@@ -72,7 +73,7 @@ public class WemoDeviceCellView: WemoCellView {
|
||||
_nameLabel.numberOfLines = 3
|
||||
_nameLabel.allowsDefaultTighteningForTruncation = true
|
||||
_nameLabel.adjustsFontSizeToFitWidth = true
|
||||
_nameLabel.textColor = UIColor.whiteColor()
|
||||
_nameLabel.textColor = UIColor.white
|
||||
self.contentView.addSubview(_nameLabel)
|
||||
|
||||
_ordinalLabel.font = UIFont(name: "Orbitron-Medium", size: 21.0)
|
||||
@@ -91,7 +92,7 @@ public class WemoDeviceCellView: WemoCellView {
|
||||
|
||||
// MARK: Overrides
|
||||
|
||||
override public func layoutSubviews()
|
||||
override open func layoutSubviews()
|
||||
{
|
||||
super.layoutSubviews()
|
||||
|
||||
@@ -128,7 +129,7 @@ public class WemoDeviceCellView: WemoCellView {
|
||||
{
|
||||
didSet
|
||||
{
|
||||
_nameLabel.text = self.deviceName.uppercaseString
|
||||
_nameLabel.text = self.deviceName.uppercased()
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
@@ -167,7 +168,8 @@ public class WemoDeviceCellView: WemoCellView {
|
||||
}
|
||||
}
|
||||
|
||||
public class WemoActionCellView: WemoCellView {
|
||||
open class WemoActionCellView: WemoCellView
|
||||
{
|
||||
var textLabel: UILabel = UILabel()
|
||||
|
||||
override init(frame: CGRect)
|
||||
@@ -175,8 +177,8 @@ public class WemoActionCellView: WemoCellView {
|
||||
super.init(frame: frame)
|
||||
|
||||
self.textLabel.font = UIFont(name: "Orbitron-Medium", size: 21.0)
|
||||
self.textLabel.textColor = UIColor.whiteColor()
|
||||
self.textLabel.textAlignment = .Center
|
||||
self.textLabel.textColor = UIColor.white
|
||||
self.textLabel.textAlignment = .center
|
||||
self.addSubview(self.textLabel)
|
||||
}
|
||||
|
||||
@@ -185,7 +187,7 @@ public class WemoActionCellView: WemoCellView {
|
||||
fatalError("unsupported")
|
||||
}
|
||||
|
||||
override public func layoutSubviews()
|
||||
override open func layoutSubviews()
|
||||
{
|
||||
super.layoutSubviews()
|
||||
self.textLabel.frame = self.bounds
|
||||
@@ -196,9 +198,9 @@ public class WemoActionCellView: WemoCellView {
|
||||
didSet
|
||||
{
|
||||
if (enabled) {
|
||||
self.textLabel.textColor = UIColor.whiteColor()
|
||||
self.textLabel.textColor = UIColor.white
|
||||
} else {
|
||||
self.textLabel.textColor = UIColor.darkGrayColor()
|
||||
self.textLabel.textColor = UIColor.darkGray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,24 +10,24 @@ import UIKit
|
||||
|
||||
class XIONLogoView: UIView
|
||||
{
|
||||
private var _xionLogoImageView: UIImageView = UIImageView()
|
||||
private var _logoInnerRingImageView: UIImageView = UIImageView()
|
||||
private var _logoOuterRingImageView: UIImageView = UIImageView()
|
||||
fileprivate var _xionLogoImageView: UIImageView = UIImageView()
|
||||
fileprivate var _logoInnerRingImageView: UIImageView = UIImageView()
|
||||
fileprivate var _logoOuterRingImageView: UIImageView = UIImageView()
|
||||
|
||||
override init(frame: CGRect)
|
||||
{
|
||||
super.init(frame: frame)
|
||||
|
||||
self.backgroundColor = UIColor.blackColor()
|
||||
self.backgroundColor = UIColor.black
|
||||
|
||||
_xionLogoImageView.image = UIImage(named: "XIONLogoWithRing")
|
||||
_xionLogoImageView.contentMode = .ScaleAspectFit
|
||||
_xionLogoImageView.contentMode = .scaleAspectFit
|
||||
|
||||
_logoInnerRingImageView.image = UIImage(named: "XIONLogoInnerRing")
|
||||
_logoInnerRingImageView.contentMode = .ScaleAspectFit
|
||||
_logoInnerRingImageView.contentMode = .scaleAspectFit
|
||||
|
||||
_logoOuterRingImageView.image = UIImage(named: "XIONLogoOuterRing")
|
||||
_logoOuterRingImageView.contentMode = .ScaleAspectFit
|
||||
_logoOuterRingImageView.contentMode = .scaleAspectFit
|
||||
|
||||
self.addSubview(_logoOuterRingImageView)
|
||||
self.addSubview(_logoInnerRingImageView)
|
||||
@@ -55,7 +55,7 @@ class XIONLogoView: UIView
|
||||
{
|
||||
self.stopAnimating()
|
||||
|
||||
let duration: NSTimeInterval = 20.0
|
||||
let duration: TimeInterval = 20.0
|
||||
|
||||
let clockwiseAnim = CABasicAnimation(keyPath: "transform.rotation")
|
||||
clockwiseAnim.fromValue = 0.0
|
||||
@@ -69,8 +69,8 @@ class XIONLogoView: UIView
|
||||
counterClockwiseAnim.duration = duration
|
||||
counterClockwiseAnim.repeatCount = Float.infinity
|
||||
|
||||
_logoInnerRingImageView.layer.addAnimation(clockwiseAnim, forKey: "LogoClockwiseAnimation")
|
||||
_logoOuterRingImageView.layer.addAnimation(counterClockwiseAnim, forKey: "LogoCounterclockwiseAnimation")
|
||||
_logoInnerRingImageView.layer.add(clockwiseAnim, forKey: "LogoClockwiseAnimation")
|
||||
_logoOuterRingImageView.layer.add(counterClockwiseAnim, forKey: "LogoCounterclockwiseAnimation")
|
||||
}
|
||||
|
||||
func stopAnimating()
|
||||
|
||||
Reference in New Issue
Block a user