2020-09-10 16:43:42 +00:00
|
|
|
module MetaBrush.Document.History
|
|
|
|
( DocumentHistory(..)
|
|
|
|
, back, fwd, newHistory, newFutureStep
|
|
|
|
, atStart, atEnd
|
|
|
|
, affirmPresent
|
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
-- base
|
|
|
|
import GHC.Generics
|
|
|
|
( Generic )
|
|
|
|
|
|
|
|
-- containers
|
|
|
|
import Data.Sequence
|
|
|
|
( Seq(..) )
|
|
|
|
import qualified Data.Sequence as Seq
|
|
|
|
( length, drop )
|
|
|
|
|
|
|
|
-- deepseq
|
|
|
|
import Control.DeepSeq
|
|
|
|
( NFData(..), deepseq )
|
|
|
|
|
|
|
|
-- generic-lens
|
|
|
|
import Data.Generics.Product.Fields
|
|
|
|
( field' )
|
|
|
|
|
|
|
|
-- lens
|
|
|
|
import Control.Lens
|
|
|
|
( set )
|
|
|
|
|
|
|
|
-- MetaBrush
|
|
|
|
import MetaBrush.Document
|
|
|
|
( Document(..), DocumentContent(..) )
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
data DocumentHistory
|
|
|
|
= History
|
|
|
|
{ past :: !( Seq DocumentContent )
|
|
|
|
, present :: !Document
|
|
|
|
, future :: ![ DocumentContent ]
|
|
|
|
}
|
|
|
|
deriving stock ( Show, Generic )
|
|
|
|
instance NFData DocumentHistory where
|
|
|
|
rnf ( History { past = ps, present, future } ) =
|
|
|
|
ps `deepseq` present `deepseq` future `deepseq` ()
|
2022-02-13 16:30:54 +00:00
|
|
|
|
2020-09-10 16:43:42 +00:00
|
|
|
back :: DocumentHistory -> DocumentHistory
|
|
|
|
back hist@( History { past = ps, present = c, future = fs } ) = case ps of
|
|
|
|
Empty -> hist
|
|
|
|
qs :|> q -> History { past = qs, present = c { documentContent = q }, future = documentContent c : fs }
|
|
|
|
|
|
|
|
fwd :: DocumentHistory -> DocumentHistory
|
|
|
|
fwd hist@( History { past = ps, present = c, future = fs } ) = case fs of
|
|
|
|
[] -> hist
|
|
|
|
g : gs -> History { past = ps :|> documentContent c, present = c { documentContent = g }, future = gs }
|
|
|
|
|
|
|
|
newHistory :: Document -> DocumentHistory
|
|
|
|
newHistory a = History { past = Empty, present = a, future = [] }
|
|
|
|
|
|
|
|
newFutureStep :: Int -> Document -> DocumentHistory -> DocumentHistory
|
|
|
|
newFutureStep maxPastDocs a ( History { past = ps, present = c } ) =
|
|
|
|
History
|
|
|
|
{ past = Seq.drop ( n - maxPastDocs ) ( ps :|> documentContent c )
|
|
|
|
, present = a
|
|
|
|
, future = []
|
|
|
|
}
|
|
|
|
where
|
|
|
|
n :: Int
|
|
|
|
n = 1 + Seq.length ps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
atStart, atEnd :: DocumentHistory -> Bool
|
|
|
|
atStart hist = null ( past hist )
|
|
|
|
atEnd hist = null ( future hist )
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
affirmPresent :: DocumentHistory -> DocumentHistory
|
|
|
|
affirmPresent
|
|
|
|
= set ( field' @"past" . traverse . field' @"unsavedChanges" )
|
|
|
|
True
|
|
|
|
. set ( field' @"present" . field' @"documentContent" . field' @"unsavedChanges" )
|
|
|
|
False
|
|
|
|
. set ( field' @"future" . traverse . field' @"unsavedChanges" )
|
|
|
|
True
|