Skip to content

Commit f004907

Browse files
committed
demo 3 fixes
1 parent 278d970 commit f004907

File tree

7 files changed

+153
-63
lines changed

7 files changed

+153
-63
lines changed

src/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ export namespace CommandIDs {
1616
export const startFullscreen = 'dashboard:start-fullscreen';
1717
export const createNew = 'dashboard:create-new';
1818
export const enableGrid = 'dashboard:enable-grid';
19+
export const setGridSize = 'dashboard:set-grid-size';
1920
}

src/custom_layout.ts

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,16 @@ export class DashboardLayout extends Layout {
235235
widget: DashboardWidget,
236236
pos: Widgetstore.WidgetPosition
237237
): boolean {
238-
this.startBatch();
238+
const wasInBatch = this.inBatch;
239+
if (!wasInBatch) {
240+
this.startBatch();
241+
}
242+
239243
const success = this._updateWidget(widget, pos);
240-
this.endBatch();
244+
245+
if (!wasInBatch) {
246+
this.endBatch();
247+
}
241248
return success;
242249
}
243250

@@ -287,10 +294,10 @@ export class DashboardLayout extends Layout {
287294

288295
// Snap to grid if in grid mode.
289296
if (this._mode === 'grid') {
290-
left = mround(left, this._gridWidth);
291-
top = mround(top, this._gridHeight);
292-
width = Math.max(mround(width, this._gridWidth), this._gridWidth);
293-
height = Math.max(mround(height, this._gridHeight), this._gridHeight);
297+
left = mround(left, this._gridSize);
298+
top = mround(top, this._gridSize);
299+
width = Math.max(mround(width, this._gridSize), this._gridSize);
300+
height = Math.max(mround(height, this._gridSize), this._gridSize);
294301
// Change width/height now to force grid changes if they're small.
295302
item.update(0, 0, 0, 0);
296303
}
@@ -531,7 +538,7 @@ export class DashboardLayout extends Layout {
531538
each(overlaps, (overlap) => void this._handleOverlap(pos, overlap));
532539
}
533540

534-
fixOverlaps(widget: DashboardWidget) {
541+
fixOverlaps(widget: DashboardWidget): void {
535542
const overlaps = filter(
536543
this._widgetsInSelection(widget.pos),
537544
(overlap) => overlap.widget !== widget
@@ -678,16 +685,60 @@ export class DashboardLayout extends Layout {
678685
let { left, top, width, height } = pos;
679686

680687
if (this.mode === 'grid') {
681-
width = Math.max(mround(width, this._gridWidth), this._gridWidth);
682-
height = Math.max(mround(height, this._gridHeight), this._gridWidth);
683-
left = mround(left, this._gridWidth);
684-
top = mround(top, this._gridHeight);
688+
width = Math.max(mround(width, this._gridSize), this._gridSize);
689+
height = Math.max(mround(height, this._gridSize), this._gridSize);
690+
left = mround(left, this._gridSize);
691+
top = mround(top, this._gridSize);
685692
}
686693

687694
context.strokeRect(left, top, width, height);
688695
context.fillRect(left, top, width, height);
689696
}
690697

698+
set gridSize(s: number) {
699+
this._gridSize = s;
700+
const backgroundPosition = `0 0, 0 ${s}px, ${s}px -${s}px, -${s}px 0px`;
701+
702+
this.canvas.style.backgroundPosition = backgroundPosition;
703+
this.canvas.style.backgroundSize = `${2 * s}px ${2 * s}px`;
704+
this.parent.update();
705+
706+
this.startBatch();
707+
each(this, (_widget) => {
708+
const widget = _widget as DashboardWidget;
709+
this.updateWidget(widget, widget.pos);
710+
});
711+
this.endBatch();
712+
}
713+
714+
get gridSize(): number {
715+
return this._gridSize;
716+
}
717+
718+
trimCanvas(): void {
719+
const model = (this.parent as Dashboard).model;
720+
let maxWidth = 0;
721+
let maxHeight = 0;
722+
723+
each(this, (_widget) => {
724+
const widget = _widget as DashboardWidget;
725+
const { left, top, width, height } = widget.pos;
726+
if (left + width > maxWidth) {
727+
maxWidth = left + width;
728+
}
729+
if (top + height > maxHeight) {
730+
maxHeight = top + height;
731+
}
732+
});
733+
734+
if (maxWidth) {
735+
model.width = maxWidth;
736+
}
737+
if (maxHeight) {
738+
model.height = maxHeight;
739+
}
740+
}
741+
691742
// Map from widget ids to LayoutItems
692743
private _items: Map<string, LayoutItem>;
693744
// Datastore widgets are rendered from / saved to.
@@ -705,8 +756,7 @@ export class DashboardLayout extends Layout {
705756
// Parent dashboard.
706757
private _dashboard: Dashboard;
707758

708-
private _gridWidth = 100;
709-
private _gridHeight = 100;
759+
private _gridSize = 50;
710760

711761
// Changed signal
712762
private _changed = new Signal<this, IDashboardChange[]>(this);

src/dashboard.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export class Dashboard extends Widget {
8989
this.node.addEventListener('lm-dragover', this, true);
9090
this.node.addEventListener('lm-drop', this, true);
9191
this.node.addEventListener('lm-dragend', this, true);
92+
this.node.addEventListener('scroll', this);
9293
}
9394

9495
/**
@@ -100,6 +101,7 @@ export class Dashboard extends Widget {
100101
this.node.removeEventListener('lm-dragleave', this, true);
101102
this.node.removeEventListener('lm-dragover', this, true);
102103
this.node.removeEventListener('lm-drop', this, true);
104+
this.node.removeEventListener('scroll', this);
103105
}
104106

105107
/**
@@ -204,6 +206,9 @@ export class Dashboard extends Widget {
204206

205207
handleEvent(event: Event): void {
206208
switch (event.type) {
209+
case 'scroll':
210+
this._evtScroll(event);
211+
break;
207212
case 'lm-dragenter':
208213
this._evtDragEnter(event as IDragEvent);
209214
break;
@@ -219,6 +224,29 @@ export class Dashboard extends Widget {
219224
}
220225
}
221226

227+
private _evtScroll(_event: Event): void {
228+
const model = this.model;
229+
230+
console.log('scrollMode', model.scrollMode);
231+
if (model.scrollMode !== 'infinite') {
232+
return;
233+
}
234+
235+
const elem = this.node;
236+
const rightEdge = elem.offsetWidth + elem.scrollLeft;
237+
const bottomEdge = elem.offsetHeight + elem.scrollTop;
238+
239+
if (rightEdge >= model.width && rightEdge > this._oldRightEdge) {
240+
model.width += 200;
241+
}
242+
if (bottomEdge >= model.height && bottomEdge > this._oldBottomEdge) {
243+
model.height += 200;
244+
}
245+
246+
this._oldBottomEdge = bottomEdge;
247+
this._oldRightEdge = rightEdge;
248+
}
249+
222250
/**
223251
* Add a widget to the layout.
224252
*
@@ -320,6 +348,8 @@ export class Dashboard extends Widget {
320348

321349
private _model: IDashboardModel;
322350
private _context: DocumentRegistry.IContext<DocumentRegistry.IModel>;
351+
private _oldRightEdge = 0;
352+
private _oldBottomEdge = 0;
323353
}
324354

325355
/**
@@ -328,9 +358,11 @@ export class Dashboard extends Widget {
328358
export namespace Dashboard {
329359
export type Mode = 'edit' | 'present' | 'grid';
330360

331-
export const DEFAULT_WIDTH = 1270;
361+
export type ScrollMode = 'infinite' | 'constrained';
362+
363+
export const DEFAULT_WIDTH = 1920;
332364

333-
export const DEFAULT_HEIGHT = 720;
365+
export const DEFAULT_HEIGHT = 1080;
334366

335367
export interface IOptions extends Widget.IOptions {
336368
/**

src/index.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ import {
55

66
import { INotebookTracker } from '@jupyterlab/notebook';
77

8-
import { WidgetTracker, showDialog, Dialog } from '@jupyterlab/apputils';
8+
import {
9+
WidgetTracker,
10+
showDialog,
11+
Dialog,
12+
InputDialog,
13+
} from '@jupyterlab/apputils';
914

1015
import { CodeCell } from '@jupyterlab/cells';
1116

@@ -48,6 +53,8 @@ import { CommandIDs } from './commands';
4853

4954
import { ReadonlyJSONObject } from '@lumino/coreutils';
5055

56+
import { DashboardLayout } from './custom_layout';
57+
5158
const extension: JupyterFrontEndPlugin<IDashboardTracker> = {
5259
id: 'jupyterlab-interactive-dashboard-editor',
5360
autoStart: true,
@@ -113,19 +120,17 @@ const extension: JupyterFrontEndPlugin<IDashboardTracker> = {
113120

114121
app.docRegistry.addModelFactory(modelFactory);
115122
app.docRegistry.addWidgetFactory(widgetFactory);
116-
widgetFactory.widgetCreated.connect((sender, widget) => {
123+
widgetFactory.widgetCreated.connect((_sender, widget) => {
117124
void dashboardTracker.add(widget.content);
118125

119126
widget.title.icon = dashboardFiletype.icon;
120127
widget.title.iconClass = dashboardFiletype.iconClass || '';
121128
widget.title.iconLabel = dashboardFiletype.iconLabel || '';
122129

123130
const model = widget.content.model;
124-
model.loaded.connect(() => {
125-
if (!model.width && !model.height) {
126-
app.commands.execute(CommandIDs.setDimensions);
127-
}
128-
});
131+
model.scrollMode = 'infinite';
132+
model.width = Dashboard.DEFAULT_WIDTH;
133+
model.height = Dashboard.DEFAULT_HEIGHT;
129134
});
130135

131136
// Add commands to context menus.
@@ -257,6 +262,9 @@ const extension: JupyterFrontEndPlugin<IDashboardTracker> = {
257262
{
258263
command: CommandIDs.setDimensions,
259264
},
265+
{
266+
command: CommandIDs.setGridSize,
267+
},
260268
]);
261269

262270
mainMenu.fileMenu.newMenu.addGroup([
@@ -445,6 +453,20 @@ function addCommands(
445453
isEnabled: hasDashboard,
446454
});
447455

456+
commands.addCommand(CommandIDs.setGridSize, {
457+
label: 'Set Grid Dimensions',
458+
execute: async (args) => {
459+
const newSize = await InputDialog.getNumber({
460+
title: 'Enter Grid Size',
461+
});
462+
if (newSize.value) {
463+
const layout = dashboardTracker.currentWidget.layout as DashboardLayout;
464+
layout.gridSize = newSize.value;
465+
}
466+
},
467+
isEnabled: hasDashboard,
468+
});
469+
448470
commands.addCommand(CommandIDs.copy, {
449471
label: (args) => (inToolbar(args) ? '' : 'Copy'),
450472
icon: copyIcon,

src/model.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ export interface IDashboardModel extends DocumentRegistry.IModel {
6262
width: number;
6363

6464
height: number;
65+
66+
scrollMode: Dashboard.ScrollMode;
6567
}
6668

6769
export class DashboardModel extends DocumentModel implements IDashboardModel {
@@ -253,6 +255,13 @@ export class DashboardModel extends DocumentModel implements IDashboardModel {
253255
return this._loaded;
254256
}
255257

258+
get scrollMode(): Dashboard.ScrollMode {
259+
return this._scrollMode;
260+
}
261+
set scrollMode(newValue: Dashboard.ScrollMode) {
262+
this._scrollMode = newValue;
263+
}
264+
256265
/**
257266
* The widget store for the dashboard.
258267
*/
@@ -273,6 +282,7 @@ export class DashboardModel extends DocumentModel implements IDashboardModel {
273282
private _path: string;
274283
private _mode: Dashboard.Mode = 'edit';
275284
private _docManager: IDocumentManager;
285+
private _scrollMode: Dashboard.ScrollMode = 'constrained';
276286
}
277287

278288
/**

src/widget.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ const EDITABLE_WIDGET_CLASS = 'pr-EditableWidget';
4242

4343
const IN_DRAG_CLASS = 'pr-InDrag';
4444

45-
const WIDGET_OVERLAY_CLASS = 'pr-WidgetOverlay';
46-
4745
/**
4846
* Widget to wrap delete/move/etc functionality of widgets in a dashboard (future).
4947
*/
@@ -118,7 +116,7 @@ export class DashboardWidget extends Widget {
118116
this.fitContent();
119117
}
120118
// Make widget visible again.
121-
this.node.style.opacity = '1.0';
119+
this.node.style.opacity = null;
122120
// Emit the ready signal.
123121
this._ready.emit(undefined);
124122
};
@@ -134,9 +132,6 @@ export class DashboardWidget extends Widget {
134132

135133
this.addClass(DASHBOARD_WIDGET_CLASS);
136134
this.addClass(EDITABLE_WIDGET_CLASS);
137-
this._overlay = document.createElement('div');
138-
this._overlay.classList.add(WIDGET_OVERLAY_CLASS);
139-
this.node.appendChild(this._overlay);
140135
}
141136

142137
/**
@@ -359,8 +354,8 @@ export class DashboardWidget extends Widget {
359354
width: 0,
360355
height: 0,
361356
};
362-
const overlaps = this.overlaps(pos);
363-
return overlaps.type !== 'none';
357+
const overlap = this.overlaps(pos);
358+
return overlap.type !== 'none';
364359
}
365360

366361
overlaps(_pos: Widgetstore.WidgetPosition): DashboardWidget.Overlap {
@@ -421,7 +416,7 @@ export class DashboardWidget extends Widget {
421416
if (this.isDisposed) {
422417
return;
423418
}
424-
this.node.style.opacity = '1.0';
419+
this.node.style.opacity = null;
425420
this.node.style.pointerEvents = 'auto';
426421
this.removeClass(IN_DRAG_CLASS);
427422
this._drag = null;
@@ -433,7 +428,7 @@ export class DashboardWidget extends Widget {
433428
event.stopPropagation();
434429
event.preventDefault();
435430

436-
this.node.style.opacity = '1.0';
431+
this.node.style.opacity = null;
437432

438433
if (this._mouseMode === 'resize' && this.parent !== undefined) {
439434
const pos = this.pos;
@@ -547,10 +542,8 @@ export class DashboardWidget extends Widget {
547542
this._mode = newMode;
548543
if (newMode === 'present') {
549544
this.removeClass(EDITABLE_WIDGET_CLASS);
550-
this._overlay.classList.remove(WIDGET_OVERLAY_CLASS);
551545
} else {
552546
this.addClass(EDITABLE_WIDGET_CLASS);
553-
this._overlay.classList.add(WIDGET_OVERLAY_CLASS);
554547
}
555548
if (newMode === 'grid') {
556549
if (this.parent) {
@@ -594,7 +587,6 @@ export class DashboardWidget extends Widget {
594587
widgetY: number;
595588
} | null = null;
596589
private _locked = false;
597-
private _overlay: HTMLElement;
598590
private _content: Widget;
599591
}
600592

0 commit comments

Comments
 (0)