Add widgetGetSizeReq back. It helps avoid a confusing pattern in Single/Container

This commit is contained in:
Francisco Vallarino 2021-04-25 15:44:45 -03:00
parent 44b6141caf
commit 9bbcb8b5c1
23 changed files with 100 additions and 71 deletions

View File

@ -316,6 +316,12 @@ data Widget s e =
-> Path
-> i
-> Maybe (WidgetResult s e),
-- | Returns the size requirements for the widget. This is called to update
-- WidgetNodeInfo only at specific times.
widgetGetSizeReq
:: WidgetEnv s e
-> WidgetNode s e
-> (SizeReq, SizeReq),
-- | Resizes the children of this widget
--
-- Vieport assigned to the widget

View File

@ -309,6 +309,7 @@ createComposite comp state = widget where
widgetFindByPath = compositeFindByPath comp state,
widgetHandleEvent = compositeHandleEvent comp state,
widgetHandleMessage = compositeHandleMessage comp state,
widgetGetSizeReq = compositeGetSizeReq comp state,
widgetResize = compositeResize comp state,
widgetRender = compositeRender comp state
}
@ -539,13 +540,14 @@ compositeHandleMessage comp state@CompositeState{..} wenv widgetComp target arg
result = widgetHandleMessage cmpWidget cwenv _cpsRoot target arg
-- Preferred size
updateSizeReq
compositeGetSizeReq
:: (CompositeModel s, CompositeEvent e, CompositeEvent ep, ParentModel sp)
=> CompositeState s e
=> Composite s e sp ep
-> CompositeState s e
-> WidgetEnv sp ep
-> WidgetNode sp ep
-> WidgetNode sp ep
updateSizeReq state wenv widgetComp = newComp where
-> (SizeReq, SizeReq)
compositeGetSizeReq comp state wenv widgetComp = (newReqW, newReqH) where
CompositeState{..} = state
style = activeStyle wenv widgetComp
widget = _cpsRoot ^. L.widget
@ -555,6 +557,17 @@ updateSizeReq state wenv widgetComp = newComp where
-- User settings take precedence
newReqW = fromMaybe tmpReqW (style ^. L.sizeReqW)
newReqH = fromMaybe tmpReqH (style ^. L.sizeReqH)
-- Preferred size
updateSizeReq
:: (CompositeModel s, CompositeEvent e, CompositeEvent ep, ParentModel sp)
=> Composite s e sp ep
-> CompositeState s e
-> WidgetEnv sp ep
-> WidgetNode sp ep
-> WidgetNode sp ep
updateSizeReq comp state wenv widgetComp = newComp where
(newReqW, newReqH) = compositeGetSizeReq comp state wenv widgetComp
newComp = widgetComp
& L.info . L.sizeReqW .~ newReqW
& L.info . L.sizeReqH .~ newReqH
@ -656,7 +669,7 @@ toParentResult comp state wenv widgetComp result = newResult where
}
newComp = widgetComp
& L.widget .~ createComposite comp newState
newNode = updateSizeReq newState wenv newComp
newNode = updateSizeReq comp newState wenv newComp
newReqs = seqCatMaybes (toParentReq widgetId <$> reqs)
newResult = WidgetResult newNode newReqs

View File

