2020-11-02 12:19:13 +01:00

181 lines
8.4 KiB
Swift

//
// Document.swift
// Graphic Analysis 2
//
// Created by Kilian Hofmann on 15.06.17.
// Copyright © 2017 Kilian Hofmann. All rights reserved.
//
import Cocoa
class Document: NSDocument {
var year: FileWrapper?
var months: [FileWrapper?] = [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
var days: [[FileWrapper?]] = []
var yearDatasource: CollectionViewYear = CollectionViewYear()
var monthDatasource: CollectionViewMonth = CollectionViewMonth()
var windowController: NSWindowController = NSWindowController()
var pdfWindows: [Data] = [Data(), Data(), Data(), Data(), Data(), Data(), Data(), Data(), Data(), Data(), Data(), Data()]
var pdfBegin: Bool = false
var name: String = ""
@IBOutlet var collectionViewYear: NSCollectionView!
@IBOutlet var collectionViewMonth: NSCollectionView!
@IBOutlet var progress: NSProgressIndicator!
@IBOutlet var exportProgress: NSProgressIndicator!
override class var autosavesInPlace: Bool {
return false;
}
override init() {
super.init()
for _ in 0..<12 {
var temp: [FileWrapper?] = []
for _ in 0..<31 {
temp.append(nil)
}
days.append(temp)
}
}
override var windowNibName: NSNib.Name? {
return "Document"
}
override func read(from fileWrapper: FileWrapper, ofType typeName: String) throws {
name = (fileWrapper.filename! as NSString).deletingPathExtension
year = fileWrapper
for entry in fileWrapper.fileWrappers! {
guard let month = Int(entry.key) else { continue }
months[month-1] = entry.value
for entry2 in entry.value.fileWrappers! {
guard let day = Int(entry2.key) else { continue }
days[month-1][day-1] = entry2.value
}
}
//throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
}
override func windowControllerDidLoadNib(_ windowController: NSWindowController) {
// Setup collection layout
let flowLayout = NSCollectionViewFlowLayout()
flowLayout.itemSize = NSSize(width: 228, height: 211)
flowLayout.sectionInset = NSEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
flowLayout.minimumInteritemSpacing = 10
flowLayout.minimumLineSpacing = 10
collectionViewYear.collectionViewLayout = flowLayout
let flowLayout2 = NSCollectionViewFlowLayout()
flowLayout2.itemSize = NSSize(width: 135, height: 132)
flowLayout2.sectionInset = NSEdgeInsets(top: 2, left: 2, bottom: 2, right: 2)
flowLayout2.minimumInteritemSpacing = 2
flowLayout2.minimumLineSpacing = 2
collectionViewMonth.collectionViewLayout = flowLayout2
// Performance
windowController.window?.contentView?.wantsLayer = true
self.windowController = windowController
// Data sources and delegate
monthDatasource = CollectionViewMonth(days: days, document: self)
yearDatasource = CollectionViewYear(months: months, dataSourceMonth: monthDatasource, collectionViewMonth: collectionViewMonth, document: self)
collectionViewYear.dataSource = yearDatasource
collectionViewYear.delegate = yearDatasource
collectionViewMonth.dataSource = monthDatasource
collectionViewMonth.delegate = monthDatasource
}
override func shouldCloseWindowController(_ windowController: NSWindowController, delegate: Any?, shouldClose shouldCloseSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
pthread_mutex_lock(&(NSApp.delegate as! AppDelegate).lock)
if !pdfBegin {
super.shouldCloseWindowController(windowController, delegate: delegate, shouldClose: shouldCloseSelector, contextInfo: contextInfo)
} else {
let alert = NSAlert()
alert.messageText = "Warning"
alert.informativeText = "PDF export active. Please wait until completed."
alert.alertStyle = NSAlert.Style.warning
alert.addButton(withTitle: "OK")
alert.runModal()
}
pthread_mutex_unlock(&(NSApp.delegate as! AppDelegate).lock)
}
override func printOperation(withSettings printSettings: [NSPrintInfo.AttributeKey : Any]) throws -> NSPrintOperation {
let printOperation: NSPrintOperation = NSPrintOperation(view: collectionViewMonth)
printOperation.printInfo.orientation = .landscape
printOperation.printInfo.horizontalPagination = .fit
printOperation.printInfo.verticalPagination = .fit
printOperation.printInfo.topMargin = 1
printOperation.printInfo.rightMargin = 1
printOperation.printInfo.bottomMargin = 1
printOperation.printInfo.leftMargin = 1
return printOperation
}
@IBAction func exportPDF(sender: Any) {
(sender as! NSMenuItem).isEnabled = false
let savePanel: NSSavePanel = NSSavePanel()
savePanel.allowedFileTypes = ["pdf"]
savePanel.nameFieldStringValue = name
savePanel.canCreateDirectories = true
savePanel.beginSheetModal(for: windowController.window!) { result in
if result.rawValue == NSFileHandlingPanelOKButton {
self.exportProgress.doubleValue = 0
self.exportProgress.isHidden = false
let operationQueue: OperationQueue = OperationQueue()
let d_group: DispatchGroup = DispatchGroup()
let bg_queue: DispatchQueue = DispatchQueue.global()
operationQueue.addOperation {
pthread_mutex_lock(&(NSApp.delegate as! AppDelegate).lock)
self.pdfBegin = true
pthread_mutex_unlock(&(NSApp.delegate as! AppDelegate).lock)
var bounds: NSRect = NSMakeRect(0, 0, 964, 675)
let data: NSMutableData = NSMutableData()
let dataConsumer: CGDataConsumer = CGDataConsumer(data: data)!
let context: CGContext = CGContext(consumer: dataConsumer, mediaBox: &bounds, nil)!
context.beginPDFPage(nil)
let window: PDFTitle = PDFTitle(title: "Monthly loss overview of year \(self.name)")
let providerTitle: CGDataProvider = CGDataProvider(data: (window.window?.contentView?.dataWithPDF(inside: (window.window?.contentView?.bounds)!))! as CFData)!
let titlePDF: CGPDFDocument = CGPDFDocument(providerTitle)!
let titlePage: CGPDFPage = titlePDF.page(at: 1)!
context.drawPDFPage(titlePage)
context.endPDFPage()
for i in 0..<12 {
bg_queue.async(group: d_group, qos: DispatchQoS(qosClass: .background, relativePriority: 0), flags: .barrier) {
let window: PDFDraw = PDFDraw(month: i)
window.days = self.days[i]
self.pdfWindows[i] = (window.window?.contentView?.dataWithPDF(inside: (window.window?.contentView?.bounds)!))!
DispatchQueue.main.async {
self.exportProgress.increment(by: 100/13)
}
}
}
let _: DispatchTimeoutResult = d_group.wait(timeout: .distantFuture)
for i in 0..<12 {
context.beginPDFPage(nil)
let montDataProvider: CGDataProvider = CGDataProvider(data: self.pdfWindows[i] as CFData)!
let monthPDF: CGPDFDocument = CGPDFDocument(montDataProvider)!
let page: CGPDFPage = monthPDF.page(at: 1)!
context.drawPDFPage(page)
context.endPDFPage()
}
context.closePDF()
data.write(to: savePanel.url!, atomically: true)
DispatchQueue.main.async {
self.exportProgress.increment(by: 100/13)
}
pthread_mutex_lock(&(NSApp.delegate as! AppDelegate).lock)
self.pdfBegin = false
pthread_mutex_unlock(&(NSApp.delegate as! AppDelegate).lock)
self.exportProgress.isHidden = true
(sender as! NSMenuItem).isEnabled = true
}
}
}
}
}