;; @file packer.nu
;; @discussion PagePacker in Nu.
;;
;; @copyright Copyright (c) 2007 Tim Burks, Neon Design Technology, Inc.
;; Substantially derived from original Objective-C source code by Aaron Hillegass.
;; See objc/PagePacker.m for the copyright notice for the original code.
(global BLOCK_COUNT 8) ;; We display 8 pages in a PagePacker document. There is no easy way to change this.
;; @class CatalogController
;; @discussion This class controls the display of the PDF source document.
;; Pages can be dragged from this document into the PagePacker document view.
(class CatalogController is NSWindowController
(ivar (id) pdfView
(id) pageSlider
(id) pageField
(int) currentPageIndex)
(set sharedCatalogController nil) ;; Since the assignment is made inside the class declaration, Nu closures make this a class variable.
(+ sharedCatalogController is sharedCatalogController)
(- init is
(super initWithWindowNibName:"CatalogController")
(unless sharedCatalogController
(set sharedCatalogController self))
(set @currentPageIndex 0)
self)
(- windowDidLoad is
(set path ((NSBundle mainBundle) pathForResource:"diyp3h_core_1up" ofType:@"pdf"))
(set url (NSURL fileURLWithPath:path))
(set pdfDoc ((PDFDocument alloc) initWithURL:url))
(set pageCount (pdfDoc pageCount))
(@pageSlider set:
(numberOfTickMarks:(- pageCount 2)
minValue:0
maxValue:(- pageCount 1)))
(@pdfView setBounds:'(65 90 260 380))
(@pdfView setDocument:pdfDoc)
(@pdfView setDisplayMode:kPDFDisplaySinglePage)
(set w (self window))
(w setBecomesKeyOnlyIfNeeded:YES)
(w setNextResponder:self))
(- (void)changeToPage:(int)i is
(unless (eq @currentPageIndex i)
(set doc (@pdfView document))
(unless (or (< i 0) (>= i (doc pageCount)))
(set @currentPageIndex i)
(@pdfView goToPage:(doc pageAtIndex:@currentPageIndex))
(@pageField setIntValue:(+ @currentPageIndex 1)))))
(- (void)changePage:(id)sender is
(self changeToPage:(@pageSlider intValue)))
(- (void)scrollWheel:(id)theEvent is
(set deltaY (theEvent deltaY))
(if (> deltaY 0.1)
(self changeToPage:(+ @currentPageIndex 1))
(@pageSlider setIntValue:@currentPageIndex))
(if (< deltaY -0.1)
(self changeToPage:(- @currentPageIndex 1))
(@pageSlider setIntValue:@currentPageIndex)))
(- (void)moveLeft:(id)sender is
(self changeToPage:(- @currentPageIndex 1))
(@pageSlider setIntValue:@currentPageIndex))
(- (void)moveRight:(id)sender is
(self changeToPage:(+ @currentPageIndex 1))
(@pageSlider setIntValue:@currentPageIndex))
(- (void)moveUp:(id)sender is
(self changeToPage:(+ @currentPageIndex 1))
(@pageSlider setIntValue:@currentPageIndex))
(- (void)moveDown:(id)sender is
(self changeToPage:(- @currentPageIndex 1))
(@pageSlider setIntValue:@currentPageIndex)))
;; @class MyDocument
;; @discussion This is the main PagePacker document.
(class MyDocument is NSDocument
(ivar (id) packModel (id) packerView)
(- (id)init is
(super init)
(set @packModel ((PackModel alloc) init))
(@packModel setUndoManager:(self undoManager))
self)
(- (id)windowNibName is "MyDocument")
(- (void)updateUI is
(@packerView setPackModel:@packModel)
((@packerView window) setNextResponder:(CatalogController sharedCatalogController)))
(- (void)windowControllerDidLoadNib:(id) aController is
(super windowControllerDidLoadNib:aController)
(self updateUI))
(- (id)dataRepresentationOfType:(id)aType is
(NSKeyedArchiver archivedDataWithRootObject:@packModel))
(- (BOOL)loadDataRepresentation:(id)data ofType:(id)aType is
(set @packModel (NSKeyedUnarchiver unarchiveObjectWithData:data))
(@packModel setUndoManager:(self undoManager))
(if @packerView (self updateUI))
YES)
(- (id) printOperationWithSettings:(id)printSettings error:(id *)errorReference is
(NSPrintOperation printOperationWithView:@packerView printInfo:(self printInfo))))
;; @class DragingSourcePDFView
;; @discussion This class controls the view of the source document.
(class DraggingSourcePDFView is PDFView
(ivar (id) mouseDownEvent)
(+ (void) initialize is
(set $dragImage (NSImage imageNamed:"Generic")))
(- (id) hitTest:(NSPoint) aPoint is
(if (PointInRect aPoint (self frame))
(then self)
(else nil)))
(- (BOOL) shouldDelayWindowOrderingForEvent:(id) theEvent is YES)
(- (BOOL) acceptsFirstMouse:(id) theEvent is YES)
(- (int) draggingSourceOperationMaskForLocal:(BOOL) flag is NSDragOperationCopy)
(- (id) menuForEvent:(id) e is nil)
(- (void) mouseDown:(id) e is
(NSApp preventWindowOrdering)
(set @mouseDownEvent e))
(- (void) mouseDragged:(id) e is
(set start (@mouseDownEvent locationInWindow))
(set current (e locationInWindow))
;; Is this a significant distance from the mouseDown?
(unless (< (distanceSquaredBetweenPoints start current) 52.0)
(set dragStart (self convertPoint:start fromView:nil))
(set imageSize ($dragImage size))
(set dragStart (list (- (dragStart first) (/ (imageSize first) 3.0))
(- (dragStart second) (/ (imageSize second) 3.0))))
(set page (self currentPage))
(set d (page dataRepresentation))
(set dPboard (NSPasteboard pasteboardWithName:NSDragPboard))
(dPboard declareTypes:(NSArray arrayWithObject:NSPDFPboardType) owner:self)
(dPboard setData:d forType:NSPDFPboardType)
(self dragImage:$dragImage
at:dragStart
offset:'(0 0)
event:@mouseDownEvent
pasteboard:dPboard
source:self
slideBack:YES)
(set @mouseDownEvent nil)))
(- (void) mouseUp:(id) e is
(set @mouseDownEvent nil)))
;; @class PackModel
;; @discussion This class describes the PagePacker document.
(class PackModel is NSObject
(ivar (id) pageInfos (id) undoManager)
(- (id) init is
(super init)
(set @pageInfos ((NSMutableArray alloc) init))
(BLOCK_COUNT times: (do (i) (@pageInfos addObject:nil)))
self)
(- (id) preparedImageRepForPage:(int) pageNum is
(set obj (@pageInfos objectAtIndex:pageNum))
(if obj
(then (obj preparedImageRep))
(else nil)))
(- (void) replacePageInfoAt:(int) i withPageInfo:(id) pi is
(set oldInfo (@pageInfos objectAtIndex:i))
(unless (eq pi oldInfo)
((@undoManager prepareWithInvocationTarget:self) replacePageInfoAt:i withPageInfo:oldInfo)
(@pageInfos replaceObjectAtIndex:i withObject:pi)
((NSNotificationCenter defaultCenter) postNotificationName:"PackModelChangedNotification" object:self userInfo:nil)))
(- (void) setImageRep:(id) r pageOfRep:(int) repPage forPage:(int) viewPage is
(set pi ((PageInfo alloc) init))
(pi setImageRep:r)
(pi setPageOfRep:repPage)
(self replacePageInfoAt:viewPage withPageInfo:pi))
(- (id)initWithCoder:(id) c is
(super init)
(set @pageInfos (c decodeObjectForKey:"pageInfos"))
self)
(- (void)encodeWithCoder:(id) c is
(c encodeObject:@pageInfos forKey:"pageInfos"))
(- (void) setUndoManager:(id) undo is
(set @undoManager undo))
(- (id) undoManager is @undoManager)
(- (void) removeAllImageReps is
(BLOCK_COUNT times:
(do (i)
(self replacePageInfoAt:i withPageInfo:nil))))
(- (void) removeImageRepAtPage:(int) i is
(self replacePageInfoAt:i withPageInfo:nil))
(- (void) swapImageRepAt:(int) i withRepAt:(int) j is
(set pii (@pageInfos objectAtIndex:i))
(set pij (@pageInfos objectAtIndex:j))
(self replacePageInfoAt:i withPageInfo:pij)
(self replacePageInfoAt:j withPageInfo:pii))
(- (void) copyImageRepAt:(int) i toRepAt:(int) j is
(set pii (@pageInfos objectAtIndex:i))
(set pij ((PageInfo alloc) init))
(pij setImageRep:(pii imageRep))
(pij setPageOfRep:(pii pageOfRep))
(self replacePageInfoAt:j withPageInfo:pij))
(- (BOOL)pageIsFilled:(int) i is
(if (@pageInfos objectAtIndex:i) (then 1) (else 0)))
(- (id) textAttributes is
(NSDictionary dictionaryWithObject:((PreferenceController sharedPreferenceController) textFont)
forKey:NSFontAttributeName))
(- (int) putAttributedString:(id) attStr startingOnPage:(int) i is
(set pdf (pdfFromAttributedStringOfSize attStr '(200 300)))
(self putPDFData:pdf startingOnPage:i))
(- (int) putPDF:(id) pdf startingOnPage:(int) i is
(set pageCount (pdf pageCount))
(for ((set j 0)
(and (< j pageCount) (< (+ j i) BLOCK_COUNT))
(set j (+ j 1)))
(self setImageRep:pdf pageOfRep:j forPage:(+ i j)))
(+ i j))
(- (int) putFile:(id) currentPath startingOnPage:(int) i is
(set imageRep (NSImageRep imageRepWithContentsOfFile:currentPath))
(if (not imageRep)
(then
(set str (NSString stringWithContentsOfFile:currentPath
encoding:NSUTF8StringEncoding
error:nil))
(if str
(then
(set atts (self textAttributes))
(set attStr ((NSAttributedString alloc) initWithString:str attributes:atts))
(self putAttributedString:attStr startingOnPage:i))
(else i)))
(else
(if (imageRep isKindOfClass:NSPDFImageRep)
(then
(self putPDF:imageRep startingOnPage:i))
(else
(self setImageRep:imageRep
pageOfRep:-1
forPage:i)
(+ 1 i))))))
(- (int) putFiles:(id) filenames startingOnPage:(int) i is
(set currentStart i)
(set fileCount (filenames count))
(for ((set currentFileIndex 0)
(< currentFileIndex fileCount)
(set currentFileIndex (+ currentFileIndex 1)))
(set currentStart (self putFile:(filenames objectAtIndex:currentFileIndex) startingOnPage:currentStart)))
currentStart)
(- (int) putPDFData:(id) d startingOnPage:(int) i is
(set ir ((NSPDFImageRep alloc) initWithData:d))
(set pageCount (ir pageCount))
(for ((set j 0)
(and (< j pageCount) (< (+ j i) BLOCK_COUNT))
(set j (+ j 1)))
(self setImageRep:ir
pageOfRep:j
forPage:(+ i j)))
(+ i j)))
;; @class PageInfo
;; @discussion This class describes an individual page in a PagePacker document.
(class PageInfo is NSObject
(ivar (id) imageRep (int) pageOfRep)
(- (void) encodeWithCoder:(id) c is
(c encodeObject:@imageRep forKey:@"imageRep")
(c encodeInt:@pageOfRep forKey:@"pageOfRep"))
(- (id) initWithCoder:(id) c is
(super init)
(set @imageRep (c decodeObjectForKey:@"imageRep"))
(set @pageOfRep (c decodeIntForKey:@"pageOfRep"))
self)
(- (id) preparedImageRep is
(if (>= @pageOfRep 0)
(@imageRep setCurrentPage:@pageOfRep))
@imageRep)
(- (void) setImageRep:(id) r is
(set @imageRep r))
(- (id) imageRep is @imageRep)
(- (void)setPageOfRep:(int)i is
(set @pageOfRep i))
(- (int)pageOfRep is @pageOfRep)
(- (id)description is
"<PageInfo: #{(@imageRep description)}, #{@pageOfRep}>"))
;; @class RoundCloseButtonCell
;; @discussion This class provides a custom button cell for use in the PackerView display.
(class RoundCloseButtonCell is NSButtonCell
(- (void)drawWithFrame:(NSRect)cellFrame inView:(id)controlView is
(if (NSGraphicsContext currentContextDrawingToScreen)
(if (self isHighlighted)
(then ((NSColor orangeColor) set))
(else ((NSColor blueColor) set)))
(NSBezierPath fillRect:cellFrame)
(NSBezierPath setDefaultLineWidth:3)
((NSColor whiteColor) set)
(NSBezierPath strokeRect:cellFrame)
(set p ((NSBezierPath alloc) init))
(p setLineWidth:3.0)
(p setLineCapStyle:NSSquareLineCapStyle)
(set xRect (NSInsetRect cellFrame 9 7))
(p moveToPoint:(list (xRect first) (xRect second)))
(p lineToPoint:(list (+ (xRect first) (xRect third)) (+ (xRect second) (xRect fourth))))
(p moveToPoint:(list (xRect first) (+ (xRect second) (xRect fourth))))
(p lineToPoint:(list (+ (xRect first) (xRect third)) (xRect second)))
((NSColor whiteColor) set)
(p stroke))))
;; @class PackerView
;; @discussion This class provides a view of a PagePacker document.
(class PackerView
(ivar (id) packModel
(id) foldLines
(id) cutLine
(NSRect) imageablePageRect
(BOOL) showsImageableRect
(int) dropPage
(int) dragStart)
(set