@ -133,10 +133,9 @@ type ContainerMessageHandler s e
-> i
-> Maybe (WidgetResult s e)
type ContainerGetSizeReqHandler s e a
type ContainerGetSizeReqHandler s e
= WidgetEnv s e
-> WidgetNode s e
-> a
-> Seq (WidgetNode s e)
-> (SizeReq, SizeReq)
@ -177,7 +176,7 @@ data Container s e a = Container {
containerFindByPoint :: ContainerFindByPointHandler s e,
containerHandleEvent :: ContainerEventHandler s e,
containerHandleMessage :: ContainerMessageHandler s e,
containerGetSizeReq :: ContainerGetSizeReqHandler s e a,
containerGetSizeReq :: ContainerGetSizeReqHandler s e,
containerResize :: ContainerResizeHandler s e,
containerRender :: ContainerRenderHandler s e,
containerRenderAfter :: ContainerRenderHandler s e
@ -230,6 +229,7 @@ createContainer state container = Widget {
widgetFindByPath = containerFindByPath,
widgetHandleEvent = handleEventWrapper container,
widgetHandleMessage = handleMessageWrapper container,
widgetGetSizeReq = getSizeReqWrapper container,
widgetResize = resizeWrapper container,
widgetRender = renderWrapper container
}
@ -314,7 +314,7 @@ initWrapper container wenv node = initPostHandler wenv node result where
results = Seq.mapWithIndex initChild children
newReqs = foldMap _wrRequests results
newChildren = fmap _wrNode results
newNode = updateSizeReq container wenv $ tempNode
newNode = updateSizeReq wenv $ tempNode
& L.children .~ newChildren
result = WidgetResult newNode (reqs <> newReqs)
@ -358,7 +358,7 @@ mergeWrapper container wenv newNode oldNode = newResult where
Nothing -> resultWidget (mResult ^. L.node)
tmpResult
| isResizeResult (Just postRes) = postRes
& L.node .~ updateSizeReq container wenv (postRes ^. L.node)
& L.node .~ updateSizeReq wenv (postRes ^. L.node)
| otherwise = postRes
newResult = handleWidgetIdChange oldNode tmpResult
@ -702,33 +702,37 @@ handleMessageWrapper container wenv node target arg
| otherwise = messageResult
-- | Preferred size
defaultGetSizeReq :: ContainerGetSizeReqHandler s e a
defaultGetSizeReq wenv node state children = (newReqW, newReqH) where
defaultGetSizeReq :: ContainerGetSizeReqHandler s e
defaultGetSizeReq wenv node children = (newReqW, newReqH) where
(newReqW, newReqH) = case Seq.lookup 0 children of
Just child -> (child ^. L.info . L.sizeReqW, child ^. L.info . L.sizeReqH)
_ -> def
updateSizeReq
getSizeReqWrapper
:: WidgetModel a
=> Container s e a
-> WidgetEnv s e
-> WidgetNode s e
-> WidgetNode s e
updateSizeReq container wenv node = newNode where
-> (SizeReq, SizeReq)
getSizeReqWrapper container wenv node = (newReqW, newReqH) where
addStyleReq = containerAddStyleReq container
handler = containerGetSizeReq container
currState = widgetGetState (node ^. L.widget) wenv node
style = containerGetActiveStyle container wenv node
children = node ^. L.children
reqs = case useState currState of
Just state -> handler wenv node state children
_ -> def
reqs = handler wenv node children
(tmpReqW, tmpReqH)
| addStyleReq = sizeReqAddStyle style reqs
| otherwise = reqs
-- User settings take precedence
newReqW = fromMaybe tmpReqW (style ^. L.sizeReqW)
newReqH = fromMaybe tmpReqH (style ^. L.sizeReqH)
updateSizeReq
:: WidgetEnv s e
-> WidgetNode s e
-> WidgetNode s e
updateSizeReq wenv node = newNode where
(newReqW, newReqH) = widgetGetSizeReq (node ^. L.widget) wenv node
newNode = node
& L.info . L.sizeReqW .~ newReqW
& L.info . L.sizeReqH .~ newReqH
@ -748,7 +752,7 @@ handleSizeReqChange container wenv node evt mResult = result where
styleChanged = isJust evt && styleStateChanged wenv baseNode (fromJust evt)
result
| styleChanged || resizeReq = Just $ baseResult
& L.node .~ updateSizeReq container wenv baseNode
& L.node .~ updateSizeReq wenv baseNode
| otherwise = mResult
-- | Resize

View File

@ -181,8 +181,8 @@ makeBox config = widget where
| otherwise = Nothing
_ -> Nothing
getSizeReq :: ContainerGetSizeReqHandler s e a
getSizeReq wenv node currState children = newSizeReq where
getSizeReq :: ContainerGetSizeReqHandler s e
getSizeReq wenv node children = newSizeReq where
updateSizeReq = fromMaybe id (_boxSizeReqUpdater config)
child = Seq.index children 0
newReqW = child ^. L.info . L.sizeReqW

View File

@ -107,8 +107,8 @@ makeDraggable msg config = widget where
path = node ^. L.info . L.path
dragMsg = WidgetDragMsg msg
getSizeReq :: ContainerGetSizeReqHandler s e a
getSizeReq wenv node currState children = (newReqW, newReqH) where
getSizeReq :: ContainerGetSizeReqHandler s e
getSizeReq wenv node children = (newReqW, newReqH) where
child = Seq.index children 0
newReqW = child ^. L.info . L.sizeReqW
newReqH = child ^. L.info . L.sizeReqH

View File

@ -70,7 +70,7 @@ makeFixedGrid isHorizontal config = widget where
isVertical = not isHorizontal
getSizeReq wenv currState node children = newSizeReq where
getSizeReq wenv node children = newSizeReq where
updateSizeReq = fromMaybe id (_grcSizeReqUpdater config)
vchildren = Seq.filter (_wniVisible . _wnInfo) children
newSizeReqW = getDimSizeReq isHorizontal (_wniSizeReqW . _wnInfo) vchildren

View File

@ -416,8 +416,8 @@ makeScroll config state = widget where
& L.widget .~ makeScroll config newState
result = resultWidget newNode
getSizeReq :: ContainerGetSizeReqHandler s e a
getSizeReq wenv node currState children = sizeReq where
getSizeReq :: ContainerGetSizeReqHandler s e
getSizeReq wenv node children = sizeReq where
style = scrollActiveStyle wenv node
child = Seq.index children 0
tw = sizeReqMaxBounded $ child ^. L.info . L.sizeReqW

View File

@ -210,8 +210,8 @@ makeSplit isHorizontal config state = widget where
| otherwise = CursorSizeV
cursorIconReq = SetCursorIcon widgetId dragIcon
getSizeReq :: ContainerGetSizeReqHandler s e a
getSizeReq wenv node currState children = (reqW, reqH) where
getSizeReq :: ContainerGetSizeReqHandler s e
getSizeReq wenv node children = (reqW, reqH) where
node1 = Seq.index children 0
node2 = Seq.index children 1
reqW1 = node1 ^. L.info . L.sizeReqW

View File

@ -90,7 +90,7 @@ makeStack isHorizontal config = widget where
isVertical = not isHorizontal
ignoreEmptyArea = fromMaybe False (_stcIgnoreEmptyArea config)
getSizeReq wenv node currState children = newSizeReq where
getSizeReq wenv node children = newSizeReq where
updateSizeReq = fromMaybe id (_stcSizeReqUpdater config)
vchildren = Seq.filter (_wniVisible . _wnInfo) children
newSizeReqW = getDimSizeReq isHorizontal (_wniSizeReqW . _wnInfo) vchildren

View File

@ -139,7 +139,7 @@ makeZStack config state = widget where
| onlyTopActive = Seq.take 1 vchildren
| otherwise = vchildren
getSizeReq wenv node currState children = (newSizeReqW, newSizeReqH) where
getSizeReq wenv node children = (newSizeReqW, newSizeReqH) where
vchildren = Seq.filter (_wniVisible . _wnInfo) children
newSizeReqW = getDimSizeReq (_wniSizeReqW . _wnInfo) vchildren
newSizeReqH = getDimSizeReq (_wniSizeReqH . _wnInfo) vchildren

View File

@ -9,8 +9,7 @@ module Monomer.Widgets.Single (
module Monomer.Widgets.Util,
Single(..),
createSingle,
updateSizeReq
createSingle
) where
import Control.Exception (AssertionFailed(..), throw)
@ -84,10 +83,9 @@ type SingleMessageHandler s e
-> i
-> Maybe (WidgetResult s e)
type SingleGetSizeReqHandler s e a
type SingleGetSizeReqHandler s e
= WidgetEnv s e
-> WidgetNode s e
-> a
-> (SizeReq, SizeReq)
type SingleResizeHandler s e
@ -117,7 +115,7 @@ data Single s e a = Single {
singleFindByPoint :: SingleFindByPointHandler s e,
singleHandleEvent :: SingleEventHandler s e,
singleHandleMessage :: SingleMessageHandler s e,
singleGetSizeReq :: SingleGetSizeReqHandler s e a,
singleGetSizeReq :: SingleGetSizeReqHandler s e,
singleResize :: SingleResizeHandler s e,
singleRender :: SingleRenderHandler s e
}
@ -155,6 +153,7 @@ createSingle state single = Widget {
widgetFindByPath = singleFindByPath,
widgetHandleEvent = handleEventWrapper single,
widgetHandleMessage = handleMessageWrapper single,
widgetGetSizeReq = getSizeReqWrapper single,
widgetResize = resizeHandlerWrapper single,
widgetRender = renderWrapper single
}
@ -180,7 +179,7 @@ initWrapper single wenv node = newResult where
styledNode = initNodeStyle getBaseStyle wenv node
tmpResult = initHandler wenv styledNode
newResult = tmpResult
& L.node .~ updateSizeReq single wenv (tmpResult ^. L.node)
& L.node .~ updateSizeReq wenv (tmpResult ^. L.node)
defaultMerge :: SingleMergeHandler s e a
defaultMerge wenv newNode oldState oldNode = resultWidget newNode
@ -221,7 +220,7 @@ runNodeHandler single wenv newNode oldInfo nodeHandler = newResult where
tmpResult = nodeHandler wenv styledNode
newResult
| isResizeResult (Just tmpResult) = tmpResult
& L.node .~ updateSizeReq single wenv (tmpResult ^. L.node)
& L.node .~ updateSizeReq wenv (tmpResult ^. L.node)
| otherwise = tmpResult
getInstanceTreeWrapper
@ -343,29 +342,33 @@ handleMessageWrapper single wenv node target msg = result where
result = handleSizeReqChange single wenv node Nothing
$ handler wenv node target msg
defaultGetSizeReq :: SingleGetSizeReqHandler s e a
defaultGetSizeReq :: SingleGetSizeReqHandler s e
defaultGetSizeReq wenv node = def
updateSizeReq
getSizeReqWrapper
:: WidgetModel a
=> Single s e a
-> WidgetEnv s e
-> WidgetNode s e
-> WidgetNode s e
updateSizeReq single wenv node = newNode where
-> (SizeReq, SizeReq)
getSizeReqWrapper single wenv node = (newReqW, newReqH) where
addStyleReq = singleAddStyleReq single
handler = singleGetSizeReq single
style = singleGetActiveStyle single wenv node
currState = widgetGetState (node ^. L.widget) wenv node
reqs = case useState currState of
Just state -> handler wenv node state
_ -> def
reqs = handler wenv node
(tmpReqW, tmpReqH)
| addStyleReq = sizeReqAddStyle style reqs
| otherwise = reqs
-- User settings take precedence
newReqW = fromMaybe tmpReqW (style ^. L.sizeReqW)
newReqH = fromMaybe tmpReqH (style ^. L.sizeReqH)
updateSizeReq
:: WidgetEnv s e
-> WidgetNode s e
-> WidgetNode s e
updateSizeReq wenv node = newNode where
(newReqW, newReqH) = widgetGetSizeReq (node ^. L.widget) wenv node
newNode = node
& L.info . L.sizeReqW .~ newReqW
& L.info . L.sizeReqH .~ newReqH
@ -385,7 +388,7 @@ handleSizeReqChange single wenv node evt mResult = result where
styleChanged = isJust evt && styleStateChanged wenv newNode (fromJust evt)
result
| styleChanged || resizeReq = Just $ baseResult
& L.node .~ updateSizeReq single wenv newNode
& L.node .~ updateSizeReq wenv newNode
| otherwise = mResult
defaultResize :: SingleResizeHandler s e

View File

@ -239,8 +239,8 @@ makeButton caption config = widget where
result = resultReqsEvts node requests events
resultFocus = resultReqs node [SetFocus (node ^. L.info . L.widgetId)]
getSizeReq :: ContainerGetSizeReqHandler s e a
getSizeReq wenv node currState children = (newReqW, newReqH) where
getSizeReq :: ContainerGetSizeReqHandler s e
getSizeReq wenv node children = (newReqW, newReqH) where
-- Main section reqs
child = Seq.index children 0
newReqW = child ^. L.info . L.sizeReqW

View File

@ -161,7 +161,7 @@ makeCheckbox widgetData config = widget where
setValueReq = widgetDataSet widgetData newValue
reqs = setValueReq ++ _ckcOnChangeReq config
getSizeReq wenv node currState = req where
getSizeReq wenv node = req where
theme = activeTheme wenv node
width = fromMaybe (theme ^. L.checkboxWidth) (_ckcWidth config)
req = (fixedSize width, fixedSize width)

View File

@ -259,7 +259,7 @@ makeDial field minVal maxVal config state = widget where
& L.requests <>~ Seq.fromList (reqs <> evts)
| otherwise = result
getSizeReq wenv node currState = req where
getSizeReq wenv node = req where
theme = activeTheme wenv node
width = fromMaybe (theme ^. L.dialWidth) (_dlcWidth config)
req = (fixedSize width, fixedSize width)

View File

@ -388,8 +388,8 @@ makeDropdown widgetData items makeMain makeRow config state = widget where
newEvents = Seq.fromList (evts ++ evtsIdx)
result = WidgetResult newNode (reqs <> newReqs <> newEvents)
getSizeReq :: ContainerGetSizeReqHandler s e a
getSizeReq wenv node currState children = (newReqW, newReqH) where
getSizeReq :: ContainerGetSizeReqHandler s e
getSizeReq wenv node children = (newReqW, newReqH) where
-- Main section reqs
mainC = Seq.index children 0
mainReqW = mainC ^. L.info . L.sizeReqW

View File

@ -65,7 +65,7 @@ makeImage iconType config = widget where
singleRender = render
}
getSizeReq wenv node currState = sizeReq where
getSizeReq wenv node = sizeReq where
(w, h) = (16, 16)
factor = 1
sizeReq = (minSize w factor, minSize h factor)

