DocHubController.swift #12

  • //
  • main/
  • guest/
  • tjuricek/
  • DocHub/
  • DocHub/
  • DocHubController.swift
  • View
  • Commits
  • Open Download .zip Download (5 KB)
//
//  DocHubControllers.swift
//  DocHub
//
//  Created by Tristan Juricek on 6/10/14.
//  Copyright (c) 2014 Perforce. All rights reserved.
//

import Foundation
import AppKit

// The controller deals with nearly all "application" events from the different
// views, well, since there's really only supposed to be one window.
class DocHubController : NSObject, NSApplicationDelegate, NSSplitViewDelegate,
    LibraryViewDelegate {
        
    var window: NSWindow
    var mainSplitView: NSSplitView
    var librarySourceListController: LibrarySourceListController
    var libraryView: LibraryView
    var navigatorController: NavigatorController
    var toolbar: NSToolbar
    var toolbarDelegate: DocHubToolbarDelegate?
    
    var addPerforceController: AddPerforceController? = nil
    
    let docHubLocation = DocHubLocation()
    
    init() {
        let winRect = NSRect(x: 50, y: 150, width: 1024, height: 800)
        window = NSWindow(contentRect: winRect,
            styleMask: NSTitledWindowMask | NSClosableWindowMask |
                NSMiniaturizableWindowMask | NSResizableWindowMask,
            backing: NSBackingStoreType.Buffered,
            defer: false)
        
        mainSplitView = NSSplitView(frame: NSRect(x:0, y:0, width: 1024, height:800))
        
        librarySourceListController = LibrarySourceListController(nibName: "LibrarySourceListView", bundle: nil, docHubLocation: docHubLocation)
        
        libraryView = LibraryView(frame: NSRect(x: 0, y: 0, width: 200, height:800),
            sourceList: librarySourceListController.view)
        
        navigatorController = NavigatorController(nibName: "NavigatorView",
            bundle: nil, docHubLocation: docHubLocation)

        toolbar = NSToolbar(identifier: "DocHubToolbar")

        super.init()
        
        libraryView.delegate = self
        
    }
    
    func applicationDidFinishLaunching(aNotification: NSNotification?) {

        docHubLocation.areaObserver.listeners.append({ self.areaChanged($0) })
        docHubLocation.directoryObserver.listeners.append({ self.directoryChanged($0) })
        
        toolbarDelegate = DocHubToolbarDelegate(mainController:self)
        toolbar.delegate = toolbarDelegate
        toolbar.sizeMode = NSToolbarSizeMode.Regular
        toolbar.displayMode = NSToolbarDisplayMode.IconOnly
        
        window.toolbar = toolbar
        
        let libraryItem = toolbar.items
            .findFirst({ $0.itemIdentifier == DocHubLibraryToolbarItemIdentifier })
            as DocHubToolbarDelegate.LibraryItem
        libraryItem.selected = true
        
        mainSplitView.dividerStyle = NSSplitViewDividerStyle.Thin
        mainSplitView.vertical = true
        mainSplitView.delegate = self
        mainSplitView.autoresizingMask = NSAutoresizingMaskOptions.ViewHeightSizable |
            NSAutoresizingMaskOptions.ViewWidthSizable
        
        
        mainSplitView.addSubview(libraryView)
        mainSplitView.addSubview(navigatorController.view)

        window.contentView.addSubview(mainSplitView)

        window.title = NSLocalizedString("Document Hub", comment:"window.title")
        
        window.makeKeyAndOrderFront(self)

        mainSplitView.setPosition(200, ofDividerAtIndex: 0)
    }
    
    func areaChanged(area:Area) {
        window.title = "\(area.library.name): \(area.name)"
    }
    
    func directoryChanged(directory:Directory) {
        window.title = "\(directory.area.library.name): \(directory.name)"
    }
    
    func applicationWillTerminate(aNotification: NSNotification?) {
        // Insert code here to tear down your application
    }
    
    func toggleLibrary() {
        let isCollapsed = mainSplitView.isSubviewCollapsed(libraryView)
        if isCollapsed {
            uncollapseLibrary()
        } else {
            collapseLibrary()
        }
    }
    
    func uncollapseLibrary() {

        mainSplitView.setPosition(200, ofDividerAtIndex: 0)

        libraryView.hidden = false
        
        let libraryItem = toolbar.items
            .findFirst({ $0.itemIdentifier == DocHubLibraryToolbarItemIdentifier })
                as DocHubToolbarDelegate.LibraryItem
        libraryItem.selected = true
    }
    
    func collapseLibrary() {

        mainSplitView.setPosition(0, ofDividerAtIndex: 0)

        libraryView.hidden = true
        
        let libraryItem = toolbar.items
            .findFirst({ $0.itemIdentifier == DocHubLibraryToolbarItemIdentifier })
            as DocHubToolbarDelegate.LibraryItem
        libraryItem.selected = false
    }

    func splitView(splitView: NSSplitView!,
        canCollapseSubview subview: NSView!) -> Bool {
        
        return subview === libraryView
    }
    
    func splitView(splitView: NSSplitView!,
        shouldCollapseSubview subview: NSView!,
        forDoubleClickOnDividerAtIndex dividerIndex: Int) -> Bool {
        
        return dividerIndex == 0
    }
    
    func addPerforceServer()  {
        addPerforceController = AddPerforceController(windowNibName:"AddPerforceSheet")
        
        NSApp.beginSheet(addPerforceController!.window, modalForWindow: window,
            modalDelegate: self, didEndSelector: "addPerforceServerDone",
            contextInfo: nil)
    }
    
    func addPerforceServerDone() {
        addPerforceController!.window.orderOut(addPerforceController!)
        addPerforceController = nil

        librarySourceListController.reload()
    }
}
# Change User Description Committed
#12 9583 tjuricek Set up basic directory browsing.
#11 9560 tjuricek Setup parent reference to Library protocol, and handle using a separate model class.
Adds a "library" ID to the title bar, which may make sense.
#10 9556 tjuricek Add an informal "PropertyObserver" class to set up a typed bindings system, which in turn updates the window title at the moment.
#9 9555 tjuricek Changing how the main splitter is toggled
#8 9553 tjuricek Adjust the library toolbar icon to act like a toggle switch, similar to XCode 6's toolbar buttons.

