@@ -46,13 +46,13 @@ import Data.Default
46import Data.Dependent.Map (DMap)
46import Data.Dependent.Map (DMap)
47import qualified Data.Dependent.Map as DMap
47import qualified Data.Dependent.Map as DMap
48import Data.Dependent.Sum
48import Data.Dependent.Sum
49+import Data.Functor.Compose
50+import Data.Functor.Constant
49import Data.Functor.Misc
51import Data.Functor.Misc
50import Data.IORef
52import Data.IORef
52import qualified Data.Map as Map
53import qualified Data.Map as Map
53import Data.Maybe
54import Data.Maybe
54import Data.Monoid
55import Data.Monoid
55−import Data.Some (Some)
56import qualified Data.Some as Some
56import qualified Data.Some as Some
57import Data.Text (Text)
57import Data.Text (Text)
58import qualified Data.Text as T
58import qualified Data.Text as T
@@ -70,8 +70,7 @@ import GHCJS.DOM.MouseEvent
70import qualified GHCJS.DOM.Touch as Touch
70import qualified GHCJS.DOM.Touch as Touch
71import qualified GHCJS.DOM.TouchEvent as TouchEvent
71import qualified GHCJS.DOM.TouchEvent as TouchEvent
72import qualified GHCJS.DOM.TouchList as TouchList
72import qualified GHCJS.DOM.TouchList as TouchList
73−import GHCJS.DOM.Node (appendChild_, getOwnerDocumentUnchecked, getParentNodeUnchecked,
73+import GHCJS.DOM.Node (appendChild_, getOwnerDocumentUnchecked, getParentNodeUnchecked, setNodeValue, toNode)
74− setNodeValue, toNode)
75import qualified GHCJS.DOM.Node as DOM (insertBefore_)
74import qualified GHCJS.DOM.Node as DOM (insertBefore_)
76import GHCJS.DOM.Types
75import GHCJS.DOM.Types
77 (liftJSM, askJSM, runJSM, JSM, MonadJSM(..),
76 (liftJSM, askJSM, runJSM, JSM, MonadJSM(..),
@@ -190,6 +189,20 @@ extractUpTo df s e = liftJSM $ do
191type SupportsImmediateDomBuilder t m = (Reflex t, MonadJSM m, MonadJSM (Performable m), MonadHold t m, MonadFix m, PerformEvent t m, MonadReflexCreateTrigger t m, MonadRef m, Ref m ~ Ref JSM, MonadAdjust t m)
190type SupportsImmediateDomBuilder t m = (Reflex t, MonadJSM m, MonadJSM (Performable m), MonadHold t m, MonadFix m, PerformEvent t m, MonadReflexCreateTrigger t m, MonadRef m, Ref m ~ Ref JSM, MonadAdjust t m)
192+{-# INLINABLE collectUpTo #-}
193+collectUpTo :: (MonadJSM m, IsNode start, IsNode end) => start -> end -> m DOM.DocumentFragment
195+ currentParent <- getParentNodeUnchecked e -- May be different than it was at initial construction, e.g., because the parent may have dumped us in from a DocumentFragment
196+ collectUpToGivenParent currentParent s e
198+{-# INLINABLE collectUpToGivenParent #-}
199+collectUpToGivenParent :: (MonadJSM m, IsNode parent, IsNode start, IsNode end) => parent -> start -> end -> m DOM.DocumentFragment
200+collectUpToGivenParent currentParent s e = do
201+ doc <- getOwnerDocumentUnchecked currentParent
202+ df <- createDocumentFragmentUnchecked doc
193newtype EventFilterTriggerRef t er (en :: EventTag) = EventFilterTriggerRef (IORef (Maybe (EventTrigger t (er en))))
206newtype EventFilterTriggerRef t er (en :: EventTag) = EventFilterTriggerRef (IORef (Maybe (EventTrigger t (er en))))
195wrap :: forall m er t. SupportsImmediateDomBuilder t m => RawElement GhcjsDomSpace -> RawElementConfig er t (ImmediateDomBuilderT t m) -> ImmediateDomBuilderT t m (Element er GhcjsDomSpace t)
208wrap :: forall m er t. SupportsImmediateDomBuilder t m => RawElement GhcjsDomSpace -> RawElementConfig er t (ImmediateDomBuilderT t m) -> ImmediateDomBuilderT t m (Element er GhcjsDomSpace t)
@@ -450,37 +463,72 @@ instance (Reflex t, MonadAdjust t m, MonadJSM m, MonadHold t m, PerformEvent t m
450 insertBefore df after
463 insertBefore df after
451 return result
464 return result
452 return (result0, result')
465 return (result0, result')
453− sequenceDMapWithAdjust (dm0 :: DMap k (ImmediateDomBuilderT t m)) dm' = do
466+ traverseDMapWithKeyWithAdjust (f :: forall a. k a -> v a -> ImmediateDomBuilderT t m (v' a)) (dm0 :: DMap k v) dm' = do
454 initialEnv <- ImmediateDomBuilderT ask
467 initialEnv <- ImmediateDomBuilderT ask
455− let drawChildInitial :: ImmediateDomBuilderT t m a -> m (DOM.DocumentFragment, DOM.Text, a)
468+ (children0, children') <- lift $ traverseDMapWithKeyWithAdjust (\k v -> drawChildUpdate initialEnv $ f k v) dm0 dm'
456− drawChildInitial child = runImmediateDomBuilderT ((,,) <$> pure (error "sequenceDMapWithAdjust{ImmediateDomBuilderT}: drawChildInitial: DocumentFragment evaluated") <*> textNodeInternal ("" :: Text) <*> child) initialEnv --TODO: Don't return a DocumentFragment at all here; this will require that sequenceDMapWithAdjust accept differently-typed values for the constant and Event arguments.
457− drawChildUpdate :: ImmediateDomBuilderT t m a -> m (DOM.DocumentFragment, DOM.Text, a)
458− drawChildUpdate child = do
459− df <- createDocumentFragmentUnchecked $ _immediateDomBuilderEnv_document initialEnv
460− runImmediateDomBuilderT ((,,) <$> pure df <*> textNodeInternal ("" :: Text) <*> child) $ initialEnv
461− { _immediateDomBuilderEnv_parent = toNode df
463− updateChildren = ffor dm' $ \(PatchDMap p) -> PatchDMap $
464− mapKeyValuePairsMonotonic (\(k :=> ComposeMaybe mv) -> WrapArg k :=> ComposeMaybe (fmap drawChildUpdate mv)) p
465− (children0, children') <- lift $ sequenceDMapWithAdjust (mapKeyValuePairsMonotonic (\(k :=> v) -> WrapArg k :=> drawChildInitial v) dm0) (updateChildren :: Event t (PatchDMap (WrapArg ((,,) DOM.DocumentFragment DOM.Text) k) m)) --TODO: Update stuff
466− let result0 = mapKeyValuePairsMonotonic (\(WrapArg k :=> Identity (_, _, v)) -> k :=> Identity v) children0
469+ let result0 = DMap.map (\(Compose (_, _, v)) -> v) children0
467− placeholders0 = dmapToMap $ mapKeyValuePairsMonotonic (\(WrapArg k :=> Identity (_, ph, _)) -> Const2 (Some.This k) :=> Identity ph) children0
470+ placeholders0 = weakenDMapWith (\(Compose (_, ph, _)) -> ph) children0
468− result' = ffor children' $ \(PatchDMap p) -> PatchDMap $
471+ result' = ffor children' $ mapPatchDMap $ \(Compose (_, _, r)) -> r
469− mapKeyValuePairsMonotonic (\(WrapArg k :=> v) -> k :=> fmap (\(_, _, r) -> r) v) p
472+ placeholders' = fforCheap children' $ weakenPatchDMapWith $ \(Compose (_, ph, _)) -> ph
470− placeholders' = ffor children' $ \(PatchDMap p) -> PatchMap $
471− dmapToMap $ mapKeyValuePairsMonotonic (\(WrapArg k :=> v) -> Const2 (Some.This k) :=> Identity (fmap ((\(_, ph, _) -> ph) . runIdentity) (getComposeMaybe v))) p
472− placeholders :: Behavior t (Map (Some k) DOM.Text) <- current . incrementalToDynamic <$> holdIncremental placeholders0 placeholders'
473+ placeholders <- current . incrementalToDynamic <$> holdIncremental placeholders0 placeholders'
474+ _ <- DMap.traverseWithKey (\_ (Compose (df, _, _)) -> Constant () <$ append df) children0
473 lastPlaceholder <- textNodeInternal ("" :: Text)
475 lastPlaceholder <- textNodeInternal ("" :: Text)
474 performEvent_ $ flip push children' $ \(PatchDMap p) -> do
476 performEvent_ $ flip push children' $ \(PatchDMap p) -> do
475 phs <- sample placeholders
477 phs <- sample placeholders
476 if DMap.null p then return Nothing else return $ Just $ do
478 if DMap.null p then return Nothing else return $ Just $ do
477− let f :: DSum (WrapArg ((,,) DOM.DocumentFragment DOM.Text) k) (ComposeMaybe Identity) -> Performable m ()
479+ let g :: DSum k (ComposeMaybe (Compose ((,,) DOM.DocumentFragment DOM.Text) v')) -> Performable m ()
478− f (WrapArg k :=> ComposeMaybe mv) = do
480+ g (k :=> ComposeMaybe mv) = do
479 let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phs
481 let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phs
480 forM_ (Map.lookup (Some.This k) phs) $ \thisPlaceholder -> thisPlaceholder `deleteUpTo` nextPlaceholder
482 forM_ (Map.lookup (Some.This k) phs) $ \thisPlaceholder -> thisPlaceholder `deleteUpTo` nextPlaceholder
481− forM_ mv $ \(Identity (df, _, _)) -> df `insertBefore` nextPlaceholder
483+ forM_ mv $ \(Compose (df, _, _)) -> df `insertBefore` nextPlaceholder
482− mapM_ f $ DMap.toList p
484+ mapM_ g $ DMap.toList p
483 return (result0, result')
485 return (result0, result')
486+ traverseDMapWithKeyWithAdjustWithMove (f :: forall a. k a -> v a -> ImmediateDomBuilderT t m (v' a)) (dm0 :: DMap k v) dm' = do
487+ initialEnv <- ImmediateDomBuilderT ask
488+ (children0, children') <- lift $ traverseDMapWithKeyWithAdjustWithMove (\k v -> drawChildUpdate initialEnv $ f k v) dm0 dm'
489+ let result0 = DMap.map (\(Compose (_, _, v)) -> v) children0
490+ placeholders0 = weakenDMapWith (\(Compose (_, ph, _)) -> ph) children0
491+ result' = ffor children' $ mapPatchDMapWithMove $ \(Compose (_, _, r)) -> r
492+ placeholders' = fforCheap children' $ weakenPatchDMapWithMoveWith $ \(Compose (_, ph, _)) -> ph
493+ placeholders <- current . incrementalToDynamic <$> holdIncremental placeholders0 placeholders'
494+ _ <- DMap.traverseWithKey (\_ (Compose (df, _, _)) -> Constant () <$ append df) children0
495+ lastPlaceholder <- textNodeInternal ("" :: Text)
496+ performEvent_ $ flip push children' $ \p_ -> do
497+ let p = unPatchDMapWithMove p_
498+ phsBefore <- sample placeholders
499+ if DMap.null p then return Nothing else return $ Just $ do
500+ let collectIfMoved :: forall a. k a -> DMapEdit k (Compose ((,,) DOM.DocumentFragment DOM.Text) v') a -> Performable m (Constant (Maybe DOM.DocumentFragment) a)
501+ collectIfMoved k e = do
502+ let mThisPlaceholder = Map.lookup (Some.This k) phsBefore -- Will be Nothing if this element wasn't present before
503+ nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phsBefore
504+ case dmapEditMoved e of
506+ mapM_ (`deleteUpTo` nextPlaceholder) mThisPlaceholder
507+ return $ Constant Nothing
509+ Constant <$> mapM (`collectUpTo` nextPlaceholder) mThisPlaceholder
510+ collected <- DMap.traverseWithKey collectIfMoved p
511+ let phsAfter = fromMaybe phsBefore $ apply (weakenPatchDMapWithMoveWith (\(Compose (_, ph, _)) -> ph) p_) phsBefore --TODO: Don't recompute this
512+ let placeFragment :: forall a. k a -> DMapEdit k (Compose ((,,) DOM.DocumentFragment DOM.Text) v') a -> Performable m (Constant () a)
513+ placeFragment k e = do
514+ let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phsAfter
516+ DMapEdit_Insert _ (Compose (df, _, _)) -> do
517+ df `insertBefore` nextPlaceholder
518+ DMapEdit_Delete _ -> do
520+ DMapEdit_Move _ fromKey -> do
521+ Just (Constant mdf) <- return $ DMap.lookup fromKey collected
522+ mapM_ (`insertBefore` nextPlaceholder) mdf
523+ return $ Constant ()
524+ mapM_ (\(k :=> v) -> void $ placeFragment k v) $ DMap.toDescList p -- We need to go in reverse order here, to make sure the placeholders are in the right spot at the right time
526+ return (result0, result')
528+drawChildUpdate :: MonadJSM m => ImmediateDomBuilderEnv t -> ImmediateDomBuilderT t m (v' a) -> m (Compose ((,,) DOM.DocumentFragment DOM.Text) v' a)
529+drawChildUpdate initialEnv child = do
530+ df <- createDocumentFragmentUnchecked $ _immediateDomBuilderEnv_document initialEnv
531+ runImmediateDomBuilderT (Compose <$> ((,,) <$> pure df <*> textNodeInternal ("" :: Text) <*> child)) $ initialEnv { _immediateDomBuilderEnv_parent = toNode df }
485mkHasFocus :: (MonadHold t m, Reflex t) => Element er d t -> m (Dynamic t Bool)
533mkHasFocus :: (MonadHold t m, Reflex t) => Element er d t -> m (Dynamic t Bool)
486mkHasFocus e = do
534mkHasFocus e = do