View File

@ -162,8 +162,8 @@ makeImage imgPath config state = widget where
& L.widget .~ makeImage imgPath config newState
result = Just $ resultReqs newNode [ResizeWidgets]
getSizeReq wenv node currState = sizeReq where
Size w h = maybe def snd (isImageData currState)
getSizeReq wenv node = sizeReq where
Size w h = maybe def snd (isImageData state)
factor = 1
sizeReq = (expandSize w factor, expandSize h factor)

View File

@ -511,10 +511,10 @@ makeInputField config state = widget where
| isValid || not textAdd = resultReqsEvts newNode reqs events
| otherwise = resultReqsEvts node reqs events
getSizeReq wenv node currState = sizeReq where
getSizeReq wenv node = sizeReq where
defWidth = _ifcDefWidth config
resizeOnChange = _ifcResizeOnChange config
currText = _ifsCurrText currState
currText = _ifsCurrText state
style = activeStyle wenv node
Size w h = getTextSize wenv style currText
targetW

View File

@ -177,9 +177,9 @@ makeLabel config state = widget where
& L.widget .~ makeLabel config newState
result = resultReqs resNode reqs
getSizeReq wenv node currState = (sizeW, sizeH) where
caption = _lstCaption currState
prevResize = _lstPrevResize currState
getSizeReq wenv node = (sizeW, sizeH) where
caption = _lstCaption state
prevResize = _lstPrevResize state
ts = wenv ^. L.timestamp
style = activeStyle wenv node
cw = getContentArea style node ^. L.w

