Skip to content

Commit 40816a0

Browse files
committed
Implement static plot zoom
1 parent 065d575 commit 40816a0

File tree

7 files changed

+44
-14
lines changed

7 files changed

+44
-14
lines changed

src/vs/workbench/contrib/positronPlots/browser/components/plotsContainer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,12 @@ export const PlotsContainer = (props: PlotContainerProps) => {
180180
height={plotHeight}
181181
plotClient={plotInstance}
182182
width={plotWidth}
183-
zoom={plotInstance.metadata.zoom_level} />;
183+
zoom={plotInstance.zoomLevel} />;
184184
} else if (plotInstance instanceof StaticPlotClient) {
185185
return <StaticPlotInstance
186186
key={plotInstance.id}
187187
plotClient={plotInstance}
188-
zoom={plotInstance.metadata.zoom_level} />;
188+
zoom={plotInstance.zoomLevel} />;
189189
} else if (plotInstance instanceof WebviewPlotClient) {
190190
return <WebviewPlotInstance
191191
key={plotInstance.id}

src/vs/workbench/contrib/positronPlots/browser/components/staticPlotInstance.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import React, { useEffect, useRef, useState } from 'react';
88

99
// Other dependencies.
1010
import { PanZoomImage } from './panZoomImage.js';
11-
import { ZoomLevel } from './zoomPlotMenuButton.js';
1211
import { StaticPlotClient } from '../../../../services/positronPlots/common/staticPlotClient.js';
12+
import { ZoomLevel } from '../../../../services/positronPlots/common/positronPlots.js';
1313

1414
/**
1515
* StaticPlotInstanceProps interface.

src/vs/workbench/contrib/positronPlots/browser/positronPlotsService.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { ILanguageRuntimeMessageOutput, LanguageRuntimeSessionMode, RuntimeOutpu
1010
import { ILanguageRuntimeSession, IRuntimeClientInstance, IRuntimeSessionService, RuntimeClientType } from '../../../services/runtimeSession/common/runtimeSessionService.js';
1111
import { HTMLFileSystemProvider } from '../../../../platform/files/browser/htmlFileSystemProvider.js';
1212
import { IFileService } from '../../../../platform/files/common/files.js';
13-
import { createSuggestedFileNameForPlot, DarkFilter, HistoryPolicy, IPositronPlotClient, IPositronPlotsService, PlotRenderFormat, PlotRenderSettings, POSITRON_PLOTS_VIEW_ID, ZoomLevel } from '../../../services/positronPlots/common/positronPlots.js';
13+
import { createSuggestedFileNameForPlot, DarkFilter, HistoryPolicy, IPositronPlotClient, IPositronPlotsService, isZoomablePlotClient, PlotRenderFormat, PlotRenderSettings, POSITRON_PLOTS_VIEW_ID, ZoomLevel } from '../../../services/positronPlots/common/positronPlots.js';
1414
import { Emitter, Event } from '../../../../base/common/event.js';
1515
import { StaticPlotClient } from '../../../services/positronPlots/common/staticPlotClient.js';
1616
import { IStorageService, StorageTarget, StorageScope } from '../../../../platform/storage/common/storage.js';
@@ -566,11 +566,13 @@ export class PositronPlotsService extends Disposable implements IPositronPlotsSe
566566

567567
setEditorPlotZoom(plotId: string, zoomLevel: ZoomLevel): void {
568568
const plot = this._editorPlots.get(plotId);
569-
if (plot instanceof PlotClientInstance) {
569+
570+
if (isZoomablePlotClient(plot)) {
570571
plot.zoomLevel = zoomLevel;
571572
this.storePlotMetadata(plot.metadata);
572573
} else {
573-
this._notificationService.error(localize('positronPlots.zoom.setInvalidPlotType', 'Cannot set zoom for this plot type'));
574+
// plot not found, show an error
575+
this._notificationService.error(localize('positronPlots.zoom.invalidPlotId', 'Plot not found: {0}', plotId));
574576
}
575577
}
576578

src/vs/workbench/contrib/positronPlotsEditor/browser/editorPlotsContainer.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import React, { useEffect, useState } from 'react';
1313
import { DynamicPlotInstance } from '../../positronPlots/browser/components/dynamicPlotInstance.js';
1414
import { StaticPlotInstance } from '../../positronPlots/browser/components/staticPlotInstance.js';
1515
import { PlotClientInstance } from '../../../services/languageRuntime/common/languageRuntimePlotClient.js';
16-
import { IPositronPlotClient, IPositronPlotsService, ZoomLevel } from '../../../services/positronPlots/common/positronPlots.js';
16+
import { IPositronPlotClient, IPositronPlotsService, ZoomLevel, isZoomablePlotClient } from '../../../services/positronPlots/common/positronPlots.js';
1717
import { StaticPlotClient } from '../../../services/positronPlots/common/staticPlotClient.js';
1818
import { DisposableStore } from '../../../../base/common/lifecycle.js';
1919

@@ -66,15 +66,14 @@ export const EditorPlotsContainer = (props: EditorPlotsContainerProps) => {
6666
// Create the disposable store for cleanup.
6767
const disposableStore = new DisposableStore();
6868

69-
// listen to the plots service for zoom level changes
70-
if (props.plotClient instanceof PlotClientInstance) {
69+
if (isZoomablePlotClient(props.plotClient)) {
70+
// listen to the plots service for zoom level changes
7171
disposableStore.add(props.plotClient.onDidChangeZoomLevel((zoomLevel) => {
7272
setZoom(zoomLevel);
7373
}));
7474
setZoom(props.plotClient.zoomLevel);
7575
}
7676

77-
7877
// Return the cleanup function that will dispose of the event handlers.
7978
return () => disposableStore.dispose();
8079
}, [props.plotClient]);

src/vs/workbench/services/languageRuntime/common/languageRuntimePlotClient.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { Disposable, IDisposable } from '../../../../base/common/lifecycle.js';
77
import { Event, Emitter } from '../../../../base/common/event.js';
8-
import { IPositronPlotClient, ZoomLevel } from '../../positronPlots/common/positronPlots.js';
8+
import { IPositronPlotClient, IZoomablePlotClient, ZoomLevel } from '../../positronPlots/common/positronPlots.js';
99
import { IntrinsicSize, PlotResult, PlotRenderFormat } from './positronPlotComm.js';
1010
import { IPlotSize, IPositronPlotSizingPolicy } from '../../positronPlots/common/sizingPolicy.js';
1111
import { PositronPlotCommProxy } from './positronPlotCommProxy.js';
@@ -82,7 +82,7 @@ export interface IPositronPlotMetadata {
8282
* An instance of a plot client widget generated by a language runtime. A plot can be rendered
8383
* by calling the `render` method, which returns a promise that resolves to the rendered plot.
8484
*/
85-
export class PlotClientInstance extends Disposable implements IPositronPlotClient {
85+
export class PlotClientInstance extends Disposable implements IPositronPlotClient, IZoomablePlotClient {
8686
/**
8787
* The currently active render request, if any.
8888
*/

src/vs/workbench/services/positronPlots/common/positronPlots.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ export interface IPositronPlotClient extends IDisposable {
2121
readonly metadata: IPositronPlotMetadata;
2222
}
2323

24+
export interface IZoomablePlotClient {
25+
zoomLevel: ZoomLevel;
26+
27+
onDidChangeZoomLevel: Event<ZoomLevel>;
28+
}
29+
2430
export enum ZoomLevel {
2531
Fit = 0,
2632
Fifty = 0.5,
@@ -76,6 +82,11 @@ export enum DarkFilter {
7682
Auto = 'auto'
7783
}
7884

85+
export const isZoomablePlotClient = (obj: any): obj is IZoomablePlotClient => {
86+
return 'zoomLevel' in obj && typeof obj.zoomLevel === 'number' &&
87+
'onDidChangeZoomLevel' in obj && typeof obj.onDidChangeZoomLevel === 'function';
88+
};
89+
7990
/**
8091
* Creates a suggested file name for a plot.
8192
* @param storageService The storage service to use.

src/vs/workbench/services/positronPlots/common/staticPlotClient.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,26 @@
33
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import { Emitter, Event } from '../../../../base/common/event.js';
67
import { Disposable } from '../../../../base/common/lifecycle.js';
78
import { IStorageService } from '../../../../platform/storage/common/storage.js';
89
import { IPositronPlotMetadata } from '../../languageRuntime/common/languageRuntimePlotClient.js';
910
import { ILanguageRuntimeMessageOutput } from '../../languageRuntime/common/languageRuntimeService.js';
10-
import { createSuggestedFileNameForPlot, IPositronPlotClient, ZoomLevel } from './positronPlots.js';
11+
import { createSuggestedFileNameForPlot, IPositronPlotClient, IZoomablePlotClient, ZoomLevel } from './positronPlots.js';
1112

1213
/**
1314
* Creates a static plot client from a language runtime message.
1415
*/
15-
export class StaticPlotClient extends Disposable implements IPositronPlotClient {
16+
export class StaticPlotClient extends Disposable implements IPositronPlotClient, IZoomablePlotClient {
1617
public readonly metadata: IPositronPlotMetadata;
1718
public readonly mimeType;
1819
public readonly data;
1920

21+
// Zoom level emitter
22+
public onDidChangeZoomLevel: Event<ZoomLevel>;
23+
24+
private readonly _zoomLevelEventEmitter = new Emitter<ZoomLevel>();
25+
2026
constructor(storageService: IStorageService, sessionId: string, message: ILanguageRuntimeMessageOutput,
2127
public readonly code?: string) {
2228
super();
@@ -48,6 +54,9 @@ export class StaticPlotClient extends Disposable implements IPositronPlotClient
4854
// Save the MIME type and data for the image.
4955
this.mimeType = imageKey;
5056
this.data = data;
57+
58+
// Set up the zoom level event emitter.
59+
this.onDidChangeZoomLevel = this._zoomLevelEventEmitter.event;
5160
}
5261

5362
get uri() {
@@ -61,4 +70,13 @@ export class StaticPlotClient extends Disposable implements IPositronPlotClient
6170
get id() {
6271
return this.metadata.id;
6372
}
73+
74+
set zoomLevel(zoom: ZoomLevel) {
75+
this.metadata.zoom_level = zoom;
76+
this._zoomLevelEventEmitter.fire(zoom);
77+
}
78+
79+
get zoomLevel(): ZoomLevel {
80+
return this.metadata.zoom_level ?? ZoomLevel.Fit;
81+
}
6482
}

0 commit comments

Comments
 (0)