提交 bb6f634f 编写于 作者: M Martin Aeschlimann

Add IThemeService.setTheme

上级 75361af8
......@@ -4,41 +4,6 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import nls = require('vs/nls');
export enum BaseTheme {
VS,
VS_DARK,
HIGH_CONTRAST
}
export function getBaseThemes(includeHighContrast: boolean): BaseTheme[] {
if (includeHighContrast) {
return [BaseTheme.VS, BaseTheme.VS_DARK, BaseTheme.HIGH_CONTRAST];
}
return [BaseTheme.VS, BaseTheme.VS_DARK];
}
export function toId(theme: BaseTheme): string {
switch (theme) {
case BaseTheme.VS:
return 'vs';
case BaseTheme.VS_DARK:
return 'vs-dark';
}
return 'hc-black';
}
export function toLabel(theme: BaseTheme): string {
switch (theme) {
case BaseTheme.VS:
return nls.localize('theme.vs', 'Light (Visual Studio)');
case BaseTheme.VS_DARK:
return nls.localize('theme.vs-dark', 'Dark (Visual Studio)');
}
return nls.localize('theme.hc', 'High Contrast');
}
export function isLightTheme(themeId: string) {
return /vs($| )/.test(themeId);
}
......
......@@ -5,7 +5,6 @@
'use strict';
import {Dimension, Builder, Box} from 'vs/base/browser/builder';
import {Preferences} from 'vs/workbench/common/constants';
import {EditorEvent, EventType} from 'vs/workbench/common/events';
import {Part} from 'vs/workbench/browser/part';
import {QuickOpenController} from 'vs/workbench/browser/parts/quickopen/quickOpenController';
......@@ -13,9 +12,11 @@ import {Sash, ISashEvent, IVerticalSashLayoutProvider, IHorizontalSashLayoutProv
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IPartService, Position} from 'vs/workbench/services/part/common/partService';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IStorageService, StorageScope, StorageEventType} from 'vs/platform/storage/common/storage';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {IContextViewService} from 'vs/platform/contextview/browser/contextView';
import {IEventService} from 'vs/platform/event/common/event';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
const DEFAULT_MIN_PART_WIDTH = 170;
const DEFAULT_MIN_PANEL_PART_HEIGHT = 170;
......@@ -23,10 +24,6 @@ const DEFAULT_MIN_EDITOR_PART_HEIGHT = 170;
const HIDE_SIDEBAR_WIDTH_THRESHOLD = 50;
const HIDE_PANEL_HEIGHT_THRESHOLD = 50;
const LAYOUT_RELATED_PREFERENCES = [
Preferences.THEME
];
export class LayoutOptions {
public margin: Box;
......@@ -66,7 +63,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
private statusbar: Part;
private quickopen: QuickOpenController;
private options: LayoutOptions;
private toUnbind: { (): void; }[];
private toUnbind: IDisposable[];
private computedStyles: ComputedStyles;
private workbenchSize: Dimension;
private sashX: Sash;
......@@ -92,11 +89,12 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
quickopen: QuickOpenController,
options: LayoutOptions,
@IStorageService private storageService: IStorageService,
@IEventService private eventService: IEventService,
@IEventService eventService: IEventService,
@IContextViewService private contextViewService: IContextViewService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IPartService private partService: IPartService
@IPartService private partService: IPartService,
@IThemeService themeService: IThemeService
) {
this.parent = parent;
this.workbenchContainer = workbenchContainer;
......@@ -120,14 +118,12 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
this.sidebarWidth = this.storageService.getInteger(WorkbenchLayout.sashXWidthSettingsKey, StorageScope.GLOBAL, -1);
this.panelHeight = this.storageService.getInteger(WorkbenchLayout.sashYHeightSettingsKey, StorageScope.GLOBAL, 0);
this.registerListeners();
this.toUnbind.push(themeService.onDidThemeChange(_ => this.relayout()));
this.toUnbind.push(eventService.addListener2(EventType.EDITOR_INPUT_CHANGING, (e: EditorEvent) => this.onEditorInputChanging(e)));
this.registerSashListeners();
}
private registerListeners(): void {
this.toUnbind.push(this.eventService.addListener(StorageEventType.STORAGE, (e: StorageEvent) => this.onPreferenceChange(e)));
this.toUnbind.push(this.eventService.addListener(EventType.EDITOR_INPUT_CHANGING, (e: EditorEvent) => this.onEditorInputChanging(e)));
}
private registerSashListeners(): void {
let startX: number = 0;
......@@ -239,18 +235,16 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
}
}
private onPreferenceChange(e: StorageEvent): void {
if (e.key && LAYOUT_RELATED_PREFERENCES.indexOf(e.key) >= 0) {
private relayout(): void {
// Recompute Styles
this.computeStyle();
this.editor.getLayout().computeStyle();
this.sidebar.getLayout().computeStyle();
this.panel.getLayout().computeStyle();
// Recompute Styles
this.computeStyle();
this.editor.getLayout().computeStyle();
this.sidebar.getLayout().computeStyle();
this.panel.getLayout().computeStyle();
// Trigger Layout
this.layout();
}
// Trigger Layout
this.layout();
}
private computeStyle(): void {
......@@ -494,8 +488,9 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal
}
public dispose(): void {
while (this.toUnbind.length) {
this.toUnbind.pop()();
if (this.toUnbind) {
dispose(this.toUnbind);
this.toUnbind = null;
}
}
}
......@@ -23,6 +23,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat
import {IMessageService} from 'vs/platform/message/common/message';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
/**
* An editor implementation that is capable of showing string inputs or promise inputs that resolve to a string.
......@@ -43,9 +44,10 @@ export class StringEditor extends BaseTextEditor {
@IConfigurationService configurationService: IConfigurationService,
@IEventService eventService: IEventService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IModeService modeService: IModeService
@IModeService modeService: IModeService,
@IThemeService themeService: IThemeService
) {
super(StringEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, modeService);
super(StringEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, modeService, themeService);
this.mapResourceToEditorViewState = Object.create(null);
......
......@@ -36,6 +36,7 @@ import {IMessageService} from 'vs/platform/message/common/message';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IKeybindingService, IKeybindingContextKey} from 'vs/platform/keybinding/common/keybindingService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
/**
* The text editor that leverages the monaco diff text editor for the editing experience.
......@@ -60,9 +61,10 @@ export class TextDiffEditor extends BaseTextEditor {
@IEventService eventService: IEventService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IModeService modeService: IModeService,
@IKeybindingService keybindingService: IKeybindingService
@IKeybindingService keybindingService: IKeybindingService,
@IThemeService themeService: IThemeService
) {
super(TextDiffEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, modeService);
super(TextDiffEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, modeService, themeService);
this.textDiffEditorVisible = keybindingService.createKey<boolean>('textCompareEditorVisible', false);
}
......
......@@ -10,7 +10,6 @@ import {TPromise} from 'vs/base/common/winjs.base';
import {Dimension, Builder} from 'vs/base/browser/builder';
import objects = require('vs/base/common/objects');
import {CodeEditorWidget} from 'vs/editor/browser/widget/codeEditorWidget';
import {Preferences} from 'vs/workbench/common/constants';
import {IEditorViewState} from 'vs/editor/common/editorCommon';
import {OptionsChangeEvent, EventType as WorkbenchEventType, EditorEvent, TextEditorSelectionEvent} from 'vs/workbench/common/events';
import {Scope} from 'vs/workbench/common/memento';
......@@ -21,8 +20,7 @@ import {IEditorSelection, IEditor, EventType, IConfigurationChangedEvent, IModel
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IFilesConfiguration} from 'vs/platform/files/common/files';
import {Position} from 'vs/platform/editor/common/editor';
import {DEFAULT_THEME_ID} from 'vs/workbench/services/themes/common/themeService';
import {IStorageService, StorageScope, StorageEvent, StorageEventType} from 'vs/platform/storage/common/storage';
import {IStorageService} from 'vs/platform/storage/common/storage';
import {IConfigurationService, IConfigurationServiceEvent, ConfigurationServiceEventTypes} from 'vs/platform/configuration/common/configuration';
import {IEventService} from 'vs/platform/event/common/event';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
......@@ -30,6 +28,7 @@ import {IMessageService} from 'vs/platform/message/common/message';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
const EDITOR_VIEW_STATE_PREFERENCE_KEY = 'editorViewState';
......@@ -51,14 +50,16 @@ export abstract class BaseTextEditor extends BaseEditor {
@IConfigurationService private configurationService: IConfigurationService,
@IEventService private _eventService: IEventService,
@IWorkbenchEditorService private _editorService: IWorkbenchEditorService,
@IModeService private _modeService: IModeService
@IModeService private _modeService: IModeService,
@IThemeService private _themeService: IThemeService
) {
super(id, telemetryService);
this.toUnbind.push(this._eventService.addListener(StorageEventType.STORAGE, (e: StorageEvent) => this.onPreferencesChanged(e)));
this.toUnbind.push(this._eventService.addListener(WorkbenchEventType.WORKBENCH_OPTIONS_CHANGED, (e) => this.onOptionsChanged(e)));
this.toUnbind.push(this.configurationService.addListener(ConfigurationServiceEventTypes.UPDATED, (e: IConfigurationServiceEvent) => this.applyConfiguration(e.config)));
}
this.toUnbind.push(_themeService.onDidThemeChange(_ => this.onThemeChanged()).dispose);
}
public get instantiationService(): IInstantiationService {
return this._instantiationService;
......@@ -97,12 +98,8 @@ export abstract class BaseTextEditor extends BaseEditor {
}
}
private onPreferencesChanged(e: StorageEvent): void {
// Update Theme in Editor Control
if (e.key === Preferences.THEME) {
this.editorControl.updateOptions(this.getCodeEditorOptions());
}
private onThemeChanged(): void {
this.editorControl.updateOptions(this.getCodeEditorOptions());
}
protected getCodeEditorOptions(): IEditorOptions {
......@@ -111,7 +108,7 @@ export abstract class BaseTextEditor extends BaseEditor {
readOnly: this.contextService.getOptions().readOnly,
glyphMargin: true,
lineNumbersMinChars: 3,
theme: this._storageService.get(Preferences.THEME, StorageScope.GLOBAL, DEFAULT_THEME_ID)
theme: this._themeService.getTheme()
};
// Always mixin editor options from the context into our set to allow for override
......
......@@ -17,7 +17,7 @@ import assert = require('vs/base/common/assert');
import timer = require('vs/base/common/timer');
import errors = require('vs/base/common/errors');
import {Registry} from 'vs/platform/platform';
import {Identifiers, Preferences} from 'vs/workbench/common/constants';
import {Identifiers} from 'vs/workbench/common/constants';
import {EventType} from 'vs/workbench/common/events';
import {IOptions} from 'vs/workbench/common/options';
import {IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions} from 'vs/workbench/common/contributions';
......@@ -41,9 +41,8 @@ import {AbstractKeybindingService} from 'vs/platform/keybinding/browser/keybindi
import {IUntitledEditorService, UntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {WorkbenchEditorService} from 'vs/workbench/services/editor/browser/editorService';
import {Position, Parts, IPartService} from 'vs/workbench/services/part/common/partService';
import {DEFAULT_THEME_ID} from 'vs/workbench/services/themes/common/themeService';
import {IWorkspaceContextService as IWorkbenchWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IStorageService, StorageScope, StorageEvent, StorageEventType} from 'vs/platform/storage/common/storage';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {IWorkspace, IConfiguration} from 'vs/platform/workspace/common/workspace';
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {IContextMenuService} from 'vs/platform/contextview/browser/contextView';
......@@ -112,7 +111,6 @@ export class Workbench implements IPartService {
private workbenchLayout: WorkbenchLayout;
private toDispose: IDisposable[];
private toShutdown: { shutdown: () => void; }[];
private currentTheme: string;
private callbacks: IWorkbenchCallbacks;
private creationPromise: TPromise<boolean>;
private creationPromiseComplete: ValueCallback;
......@@ -144,7 +142,6 @@ export class Workbench implements IPartService {
instantiationService
};
this.currentTheme = null;
this.toDispose = [];
this.toShutdown = [];
this.editorBackgroundDelayer = new Delayer<void>(50);
......@@ -689,15 +686,6 @@ export class Workbench implements IPartService {
private registerListeners(): void {
// Listen to Preference changes
this.toDispose.push(this.toDisposable(this.eventService.addListener(StorageEventType.STORAGE, (e: StorageEvent) => {
switch (e.key) {
case Preferences.THEME:
this.applyTheme(e.newValue);
break;
}
})));
// Listen to editor changes
this.toDispose.push(this.toDisposable(this.eventService.addListener(EventType.EDITOR_CLOSED, () => this.onEditorOpenedOrClosed())));
this.toDispose.push(this.toDisposable(this.eventService.addListener(EventType.EDITOR_OPENED, () => this.onEditorOpenedOrClosed())));
......@@ -779,28 +767,10 @@ export class Workbench implements IPartService {
// Create QuickOpen
this.createQuickOpen();
// Check theme in preferences
let currentTheme = this.storageService.get(Preferences.THEME, StorageScope.GLOBAL, DEFAULT_THEME_ID);
// Apply theme
this.applyTheme(currentTheme);
// Add Workbench to DOM
this.workbenchContainer.build(this.container);
}
private applyTheme(theme: string): void {
if (this.currentTheme) {
this.workbench.removeClass(this.currentTheme);
}
this.currentTheme = theme || null;
if (this.currentTheme) {
this.workbench.addClass(this.currentTheme);
}
}
private createActivityBarPart(): void {
let activitybarPartContainer = $(this.workbench)
.div({
......
......@@ -13,7 +13,6 @@ import Severity from 'vs/base/common/severity';
import {Separator} from 'vs/base/browser/ui/actionbar/actionbar';
import {IAction, Action} from 'vs/base/common/actions';
import {IPartService} from 'vs/workbench/services/part/common/partService';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {IMessageService} from 'vs/platform/message/common/message';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
......@@ -51,7 +50,6 @@ export class ElectronIntegration {
@ITelemetryService private telemetryService: ITelemetryService,
@IConfigurationService private configurationService: IConfigurationService,
@IKeybindingService private keybindingService: IKeybindingService,
@IStorageService private storageService: IStorageService,
@IMessageService private messageService: IMessageService,
@IContextMenuService private contextMenuService: IContextMenuService
) {
......@@ -113,11 +111,6 @@ export class ElectronIntegration {
ipc.send('vscode:workbenchLoaded', this.windowService.getWindowId());
});
// Theme changes
ipc.on('vscode:changeTheme', (event, theme: string) => {
this.storageService.store('workbench.theme', theme, StorageScope.GLOBAL);
});
// Message support
ipc.on('vscode:showInfoMessage', (event, message: string) => {
this.messageService.show(Severity.Info, message);
......
......@@ -21,7 +21,6 @@ import {dispose, IDisposable} from 'vs/base/common/lifecycle';
import errors = require('vs/base/common/errors');
import {ContextViewService} from 'vs/platform/contextview/browser/contextViewService';
import {ContextMenuService} from 'vs/workbench/services/contextview/electron-browser/contextmenuService';
import {Preferences} from 'vs/workbench/common/constants';
import timer = require('vs/base/common/timer');
import {Workbench} from 'vs/workbench/browser/workbench';
import {Storage, inMemoryLocalStorageInstance} from 'vs/workbench/common/storage';
......@@ -69,7 +68,7 @@ import {MainThreadWorkspace} from 'vs/workbench/api/node/extHostWorkspace';
import {MainThreadConfiguration} from 'vs/workbench/api/node/extHostConfiguration';
import {MainThreadLanguageFeatures} from 'vs/workbench/api/node/extHostLanguageFeatures';
import {IOptions} from 'vs/workbench/common/options';
import {IStorageService, StorageScope, StorageEvent, StorageEventType} from 'vs/platform/storage/common/storage';
import {IStorageService} from 'vs/platform/storage/common/storage';
import {MainThreadStorage} from 'vs/platform/storage/common/remotable.storage';
import {IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import {createInstantiationService as createInstantiationService } from 'vs/platform/instantiation/common/instantiationService';
......@@ -89,8 +88,8 @@ import {MainThreadModeServiceImpl} from 'vs/editor/common/services/modeServiceIm
import {IModeService} from 'vs/editor/common/services/modeService';
import {IUntitledEditorService, UntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {CrashReporter} from 'vs/workbench/electron-browser/crashReporter';
import {IThemeService, DEFAULT_THEME_ID} from 'vs/workbench/services/themes/common/themeService';
import {ThemeService} from 'vs/workbench/services/themes/node/themeService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
import {ThemeService} from 'vs/workbench/services/themes/electron-browser/themeService';
import {getService } from 'vs/base/common/service';
import {connect} from 'vs/base/node/service.net';
import {IExtensionsService} from 'vs/workbench/parts/extensions/common/extensions';
......@@ -118,7 +117,7 @@ export class WorkbenchShell {
private windowService: IWindowService;
private threadService: MainThreadService;
private configurationService: IConfigurationService;
private themeService: IThemeService;
private themeService: ThemeService;
private contextService: IWorkspaceContextService;
private telemetryService: ElectronTelemetryService;
private keybindingService: WorkbenchKeybindingService;
......@@ -281,7 +280,7 @@ export class WorkbenchShell {
let editorWorkerService = new EditorWorkerServiceImpl(modelService);
let untitledEditorService = new UntitledEditorService();
this.themeService = new ThemeService(extensionService);
this.themeService = new ThemeService(extensionService, this.windowService, this.storageService);
let result = createInstantiationService();
result.addSingleton(ITelemetryService, this.telemetryService);
......@@ -363,46 +362,7 @@ export class WorkbenchShell {
this.registerListeners();
// Enable theme support
let themeId = this.storageService.get(Preferences.THEME, StorageScope.GLOBAL, null);
if (!themeId) {
themeId = DEFAULT_THEME_ID;
this.storageService.store(Preferences.THEME, themeId, StorageScope.GLOBAL);
}
this.setTheme(themeId, false);
this.toUnbind.push(this.storageService.addListener2(StorageEventType.STORAGE, (e: StorageEvent) => {
if (e.key === Preferences.THEME) {
this.setTheme(e.newValue);
}
}));
}
private setTheme(themeId: string, layout = true): void {
if (!themeId) {
return;
}
let applyTheme = (themeId: string) => {
if (this.currentTheme) {
$(this.container).removeClass(this.currentTheme);
}
this.currentTheme = themeId;
$(this.container).addClass(this.currentTheme);
if (layout) {
this.layout();
}
};
this.themeService.loadTheme(themeId).then(theme => {
let newThemeId = theme ? theme.id : DEFAULT_THEME_ID;
this.themeService.applyThemeCSS(newThemeId);
applyTheme(newThemeId);
if (newThemeId !== themeId) {
this.storageService.store(Preferences.THEME, newThemeId, StorageScope.GLOBAL);
}
}, error => {
this.themeService.initialize(this.container).then(null, error => {
errors.onUnexpectedError(error);
});
}
......
......@@ -317,11 +317,6 @@ export class WindowsManager {
}
});
ipc.on('vscode:changeTheme', (event, theme: string) => {
this.sendToAll('vscode:changeTheme', theme);
storage.setItem(window.VSCodeWindow.themeStorageKey, theme);
});
ipc.on('vscode:broadcast', (event, windowId: number, target: string, broadcast: { channel: string; payload: any; }) => {
if (broadcast.channel && broadcast.payload) {
if (target) {
......
......@@ -33,6 +33,7 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat
import {IMessageService, Severity, CancelAction} from 'vs/platform/message/common/message';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
/**
* An implementation of editor for file system resources.
......@@ -54,9 +55,10 @@ export class TextFileEditor extends BaseTextEditor {
@IConfigurationService configurationService: IConfigurationService,
@IEventService eventService: IEventService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IModeService modeService: IModeService
@IModeService modeService: IModeService,
@IThemeService themeService: IThemeService
) {
super(TextFileEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, modeService);
super(TextFileEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, modeService, themeService);
// Since we are the one providing save-support for models, we hook up the error handler for saving
TextFileEditorModel.setSaveErrorHandler(instantiationService.createInstance(SaveErrorHandler));
......
......@@ -17,13 +17,11 @@ import {BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor';
import {Position} from 'vs/platform/editor/common/editor';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {IStorageService, StorageEventType, StorageScope} from 'vs/platform/storage/common/storage';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {BaseTextEditorModel} from 'vs/workbench/common/editor/textEditorModel';
import {Preferences} from 'vs/workbench/common/constants';
import {HtmlInput} from 'vs/workbench/parts/html/common/htmlInput';
import {isLightTheme} from 'vs/platform/theme/common/themes';
import {DEFAULT_THEME_ID} from 'vs/workbench/services/themes/common/themeService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
/**
* An implementation of editor for showing HTML content in an IFrame by leveraging the IFrameEditorInput.
......@@ -33,7 +31,7 @@ export class HtmlPreviewPart extends BaseEditor {
static ID: string = 'workbench.editor.htmlPreviewPart';
private _editorService: IWorkbenchEditorService;
private _storageService: IStorageService;
private _themeService: IThemeService;
private _iFrameElement: HTMLIFrameElement;
private _iFrameMessageSubscription = EmptyDisposable;
private _iFrameBase: URI;
......@@ -46,13 +44,12 @@ export class HtmlPreviewPart extends BaseEditor {
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IStorageService storageService: IStorageService,
@IWorkspaceContextService contextService: IWorkspaceContextService
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IThemeService themeService: IThemeService
) {
super(HtmlPreviewPart.ID, telemetryService);
this._editorService = editorService;
this._storageService = storageService;
this._iFrameBase = contextService.toResource('/');
}
......@@ -84,8 +81,8 @@ export class HtmlPreviewPart extends BaseEditor {
parent.getHTMLElement().appendChild(iFrameContainerElement);
this._themeChangeSubscription = this._storageService.addListener2(StorageEventType.STORAGE, event => {
if (event.key === Preferences.THEME && this.isVisible()) {
this._themeChangeSubscription = this._themeService.onDidThemeChange(themeId => {
if (this.isVisible()) {
this._updateIFrameContent(true);
}
});
......@@ -207,7 +204,7 @@ export class HtmlPreviewPart extends BaseEditor {
const parser = new DOMParser();
const newDocument = parser.parseFromString(html, 'text/html');
// ensure styles
const styleElement = Integration.defaultStyle(this._iFrameElement.parentElement, this._storageService.get(Preferences.THEME, StorageScope.GLOBAL, DEFAULT_THEME_ID));
const styleElement = Integration.defaultStyle(this._iFrameElement.parentElement, this._themeService.getTheme());
if (newDocument.head.hasChildNodes()) {
newDocument.head.insertBefore(styleElement, newDocument.head.firstChild);
} else {
......
......@@ -11,19 +11,20 @@ import {FileChangeType, FileChangesEvent, EventType as FileEventType} from 'vs/p
import paths = require('vs/base/common/paths');
import {EventType as EditorEventType, IModelContentChangedEvent} from 'vs/editor/common/editorCommon';
import {Preferences} from 'vs/workbench/common/constants';
import themes = require('vs/platform/theme/common/themes');
import {getBaseThemeId} from 'vs/platform/theme/common/themes';
import {IWorkbenchContribution} from 'vs/workbench/common/contributions';
import {IFrameEditor} from 'vs/workbench/browser/parts/editor/iframeEditor';
import {MarkdownEditorInput} from 'vs/workbench/parts/markdown/common/markdownEditorInput';
import {EditorEvent, EventType as WorkbenchEventType} from 'vs/workbench/common/events';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IStorageService, StorageScope, StorageEvent, StorageEventType} from 'vs/platform/storage/common/storage';
import {IConfigurationService, IConfigurationServiceEvent, ConfigurationServiceEventTypes} from 'vs/platform/configuration/common/configuration';
import {IModelService} from 'vs/editor/common/services/modelService';
import {IEventService} from 'vs/platform/event/common/event';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
import {IDisposable} from 'vs/base/common/lifecycle';
interface ILanguageConfiguration {
markdown: {
......@@ -38,7 +39,7 @@ export class MarkdownFileTracker implements IWorkbenchContribution {
private fileChangeListener: () => void;
private configFileChangeListener: () => void;
private themeChangeListener: () => void;
private themeChangeListener: IDisposable;
private editorInputChangeListener: () => void;
private markdownConfigurationThumbprint: string;
private markdownConfigurationPaths: string[];
......@@ -50,15 +51,15 @@ export class MarkdownFileTracker implements IWorkbenchContribution {
@IEventService private eventService: IEventService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IConfigurationService private configurationService: IConfigurationService,
@IStorageService private storageService: IStorageService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IModelService private modelService: IModelService,
@IInstantiationService private instantiationService: IInstantiationService
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService private themeService: IThemeService
) {
this.markdownConfigurationPaths = [];
this.hasModelListenerOnResourcePath = Object.create(null);
this.configureMode(this.storageService.get(Preferences.THEME, StorageScope.GLOBAL));
this.configureMode(themeService.getTheme());
this.registerListeners();
}
......@@ -74,11 +75,9 @@ export class MarkdownFileTracker implements IWorkbenchContribution {
this.readMarkdownConfiguration(this.configurationService.getConfiguration<ILanguageConfiguration>());
// listen to theme changes
this.themeChangeListener = this.storageService.addListener(StorageEventType.STORAGE, (e: StorageEvent) => {
if (e.key === Preferences.THEME) {
this.configureMode(e.newValue);
this.reloadMarkdownEditors(true);
}
this.themeChangeListener = this.themeService.onDidThemeChange(themeId => {
this.configureMode(themeId);
this.reloadMarkdownEditors(true);
});
}
......@@ -122,7 +121,7 @@ export class MarkdownFileTracker implements IWorkbenchContribution {
private configureMode(theme: string): void {
if (theme) {
let baseTheme = themes.getBaseThemeId(theme);
let baseTheme = getBaseThemeId(theme);
this.modeService.configureMode('text/x-web-markdown', { theme: baseTheme });
}
}
......
......@@ -13,11 +13,11 @@ import {EditorModel} from 'vs/workbench/common/editor';
import {Preferences} from 'vs/workbench/common/constants';
import {IModel} from 'vs/editor/common/editorCommon';
import {IEmitOutput} from 'vs/editor/common/modes';
import themes = require('vs/platform/theme/common/themes');
import {isLightTheme} from 'vs/platform/theme/common/themes';
import {DEFAULT_THEME_ID} from 'vs/workbench/services/themes/common/themeService';
import {MARKDOWN_MIME, MARKDOWN_MODE_ID} from 'vs/workbench/parts/markdown/common/markdown';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
interface IMarkdownWorkerOutput extends IEmitOutput {
......@@ -35,7 +35,7 @@ export class MarkdownEditorModel extends IFrameEditorModel {
resource: URI,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IStorageService private storageService: IStorageService
@IThemeService private themeService: IThemeService
) {
super(resource);
}
......@@ -50,8 +50,8 @@ export class MarkdownEditorModel extends IFrameEditorModel {
// On Error: Show error to user as rendered HTML
let onError = (error: Error) => {
try {
let theme = this.storageService.get(Preferences.THEME, StorageScope.GLOBAL, DEFAULT_THEME_ID);
let usesLightTheme = themes.isLightTheme(theme);
let theme = this.themeService.getTheme();
let usesLightTheme = isLightTheme(theme);
let markdownError = nls.localize('markdownError', "Unable to open '{0}' for Markdown rendering. Please make sure the file exists and that it is a valid Markdown file.", paths.basename(this.resource.fsPath));
this.setContents('<html><head><style type="text/css">body {color: ' + (usesLightTheme ? 'black' : 'white') + '; font-family: "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", sans-serif, "Droid Sans Fallback"; font-size: 13px; margin: 0; line-height: 1.4em; padding-left: 20px;}</style></head><body>', markdownError, '</body></html>');
......
......@@ -24,6 +24,7 @@ import {OutputEditorInput} from 'vs/workbench/parts/output/common/outputEditorIn
import {SwitchOutputAction, SwitchOutputActionItem, ClearOutputAction} from 'vs/workbench/parts/output/browser/outputActions';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
export class OutputPanel extends StringEditor {
......@@ -40,10 +41,11 @@ export class OutputPanel extends StringEditor {
@IEventService eventService: IEventService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IModeService modeService: IModeService,
@IThemeService themeService: IThemeService,
@IOutputService private outputService: IOutputService
) {
super(telemetryService, instantiationService, contextService, storageService,
messageService, configurationService, eventService, editorService, modeService);
messageService, configurationService, eventService, editorService, modeService, themeService);
this.toDispose = [];
}
......
......@@ -7,19 +7,15 @@
import nls = require('vs/nls');
import winjs = require('vs/base/common/winjs.base');
import actions = require('vs/base/common/actions');
import Constants = require('vs/workbench/common/constants');
import {SyncActionDescriptor} from 'vs/platform/actions/common/actions';
import {IMessageService, Severity} from 'vs/platform/message/common/message';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import platform = require('vs/platform/platform');
import workbenchActionRegistry = require('vs/workbench/common/actionRegistry');
import {IQuickOpenService, IPickOpenEntry} from 'vs/workbench/services/quickopen/common/quickOpenService';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {IThemeService, IThemeData, DEFAULT_THEME_ID} from 'vs/workbench/services/themes/common/themeService';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
import {RunOnceScheduler} from 'vs/base/common/async';
import {ipcRenderer as ipc} from 'electron';
class SelectThemeAction extends actions.Action {
public static ID = 'workbench.action.selectTheme';
......@@ -30,7 +26,6 @@ class SelectThemeAction extends actions.Action {
label: string,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IStorageService private storageService: IStorageService,
@IMessageService private messageService: IMessageService,
@IThemeService private themeService: IThemeService
) {
......@@ -40,11 +35,10 @@ class SelectThemeAction extends actions.Action {
public run(): winjs.TPromise<void> {
return this.themeService.getThemes().then(contributedThemes => {
let currentTheme = this.storageService.get(Constants.Preferences.THEME, StorageScope.GLOBAL, DEFAULT_THEME_ID);
let currentTheme = this.themeService.getTheme();
let picks: IPickOpenEntry[] = [];
let contributedThemesById: { [id: string]: IThemeData } = {};
contributedThemes.forEach(theme => {
picks.push({ id: theme.id, label: theme.label, description: theme.description });
contributedThemes[theme.id] = theme;
......@@ -59,31 +53,20 @@ class SelectThemeAction extends actions.Action {
}
});
let selectTheme = pick => {
let selectTheme = (pick, broadcast) => {
if (pick) {
let themeId = pick.id;
if (!contributedThemesById[themeId]) {
// built-in theme
ipc.send('vscode:changeTheme', themeId);
} else {
// before applying, check that it can be loaded
return this.themeService.applyThemeCSS(themeId).then(_ => {
ipc.send('vscode:changeTheme', themeId);
}, error => {
this.messageService.show(Severity.Info, nls.localize('problemChangingTheme', "Problem loading theme: {0}", error.message));
});
}
this.themeService.setTheme(themeId, broadcast).then(null, error => {
this.messageService.show(Severity.Info, nls.localize('problemChangingTheme', "Problem loading theme: {0}", error.message));
});
} else {
// undo changes
if (this.storageService.get(Constants.Preferences.THEME, StorageScope.GLOBAL) !== currentTheme) {
ipc.send('vscode:changeTheme', currentTheme);
}
this.themeService.setTheme(currentTheme, broadcast);
}
};
let themeToPreview : IPickOpenEntry = null;
let previewThemeScheduler = new RunOnceScheduler(() => {
selectTheme(themeToPreview);
selectTheme(themeToPreview, false);
}, 200);
let previewTheme = pick => {
themeToPreview = pick;
......@@ -91,7 +74,7 @@ class SelectThemeAction extends actions.Action {
};
let pickTheme = pick => {
previewThemeScheduler.dispose();
selectTheme(pick);
selectTheme(pick, true);
};
return this.quickOpenService.pick(picks, { placeHolder: nls.localize('themes.selectTheme', "Select Color Theme"), autoFocus: { autoFocusIndex: selectedPickIndex } }).then(pickTheme, null, previewTheme);
});
......
......@@ -6,16 +6,16 @@
import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation';
import {TPromise} from 'vs/base/common/winjs.base';
import Event from 'vs/base/common/event';
export let IThemeService = createDecorator<IThemeService>('themeService');
export const DEFAULT_THEME_ID = 'vs-dark vscode-theme-defaults-themes-dark_plus-json';
export interface IThemeService {
serviceId: ServiceIdentifier<any>;
loadTheme(themeId: string): TPromise<IThemeData>;
applyThemeCSS(themeId: string): TPromise<boolean>;
setTheme(themeId: string, broadcastToAllWindows: boolean): TPromise<boolean>;
getTheme(): string;
getThemes(): TPromise<IThemeData[]>;
onDidThemeChange: Event<string>;
}
export interface IThemeData {
......
......@@ -8,18 +8,27 @@ import {TPromise} from 'vs/base/common/winjs.base';
import nls = require('vs/nls');
import Paths = require('vs/base/common/paths');
import Json = require('vs/base/common/json');
import Themes = require('vs/platform/theme/common/themes');
import {IThemeExtensionPoint} from 'vs/platform/theme/common/themeExtensionPoint';
import {IExtensionService} from 'vs/platform/extensions/common/extensions';
import {ExtensionsRegistry, IExtensionMessageCollector} from 'vs/platform/extensions/common/extensionsRegistry';
import {IThemeService, IThemeData, DEFAULT_THEME_ID} from 'vs/workbench/services/themes/common/themeService';
import {IThemeService, IThemeData} from 'vs/workbench/services/themes/common/themeService';
import {getBaseThemeId, getSyntaxThemeId} from 'vs/platform/theme/common/themes';
import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
import {Preferences} from 'vs/workbench/common/constants';
import {$} from 'vs/base/browser/builder';
import Event, {Emitter} from 'vs/base/common/event';
import plist = require('vs/base/node/plist');
import pfs = require('vs/base/node/pfs');
// implementation
let defaultBaseTheme = Themes.getBaseThemeId(DEFAULT_THEME_ID);
const DEFAULT_THEME_ID = 'vs-dark vscode-theme-defaults-themes-dark_plus-json';
const THEME_CHANNEL = 'vscode:changeTheme';
let defaultBaseTheme = getBaseThemeId(DEFAULT_THEME_ID);
const defaultThemeExtensionId = 'vscode-theme-defaults';
const oldDefaultThemeExtensionId = 'vscode-theme-colorful-defaults';
......@@ -86,32 +95,101 @@ export class ThemeService implements IThemeService {
serviceId = IThemeService;
private knownThemes: IThemeData[];
constructor(private extensionService: IExtensionService) {
private currentTheme: string;
private container: HTMLElement;
private onThemeChange: Emitter<string>;
constructor(
private extensionService: IExtensionService,
@IWindowService private windowService: IWindowService,
@IStorageService private storageService: IStorageService) {
this.knownThemes = [];
this.onThemeChange = new Emitter<string>();
themesExtPoint.setHandler((extensions) => {
for (let ext of extensions) {
this.onThemes(ext.description.extensionFolderPath, ext.description.id, ext.value, ext.collector);
}
});
windowService.onBroadcast(e => {
if (e.channel === THEME_CHANNEL && typeof e.payload === 'string') {
this.setTheme(e.payload, false);
}
});
}
public get onDidThemeChange(): Event<string> {
return this.onThemeChange.event;
}
public initialize(container: HTMLElement): TPromise<boolean> {
this.container = container;
let themeId = this.storageService.get(Preferences.THEME, StorageScope.GLOBAL, null);
if (!themeId) {
themeId = DEFAULT_THEME_ID;
this.storageService.store(Preferences.THEME, themeId, StorageScope.GLOBAL);
}
return this.setTheme(themeId, false);
}
public setTheme(themeId: string, broadcastToAllWindows: boolean) : TPromise<boolean> {
if (!themeId) {
return TPromise.as(false);
}
if (themeId === this.currentTheme) {
if (broadcastToAllWindows) {
this.windowService.broadcast({ channel: THEME_CHANNEL, payload: themeId });
}
return TPromise.as(false);
}
themeId = validateThemeId(themeId); // migrate theme ids
let onApply = (newThemeId) => {
if (this.container) {
if (this.currentTheme) {
$(this.container).removeClass(this.currentTheme);
}
this.currentTheme = newThemeId;
$(this.container).addClass(newThemeId);
}
this.storageService.store(Preferences.THEME, newThemeId, StorageScope.GLOBAL);
if (broadcastToAllWindows) {
this.windowService.broadcast({ channel: THEME_CHANNEL, payload: newThemeId });
}
this.onThemeChange.fire(newThemeId);
};
return this.applyThemeCSS(themeId, DEFAULT_THEME_ID, onApply);
}
public loadTheme(themeId: string): TPromise<IThemeData> {
themeId = validateThemeId(themeId);
public getTheme() {
return this.currentTheme || DEFAULT_THEME_ID;
}
private loadTheme(themeId: string, defaultId?: string): TPromise<IThemeData> {
return this.getThemes().then(allThemes => {
let themes = allThemes.filter(t => t.id === themeId);
if (themes.length > 0) {
return themes[0];
}
if (defaultId) {
let themes = allThemes.filter(t => t.id === defaultId);
if (themes.length > 0) {
return themes[0];
}
}
return null;
});
}
public applyThemeCSS(themeId: string): TPromise<boolean> {
return this.loadTheme(themeId).then(theme => {
private applyThemeCSS(themeId: string, defaultId: string, onApply: (themeId:string) => void): TPromise<boolean> {
return this.loadTheme(themeId, defaultId).then(theme => {
if (theme) {
return applyTheme(theme);
return applyTheme(theme, onApply);
}
return null;
});
......@@ -164,15 +242,18 @@ function toCssSelector(str: string) {
return str.replace(/[^_\-a-zA-Z0-9]/g, '-');
}
function applyTheme(theme: IThemeData): TPromise<boolean> {
function applyTheme(theme: IThemeData, onApply: (themeId:string) => void): TPromise<boolean> {
if (theme.styleSheetContent) {
_applyRules(theme.styleSheetContent);
onApply(theme.id);
return TPromise.as(true);
}
return _loadThemeDocument(theme.path).then(themeDocument => {
let styleSheetContent = _processThemeObject(theme.id, themeDocument);
theme.styleSheetContent = styleSheetContent;
_applyRules(styleSheetContent);
return true;
onApply(theme.id);
return false;
}, error => {
return TPromise.wrapError(nls.localize('error.cannotloadtheme', "Unable to load {0}", theme.path));
});
......@@ -216,7 +297,7 @@ function _processThemeObject(themeId: string, themeDocument: ThemeDocument): str
selection: void 0
};
let themeSelector = `${Themes.getBaseThemeId(themeId)}.${Themes.getSyntaxThemeId(themeId)}`;
let themeSelector = `${getBaseThemeId(themeId)}.${getSyntaxThemeId(themeId)}`;
if (Array.isArray(themeSettings)) {
themeSettings.forEach((s : ThemeSetting, index, arr) => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册