From a2c2c4487bf65587e6728c15bc83d73d68b06e4e Mon Sep 17 00:00:00 2001 From: Joscha Date: Wed, 26 Feb 2020 08:34:19 +0000 Subject: [PATCH] [client] Improve cursor behaviour when elements are deleted --- src/Forest/Client/UiState.hs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Forest/Client/UiState.hs b/src/Forest/Client/UiState.hs index 915172b..7991a17 100644 --- a/src/Forest/Client/UiState.hs +++ b/src/Forest/Client/UiState.hs @@ -33,6 +33,7 @@ module Forest.Client.UiState ) where import Brick +import Data.List import Data.Maybe import qualified Data.Set as Set import qualified Data.Text as T @@ -113,7 +114,29 @@ validate :: UiState n -> UiState n validate = validateEditor . validateFocused . validateUnfolded replaceRootNode :: Node -> UiState n -> UiState n -replaceRootNode node s = validate s {uiRootNode = node} +replaceRootNode node s = validate s { uiRootNode = node + , uiFocused = findNextValidNode (uiRootNode s) node (uiFocused s) + } + +-- | Find a node that is close to the previously focused node, taking into +-- account its previous position in the tree. +findNextValidNode :: Node -> Node -> Path -> Path +findNextValidNode _ _ (Path []) = Path [] +findNextValidNode from to (Path (x:xs)) = fromMaybe (Path []) $ do + fromNode <- applyId x from + case applyId x to of + Just toNode -> pure $ Path [x] <> findNextValidNode fromNode toNode (Path xs) + Nothing -> do + fromIdx <- elemIndex x $ OMap.keys $ nodeChildren from + let toKeys = OMap.keys $ nodeChildren to + x' <- getValueClosestToIndex fromIdx toKeys + pure $ Path [x'] + where + -- Slightly unsafe code, but it should be fine + getValueClosestToIndex idx list + | length list > idx = Just $ list !! idx + | null list = Nothing + | otherwise = Just $ last list moveFocus :: (Node -> Path -> Path) -> UiState n -> UiState n moveFocus f s =