summaryrefslogtreecommitdiffstats
path: root/src/TextViewport/Render/RenderState.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/TextViewport/Render/RenderState.hs')
-rw-r--r--src/TextViewport/Render/RenderState.hs132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/TextViewport/Render/RenderState.hs b/src/TextViewport/Render/RenderState.hs
new file mode 100644
index 0000000..26e92e1
--- /dev/null
+++ b/src/TextViewport/Render/RenderState.hs
@@ -0,0 +1,132 @@
+module TextViewport.Render.RenderState where
+
+import Data.Sequence (Seq)
+import Data.Sequence qualified as Seq
+import TextViewport.Buffer.Item
+import TextViewport.Buffer.Buffer (Buffer(Buffer))
+import TextViewport.Buffer.Buffer qualified as Buffer
+import TextViewport.Render.RenderBuffer (renderBuffer)
+import TextViewport.Render.RenderCache (RenderCache(..), emptyRenderCacheFor, resizeCache)
+import TextViewport.Render.RenderedBuffer (RenderedBuffer(RenderedBuffer))
+import TextViewport.Render.RenderedBuffer qualified as RenderedBuffer
+
+data RenderState = RenderState
+ { rsBuffer :: Buffer -- original items
+ , rsCache :: RenderCache -- per-item cached renders
+ , rsRendered :: RenderedBuffer -- fully segmented + hyphenated lines
+ , rsWidth :: Int -- segmenting width
+ , rsLineCount :: Int
+ } deriving (Eq, Show)
+
+mkRenderState :: Int -> Buffer -> RenderState
+mkRenderState width buf =
+ let (cache1, rendered) = renderBuffer width buf (emptyRenderCacheFor buf)
+ in RenderState
+ { rsBuffer = buf
+ , rsCache = cache1
+ , rsRendered = rendered
+ , rsWidth = width
+ , rsLineCount = length (RenderedBuffer.flatten rendered)
+ }
+
+-- RenderState has to be rebuilt whenever the buffer or the width changes.
+updateRenderState :: Int -> Buffer -> RenderState -> RenderState
+updateRenderState width buf rs =
+ let (cache1, rendered) = renderBuffer width buf (rsCache rs)
+ in rs
+ { rsBuffer = buf
+ , rsCache = cache1
+ , rsRendered = rendered
+ , rsWidth = width
+ , rsLineCount = length (RenderedBuffer.flatten rendered)
+ }
+
+modifyItemRS :: Int -> (Item -> Item) -> RenderState -> RenderState
+modifyItemRS ix f st =
+ let buf' = Buffer.modifyItem ix f (rsBuffer st)
+ cache' = resizeCache buf' (rsCache st)
+ (cache1, rendered1) = renderBuffer (rsWidth st) buf' cache'
+ in st { rsBuffer = buf'
+ , rsCache = cache1
+ , rsRendered = rendered1
+ , rsLineCount = length (RenderedBuffer.flatten rendered1)
+ }
+
+insertItem :: Int -> Item -> RenderState -> RenderState
+insertItem i newItem st =
+ let Buffer items = rsBuffer st
+ items' = Seq.insertAt i newItem items
+ buf' = Buffer items'
+ cache' = resizeCache buf' (rsCache st)
+ (cache1, rendered1) = renderBuffer (rsWidth st) buf' cache'
+ in st { rsBuffer = buf'
+ , rsCache = cache1
+ , rsRendered = rendered1
+ , rsLineCount = length (RenderedBuffer.flatten rendered1)
+ }
+
+deleteItem :: Int -> RenderState -> RenderState
+deleteItem i st =
+ let Buffer items = rsBuffer st
+ items' = Seq.deleteAt i items
+ buf' = Buffer items'
+ cache' = resizeCache buf' (rsCache st)
+ (cache1, rendered1) = renderBuffer (rsWidth st) buf' cache'
+ in st { rsBuffer = buf'
+ , rsCache = cache1
+ , rsRendered = rendered1
+ , rsLineCount = length (RenderedBuffer.flatten rendered1)
+ }
+
+replaceItem :: Int -> Item -> RenderState -> RenderState
+replaceItem i newItem st =
+ let Buffer items = rsBuffer st
+ items' = Seq.update i newItem items
+ buf' = Buffer items'
+ cache' = resizeCache buf' (rsCache st)
+ (cache1, rendered1) = renderBuffer (rsWidth st) buf' cache'
+ in st { rsBuffer = buf'
+ , rsCache = cache1
+ , rsRendered = rendered1
+ , rsLineCount = length (RenderedBuffer.flatten rendered1)
+ }
+
+appendItem :: Item -> RenderState -> RenderState
+appendItem newItem st =
+ insertItem (Seq.length (let Buffer xs = rsBuffer st in xs)) newItem st
+
+clearBuffer :: RenderState -> RenderState
+clearBuffer st =
+ let buf' = Buffer Seq.empty
+ cache' = RenderCache Seq.empty
+ in st { rsBuffer = buf'
+ , rsCache = cache'
+ , rsRendered = RenderedBuffer Seq.empty
+ , rsLineCount = 0
+ }
+
+fromList :: Int -> [Item] -> RenderState
+fromList width xs =
+ let buf = Buffer (Seq.fromList xs)
+ cache0 = RenderCache (Seq.replicate (length xs) Nothing)
+ (cache1, rendered) = renderBuffer width buf cache0
+ in RenderState
+ { rsBuffer = buf
+ , rsCache = cache1
+ , rsRendered = rendered
+ , rsWidth = width
+ , rsLineCount = length (RenderedBuffer.flatten rendered)
+ }
+
+fromSeq :: Int -> Seq Item -> RenderState
+fromSeq width items =
+ let buf = Buffer items
+ cache0 = RenderCache (Seq.replicate (Seq.length items) Nothing)
+ (cache1, rendered) = renderBuffer width buf cache0
+ in RenderState
+ { rsBuffer = buf
+ , rsCache = cache1
+ , rsRendered = rendered
+ , rsWidth = width
+ , rsLineCount = length (RenderedBuffer.flatten rendered)
+ }