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

Refactor toolbar #396

Merged
merged 1 commit into from
Dec 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions css/mpl_widget.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
/* Toolbar */

.jupyter-matplotlib-toolbar {
position: absolute;
overflow: visible;
z-index: 100;
}

.jupyter-matplotlib-toolbar-fadein-fadeout {
transition: visibility 0.5s linear, opacity 0.5s linear;
}

.jupyter-matplotlib-button {
Expand All @@ -18,9 +24,12 @@
/* Figure */

.jupyter-matplotlib-figure {
width: auto;
width: fit-content;
height: auto;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martinRenou i thought the centering was reverted?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was.. This looks like a leftover. But this does not seem to affect the plot? It is not centered when I try latest.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh i was just seeing this behavior. let me try in a fresh env

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this on the binder link - maybe this is browser based. I'm on Firefox 93

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed on chrome it is not centered, but it is on firefox:

left = chrome
right = firefox
Peek 2022-01-19 18-15

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish the visual regression tests caught that. We might be able to use playwright with Firefox as well. #422

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for catching this!

}

.jupyter-matplotlib-canvas-container {
Expand All @@ -32,6 +41,13 @@
flex: 1 1 auto;
}

.jupyter-matplotlib-canvas-div:focus {
outline: 1px solid var(--jp-widgets-input-focus-border-color);
.jupyter-matplotlib-header {
width: 100%;
text-align: center;
}

.jupyter-matplotlib-footer {
width: 100%;
text-align: center;
min-height: var(--jp-widgets-inline-height);
}
628 changes: 548 additions & 80 deletions examples/ipympl.ipynb

Large diffs are not rendered by default.

34 changes: 30 additions & 4 deletions ipympl/backend_nbagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import sys
import types
from warnings import warn

# In the case of a pyodide context (JupyterLite)
# we mock Tornado, as it cannot be imported and would
Expand Down Expand Up @@ -54,6 +55,7 @@
Tuple,
Unicode,
default,
observe,
)

from ._version import js_semver
Expand Down Expand Up @@ -99,15 +101,19 @@ class Toolbar(DOMWidget, NavigationToolbar2WebAgg):
_view_name = Unicode('ToolbarView').tag(sync=True)

toolitems = List().tag(sync=True)
orientation = Enum(['horizontal', 'vertical'], default_value='vertical').tag(
sync=True
)
button_style = CaselessStrEnum(
values=['primary', 'success', 'info', 'warning', 'danger', ''],
default_value='',
help="""Use a predefined styling for the button.""",
).tag(sync=True)

#######
# Those traits are deprecated
orientation = Enum(['horizontal', 'vertical'], default_value='vertical').tag(
sync=True
)
collapsed = Bool(True).tag(sync=True)
#######

_current_action = Enum(values=['pan', 'zoom', ''], default_value='').tag(sync=True)

Expand Down Expand Up @@ -153,6 +159,23 @@ def _default_toolitems(self):
if icon_name in icons
]

def __getattr__(self, name):
if name in ['orientation', 'collapsed']:
warn(
"The Toolbar properties 'orientation' and 'collapsed' are deprecated."
"Accessing them will raise an error in a coming ipympl release",
DeprecationWarning,
)

return super().__getattr__(name)

@observe('orientation', 'collapsed')
def _on_orientation_collapsed_changed(self, change):
warn(
"The Toolbar properties 'orientation' and 'collapsed' are deprecated.",
DeprecationWarning,
)


class Canvas(DOMWidget, FigureCanvasWebAggCore):

Expand All @@ -165,7 +188,10 @@ class Canvas(DOMWidget, FigureCanvasWebAggCore):
_view_name = Unicode('MPLCanvasView').tag(sync=True)

