module Graphics.UI.WXCore.Print(
pageSetupDialog
, pageSetupShowModal
, printDialog
, printPreview
, PageFunction
, PrintFunction
, PageInfo(..)
, PrintInfo(..)
, pageSetupDataGetPageInfo, pageSetupDataSetPageInfo
, printOutGetPrintInfo
, pageSetupDialogGetFrame
) where
import Graphics.UI.WXCore.WxcClasses
import Graphics.UI.WXCore.WxcClassInfo
import Graphics.UI.WXCore.Types
import Graphics.UI.WXCore.Events
import Graphics.UI.WXCore.Frame
type PageFunction = PageInfo -> PrintInfo -> Size -> (Int,Int)
type PrintFunction = PageInfo -> PrintInfo -> Size -> DC () -> Int -> IO ()
onPrint :: Bool
-> PageInfo -> Printout (CWXCPrintout a)
-> PageFunction
-> PrintFunction
-> EventPrint -> IO ()
onPrint isPreview pageInfo printOut pageRangeFunction printFunction ev
= case ev of
PrintPrepare ->
printOutInitPageRange printOut pageInfo pageRangeFunction >>
return ()
PrintPage _cancel dc n ->
do{ printInfo <- printOutGetPrintInfo printOut
; let io info size = printFunction pageInfo info size dc n
; if isPreview
then do let previewInfo = toScreenInfo printInfo
(scaleX,scaleY) <- getPreviewZoom pageInfo previewInfo dc
dcScale dc scaleX scaleY (respectMargin pageInfo previewInfo dc (io previewInfo))
else respectMargin pageInfo printInfo dc (io printInfo)
}
_ -> return ()
respectMargin :: PageInfo -> PrintInfo -> DC a -> (Size -> IO b) -> IO b
respectMargin pageInfo printInfo dc io
= do let ((left,top),printSize) = printableArea pageInfo printInfo
scaleX <- dcGetUserScaleX dc
scaleY <- dcGetUserScaleY dc
dcSetDeviceOrigin dc (pt (round (scaleX*left)) (round (scaleY*top)))
dcSetClippingRegion dc (rect (pt 0 0) printSize)
io printSize
printableArea :: PageInfo -> PrintInfo -> ((Double,Double),Size)
printableArea pageInfo printInfo
= let (printW,printH) = pixelToMM (printerPPI printInfo) (printPageSize printInfo)
(ppmmW,ppmmH) = ppiToPPMM (printerPPI printInfo)
minX = (toDouble (sizeW (pageSize pageInfo)) printW)/2
minY = (toDouble (sizeH (pageSize pageInfo)) printH)/2
top = ppmmH * (max minY (toDouble $ rectTop $ pageArea pageInfo))
left = ppmmW * (max minX (toDouble $ rectLeft $ pageArea pageInfo))
(Point mright mbottom)
= pointSub (pointFromSize (pageSize pageInfo)) (rectBottomRight (pageArea pageInfo))
bottom= ppmmH * (max minY (toDouble mbottom))
right = ppmmW * (max minX (toDouble mright))
dw = round (right + left)
dh = round (bottom + top)
(dw', dh') = if sizeW (printPageSize printInfo) < sizeH (printPageSize printInfo)
then (dw, dh)
else (dh, dw)
printSize = sz (sizeW (printPageSize printInfo) dw')
(sizeH (printPageSize printInfo) dh')
in ((left,top),printSize)
getPreviewZoom :: PageInfo -> PrintInfo -> DC a -> IO (Double,Double)
getPreviewZoom _pageInfo printInfo dc
= do size <- dcGetSize dc
let (printW,printH) = pixelToMM (printerPPI printInfo) (printPageSize printInfo)
(screenW,screenH) = pixelToMM (screenPPI printInfo) size
scaleX = screenW / printW
scaleY = screenH / printH
return (scaleX,scaleY)
toScreenInfo :: PrintInfo -> PrintInfo
toScreenInfo printInfo
= let scaleX = (toDouble (sizeW (screenPPI printInfo))) / (toDouble (sizeW (printerPPI printInfo)))
scaleY = (toDouble (sizeH (screenPPI printInfo))) / (toDouble (sizeH (printerPPI printInfo)))
pxX = round (scaleX * (toDouble (sizeW (printPageSize printInfo))))
pxY = round (scaleY * (toDouble (sizeH (printPageSize printInfo))))
in printInfo{ printerPPI = screenPPI printInfo
, printPageSize = sz pxX pxY
}
pixelToMM :: Size -> Size -> (Double,Double)
pixelToMM ppi size
= let convert f = toDouble (f size) / (toDouble (f ppi) / 25.4)
in (convert sizeW, convert sizeH)
ppiToPPMM :: Size -> (Double,Double)
ppiToPPMM ppi
= let convert f = toDouble (f ppi) / 25.4
in (convert sizeW, convert sizeH)
toDouble :: Int -> Double
toDouble i = fromIntegral i
dcScale :: DC a -> Double -> Double -> IO b -> IO b
dcScale dc scaleX scaleY io
= do oldX <- dcGetUserScaleX dc
oldY <- dcGetUserScaleY dc
dcSetUserScale dc (oldX*scaleX) (oldY*scaleY)
x <- io
dcSetUserScale dc oldX oldY
return x
printDialog :: PageSetupDialog a
-> String
-> PageFunction
-> PrintFunction
-> IO ()
printDialog pageSetupDialog' title pageRangeFunction printFunction =
do{ pageSetupData <- pageSetupDialogGetPageSetupData pageSetupDialog'
; printData <- pageSetupDialogDataGetPrintData pageSetupData
; printDialogData <- printDialogDataCreateFromData printData
; printDialogDataSetAllPages printDialogData True
; printer <- printerCreate printDialogData
; printout <- wxcPrintoutCreate title
; pageInfo <- pageSetupDataGetPageInfo pageSetupData
; _ <- printOutInitPageRange printout pageInfo pageRangeFunction
; printOutOnPrint printout (onPrint False pageInfo printout pageRangeFunction printFunction)
; frame <- pageSetupDialogGetFrame pageSetupDialog'
; _ <- printerPrint printer frame printout True
; objectDelete printDialogData
; objectDelete printout
; objectDelete printer
}
printPreview :: PageSetupDialog a
-> String
-> PageFunction
-> PrintFunction
-> IO ()
printPreview pageSetupDialog' title pageRangeFunction printFunction =
do{ pageSetupData <- pageSetupDialogGetPageSetupData pageSetupDialog'
; pageInfo <- pageSetupDataGetPageInfo pageSetupData
; printout1 <- wxcPrintoutCreate "Print to preview"
; printout2 <- wxcPrintoutCreate "Print to printer"
; startPage <- printOutInitPageRange printout1 pageInfo pageRangeFunction
; _ <- printOutInitPageRange printout2 pageInfo pageRangeFunction
; printOutOnPrint printout1 (onPrint True pageInfo printout1 pageRangeFunction printFunction)
; printOutOnPrint printout2 (onPrint False pageInfo printout2 pageRangeFunction printFunction)
; printData <- pageSetupDialogDataGetPrintData pageSetupData
; printDialogData <- printDialogDataCreateFromData printData
; printDialogDataSetAllPages printDialogData True
; preview <- printPreviewCreateFromDialogData printout1 printout2 printDialogData
; _ <- printPreviewSetCurrentPage preview startPage
; frame <- pageSetupDialogGetFrame pageSetupDialog'
; previewFrame <- previewFrameCreate preview frame title rectNull frameDefaultStyle title
; previewFrameInitialize previewFrame
; _ <- windowShow previewFrame
; windowRaise previewFrame
}
printOutInitPageRange :: WXCPrintout a -> PageInfo -> PageFunction -> IO Int
printOutInitPageRange printOut pageInfo pageRangeFunction
= do{ printInfo <- printOutGetPrintInfo printOut
; let (_,size) = printableArea pageInfo printInfo
(start,end) = pageRangeFunction pageInfo printInfo size
; wxcPrintoutSetPageLimits printOut start end start end
; return start
}
pageSetupDialogGetFrame :: PageSetupDialog a -> IO (Frame ())
pageSetupDialogGetFrame pageSetupDialog'
= do p <- windowGetParent pageSetupDialog'
case (safeCast p classFrame) of
Just frame -> return frame
Nothing -> do w <- wxcAppGetTopWindow
case (safeCast w classFrame) of
Just frame -> return frame
Nothing -> error "pageSetupDialogGetFrame: no parent frame found!"
pageSetupDialog :: Frame a -> Int -> IO (PageSetupDialog ())
pageSetupDialog f margin
= do pageSetupData <- pageSetupDialogDataCreate
if (margin > 0)
then do pageInfo <- pageSetupDataGetPageInfo pageSetupData
let p0 = pt margin margin
p1 = pointSub (pointFromSize (pageSize pageInfo)) p0
newInfo = pageInfo{ pageArea = rectBetween p0 p1 }
pageSetupDataSetPageInfo pageSetupData newInfo
else return ()
pageSetupDialog' <- pageSetupDialogCreate f pageSetupData
prev <- windowGetOnClose f
windowOnClose f (do{ objectDelete pageSetupDialog'; prev })
objectDelete pageSetupData
return pageSetupDialog'
pageSetupShowModal :: PageSetupDialog a -> IO ()
pageSetupShowModal p
= dialogShowModal p >> return ()
data PageInfo = PageInfo{ pageSize :: Size
, pageArea :: Rect
}
deriving Show
pageSetupDataGetPageInfo :: PageSetupDialogData a -> IO PageInfo
pageSetupDataGetPageInfo pageSetupData
= do{ topLeft <- pageSetupDialogDataGetMarginTopLeft pageSetupData
; bottomRight <- pageSetupDialogDataGetMarginBottomRight pageSetupData
; paperSize <- pageSetupDialogDataGetPaperSize pageSetupData
; return (PageInfo
{ pageSize = paperSize
, pageArea = rectBetween topLeft (pointSub (pointFromSize paperSize) bottomRight)
})
}
pageSetupDataSetPageInfo :: PageSetupDialogData a -> PageInfo -> IO ()
pageSetupDataSetPageInfo pageSetupData pageInfo
= do{ let topLeft = rectTopLeft (pageArea pageInfo)
bottomRight = pointSub (pointFromSize (pageSize pageInfo)) (rectBottomRight (pageArea pageInfo))
; pageSetupDialogDataSetMarginTopLeft pageSetupData topLeft
; pageSetupDialogDataSetMarginBottomRight pageSetupData bottomRight
; pageSetupDialogDataSetPaperSize pageSetupData (pageSize pageInfo)
}
data PrintInfo = PrintInfo { screenPPI :: Size
, printerPPI :: Size
, printPageSize :: Size
} deriving Show
printOutGetPrintInfo :: Printout a -> IO PrintInfo
printOutGetPrintInfo printOut
= do{ thePrinterPPI <- printoutGetPPIPrinter printOut
; theScreenPPI <- printoutGetPPIScreen printOut
; thePageSizePixels <- printoutGetPageSizePixels printOut
; return (PrintInfo
{ printerPPI = sizeFromPoint thePrinterPPI
, screenPPI = sizeFromPoint theScreenPPI
, printPageSize = thePageSizePixels
})
}