-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Add support for "floating" UI elements #13538
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
Conversation
84cfb55 to
07cf3e2
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## branch-3.4 #13538 +/- ##
==============================================
- Coverage 92.59% 92.58% -0.02%
==============================================
Files 323 325 +2
Lines 20590 20723 +133
==============================================
+ Hits 19065 19186 +121
- Misses 1525 1537 +12 |
4f3efa6 to
9333150
Compare
9333150 to
0ae7dba
Compare
f43d82d to
aa78cde
Compare
ad87379 to
70adfa7
Compare
|
Screencast.from.30.01.2024.02.58.20.webm |
|
Screencast.from.30.01.2024.11.35.33.webm |
|
@philippjfr, @droumis, @hoxbro, this is tentatively ready for initial feedback. At this time I would suggest looking into |
examples/basic/ui/dialog.py
Outdated
| ), | ||
| ) | ||
| show_plot.js_on_click(OpenDialog(dialog=dialog)) | ||
| close_dialog.js_on_click( |
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.
Why is it not symmetric with OpenDialog?
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.
If we we are good with this kind of API, then I will fill in the missing parts. Though it's also good to show how to do things manually, if an API is missing.
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.
There seems to be no CloseDialog equivalent, correct?
Running this example with Bokeh serve (and updating the code with show -> curdoc().add_root, I can't get the close button to work and get the log:
Uncaught (in promise) Error: cannot find a view for Dialog(p1046)
get_one http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:221
default blob:http://localhost:5006/4e8e6ce5-4530-4159-ae07-e228cfae3dcf:1
execute http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:480
execute http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:216
_process_event http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:217
trigger http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:166
trigger_event http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:217
click http://localhost:5006/static/js/bokeh-widgets.min.js?v=8945a2a59d802de388cad0ff943167d1f705d69f095c16e44e908e94b6dd70ceba9b48c6ab0601f0d6b1c593988520f8ab2ce507540022d08cc8888dccb244d8:57
render http://localhost:5006/static/js/bokeh-widgets.min.js?v=8945a2a59d802de388cad0ff943167d1f705d69f095c16e44e908e94b6dd70ceba9b48c6ab0601f0d6b1c593988520f8ab2ce507540022d08cc8888dccb244d8:47
render http://localhost:5006/static/js/bokeh-widgets.min.js?v=8945a2a59d802de388cad0ff943167d1f705d69f095c16e44e908e94b6dd70ceba9b48c6ab0601f0d6b1c593988520f8ab2ce507540022d08cc8888dccb244d8:47
render http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:573
render_to http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:573
render http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:486
_toggle http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:486
connect_signals http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:486
n http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:221
emit http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:181
emit http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:181
_setv http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:180
setv http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:180
open http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:486
execute http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:485
execute http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:216
_process_event http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:217
trigger http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:166
trigger_event http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:217
click http://localhost:5006/static/js/bokeh-widgets.min.js?v=8945a2a59d802de388cad0ff943167d1f705d69f095c16e44e908e94b6dd70ceba9b48c6ab0601f0d6b1c593988520f8ab2ce507540022d08cc8888dccb244d8:57
render http://localhost:5006/static/js/bokeh-widgets.min.js?v=8945a2a59d802de388cad0ff943167d1f705d69f095c16e44e908e94b6dd70ceba9b48c6ab0601f0d6b1c593988520f8ab2ce507540022d08cc8888dccb244d8:47
render http://localhost:5006/static/js/bokeh-widgets.min.js?v=8945a2a59d802de388cad0ff943167d1f705d69f095c16e44e908e94b6dd70ceba9b48c6ab0601f0d6b1c593988520f8ab2ce507540022d08cc8888dccb244d8:47
render_to http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:573
s http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:220
s http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:220
add_document_standalone http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:220
add_document_from_session http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:232
k http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:164
embed_items http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:164
embed_document http://localhost:5006/dialog:38
fn http://localhost:5006/dialog:41
fn http://localhost:5006/dialog:57
safely http://localhost:5006/static/js/bokeh.min.js?v=09b616ff6e78e0bc7aa27d971d6bd254ee707011ace76821753ce252849fa5443f279823051efd10b5ca74b0a9a148a1306310dbde3a3dcae097acca168ae1bf:240
fn http://localhost:5006/dialog:33
EventListener.handleEvent* http://localhost:5006/dialog:61
<anonymous> http://localhost:5006/dialog:62
bokeh.min.js:221:4067There 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.
Error: cannot find a view for Dialog(p1046)
This actually doesn't work at all. This is because OpenDialog (callbacks in general) doesn't have a view, so it doesn't participate in the mechanism that allows to resolve views via the global view manager. Given the intent behind OpenDialog and this example is to have a non-root, detached/global dialog, then I need to add a mechanism to register such "free" views.
| clear = Button(label="Clear", **common) | ||
|
|
||
| toolbar = Panel( | ||
| position=box_select.overlay.nodes.bottom_left, |
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.
Where can I read about the nodes object? Does this resolve on render or does nodes.bottom_left represent some actual concrete value?
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 need to write documentation for nodes. It resolves during geometry/positioning computations, so still technically on render/paint. I'm in the process of separating those two phases, but it won't be done here. Computed values are only available in bokehjs. It may be possible to expose those values in a similar way to how computed layouts are exposed, e.g. in plots.
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 think syncing it is probably overkill, was just trying to understand how it works.
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 considered adding support for reporting computed values. For performance reasons, that would be done via a subscription based mechanism similar to how JS event callbacks work.
| position=Node(target="frame", symbol="bottom_left"), | ||
| anchor="bottom_left", | ||
| css_variables={ | ||
| "--max-width": Node(target="frame", symbol="width"), |
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.
Maybe I'm missing something, but does this have an effect on the output? If I comment out this and max-width in the stylesheet, I see no change.
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.
You can see this working here (attribution must not overflow the frame; frame is a pseudo renderer, so it doesn't have intrinsic support for managing overflow like CSS based UIs do):
Screencast.from.31.01.2024.13.34.12.webm
|
I finalized support for context menus, which completes the features I indented for this PR. Screencast.from.05.02.2024.15.09.53.webm |
|
I will finish docstrings and some rudimentary testing later today, so that we can start testing this downstream. I will continue polishing things up and adding more tests in future PRs. |
6e51e56 to
8963bdd
Compare
3563283 to
155b7c1
Compare
9e21bf9 to
9ef5062
Compare
* Add more icons
* Add hover tool's tooltip to plot's event layer
* Make Dialog movable and resizable
* Set dialog's title in examiner tool
* Add OpenDialog and ToggleVisibility callbacks
* Update defaults' baseline
* Robustify application of CSS styles
* Correctly configure pointer capture
* Move box shadow to the inner element
* Use a style sheet for Dialog positioning
* Implement stacking order for dialogs
* Implement dependency between dialog's states
* Robustify initialization and destruction
* Collapse/Restore dialog when scrolling on title
* Add Panel UI element
* Generalize symbolic Node API
* Add support for z-index pinning to Dialog
* Allow CSS variables in CSS preprocessor
* Don't duplicate testing effort in test_enums.py
* Improve Literal type support in Enum
* Allow adding additional UI elements
* Allow Tooltip to handle UI elements
* Add support for canvas positioning of UIs
* Add support for context menus to UIs/renderers
* Add support for data positioning
* Temporarily add CartesianFrame.resolve_symbol()
* Include PlotView's canvas in elements
* Finalize various types of node resolution
* Make implicit node resolution work
* Rename Panel -> SidePanel
* Formalize support for plot attributions
* Fix issues with resolution of coordinates/nodes
* Add examples/basic/ui/dialog.py
* Add examples/basic/ui/custom_attribution.py
* Update tests/unit/bokeh/models/test_annotations.py
* Reposition Panel when its positioning node changes
* Add examples/basic/ui/inline_data_entry.py
* Add examples/basic/ui/selection_custom_toolbar.py
* Fix code quality issues
* Move ViewManager to its own module
* Allow to manage non-root parent-less views
* Make Dialog's close action configurable
* Fix base class of bokeh.models.dom.HTML
* Add CloseDialog callback along OpenDialog
* Allow AbstractButton.label to have HTML contents
* Improve examples/basic/ui/dialog.py
* Add support for a dialog minimization area
* Add more icons and update the baseline
* Increase size allowance for bokeh.min.js
* Use Coordinate instead of Node in Tooltip
* Replace .bring-to-front() with a CSS variable
* Robustify LayoutDOMView.update_children()
* Properly rebuild toolbar when location changes
* Don't reference HTML if DOMNode is used
* Don't require root-layout in render_to()
* Use appropriate dialog close action
* Finalize support for context menus
* Add examples/basic/ui/annotation_menu.py
* Make ui.icons.Icon a UIElement
* Move ui.{panes->panels}.Panel
* Simplify definition of CompositeRenderer.elements
* Add CompositeRenderer.renderers property
* Update docstrings of bokeh.models.ui.*
* Improve menu naming convention and add docstrings
* Implement integration/examples/color_scatter.ts
* Update test_annotations.py
* Add rudimentary integration tests for UI elements
* Use consistently pointer events instead of mouse events
* Allow to programmatically display context menus
* Rename DictLike -> Dict type
* Update docstrings and properties' help
* Don't use deprecated class properties
* Update cross integration tests' baselines
|
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |



This This PR adds various new and improves existings "floating" UI elements, like dialogs, panels (e.g. floating toolbars), drop panes,
drawers (side bars),alerts, tooltips, context menus, etc. and refines methods for attaching them can to other UI elements and renderers (e.g. annotations, frames).An example of multiple dialogs, which support moving and resize (with constraints), z-order management, various controls (like minimization/maximization, collapsing, pinning) and contents which can be HTML, UI elements or layouts:
