Implement printing
This commit is contained in:
parent
61ef712df4
commit
30652c5627
|
@ -16,6 +16,7 @@
|
|||
950AB9271A296A160033A9DA /* ProjIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 950AB9261A296A160033A9DA /* ProjIcon.icns */; };
|
||||
951CD1741A23C9FC0066C1A1 /* ASBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951CD1731A23C9FC0066C1A1 /* ASBuilder.swift */; };
|
||||
951CD1771A2615000066C1A1 /* BuildProject in Resources */ = {isa = PBXBuildFile; fileRef = 951CD1761A2615000066C1A1 /* BuildProject */; };
|
||||
95388E5D1AB6882600061435 /* FileRevision in Resources */ = {isa = PBXBuildFile; fileRef = 95388E5C1AB6882600061435 /* FileRevision */; };
|
||||
9538E0EC1A8FB215001E02CC /* ACEView.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 95EA325B1A17B8DA00F66EB0 /* ACEView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
95468DDF1A228BE600668EE2 /* ASHardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95468DDE1A228BE600668EE2 /* ASHardware.swift */; };
|
||||
95468DE31A228E1300668EE2 /* Defaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = 95468DE21A228E1300668EE2 /* Defaults.plist */; };
|
||||
|
@ -102,6 +103,7 @@
|
|||
950AB9261A296A160033A9DA /* ProjIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ProjIcon.icns; path = IconResources/ProjIcon.icns; sourceTree = "<group>"; };
|
||||
951CD1731A23C9FC0066C1A1 /* ASBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASBuilder.swift; sourceTree = "<group>"; };
|
||||
951CD1761A2615000066C1A1 /* BuildProject */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = BuildProject; sourceTree = "<group>"; };
|
||||
95388E5C1AB6882600061435 /* FileRevision */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = FileRevision; sourceTree = "<group>"; };
|
||||
95468DDE1A228BE600668EE2 /* ASHardware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASHardware.swift; sourceTree = "<group>"; };
|
||||
95468DE21A228E1300668EE2 /* Defaults.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Defaults.plist; sourceTree = "<group>"; };
|
||||
95539B661A3E7EAF00D8595C /* ASSerial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASSerial.h; sourceTree = "<group>"; };
|
||||
|
@ -211,6 +213,7 @@
|
|||
951CD1731A23C9FC0066C1A1 /* ASBuilder.swift */,
|
||||
95A7C6451A3894C900EF1963 /* ASPreferences.swift */,
|
||||
951CD1761A2615000066C1A1 /* BuildProject */,
|
||||
95388E5C1AB6882600061435 /* FileRevision */,
|
||||
95539B661A3E7EAF00D8595C /* ASSerial.h */,
|
||||
95539B671A3E7EAF00D8595C /* ASSerial.mm */,
|
||||
95DF20661A45A6090013D1B5 /* ASSketchBook.swift */,
|
||||
|
@ -305,6 +308,7 @@
|
|||
9501D7F41A17025C0034C530 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0700;
|
||||
LastUpgradeCheck = 0630;
|
||||
ORGANIZATIONNAME = "Aere Perennius";
|
||||
TargetAttributes = {
|
||||
|
@ -383,6 +387,7 @@
|
|||
95CC3F071A6385B8003507AD /* CSrcIcon.icns in Resources */,
|
||||
951CD1771A2615000066C1A1 /* BuildProject in Resources */,
|
||||
95CC3F081A6385B8003507AD /* HSrcIcon.icns in Resources */,
|
||||
95388E5D1AB6882600061435 /* FileRevision in Resources */,
|
||||
95CC3F061A6385B8003507AD /* CppSrcIcon.icns in Resources */,
|
||||
95CC3F051A6385B8003507AD /* AsmSrcIcon.icns in Resources */,
|
||||
);
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0630"
|
||||
version = "1.8">
|
||||
LastUpgradeVersion = "0700"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
enableAddressSanitizer = "NO">
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
|
@ -85,6 +84,11 @@
|
|||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
<AdditionalOption
|
||||
key = "NSZombieEnabled"
|
||||
value = "YES"
|
||||
isEnabled = "YES">
|
||||
</AdditionalOption>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
|
|
|
@ -60,6 +60,12 @@ private let kNameKey = "Name"
|
|||
// exposed to ObjC APIs. As a workaround, we declare this hierarchy @objc
|
||||
//
|
||||
@objc class ASFileNode {
|
||||
var name : String
|
||||
|
||||
init(name: String) {
|
||||
self.name = name
|
||||
}
|
||||
|
||||
func nodeName() -> String {
|
||||
return ""
|
||||
}
|
||||
|
@ -87,23 +93,33 @@ private let kNameKey = "Name"
|
|||
func exists() -> Bool {
|
||||
return true
|
||||
}
|
||||
func modDate() -> NSDate? {
|
||||
return nil;
|
||||
}
|
||||
func revision() -> String? {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
class ASLogNode : ASFileNode {
|
||||
var name : String
|
||||
var path : String
|
||||
|
||||
init(name: String, path: String) {
|
||||
self.name = name
|
||||
self.path = path
|
||||
super.init(name: name)
|
||||
}
|
||||
override func nodeName() -> String {
|
||||
return "📜 "+name
|
||||
}
|
||||
override func modDate() -> NSDate? {
|
||||
let url = NSURL(fileURLWithPath: path)
|
||||
var date: AnyObject?
|
||||
url?.getResourceValue(&date, forKey: NSURLContentModificationDateKey, error: nil)
|
||||
return date as? NSDate
|
||||
}
|
||||
}
|
||||
|
||||
class ASFileGroup : ASFileNode {
|
||||
var name : String
|
||||
var children : [ASFileNode]
|
||||
var expanded : Bool
|
||||
|
||||
|
@ -111,18 +127,18 @@ class ASFileGroup : ASFileNode {
|
|||
private let kExpandedKey = "Expanded"
|
||||
private var kNodeType : String { return kNodeTypeGroup }
|
||||
|
||||
init(name: String = "") {
|
||||
self.name = name
|
||||
override init(name: String = "") {
|
||||
self.children = []
|
||||
self.expanded = true
|
||||
super.init(name: name)
|
||||
}
|
||||
init(_ prop: NSDictionary, withRootURL rootURL: NSURL) {
|
||||
name = prop[kNameKey] as! String
|
||||
expanded = prop[kExpandedKey] as! Bool
|
||||
children = []
|
||||
for child in (prop[kChildrenKey] as! [NSDictionary]) {
|
||||
children.append(ASFileNode.readPropertyList(child, rootURL: rootURL))
|
||||
}
|
||||
super.init(name: prop[kNameKey] as! String)
|
||||
}
|
||||
override func nodeName() -> String {
|
||||
return (expanded ? "📂" : "📁")+" "+name
|
||||
|
@ -167,6 +183,7 @@ class ASFileItem : ASFileNode {
|
|||
init(url: NSURL, type: ASFileType) {
|
||||
self.url = url
|
||||
self.type = type
|
||||
super.init(name:url.lastPathComponent!)
|
||||
}
|
||||
init(_ prop: NSDictionary, withRootURL rootURL: NSURL) {
|
||||
type = ASFileType(rawValue: prop[kKindKey] as! String)!
|
||||
|
@ -175,9 +192,10 @@ class ASFileItem : ASFileNode {
|
|||
} else {
|
||||
url = NSURL(fileURLWithPath:(prop[kPathKey] as! String))!.URLByStandardizingPath!
|
||||
}
|
||||
super.init(name:url.lastPathComponent!)
|
||||
}
|
||||
override func nodeName() -> String {
|
||||
return "📄 "+url.lastPathComponent!
|
||||
return "📄 "+name
|
||||
}
|
||||
|
||||
func relativePath(relativeTo: String) -> String {
|
||||
|
@ -211,6 +229,23 @@ class ASFileItem : ASFileNode {
|
|||
override func exists() -> Bool {
|
||||
return url.checkResourceIsReachableAndReturnError(nil)
|
||||
}
|
||||
override func modDate() -> NSDate? {
|
||||
var date: AnyObject?
|
||||
url.getResourceValue(&date, forKey: NSURLContentModificationDateKey, error: nil)
|
||||
return date as? NSDate
|
||||
}
|
||||
override func revision() -> String? {
|
||||
let task = NSTask()
|
||||
task.launchPath = NSBundle.mainBundle().pathForResource("FileRevision", ofType: "")!
|
||||
let outputPipe = NSPipe()
|
||||
task.standardOutput = outputPipe
|
||||
task.standardError = NSFileHandle.fileHandleWithNullDevice()
|
||||
task.arguments = [url.path!]
|
||||
task.launch()
|
||||
|
||||
return NSString(data: outputPipe.fileHandleForReading.readDataToEndOfFile(),
|
||||
encoding: NSUTF8StringEncoding) as? String
|
||||
}
|
||||
}
|
||||
|
||||
class ASFileTree : NSObject, NSOutlineViewDataSource {
|
||||
|
|
|
@ -26,7 +26,7 @@ func pushToFront(inout list: [String], front: String) {
|
|||
list.insert(front, atIndex: 0)
|
||||
}
|
||||
|
||||
class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate, NSOpenSavePanelDelegate {
|
||||
class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate, NSOpenSavePanelDelegate, ACEViewDelegate {
|
||||
@IBOutlet weak var editor : ACEView!
|
||||
@IBOutlet weak var outline : NSOutlineView!
|
||||
@IBOutlet weak var boardTool: NSPopUpButton!
|
||||
|
@ -49,7 +49,10 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate, NSOpenSavePa
|
|||
var logModified = NSDate.distantPast() as! NSDate
|
||||
var logSize = 0
|
||||
var updateLogTimer : NSTimer?
|
||||
|
||||
var printingDone : () -> () = {}
|
||||
var printModDate : NSDate?
|
||||
var printRevision : String?
|
||||
|
||||
let kVersionKey = "Version"
|
||||
let kCurVersion = 1.0
|
||||
let kFilesKey = "Files"
|
||||
|
@ -107,6 +110,8 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate, NSOpenSavePa
|
|||
editor.setTheme(currentTheme)
|
||||
editor.setKeyboardHandler(keyboardHandler)
|
||||
editor.setFontSize(fontSize)
|
||||
editor.delegate = self
|
||||
|
||||
outline.setDataSource(files)
|
||||
files.apply() { node in
|
||||
if let group = node as? ASFileGroup {
|
||||
|
@ -277,8 +282,147 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate, NSOpenSavePa
|
|||
|
||||
// MARK: Printing
|
||||
|
||||
override func printDocument(sender: AnyObject?) {
|
||||
editor.print(sender)
|
||||
override func printDocumentWithSettings(printSettings: [NSObject : AnyObject], showPrintPanel: Bool, delegate: AnyObject?, didPrintSelector: Selector, contextInfo: UnsafeMutablePointer<Void>) {
|
||||
//
|
||||
// Thanks to Erica Sadun for showing me how to call a selector in Swift
|
||||
//
|
||||
printingDone =
|
||||
{ () -> () in
|
||||
if let del : AnyObject = delegate {
|
||||
NSThread.detachNewThreadSelector(didPrintSelector, toTarget: del, withObject: contextInfo as? AnyObject)
|
||||
}
|
||||
}
|
||||
printModDate = mainEditor?.modDate()
|
||||
printRevision = mainEditor?.revision()
|
||||
|
||||
editor.print(self)
|
||||
}
|
||||
|
||||
func printSettings() -> NSPrintInfo! {
|
||||
var info = printInfo.copy() as! NSPrintInfo
|
||||
|
||||
//
|
||||
// Minimize margins
|
||||
//
|
||||
let kXMargin : CGFloat = 50.0
|
||||
let kYMargin : CGFloat = 50.0
|
||||
let paperSize = info.paperSize
|
||||
var maxBounds = info.imageablePageBounds
|
||||
|
||||
if paperSize.width - maxBounds.size.width < kXMargin {
|
||||
let adjust = kXMargin-paperSize.width+maxBounds.size.width
|
||||
maxBounds.origin.x += 0.5*adjust
|
||||
maxBounds.size.width -= adjust
|
||||
}
|
||||
if paperSize.height - maxBounds.size.height < kYMargin {
|
||||
let adjust = kYMargin-paperSize.height+maxBounds.size.height
|
||||
maxBounds.origin.y += 0.5*adjust
|
||||
maxBounds.size.height -= adjust
|
||||
}
|
||||
info.leftMargin = maxBounds.origin.x
|
||||
info.bottomMargin = maxBounds.origin.y
|
||||
info.topMargin = paperSize.height-maxBounds.size.height-info.bottomMargin
|
||||
info.rightMargin = paperSize.width-maxBounds.size.width-info.leftMargin
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
func printJobTitle() -> String! {
|
||||
return mainEditor?.nodeName() ??
|
||||
fileURL?.lastPathComponent?.stringByDeletingPathExtension ??
|
||||
"Untitled"
|
||||
}
|
||||
|
||||
func printHeaderHeight() -> Float {
|
||||
return 41.0
|
||||
}
|
||||
|
||||
func printFooterHeight() -> Float {
|
||||
return 20.0
|
||||
}
|
||||
|
||||
func drawPrintHeaderForPage(pageNo: Int32, inRect r: NSRect) {
|
||||
var rect = r
|
||||
rect.origin.y += 5.0
|
||||
rect.size.height -= 5.0
|
||||
|
||||
let ctx = NSGraphicsContext.currentContext()!
|
||||
ctx.saveGraphicsState()
|
||||
NSColor(white: 0.95, alpha: 1.0).setFill()
|
||||
var wideBox = rect
|
||||
wideBox.size.height = 20.0
|
||||
wideBox.origin.y += 0.5*(rect.size.height-wideBox.size.height)
|
||||
NSRectFill(wideBox)
|
||||
|
||||
NSColor(white: 0.7, alpha: 1.0).setFill()
|
||||
var pageNoBox = rect
|
||||
pageNoBox.size.width = 50.0
|
||||
pageNoBox.origin.x += 0.5*(rect.size.width-pageNoBox.size.width)
|
||||
NSRectFill(pageNoBox)
|
||||
ctx.restoreGraphicsState()
|
||||
|
||||
let pageNoFont = NSFont.userFixedPitchFontOfSize(25.0)!
|
||||
let pageNoAttr = [
|
||||
NSFontAttributeName: pageNoFont,
|
||||
NSForegroundColorAttributeName: NSColor.whiteColor(),
|
||||
NSStrokeWidthAttributeName: -5.0]
|
||||
let pageNoStr = "\(pageNo)"
|
||||
let pageNoSize = pageNoStr.sizeWithAttributes(pageNoAttr)
|
||||
let pageNoAt = NSPoint(
|
||||
x: pageNoBox.origin.x+0.5*(pageNoBox.size.width-pageNoSize.width),
|
||||
y: pageNoBox.origin.y+3.5)
|
||||
pageNoStr.drawAtPoint(pageNoAt, withAttributes:pageNoAttr)
|
||||
|
||||
let kXOffset : CGFloat = 5.0
|
||||
let titleFont = NSFont.userFontOfSize(12.0)!
|
||||
let titleAttr = [NSFontAttributeName:titleFont]
|
||||
var titleAt = NSPoint(
|
||||
x: wideBox.origin.x+kXOffset,
|
||||
y: wideBox.origin.y+0.5*(wideBox.size.height-titleFont.ascender+titleFont.descender))
|
||||
|
||||
if let fileNameStr = mainEditor?.name {
|
||||
fileNameStr.drawAtPoint(titleAt, withAttributes:titleAttr)
|
||||
}
|
||||
if let projectNameStr = fileURL?.lastPathComponent?.stringByDeletingPathExtension {
|
||||
let projectNameSize = projectNameStr.sizeWithAttributes(titleAttr)
|
||||
titleAt.x = wideBox.origin.x+wideBox.size.width-projectNameSize.width-kXOffset
|
||||
projectNameStr.drawAtPoint(titleAt, withAttributes:titleAttr)
|
||||
}
|
||||
}
|
||||
|
||||
func drawPrintFooterForPage(pageNo: Int32, inRect r: NSRect) {
|
||||
var rect = r
|
||||
rect.size.height -= 5.0
|
||||
|
||||
let ctx = NSGraphicsContext.currentContext()!
|
||||
ctx.saveGraphicsState()
|
||||
NSColor(white: 0.95, alpha: 1.0).setFill()
|
||||
NSRectFill(rect)
|
||||
ctx.restoreGraphicsState()
|
||||
|
||||
let kXOffset : CGFloat = 5.0
|
||||
let footFont = NSFont.userFixedPitchFontOfSize(10.0)!
|
||||
let footAttr = [NSFontAttributeName:footFont]
|
||||
var footAt = NSPoint(
|
||||
x: rect.origin.x+kXOffset,
|
||||
y: rect.origin.y+0.5*(rect.size.height-footFont.ascender+footFont.descender))
|
||||
|
||||
if let revisionStr = printRevision {
|
||||
revisionStr.drawAtPoint(footAt, withAttributes:footAttr)
|
||||
}
|
||||
if let modDate = printModDate
|
||||
{
|
||||
let dateFormatter = NSDateFormatter()
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
|
||||
let modDateStr = dateFormatter.stringFromDate(modDate)
|
||||
let modDateSize = modDateStr.sizeWithAttributes(footAttr)
|
||||
footAt.x = rect.origin.x+rect.size.width-modDateSize.width-kXOffset
|
||||
modDateStr.drawAtPoint(footAt, withAttributes:footAttr)
|
||||
}
|
||||
}
|
||||
|
||||
func printingComplete() {
|
||||
printingDone()
|
||||
}
|
||||
|
||||
// MARK: Outline View Delegate
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7515.2" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7519.1" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7515.2"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7519.1"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -11,6 +11,7 @@
|
|||
<outlet property="editor" destination="Nhg-qn-6A8" id="eUR-Gk-IBw"/>
|
||||
<outlet property="outline" destination="nij-C2-Fna" id="sVi-eL-hqZ"/>
|
||||
<outlet property="portTool" destination="4rZ-U5-AH6" id="8Nb-iI-pJH"/>
|
||||
<outlet property="printView" destination="HFe-2c-jeW" id="dh0-q5-QVW"/>
|
||||
<outlet property="progTool" destination="08n-xg-fNl" id="959-as-OtP"/>
|
||||
<outlet property="window" destination="xOd-HO-29H" id="JIz-fz-R2o"/>
|
||||
</connections>
|
||||
|
@ -278,6 +279,10 @@
|
|||
<point key="canvasLocation" x="408" y="438"/>
|
||||
</window>
|
||||
<userDefaultsController representsSharedInstance="YES" id="fpc-q0-yYy"/>
|
||||
<customView id="HFe-2c-jeW" customClass="ACEView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="163" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="BuildIcon" width="32" height="32"/>
|
||||
|
|
33
AVRsack/FileRevision
Executable file
33
AVRsack/FileRevision
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/ruby
|
||||
#
|
||||
# FileRevision FILE
|
||||
#
|
||||
# AVRsack
|
||||
#
|
||||
# Created by Matthias Neeracher on 03/16/15.
|
||||
# Copyright © 2015 Aere Perennius. All rights reserved.
|
||||
#
|
||||
|
||||
file = ARGV[0]
|
||||
if file =~ %r|(.*)/(.*)|
|
||||
Dir.chdir($1)
|
||||
file = $2
|
||||
end
|
||||
rev = ''
|
||||
IO.popen("git log -1 --pretty=oneline '#{file}'", 'r') do |io|
|
||||
if line = io.gets
|
||||
rev = line[0..7]
|
||||
end
|
||||
end
|
||||
if $? == 0 && rev.size > 0
|
||||
print rev
|
||||
else
|
||||
IO.popen("svn info '#{file}'") do |io|
|
||||
io.each_line do |line|
|
||||
if line =~ /Last Changed Rev:\s+(\S+)/
|
||||
print "r"+$1
|
||||
exit 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user