diff options
Diffstat (limited to 'src/TextViewport/Render/RenderState.hs')
| -rw-r--r-- | src/TextViewport/Render/RenderState.hs | 132 |
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) + } |
