diff --git a/XIONControlPanel.xcodeproj/project.pbxproj b/XIONControlPanel.xcodeproj/project.pbxproj index a8f8d64..41a92c9 100644 --- a/XIONControlPanel.xcodeproj/project.pbxproj +++ b/XIONControlPanel.xcodeproj/project.pbxproj @@ -109,8 +109,8 @@ 0C20E2B61C33514100BA789B /* Controllers */ = { isa = PBXGroup; children = ( - 0C41EF491C34B51500AF847F /* SwitchesViewController.swift */, 0C20E2BA1C33529700BA789B /* MainViewController.swift */, + 0C41EF491C34B51500AF847F /* SwitchesViewController.swift */, 0C20E2BC1C33534F00BA789B /* VisualizationViewController.swift */, 0CAA32781C361A2400B353CF /* WemoServer.swift */, ); @@ -427,7 +427,7 @@ PROVISIONING_PROFILE = ""; SWIFT_OBJC_BRIDGING_HEADER = "XIONControlPanel/SupportingFiles/XIONControlPanel-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = 2; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -444,7 +444,7 @@ PRODUCT_NAME = XION; PROVISIONING_PROFILE = ""; SWIFT_OBJC_BRIDGING_HEADER = "XIONControlPanel/SupportingFiles/XIONControlPanel-Bridging-Header.h"; - TARGETED_DEVICE_FAMILY = 2; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; diff --git a/XIONControlPanel/Application/AppDelegate.swift b/XIONControlPanel/Application/AppDelegate.swift index 9fbe100..b53ee20 100644 --- a/XIONControlPanel/Application/AppDelegate.swift +++ b/XIONControlPanel/Application/AppDelegate.swift @@ -9,7 +9,8 @@ import UIKit @UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { +class AppDelegate: UIResponder, UIApplicationDelegate +{ var window: UIWindow? var mainViewController: MainViewController = MainViewController() @@ -36,6 +37,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask { - return UIInterfaceOrientationMask.Landscape + var mask: UIInterfaceOrientationMask = .Portrait + + if (UIDevice.currentDevice().userInterfaceIdiom == .Phone) { + mask = UIInterfaceOrientationMask.Portrait + } else { + mask = UIInterfaceOrientationMask.All + } + + return mask } } diff --git a/XIONControlPanel/Controllers/MainViewController.swift b/XIONControlPanel/Controllers/MainViewController.swift index a46d529..7864b09 100644 --- a/XIONControlPanel/Controllers/MainViewController.swift +++ b/XIONControlPanel/Controllers/MainViewController.swift @@ -8,7 +8,8 @@ import UIKit -class MainViewController: UIViewController, SwitchesViewControllerDelegate { +class MainViewController: UIViewController, SwitchesViewControllerDelegate +{ private var _server: WemoServer private var _visualizationController: VisualizationViewController = VisualizationViewController() private var _switchesController: SwitchesViewController = SwitchesViewController() @@ -53,11 +54,13 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate { super.viewDidLayoutSubviews() let bounds = self.view.bounds + let horizontalSizeClass = self.traitCollection.horizontalSizeClass + let headerBounds = CGRect( x: 0.0, y: 0.0, width: bounds.size.width, - height: rint(bounds.size.height / 10.0) + height: rint(bounds.size.height / 8.0) ) let bodyBounds = CGRect( x: 0.0, @@ -76,10 +79,20 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate { ) _visualizationController.view.frame = visualizationFrame + var switchesOriginX: CGFloat = 0.0 + var switchesWidth: CGFloat = 0.0 + if (horizontalSizeClass == .Regular) { + switchesOriginX = CGRectGetMaxX(visualizationFrame) + switchesWidth = bodyBounds.size.width - visualizationFrame.size.width + } else { + switchesOriginX = 0.0 + switchesWidth = bodyBounds.size.width + } + let switchesControllerFrame = CGRect( - x: CGRectGetMaxX(visualizationFrame), + x: switchesOriginX, y: bodyBounds.origin.y, - width: bodyBounds.size.width - visualizationFrame.size.width, + width: switchesWidth, height: bodyBounds.size.height ) _switchesController.view.frame = switchesControllerFrame @@ -104,6 +117,12 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate { } } + override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) + { + super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) + _updateSizeClassPresentation() + } + override func prefersStatusBarHidden() -> Bool { return true @@ -133,6 +152,16 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate { // MARK: Internal + internal func _updateSizeClassPresentation() + { + let horizontalSizeClass = self.traitCollection.horizontalSizeClass + if (horizontalSizeClass == .Regular) { + _visualizationController.view.hidden = false + } else { + _visualizationController.view.hidden = true + } + } + internal func _updateVisualization(animated: Bool) { var activatedDevicesCount = 0 @@ -152,6 +181,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate { { dispatch_async(dispatch_get_main_queue()) { () -> Void in self._headerView.connectionStatusView.connectivityStatus = status + self._headerView.setNeedsLayout() self._visualizationController.connectionStatus = status } } diff --git a/XIONControlPanel/Controllers/SwitchesViewController.swift b/XIONControlPanel/Controllers/SwitchesViewController.swift index d97e12a..af43596 100644 --- a/XIONControlPanel/Controllers/SwitchesViewController.swift +++ b/XIONControlPanel/Controllers/SwitchesViewController.swift @@ -10,11 +10,13 @@ import Darwin import Foundation import UIKit -protocol SwitchesViewControllerDelegate: class { +protocol SwitchesViewControllerDelegate: class +{ func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice]) } -extension SwitchesViewControllerDelegate { +extension SwitchesViewControllerDelegate +{ func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice]) {} } @@ -30,9 +32,9 @@ class SwitchesViewController: UIViewController, static private let collectionViewDeviceSwitchCellReuseIdentifier = "DeviceSwitchReuseID" static private let collectionViewActionCellReuseIdentifier = "ActionCellReuseID" static private let collectionViewCellsSpacing: CGFloat = 5.0 - static private let collectionViewCellsPerRow = 3 - private enum ActionCell: Int { + private enum ActionCell: Int + { case AllOn case AllOff @@ -181,9 +183,20 @@ class SwitchesViewController: UIViewController, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { let spacing = SwitchesViewController.collectionViewCellsSpacing - let cellsPerRow = CGFloat(SwitchesViewController.collectionViewCellsPerRow) - let dimensions = floor((collectionView.bounds.size.width / cellsPerRow) - ((spacing * (cellsPerRow - 1.0)) / cellsPerRow)) + let bounds = collectionView.bounds + var cellsPerRow: CGFloat = 0.0 + switch (self.traitCollection.horizontalSizeClass) { + case .Regular, .Compact where (bounds.size.width >= 400.0): + cellsPerRow = 3.0 + break + case .Compact: + cellsPerRow = 2.0 + default: + cellsPerRow = 2.0 + } + + let dimensions = floor((collectionView.bounds.size.width / cellsPerRow) - ((spacing * (cellsPerRow - 1.0)) / cellsPerRow)) if (indexPath.item < ActionCell.count) { return CGSize(width: collectionView.bounds.size.width, height: rint(dimensions / 2.0)) } else { diff --git a/XIONControlPanel/Controllers/VisualizationViewController.swift b/XIONControlPanel/Controllers/VisualizationViewController.swift index a9a1c21..b16dfcd 100644 --- a/XIONControlPanel/Controllers/VisualizationViewController.swift +++ b/XIONControlPanel/Controllers/VisualizationViewController.swift @@ -14,7 +14,8 @@ import UIKit let π = CGFloat(M_PI) -class VisualizationViewController: UIViewController { +class VisualizationViewController: UIViewController +{ private var _scene: SCNScene = SCNScene() private var _sceneView: SCNView? private var _cameraNode: SCNNode = SCNNode() diff --git a/XIONControlPanel/Controllers/WemoServer.swift b/XIONControlPanel/Controllers/WemoServer.swift index edba070..0bdad5c 100644 --- a/XIONControlPanel/Controllers/WemoServer.swift +++ b/XIONControlPanel/Controllers/WemoServer.swift @@ -8,14 +8,16 @@ import Foundation -enum ConnectionStatus { +enum ConnectionStatus +{ case Disconnected case Connecting case Connected case Error } -class WemoServer { +class WemoServer +{ private(set) var baseURL: NSURL private(set) var connected: Bool = false @@ -108,7 +110,8 @@ class WemoServer { } } -internal class WemoOperation : NSOperation { +internal class WemoOperation : NSOperation +{ var baseURL: NSURL var session: NSURLSession @@ -121,7 +124,8 @@ internal class WemoOperation : NSOperation { } } -internal class ConnectOperation : WemoOperation { +internal class ConnectOperation : WemoOperation +{ override func main() { let semaphore = Semaphore(value: 0) @@ -140,7 +144,8 @@ internal class ConnectOperation : WemoOperation { } } -internal class FetchDevicesOperation : WemoOperation { +internal class FetchDevicesOperation : WemoOperation +{ internal(set) var devices: [WemoDevice] = [] override func main() @@ -176,7 +181,8 @@ internal class FetchDevicesOperation : WemoOperation { } } -internal class ToggleDeviceOperation : WemoOperation { +internal class ToggleDeviceOperation : WemoOperation +{ var device: WemoDevice var state: WemoDevice.State diff --git a/XIONControlPanel/Models/WemoDevice.swift b/XIONControlPanel/Models/WemoDevice.swift index 5eed0b4..584b9f3 100644 --- a/XIONControlPanel/Models/WemoDevice.swift +++ b/XIONControlPanel/Models/WemoDevice.swift @@ -8,13 +8,16 @@ import Foundation -class WemoDevice: Hashable { - enum State { +class WemoDevice: Hashable +{ + enum State + { case Off case On } - enum Type { + enum Type + { case Switch } diff --git a/XIONControlPanel/SupportingFiles/Info.plist b/XIONControlPanel/SupportingFiles/Info.plist index 3cf4046..6ce6140 100644 --- a/XIONControlPanel/SupportingFiles/Info.plist +++ b/XIONControlPanel/SupportingFiles/Info.plist @@ -45,6 +45,8 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown UISupportedInterfaceOrientations~ipad diff --git a/XIONControlPanel/Utilities/NSErrorAdditions.swift b/XIONControlPanel/Utilities/NSErrorAdditions.swift index dc06879..6c155c8 100644 --- a/XIONControlPanel/Utilities/NSErrorAdditions.swift +++ b/XIONControlPanel/Utilities/NSErrorAdditions.swift @@ -8,12 +8,14 @@ import Foundation -enum XIONErrorCode: Int { +enum XIONErrorCode: Int +{ case Unknown case ConnectionError } -extension NSError { +extension NSError +{ private static let XIONErrorDomain = "com.xionsf.controlpanel" class func xionError(code: XIONErrorCode) -> NSError diff --git a/XIONControlPanel/Utilities/NSURLAdditions.swift b/XIONControlPanel/Utilities/NSURLAdditions.swift index 09cffe7..48d903b 100644 --- a/XIONControlPanel/Utilities/NSURLAdditions.swift +++ b/XIONControlPanel/Utilities/NSURLAdditions.swift @@ -7,8 +7,10 @@ import Foundation -extension NSURL { - var requestParameters: [String : String]? { +extension NSURL +{ + var requestParameters: [String : String]? + { get { let urlComponents = self.absoluteString.componentsSeparatedByString("/") diff --git a/XIONControlPanel/Utilities/Semaphore.swift b/XIONControlPanel/Utilities/Semaphore.swift index 6f8be57..578c626 100644 --- a/XIONControlPanel/Utilities/Semaphore.swift +++ b/XIONControlPanel/Utilities/Semaphore.swift @@ -8,7 +8,8 @@ import Foundation -class Semaphore { +class Semaphore +{ private var _semaphore: dispatch_semaphore_t init(value: Int) diff --git a/XIONControlPanel/Utilities/StandardError.swift b/XIONControlPanel/Utilities/StandardError.swift index 261741b..7a6f735 100644 --- a/XIONControlPanel/Utilities/StandardError.swift +++ b/XIONControlPanel/Utilities/StandardError.swift @@ -8,8 +8,10 @@ import Foundation -class StandardErrorOutputStream: OutputStreamType { - func write(string: String) { +class StandardErrorOutputStream: OutputStreamType +{ + func write(string: String) + { let stderr = NSFileHandle.fileHandleWithStandardError() stderr.writeData(string.dataUsingEncoding(NSUTF8StringEncoding)!) } diff --git a/XIONControlPanel/Views/ConnectionStatusView.swift b/XIONControlPanel/Views/ConnectionStatusView.swift index 16998d9..a2e0514 100644 --- a/XIONControlPanel/Views/ConnectionStatusView.swift +++ b/XIONControlPanel/Views/ConnectionStatusView.swift @@ -8,7 +8,8 @@ import UIKit -class ConnectionStatusView: UIView { +class ConnectionStatusView: UIView +{ private var _connectivityStatus: ConnectionStatus = .Disconnected private var _japaneseLabel: UILabel = UILabel() private var _englishLabel: UILabel = UILabel() diff --git a/XIONControlPanel/Views/HeaderView.swift b/XIONControlPanel/Views/HeaderView.swift index 0efe50d..72faa11 100644 --- a/XIONControlPanel/Views/HeaderView.swift +++ b/XIONControlPanel/Views/HeaderView.swift @@ -10,7 +10,8 @@ import Darwin import Foundation import UIKit -class HeaderView: UIView { +class HeaderView: UIView +{ var xionLogoView: XIONLogoView = XIONLogoView() var connectionStatusView: ConnectionStatusView = ConnectionStatusView() @@ -58,31 +59,39 @@ class HeaderView: UIView { ) self.xionLogoView.frame = logoFrame - let titleJPVerticalMargin: CGFloat = 5.0 - let titleLabelSize = _xionTitleLabel.sizeThatFits(bounds.size) - let jpLabelSize = _xionJapaneseLabel.sizeThatFits(bounds.size) - let totalLabelsHeight = titleLabelSize.height + titleJPVerticalMargin + jpLabelSize.height + if (self.traitCollection.horizontalSizeClass == .Compact) { + _xionTitleLabel.hidden = true + _xionJapaneseLabel.hidden = true + } else { + _xionTitleLabel.hidden = false + _xionJapaneseLabel.hidden = false - let titleFrame = CGRect( - x: CGRectGetMaxX(logoFrame) + hpadding * 2.0, - y: rint(bounds.size.height / 2.0 - totalLabelsHeight / 2.0), - width: titleLabelSize.width, - height: titleLabelSize.height - ) - _xionTitleLabel.frame = titleFrame + let titleJPVerticalMargin: CGFloat = 5.0 + let titleLabelSize = _xionTitleLabel.sizeThatFits(bounds.size) + let jpLabelSize = _xionJapaneseLabel.sizeThatFits(bounds.size) + let totalLabelsHeight = titleLabelSize.height + titleJPVerticalMargin + jpLabelSize.height + + let titleFrame = CGRect( + x: CGRectGetMaxX(logoFrame) + hpadding * 2.0, + y: rint(bounds.size.height / 2.0 - totalLabelsHeight / 2.0), + width: titleLabelSize.width, + height: titleLabelSize.height + ) + _xionTitleLabel.frame = titleFrame + + let jpTitleFrame = CGRect( + x: titleFrame.origin.x, + y: CGRectGetMaxY(titleFrame) + titleJPVerticalMargin, + width: jpLabelSize.width, + height: jpLabelSize.height + 2.0 + ) + _xionJapaneseLabel.frame = jpTitleFrame + } - let jpTitleFrame = CGRect( - x: titleFrame.origin.x, - y: CGRectGetMaxY(titleFrame) + titleJPVerticalMargin, - width: jpLabelSize.width, - height: jpLabelSize.height + 2.0 - ) - _xionJapaneseLabel.frame = jpTitleFrame - - let connectionStatusDimensions = CGSize(width: rint((1.0 / 8.0) * bounds.size.width), height: bounds.size.height) + let connectionStatusDimensions = self.connectionStatusView.sizeThatFits(bounds.size) let connectionStatusFrame = CGRect( - x: bounds.size.width - connectionStatusDimensions.width, - y: 0.0, + x: bounds.size.width - connectionStatusDimensions.width - hpadding, + y: rint(bounds.size.height / 2.0 - connectionStatusDimensions.height / 2.0), width: connectionStatusDimensions.width, height: connectionStatusDimensions.height ) diff --git a/XIONControlPanel/Views/SwitchIndicatorView.swift b/XIONControlPanel/Views/SwitchIndicatorView.swift index 726562e..426c72c 100644 --- a/XIONControlPanel/Views/SwitchIndicatorView.swift +++ b/XIONControlPanel/Views/SwitchIndicatorView.swift @@ -8,7 +8,8 @@ import UIKit -class SwitchIndicatorView: UIView { +class SwitchIndicatorView: UIView +{ private var _status: Bool = false private var _foregroundColor: UIColor = UIColor.whiteColor() private var _outerCircleLayer: CAShapeLayer = CAShapeLayer() diff --git a/XIONControlPanel/Views/WemoCellView.swift b/XIONControlPanel/Views/WemoCellView.swift index a0cd377..537613e 100644 --- a/XIONControlPanel/Views/WemoCellView.swift +++ b/XIONControlPanel/Views/WemoCellView.swift @@ -8,7 +8,8 @@ import UIKit -public class WemoCellView: UICollectionViewCell { +public class WemoCellView: UICollectionViewCell +{ private var _selectionOverlayView: UIView = UIView() static private var disabledBackgroundColor = UIColor(white: 0.2, alpha: 1.0) diff --git a/XIONControlPanel/Views/XIONLogoView.swift b/XIONControlPanel/Views/XIONLogoView.swift index 7a5de99..6f9d108 100644 --- a/XIONControlPanel/Views/XIONLogoView.swift +++ b/XIONControlPanel/Views/XIONLogoView.swift @@ -8,7 +8,8 @@ import UIKit -class XIONLogoView: UIView { +class XIONLogoView: UIView +{ private var _xionLogoImageView: UIImageView = UIImageView() private var _logoInnerRingImageView: UIImageView = UIImageView() private var _logoOuterRingImageView: UIImageView = UIImageView()