%! % Animator window % By Don Hopkins, University of Maryland Human Computer Interaction Lab. % % This is a partially completed animator tool. % There's room to add all kinds of weird functionality. % Go for it! % % Copyright (C) 1988 by Don Hopkins. All rights reserved. % This program is provided for unrestricted use, provided that this % copyright message is preserved. There is no warranty, and no author % or distributer accepts responsibility for any damage caused by this % program. % systemdict begin systemdict /Item known not {(NeWS/liteitem.ps) LoadFile pop} if systemdict /PieMenu known not {(NeWS/piemenu.ps) LoadFile pop} if /Scrollodexbar SimpleScrollbar dictbegin /StartX null def /StartY null def /DotX null def /DotY null def /NumbRadius 6 def /SliceWidth 10 def dictend classbegin % Bug: EraseBox used to try to call BoxPath with IPV of null /EraseBox { % - => - (fill painted box with background color) ItemPaintedValue null ne { ItemPaintedValue BoxPath ItemFillColor setcolor fill } if } def /SetScrollMotion { % - => - (set ScrollMotion from event location) CurrentEvent /Name get MenuButton eq { /ScrollMotion /Scrollodex def CurrentEvent begin /StartX XLocation /StartY YLocation end def def } { CurrentEvent /YLocation get % y dup ButtonSize le { /ScrollMotion /ScrollLineBackward def } { dup ItemHeight ButtonSize sub ge { /ScrollMotion /ScrollLineForward def } { ItemPaintedValue ValueToY % y yPainted 2 copy le { /ScrollMotion /ScrollPageBackward def } { 2 copy BoxSize add ge { /ScrollMotion /ScrollPageForward def } { /ScrollMotion /ScrollAbsolute def } ifelse % 2 copy BoxSize add ge } ifelse % 2 copy le pop % pop yPainted } ifelse % dup ItemHeight ButtonSize sub ge } ifelse % dup ButtonSize le pop % pop y } ifelse } def /ClientDown { % - => - SetScrollMotion CurrentEvent begin gsave fboverlay setcanvas /DotX XLocation /DotY YLocation grestore end def def DoScroll } def /ClientUp { % - => - ItemValue ItemInitialValue ne {NotifyUser} if ScrollMotion /Scrollodex eq { gsave fboverlay setcanvas erasepage grestore } if } def /ClientDrag { % - => - ScrollMotion dup /ScrollAbsolute eq exch /Scrollodex eq or {DoScroll} if } def /DoScroll { % - => - SetScrollValue ItemValue ItemPaintedValue ne { EraseBox PaintBox } if ScrollMotion /Scrollodex eq { gsave fboverlay setcanvas erasepage newpath DotX DotY NumbRadius 0 360 arc closepath 0 setgray fill DotX DotY moveto CurrentEvent begin XLocation YLocation end lineto stroke grestore } if } def /SetScrollValueDict 10 dict dup begin /Scrollodex {CurrentEvent ScrollodexValue} def /ScrollAbsolute {CurrentEvent /YLocation get YToValue} def /ScrollLineForward {ItemValue BarLineValue add} def /ScrollLineBackward {ItemValue BarLineValue sub} def /ScrollPageForward {ItemValue BarPageValue add} def /ScrollPageBackward {ItemValue BarPageValue sub} def end def /ScrollodexValue { % event => value 10 dict begin begin /X XLocation StartX sub /Y YLocation StartY sub end def def X dup mul Y dup mul add sqrt NumbRadius le { ItemValue } { X abs Y neg atan SliceWidth sub 180 SliceWidth dup add sub div BarMax BarMin sub mul BarMin add } ifelse end } def % faster than setvalue /updatevalue { % value => - dup ItemValue ne { gsave /ItemValue exch def ItemCanvas setcanvas EraseBox PaintBox grestore } {pop} ifelse } def /updaterange { % [min max dLine dPg dView] => - gsave ItemCanvas setcanvas EraseBox /ItemPaintedValue null def setrange PaintBox grestore } def classend def /Animator ScrollWindow dictbegin /Mag 1 def /XOffset 0 def /YOffset 0 def /Pages [] def /NewCan null def /ParentCan null def /SourceCan null def /FlipProcess null def /MaxFlipSleep 1 def /FlipSleep MaxFlipSleep def /SavedFlipSleep MaxFlipSleep def /ThisPage null def /ReverseTime false def /FrameLabel (Animator) def /IconImage /artist def /PageNumbers null def /DragX null def /DragY null def dictend classbegin /createscrollbars { /HScrollbar [MaxFlipSleep 0 .01 .1 null] MaxFlipSleep {/hscroll-notify ThisWindow send} FrameCanvas /new Scrollodexbar send dup /ClientDrag { /ClientDrag ParentDict supersend NotifyUser } put dup /BarVertical? false put def /VScrollbar [0 1 .01 .1 null] 0 {/vscroll-notify ThisWindow send} FrameCanvas /new Scrollodexbar send dup /ClientDrag { /ClientDrag ParentDict supersend NotifyUser } put def } def /vscroll-notify { Pages length 0 ne { VScrollbar /ItemValue get floor 0 max Pages length 1 sub min change-page } if } def /hscroll-notify { FlipProcess null ne { FlipProcess killprocess } if /FlipSleep HScrollbar /ItemValue get def FlipSleep MaxFlipSleep lt { /FlipProcess { { FlipSleep 60 div sleep flip-page } loop } fork def } if } def /change-page { % n => - Pages length 0 eq { /ThisPage null def } if dup ThisPage eq {pop} { /ThisPage exch def % paint-this-page } ifelse } def /update-vscroller { FlipSleep 0 ne { ThisPage /updatevalue VScrollbar send } if } def /clip-page {} def /image-page { imagecanvas } def /flash-image-cursor { % can => - pop 5 setrasteropcode 0 0 1 1 rectpath gsave fill newpath .5 .5 .5 0 360 arc closepath gsave fill grestore fill grestore fill } def /begin-this-page { gsave Pages ThisPage get begin can setcanvas clippath pathbbox points2rect ClientCanvas setcanvas XOffset YOffset translate scale pop pop Mag 1 ne { Mag dup scale } if } def /end-this-page { end grestore } def /paint-overlay { segments length 0 ne { 5 setrasteropcode 0 setlinewidth newpath segments { exec } forall closepath fill } if } def /paint-this-page { ThisPage null eq { gsave ClientCanvas setcanvas erasepage grestore } { begin-this-page clip-page can image-page paint-overlay end-this-page } ifelse } def /update-last-page { ThisPage Pages length 1 sub eq { paint-this-page } if } def /flip-page { Pages length 0 ne { ReverseTime { ThisPage 1 sub dup 0 lt { pop Pages length 1 sub } if } { ThisPage 1 add dup Pages length ge { pop 0 } if } ifelse change-page update-vscroller } if } def /new-page { % - => can gsave /NewCan ClientCanvas newcanvas def NewCan /Transparent false put NewCan /Retained true put ClientCanvas setcanvas clippath NewCan reshapecanvas NewCan dup add-page grestore } def /copy-page { % source => - gsave /SourceCan exch def new-page setcanvas clippath pathbbox points2rect 4 -2 roll translate scale 5 { pause } repeat SourceCan imagecanvas 5 { pause } repeat /SourceCan null def % some day it might refresh from these on resize... update-last-page grestore } def /update-scrollbar { Pages length dup 0 ne { VScrollbar /ItemValue ThisPage put [exch 1 sub 1 max 0 1 8 1 Pages length div] /updaterange VScrollbar send } { pop } ifelse } def /page-dict-size 64 def /add-page { % can => - page-dict-size dict begin /can exch def % For mapping from canvas => page# PageNumbers can Pages length put /segments [] def currentdict end /Pages [ Pages aload pop counttomark 3 add -1 roll ] def Pages length 1 eq { /ThisPage 0 def } if ThisPage Pages length 2 sub eq ReverseTime not and { /ThisPage Pages length 1 sub def } if update-scrollbar } def /new { /new super send begin /ZoomMenu [ (Big) {PieDistance PieRadius le /zoom-big ThisWindow send} (Reset) {/zoom-reset ThisWindow send} (Small) {PieDistance PieRadius le /zoom-small ThisWindow send} (Window) {/zoom-window ThisWindow send} ] /new PieMenu send def /ClipMenu [ (Time Shreds) {ThisWindow /clip-page {time-shreds} put} (Square) {ThisWindow /clip-page {square-clip} put} (Circle) {ThisWindow /clip-page {circle-clip} put} (Time Blobs) {ThisWindow /clip-page {time-blobs} put} (None) {ThisWindow /clip-page {} put} (Shape) {ThisWindow /clip-page {shape-clip} put} ] /new PieMenu send def /ResetMenu [ (Zoom) {/zoom-reset ThisWindow send} (All) {/all-reset ThisWindow send} (Pan) {/pan-reset ThisWindow send} (Flip) {/flip-reset ThisWindow send} ] /new PieMenu send def /RenderMenu [ (Image) {ThisWindow /image-page {imagecanvas} put} (White) {ThisWindow /image-page {1 setgray true exch imagemaskcanvas} put} (Nothing) {ThisWindow /image-page {flash-image-cursor} put} (Black) {ThisWindow /image-page {0 setgray false exch imagemaskcanvas} put} ] /new PieMenu send def /EraseMenu [ (White) {/erase-to-white ThisWindow send} (Black) {/erase-to-black ThisWindow send} ] /new PieMenu send def EraseMenu /PieInitialAngle 0 put /MoreMenu [ (Clip...) ClipMenu (Reset...) ResetMenu (Render...) RenderMenu (Erase...) EraseMenu ] /new PieMenu send def /ToolMenu [ (Shape) { ThisWindow /page-point {add-segment} put ThisWindow /page-adjust {delete-segment} put } (Pan) { ThisWindow /page-point {drag-image} put ThisWindow /page-adjust {move-image} put } ] /new PieMenu send def /FlipMenu [ (Reverse) {ThisWindow /ReverseTime true put} (Start) {/start-flip ThisWindow send} (Forward) {ThisWindow /ReverseTime false put} (Stop) {/stop-flip ThisWindow send} ] /new PieMenu send def /ClientMenu [ (Zoom...) ZoomMenu (More...) MoreMenu (Tool...) ToolMenu (Flip...) FlipMenu ] /new PieMenu send def /PageNumbers 512 dict def currentdict end } def /set-zoom { .001 max 100 min dup 1 sub abs .01 lt {pop 1} if /Mag exch def } def /zoom-big { % bool => - { Mag 1.1 mul } { Mag 2 mul } ifelse set-zoom % paint-this-page } def /zoom-small { % bool => - { Mag .9 mul } { Mag .5 mul } ifelse set-zoom % paint-this-page } def /zoom-window { % **** WRITE ME % Scale the image to fit in a (ClientWidth ClientHeight min) square } def /zoom-reset { /Mag 1 def % paint-this-page } def /erase-to-white { gsave ClientCanvas setcanvas 1 fillcanvas grestore } def /erase-to-black { gsave ClientCanvas setcanvas 0 fillcanvas grestore } def /all-reset { /Mag 1 def /XOffset 0 def /YOffset 0 def /This-Page 0 def flip-reset paint-this-page } def /pan-reset { /XOffset 0 def /YOffset 0 def paint-this-page } def /flip-reset { stop-flip 0 change-page update-vscroller } def /set-flip-sleep { /updatevalue HScrollbar send hscroll-notify } def /stop-flip { MaxFlipSleep set-flip-sleep } def /start-flip { 0 set-flip-sleep } def /flipiconic { % - => - /flipiconic super send Iconic? { /SavedFlipSleep FlipSleep def stop-flip } { SavedFlipSleep set-flip-sleep } ifelse } def /destroy { unmap /Pages null def /destroy super send } def /CreateFrameInterests { /CreateFrameInterests super send FrameInterests begin /PagePointEvent PointButton /page-point DownTransition ClientCanvas eventmgrinterest def /PageAdjustEvent AdjustButton /page-adjust DownTransition ClientCanvas eventmgrinterest def end } def /page-point {drag-image} def /page-adjust {move-image} def /move-image { 10 dict begin /image-page {flash-image-cursor} def drag-image end } def /drag-image { gsave ClientCanvas setcanvas CurrentEvent begin /DragX XLocation XOffset sub /DragY YLocation YOffset sub end store store [ [PointButton AdjustButton MenuButton] /drag-image-finish [UpTransition DownTransition] null eventmgrinterest dup /Exclusivity true put MouseDragged /drag-image-move null null eventmgrinterest ] forkeventmgr pop grestore } def /drag-image-move { begin-this-page paint-overlay end-this-page CurrentEvent begin /XOffset XLocation DragX sub /YOffset YLocation DragY sub end store store paint-this-page } def /drag-image-finish { drag-image-move currentprocess killprocess } def /PaintClient { paint-this-page } def % Page clipping functions /circle-clip { newpath .5 .5 .5 0 360 arc closepath clip } def /square-clip { 0 0 1 1 rectpath clip } def /time-shreds { newpath 5 { random random % x y random dup add 1 sub % x y w random dup add 1 sub % x y w h rectpath % } repeat eoclip } def /time-blobs { newpath 2 { random random random % x y r 0 360 arc closepath } repeat eoclip } def % page point and adjust functions /add-segment { begin-this-page paint-overlay /segments [ segments aload pop dup mark eq { [ CurrentEvent begin XLocation YLocation end /moveto cvx ] cvx } { [ CurrentEvent begin XLocation YLocation end /lineto cvx ] cvx } ifelse ] def paint-overlay end-this-page } def /delete-segment { Pages ThisPage get /segments get length 0 ne { begin-this-page paint-overlay /segments [ segments aload pop pop ] def paint-overlay end-this-page } if } def /shape-clip { segments length 0 ne { newpath segments { exec } forall closepath clip } if } def classend def /CamWindow Animator def /anim { /Win framebuffer /new Animator send def /reshapefromuser Win send /map Win send /grab { 20 { pause } repeat currentfile readcanvas /copy-page Win send } def } def /cam /anim load def end % systemdict