Skip to content

Commit

Permalink
Clear control widget on tab switching. (#94)
Browse files Browse the repository at this point in the history
* Clear control widget on tab switching.

* add ui test
  • Loading branch information
trungleduc authored Jun 27, 2023
1 parent a538f01 commit e68c896
Show file tree
Hide file tree
Showing 16 changed files with 1,670 additions and 1,434 deletions.
2 changes: 2 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export namespace CommandIDs {
export const newTable = 'glue-control:new-table-viewer';

export const openControlPanel = 'glue-control:open-control-panel';

export const closeControlPanel = 'glue-control:close-control-panel';
}

export interface INewViewerArgs {
Expand Down
12 changes: 12 additions & 0 deletions src/document/sharedModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ export class GlueSessionSharedModel
return this._tabsChanged;
}

get localStateChanged(): ISignal<
IGlueSessionSharedModel,
{ keys: string[] }
> {
return this._localStateChanged;
}

getValue(key: string): IDict | undefined {
const content = this._contents.get(key);
if (!content) {
Expand Down Expand Up @@ -194,6 +201,7 @@ export class GlueSessionSharedModel
value: tab,
emitter: emitter
});
this._localStateChanged.emit({ keys: ['selectedTab'] });
}

getSelectedTab(): number | null {
Expand Down Expand Up @@ -273,4 +281,8 @@ export class GlueSessionSharedModel
private _linksChanged = new Signal<IGlueSessionSharedModel, IDict>(this);
private _tabChanged = new Signal<IGlueSessionSharedModel, IDict>(this);
private _tabsChanged = new Signal<IGlueSessionSharedModel, IDict>(this);
private _localStateChanged = new Signal<
IGlueSessionSharedModel,
{ keys: string[] }
>(this);
}
6 changes: 6 additions & 0 deletions src/leftPanel/config/configPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ export class ConfigPanel extends SidePanel {
private _createHeader(): void {
this.toolbar.addItem('Header', this._panelHeader);
this._model.displayConfigRequested.connect(this._updateHeader, this);
this._model.clearConfigRequested.connect(() => {
this._panelHeader.node.innerHTML = '';
if (this._model.currentSessionWidget) {
this._headerData.delete(this._model.currentSessionWidget);
}
}, this);
}

private _updateHeader(
Expand Down
16 changes: 16 additions & 0 deletions src/leftPanel/config/configWidgetModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class ConfigWidgetModel implements IDisposable {
this._config = options.config;
this._model.glueSessionChanged.connect(this._sessionChanged, this);
this._model.displayConfigRequested.connect(this._showConfig, this);
this._model.clearConfigRequested.connect(this._clearConfig, this);
}

get config(): 'Layer' | 'Viewer' {
Expand All @@ -43,9 +44,24 @@ export class ConfigWidgetModel implements IDisposable {

this._disposed = true;
this._model.glueSessionChanged.disconnect(this._sessionChanged);
this._model.displayConfigRequested.disconnect(this._showConfig);
this._model.clearConfigRequested.disconnect(this._clearConfig);

Signal.clearData(this);
}

private _clearConfig(): void {
const context = this._model.currentSessionContext();

if (context && this._currentSessionWidget) {
const output = this._outputs.get(this._currentSessionWidget);
if (!output) {
return;
}
output.model.clear();
this._currentArgs = undefined;
}
}
private _showConfig(
sender: IControlPanelModel,
args: IRequestConfigDisplay
Expand Down
8 changes: 7 additions & 1 deletion src/leftPanel/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ export class ControlPanelModel implements IControlPanelModel {
> {
return this._displayConfigRequested;
}
get clearConfigRequested(): ISignal<IControlPanelModel, void> {
return this._clearConfigRequested;
}

get selectedDataset(): string | null {
return this._selectedDataset;
Expand Down Expand Up @@ -80,7 +83,9 @@ export class ControlPanelModel implements IControlPanelModel {
displayConfig(args: IRequestConfigDisplay): void {
this._displayConfigRequested.emit(args);
}

clearConfig(): void {
this._clearConfigRequested.emit();
}
private _onTabsChanged(_: any, e: any): void {
this._tabs = this._sessionModel?.sharedModel.tabs ?? {};
this._tabsChanged.emit();
Expand All @@ -100,6 +105,7 @@ export class ControlPanelModel implements IControlPanelModel {
IControlPanelModel,
IRequestConfigDisplay
>(this);
private _clearConfigRequested = new Signal<IControlPanelModel, void>(this);

private _sessionModel?: IGlueSessionModel;
}
Expand Down
9 changes: 9 additions & 0 deletions src/leftPanel/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,15 @@ function addCommands(
});
}
});

commands.addCommand(CommandIDs.closeControlPanel, {
execute: () => {
if (!controlModel.sharedModel) {
return;
}
controlModel.clearConfig();
}
});
}

export const controlPanel: JupyterFrontEndPlugin<void> = {
Expand Down
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface IGlueSessionSharedModel
linksChanged: ISignal<IGlueSessionSharedModel, IDict>;
tabChanged: ISignal<IGlueSessionSharedModel, IDict>;
tabsChanged: ISignal<IGlueSessionSharedModel, IDict>;

localStateChanged: ISignal<IGlueSessionSharedModel, { keys: string[] }>;
addTab(): void;
getTabNames(): string[];
getTabData(tabName: string): IDict<IGlueSessionViewerTypes> | undefined;
Expand Down Expand Up @@ -104,8 +104,10 @@ export interface IControlPanelModel {
tabsChanged: ISignal<IControlPanelModel, void>;
currentSessionWidget: IGlueSessionWidget | null;
displayConfigRequested: ISignal<IControlPanelModel, IRequestConfigDisplay>;
clearConfigRequested: ISignal<IControlPanelModel, void>;
getTabs(): IGlueSessionTabs;
displayConfig(args: IRequestConfigDisplay): void;
clearConfig(): void;
currentSessionContext(): ISessionContext | undefined;
}

Expand Down
1 change: 1 addition & 0 deletions src/viewPanel/sessionWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ export class SessionWidget extends BoxPanel {
args: TabBar.ICurrentChangedArgs<Widget>
) {
this._model.setSelectedTab(args.currentIndex);
this._commands.execute(CommandIDs.closeControlPanel);
}

private _spinner: HTMLDivElement;
Expand Down
148 changes: 91 additions & 57 deletions src/viewPanel/tabLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,62 +111,53 @@ export class TabLayout extends Layout {
}

/**
* Dispose of the resources held by the widget.
* Create an iterator over the widgets in the layout.
*
* @returns A new iterator over the widgets in the layout.
*/
dispose(): void {
this._grid.destroy();
super.dispose();
*[Symbol.iterator](): IterableIterator<Widget> {
yield* this._gridItems.values();
}

/**
* Init the gridstack layout
* Helper to get access to underlying GridStack object
*/
init(): void {
super.init();
if (this.parent) {
this.parent.node.appendChild(this._gridHost);
}
// fake window resize event to resize bqplot
window.dispatchEvent(new Event('resize'));
get grid(): GridStack {
return this._grid;
}

/**
* Handle `update-request` messages sent to the widget.
* Get the list of `GridStackItem` (Lumino widgets).
*/
protected onUpdateRequest(msg: Message): void {
const items = this._grid?.getGridItems();
items?.forEach(item => {
this._grid.removeWidget(item, true, false);
this._grid.addWidget(item);
});
get gridItems(): Map<string, GridStackItem> {
return this._gridItems;
}

/**
* Handle `resize-request` messages sent to the widget.
* Get the list of `GridItemHTMLElement`.
*/
protected onResize(msg: Message): void {
// Using timeout to wait until the resize stop
// rerendering all the widgets every time uses
// too much resources
clearTimeout(this._resizeTimeout);
this._resizeTimeout = setTimeout(this._onResizeStops, 500);
this._prepareGrid();
get gridElements(): GridItemHTMLElement[] {
return this._grid.getGridItems() ?? [];
}

/**
* Handle `fit-request` messages sent to the widget.
* Dispose of the resources held by the widget.
*/
protected onFitRequest(msg: Message): void {
this._prepareGrid();
dispose(): void {
this._grid.destroy();
super.dispose();
}

/**
* Create an iterator over the widgets in the layout.
*
* @returns A new iterator over the widgets in the layout.
* Init the gridstack layout
*/
*[Symbol.iterator](): IterableIterator<Widget> {
yield* this._gridItems.values();
init(): void {
super.init();
if (this.parent) {
this.parent.node.appendChild(this._gridHost);
}
// fake window resize event to resize bqplot
window.dispatchEvent(new Event('resize'));
}

/**
Expand All @@ -178,27 +169,6 @@ export class TabLayout extends Layout {
return;
}

/**
* Helper to get access to underlying GridStack object
*/
get grid(): GridStack {
return this._grid;
}

/**
* Get the list of `GridStackItem` (Lumino widgets).
*/
get gridItems(): Map<string, GridStackItem> {
return this._gridItems;
}

/**
* Get the list of `GridItemHTMLElement`.
*/
get gridElements(): GridItemHTMLElement[] {
return this._grid.getGridItems() ?? [];
}

/**
* Add new cell to gridstack.
*
Expand Down Expand Up @@ -273,11 +243,75 @@ export class TabLayout extends Layout {
items?.forEach(item => this._grid.removeWidget(item, true, false));
}

/**
* Unselect all items of the grid layout.
*/
unselectGridItems(): void {
this._grid.getGridItems().forEach(i => i.classList.remove('grid-selected'));
}

/**
* Handle `update-request` messages sent to the widget.
*/
protected onUpdateRequest(msg: Message): void {
const items = this._grid?.getGridItems();
items?.forEach(item => {
this._grid.removeWidget(item, true, false);
this._grid.addWidget(item);
});
}

/**
* Handle `resize-request` messages sent to the widget.
*/
protected onResize(msg: Message): void {
// Using timeout to wait until the resize stop
// rerendering all the widgets every time uses
// too much resources
clearTimeout(this._resizeTimeout);
this._resizeTimeout = setTimeout(this._onResizeStops, 500);
this._prepareGrid();
}

/**
* Handle `fit-request` messages sent to the widget.
*/
protected onFitRequest(msg: Message): void {
this._prepareGrid();
}

/**
* Handle `after-attach` messages sent to the widget.
*/
protected onAfterAttach(msg: Message): void {
super.onAfterAttach(msg);
this._gridHost.addEventListener('click', this._onClick.bind(this));
}

/**
* Handle `before-attach` messages sent to the widget.
*/
protected onBeforeDetach(msg: Message): void {
this._gridHost.removeEventListener('click', this._onClick.bind(this));

super.onBeforeDetach(msg);
}

/**
* Handle click event to the widget.
*/
private _onClick(event: MouseEvent) {
if (event.target === event.currentTarget) {
this._commands.execute(CommandIDs.closeControlPanel);
this.unselectGridItems();
}
}

/**
* Handle edit request of a grid item.
*/
private _handleEdit(item: GridStackItem): void {
this._grid.getGridItems().forEach(i => i.classList.remove('grid-selected'));
this.unselectGridItems();
item.node.classList.add('grid-selected');
this._commands.execute(CommandIDs.openControlPanel, {
cellId: item.cellIdentity,
Expand Down
11 changes: 10 additions & 1 deletion src/viewPanel/tabView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class TabView extends Widget {

layout.gridItemChanged.connect(this._onLayoutChanged, this);
this._model.tabChanged.connect(this._onTabChanged, this);
this._model.localStateChanged.connect(this._onLocalStateChanged, this);
}

dispose(): void {
Expand All @@ -49,7 +50,7 @@ export class TabView extends Widget {
this
);
this._model.tabChanged.disconnect(this._onTabChanged, this);

this._model.localStateChanged.disconnect(this._onLocalStateChanged);
super.dispose();
}

Expand Down Expand Up @@ -321,6 +322,14 @@ export class TabView extends Widget {
}
}

private _onLocalStateChanged(
sender: IGlueSessionSharedModel,
changes: { keys: string[] }
) {
if (changes.keys.includes('selectedTab')) {
(this.layout as TabLayout).unselectGridItems();
}
}
private _selectedItem: GridStackItem | null = null;
private _model: IGlueSessionSharedModel;
private _context: DocumentRegistry.IContext<GlueSessionModel>;
Expand Down
Loading

0 comments on commit e68c896

Please sign in to comment.