-
-
Notifications
You must be signed in to change notification settings - Fork 127
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
Datagrid: Introduce AsyncCellRenderer and ImageRenderer #630
Conversation
Ready for review!! CI failure seems unrelated, I don't have the right to restart it |
All green! Thanks to the person who restarted it :D |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! I kicked the failing test. I left two questions on the API design.
Also, we now have a minimal scaffold for datagrid tests here, it would be greatly appreciated if the critical subset of the new API was unit-tested.
/** | ||
* Sizing mode. Can be 'original', 'fit-height', 'fit-width', or 'fill'. | ||
* 'fit-height' will make the image fit the available height in the cell, respecting the image size ratio. | ||
* 'fit-width' will make the image fit the available width in the cell, respecting the image size ratio. | ||
* 'fill' will make the image fill the available space in the cell, NOT respecting the image size ratio. | ||
* 'original' will make respect the size of the original image. | ||
* | ||
* The default is 'fit-height' | ||
*/ | ||
sizingMode?: CellRenderer.ConfigOption<SizingMode>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it would be better to go for more flexible width: 100%
and height: 100%
. This way we can implement other sizing options (e.g. based on pixels) in the future, and already use width: 50%. Unless it does not make sense here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That works with me. Note that we cannot apply CSS rules though, so we'll need to parse the percentage and compute it manually. But it's not impossible :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, parsing only %
values for now should be managable. I would encourage doing this in this PR. In the future we might swap the implementation for CSSStyleValue.parse
once Firefox supports it.
} | ||
} | ||
|
||
static dataCache = new Map<string, HTMLImageElement | undefined>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do elements in this cache need to be disposed some way to avoid memory leaks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it's a static property, it will live as long as the page is running, is that right? So I guess there will be no memory leak happening?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we may want to clean the cache periodically, could be done in a separate PR if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In context of outputs in a notebook, if user opens and then closes 100 notebooks with different in images in data grids, will the memory stay constant or increase with each notebook? If this was tied to a renderer instance, I imagine we would not need to worry as the reference would not linger, but then we would need to fetch the resource for each output rendering which is not ideal either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Culling the cache periodically might be a solution indeed, but we would want to do this selectively (not touch any currently rendered data grids). So we may want to change the cache implementation in the future to do some reference counting or time-based expiration. To make it easier on future ourselves, what if that was a non-exported global variable so that it is not a part of public API? Any downside to this idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory will increase if those images are always different.
To make it easier on future ourselves, what if that was a non-exported global variable so that it is not a part of public API
Right!! We should definitely make that cache property private.
I'm fine with the idea to periodically clean the cache. The browser will have cached the image somewhere anyway, so next time we reload the same image it should not take much time to download again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would that work for you if I make the cache property private for now, and we can come up with cache cleaning logic in a separate PR (if/when we see issues with it)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, absolutely!
@krassowski thanks a lot for the useful review! I just pushed another commit:
|
Oops forgot to tackle this, will do |
@krassowski I think it's good for another round of review if you have time! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @martinRenou!
This is a step towards fixing jupyter-widgets/ipydatagrid#253
Introducing
AsyncCellRenderer
Prior to this change, the Lumino datagrid would not allow rendering cells asynchronously. This means that rendering images was not really possible (unless the cell renderer had a reference to the datagrid and requested a redraw once the asynchronous task was done).
This PR introduces the
AsyncCellRenderer
abstract class, which the datagrid uses as following (more or less pseudo-code):This allows supporting asynchronous cell rendering without slowing down the synchronous way.
Introducing the
ImageRenderer
This implements the
AsyncCellRenderer
and allows to load images in the datagrid: