module Language.LaTeX.Builder.Beamer
where
import Language.LaTeX.Builder.MonoidUtils
import Language.LaTeX.Types
import qualified Language.LaTeX.Builder.Internal as BI
import qualified Language.LaTeX.Builder as B
import Language.LaTeX.Builder.QQ
import Control.Applicative
import Data.List (intersperse)
import Data.Maybe
import Data.Monoid
data DocClassOption = Compress
| T
| Red
| Handout
| RawDocClassOption String
compress, t, red, handout :: DocClassOption
compress = Compress
t = T
red = Red
handout = Handout
rawDocClassOption :: String -> DocClassOption
rawDocClassOption = RawDocClassOption
showDocClassOption :: DocClassOption -> String
showDocClassOption Compress = "compress"
showDocClassOption T = "t"
showDocClassOption Red = "red"
showDocClassOption Handout = "handout"
showDocClassOption (RawDocClassOption x) = x
documentclasskind :: DocumentClassKind
documentclasskind = OtherDocumentClassKind "beamer"
beamer :: Maybe LatexLength -> [DocClassOption] -> [AnyItem] -> DocumentClass
beamer msize opts
= B.documentclass documentclasskind
. (maybeToList (BI.texLength <$> msize) ++)
. (map (BI.rawAnyTex . showDocClassOption) opts ++)
type TargetName = String
type Label = String
labelArg :: Label -> Arg AnyItem
labelArg = BI.mandatoryLatexItem . BI.rawTex
targetArg :: TargetName -> Arg AnyItem
targetArg = BI.mandatoryLatexItem . BI.rawTex
data FrameOpt = Label Label
| Fragile
| OtherOption String String
deriving (Eq,Ord)
data OverlayInt = OvInt Int
| OvPlus
| OvPlusOffset Int
| OvDot
deriving (Eq,Ord)
data Overlay = OvSingle OverlayInt
| OvFromTo OverlayInt OverlayInt
| OvFrom OverlayInt
deriving (Eq,Ord)
type Overlays = [Overlay]
type BeamerOpt = (String, String)
texFrameOpt :: FrameOpt -> BeamerOpt
texFrameOpt (Label lbl) = ("label",lbl)
texFrameOpt Fragile = ("fragile","")
texFrameOpt (OtherOption a b) = (a,b)
texFrameOpts :: [FrameOpt] -> Arg AnyItem
texFrameOpts = beamerOpts . map texFrameOpt
showOvInt :: OverlayInt -> ShowS
showOvInt (OvInt i) = shows i
showOvInt OvPlus = ('+':)
showOvInt OvDot = ('.':)
showOvInt (OvPlusOffset off) = ('+':) . ('(':) . shows off . (')':)
showOverlay :: Overlay -> ShowS
showOverlay (OvSingle i) = showOvInt i
showOverlay (OvFromTo i j) = showOvInt i . ('-':) . showOvInt j
showOverlay (OvFrom i) = showOvInt i . ('-':)
showOverlays :: Overlays -> Maybe String
showOverlays [] = Nothing
showOverlays ovs = Just . ('<':) . (++">") . showsOv ovs $ []
where
showsOv :: Overlays -> ShowS
showsOv = mconcat . intersperse (',':) . map showOverlay
texOverlaysOpt :: Overlays -> Maybe LatexItem
texOverlaysOpt = fmap BI.rawTex . showOverlays
texOverlaysArg :: Overlays -> Arg a
texOverlaysArg = maybe BI.noArg BI.rawArg . showOverlays
texOverlaysOptArg :: Overlays -> Arg AnyItem
texOverlaysOptArg = maybe BI.noArg (BI.optionalLatexItem . BI.rawTex) . showOverlays
label :: Label -> FrameOpt
label = Label
frame :: Overlays -> Overlays -> [FrameOpt] -> LatexItem -> LatexItem -> ParItem -> ParItem
frame ov mov fopts title subtitle =
BI.parEnvironmentPar "frame" [ texOverlaysArg ov
, texOverlaysOptArg mov
, texFrameOpts fopts
] . (mapNonEmpty frametitle title ⊕)
. (mapNonEmpty framesubtitle subtitle ⊕)
frameO :: Overlays -> ParItem -> ParItem
frameO overlays = BI.parEnvironmentPar "frame" [texOverlaysOptArg overlays]
example :: ParItem -> ParItem
example = BI.parEnvironmentPar "example" []
theorem :: ParItem -> ParItem
theorem = BI.parEnvironmentPar "theorem" []
block :: LatexItem -> ParItem -> ParItem
block title = BI.parEnvironmentPar "block" [BI.mandatoryLatexItem title]
slide :: LatexItem -> ParItem -> ParItem
slide tit = frame [] [] [] tit ø
slideO :: LatexItem -> Overlays -> ParItem -> ParItem
slideO tit ovs body = frameO ovs (frametitle tit ⊕ body)
frametitle :: LatexItem -> ParItem
frametitle = BI.parCmdArg "frametitle" . BI.latexItem
framesubtitle :: LatexItem -> ParItem
framesubtitle = BI.parCmdArg "framesubtitle" . BI.latexItem
ovFrom :: OverlayInt -> Overlay
ovFrom = OvFrom
ovFromTo :: OverlayInt -> OverlayInt -> Overlay
ovFromTo = OvFromTo
ovSingle :: OverlayInt -> Overlay
ovSingle = OvSingle
ovInt :: Int -> OverlayInt
ovInt i | i > 0 = OvInt i
| otherwise = error "ovInt: strictly positive Int expected"
ovPlus :: OverlayInt
ovPlus = OvPlus
ovDot :: OverlayInt
ovDot = OvDot
ovIncr :: Overlays
ovIncr = [ovFrom ovPlus]
ovInts :: [Int] -> Overlays
ovInts = map (ovSingle . ovInt)
alert :: LatexItem -> LatexItem
alert = BI.latexCmdArg "alert"
itemize :: Overlays -> [ListItem] -> ParItem
itemize = B.itemize . texOverlaysOpt
enumerate :: Overlays -> [ListItem] -> ParItem
enumerate = B.enumerate . texOverlaysOpt
description :: Overlays -> [ListItem] -> ParItem
description = B.description . texOverlaysOpt
pause :: LatexItem
pause = BI.texCmdNoArg "pause"
pause' :: Maybe Int -> LatexItem
pause' = BI.latexCmdArgs "pause" . maybeToList . fmap (BI.optional . BI.rawTex . show)
only :: Overlays -> LatexItem -> LatexItem
only ov arg = BI.latexCmdArgs "only" [texOverlaysArg ov, BI.mandatory arg]
uncover :: Overlays -> LatexItem -> LatexItem
uncover ov arg = BI.latexCmdArgs "uncover" [texOverlaysArg ov, BI.mandatory arg]
visible :: Overlays -> LatexItem -> LatexItem
visible ov arg = BI.latexCmdArgs "visible" [texOverlaysArg ov, BI.mandatory arg]
invisible :: Overlays -> LatexItem -> LatexItem
invisible ov arg = BI.latexCmdArgs "invisible" [texOverlaysArg ov, BI.mandatory arg]
alt :: Overlays -> LatexItem -> LatexItem -> LatexItem
alt ov arg1 arg2 = BI.latexCmdArgs "alt" [texOverlaysArg ov, BI.mandatory arg1, BI.mandatory arg2]
temporal :: Overlays -> LatexItem -> LatexItem -> LatexItem -> LatexItem
temporal ov arg1 arg2 arg3
= BI.latexCmdArgs "temporal" [ texOverlaysArg ov
, BI.mandatory arg1
, BI.mandatory arg2
, BI.mandatory arg3
]
visibleenv :: Overlays -> ParItem -> ParItem
visibleenv ov = BI.parEnvironmentPar "visibleenv" [texOverlaysArg ov]
invisibleenv :: Overlays -> ParItem -> ParItem
invisibleenv ov = BI.parEnvironmentPar "invisibleenv" [texOverlaysArg ov]
uncoverenv :: Overlays -> ParItem -> ParItem
uncoverenv ov = BI.parEnvironmentPar "uncoverenv" [texOverlaysArg ov]
onlyenv :: Overlays -> ParItem -> ParItem
onlyenv ov = BI.parEnvironmentPar "onlyenv" [texOverlaysArg ov]
altenv :: Overlays
-> LatexItem
-> LatexItem
-> LatexItem
-> LatexItem
-> ParItem
-> ParItem
altenv ov b e ab ae =
BI.parEnvironmentPar "altenv" [ texOverlaysArg ov
, BI.mandatoryLatexItem b
, BI.mandatoryLatexItem e
, BI.mandatoryLatexItem ab
, BI.mandatoryLatexItem ae
]
beamerOpts :: [BeamerOpt] -> Arg AnyItem
beamerOpts = BI.namedOpts . map f
where f (x,y) = Named x $ BI.rawAnyTex y
beamerPreambleCmdArgs :: String -> [BeamerOpt] -> LatexItem -> PreambleItem
beamerPreambleCmdArgs name opts arg = BI.preambleCmdArgs name [beamerOpts opts, BI.mandatoryLatexItem arg]
usetheme, usefonttheme, useinnertheme, useoutertheme,
usecolortheme :: [BeamerOpt] -> LatexItem -> PreambleItem
usetheme = beamerPreambleCmdArgs "usetheme"
usefonttheme = beamerPreambleCmdArgs "usefonttheme"
useinnertheme = beamerPreambleCmdArgs "useinnertheme"
useoutertheme = beamerPreambleCmdArgs "useoutertheme"
usecolortheme = beamerPreambleCmdArgs "usecolortheme"
beamerbutton :: LatexItem -> LatexItem
beamerbutton = BI.latexCmdArg "beamerbutton"
beamergotobutton :: LatexItem -> LatexItem
beamergotobutton = BI.latexCmdArg "beamergotobutton"
beamerskipbutton :: LatexItem -> LatexItem
beamerskipbutton = BI.latexCmdArg "beamerskipbutton"
beamerreturnbutton :: LatexItem -> LatexItem
beamerreturnbutton = BI.latexCmdArg "beamerreturnbutton"
hyperlink :: Overlays -> TargetName -> LatexItem -> Overlays -> LatexItem
hyperlink ov1 target linkText ov2 =
BI.latexCmdAnyArgs "hyperlink" [ texOverlaysArg ov1
, targetArg target
, BI.mandatoryLatexItem linkText
, texOverlaysArg ov2
]
againframe :: Overlays -> Overlays -> [FrameOpt] -> Label -> ParItem
againframe ov1 ov2 fopts lbl =
BI.parCmdArgs "againframe" [ texOverlaysArg ov1
, texOverlaysArg ov2
, texFrameOpts fopts
, labelArg lbl
]
beamertemplatenavigationsymbolsempty :: PreambleItem
beamertemplatenavigationsymbolsempty = BI.preambleCmdArgs "beamertemplatenavigationsymbolsempty" []
type TexDimension = LatexLength
data BeamerSize
= TextMarginLeft TexDimension
| TextMarginRight TexDimension
| SidebarWidthLeft TexDimension
| SidebarWidthRight TexDimension
| DescriptionWidth TexDimension
| DescriptionWidthOf LatexItem
| MiniFrameSize TexDimension
| MiniFrameOffset TexDimension
texBeamerSizeArg :: BeamerSize -> Arg AnyItem
texBeamerSizeArg bs = BI.namedArgs . pure $ case bs of
TextMarginLeft dim -> n "text margin left" $ BI.texLength dim
TextMarginRight dim -> n "text margin right" $ BI.texLength dim
SidebarWidthLeft dim -> n "sidebar width left" $ BI.texLength dim
SidebarWidthRight dim -> n "sidebar width right" $ BI.texLength dim
DescriptionWidth dim -> n "description width" $ BI.texLength dim
DescriptionWidthOf txt -> n "description width of" $ BI.latexItem txt
MiniFrameSize dim -> n "mini frame size" $ BI.texLength dim
MiniFrameOffset dim -> n "mini frame offset" $ BI.texLength dim
where n = Named
setbeamersize :: BeamerSize -> PreambleItem
setbeamersize = BI.preambleCmdArgs "setbeamersize" . pure . texBeamerSizeArg
appendix :: ParItem
appendix = BI.parCmdArgs "appendix" []
data Footline = Footline { authorPercent :: Percentage
, titlePercent :: Percentage
, datePercent :: Maybe Percentage
, showTotalFrames :: Bool }
defaultFootline :: Footline
defaultFootline = Footline { authorPercent = 34
, titlePercent = 36
, datePercent = Nothing
, showTotalFrames = True }
footline :: Footline -> PreambleItem
footline Footline{authorPercent=authorp,titlePercent=titlep,datePercent=maydatep,showTotalFrames=stf} =
let datep = fromMaybe (100 authorp titlep) maydatep
f (Percentage p) = BI.rawPreamble $ show p
maytotalframes = if stf then [qp| / \inserttotalframenumber|] else ø
in
[qp|
| \defbeamertemplate*{footline}{infolines theme without institution}
| {
| \leavevmode%
| \hbox{%
| \begin{beamercolorbox}[wd=.|] ⊕ f authorp ⊕ [qp|\paperwidth,ht=2.25ex,dp=1.125ex,center]{author in head/foot}%
| \usebeamerfont{author in head/foot}
| \insertshortauthor
| \end{beamercolorbox}%
| \begin{beamercolorbox}[wd=.|] ⊕ f titlep ⊕ [qp|\paperwidth,ht=2.25ex,dp=1.125ex,center]{title in head/foot}%
| \usebeamerfont{title in head/foot}
| \insertshorttitle
| \end{beamercolorbox}%
| \begin{beamercolorbox}[wd=.|] ⊕ f datep ⊕ [qp|\paperwidth,ht=2.25ex,dp=1.125ex,right]{date in head/foot}%
| \usebeamerfont{date in head/foot}
| \insertshortdate{}\hspace*{2em}
| \insertframenumber{}|] ⊕ maytotalframes ⊕ [qp|\hspace*{2ex}
| \end{beamercolorbox}}%
| \vskip0pt%
| }
|]