Skip to content

Commit

Permalink
Refactor toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
martinRenou committed Dec 15, 2021
1 parent 480a236 commit afdebbf
Show file tree
Hide file tree
Showing 24 changed files with 870 additions and 209 deletions.
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;
}

.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

0 comments on commit afdebbf

Please sign in to comment.