toolbar = Instance(Toolbar, allow_none=True).tag(sync=True, **widget_serialization)
toolbar_visible = Bool(True).tag(sync=True)
toolbar_visible = Enum(
['visible', 'hidden', 'fade-in-fade-out', True, False],
default_value='fade-in-fade-out',
).tag(sync=True)
toolbar_position = Enum(
['top', 'bottom', 'left', 'right'], default_value='left'
).tag(sync=True)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"files": [
"lib/**/*.js",
"dist/*.js",
"src/**/*.css"
"css/*.css"
],
"repository": {
"type": "git",
Expand Down
120 changes: 45 additions & 75 deletions src/mpl_widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import * as utils from './utils';

import { MODULE_VERSION } from './version';

import { ToolbarView } from './toolbar_widget';

export class MPLCanvasModel extends DOMWidgetModel {
offscreen_canvas: HTMLCanvasElement;
offscreen_context: CanvasRenderingContext2D;
Expand All @@ -33,7 +35,7 @@ export class MPLCanvasModel extends DOMWidgetModel {
header_visible: true,
footer_visible: true,
toolbar: null,
toolbar_visible: true,
toolbar_visible: 'fade-in-fade-out',
toolbar_position: 'horizontal',
resizable: true,
capture_scroll: false,
Expand Down Expand Up @@ -362,7 +364,7 @@ export class MPLCanvasView extends DOMWidgetView {
canvas_div: HTMLDivElement;
canvas: HTMLCanvasElement;
header: HTMLDivElement;
toolbar_view: DOMWidgetView;
toolbar_view: ToolbarView;
resize_handle_size: number;
resizing: boolean;
context: CanvasRenderingContext2D;
Expand All @@ -374,41 +376,35 @@ export class MPLCanvasView extends DOMWidgetView {
private _resize_event: (event: MouseEvent) => void;
private _stop_resize_event: () => void;

render() {
async render() {
this.resizing = false;
this.resize_handle_size = 20;

this.el.classList.add('jupyter-matplotlib');

this.figure = document.createElement('div');
this.figure.classList.add(
'jupyter-matplotlib-figure',
'jupyter-widgets',
'widget-container',
'widget-box',
'widget-vbox'
);
this.figure.classList.add('jupyter-matplotlib-figure');

this.el.appendChild(this.figure);

this._init_header();
this._init_canvas();
await this._init_toolbar();
this._init_footer();

this._resize_event = this.resize_event.bind(this);
this._stop_resize_event = this.stop_resize_event.bind(this);
window.addEventListener('mousemove', this._resize_event);
window.addEventListener('mouseup', this._stop_resize_event);

return this.create_child_view(this.model.get('toolbar')).then(
(toolbar_view) => {
this.toolbar_view = toolbar_view;

this._update_toolbar_position();

this._update_header_visible();
this._update_footer_visible();
this._update_toolbar_visible();
this.figure.addEventListener('mouseenter', () => {
this.toolbar_view.fade_in();
});
this.figure.addEventListener('mouseleave', () => {
this.toolbar_view.fade_out();
});

this.model_events();
}
);
this.model_events();
}

model_events() {
Expand Down Expand Up @@ -449,64 +445,23 @@ export class MPLCanvasView extends DOMWidgetView {
}

_update_toolbar_visible() {
this.toolbar_view.el.style.display = this.model.get('toolbar_visible')
? ''
: 'none';
this.toolbar_view.set_visibility(this.model.get('toolbar_visible'));
}

_update_toolbar_position() {
const toolbar_position = this.model.get('toolbar_position');
if (toolbar_position === 'top' || toolbar_position === 'bottom') {
this.el.classList.add(
'jupyter-widgets',
'widget-container',
'widget-box',
'widget-vbox',
'jupyter-matplotlib'
);
this.model.get('toolbar').set('orientation', 'horizontal');

this.clear();

if (toolbar_position === 'top') {
this.el.appendChild(this.toolbar_view.el);
this.el.appendChild(this.figure);
} else {
this.el.appendChild(this.figure);
this.el.appendChild(this.toolbar_view.el);
}
} else {
this.el.classList.add(
'jupyter-widgets',
'widget-container',
'widget-box',
'widget-hbox',
'jupyter-matplotlib'
);
this.model.get('toolbar').set('orientation', 'vertical');

this.clear();

if (toolbar_position === 'left') {
this.el.appendChild(this.toolbar_view.el);
this.el.appendChild(this.figure);
} else {
this.el.appendChild(this.figure);
this.el.appendChild(this.toolbar_view.el);
}
}
}

clear() {
while (this.el.firstChild) {
this.el.removeChild(this.el.firstChild);
}
this.model
.get('toolbar')
.set('position', this.model.get('toolbar_position'));
}

_init_header() {
this.header = document.createElement('div');
this.header.style.textAlign = 'center';
this.header.classList.add('jupyter-widgets', 'widget-label');
this.header.classList.add(
'jupyter-widgets',
'widget-label',
'jupyter-matplotlib-header'
);
this._update_header_visible();
this._update_figure_label();
this.figure.appendChild(this.header);
}
Expand Down Expand Up @@ -603,6 +558,17 @@ export class MPLCanvasView extends DOMWidgetView {
this.resize_and_update_canvas(this.model.size);
}

async _init_toolbar() {
this.toolbar_view = (await this.create_child_view(
this.model.get('toolbar')
)) as ToolbarView;

this.figure.appendChild(this.toolbar_view.el);

this._update_toolbar_position();
this._update_toolbar_visible();
}

/*
* Update the canvas view
*/
Expand Down Expand Up @@ -698,8 +664,12 @@ export class MPLCanvasView extends DOMWidgetView {

_init_footer() {
this.footer = document.createElement('div');
this.footer.style.textAlign = 'center';
this.footer.classList.add('jupyter-widgets', 'widget-label');
this.footer.classList.add(
'jupyter-widgets',
'widget-label',
'jupyter-matplotlib-footer'
);
this._update_footer_visible();
this._update_message();
this.figure.appendChild(this.footer);
}
Expand Down
Loading