View File

@ -393,7 +393,7 @@ makeListView widgetData items makeRow config state = widget where
>>= lookup 0 -- vstack
>>= lookup idx -- item
getSizeReq wenv node currState children = (newSizeReqW, newSizeReqH) where
getSizeReq wenv node children = (newSizeReqW, newSizeReqH) where
child = Seq.index children 0
newSizeReqW = _wniSizeReqW . _wnInfo $ child
newSizeReqH = _wniSizeReqH . _wnInfo $ child
@ -445,9 +445,12 @@ updateItemStyle wenv merge idx mstyle (items, resizeReq) = result where
updateItemSizeReq :: WidgetEnv s e -> WidgetNode s e -> (WidgetNode s e, Bool)
updateItemSizeReq wenv item = (newItem, resizeReq) where
result = widgetMerge (item ^. L.widget) wenv item item
newItem = result ^. L.node
resizeReq = isResizeResult (Just result)
(oldReqW, oldReqH) = (item^. L.info . L.sizeReqW, item^. L.info . L.sizeReqH)
(newReqW, newReqH) = widgetGetSizeReq (item ^. L.widget) wenv item
newItem = item
& L.info . L.sizeReqW .~ newReqW
& L.info . L.sizeReqH .~ newReqH
resizeReq = (oldReqW, oldReqH) /= (newReqW, newReqH)
mergeItemStyle :: WidgetNode s e -> Maybe Style -> WidgetNode s e
mergeItemStyle item Nothing = item

