Skip to content

Commit 2c013da

Browse files
authored
Merge pull request #133 from bmorris3/set-ref-widget
enable: anchor new Sidecar relative to a reference widget
2 parents 5e52470 + 4e7f81e commit 2c013da

File tree

5 files changed

+55
-8
lines changed

5 files changed

+55
-8
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@ new JupyterLab window which can be re-arranged as desired.
5757

5858
![sidecar in main work area](sidecar-main-area.gif)
5959

60+
### Arrange a new sidecar with respect to another sidecar
61+
62+
The `anchor` parameter sets the position of the new sidecar relative to the
63+
notebook that opens the sidecar, by default. To open a new sidecar whose `anchor`
64+
is defined relative to another sidecar output, set the `ref` parameter with
65+
the instance of the reference sidecar.
66+
67+
For example:
68+
69+
![sidecar arranged with respect to another sidecar](sidecar-ref-anchor.png)
70+
6071
## Development
6172

6273
```bash

sidecar-ref-anchor.png

183 KB
Loading

sidecar/sidecar.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
"""
88
TODO: Add module docstring
99
"""
10-
11-
from ipywidgets import Output
12-
from traitlets import Unicode, CaselessStrEnum
10+
import warnings
11+
from ipywidgets import Output, widget_serialization
12+
from traitlets import Unicode, CaselessStrEnum, Any, Instance, observe
1313
from ._frontend import EXTENSION_SPEC_VERSION
1414

1515
module_name = "@jupyter-widgets/jupyterlab-sidecar"
@@ -28,3 +28,13 @@ class Sidecar(Output):
2828
default_value='right',
2929
allow_none=True
3030
).tag(sync=True)
31+
ref = Instance('sidecar.Sidecar', allow_none=True).tag(sync=True, **widget_serialization)
32+
_widget_id = Any().tag(sync=True)
33+
34+
@observe('ref')
35+
def _validate_ref_anchor(self, *args):
36+
if self.ref.anchor == 'right':
37+
warnings.warn(
38+
"`ref` cannot be set when `ref.anchor == 'right'`. "
39+
"Proceeding with `ref = None`.", UserWarning
40+
)

src/index.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const sidecarPlugin: JupyterFrontEndPlugin<void> = {
2525
const SidecarView = class extends output.OutputView {
2626
model: SidecarModel;
2727

28-
render() {
28+
async render() {
2929
if (!this.model.rendered) {
3030
super.render();
3131

@@ -42,7 +42,7 @@ const sidecarPlugin: JupyterFrontEndPlugin<void> = {
4242
}
4343
);
4444
w.id = UUID.uuid4();
45-
45+
this.model.set('_widget_id', w.id);
4646
if (this.model.views && Object.keys(this.model.views).length > 1) {
4747
w.node.style.display = 'none';
4848
const key = Object.keys(this.model.views)[0];
@@ -53,12 +53,19 @@ const sidecarPlugin: JupyterFrontEndPlugin<void> = {
5353
});
5454
} else {
5555
const anchor = this.model.get('anchor') || 'right';
56+
const ref = this.model.get('ref');
57+
let widget_id: string | null = null;
58+
if (ref) {
59+
await ref.created;
60+
widget_id = ref.get('_widget_id');
61+
}
5662
if (anchor === 'right') {
5763
app.shell.add(w, 'right');
5864
} else {
59-
app.shell.add(w, 'main', { mode: anchor });
65+
app.shell.add(w, 'main', { ref: widget_id, mode: anchor });
6066
}
6167
app.shell.activateById(w.id);
68+
this.model.resolveCreated();
6269
}
6370
}
6471
}

src/widget.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
import { DOMWidgetModel } from '@jupyter-widgets/base';
55
import { output } from '@jupyter-widgets/jupyterlab-manager';
6-
6+
import { PromiseDelegate } from '@lumino/coreutils';
7+
import { unpack_models } from '@jupyter-widgets/base';
78
import { EXTENSION_SPEC_VERSION } from './version';
89

910
export class SidecarModel extends output.OutputModel {
@@ -19,10 +20,28 @@ export class SidecarModel extends output.OutputModel {
1920
_view_module: SidecarModel.view_module,
2021
_view_module_version: SidecarModel.view_module_version,
2122
title: 'Sidecar',
22-
anchor: 'right'
23+
anchor: 'right',
24+
ref: null,
25+
_widget_id: null
2326
};
2427
}
2528

29+
get created(): Promise<void> {
30+
return this._viewCreated.promise;
31+
}
32+
33+
public resolveCreated() {
34+
this._viewCreated.resolve();
35+
}
36+
37+
private _viewCreated: PromiseDelegate<void> = new PromiseDelegate<void>();
38+
39+
// deserialize the ref property
40+
static serializers = {
41+
...DOMWidgetModel.serializers,
42+
ref: { deserialize: unpack_models as any }
43+
};
44+
2645
initialize(attributes: any, options: any) {
2746
super.initialize(attributes, options);
2847

0 commit comments

Comments
 (0)