提交 e73ffc02 编写于 作者: B Benjamin Pasero 提交者: GitHub

Merge pull request #22630 from mjbvz/allow-displaying-large-resources-in-resource-viewer

Add button to resource viewer to open unsupported resource in external program
......@@ -111,8 +111,13 @@ export class ResourceViewer {
private static MAX_IMAGE_SIZE = ResourceViewer.MB; // showing images inline is memory intense, so we have a limit
public static show(descriptor: IResourceDescriptor, container: Builder, scrollbar: DomScrollableElement, metadataClb?: (meta: string) => void): void {
public static show(
descriptor: IResourceDescriptor,
container: Builder,
scrollbar: DomScrollableElement,
openExternal: (URI) => void,
metadataClb?: (meta: string) => void
): void {
// Ensure CSS class
$(container).setClass('monaco-resource-viewer');
......@@ -128,29 +133,47 @@ export class ResourceViewer {
}
// Show Image inline
if (mime.indexOf('image/') >= 0 && descriptor.size <= ResourceViewer.MAX_IMAGE_SIZE) {
$(container)
.empty()
.addClass('image')
.img({ src: imageSrc(descriptor) })
.on(DOM.EventType.LOAD, (e, img) => {
const imgElement = <HTMLImageElement>img.getHTMLElement();
if (imgElement.naturalWidth > imgElement.width || imgElement.naturalHeight > imgElement.height) {
$(container).addClass('oversized');
img.on(DOM.EventType.CLICK, (e, img) => {
$(container).toggleClass('full-size');
scrollbar.scanDomNode();
});
}
if (metadataClb) {
metadataClb(nls.localize('imgMeta', "{0}x{1} {2}", imgElement.naturalWidth, imgElement.naturalHeight, ResourceViewer.formatSize(descriptor.size)));
}
scrollbar.scanDomNode();
});
if (mime.indexOf('image/') >= 0) {
if (descriptor.size <= ResourceViewer.MAX_IMAGE_SIZE) {
$(container)
.empty()
.addClass('image')
.img({ src: imageSrc(descriptor) })
.on(DOM.EventType.LOAD, (e, img) => {
const imgElement = <HTMLImageElement>img.getHTMLElement();
if (imgElement.naturalWidth > imgElement.width || imgElement.naturalHeight > imgElement.height) {
$(container).addClass('oversized');
img.on(DOM.EventType.CLICK, (e, img) => {
$(container).toggleClass('full-size');
scrollbar.scanDomNode();
});
}
if (metadataClb) {
metadataClb(nls.localize('imgMeta', "{0}x{1} {2}", imgElement.naturalWidth, imgElement.naturalHeight, ResourceViewer.formatSize(descriptor.size)));
}
scrollbar.scanDomNode();
});
} else {
$(container)
.empty()
.p({
text: nls.localize('largeImageError', "The image is too large to display in the editor. ")
})
.append($('a', {
role: 'button',
class: 'open-external',
text: nls.localize('resourceOpenExternalButton', "Open image")
}).on(DOM.EventType.CLICK, (e) => {
openExternal(descriptor.resource);
}))
.append($('span', {
text: nls.localize('resourceOpenExternalText', ' using external program?')
}));
}
}
// Handle generic Binary Files
......
......@@ -47,4 +47,10 @@
max-width: initial;
max-height: initial;
cursor: zoom-out;
}
\ No newline at end of file
}
.monaco-resource-viewer .open-external,
.monaco-resource-viewer .open-external:hover {
cursor: pointer;
text-decoration: underline;
}
......@@ -57,7 +57,7 @@ export interface IWindowsService {
// This needs to be handled from browser process to prevent
// foreground ordering issues on Windows
openExternal(url: string): TPromise<void>;
openExternal(url: string): TPromise<boolean>;
// TODO: this is a bit backwards
startCrashReporter(config: Electron.CrashReporterStartOptions): TPromise<void>;
......
......@@ -43,7 +43,7 @@ export interface IWindowsChannel extends IChannel {
call(command: 'log', arg: [string, string[]]): TPromise<void>;
call(command: 'closeExtensionHostWindow', arg: string): TPromise<void>;
call(command: 'showItemInFolder', arg: string): TPromise<void>;
call(command: 'openExternal', arg: string): TPromise<void>;
call(command: 'openExternal', arg: string): TPromise<boolean>;
call(command: 'startCrashReporter', arg: Electron.CrashReporterStartOptions): TPromise<void>;
call(command: string, arg?: any): TPromise<any>;
}
......@@ -231,7 +231,7 @@ export class WindowsChannelClient implements IWindowsService {
return this.channel.call('showItemInFolder', path);
}
openExternal(url: string): TPromise<void> {
openExternal(url: string): TPromise<boolean> {
return this.channel.call('openExternal', url);
}
......
......@@ -260,9 +260,8 @@ export class WindowsService implements IWindowsService, IDisposable {
return TPromise.as(null);
}
openExternal(url: string): TPromise<void> {
shell.openExternal(url);
return TPromise.as(null);
openExternal(url: string): TPromise<boolean> {
return TPromise.as(shell.openExternal(url));
}
startCrashReporter(config: Electron.CrashReporterStartOptions): TPromise<void> {
......
......@@ -7,6 +7,7 @@
import nls = require('vs/nls');
import Event, { Emitter } from 'vs/base/common/event';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
import { ResourceViewer } from 'vs/base/browser/ui/resourceviewer/resourceViewer';
......@@ -17,6 +18,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IWindowsService } from 'vs/platform/windows/common/windows';
/*
* This class is only intended to be subclassed and not instantiated.
......@@ -31,7 +33,8 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
constructor(
id: string,
telemetryService: ITelemetryService,
themeService: IThemeService
themeService: IThemeService,
private windowsService: IWindowsService
) {
super(id, telemetryService, themeService);
......@@ -86,7 +89,19 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
// Render Input
const model = <BinaryEditorModel>resolvedModel;
ResourceViewer.show({ name: model.getName(), resource: model.getResource(), size: model.getSize(), etag: model.getETag() }, this.binaryContainer, this.scrollbar, (meta) => this.handleMetadataChanged(meta));
ResourceViewer.show(
{ name: model.getName(), resource: model.getResource(), size: model.getSize(), etag: model.getETag() },
this.binaryContainer,
this.scrollbar,
(resource: URI) => {
this.windowsService.openExternal(resource.toString()).then(didOpen => {
if (!didOpen) {
return this.windowsService.showItemInFolder(resource.fsPath);
}
return undefined;
});
},
(meta) => this.handleMetadataChanged(meta));
return TPromise.as<void>(null);
});
......
......@@ -9,6 +9,7 @@ import { BaseBinaryResourceEditor } from 'vs/workbench/browser/parts/editor/bina
import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IWindowsService } from "vs/platform/windows/common/windows";
/**
* An implementation of editor for binary files like images.
......@@ -19,9 +20,10 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor {
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService
@IThemeService themeService: IThemeService,
@IWindowsService windowsService: IWindowsService
) {
super(BinaryFileEditor.ID, telemetryService, themeService);
super(BinaryFileEditor.ID, telemetryService, themeService, windowsService);
}
public getTitle(): string {
......
......@@ -976,8 +976,8 @@ export class TestWindowsService implements IWindowsService {
// This needs to be handled from browser process to prevent
// foreground ordering issues on Windows
openExternal(url: string): TPromise<void> {
return TPromise.as(void 0);
openExternal(url: string): TPromise<boolean> {
return TPromise.as(true);
}
// TODO: this is a bit backwards
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册