View File

@ -150,7 +150,7 @@ makeRadio field option config = widget where
setValueReq = widgetDataSet field option
reqs = setValueReq ++ _rdcOnChangeReq config
getSizeReq wenv node currState = req where
getSizeReq wenv node = req where
theme = activeTheme wenv node
width = fromMaybe (theme ^. L.radioWidth) (_rdcWidth config)
req = (fixedSize width, fixedSize width)

View File

@ -77,7 +77,7 @@ makeSpacer config = widget where
singleGetSizeReq = getSizeReq
}
getSizeReq wenv currState node = sizeReq where
getSizeReq wenv node = sizeReq where
direction = wenv ^. L.layoutDirection
width = fromMaybe 5 (_spcWidth config)
height = fromMaybe 5 (_spcHeight config)

View File

@ -580,20 +580,20 @@
- Make Eq WidgetRequest require Eq e
- Rename widgetSave to something more appropriate
- Standardize use of Typeable/WidgetEvent/WidgetModel
- Should node come immediately after wenv in Widget methods?
- Is merging Task and Producer a good idea? (most likely not)
- It's clearer for the user to keep them as separate concepts
Next
- Add examples
- OpenGL example
- Something of generative art (custom Widget example)
- Should node come immediately after wenv in Widget methods?
- Can Req combinators be removed?
- Find a way out of currState in getSizeReq (most likely add method back to Widget). It's very confusing and error prone
- There must be some way to avoid adding the method back. Can't the same object be forced to update?
- Should cascadeCtx be part of widget interface? Maybe it can be handled on init?
- This could avoid rebuilding listView items when hidden/shown
- Notify of viewport change (maybe for chart?)
- Isn't resize enough? Not sure what the use case for this was
- Is merging Task and Producer a good idea? (most likely not)
- Can Req combinators be removed?
- Maybe offset should be in node info?
- Focus tracking in nested non-expanded scrolls is not possible otherwise
- Maybe IgnoreParentEvents could work?