I'm not 100% sure about the placement of the left 3 buttons, so this may end up requiring a lot of custom views to be more consistent with the inconsistency that is 10.10.
#7 9545 tjuricek Use the left column to navigate p4 servers as "libraries" with their depots as "areas".

I've had to stop using the output of login -p at the moment, since it doesn't quite work with the Objective-C API in lieu of a password.
#6 9469 tjuricek Add sheet view for collecting Perforce connection information.
#5 9438 tjuricek Updated style of the library toolbar icon to match more of the Yosemite look and feel.

Removed the "back/next" buttons. We should probably use a single view for them, and bring them back when they'll actually be used.
#4 9433 tjuricek Setup the library toggle mechanism to the toolbar.
#3 9432 tjuricek Added framework for a standard toolbar.
#2 9420 tjuricek Minimal UI framework.

Lesson learned: if you're not using nibs, thou shalt access thy application as NSApplication.sharedApplication, or thy will encounter strange resizing exceptions.
#1 9249 tjuricek Added test p4d setup, and reorganized some core code.

I've decided to not use InterfaceBuilder in this project, because I don't like that the .xib files are not very easy to merge, and the object lifetimes are a bit more difficult to trace. The DocHubController will operate as the app delegate, and will create views manually.

Using the gradle toolchain to setup p4d. To use, execute:

./gradlew startPerforce
./gradlew initPerforce # only needed the first time

This creates the p4d that uses build/perforce/work
//guest/tjuricek/DocHub/DocHub/AppDelegate.swift
#1 9229 tjuricek Basic project code for a prototype

Assumes p4api library is available at /usr/local/p4api