if { [catch {package require MuPDF} ] } {
  # retry 
  lappend auto_path ../../XBUILD
  package require MuPDF
}

catch {console show}
 # side effect: update g(currPageNum), g(currPdfPage)
proc nextPage {} {
	global g
	if { $g(currPageNum) < $g(lastPageNum) } {
		incr g(currPageNum)
		set g(currPdfPage) [$g(pdf) getpage $g(currPageNum)] 
		drawPageWithClipping $g(pdfWidget) $g(currPdfPage) $g(zoom)
	}
}

 # side effect: update g(currPageNum), g(currPdfPage)
proc prevPage {} {
	global g
	if { $g(currPageNum) > 0 } {
		incr g(currPageNum) -1 
		set g(currPdfPage) [$g(pdf) getpage $g(currPageNum)] 
		drawPageWithClipping $g(pdfWidget) $g(currPdfPage) $g(zoom)	
	}
}

 # side effect: update g(zoom)
proc incrZoom {} {
	global g
	if { $g(zoom) < 4.0 } { 
		set g(zoom) [expr $g(zoom) + 0.1]
		drawPageWithClipping $g(pdfWidget) $g(currPdfPage) $g(zoom)	
	}
}

 # side effect: update g(zoom)
proc decrZoom {} {
	global g
	if { $g(zoom) > 0.2 } { 
		set g(zoom) [expr $g(zoom) - 0.1]
		drawPageWithClipping $g(pdfWidget) $g(currPdfPage) $g(zoom)	
	}
}


 # side effect: update g(prev.clipPageDX) g(prev.clipPageDY)
proc redrawIfNeeded {w pdfPage zoom } {
	global g

    set wp [winfo parent $w]
	set WX [winfo width $wp]
	set WY [winfo height $wp]
	lassign [bestClip $WX $WY $zoom $pdfPage] dx dy
		
	if { $dx > $g(prev.clipPageDX) ||  $dy > $g(prev.clipPageDY) } {
	  drawPage $w $pdfPage $zoom $dx $dy
	}
}


set g(pdfWidget) .page

 # just a bare GUI - a label containing an image "imagePage"
image create photo imagePage
label $g(pdfWidget) -image imagePage -anchor nw -padx 5 -pady 5  -bg orange
label .info1 -text "Change Page:  Press Up / Down keys" -relief groove
label .info2 -text "Zoom :  Press  <+> / <->" -relief groove

pack .info1 -fill x -padx 2 -pady 2 -side bottom
pack .info2 -fill x -padx 2 -pady 2 -side bottom
pack $g(pdfWidget) -expand 1 ;# -fill both

wm geometry . 500x700
update


bind $g(pdfWidget) <Key-Up> 	{ prevPage }
bind $g(pdfWidget) <Key-Down>	{ nextPage }

bind $g(pdfWidget) <Key-plus>	{ incrZoom }
bind $g(pdfWidget) <Key-minus>	{ decrZoom }


 # Given a window of (WX,WY) pixels, and a pdfPage
 # return the dimension of the portion of the pdfPage (in points),
 # that, when zoomed, will fit the window
proc bestClip { WX WY zoom pdfPage } {
	lassign [$pdfPage size] wx wy ;# in points
	#set dx [expr {min($WX,$zoom*$wx)/$zoom}]
	#set dy [expr {min($WY,$zoom*$wy)/$zoom}]
	set dx [expr {min($WX/$zoom,$wx)}]
	set dy [expr {min($WY/$zoom,$wy)}]

	list $dx $dy
}

proc drawPageWithClipping { w pdfPage zoom } {
set wp [winfo parent $w]
	set WX [winfo width $wp]
	set WY [winfo height $wp]
	lassign [bestClip $WX $WY $zoom $pdfPage] dx dy
	drawPage $w $pdfPage $zoom $dx $dy
}


 # side effect: update g(prev.clipPageDX) g(prev.clipPageDY)
proc drawPage { w pdfPage zoom dx dy } {
	 global g

	  # recreate an empty image ..
     set image [$w cget -image]
	 image create photo $image
     $pdfPage saveImage $image -zoom $zoom -from 0 0 $dx $dy
     set g(prev.clipPageDX) $dx
     set g(prev.clipPageDY) $dy
     
     # just for testing
##     lassign [$pdfPage size] PX PY
##     puts "draw $dx x $dy (points) - [format "%.2f%% x %.2f%%" [expr {100.0*$dx/$PX}]  [expr {100.0*$dy/$PY}]]"
}

 # ---

set pdfFileName [tk_getOpenFile -filetypes {{Pdf .pdf}}  -title "Choose a Pdf .."]

set g(pdf) [mupdf::open $pdfFileName]

set g(lastPageNum) [expr [$g(pdf) npages]-1]
set g(zoom) 1.0

set g(prev.clipPageDX) -1
set g(prev.clipPageDY) -1
set g(currPageNum) -1
nextPage  ;# this will draw page 0

focus $g(pdfWidget)


bind  $g(pdfWidget) <Configure> {
	redrawIfNeeded %W $g(currPdfPage) $g(zoom)
}
