module TextViewport.Viewport.Viewport where import TextViewport.Render.RenderState (RenderState) import TextViewport.Render.RenderState qualified as RenderState data Viewport = Viewport { vpWidth :: !Int , vpHeight :: !Int , vpOffset :: !Int } deriving (Show) mkViewport :: Int -> Int -> RenderState -> Viewport mkViewport width height rs = alignBottom rs Viewport { vpWidth = width , vpHeight = height , vpOffset = 0 } -- any function that sets vpOffset and can overshoot should use clampViewport clampViewport :: RenderState -> Viewport -> Viewport clampViewport rs vp = let total = RenderState.rsLineCount rs maxOff = max 0 (total - vpHeight vp) off = vpOffset vp in vp { vpOffset = max 0 (min maxOff off) } scrollBy :: Int -> Viewport -> Viewport scrollBy delta vp = vp { vpOffset = vpOffset vp + delta } scrollUp :: Int -> Viewport -> Viewport scrollUp n = scrollBy (-n) scrollDown :: Int -> Viewport -> Viewport scrollDown n = scrollBy n pageUp :: Viewport -> Viewport pageUp vp = scrollBy (-(vpHeight vp)) vp pageDown :: Viewport -> Viewport pageDown vp = scrollBy (vpHeight vp) vp alignTop :: Viewport -> Viewport alignTop vp = vp { vpOffset = 0 } alignBottom :: RenderState -> Viewport -> Viewport alignBottom rs vp = let total = RenderState.rsLineCount rs off = max 0 (total - vpHeight vp) in vp { vpOffset = off }