diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index b8a8325af3931..fd12b0179c1e3 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -20,6 +20,8 @@ import { dispose } from 'vs/base/common/lifecycle'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IFileService } from 'vs/platform/files/common/files'; +import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; export interface IOpenCallbacks { openInternal: (input: EditorInput, options: EditorOptions) => Promise; @@ -50,7 +52,9 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { themeService: IThemeService, @IFileService private readonly fileService: IFileService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, - @IStorageService storageService: IStorageService + @IStorageService storageService: IStorageService, + @IStatusbarService private readonly statusbarService: IStatusbarService, + @IContextMenuService private readonly contextMenuService: IContextMenuService ) { super(id, telemetryService, themeService, storageService); @@ -97,7 +101,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { openInternalClb: () => this.handleOpenInternalCallback(input, options), openExternalClb: this.environmentService.configuration.remoteAuthority ? undefined : resource => this.callbacks.openExternal(resource), metadataClb: meta => this.handleMetadataChanged(meta) - }); + }, this.statusbarService, this.contextMenuService); } private async handleOpenInternalCallback(input: EditorInput, options: EditorOptions): Promise { diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 5c37926ade2a6..82e919d0d2ab3 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -8,8 +8,6 @@ import * as nls from 'vs/nls'; import { URI, UriComponents } from 'vs/base/common/uri'; import { Action, IAction } from 'vs/base/common/actions'; import { IEditorQuickOpenEntry, IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; -import { StatusbarItemDescriptor, IStatusbarRegistry, Extensions as StatusExtensions } from 'vs/workbench/browser/parts/statusbar/statusbar'; -import { StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar'; import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext } from 'vs/workbench/common/editor'; import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; @@ -49,7 +47,6 @@ import { isMacintosh } from 'vs/base/common/platform'; import { AllEditorsPicker, ActiveEditorGroupPicker } from 'vs/workbench/browser/parts/editor/editorPicker'; import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { OpenWorkspaceButtonContribution } from 'vs/workbench/browser/parts/editor/editorWidgets'; -import { ZoomStatusbarItem } from 'vs/workbench/browser/parts/editor/resourceViewer'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { toLocalResource } from 'vs/base/common/resources'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; @@ -224,16 +221,6 @@ registerEditorContribution(OpenWorkspaceButtonContribution); // Register Editor Status Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorStatus, LifecyclePhase.Ready); -// Register Zoom Status -const statusBar = Registry.as(StatusExtensions.Statusbar); -statusBar.registerStatusbarItem(new StatusbarItemDescriptor( - ZoomStatusbarItem, - 'status.imageZoom', - nls.localize('status.imageZoom', "Image Zoom"), - StatusbarAlignment.RIGHT, - 101 /* to the left of editor status (100) */) -); - // Register Status Actions const registry = Registry.as(ActionExtensions.WorkbenchActions); registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeModeAction, ChangeModeAction.ID, ChangeModeAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_M) }), 'Change Language Mode'); diff --git a/src/vs/workbench/browser/parts/editor/media/resourceviewer.css b/src/vs/workbench/browser/parts/editor/media/resourceviewer.css index af8cc51704a9c..b6f7b107db7b9 100644 --- a/src/vs/workbench/browser/parts/editor/media/resourceviewer.css +++ b/src/vs/workbench/browser/parts/editor/media/resourceviewer.css @@ -58,10 +58,6 @@ cursor: zoom-out; } -.monaco-workbench .part.statusbar > .items-container > .statusbar-item > a.zoom-statusbar-item { - padding: 0 5px 0 5px; -} - .monaco-resource-viewer .embedded-link, .monaco-resource-viewer .embedded-link:hover { cursor: pointer; diff --git a/src/vs/workbench/browser/parts/editor/resourceViewer.ts b/src/vs/workbench/browser/parts/editor/resourceViewer.ts index 65b7706e60d7a..a3772c915a922 100644 --- a/src/vs/workbench/browser/parts/editor/resourceViewer.ts +++ b/src/vs/workbench/browser/parts/editor/resourceViewer.ts @@ -12,16 +12,13 @@ import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableEle import { LRUCache } from 'vs/base/common/map'; import { Schemas } from 'vs/base/common/network'; import { clamp } from 'vs/base/common/numbers'; -import { Themable } from 'vs/workbench/common/theme'; -import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IDisposable, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Action } from 'vs/base/common/actions'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { memoize } from 'vs/base/common/decorators'; import * as platform from 'vs/base/common/platform'; import { IFileService } from 'vs/platform/files/common/files'; +import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar'; export interface IResourceDescriptor { readonly resource: URI; @@ -81,7 +78,9 @@ export class ResourceViewer { fileService: IFileService, container: HTMLElement, scrollbar: DomScrollableElement, - delegate: ResourceViewerDelegate + delegate: ResourceViewerDelegate, + statusbarService: IStatusbarService, + contextMenuService: IContextMenuService ): ResourceViewerContext { // Ensure CSS class @@ -89,7 +88,7 @@ export class ResourceViewer { // Images if (ResourceViewer.isImageResource(descriptor)) { - return ImageView.create(container, descriptor, fileService, scrollbar, delegate); + return ImageView.create(container, descriptor, fileService, scrollbar, delegate, statusbarService, contextMenuService); } // Large Files @@ -120,10 +119,12 @@ class ImageView { descriptor: IResourceDescriptor, fileService: IFileService, scrollbar: DomScrollableElement, - delegate: ResourceViewerDelegate + delegate: ResourceViewerDelegate, + statusbarService: IStatusbarService, + contextMenuService: IContextMenuService ): ResourceViewerContext { if (ImageView.shouldShowImageInline(descriptor)) { - return InlineImageView.create(container, descriptor, fileService, scrollbar, delegate); + return InlineImageView.create(container, descriptor, fileService, scrollbar, delegate, statusbarService, contextMenuService); } return LargeImageView.create(container, descriptor, delegate); @@ -234,71 +235,52 @@ class FileSeemsBinaryFileView { type Scale = number | 'fit'; -export class ZoomStatusbarItem extends Themable implements IStatusbarItem { - - static instance: ZoomStatusbarItem; +export class ZoomStatusbarItem extends Disposable { - private showTimeout: any; + private statusbarItem: IStatusbarEntryAccessor; - private statusBarItem: HTMLElement; - private onSelectScale?: (scale: Scale) => void; + onSelectScale?: (scale: Scale) => void; constructor( - @IContextMenuService private readonly contextMenuService: IContextMenuService, - @IEditorService editorService: IEditorService, - @IThemeService themeService: IThemeService + private readonly contextMenuService: IContextMenuService, + private readonly statusbarService: IStatusbarService ) { - super(themeService); - - ZoomStatusbarItem.instance = this; - - this._register(editorService.onDidActiveEditorChange(() => this.onActiveEditorChanged())); + super(); } - private onActiveEditorChanged(): void { - this.hide(); - this.onSelectScale = undefined; - } + updateStatusbar(scale: Scale, onSelectScale?: (scale: Scale) => void): void { + const entry: IStatusbarEntry = { + text: this.zoomLabel(scale) + }; - show(scale: Scale, onSelectScale: (scale: number) => void) { - clearTimeout(this.showTimeout); - this.showTimeout = setTimeout(() => { + if (onSelectScale) { this.onSelectScale = onSelectScale; - this.statusBarItem.style.display = 'block'; - this.updateLabel(scale); - }, 0); - } + } - hide() { - this.statusBarItem.style.display = 'none'; - } + if (!this.statusbarItem) { + this.statusbarItem = this.statusbarService.addEntry(entry, 'status.imageZoom', nls.localize('status.imageZoom', "Image Zoom"), StatusbarAlignment.RIGHT, 101 /* to the left of editor status (100) */); + + this._register(this.statusbarItem); - render(container: HTMLElement): IDisposable { - if (!this.statusBarItem && container) { - this.statusBarItem = DOM.append(container, DOM.$('a.zoom-statusbar-item')); - this.statusBarItem.setAttribute('role', 'button'); - this.statusBarItem.style.display = 'none'; + const element = document.getElementById('status.imageZoom')!; - DOM.addDisposableListener(this.statusBarItem, DOM.EventType.CLICK, () => { + this._register(DOM.addDisposableListener(element, DOM.EventType.CLICK, (e: MouseEvent) => { this.contextMenuService.showContextMenu({ - getAnchor: () => container, + getAnchor: () => element, getActions: () => this.zoomActions }); - }); + })); + } else { + this.statusbarItem.update(entry); } - - return this; - } - - private updateLabel(scale: Scale) { - this.statusBarItem.textContent = ZoomStatusbarItem.zoomLabel(scale); } @memoize private get zoomActions(): Action[] { const scales: Scale[] = [10, 5, 2, 1, 0.5, 0.2, 'fit']; return scales.map(scale => - new Action(`zoom.${scale}`, ZoomStatusbarItem.zoomLabel(scale), undefined, undefined, () => { + new Action(`zoom.${scale}`, this.zoomLabel(scale), undefined, undefined, () => { + this.updateStatusbar(scale); if (this.onSelectScale) { this.onSelectScale(scale); } @@ -307,7 +289,7 @@ export class ZoomStatusbarItem extends Themable implements IStatusbarItem { })); } - private static zoomLabel(scale: Scale): string { + private zoomLabel(scale: Scale): string { return scale === 'fit' ? nls.localize('zoom.action.fit.label', 'Whole Image') : `${Math.round(scale * 100)}%`; @@ -361,10 +343,15 @@ class InlineImageView { descriptor: IResourceDescriptor, fileService: IFileService, scrollbar: DomScrollableElement, - delegate: ResourceViewerDelegate + delegate: ResourceViewerDelegate, + statusbarService: IStatusbarService, + contextMenuService: IContextMenuService ) { const disposables = new DisposableStore(); + const zoomStatusbarItem = new ZoomStatusbarItem(contextMenuService, statusbarService); + disposables.add(zoomStatusbarItem); + const context: ResourceViewerContext = { layout(dimension: DOM.Dimension) { }, dispose: () => disposables.dispose() @@ -423,7 +410,7 @@ class InlineImageView { InlineImageView.imageStateCache.set(cacheKey, { scale: scale, offsetX: newScrollLeft, offsetY: newScrollTop }); } - ZoomStatusbarItem.instance.show(scale, updateScale); + zoomStatusbarItem.updateStatusbar(scale, updateScale); scrollbar.scanDomNode(); } diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index e41171068829b..dcc9d5da3de32 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -604,6 +604,7 @@ export class StatusbarPart extends Part implements IStatusbarService { private doCreateStatusItem(id: string, name: string, alignment: StatusbarAlignment, priority: number = 0, ...extraClasses: string[]): HTMLElement { const itemContainer = document.createElement('div'); itemContainer.title = name; + itemContainer.id = id; addClass(itemContainer, 'statusbar-item'); if (extraClasses) { diff --git a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts index f9719911f6c41..6402c9fb41429 100644 --- a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts @@ -16,6 +16,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IStorageService } from 'vs/platform/storage/common/storage'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IFileService } from 'vs/platform/files/common/files'; +import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; /** * An implementation of editor for binary files like images. @@ -32,6 +34,8 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor { @IStorageService storageService: IStorageService, @IFileService fileService: IFileService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IStatusbarService statusbarService: IStatusbarService, + @IContextMenuService contextMenuService: IContextMenuService ) { super( BinaryFileEditor.ID, @@ -44,6 +48,8 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor { fileService, environmentService, storageService, + statusbarService, + contextMenuService ); }