OS X/ViewController.swift

/*
 Copyright (C) 2016 Apple Inc. All Rights Reserved.
 See LICENSE.txt for this sample’s licensing information
 
 Abstract:
 The app's view controller class.
 */
 
import SceneKit
 
class ViewController: NSViewController {
    
    @IBOutlet private weak var sceneView: SCNView!
    @IBOutlet private weak var popupButton: NSPopUpButton!
    @IBOutlet private var configButton: NSButton!
 
    private var controller: Controller!
    
    override func viewDidLoad() {
        super.viewDidLoad()
 
        controller = Controller(view: sceneView)
        controller.selectScene(at: 0)
        
        configurePopupButton()
    }
    
    override func viewWillAppear() {
        guard let window = view.window else { return }
        
        window.appearance = NSAppearance(named: NSAppearanceNameVibrantDark)
        
        let accessoryViewController = NSTitlebarAccessoryViewController()
        accessoryViewController.view = configButton
        accessoryViewController.layoutAttribute = .trailing
        window.addTitlebarAccessoryViewController(accessoryViewController)
    }
 
    // MARK: UI for Image Selection
    
    private func configurePopupButton() {
        for i in 0 ..< controller.sceneTitles.count {
            let item = NSMenuItem(title: controller.sceneTitles[i], action: #selector(sceneDidChange), keyEquivalent: "")
            item.tag = i
            popupButton.menu?.addItem(item)
        }
    }
    
    private dynamic func sceneDidChange(_ sender: AnyObject?) {
        let menuItem = sender as! NSMenuItem
        controller.selectScene(at: menuItem.tag)
    }
    
    // MARK: Split View Handle and Mouse Events
    
    private func updateHandlePosition(with event: NSEvent) {
        let location = sceneView.convert(event.locationInWindow, from: nil)
        let splitFraction = Float(location.x / view.bounds.size.width)
        controller.splitFraction = splitFraction
    }
    
    override func mouseDragged(with event: NSEvent) {
        updateHandlePosition(with: event)
    }
    
    override func mouseUp(with event: NSEvent) {
        updateHandlePosition(with: event)
    }
    
    override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
        if let destination = segue.destinationController as? ConfigViewController, segue.identifier == "ConfigPopover" {
            destination.visualizationType = controller.visualizationType
            destination.didChangeVisualizationTypeHandler = { [weak self] type in
                self?.controller.visualizationType = type
            }
        }
    }
}
 
class ConfigViewController : NSViewController {
    @IBOutlet private weak var gamutClampButton: NSButton!
    @IBOutlet private weak var wideGamutHighlightButton: NSButton!
 
    var didChangeVisualizationTypeHandler: (Controller.VisualizationType) -> (Void) = { _ in }
    var visualizationType: Controller.VisualizationType = .gamutClamp {
        didSet {
            updateSelectedRadioButton()
        }
    }
    override func viewDidLoad() {
        updateSelectedRadioButton()
    }
    
    private func updateSelectedRadioButton() {
        if isViewLoaded {
            gamutClampButton.state = visualizationType == .gamutClamp ? NSOnState : NSOffState
            wideGamutHighlightButton.state = visualizationType == .wideGamutHighlight ? NSOnState : NSOffState
        }
    }
    
    @IBAction private func pickVisualizationMode(_ sender: NSButton) {
        let visualizationType = Controller.VisualizationType(rawValue: sender.tag)!
        didChangeVisualizationTypeHandler(visualizationType)
    }
}