Skip to content
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
14 changes: 5 additions & 9 deletions rerun_notebook/src/js/widget.css
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
.rerun_notebook canvas {
.rerun_notebook {
margin: 0;
padding: 0;
width: 100%;
height: 100%;

min-width: 200px;
min-height: 400px;
max-width: 960px;
max-height: 720px;
background: transparent !important;
}

.rerun_notebook {
.rerun_notebook > div {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: transparent !important;
}

Expand Down
95 changes: 47 additions & 48 deletions rerun_notebook/src/js/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,66 @@ const PANELS = ["top", "blueprint", "selection", "time"] as const;

/* Specifies attributes defined with traitlets in ../rerun_notebook/__init__.py */
interface WidgetModel {
_width?: number;
_height?: number;
_width: number | string;
_height: number | string;

_url?: string;
_panel_states?: PanelStates;
_time_ctrl: [timeline: string | null, time: number | null, play: boolean];
_recording_id?: string;

_fallback_token?: string;
}

type Opt<T> = T | null | undefined;

function _resize(el: HTMLElement, width: number | string, height: number | string) {
const style = el.style;

if (typeof width === "string" && width === "auto") {
style.width = "100%";
} else if (typeof width === "number") {
style.width = `${Math.max(200, width)}px`;
} else {
style.width = "640px";
}

if (typeof height === "string" && height === "auto") {
style.height = "auto";
style.aspectRatio = "16 / 9";
} else if (typeof height === "number") {
style.height = `${Math.max(200, height)}px`;
style.aspectRatio = "";
} else {
style.height = "640px";
style.aspectRatio = "";
}
}

function dbg(...args: any[]): boolean {
console.log(...args)
return true;
}

class ViewerWidget {
viewer: WebViewer = new WebViewer();
url: Opt<string> = null;
panel_states: Opt<PanelStates> = null;
options: WebViewerOptions = { hide_welcome_screen: true };
options: WebViewerOptions = {
hide_welcome_screen: true,
width: "100%",
height: "100%",
};

channel: LogChannel | null = null;

constructor(model: AnyModel<WidgetModel>) {
constructor(model: AnyModel<WidgetModel>, el: HTMLElement) {
this.url = model.get("_url");
model.on("change:_url", this.on_change_url);

this.panel_states = model.get("_panel_states");
model.on("change:_panel_states", this.on_change_panel_states);

model.on("change:_width", (_, width) => this.on_resize(null, { width }));
model.on("change:_height", (_, height) => this.on_resize(null, { height }));
model.on("change:_width", (_, width) => dbg("resize") && this.on_resize(el, width, model.get("_height")));
model.on("change:_height", (_, height) => dbg("resize") && this.on_resize(el, model.get("_width"), height));

model.on("msg:custom", this.on_custom_message);

Expand All @@ -54,54 +84,21 @@ class ViewerWidget {

this.viewer.on("ready", () => {
this.channel = this.viewer.open_channel("temp");

this.on_resize(null, {
width: model.get("_width"),
height: model.get("_height"),
});
this.on_change_panel_states(null, this.panel_states);

model.send("ready");
});
}

async start(el: HTMLElement) {
await this.viewer.start(this.url ?? null, el, this.options);

this.on_change_panel_states(null, this.panel_states);
this.viewer.start(this.url ?? null, el, this.options);
this.on_resize(el, model.get("_width"), model.get("_height"));
}

stop() {
this.viewer.stop();
}

on_resize = (_: unknown, new_size: { width?: number; height?: number }) => {
const canvas = this.viewer.canvas;
if (!canvas) throw new Error("on_resize called before viewer ready");

const MIN_WIDTH = 200;
const MIN_HEIGHT = 200;

if (new_size.width) {
const newWidth = Math.max(new_size.width, MIN_WIDTH);
canvas.style.width = `${newWidth}px`;
canvas.style.minWidth = "none";
canvas.style.maxWidth = "none";
} else {
canvas.style.width = "";
canvas.style.minWidth = "";
canvas.style.maxWidth = "";
}

if (new_size.height) {
const newHeight = Math.max(new_size.height, MIN_HEIGHT);
canvas.style.height = `${newHeight}px`;
canvas.style.minHeight = "none";
canvas.style.maxHeight = "none";
} else {
canvas.style.height = "";
canvas.style.minHeight = "";
canvas.style.maxHeight = "";
}
on_resize(parent: HTMLElement, width: number | string, height: number | string) {
_resize(parent, width, height)
};

on_change_url = (_: unknown, new_url?: Opt<string>) => {
Expand Down Expand Up @@ -193,8 +190,10 @@ class ViewerWidget {
const render: Render<WidgetModel> = ({ model, el }) => {
el.classList.add("rerun_notebook");

let widget = new ViewerWidget(model);
widget.start(el);
const container = document.createElement("div");
el.append(container);

let widget = new ViewerWidget(model, container);
return () => widget.stop();
};

Expand Down
8 changes: 4 additions & 4 deletions rerun_notebook/src/rerun_notebook/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ class Viewer(anywidget.AnyWidget): # type: ignore[misc]
#
# Example: `set_time_ctrl` uses `self.send`, and the state of the timeline is exposed via Viewer events.

_width = traitlets.Int(allow_none=True).tag(sync=True)
_height = traitlets.Int(allow_none=True).tag(sync=True)
_width = traitlets.Union([traitlets.Int(), traitlets.Unicode()]).tag(sync=True)
_height = traitlets.Union([traitlets.Int(), traitlets.Unicode()]).tag(sync=True)

_url = traitlets.Unicode(allow_none=True).tag(sync=True)

Expand All @@ -173,8 +173,8 @@ class Viewer(anywidget.AnyWidget): # type: ignore[misc]
def __init__(
self,
*,
width: int | None = None,
height: int | None = None,
width: int | Literal["auto"],
height: int | Literal["auto"],
url: str | None = None,
panel_states: Mapping[Panel, PanelState] | None = None,
fallback_token: str | None = None,
Expand Down
16 changes: 10 additions & 6 deletions rerun_py/rerun_sdk/rerun/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ class Viewer:
def __init__(
self,
*,
width: int | None = None,
height: int | None = None,
width: int | Literal["auto"] | None = None,
height: int | Literal["auto"] | None = None,
url: str | None = None,
blueprint: BlueprintLike | None = None,
recording: RecordingStream | None = None,
Expand All @@ -83,10 +83,14 @@ def __init__(

Parameters
----------
width : int
The width of the viewer in pixels.
height : int
The height of the viewer in pixels.
width:
The width of the viewer in pixels, or "auto".

When set to "auto", scales to 100% of the notebook cell's width.
height:
The height of the viewer in pixels, or "auto".

When set to "auto", scales using a 16:9 aspect ratio with `width`.
url:
Optional URL passed to the viewer for displaying its contents.
recording:
Expand Down