Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More flexible collection management #461

Open
bradrn opened this issue Nov 22, 2021 · 4 comments
Open

More flexible collection management #461

bradrn opened this issue Nov 22, 2021 · 4 comments

Comments

@bradrn
Copy link

bradrn commented Nov 22, 2021

Currently Reflex supports managing collections of widgets via the various functions in Reflex.Collection, roughly:

listHoldWithKey        :: Ord k => Map k v   -> Event  (Map k (Maybe v))  -> (k ->         v -> m        a ) -> m (Dynamic (Map k a))
listWithKey            :: Ord k =>              Dynamic (Map k v)         -> (k -> Dynamic v -> m        a ) -> m (Dynamic (Map k a))
list                   :: Ord k =>              Dynamic (Map k v)         -> (     Dynamic v -> m        a ) -> m (Dynamic (Map k a))
simpleList             ::                       Dynamic [v]               -> (     Dynamic v -> m        a ) -> m (Dynamic       [a])
listViewWithKey        :: Ord k =>              Dynamic (Map k v)         -> (k -> Dynamic v -> m (Event a)) -> m (Event   (Map k a))
listWithKeyShallowDiff :: Ord k => Map k v   -> Event (Map k (Maybe v)) -> (k ->         v -> Event   v    -> m a)         -> m (Dynamic (Map k a))
selectViewListWithKey_ :: Ord k => Dynamic k -> Dynamic (Map k v)       -> (k -> Dynamic v -> Dynamic Bool -> m (Event a)) -> m (Event k)

These work well enough for simple interfaces. Unfortunately, they have a major problem: they are all list functions. That is, Reflex currently renders the m a widgets by running them sequentially in the order specified by the map keys; there is no way to render them in any other order. Accordingly, it can be difficult to dynamically manage tables or any other sort of widget layout.

Additionally, these functions make it difficult to do anything aside from simply adding widgets to the end and removing widgets from anywhere. Inserting an element in the middle of a map is difficult, for instance, and swapping two widgets is completely impossible.

In theory, I should be able to write a replacement function myself which does what I want. In practice, this requires dealing with Adjustable, a typeclass with practically no documentation whatsoever (#418), as well as various other corners of the library with just as little documentation (e.g. Incremental). I only even know that much from reading the definition of listWithKey. Basic widget manipulation should not require reading the source code of the GUI library!

Accordingly, it would be nice to have a new, fully general function for collection management, one which supports the manipulations I mentioned above. I suggest something like the following:

collectionHoldWithKey :: Ord k => Map k v -> Event (PatchMapWithMove k v) -> (k -> v -> m a) -> (Map k (m a) -> m (Map k a)) -> m (Dynamic (Map k a))

The idea here would be that the final parameter provides a method for collecting each individual widget into a larger widget, allowing control of sequencing etc. But I’m not sure if this would work as is.

@tek
Copy link

tek commented Nov 22, 2021

I have experimented with this a bit:

https://gist.github.com/tek/d427c0fd9f8650892d3c469b63b55175

I also tried to use PatchDMapWithMove, but the entries aren't reordered when drawing the list with reflex-dom:

https://gist.github.com/tek/1ea3d43127d5f17fafbfd139f169b269

@alexfmpe
Copy link
Member

there is no way to render them in any other order

If you’re using reflex-dom you can control order with css via flex-order

@bradrn
Copy link
Author

bradrn commented Nov 27, 2021

https://gist.github.com/tek/d427c0fd9f8650892d3c469b63b55175

This looks interesting, but I’m not quite sure what it does. What is SortedUpdate, and how does patchableList differ from listHoldWithKey?

If you’re using reflex-dom you can control order with css via flex-order

Unfortunately, I’m not using flexbox. And even if I were, this wouldn’t solve all my problems, since it will still always render in a list.

@tek
Copy link

tek commented Nov 27, 2021

@bradrn

This looks interesting, but I’m not quite sure what it does. What is SortedUpdate, and how does patchableList differ from listHoldWithKey?

The type of the update elements in the Event passed to the widget is different from the one that is used to create it.
SortedUpdate contains either a Left with an update, a Right . Just for a new element or a Right Nothing for a deletion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants