Add UpdateWidgetId request, handle it in Handlers/WidgetTask

This commit is contained in:
Francisco Vallarino 2020-12-27 22:12:24 -03:00
parent a13da072bd
commit babbd865bd
11 changed files with 134 additions and 48 deletions

View File

@ -59,7 +59,16 @@ handleAppEvent
-> AppEvent -> AppEvent
-> [AppEventResponse App AppEvent] -> [AppEventResponse App AppEvent]
handleAppEvent wenv model evt = case evt of handleAppEvent wenv model evt = case evt of
IncButton -> [Model (model & clickCount %~ (+1))] IncButton -> [Model (model & clickCount %~ (+1)),
Task $ do
threadDelay 1000000
putStrLn "Done 1"
return Nothing,
Task $ do
threadDelay 2000000
putStrLn "Done 2"
return Nothing
]
-- PrintMessage txt -> Model (model & showAlert .~ True) -- PrintMessage txt -> Model (model & showAlert .~ True)
PrintMessage txt -> [Task $ do PrintMessage txt -> [Task $ do
print txt print txt
@ -107,7 +116,14 @@ handleAppEvent wenv model evt = case evt of
_ -> [] _ -> []
buildUI :: WidgetEnv App AppEvent -> App -> WidgetNode App AppEvent buildUI :: WidgetEnv App AppEvent -> App -> WidgetNode App AppEvent
buildUI wenv model = trace "Creating UI" widgetTree where buildUI wenv model = trace "Creating UI" widgetIdChanged where
widgetIdChanged = vstack [
button "Show label" IncButton,
hstack $ [label "First" | model ^. clickCount > 0] ++ [
label "Test",
image_ "https://picsum.photos/600/400" [fitFill, onLoadError ImageMsg]
]
]
widgetInput = vstack [ widgetInput = vstack [
dropdown_ dropdown1 items label label [maxHeight 200], dropdown_ dropdown1 items label label [maxHeight 200],
hgrid [ hgrid [

View File

@ -33,6 +33,7 @@ makeLensesWith abbreviatedFields ''WidgetEnv
makeLensesWith abbreviatedFields ''WidgetRequest makeLensesWith abbreviatedFields ''WidgetRequest
makeLensesWith abbreviatedFields ''WidgetResult makeLensesWith abbreviatedFields ''WidgetResult
makeLensesWith abbreviatedFields ''WidgetData makeLensesWith abbreviatedFields ''WidgetData
makeLensesWith abbreviatedFields ''WidgetId
makeLensesWith abbreviatedFields ''WidgetNode makeLensesWith abbreviatedFields ''WidgetNode
makeLensesWith abbreviatedFields ''WidgetNodeInfo makeLensesWith abbreviatedFields ''WidgetNodeInfo
makeLensesWith abbreviatedFields ''WidgetInstanceNode makeLensesWith abbreviatedFields ''WidgetInstanceNode

View File

@ -57,7 +57,7 @@ data WidgetData s a
data WidgetId = WidgetId { data WidgetId = WidgetId {
_widTs :: Int, _widTs :: Int,
_widPath :: Path _widPath :: Path
} deriving (Eq, Show) } deriving (Eq, Show, Ord)
instance Default WidgetId where instance Default WidgetId where
def = WidgetId 0 rootPath def = WidgetId 0 rootPath
@ -89,9 +89,10 @@ data WidgetRequest s
| ExitApplication Bool | ExitApplication Bool
| UpdateWindow WindowRequest | UpdateWindow WindowRequest
| UpdateModel (s -> s) | UpdateModel (s -> s)
| UpdateWidgetPath WidgetId Path
| forall i . Typeable i => SendMessage Path i | forall i . Typeable i => SendMessage Path i
| forall i . Typeable i => RunTask Path (IO i) | forall i . Typeable i => RunTask WidgetId Path (IO i)
| forall i . Typeable i => RunProducer Path ((i -> IO ()) -> IO ()) | forall i . Typeable i => RunProducer WidgetId Path ((i -> IO ()) -> IO ())
data WidgetResult s e = WidgetResult { data WidgetResult s e = WidgetResult {
_wrNode :: WidgetNode s e, _wrNode :: WidgetNode s e,
@ -314,6 +315,7 @@ instance Show (WidgetRequest s) where
show ExitApplication{} = "ExitApplication" show ExitApplication{} = "ExitApplication"
show (UpdateWindow req) = "UpdateWindow: " ++ show req show (UpdateWindow req) = "UpdateWindow: " ++ show req
show UpdateModel{} = "UpdateModel" show UpdateModel{} = "UpdateModel"
show (UpdateWidgetPath wid path) = "UpdateWidgetPath: " ++ show (wid, path)
show SendMessage{} = "SendMessage" show SendMessage{} = "SendMessage"
show RunTask{} = "RunTask" show RunTask{} = "RunTask"
show RunProducer{} = "RunProducer" show RunProducer{} = "RunProducer"

View File

@ -13,7 +13,8 @@ module Monomer.Main.Handlers (
) where ) where
import Control.Concurrent.Async (async) import Control.Concurrent.Async (async)
import Control.Lens ((&), (^.), (.~), (%~), (.=), (?=), at, non, use) import Control.Lens (
(&), (^.), (.~), (%~), (.=), (%=), (?=), ix, at, non, use, _1)
import Control.Monad.STM (atomically) import Control.Monad.STM (atomically)
import Control.Concurrent.STM.TChan (TChan, newTChanIO, writeTChan) import Control.Concurrent.STM.TChan (TChan, newTChanIO, writeTChan)
import Control.Applicative ((<|>)) import Control.Applicative ((<|>))
@ -194,9 +195,10 @@ handleRequests reqs step = foldM handleRequest step reqs where
ExitApplication exit -> handleExitApplication exit step ExitApplication exit -> handleExitApplication exit step
UpdateWindow req -> handleUpdateWindow req step UpdateWindow req -> handleUpdateWindow req step
UpdateModel fn -> handleUpdateModel fn step UpdateModel fn -> handleUpdateModel fn step
UpdateWidgetPath wid path -> handleUpdateWidgetPath wid path step
SendMessage path msg -> handleSendMessage path msg step SendMessage path msg -> handleSendMessage path msg step
RunTask path handler -> handleRunTask path handler step RunTask wid path handler -> handleRunTask wid path handler step
RunProducer path handler -> handleRunProducer path handler step RunProducer wid path handler -> handleRunProducer wid path handler step
handleResizeWidgets handleResizeWidgets
:: (MonomerM s m) :: (MonomerM s m)
@ -368,6 +370,12 @@ handleUpdateModel fn (wenv, evts, root) = do
where where
wenv2 = wenv & L.model %~ fn wenv2 = wenv & L.model %~ fn
handleUpdateWidgetPath
:: (MonomerM s m) => WidgetId -> Path -> HandlerStep s e -> m (HandlerStep s e)
handleUpdateWidgetPath wid path step = do
setWidgetIdPath wid path
return step
handleSendMessage handleSendMessage
:: forall s e m msg . (MonomerM s m, Typeable msg) :: forall s e m msg . (MonomerM s m, Typeable msg)
=> Path => Path
@ -386,29 +394,35 @@ handleSendMessage path message (wenv, events, widgetRoot) = do
handleRunTask handleRunTask
:: forall s e m i . (MonomerM s m, Typeable i) :: forall s e m i . (MonomerM s m, Typeable i)
=> Path => WidgetId
-> Path
-> IO i -> IO i
-> HandlerStep s e -> HandlerStep s e
-> m (HandlerStep s e) -> m (HandlerStep s e)
handleRunTask path handler previousStep = do handleRunTask widgetId path handler previousStep = do
asyncTask <- liftIO $ async (liftIO handler) asyncTask <- liftIO $ async (liftIO handler)
previousTasks <- use L.widgetTasks previousTasks <- use L.widgetTasks
L.widgetTasks .= previousTasks |> WidgetTask path asyncTask L.widgetTasks .= previousTasks |> WidgetTask widgetId asyncTask
addWidgetIdPath widgetId path
return previousStep return previousStep
handleRunProducer handleRunProducer
:: forall s e m i . (MonomerM s m, Typeable i) :: forall s e m i . (MonomerM s m, Typeable i)
=> Path => WidgetId
-> Path
-> ((i -> IO ()) -> IO ()) -> ((i -> IO ()) -> IO ())
-> HandlerStep s e -> HandlerStep s e
-> m (HandlerStep s e) -> m (HandlerStep s e)
handleRunProducer path handler previousStep = do handleRunProducer widgetId path handler previousStep = do
newChannel <- liftIO newTChanIO newChannel <- liftIO newTChanIO
asyncTask <- liftIO $ async (liftIO $ handler (sendMessage newChannel)) asyncTask <- liftIO $ async (liftIO $ handler (sendMessage newChannel))
previousTasks <- use L.widgetTasks previousTasks <- use L.widgetTasks
L.widgetTasks .= previousTasks |> WidgetProducer path newChannel asyncTask L.widgetTasks .= previousTasks |> WidgetProducer widgetId newChannel asyncTask
addWidgetIdPath widgetId path
return previousStep return previousStep
addFocusReq addFocusReq
@ -532,3 +546,11 @@ cursorToSDL CursorSizeH = SDLEnum.SDL_SYSTEM_CURSOR_SIZEWE
cursorToSDL CursorSizeV = SDLEnum.SDL_SYSTEM_CURSOR_SIZENS cursorToSDL CursorSizeV = SDLEnum.SDL_SYSTEM_CURSOR_SIZENS
cursorToSDL CursorDiagTL = SDLEnum.SDL_SYSTEM_CURSOR_SIZENWSE cursorToSDL CursorDiagTL = SDLEnum.SDL_SYSTEM_CURSOR_SIZENWSE
cursorToSDL CursorDiagTR = SDLEnum.SDL_SYSTEM_CURSOR_SIZENESW cursorToSDL CursorDiagTR = SDLEnum.SDL_SYSTEM_CURSOR_SIZENESW
setWidgetIdPath :: (MonomerM s m) => WidgetId -> Path -> m ()
setWidgetIdPath widgetId path =
L.widgetPaths . ix widgetId . _1 .= path
addWidgetIdPath :: (MonomerM s m) => WidgetId -> Path -> m ()
addWidgetIdPath widgetId path =
L.widgetPaths . at widgetId . non (path, 0) %= \(_, c) -> (path, c + 1)

View File

@ -23,6 +23,7 @@ import Monomer.Core.BasicTypes
import Monomer.Core.Combinators import Monomer.Core.Combinators
import Monomer.Core.StyleTypes import Monomer.Core.StyleTypes
import Monomer.Core.ThemeTypes import Monomer.Core.ThemeTypes
import Monomer.Core.WidgetTypes
import Monomer.Event.Types import Monomer.Event.Types
import Monomer.Graphics.Types import Monomer.Graphics.Types
@ -35,8 +36,8 @@ data RenderSchedule = RenderSchedule {
} deriving (Eq, Show) } deriving (Eq, Show)
data WidgetTask data WidgetTask
= forall i . Typeable i => WidgetTask Path (Async i) = forall i . Typeable i => WidgetTask WidgetId (Async i)
| forall i . Typeable i => WidgetProducer Path (TChan i) (Async ()) | forall i . Typeable i => WidgetProducer WidgetId (TChan i) (Async ())
data MonomerContext s = MonomerContext { data MonomerContext s = MonomerContext {
_mcMainModel :: s, _mcMainModel :: s,
@ -51,6 +52,7 @@ data MonomerContext s = MonomerContext {
_mcOverlayPath :: Maybe Path, _mcOverlayPath :: Maybe Path,
_mcMainBtnPress :: Maybe (Path, Point), _mcMainBtnPress :: Maybe (Path, Point),
_mcWidgetTasks :: Seq WidgetTask, _mcWidgetTasks :: Seq WidgetTask,
_mcWidgetPaths :: Map WidgetId (Path, Int),
_mcCursorIcons :: Map CursorIcon SDLR.Cursor, _mcCursorIcons :: Map CursorIcon SDLR.Cursor,
_mcRenderRequested :: Bool, _mcRenderRequested :: Bool,
_mcRenderSchedule :: Map Path RenderSchedule, _mcRenderSchedule :: Map Path RenderSchedule,

View File

@ -36,6 +36,7 @@ initMonomerContext model win winSize useHiDPI devicePixelRate = MonomerContext {
_mcOverlayPath = Nothing, _mcOverlayPath = Nothing,
_mcMainBtnPress = Nothing, _mcMainBtnPress = Nothing,
_mcWidgetTasks = Seq.empty, _mcWidgetTasks = Seq.empty,
_mcWidgetPaths = Map.empty,
_mcCursorIcons = Map.empty, _mcCursorIcons = Map.empty,
_mcRenderRequested = False, _mcRenderRequested = False,
_mcRenderSchedule = Map.empty, _mcRenderSchedule = Map.empty,

View File

@ -5,7 +5,7 @@ module Monomer.Main.WidgetTask (handleWidgetTasks) where
import Control.Concurrent.Async (poll) import Control.Concurrent.Async (poll)
import Control.Concurrent.STM.TChan (tryReadTChan) import Control.Concurrent.STM.TChan (tryReadTChan)
import Control.Exception.Base import Control.Exception.Base
import Control.Lens ((&), (^.), (.=), use) import Control.Lens ((&), (^.), (.=), (%=), use, at, non, _1)
import Control.Monad.Extra import Control.Monad.Extra
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Control.Monad.STM (atomically) import Control.Monad.STM (atomically)
@ -19,6 +19,7 @@ import qualified Data.Sequence as Seq
import Monomer.Core import Monomer.Core
import Monomer.Main.Handlers import Monomer.Main.Handlers
import Monomer.Main.Lens import Monomer.Main.Lens
import Monomer.Main.Util
import Monomer.Main.Types import Monomer.Main.Types
import qualified Monomer.Lens as L import qualified Monomer.Lens as L
@ -31,7 +32,9 @@ handleWidgetTasks wenv widgetRoot = do
(active, finished) <- partitionM isThreadActive (toList tasks) (active, finished) <- partitionM isThreadActive (toList tasks)
widgetTasks .= Seq.fromList active widgetTasks .= Seq.fromList active
processTasks wenv widgetRoot tasks result <- processTasks wenv widgetRoot tasks
mapM_ handleFinishedTask finished
return result
processTasks processTasks
:: (MonomerM s m, Traversable t) :: (MonomerM s m, Traversable t)
@ -51,41 +54,41 @@ processTask
-> WidgetNode s e -> WidgetNode s e
-> WidgetTask -> WidgetTask
-> m (HandlerStep s e) -> m (HandlerStep s e)
processTask wenv widgetRoot (WidgetTask path task) = do processTask wenv widgetRoot (WidgetTask widgetId task) = do
taskStatus <- liftIO $ poll task taskStatus <- liftIO $ poll task
case taskStatus of case taskStatus of
Just taskRes -> processTaskResult wenv widgetRoot path taskRes Just taskRes -> processTaskResult wenv widgetRoot widgetId taskRes
Nothing -> return (wenv, Seq.empty, widgetRoot) Nothing -> return (wenv, Seq.empty, widgetRoot)
processTask model widgetRoot (WidgetProducer path channel task) = do processTask model widgetRoot (WidgetProducer widgetId channel task) = do
channelStatus <- liftIO . atomically $ tryReadTChan channel channelStatus <- liftIO . atomically $ tryReadTChan channel
case channelStatus of case channelStatus of
Just taskMsg -> processTaskEvent model widgetRoot path taskMsg Just taskMsg -> processTaskEvent model widgetRoot widgetId taskMsg
Nothing -> return (model, Seq.empty, widgetRoot) Nothing -> return (model, Seq.empty, widgetRoot)
processTaskResult processTaskResult
:: (MonomerM s m, Typeable a) :: (MonomerM s m, Typeable a)
=> WidgetEnv s e => WidgetEnv s e
-> WidgetNode s e -> WidgetNode s e
-> Path -> WidgetId
-> Either SomeException a -> Either SomeException a
-> m (HandlerStep s e) -> m (HandlerStep s e)
processTaskResult wenv widgetRoot _ (Left ex) = do processTaskResult wenv widgetRoot _ (Left ex) = do
liftIO . putStrLn $ "Error processing Widget task result: " ++ show ex liftIO . putStrLn $ "Error processing Widget task result: " ++ show ex
return (wenv, Seq.empty, widgetRoot) return (wenv, Seq.empty, widgetRoot)
processTaskResult wenv widgetRoot path (Right taskResult) processTaskResult wenv widgetRoot widgetId (Right taskResult)
= processTaskEvent wenv widgetRoot path taskResult = processTaskEvent wenv widgetRoot widgetId taskResult
processTaskEvent processTaskEvent
:: (MonomerM s m, Typeable a) :: (MonomerM s m, Typeable a)
=> WidgetEnv s e => WidgetEnv s e
-> WidgetNode s e -> WidgetNode s e
-> Path -> WidgetId
-> a -> a
-> m (HandlerStep s e) -> m (HandlerStep s e)
processTaskEvent wenv widgetRoot path event = do processTaskEvent wenv widgetRoot widgetId event = do
currentFocus <- use L.focusedPath path <- getWidgetIdPath widgetId
let emptyResult = WidgetResult widgetRoot Seq.empty Seq.empty let emptyResult = WidgetResult widgetRoot Seq.empty Seq.empty
let widget = widgetRoot ^. L.widget let widget = widgetRoot ^. L.widget
@ -94,6 +97,25 @@ processTaskEvent wenv widgetRoot path event = do
handleWidgetResult wenv widgetResult handleWidgetResult wenv widgetResult
isThreadActive :: (MonomerM s m) => WidgetTask -> m Bool handleFinishedTask :: MonomerM s m => WidgetTask -> m ()
handleFinishedTask task = delWidgetIdPath (taskWidgetId task)
isThreadActive :: MonomerM s m => WidgetTask -> m Bool
isThreadActive (WidgetTask _ task) = fmap isNothing (liftIO $ poll task) isThreadActive (WidgetTask _ task) = fmap isNothing (liftIO $ poll task)
isThreadActive (WidgetProducer _ _ task) = fmap isNothing (liftIO $ poll task) isThreadActive (WidgetProducer _ _ task) = fmap isNothing (liftIO $ poll task)
taskWidgetId :: WidgetTask -> WidgetId
taskWidgetId (WidgetTask widgetId _) = widgetId
taskWidgetId (WidgetProducer widgetId _ _) = widgetId
getWidgetIdPath :: (MonomerM s m) => WidgetId -> m Path
getWidgetIdPath widgetId =
use $ L.widgetPaths . at widgetId . non (widgetId ^. L.path, 0) . _1
delWidgetIdPath :: (MonomerM s m) => WidgetId -> m ()
delWidgetIdPath widgetId =
L.widgetPaths . at widgetId %= remVal
where
remVal (Just (path, c))
| c > 1 = Just (path, c - 1)
remVal _ = Nothing

View File

@ -283,7 +283,7 @@ compositeMerge
-> WidgetNode sp ep -> WidgetNode sp ep
-> WidgetNode sp ep -> WidgetNode sp ep
-> WidgetResult sp ep -> WidgetResult sp ep
compositeMerge comp state wenv oldComp newComp = newResult where compositeMerge comp state wenv oldComp newComp = result where
oldState = widgetGetState (oldComp ^. L.widget) wenv oldState = widgetGetState (oldComp ^. L.widget) wenv
validState = fromMaybe state (useState oldState) validState = fromMaybe state (useState oldState)
CompositeState oldModel oldRoot oldGlobalKeys = validState CompositeState oldModel oldRoot oldGlobalKeys = validState
@ -318,6 +318,10 @@ compositeMerge comp state wenv oldComp newComp = newResult where
| mergeRequired = reduceResult comp newState wenv styledComp tempResult | mergeRequired = reduceResult comp newState wenv styledComp tempResult
| otherwise = resultWidget $ styledComp | otherwise = resultWidget $ styledComp
& L.widget .~ oldComp ^. L.widget & L.widget .~ oldComp ^. L.widget
widgetId = newComp ^. L.info . L.widgetId
path = newComp ^. L.info . L.path
result = newResult
& L.requests %~ (UpdateWidgetPath widgetId path <|)
-- | Dispose -- | Dispose
compositeDispose compositeDispose
@ -535,10 +539,11 @@ reduceResult comp state wenv widgetComp widgetResult = newResult where
reduceCompEvents _cpsGlobalKeys evtHandler cwenv evtModel evts reduceCompEvents _cpsGlobalKeys evtHandler cwenv evtModel evts
WidgetResult uWidget uReqs uEvts = WidgetResult uWidget uReqs uEvts =
updateComposite comp state wenv _reModel evtsRoot widgetComp updateComposite comp state wenv _reModel evtsRoot widgetComp
currentPath = widgetComp ^. L.info . L.path widgetId = widgetComp ^. L.info . L.widgetId
path = widgetComp ^. L.info . L.path
newReqs = toParentReqs reqs newReqs = toParentReqs reqs
<> tasksToRequests currentPath _reTasks <> tasksToRequests widgetId path _reTasks
<> producersToRequests currentPath _reProducers <> producersToRequests widgetId path _reProducers
<> uReqs <> uReqs
<> toParentReqs _reRequests <> toParentReqs _reRequests
<> _reMessages <> _reMessages
@ -650,12 +655,21 @@ getModel
-> s -> s
getModel comp wenv = widgetDataGet (_weModel wenv) (_cmpWidgetData comp) getModel comp wenv = widgetDataGet (_weModel wenv) (_cmpWidgetData comp)
tasksToRequests :: CompositeEvent e => Path -> Seq (IO e) -> Seq (WidgetRequest sp) tasksToRequests
tasksToRequests path reqs = RunTask path <$> reqs :: CompositeEvent e
=> WidgetId
-> Path
-> Seq (IO e)
-> Seq (WidgetRequest sp)
tasksToRequests widgetId path reqs = RunTask widgetId path <$> reqs
producersToRequests producersToRequests
:: CompositeEvent e => Path -> Seq (ProducerHandler e) -> Seq (WidgetRequest sp) :: CompositeEvent e
producersToRequests path reqs = RunProducer path <$> reqs => WidgetId
-> Path
-> Seq (ProducerHandler e)
-> Seq (WidgetRequest sp)
producersToRequests widgetId path reqs = RunProducer widgetId path <$> reqs
toParentReqs :: Seq (WidgetRequest s) -> Seq (WidgetRequest sp) toParentReqs :: Seq (WidgetRequest s) -> Seq (WidgetRequest sp)
toParentReqs reqs = fmap fromJust $ Seq.filter isJust $ fmap toParentReq reqs toParentReqs reqs = fmap fromJust $ Seq.filter isJust $ fmap toParentReq reqs
@ -674,13 +688,14 @@ toParentReq ResetOverlay = Just ResetOverlay
toParentReq (SetOverlay path) = Just (SetOverlay path) toParentReq (SetOverlay path) = Just (SetOverlay path)
toParentReq (SetCursorIcon icon) = Just (SetCursorIcon icon) toParentReq (SetCursorIcon icon) = Just (SetCursorIcon icon)
toParentReq (SendMessage path message) = Just (SendMessage path message) toParentReq (SendMessage path message) = Just (SendMessage path message)
toParentReq (RunTask path action) = Just (RunTask path action) toParentReq (RunTask wid path action) = Just (RunTask wid path action)
toParentReq (RunProducer path action) = Just (RunProducer path action) toParentReq (RunProducer wid path action) = Just (RunProducer wid path action)
toParentReq RenderOnce = Just RenderOnce toParentReq RenderOnce = Just RenderOnce
toParentReq (RenderEvery path ms) = Just (RenderEvery path ms) toParentReq (RenderEvery path ms) = Just (RenderEvery path ms)
toParentReq (RenderStop path) = Just (RenderStop path) toParentReq (RenderStop path) = Just (RenderStop path)
toParentReq (ExitApplication exit) = Just (ExitApplication exit) toParentReq (ExitApplication exit) = Just (ExitApplication exit)
toParentReq (UpdateWindow req) = Just (UpdateWindow req) toParentReq (UpdateWindow req) = Just (UpdateWindow req)
toParentReq (UpdateWidgetPath wid path) = Just (UpdateWidgetPath wid path)
toParentReq (UpdateModel fn) = Nothing toParentReq (UpdateModel fn) = Nothing
collectGlobalKeys collectGlobalKeys

View File

@ -123,26 +123,30 @@ makeImage imgPath config state = widget where
} }
init wenv node = resultReqs node reqs where init wenv node = resultReqs node reqs where
wid = node ^. L.info . L.widgetId
path = node ^. L.info . L.path path = node ^. L.info . L.path
reqs = [RunTask path $ handleImageLoad wenv imgPath] reqs = [RunTask wid path $ handleImageLoad wenv imgPath]
merge wenv oldState oldNode newNode = result where merge wenv oldState oldNode newNode = result where
newState = fromMaybe state (useState oldState) newState = fromMaybe state (useState oldState)
wid = newNode ^. L.info . L.widgetId
path = newNode ^. L.info . L.path path = newNode ^. L.info . L.path
newImgReqs = [ RunTask path $ do widgetPathReq = UpdateWidgetPath wid path
newImgReqs = [ widgetPathReq, RunTask wid path $ do
removeImage wenv imgPath removeImage wenv imgPath
handleImageLoad wenv imgPath handleImageLoad wenv imgPath
] ]
sameImgNode = newNode sameImgNode = newNode
& L.widget .~ makeImage imgPath config newState & L.widget .~ makeImage imgPath config newState
result result
| isImagePath newState == imgPath = resultWidget sameImgNode | isImagePath newState == imgPath = resultReqs sameImgNode [widgetPathReq]
| otherwise = resultReqs newNode newImgReqs | otherwise = resultReqs newNode newImgReqs
dispose wenv node = resultReqs node reqs where dispose wenv node = resultReqs node reqs where
wid = node ^. L.info . L.widgetId
path = node ^. L.info . L.path path = node ^. L.info . L.path
renderer = _weRenderer wenv renderer = _weRenderer wenv
reqs = [RunTask path $ removeImage wenv imgPath] reqs = [RunTask wid path $ removeImage wenv imgPath]
handleMessage wenv target message node = result where handleMessage wenv target message node = result where
result = cast message >>= useImage node result = cast message >>= useImage node

View File

@ -371,6 +371,7 @@
Maybe postponed after release? Maybe postponed after release?
- Make sure WidgetTask/Node association is preserved if node location in tree changes - Make sure WidgetTask/Node association is preserved if node location in tree changes
- ZStack should set _weIsTopLayer based on used space - ZStack should set _weIsTopLayer based on used space
- Button should handle ReleaseBtn instead of Click (allow multi click)
- Check multiple resize when opening dialogs - Check multiple resize when opening dialogs
- Listview is not properly changing styles - Listview is not properly changing styles
- Label needs to rebuild its glyphs if style/renderArea changes - Label needs to rebuild its glyphs if style/renderArea changes

View File

@ -23,12 +23,12 @@ initMergeWidget = describe "init/merge" $ do
Seq.length reqs1 `shouldBe` 1 Seq.length reqs1 `shouldBe` 1
Seq.index reqs1 0 `shouldSatisfy` isRunTask Seq.index reqs1 0 `shouldSatisfy` isRunTask
it "should not create a task when merging to the same path" $ it "should not create a task when merging to the same path (UpdateWidgetPath is still added)" $
Seq.length reqs2 `shouldBe` 0 Seq.length reqs2 `shouldBe` 1
it "should create a task when merging to a different path" $ do it "should create a task when merging to a different path (UpdateWidgetPath is still added)" $ do
Seq.length reqs3 `shouldBe` 1 Seq.length reqs3 `shouldBe` 2
Seq.index reqs3 0 `shouldSatisfy` isRunTask Seq.index reqs3 1 `shouldSatisfy` isRunTask
where where
wenv = mockWenv () wenv = mockWenv ()