Merge VS Code 1.31.1 (#4283)

This commit is contained in:
Matt Irvine
2019-03-15 13:09:45 -07:00
committed by GitHub
parent 7d31575149
commit 86bac90001
1716 changed files with 53308 additions and 48375 deletions

View File

@@ -36,14 +36,14 @@ export class ViewletActivityAction extends ActivityAction {
constructor(
activity: IActivity,
@IViewletService private viewletService: IViewletService,
@IPartService private partService: IPartService,
@ITelemetryService private telemetryService: ITelemetryService
@IViewletService private readonly viewletService: IViewletService,
@IPartService private readonly partService: IPartService,
@ITelemetryService private readonly telemetryService: ITelemetryService
) {
super(activity);
}
run(event: any): Thenable<any> {
run(event: any): Promise<any> {
if (event instanceof MouseEvent && event.button === 2) {
return Promise.resolve(false); // do not run on right click
}
@@ -84,13 +84,13 @@ export class ToggleViewletAction extends Action {
constructor(
private _viewlet: ViewletDescriptor,
@IPartService private partService: IPartService,
@IViewletService private viewletService: IViewletService
@IPartService private readonly partService: IPartService,
@IViewletService private readonly viewletService: IViewletService
) {
super(_viewlet.id, _viewlet.name);
}
run(): Thenable<any> {
run(): Promise<any> {
const sideBarVisible = this.partService.isVisible(Parts.SIDEBAR_PART);
const activeViewlet = this.viewletService.getActiveViewlet();
@@ -175,7 +175,7 @@ export class PlaceHolderViewletActivityAction extends ViewletActivityAction {
) {
super({ id, name: id, cssClass: `extensionViewlet-placeholder-${id.replace(/\./g, '-')}` }, viewletService, partService, telemetryService);
const iconClass = `.monaco-workbench > .activitybar .monaco-action-bar .action-label.${this.class}`; // Generate Placeholder CSS to show the icon in the activity bar
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${this.class}`; // Generate Placeholder CSS to show the icon in the activity bar
DOM.createCSSRule(iconClass, `-webkit-mask: url('${iconUrl || ''}') no-repeat 50% 50%`);
}
@@ -187,7 +187,7 @@ export class PlaceHolderViewletActivityAction extends ViewletActivityAction {
export class PlaceHolderToggleCompositePinnedAction extends ToggleCompositePinnedAction {
constructor(id: string, compositeBar: ICompositeBar) {
super({ id, name: id, cssClass: void 0 }, compositeBar);
super({ id, name: id, cssClass: undefined }, compositeBar);
}
setActivity(activity: IActivity): void {
@@ -200,13 +200,13 @@ class SwitchSideBarViewAction extends Action {
constructor(
id: string,
name: string,
@IViewletService private viewletService: IViewletService,
@IActivityService private activityService: IActivityService
@IViewletService private readonly viewletService: IViewletService,
@IActivityService private readonly activityService: IActivityService
) {
super(id, name);
}
run(offset: number): Thenable<any> {
run(offset: number): Promise<any> {
const pinnedViewletIds = this.activityService.getPinnedViewletIds();
const activeViewlet = this.viewletService.getActiveViewlet();
@@ -238,7 +238,7 @@ export class PreviousSideBarViewAction extends SwitchSideBarViewAction {
super(id, name, viewletService, activityService);
}
run(): Thenable<any> {
run(): Promise<any> {
return super.run(-1);
}
}
@@ -257,7 +257,7 @@ export class NextSideBarViewAction extends SwitchSideBarViewAction {
super(id, name, viewletService, activityService);
}
run(): Thenable<any> {
run(): Promise<any> {
return super.run(1);
}
}
@@ -271,9 +271,9 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const activeForegroundColor = theme.getColor(ACTIVITY_BAR_FOREGROUND);
if (activeForegroundColor) {
collector.addRule(`
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active .action-label,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus .action-label,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover .action-label {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active .action-label,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:focus .action-label,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:hover .action-label {
background-color: ${activeForegroundColor} !important;
}
`);
@@ -283,7 +283,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const outline = theme.getColor(activeContrastBorder);
if (outline) {
collector.addRule(`
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:before {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:before {
content: "";
position: absolute;
top: 9px;
@@ -292,26 +292,26 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
width: 32px;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.checked:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.checked:hover:before {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active:before,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.checked:before,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.checked:hover:before {
outline: 1px solid;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover:before {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:hover:before {
outline: 1px dashed;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:focus:before {
border-left-color: ${outline};
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.checked:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.checked:hover:before,
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover:before {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active:before,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.checked:before,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.checked:hover:before,
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:hover:before {
outline-color: ${outline};
}
`);
@@ -322,7 +322,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const focusBorderColor = theme.getColor(focusBorder);
if (focusBorderColor) {
collector.addRule(`
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:focus:before {
border-left-color: ${focusBorderColor};
}
`);

View File

@@ -6,6 +6,7 @@
import 'vs/css!./media/activitybarpart';
import * as nls from 'vs/nls';
import { illegalArgument } from 'vs/base/common/errors';
import { Emitter } from 'vs/base/common/event';
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -15,38 +16,39 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { IPartService, Parts, Position as SideBarPosition } from 'vs/workbench/services/part/common/partService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/toggleActivityBarVisibility';
import { IThemeService, registerThemingParticipant, ITheme } from 'vs/platform/theme/common/themeService';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND } from 'vs/workbench/common/theme';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar } from 'vs/workbench/browser/parts/compositeBar';
import { isMacintosh } from 'vs/base/common/platform';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { scheduleAtNextAnimationFrame, Dimension, addClass } from 'vs/base/browser/dom';
import { Color } from 'vs/base/common/color';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { CompositeBar, ICompositeBarItem } from 'vs/workbench/browser/parts/compositeBar';
import { Dimension, addClass } from 'vs/base/browser/dom';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { URI } from 'vs/base/common/uri';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ToggleCompositePinnedAction, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { IViewsService, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewDescriptorCollection } from 'vs/workbench/common/views';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IViewlet } from 'vs/workbench/common/viewlet';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
const SCM_VIEWLET_ID = 'workbench.view.scm';
interface ICachedViewlet {
id: string;
iconUrl: URI;
iconUrl: UriComponents;
pinned: boolean;
order: number;
visible: boolean;
views?: { when: string }[];
}
export class ActivitybarPart extends Part {
export class ActivitybarPart extends Part implements ISerializableView {
private static readonly ACTION_HEIGHT = 50;
private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets';
private static readonly CACHED_VIEWLETS = 'workbench.activity.placeholderViewlets';
private dimension: Dimension;
@@ -57,23 +59,37 @@ export class ActivitybarPart extends Part {
private compositeBar: CompositeBar;
private compositeActions: { [compositeId: string]: { activityAction: ViewletActivityAction, pinnedAction: ToggleCompositePinnedAction } } = Object.create(null);
element: HTMLElement;
minimumWidth: number = 50;
maximumWidth: number = 50;
minimumHeight: number = 0;
maximumHeight: number = Number.POSITIVE_INFINITY;
private _onDidChange = new Emitter<{ width: number; height: number; }>();
readonly onDidChange = this._onDidChange.event;
constructor(
id: string,
@IViewletService private viewletService: IViewletService,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private partService: IPartService,
@IViewletService private readonly viewletService: IViewletService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IPartService private readonly partService: IPartService,
@IThemeService themeService: IThemeService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IStorageService private storageService: IStorageService,
@IExtensionService private extensionService: IExtensionService,
@IViewsService private viewsService: IViewsService,
@IContextKeyService private contextKeyService: IContextKeyService
@IStorageService private readonly storageService: IStorageService,
@IExtensionService private readonly extensionService: IExtensionService,
@IViewsService private readonly viewsService: IViewsService,
@IContextKeyService private readonly contextKeyService: IContextKeyService
) {
super(id, { hasTitle: false }, themeService, storageService);
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, {
this.cachedViewlets = this.getCachedViewlets();
for (const cachedViewlet of this.cachedViewlets) {
if (this.shouldBeHidden(cachedViewlet.id, cachedViewlet)) {
cachedViewlet.visible = false;
}
}
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.cachedViewlets.map(v => (<ICompositeBarItem>{ id: v.id, name: undefined, visible: v.visible, order: v.order, pinned: v.pinned })), {
icon: true,
storageId: ActivitybarPart.PINNED_VIEWLETS,
orientation: ActionsOrientation.VERTICAL,
openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true),
getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction,
@@ -87,16 +103,8 @@ export class ActivitybarPart extends Part {
overflowActionSize: ActivitybarPart.ACTION_HEIGHT
}));
const previousState = this.storageService.get(ActivitybarPart.CACHED_VIEWLETS, StorageScope.GLOBAL, '[]');
this.cachedViewlets = (<ICachedViewlet[]>JSON.parse(previousState)).map(({ id, iconUrl, views }) => ({ id, views, iconUrl: typeof iconUrl === 'object' ? URI.revive(iconUrl) : void 0 }));
for (const cachedViewlet of this.cachedViewlets) {
if (this.shouldBeHidden(cachedViewlet.id, cachedViewlet)) {
this.compositeBar.hideComposite(cachedViewlet.id);
}
}
this.registerListeners();
this.onDidRegisterViewlets(viewletService.getAllViewlets());
this.onDidRegisterViewlets(viewletService.getViewlets());
}
// {{SQL CARBON EDIT}}
@@ -112,35 +120,40 @@ export class ActivitybarPart extends Part {
}
private registerListeners(): void {
this._register(this.viewletService.onDidViewletRegister(viewlet => this.onDidRegisterViewlets([viewlet])));
this._register(this.viewletService.onDidViewletDeregister(({ id }) => this.removeComposite(id, true)));
// Activate viewlet action on opening of a viewlet
this._register(this.viewletService.onDidViewletOpen(viewlet => this.onDidViewletOpen(viewlet)));
// Deactivate viewlet action on close
this._register(this.viewletService.onDidViewletClose(viewlet => this.compositeBar.deactivateComposite(viewlet.getId())));
this._register(this.viewletService.onDidViewletEnablementChange(({ id, enabled }) => {
if (enabled) {
this.compositeBar.addComposite(this.viewletService.getViewlet(id));
} else {
this.removeComposite(id, true);
}
}));
this._register(this.extensionService.onDidRegisterExtensions(() => this.onDidRegisterExtensions()));
let disposables: IDisposable[] = [];
this._register(this.extensionService.onDidRegisterExtensions(() => {
disposables = dispose(disposables);
this.onDidRegisterExtensions();
this.compositeBar.onDidChange(() => this.saveCachedViewlets(), this, disposables);
this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables);
}));
this._register(toDisposable(() => dispose(disposables)));
}
private onDidRegisterExtensions(): void {
this.removeNotExistingComposites();
for (const viewlet of this.viewletService.getAllViewlets()) {
for (const viewlet of this.viewletService.getViewlets()) {
this.enableCompositeActions(viewlet);
const viewContainer = this.getViewContainer(viewlet.id);
if (viewContainer) {
const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer);
this.onDidChangeActiveViews(viewlet, viewDescriptors);
viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(viewlet, viewDescriptors));
if (viewDescriptors) {
this.onDidChangeActiveViews(viewlet, viewDescriptors);
viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(viewlet, viewDescriptors));
}
}
}
this.saveCachedViewlets();
}
private onDidChangeActiveViews(viewlet: ViewletDescriptor, viewDescriptors: IViewDescriptorCollection): void {
@@ -157,9 +170,12 @@ export class ActivitybarPart extends Part {
this.compositeBar.activateComposite(viewlet.getId());
const viewletDescriptor = this.viewletService.getViewlet(viewlet.getId());
const viewContainer = this.getViewContainer(viewletDescriptor.id);
if (viewContainer && this.viewsService.getViewDescriptors(viewContainer).activeViewDescriptors.length === 0) {
// Update the composite bar by hiding
this.removeComposite(viewletDescriptor.id, true);
if (viewContainer) {
const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer);
if (viewDescriptors && viewDescriptors.activeViewDescriptors.length === 0) {
// Update the composite bar by hiding
this.removeComposite(viewletDescriptor.id, true);
}
}
}
@@ -187,6 +203,7 @@ export class ActivitybarPart extends Part {
}
createContentArea(parent: HTMLElement): HTMLElement {
this.element = parent;
const content = document.createElement('div');
addClass(content, 'content');
parent.appendChild(content);
@@ -201,27 +218,6 @@ export class ActivitybarPart extends Part {
this.createGlobalActivityActionBar(globalActivities);
// TODO@Ben: workaround for https://github.com/Microsoft/vscode/issues/45700
// It looks like there are rendering glitches on macOS with Chrome 61 when
// using --webkit-mask with a background color that is different from the image
// The workaround is to promote the element onto its own drawing layer. We do
// this only after the workbench has loaded because otherwise there is ugly flicker.
if (isMacintosh) {
this.lifecycleService.when(LifecyclePhase.Restored).then(() => {
scheduleAtNextAnimationFrame(() => { // another delay...
scheduleAtNextAnimationFrame(() => { // ...to prevent more flickering on startup
registerThemingParticipant((theme, collector) => {
const activityBarForeground = theme.getColor(ACTIVITY_BAR_FOREGROUND);
if (activityBarForeground && !activityBarForeground.equals(Color.white)) {
// only apply this workaround if the color is different from the image one (white)
collector.addRule('.monaco-workbench .activitybar > .content .monaco-action-bar .action-label { will-change: transform; }');
}
});
});
});
});
}
return content;
}
@@ -287,7 +283,7 @@ export class ActivitybarPart extends Part {
} else {
const cachedComposite = this.cachedViewlets.filter(c => c.id === compositeId)[0];
compositeActions = {
activityAction: this.instantiationService.createInstance(PlaceHolderViewletActivityAction, compositeId, cachedComposite && cachedComposite.iconUrl),
activityAction: this.instantiationService.createInstance(PlaceHolderViewletActivityAction, compositeId, cachedComposite ? URI.revive(cachedComposite.iconUrl) : undefined),
pinnedAction: new PlaceHolderToggleCompositePinnedAction(compositeId, this.compositeBar)
};
}
@@ -326,8 +322,8 @@ export class ActivitybarPart extends Part {
}
private removeNotExistingComposites(): void {
const viewlets = this.viewletService.getAllViewlets();
for (const { id } of this.compositeBar.getComposites()) {
const viewlets = this.viewletService.getViewlets();
for (const { id } of this.cachedViewlets) {
if (viewlets.every(viewlet => viewlet.id !== id)) {
this.removeComposite(id, false);
}
@@ -366,13 +362,19 @@ export class ActivitybarPart extends Part {
.map(v => v.id);
}
layout(dimension: Dimension): Dimension[] {
layout(dimension: Dimension): Dimension[];
layout(width: number, height: number): void;
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
if (!this.partService.isVisible(Parts.ACTIVITYBAR_PART)) {
return [dimension];
if (dim1 instanceof Dimension) {
return [dim1];
}
return;
}
// Pass to super
const sizes = super.layout(dimension);
const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2));
this.dimension = sizes[1];
@@ -381,26 +383,114 @@ export class ActivitybarPart extends Part {
// adjust height for global actions showing
availableHeight -= (this.globalActionBar.items.length * ActivitybarPart.ACTION_HEIGHT);
}
this.compositeBar.layout(new Dimension(dimension.width, availableHeight));
this.compositeBar.layout(new Dimension(dim1 instanceof Dimension ? dim1.width : dim1, availableHeight));
return sizes;
if (dim1 instanceof Dimension) {
return sizes;
}
}
protected saveState(): void {
const state: ICachedViewlet[] = [];
for (const { id, iconUrl } of this.viewletService.getAllViewlets()) {
const viewContainer = this.getViewContainer(id);
const views: { when: string }[] = [];
if (viewContainer) {
for (const { when } of this.viewsService.getViewDescriptors(viewContainer).allViewDescriptors) {
views.push({ when: when ? when.serialize() : void 0 });
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
if (e.key === ActivitybarPart.PINNED_VIEWLETS && e.scope === StorageScope.GLOBAL
&& this.cachedViewletsValue !== this.getStoredCachedViewletsValue() /* This checks if current window changed the value or not */) {
this._cachedViewletsValue = null;
const newCompositeItems: ICompositeBarItem[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
const cachedViewlets = this.getCachedViewlets();
for (const cachedViewlet of cachedViewlets) {
// Add and update existing items
const existingItem = compositeItems.filter(({ id }) => id === cachedViewlet.id)[0];
if (existingItem) {
newCompositeItems.push({
id: existingItem.id,
name: existingItem.name,
order: existingItem.order,
pinned: cachedViewlet.pinned,
visible: existingItem.visible
});
}
}
state.push({ id, iconUrl, views });
}
this.storageService.store(ActivitybarPart.CACHED_VIEWLETS, JSON.stringify(state), StorageScope.GLOBAL);
super.saveState();
for (let index = 0; index < compositeItems.length; index++) {
// Add items currently exists but does not exist in new.
if (!newCompositeItems.some(({ id }) => id === compositeItems[index].id)) {
newCompositeItems.splice(index, 0, compositeItems[index]);
}
}
this.compositeBar.setCompositeBarItems(newCompositeItems);
}
}
private saveCachedViewlets(): void {
const state: ICachedViewlet[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
const allViewlets = this.viewletService.getViewlets();
for (const compositeItem of compositeItems) {
const viewContainer = this.getViewContainer(compositeItem.id);
const viewlet = allViewlets.filter(({ id }) => id === compositeItem.id)[0];
if (viewlet) {
const views: { when: string }[] = [];
if (viewContainer) {
const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer);
if (viewDescriptors) {
for (const { when } of viewDescriptors.allViewDescriptors) {
views.push({ when: when ? when.serialize() : undefined });
}
}
}
state.push({ id: compositeItem.id, iconUrl: viewlet.iconUrl, views, pinned: compositeItem && compositeItem.pinned, order: compositeItem ? compositeItem.order : undefined, visible: compositeItem && compositeItem.visible });
}
}
this.cachedViewletsValue = JSON.stringify(state);
}
private getCachedViewlets(): ICachedViewlet[] {
const storedStates = <Array<string | ICachedViewlet>>JSON.parse(this.cachedViewletsValue);
const cachedViewlets = <ICachedViewlet[]>storedStates.map(c => {
const serialized: ICachedViewlet = typeof c === 'string' /* migration from pinned states to composites states */ ? <ICachedViewlet>{ id: c, pinned: true, order: undefined, visible: true, iconUrl: undefined, views: undefined } : c;
serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible;
return serialized;
});
for (const old of this.loadOldCachedViewlets()) {
const cachedViewlet = cachedViewlets.filter(cached => cached.id === old.id)[0];
if (cachedViewlet) {
cachedViewlet.iconUrl = old.iconUrl;
cachedViewlet.views = old.views;
}
}
return cachedViewlets;
}
private loadOldCachedViewlets(): ICachedViewlet[] {
const previousState = this.storageService.get('workbench.activity.placeholderViewlets', StorageScope.GLOBAL, '[]');
const result = (<ICachedViewlet[]>JSON.parse(previousState));
this.storageService.remove('workbench.activity.placeholderViewlets', StorageScope.GLOBAL);
return result;
}
private _cachedViewletsValue: string;
private get cachedViewletsValue(): string {
if (!this._cachedViewletsValue) {
this._cachedViewletsValue = this.getStoredCachedViewletsValue();
}
return this._cachedViewletsValue;
}
private set cachedViewletsValue(cachedViewletsValue: string) {
if (this.cachedViewletsValue !== cachedViewletsValue) {
this._cachedViewletsValue = cachedViewletsValue;
this.setStoredCachedViewletsValue(cachedViewletsValue);
}
}
private getStoredCachedViewletsValue(): string {
return this.storageService.get(ActivitybarPart.PINNED_VIEWLETS, StorageScope.GLOBAL, '[]');
}
private setStoredCachedViewletsValue(value: string): void {
this.storageService.store(ActivitybarPart.PINNED_VIEWLETS, value, StorageScope.GLOBAL);
}
private getViewContainer(viewletId: string): ViewContainer | undefined {
@@ -411,4 +501,10 @@ export class ActivitybarPart extends Part {
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
return viewContainerRegistry.get(viewletId);
}
toJSON(): object {
return {
type: Parts.ACTIVITYBAR_PART
};
}
}

View File

@@ -3,13 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item {
display: block;
position: relative;
padding: 5px 0;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-label {
display: flex;
overflow: hidden;
height: 40px;
@@ -20,7 +20,7 @@
font-size: 15px;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:focus:before {
content: "";
position: absolute;
top: 9px;
@@ -29,19 +29,19 @@
border-left: 2px solid;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.clicked:focus:before {
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.clicked:focus:before {
border-left: none !important; /* no focus feedback when using mouse */
}
.monaco-workbench > .activitybar.left > .content .monaco-action-bar .action-item:focus:before {
.monaco-workbench .activitybar.left > .content .monaco-action-bar .action-item:focus:before {
left: 1px;
}
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .action-item:focus:before {
.monaco-workbench .activitybar.right > .content .monaco-action-bar .action-item:focus:before {
right: 1px;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .badge {
.monaco-workbench .activitybar > .content .monaco-action-bar .badge {
position: absolute;
top: 5px;
left: 0;
@@ -50,7 +50,7 @@
height: 40px;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar .badge .badge-content {
.monaco-workbench .activitybar > .content .monaco-action-bar .badge .badge-content {
position: absolute;
top: 20px;
right: 8px;
@@ -65,13 +65,13 @@
/* Right aligned */
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .action-label {
.monaco-workbench .activitybar.right > .content .monaco-action-bar .action-label {
margin-left: 0;
padding: 0 50px 0 0;
background-position: calc(100% - 9px) center;
}
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .badge {
.monaco-workbench .activitybar.right > .content .monaco-action-bar .badge {
left: auto;
right: 0;
}

View File

@@ -3,23 +3,23 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench > .part.activitybar {
.monaco-workbench .part.activitybar {
width: 50px;
}
.monaco-workbench > .activitybar > .content {
.monaco-workbench .activitybar > .content {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.monaco-workbench > .activitybar > .content .monaco-action-bar {
.monaco-workbench .activitybar > .content .monaco-action-bar {
text-align: left;
background-color: inherit;
}
.monaco-workbench > .activitybar .action-item:focus {
.monaco-workbench .activitybar .action-item:focus {
outline: 0 !important; /* activity bar indicates focus custom */
}

View File

@@ -9,7 +9,6 @@ import { illegalArgument } from 'vs/base/common/errors';
import * as arrays from 'vs/base/common/arrays';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar, ICompositeBarColors, DraggedCompositeIdentifier } from 'vs/workbench/browser/parts/compositeBarActions';
@@ -20,10 +19,18 @@ import { Widget } from 'vs/base/browser/ui/widget';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
import { ITheme } from 'vs/platform/theme/common/themeService';
import { Emitter, Event } from 'vs/base/common/event';
export interface ICompositeBarItem {
id: string;
name: string;
pinned: boolean;
order: number;
visible: boolean;
}
export interface ICompositeBarOptions {
icon: boolean;
storageId: string;
orientation: ActionsOrientation;
colors: (theme: ITheme) => ICompositeBarColors;
compositeSize: number;
@@ -32,7 +39,7 @@ export interface ICompositeBarOptions {
getCompositePinnedAction: (compositeId: string) => Action;
getOnCompositeClickAction: (compositeId: string) => Action;
getContextMenuActions: () => Action[];
openComposite: (compositeId: string) => Thenable<any>;
openComposite: (compositeId: string) => Promise<any>;
getDefaultCompositeId: () => string;
hidePart: () => void;
}
@@ -51,24 +58,33 @@ export class CompositeBar extends Widget implements ICompositeBar {
private compositeTransfer: LocalSelectionTransfer<DraggedCompositeIdentifier>;
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
readonly onDidChange: Event<void> = this._onDidChange.event;
constructor(
items: ICompositeBarItem[],
private options: ICompositeBarOptions,
@IInstantiationService private instantiationService: IInstantiationService,
@IStorageService storageService: IStorageService,
@IContextMenuService private contextMenuService: IContextMenuService
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IContextMenuService private readonly contextMenuService: IContextMenuService
) {
super();
this.model = new CompositeBarModel(options, storageService);
this.model = new CompositeBarModel(items, options);
this.visibleComposites = [];
this.compositeSizeInBar = new Map<string, number>();
this.compositeTransfer = LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>();
}
getComposites(): ICompositeBarItem[] {
getCompositeBarItems(): ICompositeBarItem[] {
return [...this.model.items];
}
setCompositeBarItems(items: ICompositeBarItem[]): void {
if (this.model.setItems(items)) {
this.updateCompositeSwitcher();
}
}
getPinnedComposites(): ICompositeBarItem[] {
return this.model.pinnedItems;
}
@@ -125,7 +141,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
this.updateCompositeSwitcher();
}
addComposite({ id, name, order }: { id: string; name: string, order: number }): void {
addComposite({ id, name, order }: { id: string; name: string, order?: number }): void {
// Add to the model
if (this.model.add(id, name, order)) {
this.computeSizes([this.model.findItem(id)]);
@@ -254,7 +270,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
return item && item.activityAction;
}
private computeSizes(items: ICompositeBarItem[]): void {
private computeSizes(items: ICompositeBarModelItem[]): void {
const size = this.options.compositeSize;
if (size) {
items.forEach(composite => this.compositeSizeInBar.set(composite.id, size));
@@ -367,7 +383,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
CompositeOverflowActivityActionItem,
this.compositeOverflowAction,
() => this.getOverflowingComposites(),
() => this.model.activeItem ? this.model.activeItem.id : void 0,
() => this.model.activeItem ? this.model.activeItem.id : undefined,
(compositeId: string) => {
const item = this.model.findItem(compositeId);
return item && item.activity[0] && item.activity[0].badge;
@@ -379,8 +395,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: false, icon: true });
}
// Persist
this.model.saveState();
this._onDidChange.fire();
}
private getOverflowingComposites(): { id: string, name: string }[] {
@@ -428,15 +443,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
}
}
interface ISerializedCompositeBarItem {
id: string;
pinned: boolean;
order: number;
visible: boolean;
}
interface ICompositeBarItem extends ISerializedCompositeBarItem {
name: string;
interface ICompositeBarModelItem extends ICompositeBarItem {
activityAction: ActivityAction;
pinnedAction: Action;
activity: ICompositeActivity[];
@@ -444,28 +451,63 @@ interface ICompositeBarItem extends ISerializedCompositeBarItem {
class CompositeBarModel {
private _items: ICompositeBarModelItem[];
private readonly options: ICompositeBarOptions;
readonly items: ICompositeBarItem[];
activeItem: ICompositeBarItem;
activeItem: ICompositeBarModelItem;
constructor(
options: ICompositeBarOptions,
private storageService: IStorageService,
items: ICompositeBarItem[],
options: ICompositeBarOptions
) {
this.options = options;
this.items = this.loadItemStates();
this.setItems(items);
}
get visibleItems(): ICompositeBarItem[] {
get items(): ICompositeBarModelItem[] {
return this._items;
}
setItems(items: ICompositeBarItem[]): boolean {
const result: ICompositeBarModelItem[] = [];
let hasChanges: boolean = false;
if (!this.items || this.items.length === 0) {
this._items = items.map(i => this.createCompositeBarItem(i.id, i.name, i.order, i.pinned, i.visible));
hasChanges = true;
} else {
const existingItems = this.items;
for (let index = 0; index < items.length; index++) {
const newItem = items[index];
const existingItem = existingItems.filter(({ id }) => id === newItem.id)[0];
if (existingItem) {
if (
existingItem.pinned !== newItem.pinned ||
index !== existingItems.indexOf(existingItem)
) {
existingItem.pinned = newItem.pinned;
result.push(existingItem);
hasChanges = true;
} else {
result.push(existingItem);
}
} else {
result.push(this.createCompositeBarItem(newItem.id, newItem.name, newItem.order, newItem.pinned, newItem.visible));
hasChanges = true;
}
}
this._items = result;
}
return hasChanges;
}
get visibleItems(): ICompositeBarModelItem[] {
return this.items.filter(item => item.visible);
}
get pinnedItems(): ICompositeBarItem[] {
get pinnedItems(): ICompositeBarModelItem[] {
return this.items.filter(item => item.visible && item.pinned);
}
private createCompositeBarItem(id: string, name: string, order: number, pinned: boolean, visible: boolean): ICompositeBarItem {
private createCompositeBarItem(id: string, name: string, order: number, pinned: boolean, visible: boolean): ICompositeBarModelItem {
const options = this.options;
return {
id, name, pinned, order, visible,
@@ -551,8 +593,7 @@ class CompositeBarModel {
}
setPinned(id: string, pinned: boolean): boolean {
for (let index = 0; index < this.items.length; index++) {
const item = this.items[index];
for (const item of this.items) {
if (item.id === id) {
if (item.pinned !== pinned) {
item.pinned = pinned;
@@ -614,8 +655,7 @@ class CompositeBarModel {
if (this.activeItem) {
this.deactivate();
}
for (let index = 0; index < this.items.length; index++) {
const item = this.items[index];
for (const item of this.items) {
if (item.id === id) {
this.activeItem = item;
this.activeItem.activityAction.activate();
@@ -629,13 +669,13 @@ class CompositeBarModel {
deactivate(): boolean {
if (this.activeItem) {
this.activeItem.activityAction.deactivate();
this.activeItem = void 0;
this.activeItem = undefined;
return true;
}
return false;
}
findItem(id: string): ICompositeBarItem {
findItem(id: string): ICompositeBarModelItem {
return this.items.filter(item => item.id === id)[0];
}
@@ -647,17 +687,4 @@ class CompositeBarModel {
}
return -1;
}
private loadItemStates(): ICompositeBarItem[] {
const storedStates = <Array<string | ISerializedCompositeBarItem>>JSON.parse(this.storageService.get(this.options.storageId, StorageScope.GLOBAL, '[]'));
return <ICompositeBarItem[]>storedStates.map(c => {
const serialized: ISerializedCompositeBarItem = typeof c === 'string' /* migration from pinned states to composites states */ ? { id: c, pinned: true, order: void 0, visible: true } : c;
return this.createCompositeBarItem(serialized.id, void 0, serialized.order, serialized.pinned, isUndefinedOrNull(serialized.visible) ? true : serialized.visible);
});
}
saveState(): void {
const serialized = this.items.map(({ id, pinned, order, visible }) => ({ id, pinned, order, visible }));
this.storageService.store(this.options.storageId, JSON.stringify(serialized), StorageScope.GLOBAL);
}
}

View File

@@ -207,7 +207,7 @@ export class ActivityActionItem extends BaseActionItem {
}));
// Label
this.label = dom.append(this.element, dom.$('a.action-label'));
this.label = dom.append(this.element, dom.$('a'));
// Badge
this.badge = dom.append(this.element, dom.$('.badge'));
@@ -301,8 +301,9 @@ export class ActivityActionItem extends BaseActionItem {
}
protected updateLabel(): void {
this.label.className = 'action-label';
if (this.activity.cssClass) {
dom.addClasses(this.label, this.activity.cssClass);
dom.addClass(this.label, this.activity.cssClass);
}
if (!this.options.icon) {
this.label.textContent = this.getAction().label;
@@ -358,7 +359,7 @@ export class CompositeOverflowActivityActionItem extends ActivityActionItem {
private getBadge: (compositeId: string) => IBadge,
private getCompositeOpenAction: (compositeId: string) => Action,
colors: (theme: ITheme) => ICompositeBarColors,
@IContextMenuService private contextMenuService: IContextMenuService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IThemeService themeService: IThemeService
) {
super(action, { icon: true, colors }, themeService);
@@ -411,7 +412,7 @@ export class CompositeOverflowActivityActionItem extends ActivityActionItem {
class ManageExtensionAction extends Action {
constructor(
@ICommandService private commandService: ICommandService
@ICommandService private readonly commandService: ICommandService
) {
super('activitybar.manage.extension', nls.localize('manageExtension', "Manage Extension"));
}
@@ -434,7 +435,6 @@ export class CompositeActionItem extends ActivityActionItem {
private static manageExtensionAction: ManageExtensionAction;
private compositeActivity: IActivity;
private cssClass: string;
private compositeTransfer: LocalSelectionTransfer<DraggedCompositeIdentifier>;
constructor(
@@ -444,14 +444,13 @@ export class CompositeActionItem extends ActivityActionItem {
colors: (theme: ITheme) => ICompositeBarColors,
icon: boolean,
private compositeBar: ICompositeBar,
@IContextMenuService private contextMenuService: IContextMenuService,
@IKeybindingService private keybindingService: IKeybindingService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@IInstantiationService instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService
) {
super(compositeActivityAction, { draggable: true, colors, icon }, themeService);
this.cssClass = compositeActivityAction.class;
this.compositeTransfer = LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>();
if (!CompositeActionItem.manageExtensionAction) {
@@ -473,7 +472,7 @@ export class CompositeActionItem extends ActivityActionItem {
this.compositeActivity = {
id: this.compositeActivityAction.activity.id,
cssClass: this.cssClass,
cssClass: this.compositeActivityAction.activity.cssClass,
name: activityName
};
}
@@ -606,17 +605,6 @@ export class CompositeActionItem extends ActivityActionItem {
this.container.focus();
}
protected updateClass(): void {
if (this.cssClass) {
dom.removeClasses(this.label, this.cssClass);
}
this.cssClass = this.getAction().class;
if (this.cssClass) {
dom.addClasses(this.label, this.cssClass);
}
}
protected updateChecked(): void {
if (this.getAction().checked) {
dom.addClass(this.container, 'checked');

View File

@@ -6,7 +6,7 @@
import 'vs/css!./media/compositepart';
import * as nls from 'vs/nls';
import { defaultGenerator } from 'vs/base/common/idGenerator';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import * as strings from 'vs/base/common/strings';
import { Emitter } from 'vs/base/common/event';
import * as errors from 'vs/base/common/errors';
@@ -46,6 +46,12 @@ export interface ICompositeTitleLabel {
updateStyles(): void;
}
interface CompositeItem {
composite: Composite;
disposable: IDisposable;
progressService: IProgressService;
}
export abstract class CompositePart<T extends Composite> extends Part {
protected _onDidCompositeOpen = this._register(new Emitter<{ composite: IComposite, focus: boolean }>());
@@ -53,22 +59,20 @@ export abstract class CompositePart<T extends Composite> extends Part {
protected toolBar: ToolBar;
private instantiatedCompositeListeners: IDisposable[];
private mapCompositeToCompositeContainer: { [compositeId: string]: HTMLElement; };
private mapActionsBindingToComposite: { [compositeId: string]: () => void; };
private mapProgressServiceToComposite: { [compositeId: string]: IProgressService; };
private activeComposite: Composite;
private activeComposite: Composite | null;
private lastActiveCompositeId: string;
private instantiatedComposites: Composite[];
private instantiatedCompositeItems: Map<string, CompositeItem>;
private titleLabel: ICompositeTitleLabel;
private progressBar: ProgressBar;
private contentAreaSize: Dimension;
private telemetryActionsListener: IDisposable;
private telemetryActionsListener: IDisposable | null;
private currentCompositeOpenToken: string;
constructor(
private notificationService: INotificationService,
private storageService: IStorageService,
protected storageService: IStorageService,
private telemetryService: ITelemetryService,
protected contextMenuService: IContextMenuService,
protected partService: IPartService,
@@ -86,16 +90,14 @@ export abstract class CompositePart<T extends Composite> extends Part {
) {
super(id, options, themeService, storageService);
this.instantiatedCompositeListeners = [];
this.mapCompositeToCompositeContainer = {};
this.mapActionsBindingToComposite = {};
this.mapProgressServiceToComposite = {};
this.activeComposite = null;
this.instantiatedComposites = [];
this.instantiatedCompositeItems = new Map<string, CompositeItem>();
this.lastActiveCompositeId = storageService.get(activeCompositeSettingsKey, StorageScope.WORKSPACE, this.defaultCompositeId);
}
protected openComposite(id: string, focus?: boolean): Composite {
protected openComposite(id: string, focus?: boolean): Composite | undefined {
// Check if composite already visible and just focus in that case
if (this.activeComposite && this.activeComposite.getId() === id) {
if (focus) {
@@ -110,7 +112,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
return this.doOpenComposite(id, focus);
}
private doOpenComposite(id: string, focus?: boolean): Composite {
private doOpenComposite(id: string, focus: boolean = false): Composite | undefined {
// Use a generated token to avoid race conditions from long running promises
const currentCompositeOpenToken = defaultGenerator.nextId();
@@ -159,10 +161,9 @@ export abstract class CompositePart<T extends Composite> extends Part {
protected createComposite(id: string, isActive?: boolean): Composite {
// Check if composite is already created
for (let i = 0; i < this.instantiatedComposites.length; i++) {
if (this.instantiatedComposites[i].getId() === id) {
return this.instantiatedComposites[i];
}
const compositeItem = this.instantiatedCompositeItems.get(id);
if (compositeItem) {
return compositeItem.composite;
}
// Instantiate composite from registry otherwise
@@ -172,18 +173,18 @@ export abstract class CompositePart<T extends Composite> extends Part {
const compositeInstantiationService = this.instantiationService.createChild(new ServiceCollection([IProgressService, progressService]));
const composite = compositeDescriptor.instantiate(compositeInstantiationService);
this.mapProgressServiceToComposite[composite.getId()] = progressService;
const disposables: IDisposable[] = [];
// Remember as Instantiated
this.instantiatedComposites.push(composite);
this.instantiatedCompositeItems.set(id, { composite, disposable: toDisposable(() => dispose(disposables)), progressService });
// Register to title area update events from the composite
this.instantiatedCompositeListeners.push(composite.onTitleAreaUpdate(() => this.onTitleAreaUpdate(composite.getId())));
composite.onTitleAreaUpdate(() => this.onTitleAreaUpdate(composite.getId()), this, disposables);
return composite;
}
throw new Error(strings.format('Unable to find composite with id {0}', id));
throw new Error(`Unable to find composite with id ${id}`);
}
protected showComposite(composite: Composite): void {
@@ -219,19 +220,22 @@ export abstract class CompositePart<T extends Composite> extends Part {
}
// Report progress for slow loading composites (but only if we did not create the composites before already)
const progressService = this.mapProgressServiceToComposite[composite.getId()];
if (progressService && !compositeContainer) {
this.mapProgressServiceToComposite[composite.getId()].showWhile(Promise.resolve(), this.partService.isRestored() ? 800 : 3200 /* less ugly initial startup */);
const compositeItem = this.instantiatedCompositeItems.get(composite.getId());
if (compositeItem && !compositeContainer) {
compositeItem.progressService.showWhile(Promise.resolve(), this.partService.isRestored() ? 800 : 3200 /* less ugly initial startup */);
}
// Fill Content and Actions
// Make sure that the user meanwhile did not open another composite or closed the part containing the composite
if (!this.activeComposite || composite.getId() !== this.activeComposite.getId()) {
return void 0;
return undefined;
}
// Take Composite on-DOM and show
this.getContentArea().appendChild(compositeContainer);
const contentArea = this.getContentArea();
if (contentArea) {
contentArea.appendChild(compositeContainer);
}
show(compositeContainer);
// Setup action runner
@@ -240,7 +244,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
// Update title with composite title if it differs from descriptor
const descriptor = this.registry.getComposite(composite.getId());
if (descriptor && descriptor.name !== composite.getTitle()) {
this.updateTitle(composite.getId(), composite.getTitle());
this.updateTitle(composite.getId(), composite.getTitle() || undefined);
}
// Handle Composite Actions
@@ -296,7 +300,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
if (this.activeComposite && this.activeComposite.getId() === compositeId) {
// Title
this.updateTitle(this.activeComposite.getId(), this.activeComposite.getTitle());
this.updateTitle(this.activeComposite.getId(), this.activeComposite.getTitle() || undefined);
// Actions
const actionsBinding = this.collectCompositeActions(this.activeComposite);
@@ -322,7 +326,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
const keybinding = this.keybindingService.lookupKeybinding(compositeId);
this.titleLabel.updateTitle(compositeId, compositeTitle, keybinding ? keybinding.getLabel() : undefined);
this.titleLabel.updateTitle(compositeId, compositeTitle, (keybinding && keybinding.getLabel()) || undefined);
this.toolBar.setAriaLabel(nls.localize('ariaCompositeToolbarLabel', "{0} actions", compositeTitle));
}
@@ -341,7 +345,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
return this.toolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions));
}
protected getActiveComposite(): IComposite {
protected getActiveComposite(): IComposite | null {
return this.activeComposite;
}
@@ -349,7 +353,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
return this.lastActiveCompositeId;
}
protected hideActiveComposite(): Composite {
protected hideActiveComposite(): Composite | undefined {
if (!this.activeComposite) {
return undefined; // Nothing to do
}
@@ -423,14 +427,14 @@ export abstract class CompositePart<T extends Composite> extends Part {
this.titleLabel.updateStyles();
}
protected actionItemProvider(action: Action): IActionItem {
protected actionItemProvider(action: Action): IActionItem | null {
// Check Active Composite
if (this.activeComposite) {
return this.activeComposite.getActionItem(action);
}
return undefined;
return null;
}
createContentArea(parent: HTMLElement): HTMLElement {
@@ -443,8 +447,9 @@ export abstract class CompositePart<T extends Composite> extends Part {
return contentContainer;
}
getProgressIndicator(id: string): IProgressService {
return this.mapProgressServiceToComposite[id];
getProgressIndicator(id: string): IProgressService | null {
const compositeItem = this.instantiatedCompositeItems.get(id);
return compositeItem ? compositeItem.progressService : null;
}
protected getActions(): IAction[] {
@@ -459,10 +464,11 @@ export abstract class CompositePart<T extends Composite> extends Part {
return AnchorAlignment.RIGHT;
}
layout(dimension: Dimension): Dimension[] {
layout(dimension: Dimension): Dimension[];
layout(width: number, height: number): void;
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
// Pass to super
const sizes = super.layout(dimension);
const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2!));
// Pass Contentsize to composite
this.contentAreaSize = sizes[1];
@@ -470,20 +476,38 @@ export abstract class CompositePart<T extends Composite> extends Part {
this.activeComposite.layout(this.contentAreaSize);
}
return sizes;
if (dim1 instanceof Dimension) {
return sizes;
}
}
protected removeComposite(compositeId: string): boolean {
if (this.activeComposite && this.activeComposite.getId() === compositeId) {
// do not remove active compoiste
return false;
}
delete this.mapCompositeToCompositeContainer[compositeId];
delete this.mapActionsBindingToComposite[compositeId];
const compositeItem = this.instantiatedCompositeItems.get(compositeId);
if (compositeItem) {
compositeItem.composite.dispose();
dispose(compositeItem.disposable);
this.instantiatedCompositeItems.delete(compositeId);
}
return true;
}
dispose(): void {
this.mapCompositeToCompositeContainer = null;
this.mapProgressServiceToComposite = null;
this.mapActionsBindingToComposite = null;
this.mapCompositeToCompositeContainer = null!; // StrictNullOverride: nulling out ok in dispose
this.mapActionsBindingToComposite = null!; // StrictNullOverride: nulling out ok in dispose
for (let i = 0; i < this.instantiatedComposites.length; i++) {
this.instantiatedComposites[i].dispose();
}
this.instantiatedCompositeItems.forEach(compositeItem => {
compositeItem.composite.dispose();
dispose(compositeItem.disposable);
});
this.instantiatedComposites = [];
this.instantiatedCompositeListeners = dispose(this.instantiatedCompositeListeners);
this.instantiatedCompositeItems.clear();
super.dispose();
}

View File

@@ -12,7 +12,7 @@ import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/group/
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { LRUCache } from 'vs/base/common/map';
import { URI } from 'vs/base/common/uri';
import { once, Event } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
import { isEmptyObject } from 'vs/base/common/types';
import { DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor';
@@ -38,12 +38,12 @@ export abstract class BaseEditor extends Panel implements IEditor {
readonly minimumHeight = DEFAULT_EDITOR_MIN_DIMENSIONS.height;
readonly maximumHeight = DEFAULT_EDITOR_MAX_DIMENSIONS.height;
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }> = Event.None;
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; } | undefined> = Event.None;
protected _input: EditorInput;
protected _options: EditorOptions;
protected _input: EditorInput | null;
protected _options: EditorOptions | null;
private _group: IEditorGroup;
private _group?: IEditorGroup;
constructor(
id: string,
@@ -54,15 +54,15 @@ export abstract class BaseEditor extends Panel implements IEditor {
super(id, telemetryService, themeService, storageService);
}
get input(): EditorInput {
get input(): EditorInput | null {
return this._input;
}
get options(): EditorOptions {
get options(): EditorOptions | null {
return this._options;
}
get group(): IEditorGroup {
get group(): IEditorGroup | undefined {
return this._group;
}
@@ -77,7 +77,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
* The provided cancellation token should be used to test if the operation
* was cancelled.
*/
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
setInput(input: EditorInput, options: EditorOptions | null, token: CancellationToken): Promise<void> {
this._input = input;
this._options = options;
@@ -100,7 +100,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
* Sets the given options to the editor. Clients should apply the options
* to the current input.
*/
setOptions(options: EditorOptions): void {
setOptions(options: EditorOptions | null): void {
this._options = options;
}
@@ -118,6 +118,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
setVisible(visible: boolean, group?: IEditorGroup): void {
super.setVisible(visible);
// Propagate to Editor
this.setEditorVisible(visible, group);
}
@@ -129,7 +130,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
* @param visible the state of visibility of this editor
* @param group the editor group this editor is in.
*/
protected setEditorVisible(visible: boolean, group: IEditorGroup): void {
protected setEditorVisible(visible: boolean, group: IEditorGroup | undefined): void {
this._group = group;
}
@@ -205,18 +206,18 @@ export class EditorMemento<T> implements IEditorMemento<T> {
// Automatically clear when editor input gets disposed if any
if (resourceOrEditor instanceof EditorInput) {
once(resourceOrEditor.onDispose)(() => {
Event.once(resourceOrEditor.onDispose)(() => {
this.clearEditorState(resource);
});
}
}
loadEditorState(group: IEditorGroup, resource: URI): T;
loadEditorState(group: IEditorGroup, editor: EditorInput): T;
loadEditorState(group: IEditorGroup, resourceOrEditor: URI | EditorInput): T {
loadEditorState(group: IEditorGroup, resource: URI): T | undefined;
loadEditorState(group: IEditorGroup, editor: EditorInput): T | undefined;
loadEditorState(group: IEditorGroup, resourceOrEditor: URI | EditorInput): T | undefined {
const resource = this.doGetResource(resourceOrEditor);
if (!resource || !group) {
return void 0; // we are not in a good state to load any state for a resource
return undefined; // we are not in a good state to load any state for a resource
}
const cache = this.doLoad();
@@ -226,7 +227,7 @@ export class EditorMemento<T> implements IEditorMemento<T> {
return mementoForResource[group.id];
}
return void 0;
return undefined;
}
clearEditorState(resource: URI, group?: IEditorGroup): void;
@@ -247,7 +248,7 @@ export class EditorMemento<T> implements IEditorMemento<T> {
}
}
private doGetResource(resourceOrEditor: URI | EditorInput): URI {
private doGetResource(resourceOrEditor: URI | EditorInput): URI | null {
if (resourceOrEditor instanceof EditorInput) {
return resourceOrEditor.getResource();
}

View File

@@ -28,7 +28,7 @@ export class BinaryResourceDiffEditor extends SideBySideEditor {
super(telemetryService, instantiationService, themeService, storageService);
}
getMetadata(): string {
getMetadata(): string | null {
const master = this.masterEditor;
const details = this.detailsEditor;

View File

@@ -21,7 +21,7 @@ import { dispose } from 'vs/base/common/lifecycle';
import { IStorageService } from 'vs/platform/storage/common/storage';
export interface IOpenCallbacks {
openInternal: (input: EditorInput, options: EditorOptions) => Thenable<void>;
openInternal: (input: EditorInput, options: EditorOptions) => Promise<void>;
openExternal: (uri: URI) => void;
}
@@ -37,7 +37,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
get onDidOpenInPlace(): Event<void> { return this._onDidOpenInPlace.event; }
private callbacks: IOpenCallbacks;
private metadata: string;
private metadata: string | null;
private binaryContainer: HTMLElement;
private scrollbar: DomScrollableElement;
private resourceViewerContext: ResourceViewerContext;
@@ -55,7 +55,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
this.callbacks = callbacks;
}
getTitle(): string {
getTitle() {
return this.input ? this.input.getName() : nls.localize('binaryEditor', "Binary Viewer");
}
@@ -72,13 +72,13 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
parent.appendChild(this.scrollbar.getDomNode());
}
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
return super.setInput(input, options, token).then(() => {
return input.resolve().then(model => {
// Check for cancellation
if (token.isCancellationRequested) {
return void 0;
return undefined;
}
// Assert Model instance
@@ -97,7 +97,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
meta => this.handleMetadataChanged(meta)
);
return void 0;
return undefined;
});
});
}
@@ -110,13 +110,13 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
});
}
private handleMetadataChanged(meta: string): void {
private handleMetadataChanged(meta: string | null): void {
this.metadata = meta;
this._onMetadataChanged.fire();
}
getMetadata(): string {
getMetadata() {
return this.metadata;
}

View File

@@ -23,7 +23,7 @@ export interface IBreadcrumbsService {
register(group: GroupIdentifier, widget: BreadcrumbsWidget): IDisposable;
getWidget(group: GroupIdentifier): BreadcrumbsWidget;
getWidget(group: GroupIdentifier): BreadcrumbsWidget | undefined;
}
@@ -43,12 +43,12 @@ export class BreadcrumbsService implements IBreadcrumbsService {
};
}
getWidget(group: number): BreadcrumbsWidget {
getWidget(group: number): BreadcrumbsWidget | undefined {
return this._map.get(group);
}
}
registerSingleton(IBreadcrumbsService, BreadcrumbsService);
registerSingleton(IBreadcrumbsService, BreadcrumbsService, true);
//#region config
@@ -59,7 +59,7 @@ export abstract class BreadcrumbsConfig<T> {
onDidChange: Event<void>;
abstract getValue(overrides?: IConfigurationOverrides): T;
abstract updateValue(value: T, overrides?: IConfigurationOverrides): Thenable<void>;
abstract updateValue(value: T, overrides?: IConfigurationOverrides): Promise<void>;
abstract dispose(): void;
private constructor() {
@@ -90,10 +90,18 @@ export abstract class BreadcrumbsConfig<T> {
readonly name = name;
readonly onDidChange = onDidChange.event;
getValue(overrides?: IConfigurationOverrides): T {
return service.getValue(name, overrides);
if (overrides) {
return service.getValue(name, overrides);
} else {
return service.getValue(name);
}
}
updateValue(newValue: T, overrides?: IConfigurationOverrides): Thenable<void> {
return service.updateValue(name, newValue, overrides);
updateValue(newValue: T, overrides?: IConfigurationOverrides): Promise<void> {
if (overrides) {
return service.updateValue(name, newValue, overrides);
} else {
return service.updateValue(name, newValue);
}
}
dispose(): void {
listener.dispose();
@@ -112,7 +120,7 @@ Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfigurat
type: 'object',
properties: {
'breadcrumbs.enabled': {
description: localize('enabled', "Enable/disable navigation breadcrumbs"),
description: localize('enabled', "Enable/disable navigation breadcrumbs."),
type: 'boolean',
default: false
},

View File

@@ -35,7 +35,7 @@ import { ColorIdentifier, ColorFunction } from 'vs/platform/theme/common/colorRe
import { attachBreadcrumbsStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { FileLabel } from 'vs/workbench/browser/labels';
import { ResourceLabel } from 'vs/workbench/browser/labels';
import { BreadcrumbsConfig, IBreadcrumbsService } from 'vs/workbench/browser/parts/editor/breadcrumbs';
import { BreadcrumbElement, EditorBreadcrumbsModel, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel';
import { BreadcrumbsPicker, createBreadcrumbsPicker } from 'vs/workbench/browser/parts/editor/breadcrumbsPicker';
@@ -78,8 +78,8 @@ class Item extends BreadcrumbsItem {
render(container: HTMLElement): void {
if (this.element instanceof FileElement) {
// file/folder
let label = this._instantiationService.createInstance(FileLabel, container, {});
label.setFile(this.element.uri, {
let label = this._instantiationService.createInstance(ResourceLabel, container, {});
label.element.setFile(this.element.uri, {
hidePath: true,
hideIcon: this.element.kind === FileKind.FOLDER || !this.options.showFileIcons,
fileKind: this.element.kind,
@@ -98,7 +98,7 @@ class Item extends BreadcrumbsItem {
} else if (this.element instanceof OutlineGroup) {
// provider
let label = new IconLabel(container);
label.setValue(this.element.provider.displayName);
label.setLabel(this.element.provider.displayName);
this._disposables.push(label);
} else if (this.element instanceof OutlineElement) {
@@ -111,7 +111,7 @@ class Item extends BreadcrumbsItem {
}
let label = new IconLabel(container);
let title = this.element.symbol.name.replace(/\r|\n|\r\n/g, '\u23CE');
label.setValue(title);
label.setLabel(title);
this._disposables.push(label);
}
}
@@ -356,7 +356,7 @@ export class BreadcrumbsControl {
},
getAnchor: () => {
let maxInnerWidth = window.innerWidth - 8 /*a little less the full widget*/;
let maxHeight = Math.min(window.innerHeight * .7, 300);
let maxHeight = Math.min(window.innerHeight * 0.7, 300);
let pickerWidth = Math.min(maxInnerWidth, Math.max(240, maxInnerWidth / 4.17));
let pickerArrowSize = 8;
@@ -379,7 +379,7 @@ export class BreadcrumbsControl {
pickerArrowOffset = maxPickerArrowOffset;
}
} else {
pickerArrowOffset = (data.left + (data.width * .3)) - x;
pickerArrowOffset = (data.left + (data.width * 0.3)) - x;
}
picker.setInput(element, maxHeight, pickerWidth, pickerArrowSize, Math.max(0, pickerArrowOffset));
return { x, y };
@@ -453,15 +453,17 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
category: localize('cmd.category', "View")
}
});
MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
group: '5_editor',
order: 99,
command: {
id: 'breadcrumbs.toggle',
title: localize('miToggleBreadcrumbs', "Toggle &&Breadcrumbs"),
toggled: ContextKeyExpr.equals('config.breadcrumbs.enabled', true)
}
});
// {{SQL CARBON EDIT}} - Disable unused menu item
// MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
// group: '5_editor',
// order: 99,
// command: {
// id: 'breadcrumbs.toggle',
// title: localize('miToggleBreadcrumbs', "Toggle &&Breadcrumbs"),
// toggled: ContextKeyExpr.equals('config.breadcrumbs.enabled', true)
// }
// });
// {{SQL CARBON EDIT}} - End
CommandsRegistry.registerCommand('breadcrumbs.toggle', accessor => {
let config = accessor.get(IConfigurationService);
let value = BreadcrumbsConfig.IsEnabled.bindTo(config).getValue();

View File

@@ -8,7 +8,7 @@ import { TimeoutTimer } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { size } from 'vs/base/common/collections';
import { onUnexpectedError } from 'vs/base/common/errors';
import { debounceEvent, Emitter, Event } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { isEqual, dirname } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
@@ -31,7 +31,7 @@ export class FileElement {
export type BreadcrumbElement = FileElement | OutlineModel | OutlineGroup | OutlineElement;
type FileInfo = { path: FileElement[], folder: IWorkspaceFolder };
type FileInfo = { path: FileElement[], folder?: IWorkspaceFolder };
export class EditorBreadcrumbsModel {
@@ -41,7 +41,7 @@ export class EditorBreadcrumbsModel {
private readonly _cfgFilePath: BreadcrumbsConfig<'on' | 'off' | 'last'>;
private readonly _cfgSymbolPath: BreadcrumbsConfig<'on' | 'off' | 'last'>;
private _outlineElements: (OutlineModel | OutlineGroup | OutlineElement)[] = [];
private _outlineElements: Array<OutlineModel | OutlineGroup | OutlineElement> = [];
private _outlineDisposables: IDisposable[] = [];
private _onDidUpdate = new Emitter<this>();
@@ -105,16 +105,21 @@ export class EditorBreadcrumbsModel {
}
let info: FileInfo = {
folder: workspaceService.getWorkspaceFolder(uri),
folder: workspaceService.getWorkspaceFolder(uri) || undefined,
path: []
};
while (uri.path !== '/') {
if (info.folder && isEqual(info.folder.uri, uri)) {
let uriPrefix: URI | null = uri;
while (uriPrefix && uriPrefix.path !== '/') {
if (info.folder && isEqual(info.folder.uri, uriPrefix)) {
break;
}
info.path.unshift(new FileElement(uriPrefix, info.path.length === 0 ? FileKind.FILE : FileKind.FOLDER));
let prevPathLength = uriPrefix.path.length;
uriPrefix = dirname(uriPrefix);
if (!uriPrefix || uriPrefix.path.length === prevPathLength) {
break;
}
info.path.unshift(new FileElement(uri, info.path.length === 0 ? FileKind.FILE : FileKind.FOLDER));
uri = dirname(uri);
}
if (info.folder && workspaceService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
@@ -131,7 +136,7 @@ export class EditorBreadcrumbsModel {
this._disposables.push(DocumentSymbolProviderRegistry.onDidChange(_ => this._updateOutline()));
this._disposables.push(this._editor.onDidChangeModel(_ => this._updateOutline()));
this._disposables.push(this._editor.onDidChangeModelLanguage(_ => this._updateOutline()));
this._disposables.push(debounceEvent(this._editor.onDidChangeModelContent, _ => _, 350)(_ => this._updateOutline(true)));
this._disposables.push(Event.debounce(this._editor.onDidChangeModelContent, _ => _, 350)(_ => this._updateOutline(true)));
this._updateOutline();
// stop when editor dies
@@ -145,7 +150,9 @@ export class EditorBreadcrumbsModel {
this._updateOutlineElements([]);
}
const buffer = this._editor.getModel();
const editor = this._editor!;
const buffer = editor.getModel();
if (!buffer || !DocumentSymbolProviderRegistry.has(buffer) || !isEqual(buffer.uri, this._uri)) {
return;
}
@@ -171,11 +178,11 @@ export class EditorBreadcrumbsModel {
// copy the model
model = model.adopt();
this._updateOutlineElements(this._getOutlineElements(model, this._editor.getPosition()));
this._outlineDisposables.push(this._editor.onDidChangeCursorPosition(_ => {
this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition()));
this._outlineDisposables.push(editor.onDidChangeCursorPosition(_ => {
timeout.cancelAndSet(() => {
if (!buffer.isDisposed() && versionIdThen === buffer.getVersionId() && this._editor.getModel()) {
this._updateOutlineElements(this._getOutlineElements(model, this._editor.getPosition()));
if (!buffer.isDisposed() && versionIdThen === buffer.getVersionId() && editor.getModel()) {
this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition()));
}
}, 150);
}));
@@ -186,22 +193,22 @@ export class EditorBreadcrumbsModel {
});
}
private _getOutlineElements(model: OutlineModel, position: IPosition): (OutlineModel | OutlineGroup | OutlineElement)[] {
if (!model) {
private _getOutlineElements(model: OutlineModel, position: IPosition | null): Array<OutlineModel | OutlineGroup | OutlineElement> {
if (!model || !position) {
return [];
}
let item: OutlineGroup | OutlineElement = model.getItemEnclosingPosition(position);
let item: OutlineGroup | OutlineElement | undefined = model.getItemEnclosingPosition(position);
if (!item) {
return [model];
}
let chain: (OutlineGroup | OutlineElement)[] = [];
let chain: Array<OutlineGroup | OutlineElement> = [];
while (item) {
chain.push(item);
let parent = item.parent;
if (parent instanceof OutlineModel) {
break;
}
if (parent instanceof OutlineGroup && size(parent.parent.children) === 1) {
if (parent instanceof OutlineGroup && parent.parent && size(parent.parent.children) === 1) {
break;
}
item = parent;
@@ -209,7 +216,7 @@ export class EditorBreadcrumbsModel {
return chain.reverse();
}
private _updateOutlineElements(elements: (OutlineModel | OutlineGroup | OutlineElement)[]): void {
private _updateOutlineElements(elements: Array<OutlineModel | OutlineGroup | OutlineElement>): void {
if (!equals(elements, this._outlineElements, EditorBreadcrumbsModel._outlineElementEquals)) {
this._outlineElements = elements;
this._onDidUpdate.fire(this);

View File

@@ -14,7 +14,6 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { join } from 'vs/base/common/paths';
import { basename, dirname, isEqual } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDataSource, IFilter, IRenderer, ISorter, ITree } from 'vs/base/parts/tree/browser/tree';
import 'vs/css!./media/breadcrumbscontrol';
import { OutlineElement, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel';
@@ -26,7 +25,7 @@ import { IConstructorSignature1, IInstantiationService } from 'vs/platform/insta
import { HighlightingWorkbenchTree, IHighlighter, IHighlightingTreeConfiguration, IHighlightingTreeOptions } from 'vs/platform/list/browser/listService';
import { breadcrumbsPickerBackground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { FileLabel } from 'vs/workbench/browser/labels';
import { ResourceLabels, IResourceLabel, DEFAULT_LABELS_CONTAINER } from 'vs/workbench/browser/labels';
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
import { BreadcrumbElement, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel';
import { IFileIconTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
@@ -160,7 +159,7 @@ export abstract class BreadcrumbsPicker {
// use proper selection, reveal
let selection = this._getInitialSelection(this._tree, input);
if (selection) {
return this._tree.reveal(selection, .5).then(() => {
return this._tree.reveal(selection, 0.5).then(() => {
this._tree.setSelection([selection], this._tree);
this._tree.setFocus(selection);
this._tree.domFocus();
@@ -228,7 +227,7 @@ export class FileDataSource implements IDataSource {
return URI.isUri(element) || IWorkspace.isIWorkspace(element) || IWorkspaceFolder.isIWorkspaceFolder(element) || element.isDirectory;
}
getChildren(tree: ITree, element: IWorkspace | IWorkspaceFolder | IFileStat | URI): TPromise<IWorkspaceFolder[] | IFileStat[]> {
getChildren(tree: ITree, element: IWorkspace | IWorkspaceFolder | IFileStat | URI): Promise<IWorkspaceFolder[] | IFileStat[]> {
if (IWorkspace.isIWorkspace(element)) {
return Promise.resolve(element.folders).then(folders => {
for (let child of folders) {
@@ -253,7 +252,7 @@ export class FileDataSource implements IDataSource {
});
}
getParent(tree: ITree, element: IWorkspace | URI | IWorkspaceFolder | IFileStat): TPromise<IWorkspaceFolder | IFileStat> {
getParent(tree: ITree, element: IWorkspace | URI | IWorkspaceFolder | IFileStat): Promise<IWorkspaceFolder | IFileStat> {
return Promise.resolve(this._parents.get(element));
}
}
@@ -330,7 +329,7 @@ export class FileHighlighter implements IHighlighter {
export class FileRenderer implements IRenderer {
constructor(
@IInstantiationService private readonly _instantiationService: IInstantiationService,
private readonly _labels: ResourceLabels,
@IConfigurationService private readonly _configService: IConfigurationService,
) { }
@@ -343,10 +342,10 @@ export class FileRenderer implements IRenderer {
}
renderTemplate(tree: ITree, templateId: string, container: HTMLElement) {
return this._instantiationService.createInstance(FileLabel, container, { supportHighlights: true });
return this._labels.create(container, { supportHighlights: true });
}
renderElement(tree: ITree, element: IFileStat | IWorkspaceFolder, templateId: string, templateData: FileLabel): void {
renderElement(tree: ITree, element: IFileStat | IWorkspaceFolder, templateId: string, templateData: IResourceLabel): void {
let fileDecorations = this._configService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
let resource: URI;
let fileKind: FileKind;
@@ -366,7 +365,7 @@ export class FileRenderer implements IRenderer {
});
}
disposeTemplate(tree: ITree, templateId: string, templateData: FileLabel): void {
disposeTemplate(tree: ITree, templateId: string, templateData: IResourceLabel): void {
templateData.dispose();
}
}
@@ -428,7 +427,9 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
this._disposables.push(filter);
config.dataSource = this._instantiationService.createInstance(FileDataSource);
config.renderer = this._instantiationService.createInstance(FileRenderer);
const labels = this._instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER /* TODO@Jo visibility propagation */);
this._disposables.push(labels);
config.renderer = this._instantiationService.createInstance(FileRenderer, labels);
config.sorter = new FileSorter();
config.highlighter = new FileHighlighter();
config.filter = filter;

View File

@@ -50,6 +50,7 @@ import { AllEditorsPicker, ActiveEditorGroupPicker } from 'vs/workbench/browser/
import { Schemas } from 'vs/base/common/network';
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';
// Register String Editor
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
@@ -110,7 +111,7 @@ interface ISerializedUntitledEditorInput {
class UntitledEditorInputFactory implements IEditorInputFactory {
constructor(
@ITextFileService private textFileService: ITextFileService
@ITextFileService private readonly textFileService: ITextFileService
) { }
serialize(editorInput: EditorInput): string {
@@ -144,7 +145,7 @@ class UntitledEditorInputFactory implements IEditorInputFactory {
return instantiationService.invokeFunction<UntitledEditorInput>(accessor => {
const deserialized: ISerializedUntitledEditorInput = JSON.parse(serializedEditorInput);
const resource = !!deserialized.resourceJSON ? URI.revive(deserialized.resourceJSON) : URI.parse(deserialized.resource);
const filePath = resource.scheme === Schemas.file ? resource.fsPath : void 0;
const filePath = resource.scheme === Schemas.file ? resource.fsPath : undefined;
const language = deserialized.modeId;
const encoding = deserialized.encoding;
@@ -226,6 +227,9 @@ registerEditorContribution(OpenWorkspaceButtonContribution);
const statusBar = Registry.as<IStatusbarRegistry>(StatusExtensions.Statusbar);
statusBar.registerStatusbarItem(new StatusbarItemDescriptor(EditorStatus, StatusbarAlignment.RIGHT, 100 /* towards the left of the right hand side */));
// Register Zoom Status
statusBar.registerStatusbarItem(new StatusbarItemDescriptor(ZoomStatusbarItem, StatusbarAlignment.RIGHT, 101 /* to the left of editor status (100) */));
// Register Status Actions
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeModeAction, ChangeModeAction.ID, ChangeModeAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_M) }), 'Change Language Mode');
@@ -235,7 +239,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeEncodingAction,
export class QuickOpenActionContributor extends ActionBarContributor {
private openToSideActionInstance: OpenToSideFromQuickOpenAction;
constructor(@IInstantiationService private instantiationService: IInstantiationService) {
constructor(@IInstantiationService private readonly instantiationService: IInstantiationService) {
super();
}
@@ -745,7 +749,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, {
// Forward/Back
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '1_fwd_back',
group: '1_history_nav',
command: {
id: 'workbench.action.navigateBack',
title: nls.localize({ key: 'miBack', comment: ['&& denotes a mnemonic'] }, "&&Back"),
@@ -755,7 +759,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '1_fwd_back',
group: '1_history_nav',
command: {
id: 'workbench.action.navigateForward',
title: nls.localize({ key: 'miForward', comment: ['&& denotes a mnemonic'] }, "&&Forward"),
@@ -764,6 +768,16 @@ MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '1_history_nav',
command: {
id: 'workbench.action.navigateToLastEditLocation',
title: nls.localize({ key: 'miLastEditLocation', comment: ['&& denotes a mnemonic'] }, "&&Last Edit Location"),
precondition: ContextKeyExpr.has('canNavigateToLastEditLocation')
},
order: 3
});
// Switch Editor
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '1_any',
@@ -802,7 +816,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '2_switch',
group: '2_editor_nav',
title: nls.localize({ key: 'miSwitchEditor', comment: ['&& denotes a mnemonic'] }, "Switch &&Editor"),
submenu: MenuId.MenubarSwitchEditorMenu,
order: 1
@@ -909,7 +923,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '2_switch',
group: '2_editor_nav',
title: nls.localize({ key: 'miSwitchGroup', comment: ['&& denotes a mnemonic'] }, "Switch &&Group"),
submenu: MenuId.MenubarSwitchGroupMenu,
order: 2

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { GroupIdentifier, IWorkbenchEditorConfiguration, IWorkbenchEditorPartConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent } from 'vs/workbench/common/editor';
import { GroupIdentifier, IWorkbenchEditorConfiguration, IWorkbenchEditorPartConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditor } from 'vs/workbench/common/editor';
import { EditorGroup } from 'vs/workbench/common/editor/editorGroup';
import { IEditorGroup, GroupDirection, IAddGroupOptions, IMergeGroupOptions, GroupsOrder, IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { IDisposable } from 'vs/base/common/lifecycle';
@@ -30,6 +30,7 @@ export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
highlightModifiedTabs: false,
tabCloseButton: 'right',
tabSizing: 'fit',
focusRecentEditorAfterClose: true,
showIcons: true,
enablePreview: true,
openPositioning: 'right',
@@ -74,9 +75,9 @@ export interface IEditorOpeningEvent extends IEditorIdentifier {
* that will be executed instead. By returning another editor promise
* it is possible to override the opening with another editor. It is ok
* to return a promise that resolves to NULL to prevent the opening
* altogether.
* alltogether.
*/
prevent(callback: () => Thenable<any>): void;
prevent(callback: () => Promise<IEditor>): void;
}
export interface IEditorGroupsAccessor {
@@ -102,7 +103,7 @@ export interface IEditorGroupsAccessor {
export interface IEditorGroupView extends IDisposable, ISerializableView, IEditorGroup {
readonly group: EditorGroup;
readonly whenRestored: Thenable<void>;
readonly whenRestored: Promise<void>;
readonly disposed: boolean;
readonly onDidFocus: Event<void>;
@@ -119,7 +120,7 @@ export interface IEditorGroupView extends IDisposable, ISerializableView, IEdito
}
export function getActiveTextEditorOptions(group: IEditorGroup, expectedActiveEditor?: IEditorInput, presetOptions?: EditorOptions): EditorOptions {
const activeGroupCodeEditor = group.activeControl ? getCodeEditor(group.activeControl.getControl()) : void 0;
const activeGroupCodeEditor = group.activeControl ? getCodeEditor(group.activeControl.getControl()) : undefined;
if (activeGroupCodeEditor) {
if (!expectedActiveEditor || expectedActiveEditor.matches(group.activeEditor)) {
return TextEditorOptions.fromEditor(activeGroupCodeEditor, presetOptions);
@@ -155,5 +156,5 @@ export interface EditorGroupsServiceImpl extends IEditorGroupsService {
/**
* A promise that resolves when groups have been restored.
*/
readonly whenRestored: Thenable<void>;
readonly whenRestored: Promise<void>;
}

View File

@@ -35,7 +35,7 @@ export class ExecuteCommandAction extends Action {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
return this.commandService.executeCommand(this.commandId, this.commandArgs);
}
}
@@ -182,7 +182,7 @@ export class JoinTwoGroupsAction extends Action {
constructor(
id: string,
label: string,
@IEditorGroupsService private editorGroupService: IEditorGroupsService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
) {
super(id, label);
}
@@ -196,8 +196,8 @@ export class JoinTwoGroupsAction extends Action {
}
const targetGroupDirections = [GroupDirection.RIGHT, GroupDirection.DOWN, GroupDirection.LEFT, GroupDirection.UP];
for (let i = 0; i < targetGroupDirections.length; i++) {
const targetGroup = this.editorGroupService.findGroup({ direction: targetGroupDirections[i] }, sourceGroup);
for (const targetGroupDirection of targetGroupDirections) {
const targetGroup = this.editorGroupService.findGroup({ direction: targetGroupDirection }, sourceGroup);
if (targetGroup && sourceGroup !== targetGroup) {
this.editorGroupService.mergeGroup(sourceGroup, targetGroup);
@@ -217,7 +217,7 @@ export class JoinAllGroupsAction extends Action {
constructor(
id: string,
label: string,
@IEditorGroupsService private editorGroupService: IEditorGroupsService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
) {
super(id, label);
}
@@ -237,12 +237,12 @@ export class NavigateBetweenGroupsAction extends Action {
constructor(
id: string,
label: string,
@IEditorGroupsService private editorGroupService: IEditorGroupsService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
const nextGroup = this.editorGroupService.findGroup({ location: GroupLocation.NEXT }, this.editorGroupService.activeGroup, true);
nextGroup.focus();
@@ -258,12 +258,12 @@ export class FocusActiveGroupAction extends Action {
constructor(
id: string,
label: string,
@IEditorGroupsService private editorGroupService: IEditorGroupsService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.editorGroupService.activeGroup.focus();
return Promise.resolve(true);
@@ -276,12 +276,12 @@ export abstract class BaseFocusGroupAction extends Action {
id: string,
label: string,
private scope: IFindGroupScope,
@IEditorGroupsService private editorGroupService: IEditorGroupsService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
const group = this.editorGroupService.findGroup(this.scope, this.editorGroupService.activeGroup, true);
if (group) {
group.focus();
@@ -409,8 +409,8 @@ export class OpenToSideFromQuickOpenAction extends Action {
static readonly OPEN_TO_SIDE_LABEL = nls.localize('openToSide', "Open to the Side");
constructor(
@IEditorService private editorService: IEditorService,
@IConfigurationService private configurationService: IConfigurationService
@IEditorService private readonly editorService: IEditorService,
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super(OpenToSideFromQuickOpenAction.OPEN_TO_SIDE_ID, OpenToSideFromQuickOpenAction.OPEN_TO_SIDE_LABEL);
@@ -423,7 +423,7 @@ export class OpenToSideFromQuickOpenAction extends Action {
this.class = (preferredDirection === GroupDirection.RIGHT) ? 'quick-open-sidebyside-vertical' : 'quick-open-sidebyside-horizontal';
}
run(context: any): Thenable<any> {
run(context: any): Promise<any> {
const entry = toEditorQuickOpenEntry(context);
if (entry) {
const input = entry.getInput();
@@ -467,13 +467,13 @@ export class CloseEditorAction extends Action {
constructor(
id: string,
label: string,
@ICommandService private commandService: ICommandService
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, 'close-editor-action');
}
run(context?: IEditorCommandsContext): Promise<any> {
return this.commandService.executeCommand(CLOSE_EDITOR_COMMAND_ID, void 0, context);
return this.commandService.executeCommand(CLOSE_EDITOR_COMMAND_ID, undefined, context);
}
}
@@ -485,12 +485,12 @@ export class CloseOneEditorAction extends Action {
constructor(
id: string,
label: string,
@IEditorGroupsService private editorGroupService: IEditorGroupsService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
) {
super(id, label, 'close-editor-action');
}
run(context?: IEditorCommandsContext): Thenable<any> {
run(context?: IEditorCommandsContext): Promise<any> {
let group: IEditorGroup;
let editorIndex: number;
if (context) {
@@ -530,12 +530,12 @@ export class RevertAndCloseEditorAction extends Action {
constructor(
id: string,
label: string,
@IEditorService private editorService: IEditorService
@IEditorService private readonly editorService: IEditorService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
const activeControl = this.editorService.activeControl;
if (activeControl) {
const editor = activeControl.input;
@@ -563,13 +563,13 @@ export class CloseLeftEditorsInGroupAction extends Action {
constructor(
id: string,
label: string,
@IEditorService private editorService: IEditorService,
@IEditorGroupsService private editorGroupService: IEditorGroupsService
@IEditorService private readonly editorService: IEditorService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
) {
super(id, label);
}
run(context?: IEditorIdentifier): Thenable<any> {
run(context?: IEditorIdentifier): Promise<any> {
const { group, editor } = getTarget(this.editorService, this.editorGroupService, context);
if (group && editor) {
return group.closeEditors({ direction: CloseDirection.LEFT, except: editor });
@@ -614,7 +614,7 @@ export abstract class BaseCloseAllAction extends Action {
return groupsToClose;
}
run(): Thenable<any> {
run(): Promise<any> {
// Just close all if there are no or one dirty editor
if (this.textFileService.getDirty().length < 2) {
@@ -624,10 +624,10 @@ export abstract class BaseCloseAllAction extends Action {
// Otherwise ask for combined confirmation
return this.textFileService.confirmSave().then(confirm => {
if (confirm === ConfirmResult.CANCEL) {
return void 0;
return undefined;
}
let saveOrRevertPromise: Thenable<boolean>;
let saveOrRevertPromise: Promise<boolean>;
if (confirm === ConfirmResult.DONT_SAVE) {
saveOrRevertPromise = this.textFileService.revertAll(null, { soft: true }).then(() => true);
} else {
@@ -639,12 +639,12 @@ export abstract class BaseCloseAllAction extends Action {
return this.doCloseAll();
}
return void 0;
return undefined;
});
});
}
protected abstract doCloseAll(): Thenable<any>;
protected abstract doCloseAll(): Promise<any>;
}
export class CloseAllEditorsAction extends BaseCloseAllAction {
@@ -677,7 +677,7 @@ export class CloseAllEditorGroupsAction extends BaseCloseAllAction {
@ITextFileService textFileService: ITextFileService,
@IEditorGroupsService editorGroupService: IEditorGroupsService
) {
super(id, label, void 0, textFileService, editorGroupService);
super(id, label, undefined, textFileService, editorGroupService);
}
protected doCloseAll(): Promise<any> {
@@ -695,12 +695,12 @@ export class CloseEditorsInOtherGroupsAction extends Action {
constructor(
id: string,
label: string,
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
) {
super(id, label);
}
run(context?: IEditorIdentifier): Thenable<any> {
run(context?: IEditorIdentifier): Promise<any> {
const groupToSkip = context ? this.editorGroupService.getGroup(context.groupId) : this.editorGroupService.activeGroup;
return Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(g => {
if (g.id === groupToSkip.id) {
@@ -720,13 +720,13 @@ export class CloseEditorInAllGroupsAction extends Action {
constructor(
id: string,
label: string,
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
@IEditorService private editorService: IEditorService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IEditorService private readonly editorService: IEditorService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
const activeEditor = this.editorService.activeEditor;
if (activeEditor) {
return Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(g => g.closeEditor(activeEditor)));
@@ -780,14 +780,14 @@ export class BaseMoveGroupAction extends Action {
break;
}
for (let i = 0; i < targetNeighbours.length; i++) {
const targetNeighbour = this.editorGroupService.findGroup({ direction: targetNeighbours[i] }, sourceGroup);
if (targetNeighbour) {
return targetNeighbour;
for (const targetNeighbour of targetNeighbours) {
const targetNeighbourGroup = this.editorGroupService.findGroup({ direction: targetNeighbour }, sourceGroup);
if (targetNeighbourGroup) {
return targetNeighbourGroup;
}
}
return void 0;
return undefined;
}
}
@@ -852,11 +852,11 @@ export class MinimizeOtherGroupsAction extends Action {
static readonly ID = 'workbench.action.minimizeOtherEditors';
static readonly LABEL = nls.localize('minimizeOtherEditorGroups', "Maximize Editor Group");
constructor(id: string, label: string, @IEditorGroupsService private editorGroupService: IEditorGroupsService) {
constructor(id: string, label: string, @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.editorGroupService.arrangeGroups(GroupsArrangement.MINIMIZE_OTHERS);
return Promise.resolve(false);
@@ -868,11 +868,11 @@ export class ResetGroupSizesAction extends Action {
static readonly ID = 'workbench.action.evenEditorWidths';
static readonly LABEL = nls.localize('evenEditorGroups', "Reset Editor Group Sizes");
constructor(id: string, label: string, @IEditorGroupsService private editorGroupService: IEditorGroupsService) {
constructor(id: string, label: string, @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.editorGroupService.arrangeGroups(GroupsArrangement.EVEN);
return Promise.resolve(false);
@@ -887,14 +887,14 @@ export class MaximizeGroupAction extends Action {
constructor(
id: string,
label: string,
@IEditorService private editorService: IEditorService,
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
@IPartService private partService: IPartService
@IEditorService private readonly editorService: IEditorService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IPartService private readonly partService: IPartService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
if (this.editorService.activeEditor) {
this.editorGroupService.arrangeGroups(GroupsArrangement.MINIMIZE_OTHERS);
this.partService.setSideBarHidden(true);
@@ -915,7 +915,7 @@ export abstract class BaseNavigateEditorAction extends Action {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
const result = this.navigate();
if (!result) {
return Promise.resolve(false);
@@ -964,7 +964,7 @@ export class OpenNextEditor extends BaseNavigateEditorAction {
return { editor: previousGroupEditors[0], groupId: nextGroup.id };
}
return void 0;
return undefined;
}
}
@@ -999,7 +999,7 @@ export class OpenPreviousEditor extends BaseNavigateEditorAction {
return { editor: previousGroupEditors[previousGroupEditors.length - 1], groupId: previousGroup.id };
}
return void 0;
return undefined;
}
}
@@ -1098,11 +1098,11 @@ export class NavigateForwardAction extends Action {
static readonly ID = 'workbench.action.navigateForward';
static readonly LABEL = nls.localize('navigateNext', "Go Forward");
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.historyService.forward();
return Promise.resolve(null);
@@ -1114,11 +1114,11 @@ export class NavigateBackwardsAction extends Action {
static readonly ID = 'workbench.action.navigateBack';
static readonly LABEL = nls.localize('navigatePrevious', "Go Back");
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.historyService.back();
return Promise.resolve(null);
@@ -1130,11 +1130,11 @@ export class NavigateToLastEditLocationAction extends Action {
static readonly ID = 'workbench.action.navigateToLastEditLocation';
static readonly LABEL = nls.localize('navigateToLastEditLocation', "Go to Last Edit Location");
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.historyService.openLastEditLocation();
return Promise.resolve(null);
@@ -1146,11 +1146,11 @@ export class NavigateLastAction extends Action {
static readonly ID = 'workbench.action.navigateLast';
static readonly LABEL = nls.localize('navigateLast', "Go Last");
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.historyService.last();
return Promise.resolve(null);
@@ -1165,12 +1165,12 @@ export class ReopenClosedEditorAction extends Action {
constructor(
id: string,
label: string,
@IHistoryService private historyService: IHistoryService
@IHistoryService private readonly historyService: IHistoryService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.historyService.reopenLastClosedEditor();
return Promise.resolve(false);
@@ -1185,13 +1185,13 @@ export class ClearRecentFilesAction extends Action {
constructor(
id: string,
label: string,
@IWindowsService private windowsService: IWindowsService,
@IHistoryService private historyService: IHistoryService
@IWindowsService private readonly windowsService: IWindowsService,
@IHistoryService private readonly historyService: IHistoryService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
// Clear global recently opened
this.windowsService.clearRecentlyOpened();
@@ -1232,13 +1232,13 @@ export class BaseQuickOpenEditorInGroupAction extends Action {
constructor(
id: string,
label: string,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IKeybindingService private keybindingService: IKeybindingService
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
const keys = this.keybindingService.lookupKeybindings(this.id);
@@ -1287,13 +1287,13 @@ export class OpenPreviousEditorFromHistoryAction extends Action {
constructor(
id: string,
label: string,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IKeybindingService private keybindingService: IKeybindingService
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
const keys = this.keybindingService.lookupKeybindings(this.id);
this.quickOpenService.show(null, { quickNavigateConfiguration: { keybindings: keys } });
@@ -1307,11 +1307,11 @@ export class OpenNextRecentlyUsedEditorAction extends Action {
static readonly ID = 'workbench.action.openNextRecentlyUsedEditor';
static readonly LABEL = nls.localize('openNextRecentlyUsedEditor', "Open Next Recently Used Editor");
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.historyService.forward(true);
return Promise.resolve(null);
@@ -1323,11 +1323,11 @@ export class OpenPreviousRecentlyUsedEditorAction extends Action {
static readonly ID = 'workbench.action.openPreviousRecentlyUsedEditor';
static readonly LABEL = nls.localize('openPreviousRecentlyUsedEditor', "Open Previous Recently Used Editor");
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.historyService.back(true);
return Promise.resolve(null);
@@ -1342,12 +1342,12 @@ export class ClearEditorHistoryAction extends Action {
constructor(
id: string,
label: string,
@IHistoryService private historyService: IHistoryService
@IHistoryService private readonly historyService: IHistoryService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
// Editor history
this.historyService.clear();
@@ -1619,7 +1619,7 @@ export class BaseCreateEditorGroupAction extends Action {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
this.editorGroupService.addGroup(this.editorGroupService.activeGroup, this.direction, { activate: true });
return Promise.resolve(true);

View File

@@ -267,8 +267,8 @@ function registerDiffEditorCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: TOGGLE_DIFF_SIDE_BY_SIDE,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
primary: void 0,
when: undefined,
primary: undefined,
handler: accessor => toggleDiffSideBySide(accessor)
});
@@ -287,8 +287,8 @@ function registerDiffEditorCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
primary: void 0,
when: undefined,
primary: undefined,
handler: accessor => toggleDiffIgnoreTrimWhitespace(accessor)
});
}
@@ -319,7 +319,7 @@ function registerOpenEditorAtIndexCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: OPEN_EDITOR_AT_INDEX_COMMAND_ID + visibleIndex,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
when: undefined,
primary: KeyMod.Alt | toKeyCode(visibleIndex),
mac: { primary: KeyMod.WinCtrl | toKeyCode(visibleIndex) },
handler: accessor => openEditorAtIndex(accessor, editorIndex)
@@ -340,7 +340,7 @@ function registerOpenEditorAtIndexCommands(): void {
case 9: return KeyCode.KEY_9;
}
return void 0;
return undefined;
}
}
@@ -351,7 +351,7 @@ function registerFocusEditorGroupAtIndexCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: toCommandId(groupIndex),
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
when: undefined,
primary: KeyMod.CtrlCmd | toKeyCode(groupIndex),
handler: accessor => {
const editorGroupService = accessor.get(IEditorGroupsService);
@@ -392,7 +392,7 @@ function registerFocusEditorGroupAtIndexCommands(): void {
case 7: return 'workbench.action.focusEighthEditorGroup';
}
return void 0;
return undefined;
}
function toKeyCode(index: number): KeyCode {
@@ -406,7 +406,7 @@ function registerFocusEditorGroupAtIndexCommands(): void {
case 7: return KeyCode.KEY_8;
}
return void 0;
return undefined;
}
}
@@ -455,7 +455,7 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_SAVED_EDITORS_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
when: undefined,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_U),
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
@@ -475,7 +475,7 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
when: undefined,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_W),
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
@@ -495,7 +495,7 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_EDITOR_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
when: undefined,
primary: KeyMod.CtrlCmd | KeyCode.KEY_W,
win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] },
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
@@ -544,8 +544,8 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
primary: void 0,
when: undefined,
primary: undefined,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_T },
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
@@ -573,8 +573,8 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
primary: void 0,
when: undefined,
primary: undefined,
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
@@ -590,7 +590,7 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: KEEP_EDITOR_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
when: undefined,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.Enter),
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
@@ -607,8 +607,8 @@ function registerCloseEditorCommands() {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: SHOW_EDITORS_IN_GROUP,
weight: KeybindingWeight.WorkbenchContrib,
when: void 0,
primary: void 0,
when: undefined,
primary: undefined,
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const quickOpenService = accessor.get(IQuickOpenService);
@@ -638,7 +638,7 @@ function registerCloseEditorCommands() {
});
}
return void 0;
return undefined;
});
}
@@ -655,7 +655,7 @@ function getCommandsContext(resourceOrContext: URI | IEditorCommandsContext, con
return context;
}
return void 0;
return undefined;
}
function resolveCommandsContext(editorGroupService: IEditorGroupsService, context?: IEditorCommandsContext): { group: IEditorGroup, editor: IEditorInput, control: IEditor } {
@@ -682,7 +682,7 @@ export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsCon
if (list instanceof List && list.getHTMLElement() === document.activeElement) {
const elementToContext = (element: IEditorIdentifier | IEditorGroup) => {
if (isEditorGroup(element)) {
return { groupId: element.id, editorIndex: void 0 };
return { groupId: element.id, editorIndex: undefined };
}
return { groupId: element.groupId, editorIndex: editorGroupService.getGroup(element.groupId).getIndexOfEditor(element.editor) };
@@ -690,11 +690,11 @@ export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsCon
const onlyEditorGroupAndEditor = (e: IEditorIdentifier | IEditorGroup) => isEditorGroup(e) || isEditorIdentifier(e);
const focusedElements: (IEditorIdentifier | IEditorGroup)[] = list.getFocusedElements().filter(onlyEditorGroupAndEditor);
const focus = editorContext ? editorContext : focusedElements.length ? focusedElements.map(elementToContext)[0] : void 0; // need to take into account when editor context is { group: group }
const focusedElements: Array<IEditorIdentifier | IEditorGroup> = list.getFocusedElements().filter(onlyEditorGroupAndEditor);
const focus = editorContext ? editorContext : focusedElements.length ? focusedElements.map(elementToContext)[0] : undefined; // need to take into account when editor context is { group: group }
if (focus) {
const selection: (IEditorIdentifier | IEditorGroup)[] = list.getSelectedElements().filter(onlyEditorGroupAndEditor);
const selection: Array<IEditorIdentifier | IEditorGroup> = list.getSelectedElements().filter(onlyEditorGroupAndEditor);
// Only respect selection if it contains focused element
if (selection && selection.some(s => isEditorGroup(s) ? s.id === focus.groupId : s.groupId === focus.groupId && editorGroupService.getGroup(s.groupId).getIndexOfEditor(s.editor) === focus.editorIndex)) {

View File

@@ -8,7 +8,6 @@ import { EditorInput, EditorOptions } from 'vs/workbench/common/editor';
import { Dimension, show, hide, addClass } from 'vs/base/browser/dom';
import { Registry } from 'vs/platform/registry/common/platform';
import { IEditorRegistry, Extensions as EditorExtensions, IEditorDescriptor } from 'vs/workbench/browser/editor';
import { TPromise } from 'vs/base/common/winjs.base';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -31,10 +30,10 @@ export class EditorControl extends Disposable {
private _onDidFocus: Emitter<void> = this._register(new Emitter<void>());
get onDidFocus(): Event<void> { return this._onDidFocus.event; }
private _onDidSizeConstraintsChange = this._register(new Emitter<{ width: number; height: number; }>());
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return this._onDidSizeConstraintsChange.event; }
private _onDidSizeConstraintsChange = this._register(new Emitter<{ width: number; height: number; } | undefined>());
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; } | undefined> { return this._onDidSizeConstraintsChange.event; }
private _activeControl: BaseEditor;
private _activeControl: BaseEditor | null;
private controls: BaseEditor[] = [];
private activeControlDisposeables: IDisposable[] = [];
@@ -44,8 +43,8 @@ export class EditorControl extends Disposable {
constructor(
private parent: HTMLElement,
private groupView: IEditorGroupView,
@IPartService private partService: IPartService,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private readonly partService: IPartService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IProgressService progressService: IProgressService
) {
super();
@@ -53,21 +52,24 @@ export class EditorControl extends Disposable {
this.editorOperation = this._register(new LongRunningOperation(progressService));
}
get activeControl(): BaseEditor {
get activeControl() {
return this._activeControl;
}
openEditor(editor: EditorInput, options?: EditorOptions): TPromise<IOpenEditorResult> {
openEditor(editor: EditorInput, options?: EditorOptions): Promise<IOpenEditorResult> {
// Editor control
const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editor);
const control = this.doShowEditorControl(descriptor, options);
if (!descriptor) {
throw new Error('No editor descriptor found');
}
const control = this.doShowEditorControl(descriptor);
// Set input
return this.doSetInput(control, editor, options).then((editorChanged => (({ control, editorChanged } as IOpenEditorResult))));
return this.doSetInput(control, editor, options || null).then((editorChanged => (({ control, editorChanged } as IOpenEditorResult))));
}
private doShowEditorControl(descriptor: IEditorDescriptor, options: EditorOptions): BaseEditor {
private doShowEditorControl(descriptor: IEditorDescriptor): BaseEditor {
// Return early if the currently active editor control can handle the input
if (this._activeControl && descriptor.describes(this._activeControl)) {
@@ -130,7 +132,7 @@ export class EditorControl extends Disposable {
return control;
}
private doSetActiveControl(control: BaseEditor) {
private doSetActiveControl(control: BaseEditor | null) {
this._activeControl = control;
// Clear out previous active control listeners
@@ -143,10 +145,10 @@ export class EditorControl extends Disposable {
}
// Indicate that size constraints could have changed due to new editor
this._onDidSizeConstraintsChange.fire();
this._onDidSizeConstraintsChange.fire(undefined);
}
private doSetInput(control: BaseEditor, editor: EditorInput, options: EditorOptions): TPromise<boolean> {
private doSetInput(control: BaseEditor, editor: EditorInput, options: EditorOptions | null): Promise<boolean> {
// If the input did not change, return early and only apply the options
// unless the options instruct us to force open it even if it is the same
@@ -163,7 +165,7 @@ export class EditorControl extends Disposable {
control.focus();
}
return TPromise.as(false);
return Promise.resolve(false);
}
// Show progress while setting input after a certain timeout. If the workbench is opening
@@ -172,7 +174,7 @@ export class EditorControl extends Disposable {
// Call into editor control
const editorWillChange = !inputMatches;
return TPromise.wrap(control.setInput(editor, options, operation.token)).then(() => {
return control.setInput(editor, options, operation.token).then(() => {
// Focus (unless prevented or another operation is running)
if (operation.isCurrent()) {
@@ -191,7 +193,7 @@ export class EditorControl extends Disposable {
// Operation done
operation.stop();
return TPromise.wrapError(e);
return Promise.reject(e);
});
}

View File

@@ -96,7 +96,7 @@ class DropOverlay extends Themable {
private registerListeners(): void {
this._register(new DragAndDropObserver(this.container, {
onDragEnter: e => void 0,
onDragEnter: e => undefined,
onDragOver: e => {
const isDraggingGroup = this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype);
const isDraggingEditor = this.editorTransfer.hasData(DraggedEditorIdentifier.prototype);
@@ -170,7 +170,7 @@ class DropOverlay extends Themable {
return this.accessor.getGroup(this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier.groupId);
}
return void 0;
return undefined;
}
private handleDrop(event: DragEvent, splitDirection?: GroupDirection): void {
@@ -303,7 +303,7 @@ class DropOverlay extends Themable {
mousePosX > edgeWidthThreshold && mousePosX < editorControlWidth - edgeWidthThreshold &&
mousePosY > edgeHeightThreshold && mousePosY < editorControlHeight - edgeHeightThreshold
) {
splitDirection = void 0;
splitDirection = undefined;
}
// Offer to split otherwise
@@ -413,7 +413,7 @@ class DropOverlay extends Themable {
removeClass(this.overlay, 'overlay-move-transition');
// Reset current operation
this.currentDropOperation = void 0;
this.currentDropOperation = undefined;
}
contains(element: HTMLElement): boolean {
@@ -440,7 +440,7 @@ export class EditorDropTarget extends Themable {
private accessor: IEditorGroupsAccessor,
private container: HTMLElement,
@IThemeService themeService: IThemeService,
@IInstantiationService private instantiationService: IInstantiationService
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super(themeService);
@@ -452,7 +452,7 @@ export class EditorDropTarget extends Themable {
return this._overlay;
}
return void 0;
return undefined;
}
private registerListeners(): void {
@@ -512,15 +512,13 @@ export class EditorDropTarget extends Themable {
private findTargetGroupView(child: HTMLElement): IEditorGroupView {
const groups = this.accessor.groups;
for (let i = 0; i < groups.length; i++) {
const groupView = groups[i];
for (const groupView of groups) {
if (isAncestor(child, groupView.element)) {
return groupView;
}
}
return void 0;
return undefined;
}
private updateContainer(isDraggedOver: boolean): void {
@@ -536,7 +534,7 @@ export class EditorDropTarget extends Themable {
private disposeOverlay(): void {
if (this.overlay) {
this.overlay.dispose();
this._overlay = void 0;
this._overlay = undefined;
}
}
}

View File

@@ -4,10 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/editorgroupview';
import { TPromise } from 'vs/base/common/winjs.base';
import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup';
import { EditorInput, EditorOptions, GroupIdentifier, ConfirmResult, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext } from 'vs/workbench/common/editor';
import { Event, Emitter, once, Relay } from 'vs/base/common/event';
import { EditorInput, EditorOptions, GroupIdentifier, ConfirmResult, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor } from 'vs/workbench/common/editor';
import { Event, Emitter, Relay } from 'vs/base/common/event';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@@ -100,7 +99,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
private active: boolean;
private dimension: Dimension;
private _whenRestored: Thenable<void>;
private _whenRestored: Promise<void>;
private isRestored: boolean;
private scopedInstantiationService: IInstantiationService;
@@ -116,21 +115,21 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
private ignoreOpenEditorErrors: boolean;
private disposedEditorsWorker: RunOnceWorker<EditorInput>;
private mapEditorToPendingConfirmation: Map<EditorInput, TPromise<boolean>> = new Map<EditorInput, TPromise<boolean>>();
private mapEditorToPendingConfirmation: Map<EditorInput, Promise<boolean>> = new Map<EditorInput, Promise<boolean>>();
constructor(
private accessor: IEditorGroupsAccessor,
from: IEditorGroupView | ISerializedEditorGroup,
private _label: string,
@IInstantiationService private instantiationService: IInstantiationService,
@IContextKeyService private contextKeyService: IContextKeyService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@INotificationService private notificationService: INotificationService,
@ITelemetryService private telemetryService: ITelemetryService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@IKeybindingService private keybindingService: IKeybindingService,
@IMenuService private menuService: IMenuService,
@IContextMenuService private contextMenuService: IContextMenuService,
@INotificationService private readonly notificationService: INotificationService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@IMenuService private readonly menuService: IMenuService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
// {{SQL CARBON EDIT}}
@ICommandService private commandService: ICommandService
) {
@@ -141,7 +140,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
} else if (isSerializedEditorGroup(from)) {
this._group = this._register(instantiationService.createInstance(EditorGroup, from));
} else {
this._group = this._register(instantiationService.createInstance(EditorGroup, void 0));
this._group = this._register(instantiationService.createInstance(EditorGroup, undefined));
}
this.disposedEditorsWorker = this._register(new RunOnceWorker(editors => this.handleDisposedEditors(editors), 0));
@@ -283,9 +282,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
});
// Toolbar actions
const removeGroupAction = this._register(new Action(CLOSE_EDITOR_GROUP_COMMAND_ID, localize('closeGroupAction', "Close"), 'close-editor-group', true, () => { this.accessor.removeGroup(this); return TPromise.as(true); }));
const removeGroupAction = this._register(new Action(CLOSE_EDITOR_GROUP_COMMAND_ID, localize('closeGroupAction', "Close"), 'close-editor-group', true, () => { this.accessor.removeGroup(this); return Promise.resolve(true); }));
const keybinding = this.keybindingService.lookupKeybinding(removeGroupAction.id);
containerToolbar.push(removeGroupAction, { icon: true, label: false, keybinding: keybinding ? keybinding.getLabel() : void 0 });
containerToolbar.push(removeGroupAction, { icon: true, label: false, keybinding: keybinding ? keybinding.getLabel() : undefined });
}
private createContainerContextMenu(): void {
@@ -309,7 +308,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Fill in contributed actions
const actions: IAction[] = [];
fillInContextMenuActions(menu, void 0, actions, this.contextMenuService);
fillInContextMenuActions(menu, undefined, actions, this.contextMenuService);
// Show it
this.contextMenuService.showContextMenu({
@@ -334,7 +333,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
let target: HTMLElement;
if (e instanceof MouseEvent) {
if (e.button !== 0) {
return void 0; // only for left mouse click
return undefined; // only for left mouse click
}
target = e.target as HTMLElement;
@@ -404,9 +403,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
}
private restoreEditors(from: IEditorGroupView | ISerializedEditorGroup): Thenable<void> {
private restoreEditors(from: IEditorGroupView | ISerializedEditorGroup): Promise<void> {
if (this._group.count === 0) {
return Promise.resolve(void 0); // nothing to show
return Promise.resolve(); // nothing to show
}
// Determine editor options
@@ -491,7 +490,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Close the editor when it is no longer open in any group including diff editors
editorsToClose.forEach(editorToClose => {
const resource = editorToClose ? editorToClose.getResource() : void 0; // prefer resource to not close right-hand side editors of a diff editor
const resource = editorToClose ? editorToClose.getResource() : undefined; // prefer resource to not close right-hand side editors of a diff editor
if (!this.accessor.groups.some(groupView => groupView.group.contains(resource || editorToClose))) {
editorToClose.close();
}
@@ -609,7 +608,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return this._disposed;
}
get whenRestored(): Thenable<void> {
get whenRestored(): Promise<void> {
return this._whenRestored;
}
@@ -660,7 +659,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
get activeControl(): BaseEditor {
return this.editorControl ? this.editorControl.activeControl : void 0;
return this.editorControl ? this.editorControl.activeControl : undefined;
}
get activeEditor(): EditorInput {
@@ -731,11 +730,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
//#region openEditor()
openEditor(editor: EditorInput, options?: EditorOptions): TPromise<void> {
openEditor(editor: EditorInput, options?: EditorOptions): Promise<IEditor | null> {
// Guard against invalid inputs
if (!editor) {
return TPromise.as(void 0);
return Promise.resolve(null);
}
// Editor opening event allows for prevention
@@ -750,11 +749,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return this.doOpenEditor(editor, options);
}
private doOpenEditor(editor: EditorInput, options?: EditorOptions): TPromise<void> {
private doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise<IEditor> {
// Determine options
const openEditorOptions: IEditorOpenOptions = {
index: options ? options.index : void 0,
index: options ? options.index : undefined,
pinned: !this.accessor.partOptions.enablePreview || editor.isDirty() || (options && options.pinned) || (options && typeof options.index === 'number'),
active: this._group.count === 0 || !options || !options.inactive
};
@@ -791,10 +790,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return this.doShowEditor(editor, openEditorOptions.active, options);
}
private doShowEditor(editor: EditorInput, active: boolean, options?: EditorOptions): TPromise<void> {
private doShowEditor(editor: EditorInput, active: boolean, options?: EditorOptions): Promise<IEditor> {
// Show in editor control if the active editor changed
let openEditorPromise: TPromise<void>;
let openEditorPromise: Promise<IEditor>;
if (active) {
openEditorPromise = this.editorControl.openEditor(editor, options).then(result => {
@@ -802,13 +801,17 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
if (result.editorChanged) {
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_ACTIVE, editor });
}
return result.control;
}, error => {
// Handle errors but do not bubble them up
this.doHandleOpenEditorError(error, editor, options);
return null; // error: return NULL as result to signal this
});
} else {
openEditorPromise = TPromise.as(void 0);
openEditorPromise = Promise.resolve(null); // inactive: return NULL as result to signal this
}
// Show in title control after editor control because some actions depend on it
@@ -833,7 +836,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
actions
});
once(handle.onDidClose)(() => dispose(actions.primary));
Event.once(handle.onDidClose)(() => dispose(actions.primary));
}
// Event
@@ -850,17 +853,21 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
//#region openEditors()
openEditors(editors: { editor: EditorInput, options?: EditorOptions }[]): TPromise<void> {
openEditors(editors: { editor: EditorInput, options?: EditorOptions }[]): Promise<IEditor | null> {
if (!editors.length) {
return TPromise.as(void 0);
return Promise.resolve(null);
}
// Do not modify original array
editors = editors.slice(0);
let result: IEditor;
// Use the first editor as active editor
const { editor, options } = editors.shift();
return this.openEditor(editor, options).then(() => {
return this.openEditor(editor, options).then(activeEditor => {
result = activeEditor; // this can be NULL if the opening failed
const startingIndex = this.getIndexOfEditor(editor) + 1;
// Open the other ones inactive
@@ -870,8 +877,12 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
adjustedEditorOptions.pinned = true;
adjustedEditorOptions.index = startingIndex + index;
return this.openEditor(editor, adjustedEditorOptions);
})).then(() => void 0);
return this.openEditor(editor, adjustedEditorOptions).then(activeEditor => {
if (!result) {
result = activeEditor; // only take if the first editor opening failed
}
});
})).then(() => result);
});
}
@@ -893,7 +904,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
private doMoveEditorInsideGroup(editor: EditorInput, moveOptions?: IMoveEditorOptions): void {
const moveToIndex = moveOptions ? moveOptions.index : void 0;
const moveToIndex = moveOptions ? moveOptions.index : undefined;
if (typeof moveToIndex !== 'number') {
return; // do nothing if we move into same group without index
}
@@ -953,9 +964,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
//#region closeEditor()
closeEditor(editor: EditorInput = this.activeEditor): TPromise<void> {
closeEditor(editor: EditorInput = this.activeEditor): Promise<void> {
if (!editor) {
return TPromise.as(void 0);
return Promise.resolve();
}
// Check for dirty and veto
@@ -1025,7 +1036,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
this.ignoreOpenEditorErrors = true;
}
const options = !focusNext ? EditorOptions.create({ preserveFocus: true }) : void 0;
const options = !focusNext ? EditorOptions.create({ preserveFocus: true }) : undefined;
this.openEditor(nextActiveEditor, options).then(() => {
this.ignoreOpenEditorErrors = false;
});
@@ -1069,9 +1080,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
this._group.closeEditor(editor);
}
private handleDirty(editors: EditorInput[]): TPromise<boolean /* veto */> {
private handleDirty(editors: EditorInput[]): Promise<boolean /* veto */> {
if (!editors.length) {
return TPromise.as(false); // no veto
return Promise.resolve(false); // no veto
}
const editor = editors.shift();
@@ -1099,13 +1110,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
});
}
private doHandleDirty(editor: EditorInput): TPromise<boolean /* veto */> {
private doHandleDirty(editor: EditorInput): Promise<boolean /* veto */> {
if (
!editor.isDirty() || // editor must be dirty
this.accessor.groups.some(groupView => groupView !== this && groupView.group.contains(editor, true /* support side by side */)) || // editor is opened in other group
editor instanceof SideBySideEditorInput && this.isOpened(editor.master) // side by side editor master is still opened
) {
return TPromise.as(false);
return Promise.resolve(false);
}
// Switch to editor that we want to handle and confirm to save/revert
@@ -1146,9 +1157,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
//#region closeEditors()
closeEditors(args: EditorInput[] | ICloseEditorsFilter): TPromise<void> {
closeEditors(args: EditorInput[] | ICloseEditorsFilter): Promise<void> {
if (this.isEmpty()) {
return TPromise.as(void 0);
return Promise.resolve();
}
const editors = this.getEditorsToClose(args);
@@ -1219,7 +1230,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
//#region closeAllEditors()
closeAllEditors(): TPromise<void> {
closeAllEditors(): Promise<void> {
if (this.isEmpty()) {
// If the group is empty and the request is to close all editors, we still close
@@ -1229,7 +1240,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
this.accessor.removeGroup(this);
}
return TPromise.as(void 0);
return Promise.resolve();
}
// Check for dirty and veto
@@ -1264,7 +1275,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
//#region replaceEditors()
replaceEditors(editors: EditorReplacement[]): TPromise<void> {
replaceEditors(editors: EditorReplacement[]): Promise<void> {
// Extract active vs. inactive replacements
let activeReplacement: EditorReplacement;
@@ -1322,10 +1333,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Forward to title control
this.titleAreaControl.closeEditor(activeReplacement.editor);
return openEditorResult;
return openEditorResult.then(() => undefined);
}
return TPromise.as(void 0);
return Promise.resolve();
}
//#endregion
@@ -1379,6 +1390,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
layout(width: number, height: number): void {
this.dimension = new Dimension(width, height);
// Ensure editor container gets height as CSS depending
// on the preferred height of the title control
this.editorContainer.style.height = `calc(100% - ${this.titleAreaControl.getPreferredHeight()}px)`;
// Forward to controls
this.titleAreaControl.layout(new Dimension(this.dimension.width, this.titleAreaControl.getPreferredHeight()));
this.editorControl.layout(new Dimension(this.dimension.width, this.dimension.height - this.titleAreaControl.getPreferredHeight()));
@@ -1410,7 +1425,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
class EditorOpeningEvent implements IEditorOpeningEvent {
private override: () => TPromise<any>;
private override: () => Promise<IEditor>;
constructor(
private _group: GroupIdentifier,
@@ -1431,11 +1446,11 @@ class EditorOpeningEvent implements IEditorOpeningEvent {
return this._options;
}
prevent(callback: () => TPromise<any>): void {
prevent(callback: () => Promise<IEditor>): void {
this.override = callback;
}
isPrevented(): () => TPromise<any> {
isPrevented(): () => Promise<IEditor> {
return this.override;
}
}
@@ -1451,7 +1466,7 @@ registerThemingParticipant((theme, collector, environment) => {
// Letterpress
const letterpress = `resources/letterpress${theme.type === 'dark' ? '-dark' : theme.type === 'hc' ? '-hc' : ''}.svg`;
collector.addRule(`
.monaco-workbench > .part.editor > .content .editor-group-container.empty .editor-group-letterpress {
.monaco-workbench .part.editor > .content .editor-group-container.empty .editor-group-letterpress {
background-image: url('${URI.file(join(environment.appRoot, letterpress)).toString()}')
}
`);
@@ -1460,20 +1475,20 @@ registerThemingParticipant((theme, collector, environment) => {
const focusedEmptyGroupBorder = theme.getColor(EDITOR_GROUP_FOCUSED_EMPTY_BORDER);
if (focusedEmptyGroupBorder) {
collector.addRule(`
.monaco-workbench > .part.editor > .content:not(.empty) .editor-group-container.empty.active:focus {
.monaco-workbench .part.editor > .content:not(.empty) .editor-group-container.empty.active:focus {
outline-width: 1px;
outline-color: ${focusedEmptyGroupBorder};
outline-offset: -2px;
outline-style: solid;
}
.monaco-workbench > .part.editor > .content.empty .editor-group-container.empty.active:focus {
.monaco-workbench .part.editor > .content.empty .editor-group-container.empty.active:focus {
outline: none; /* never show outline for empty group if it is the last */
}
`);
} else {
collector.addRule(`
.monaco-workbench > .part.editor > .content .editor-group-container.empty.active:focus {
.monaco-workbench .part.editor > .content .editor-group-container.empty.active:focus {
outline: none; /* disable focus outline unless active empty group border is defined */
}
`);

View File

@@ -7,11 +7,11 @@ import 'vs/workbench/browser/parts/editor/editor.contribution';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { Part } from 'vs/workbench/browser/part';
import { Dimension, isAncestor, toggleClass, addClass, $ } from 'vs/base/browser/dom';
import { Event, Emitter, once, Relay, anyEvent } from 'vs/base/common/event';
import { Event, Emitter, Relay } from 'vs/base/common/event';
import { contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry';
import { GroupDirection, IAddGroupOptions, GroupsArrangement, GroupOrientation, IMergeGroupOptions, MergeGroupMode, ICopyEditorOptions, GroupsOrder, GroupChangeKind, GroupLocation, IFindGroupScope, EditorGroupLayout, GroupLayoutArgument } from 'vs/workbench/services/group/common/editorGroupsService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Direction, SerializableGrid, Sizing, ISerializedGrid, Orientation, GridBranchNode, isGridBranchNode, GridNode, createSerializedGrid, Grid } from 'vs/base/browser/ui/grid/grid';
import { Direction, SerializableGrid, Sizing, ISerializedGrid, Orientation, GridBranchNode, isGridBranchNode, GridNode, createSerializedGrid, Grid, ISerializableView } from 'vs/base/browser/ui/grid/grid';
import { GroupIdentifier, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor';
import { values } from 'vs/base/common/map';
import { EDITOR_GROUP_BORDER, EDITOR_PANE_BACKGROUND } from 'vs/workbench/common/theme';
@@ -23,13 +23,13 @@ import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup';
import { always } from 'vs/base/common/async';
import { EditorDropTarget } from 'vs/workbench/browser/parts/editor/editorDropTarget';
import { localize } from 'vs/nls';
import { Color } from 'vs/base/common/color';
import { CenteredViewLayout } from 'vs/base/browser/ui/centered/centeredViewLayout';
import { IView, orthogonal } from 'vs/base/browser/ui/grid/gridview';
import { IView, orthogonal, LayoutPriority } from 'vs/base/browser/ui/grid/gridview';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Parts } from 'vs/workbench/services/part/common/partService';
// {{SQL CARBON EDIT}}
import { convertEditorInput } from 'sql/parts/common/customInputConverter';
@@ -83,7 +83,7 @@ class GridWidgetView<T extends IView> implements IView {
}
}
export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditorGroupsAccessor {
export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditorGroupsAccessor, ISerializableView {
_serviceBrand: any;
@@ -109,11 +109,14 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
private onDidSetGridWidget = this._register(new Emitter<{ width: number; height: number; }>());
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; }>());
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return anyEvent(this.onDidSetGridWidget.event, this._onDidSizeConstraintsChange.event); }
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return Event.any(this.onDidSetGridWidget.event, this._onDidSizeConstraintsChange.event); }
private _onDidPreferredSizeChange: Emitter<void> = this._register(new Emitter<void>());
get onDidPreferredSizeChange(): Event<void> { return this._onDidPreferredSizeChange.event; }
private _onDidActivateGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
get onDidActivateGroup(): Event<IEditorGroupView> { return this._onDidActivateGroup.event; }
//#endregion
private dimension: Dimension;
@@ -133,15 +136,22 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
private gridWidget: SerializableGrid<IEditorGroupView>;
private gridWidgetView: GridWidgetView<IEditorGroupView>;
private _whenRestored: Thenable<void>;
private _whenRestored: Promise<void>;
private whenRestoredResolve: () => void;
element: HTMLElement;
private _onDidChange = new Emitter<{ width: number; height: number; }>();
readonly onDidChange = this._onDidChange.event;
priority: LayoutPriority = LayoutPriority.High;
constructor(
id: string,
private restorePreviousState: boolean,
@IInstantiationService private instantiationService: IInstantiationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IConfigurationService private configurationService: IConfigurationService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IStorageService storageService: IStorageService
) {
super(id, { hasTitle: false }, themeService, storageService);
@@ -220,13 +230,13 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
get orientation(): GroupOrientation {
if (!this.gridWidget) {
return void 0; // we have not been created yet
return undefined; // we have not been created yet
}
return this.gridWidget.orientation === Orientation.VERTICAL ? GroupOrientation.VERTICAL : GroupOrientation.HORIZONTAL;
}
get whenRestored(): Thenable<void> {
get whenRestored(): Promise<void> {
return this._whenRestored;
}
@@ -316,6 +326,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
const groupView = this.assertGroupView(group);
this.doSetGroupActive(groupView);
this._onDidActivateGroup.fire(groupView);
return groupView;
}
@@ -527,7 +538,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
}));
// Track dispose
once(groupView.onWillDispose)(() => {
Event.once(groupView.onWillDispose)(() => {
groupDisposables = dispose(groupDisposables);
this.groupViews.delete(groupView.id);
this.doUpdateMostRecentActive(groupView);
@@ -762,7 +773,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
private resetPreferredSize(): void {
// Reset (will be computed upon next access)
this._preferredSize = void 0;
this._preferredSize = undefined;
// Event
this._onDidPreferredSizeChange.fire();
@@ -783,6 +794,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
createContentArea(parent: HTMLElement): HTMLElement {
// Container
this.element = parent;
this.container = document.createElement('div');
addClass(this.container, 'content');
parent.appendChild(this.container);
@@ -824,7 +836,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
}
// Signal restored
always(Promise.all(this.groups.map(group => group.whenRestored)), () => this.whenRestoredResolve());
Promise.all(this.groups.map(group => group.whenRestored)).finally(() => this.whenRestoredResolve());
// Update container
this.updateContainer();
@@ -861,7 +873,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
this.groupViews.forEach(group => group.dispose());
this.groupViews.clear();
this._activeGroup = void 0;
this._activeGroup = undefined;
this.mostRecentActiveGroups = [];
}
@@ -924,7 +936,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
this._onDidSizeConstraintsChange.input = gridWidget.onDidChange;
}
this.onDidSetGridWidget.fire();
this.onDidSetGridWidget.fire(undefined);
}
private updateContainer(): void {
@@ -950,12 +962,16 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
return this.groupViews.size === 1 && this._activeGroup.isEmpty();
}
layout(dimension: Dimension): Dimension[] {
const sizes = super.layout(dimension);
layout(dimension: Dimension): Dimension[];
layout(width: number, height: number): void;
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2));
this.doLayout(sizes[1]);
return sizes;
if (dim1 instanceof Dimension) {
return sizes;
}
}
private doLayout(dimension: Dimension): void {
@@ -1016,4 +1032,10 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
}
//#endregion
}
toJSON(): object {
return {
type: Parts.EDITOR_PART
};
}
}

View File

@@ -25,8 +25,8 @@ export class EditorPickerEntry extends QuickOpenEntryGroup {
constructor(
private editor: EditorInput,
private _group: IEditorGroup,
@IModeService private modeService: IModeService,
@IModelService private modelService: IModelService
@IModeService private readonly modeService: IModeService,
@IModelService private readonly modelService: IModelService
) {
super();
}
@@ -90,7 +90,7 @@ export abstract class BaseEditorPicker extends QuickOpenHandler {
this.scorerCache = Object.create(null);
}
getResults(searchValue: string, token: CancellationToken): Thenable<QuickOpenModel> {
getResults(searchValue: string, token: CancellationToken): Promise<QuickOpenModel | null> {
const editorEntries = this.getEditorEntries();
if (!editorEntries.length) {
return Promise.resolve(null);

View File

@@ -50,7 +50,7 @@ import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { timeout } from 'vs/base/common/async';
import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { once } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
class SideBySideEditorEncodingSupport implements IEncodingSupport {
constructor(private master: IEncodingSupport, private details: IEncodingSupport) { }
@@ -290,12 +290,12 @@ export class EditorStatus implements IStatusbarItem {
private screenReaderNotification: INotificationHandle;
constructor(
@IEditorService private editorService: IEditorService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IInstantiationService private instantiationService: IInstantiationService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@IModeService private modeService: IModeService,
@ITextFileService private textFileService: ITextFileService,
@IEditorService private readonly editorService: IEditorService,
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
@IModeService private readonly modeService: IModeService,
@ITextFileService private readonly textFileService: ITextFileService,
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
@INotificationService private readonly notificationService: INotificationService
) {
@@ -518,7 +518,7 @@ export class EditorStatus implements IStatusbarItem {
{ sticky: true }
);
once(this.screenReaderNotification.onDidClose)(() => {
Event.once(this.screenReaderNotification.onDidClose)(() => {
this.screenReaderNotification = null;
});
}
@@ -548,7 +548,7 @@ export class EditorStatus implements IStatusbarItem {
private updateStatusBar(): void {
const activeControl = this.editorService.activeControl;
const activeCodeEditor = activeControl ? getCodeEditor(activeControl.getControl()) : void 0;
const activeCodeEditor = activeControl ? getCodeEditor(activeControl.getControl()) : undefined;
// Update all states
this.onScreenReaderModeChange(activeCodeEditor);
@@ -587,8 +587,8 @@ export class EditorStatus implements IStatusbarItem {
this.onEOLChange(activeCodeEditor);
let selections = activeCodeEditor.getSelections();
for (let i = 0; i < e.changes.length; i++) {
if (selections.some(selection => Range.areIntersecting(selection, e.changes[i].range))) {
for (const change of e.changes) {
if (selections.some(selection => Range.areIntersecting(selection, change.range))) {
this.onSelectionChange(activeCodeEditor);
break;
}
@@ -820,7 +820,7 @@ export class ShowLanguageExtensionsAction extends Action {
constructor(
private fileExtension: string,
@ICommandService private commandService: ICommandService,
@ICommandService private readonly commandService: ICommandService,
@IExtensionGalleryService galleryService: IExtensionGalleryService
) {
super(ShowLanguageExtensionsAction.ID, nls.localize('showLanguageExtensions', "Search Marketplace Extensions for '{0}'...", fileExtension));
@@ -828,8 +828,8 @@ export class ShowLanguageExtensionsAction extends Action {
this.enabled = galleryService.isEnabled();
}
run(): Thenable<void> {
return this.commandService.executeCommand('workbench.extensions.action.showExtensionsForLanguage', this.fileExtension).then(() => void 0);
run(): Promise<void> {
return this.commandService.executeCommand('workbench.extensions.action.showExtensionsForLanguage', this.fileExtension).then(() => undefined);
}
}
@@ -841,19 +841,19 @@ export class ChangeModeAction extends Action {
constructor(
actionId: string,
actionLabel: string,
@IModeService private modeService: IModeService,
@IModelService private modelService: IModelService,
@IEditorService private editorService: IEditorService,
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
@IQuickInputService private quickInputService: IQuickInputService,
@IPreferencesService private preferencesService: IPreferencesService,
@IInstantiationService private instantiationService: IInstantiationService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService
@IModeService private readonly modeService: IModeService,
@IModelService private readonly modelService: IModelService,
@IEditorService private readonly editorService: IEditorService,
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IPreferencesService private readonly preferencesService: IPreferencesService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService
) {
super(actionId, actionLabel);
}
run(): Thenable<any> {
run(): Promise<any> {
const activeTextEditorWidget = getCodeEditor(this.editorService.activeTextEditorWidget);
if (!activeTextEditorWidget) {
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
@@ -958,6 +958,7 @@ export class ChangeModeAction extends Action {
}
// Change mode for active editor
// {{SQL CARBON EDIT}} - Get activeControl instead of activeEditor
const activeEditor = this.editorService.activeControl;
const activeTextEditorWidget = this.editorService.activeTextEditorWidget;
const models: ITextModel[] = [];
@@ -1012,7 +1013,7 @@ export class ChangeModeAction extends Action {
return <IQuickPickItem>{
id,
label: lang,
description: (id === currentAssociation) ? nls.localize('currentAssociation', "Current Association") : void 0
description: (id === currentAssociation) ? nls.localize('currentAssociation', "Current Association") : undefined
};
});
@@ -1061,13 +1062,13 @@ class ChangeIndentationAction extends Action {
constructor(
actionId: string,
actionLabel: string,
@IEditorService private editorService: IEditorService,
@IQuickInputService private quickInputService: IQuickInputService
@IEditorService private readonly editorService: IEditorService,
@IQuickInputService private readonly quickInputService: IQuickInputService
) {
super(actionId, actionLabel);
}
run(): Thenable<any> {
run(): Promise<any> {
const activeTextEditorWidget = getCodeEditor(this.editorService.activeTextEditorWidget);
if (!activeTextEditorWidget) {
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
@@ -1111,13 +1112,13 @@ export class ChangeEOLAction extends Action {
constructor(
actionId: string,
actionLabel: string,
@IEditorService private editorService: IEditorService,
@IQuickInputService private quickInputService: IQuickInputService
@IEditorService private readonly editorService: IEditorService,
@IQuickInputService private readonly quickInputService: IQuickInputService
) {
super(actionId, actionLabel);
}
run(): Thenable<any> {
run(): Promise<any> {
const activeTextEditorWidget = getCodeEditor(this.editorService.activeTextEditorWidget);
if (!activeTextEditorWidget) {
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
@@ -1156,15 +1157,15 @@ export class ChangeEncodingAction extends Action {
constructor(
actionId: string,
actionLabel: string,
@IEditorService private editorService: IEditorService,
@IQuickInputService private quickInputService: IQuickInputService,
@ITextResourceConfigurationService private textResourceConfigurationService: ITextResourceConfigurationService,
@IFileService private fileService: IFileService
@IEditorService private readonly editorService: IEditorService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@ITextResourceConfigurationService private readonly textResourceConfigurationService: ITextResourceConfigurationService,
@IFileService private readonly fileService: IFileService
) {
super(actionId, actionLabel);
}
run(): Thenable<any> {
run(): Promise<any> {
if (!getCodeEditor(this.editorService.activeTextEditorWidget)) {
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
}
@@ -1196,7 +1197,7 @@ export class ChangeEncodingAction extends Action {
return pickActionPromise.then(action => {
if (!action) {
return void 0;
return undefined;
}
const resource = toResource(activeControl.input, { supportSideBySide: true });

View File

@@ -34,7 +34,7 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget {
private label: string,
keyBindingAction: string,
@IKeybindingService keybindingService: IKeybindingService,
@IThemeService private themeService: IThemeService
@IThemeService private readonly themeService: IThemeService
) {
super();
@@ -106,9 +106,9 @@ export class OpenWorkspaceButtonContribution extends Disposable implements IEdit
constructor(
private editor: ICodeEditor,
@IInstantiationService private instantiationService: IInstantiationService,
@IWindowService private windowService: IWindowService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IWindowService private readonly windowService: IWindowService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService
) {
super();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 266 B

View File

@@ -3,17 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control.hidden {
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control.hidden {
display: none;
}
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.selected .monaco-icon-label,
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.focused .monaco-icon-label {
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.selected .monaco-icon-label,
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.focused .monaco-icon-label {
text-decoration-line: underline;
}
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.selected .hint-more,
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.focused .hint-more {
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.selected .hint-more,
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.focused .hint-more {
text-decoration-line: underline;
}

View File

@@ -5,26 +5,26 @@
/* Container */
.monaco-workbench > .part.editor > .content .editor-group-container {
.monaco-workbench .part.editor > .content .editor-group-container {
height: 100%;
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty {
.monaco-workbench .part.editor > .content .editor-group-container.empty {
opacity: 0.5; /* dimmed to indicate inactive state */
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty.active,
.monaco-workbench > .part.editor > .content .editor-group-container.empty.dragged-over {
.monaco-workbench .part.editor > .content .editor-group-container.empty.active,
.monaco-workbench .part.editor > .content .editor-group-container.empty.dragged-over {
opacity: 1; /* indicate active/dragged-over group through undimmed state */
}
/* Letterpress */
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-letterpress {
.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-letterpress {
display: none; /* only visible when empty */
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .editor-group-letterpress {
.monaco-workbench .part.editor > .content .editor-group-container.empty > .editor-group-letterpress {
display: block;
margin: auto;
width: 100%;
@@ -35,25 +35,25 @@
background-size: 70% 70%;
}
.monaco-workbench > .part.editor > .content.empty .editor-group-container.empty > .editor-group-letterpress {
.monaco-workbench .part.editor > .content.empty .editor-group-container.empty > .editor-group-letterpress {
background-size: 100% 100%; /* larger for empty editor part */
height: 100%; /* no toolbar in this case */
}
/* Title */
.monaco-workbench > .part.editor > .content .editor-group-container > .title {
.monaco-workbench .part.editor > .content .editor-group-container > .title {
position: relative;
box-sizing: border-box;
overflow: hidden;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title:not(.tabs) {
.monaco-workbench .part.editor > .content .editor-group-container > .title:not(.tabs) {
display: flex; /* when tabs are not shown, use flex layout */
flex-wrap: nowrap;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.title-border-bottom::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title.title-border-bottom::after {
content: '';
position: absolute;
bottom: 0;
@@ -65,21 +65,21 @@
height: 1px;
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .title {
.monaco-workbench .part.editor > .content .editor-group-container.empty > .title {
display: none;
}
/* Toolbar */
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar {
.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar {
display: none;
}
.monaco-workbench > .part.editor > .content:not(.empty) .editor-group-container.empty > .editor-group-container-toolbar {
.monaco-workbench .part.editor > .content:not(.empty) .editor-group-container.empty > .editor-group-container-toolbar {
display: block;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar .action-label {
display: block;
height: 35px;
line-height: 35px;
@@ -89,30 +89,26 @@
background-repeat: no-repeat;
}
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
.vs .monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
background-image: url('close-big.svg');
}
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group,
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group,
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
background-image: url('close-big-inverse.svg');
}
/* Editor */
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-container {
height: calc(100% - 35px); /* below title control */
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .editor-container {
.monaco-workbench .part.editor > .content .editor-group-container.empty > .editor-container {
display: none;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-container > .editor-instance {
.monaco-workbench .part.editor > .content .editor-group-container > .editor-container > .editor-instance {
height: 100%;
}
.monaco-workbench > .part.editor > .content .grid-view-container {
.monaco-workbench .part.editor > .content .grid-view-container {
width: 100%;
height: 100%;
}

View File

@@ -22,7 +22,7 @@
cursor: default !important;
}
.monaco-shell .screen-reader-detected-explanation {
.monaco-workbench .screen-reader-detected-explanation {
width: 420px;
top: 30px;
right: 6px;
@@ -30,7 +30,7 @@
cursor: default;
}
.monaco-shell .screen-reader-detected-explanation .cancel {
.monaco-workbench .screen-reader-detected-explanation .cancel {
position: absolute;
top: 0;
right: 0;
@@ -41,27 +41,27 @@
cursor: pointer;
}
.monaco-shell .screen-reader-detected-explanation h2 {
.monaco-workbench .screen-reader-detected-explanation h2 {
margin: 0;
padding: 0;
font-weight: 400;
font-size: 1.8em;
}
.monaco-shell .screen-reader-detected-explanation p {
.monaco-workbench .screen-reader-detected-explanation p {
font-size: 1.2em;
}
.monaco-shell .screen-reader-detected-explanation hr {
.monaco-workbench .screen-reader-detected-explanation hr {
border: 0;
height: 2px;
}
.monaco-shell .screen-reader-detected-explanation .buttons {
.monaco-workbench .screen-reader-detected-explanation .buttons {
display: flex;
}
.monaco-shell .screen-reader-detected-explanation .buttons a {
.monaco-workbench .screen-reader-detected-explanation .buttons a {
font-size: 13px;
padding-left: 12px;
padding-right: 12px;
@@ -69,11 +69,11 @@
max-width: fit-content;
}
.monaco-shell.vs .screen-reader-detected-explanation .cancel {
.vs .monaco-workbench .screen-reader-detected-explanation .cancel {
background: url('close-statusview.svg') center center no-repeat;
}
.monaco-shell.vs-dark .screen-reader-detected-explanation .cancel,
.monaco-shell.hc-black .screen-reader-detected-explanation .cancel {
.vs-dark .monaco-workbench .screen-reader-detected-explanation .cancel,
.hc-black .monaco-workbench .screen-reader-detected-explanation .cancel {
background: url('close-statusview-inverse.svg') center center no-repeat;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 258 B

View File

@@ -5,7 +5,8 @@
/* Title Label */
.monaco-workbench > .part.editor > .content .editor-group-container > .title > .label-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title > .label-container {
height: 35px;
display: flex;
justify-content: flex-start;
align-items: center;
@@ -13,7 +14,7 @@
flex: auto;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label {
line-height: 35px;
overflow: hidden;
text-overflow: ellipsis;
@@ -21,31 +22,31 @@
padding-left: 20px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .no-tabs.title-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .no-tabs.title-label {
flex: none;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .monaco-icon-label::before {
.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before {
height: 35px; /* tweak the icon size of the editor labels when icons are enabled */
}
/* Breadcrumbs */
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control {
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control {
flex: 1 50%;
overflow: hidden;
margin-left: .45em;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item {
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item {
font-size: 0.9em;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.preview .monaco-breadcrumb-item {
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.preview .monaco-breadcrumb-item {
font-style: italic;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
content: '/';
opacity: 1;
height: inherit;
@@ -54,35 +55,36 @@
}
/* {{SQL CARBON EDIT}} */
.monaco-workbench.windows > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
.windows > .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
content: '/';
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::before,
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder + .monaco-breadcrumb-item::before,
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.relative-path .monaco-breadcrumb-item:nth-child(2)::before {
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::before,
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder + .monaco-breadcrumb-item::before,
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.relative-path .monaco-breadcrumb-item:nth-child(2)::before,
.windows > .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:nth-child(2)::before {
/* workspace folder, item following workspace folder, or relative path -> hide first seperator */
display: none;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::after {
/* use dot separator for workspace folder */
content: '\00a0•\00a0';
padding: 0px;
padding: 0;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child {
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child {
padding-right: 4px; /* does not have trailing separator*/
}
/* Title Actions */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-actions {
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions {
display: flex;
flex: initial;
opacity: 0.5;
height: 35px;
}
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .title-actions {
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .title-actions {
opacity: 1;
}

View File

@@ -5,37 +5,37 @@
/* Title Container */
.monaco-workbench > .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container {
display: flex;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element {
.monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element {
flex: 1;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element .scrollbar {
.monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element .scrollbar {
z-index: 3; /* on top of tabs */
cursor: default;
}
/* Tabs Container */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container {
display: flex;
height: 35px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container.scroll {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.scroll {
overflow: scroll !important;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container::-webkit-scrollbar {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container::-webkit-scrollbar {
display: none;
}
/* Tab */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab {
position: relative;
display: flex;
white-space: nowrap;
@@ -45,45 +45,45 @@
padding-left: 10px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-right,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-off {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-off {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab close button is not left */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
width: 120px;
min-width: fit-content;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink {
min-width: 60px;
flex-basis: 0; /* all tabs are even */
flex-grow: 1; /* all tabs grow even */
max-width: fit-content;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left::after,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off::after {
content: '';
display: flex;
flex: 0;
width: 5px; /* Reserve space to hide tab fade when close button is left or off (fixes https://github.com/Microsoft/vscode/issues/45728) */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left {
min-width: 80px; /* make more room for close button when it shows to the left */
padding-right: 5px; /* we need less room when sizing is shrink */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged {
will-change: transform; /* forces tab to be drawn on a separate layer (fixes https://github.com/Microsoft/vscode/issues/18733) */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged-over div {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged-over div {
pointer-events: none; /* prevents cursor flickering (fixes https://github.com/Microsoft/vscode/issues/38753) */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left {
flex-direction: row-reverse;
padding-left: 0;
padding-right: 10px;
@@ -91,14 +91,14 @@
/* Tab border top/bottom */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-border-top-container,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-border-bottom-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-border-top-container,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-border-bottom-container {
display: none; /* hidden by default until a color is provided (see below) */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container {
display: block;
position: absolute;
left: 0;
@@ -107,19 +107,19 @@
width: 100%;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container {
top: 0;
height: 1px;
background-color: var(--tab-border-top-color);
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container {
bottom: 0;
height: 1px;
background-color: var(--tab-border-bottom-color);
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container {
top: 0;
height: 2px;
background-color: var(--tab-dirty-border-top-color);
@@ -127,16 +127,16 @@
/* Tab Label */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
margin-top: auto;
margin-bottom: auto;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink .tab-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink .tab-label {
position: relative;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .tab-label::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .tab-label::after {
content: '';
position: absolute;
right: 0;
@@ -146,66 +146,66 @@
padding: 0;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:focus > .tab-label::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:focus > .tab-label::after {
opacity: 0; /* when tab has the focus this shade breaks the tab border (fixes https://github.com/Microsoft/vscode/issues/57819) */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label > .monaco-icon-label-description-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label > .monaco-icon-label-description-container {
overflow: visible; /* fixes https://github.com/Microsoft/vscode/issues/20182 */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-description-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-description-container {
text-overflow: clip;
}
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-description-container {
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-description-container {
text-overflow: ellipsis;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before {
height: 16px; /* tweak the icon size of the editor labels when icons are enabled */
}
/* Tab Close */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close {
margin-top: auto;
margin-bottom: auto;
width: 28px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close {
flex: 0;
overflow: hidden; /* let the close button be pushed out of view when sizing is set to shrink to make more room... */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.close-button-right.sizing-shrink > .tab-close,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink:hover > .tab-close,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close:focus-within {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.close-button-right.sizing-shrink > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink:hover > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close:focus-within {
overflow: visible; /* ...but still show the close button on hover, focus and when dirty */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off > .tab-close {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off > .tab-close {
display: none; /* hide the close action bar when we are configured to hide it */
}
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label:focus, /* always show it on focus */
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-close .action-label, /* always show it on hover */
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label { /* always show it for dirty tabs */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label:focus, /* always show it on focus */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-close .action-label, /* always show it on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label { /* always show it for dirty tabs */
opacity: 1;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label { /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label { /* show dimmed for inactive group */
opacity: 0.5;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close .action-label {
opacity: 0;
display: block;
height: 16px;
@@ -216,53 +216,53 @@
margin-right: 0.5em;
}
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action {
.vs .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action {
background: url('close-dirty.svg') center center no-repeat;
}
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action,
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action {
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action,
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action {
background: url('close-dirty-inverse.svg') center center no-repeat;
}
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover {
.vs .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover {
background: url('close.svg') center center no-repeat;
}
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover,
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover {
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover,
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover {
background: url('close-inverse.svg') center center no-repeat;
}
/* No Tab Close Button */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off {
padding-right: 10px; /* give a little bit more room if close button is off */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off {
padding-right: 5px; /* we need less room when sizing is shrink */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top) {
background-repeat: no-repeat;
background-position-y: center;
background-position-x: calc(100% - 6px); /* to the right of the tab label */
padding-right: 28px; /* make room for dirty indication when we are running without close button */
}
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty {
.vs .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top) {
background-image: url('close-dirty.svg');
}
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty,
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty {
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top),
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty {
background-image: url('close-dirty-inverse.svg');
}
/* Editor Actions */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .editor-actions {
.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions {
cursor: default;
flex: initial;
padding-left: 4px;
@@ -271,30 +271,30 @@
/* Breadcrumbs */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control {
flex: 1 100%;
height: 22px;
cursor: default;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-icon-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-icon-label {
height: 22px;
line-height: 22px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-icon-label::before {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-icon-label::before {
height: 22px; /* tweak the icon size of the editor labels when icons are enabled */
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item {
max-width: 80%;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
min-width: 16px;
height: 22px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child {
padding-right: 8px;
}

View File

@@ -5,31 +5,31 @@
/* Editor Label */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
white-space: nowrap;
flex: 1;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label a,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a {
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label a,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a {
text-decoration: none;
font-size: 13px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .monaco-icon-label::before,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label a,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label h2,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label span {
.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before,
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label a,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a,
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label h2,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label span {
cursor: pointer;
}
/* Title Actions */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-actions .action-label,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .editor-actions .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions .action-label {
display: block;
height: 35px;
line-height: 35px;
@@ -39,29 +39,29 @@
background-repeat: no-repeat;
}
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .title-actions .action-label,
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .editor-actions .action-label {
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions .action-label,
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions .action-label {
line-height: initial;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .editor-actions .action-label .label,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-actions .action-label .label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions .action-label .label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions .action-label .label {
display: none;
}
/* Drag Cursor */
.monaco-workbench > .part.editor > .content .editor-group-container > .title {
.monaco-workbench .part.editor > .content .editor-group-container > .title {
cursor: -webkit-grab;
}
/* Actions */
.monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action {
.monaco-workbench .part.editor > .content .editor-group-container > .title .close-editor-action {
background: url('close.svg') center center no-repeat;
}
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action,
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action {
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .title .close-editor-action,
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .close-editor-action {
background: url('close-inverse.svg') center center no-repeat;
}

View File

@@ -6,7 +6,7 @@
import 'vs/css!./media/notabstitlecontrol';
import { toResource, Verbosity, IEditorInput } from 'vs/workbench/common/editor';
import { TitleControl, IToolbarActions } from 'vs/workbench/browser/parts/editor/titleControl';
import { ResourceLabel } from 'vs/workbench/browser/labels';
import { ResourceLabel, IResourceLabel } from 'vs/workbench/browser/labels';
import { TAB_ACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND } from 'vs/workbench/common/theme';
import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch';
import { addDisposableListener, EventType, addClass, EventHelper, removeClass, toggleClass } from 'vs/base/browser/dom';
@@ -22,7 +22,7 @@ interface IRenderedEditorLabel {
export class NoTabsTitleControl extends TitleControl {
private titleContainer: HTMLElement;
private editorLabel: ResourceLabel;
private editorLabel: IResourceLabel;
private activeLabel: IRenderedEditorLabel = Object.create(null);
protected create(parent: HTMLElement): void {
@@ -40,8 +40,8 @@ export class NoTabsTitleControl extends TitleControl {
this.titleContainer.appendChild(labelContainer);
// Editor Label
this.editorLabel = this._register(this.instantiationService.createInstance(ResourceLabel, labelContainer, void 0));
this._register(this.editorLabel.onClick(e => this.onTitleLabelClick(e)));
this.editorLabel = this._register(this.instantiationService.createInstance(ResourceLabel, labelContainer, undefined)).element;
this._register(addDisposableListener(this.editorLabel.element, EventType.CLICK, e => this.onTitleLabelClick(e)));
// Breadcrumbs
this.createBreadcrumbsControl(labelContainer, { showFileIcons: false, showSymbolIcons: true, showDecorationColors: false, breadcrumbsBackground: () => Color.transparent });
@@ -244,7 +244,7 @@ export class NoTabsTitleControl extends TitleControl {
title = ''; // dont repeat what is already shown
}
this.editorLabel.setLabel({ name, description, resource }, { title, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] });
this.editorLabel.setResource({ name, description, resource }, { title, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] });
if (isGroupActive) {
this.editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND);
} else {

View File

@@ -28,7 +28,7 @@ export class RangeHighlightDecorations extends Disposable {
private readonly _onHighlightRemoved: Emitter<void> = this._register(new Emitter<void>());
get onHighlghtRemoved(): Event<void> { return this._onHighlightRemoved.event; }
constructor(@IEditorService private editorService: IEditorService) {
constructor(@IEditorService private readonly editorService: IEditorService) {
super();
}
@@ -58,7 +58,7 @@ export class RangeHighlightDecorations extends Disposable {
this.setEditor(editor);
}
private getEditor(resourceRange: IRangeHighlightDecoration): ICodeEditor {
private getEditor(resourceRange: IRangeHighlightDecoration): ICodeEditor | undefined {
const activeEditor = this.editorService.activeEditor;
const resource = activeEditor && activeEditor.getResource();
if (resource) {
@@ -67,7 +67,7 @@ export class RangeHighlightDecorations extends Disposable {
}
}
return null;
return undefined;
}
private setEditor(editor: ICodeEditor) {

View File

@@ -13,12 +13,10 @@ 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, StatusbarItemDescriptor, IStatusbarRegistry, Extensions } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IDisposable, Disposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { Registry } from 'vs/platform/registry/common/platform';
import { Action } from 'vs/base/common/actions';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { memoize } from 'vs/base/common/decorators';
@@ -234,7 +232,7 @@ class FileSeemsBinaryFileView {
type Scale = number | 'fit';
class ZoomStatusbarItem extends Themable implements IStatusbarItem {
export class ZoomStatusbarItem extends Themable implements IStatusbarItem {
static instance: ZoomStatusbarItem;
@@ -244,7 +242,7 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
private onSelectScale?: (scale: Scale) => void;
constructor(
@IContextMenuService private contextMenuService: IContextMenuService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IEditorService editorService: IEditorService,
@IThemeService themeService: IThemeService
) {
@@ -257,7 +255,7 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
private onActiveEditorChanged(): void {
this.hide();
this.onSelectScale = void 0;
this.onSelectScale = undefined;
}
show(scale: Scale, onSelectScale: (scale: number) => void) {
@@ -298,12 +296,12 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
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), void 0, void 0, () => {
new Action(`zoom.${scale}`, ZoomStatusbarItem.zoomLabel(scale), undefined, undefined, () => {
if (this.onSelectScale) {
this.onSelectScale(scale);
}
return void 0;
return Promise.resolve(undefined);
}));
}
@@ -314,10 +312,6 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
}
}
Registry.as<IStatusbarRegistry>(Extensions.Statusbar).registerStatusbarItem(
new StatusbarItemDescriptor(ZoomStatusbarItem, StatusbarAlignment.RIGHT, 101 /* to the left of editor status (100) */)
);
interface ImageState {
scale: Scale;
offsetX: number;
@@ -394,7 +388,7 @@ class InlineImageView {
DOM.removeClass(image, 'pixelated');
image.style.minWidth = 'auto';
image.style.width = 'auto';
InlineImageView.imageStateCache.set(cacheKey, null);
InlineImageView.imageStateCache.delete(cacheKey);
} else {
const oldWidth = image.width;
const oldHeight = image.height;
@@ -432,6 +426,10 @@ class InlineImageView {
}
function firstZoom() {
if (!image) {
return;
}
scale = image.clientWidth / image.naturalWidth;
updateScale(scale);
}
@@ -537,10 +535,13 @@ class InlineImageView {
DOM.clearNode(container);
DOM.addClasses(container, 'image', 'zoom-in');
image = DOM.append(container, DOM.$('img.scale-to-fit'));
image = DOM.append(container, DOM.$<HTMLImageElement>('img.scale-to-fit'));
image.style.visibility = 'hidden';
disposables.push(DOM.addDisposableListener(image, DOM.EventType.LOAD, e => {
if (!image) {
return;
}
if (typeof descriptor.size === 'number') {
metadataClb(nls.localize('imgMeta', '{0}x{1} {2}', image.naturalWidth, image.naturalHeight, BinarySize.formatSize(descriptor.size)));
} else {
@@ -568,7 +569,7 @@ class InlineImageView {
return context;
}
private static imageSrc(descriptor: IResourceDescriptor, fileService: IFileService): Thenable<string> {
private static imageSrc(descriptor: IResourceDescriptor, fileService: IFileService): Promise<string> {
if (descriptor.resource.scheme === Schemas.data) {
return Promise.resolve(descriptor.resource.toString(true /* skip encoding */));
}
@@ -582,7 +583,7 @@ class InlineImageView {
}
function getMime(descriptor: IResourceDescriptor) {
let mime = descriptor.mime;
let mime: string | undefined = descriptor.mime;
if (!mime && descriptor.resource.scheme !== Schemas.data) {
mime = mimes.getMediaMime(descriptor.resource.path);
}

View File

@@ -15,7 +15,7 @@ import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/br
import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
import { SplitView, Sizing, Orientation } from 'vs/base/browser/ui/splitview/splitview';
import { Event, Relay, anyEvent, mapEvent, Emitter } from 'vs/base/common/event';
import { Event, Relay, Emitter } from 'vs/base/common/event';
import { IStorageService } from 'vs/platform/storage/common/storage';
export class SideBySideEditor extends BaseEditor {
@@ -43,8 +43,8 @@ export class SideBySideEditor extends BaseEditor {
get minimumHeight() { return this.minimumMasterHeight + this.minimumDetailsHeight; }
get maximumHeight() { return this.maximumMasterHeight + this.maximumDetailsHeight; }
protected masterEditor: BaseEditor;
protected detailsEditor: BaseEditor;
protected masterEditor?: BaseEditor;
protected detailsEditor?: BaseEditor;
private masterEditorContainer: HTMLElement;
private detailsEditorContainer: HTMLElement;
@@ -52,13 +52,13 @@ export class SideBySideEditor extends BaseEditor {
private splitview: SplitView;
private dimension: DOM.Dimension = new DOM.Dimension(0, 0);
private onDidCreateEditors = this._register(new Emitter<{ width: number; height: number; }>());
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; }>());
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }> = anyEvent(this.onDidCreateEditors.event, this._onDidSizeConstraintsChange.event);
private onDidCreateEditors = this._register(new Emitter<{ width: number; height: number; } | undefined>());
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; } | undefined>());
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; } | undefined> = Event.any(this.onDidCreateEditors.event, this._onDidSizeConstraintsChange.event);
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IInstantiationService private instantiationService: IInstantiationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IStorageService storageService: IStorageService
) {
@@ -92,7 +92,7 @@ export class SideBySideEditor extends BaseEditor {
this.updateStyles();
}
setInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
setInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
const oldInput = <SideBySideEditorInput>this.input;
return super.setInput(newInput, options, token)
.then(() => this.updateInput(oldInput, newInput, options, token));
@@ -141,7 +141,7 @@ export class SideBySideEditor extends BaseEditor {
this.splitview.layout(dimension.width);
}
getControl(): IEditorControl {
getControl(): IEditorControl | null {
if (this.masterEditor) {
return this.masterEditor.getControl();
}
@@ -149,15 +149,15 @@ export class SideBySideEditor extends BaseEditor {
return null;
}
getMasterEditor(): IEditor {
getMasterEditor(): IEditor | undefined {
return this.masterEditor;
}
getDetailsEditor(): IEditor {
getDetailsEditor(): IEditor | undefined {
return this.detailsEditor;
}
private updateInput(oldInput: SideBySideEditorInput, newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
private updateInput(oldInput: SideBySideEditorInput, newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
if (!newInput.matches(oldInput)) {
if (oldInput) {
this.disposeEditors();
@@ -165,22 +165,28 @@ export class SideBySideEditor extends BaseEditor {
return this.setNewInput(newInput, options, token);
}
if (!this.detailsEditor || !this.masterEditor) {
return Promise.resolve();
}
return Promise.all([
this.detailsEditor.setInput(newInput.details, null, token),
this.masterEditor.setInput(newInput.master, options, token)]
).then(() => void 0);
).then(() => undefined);
}
private setNewInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
const detailsEditor = this._createEditor(<EditorInput>newInput.details, this.detailsEditorContainer);
const masterEditor = this._createEditor(<EditorInput>newInput.master, this.masterEditorContainer);
private setNewInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
const detailsEditor = this.doCreateEditor(<EditorInput>newInput.details, this.detailsEditorContainer);
const masterEditor = this.doCreateEditor(<EditorInput>newInput.master, this.masterEditorContainer);
return this.onEditorsCreated(detailsEditor, masterEditor, newInput.details, newInput.master, options, token);
}
private _createEditor(editorInput: EditorInput, container: HTMLElement): BaseEditor {
private doCreateEditor(editorInput: EditorInput, container: HTMLElement): BaseEditor {
const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editorInput);
if (!descriptor) {
throw new Error('No descriptor for editor found');
}
const editor = descriptor.instantiate(this.instantiationService);
editor.create(container);
@@ -193,12 +199,12 @@ export class SideBySideEditor extends BaseEditor {
this.detailsEditor = details;
this.masterEditor = master;
this._onDidSizeConstraintsChange.input = anyEvent(
mapEvent(details.onDidSizeConstraintsChange, () => undefined),
mapEvent(master.onDidSizeConstraintsChange, () => undefined)
this._onDidSizeConstraintsChange.input = Event.any(
Event.map(details.onDidSizeConstraintsChange, () => undefined),
Event.map(master.onDidSizeConstraintsChange, () => undefined)
);
this.onDidCreateEditors.fire();
this.onDidCreateEditors.fire(undefined);
return Promise.all([this.detailsEditor.setInput(detailsInput, null, token), this.masterEditor.setInput(masterInput, options, token)]).then(() => this.focus());
}
@@ -214,12 +220,12 @@ export class SideBySideEditor extends BaseEditor {
private disposeEditors(): void {
if (this.detailsEditor) {
this.detailsEditor.dispose();
this.detailsEditor = null;
this.detailsEditor = undefined;
}
if (this.masterEditor) {
this.masterEditor.dispose();
this.masterEditor = null;
this.masterEditor = undefined;
}
this.detailsEditorContainer.innerHTML = '';

View File

@@ -10,7 +10,7 @@ import { toResource, GroupIdentifier, IEditorInput, Verbosity, EditorCommandsCon
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch';
import { KeyCode } from 'vs/base/common/keyCodes';
import { ResourceLabel } from 'vs/workbench/browser/labels';
import { ResourceLabels, IResourceLabel, DEFAULT_LABELS_CONTAINER } from 'vs/workbench/browser/labels';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -69,7 +69,7 @@ export class TabsTitleControl extends TitleControl {
private tabsScrollbar: ScrollableElement;
private closeOneEditorAction: CloseOneEditorAction;
private tabLabelWidgets: ResourceLabel[] = [];
private tabResourceLabels: ResourceLabels;
private tabLabels: IEditorInputLabel[] = [];
private tabDisposeables: IDisposable[] = [];
@@ -83,7 +83,7 @@ export class TabsTitleControl extends TitleControl {
group: IEditorGroupView,
@IContextMenuService contextMenuService: IContextMenuService,
@IInstantiationService instantiationService: IInstantiationService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
@IContextKeyService contextKeyService: IContextKeyService,
@IKeybindingService keybindingService: IKeybindingService,
@ITelemetryService telemetryService: ITelemetryService,
@@ -142,6 +142,9 @@ export class TabsTitleControl extends TitleControl {
addClass(breadcrumbsContainer, 'tabs-breadcrumbs');
this.titleContainer.appendChild(breadcrumbsContainer);
this.createBreadcrumbsControl(breadcrumbsContainer, { showFileIcons: true, showSymbolIcons: true, showDecorationColors: false, breadcrumbsBackground: breadcrumbsBackground });
// Tab Labels
this.tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER));
}
private createTabsScrollbar(scrollable: HTMLElement): ScrollableElement {
@@ -314,7 +317,6 @@ export class TabsTitleControl extends TitleControl {
(this.tabsContainer.lastChild as HTMLElement).remove();
// Remove associated tab label and widget
this.tabLabelWidgets.pop();
this.tabDisposeables.pop().dispose();
}
@@ -330,7 +332,7 @@ export class TabsTitleControl extends TitleControl {
clearNode(this.tabsContainer);
this.tabDisposeables = dispose(this.tabDisposeables);
this.tabLabelWidgets = [];
this.tabResourceLabels.clear();
this.tabLabels = [];
this.clearEditorActionsToolbar();
@@ -414,12 +416,12 @@ export class TabsTitleControl extends TitleControl {
this.redraw();
}
private withTab(editor: IEditorInput, fn: (tabContainer: HTMLElement, tabLabelWidget: ResourceLabel, tabLabel: IEditorInputLabel) => void): void {
private withTab(editor: IEditorInput, fn: (tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
const editorIndex = this.group.getIndexOfEditor(editor);
const tabContainer = this.tabsContainer.children[editorIndex] as HTMLElement;
if (tabContainer) {
fn(tabContainer, this.tabLabelWidgets[editorIndex], this.tabLabels[editorIndex]);
fn(tabContainer, this.tabResourceLabels.get(editorIndex), this.tabLabels[editorIndex]);
}
}
@@ -441,8 +443,7 @@ export class TabsTitleControl extends TitleControl {
tabContainer.appendChild(tabBorderTopContainer);
// Tab Editor Label
const editorLabel = this.instantiationService.createInstance(ResourceLabel, tabContainer, void 0);
this.tabLabelWidgets.push(editorLabel);
const editorLabel = this.tabResourceLabels.create(tabContainer);
// Tab Close Button
const tabCloseContainer = document.createElement('div');
@@ -479,7 +480,7 @@ export class TabsTitleControl extends TitleControl {
e.preventDefault(); // required to prevent auto-scrolling (https://github.com/Microsoft/vscode/issues/16690)
}
return void 0; // only for left mouse click
return undefined; // only for left mouse click
}
if (this.originatesFromTabActionBar(e)) {
@@ -489,7 +490,7 @@ export class TabsTitleControl extends TitleControl {
// Open tabs editor
this.group.openEditor(this.group.getEditor(index));
return void 0;
return undefined;
};
const showContextMenu = (e: Event) => {
@@ -836,16 +837,16 @@ export class TabsTitleControl extends TitleControl {
this.layout(this.dimension);
}
private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel, tabLabel: IEditorInputLabel) => void): void {
private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
this.group.editors.forEach((editor, index) => {
const tabContainer = this.tabsContainer.children[index] as HTMLElement;
if (tabContainer) {
fn(editor, index, tabContainer, this.tabLabelWidgets[index], this.tabLabels[index]);
fn(editor, index, tabContainer, this.tabResourceLabels.get(index), this.tabLabels[index]);
}
});
}
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel, tabLabel: IEditorInputLabel): void {
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
// Label
this.redrawLabel(editor, tabContainer, tabLabelWidget, tabLabel);
@@ -880,7 +881,7 @@ export class TabsTitleControl extends TitleControl {
this.setEditorTabColor(editor, tabContainer, this.group.isActive(editor));
}
private redrawLabel(editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel, tabLabel: IEditorInputLabel): void {
private redrawLabel(editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
const name = tabLabel.name;
const description = tabLabel.description || '';
const title = tabLabel.title || '';
@@ -890,14 +891,14 @@ export class TabsTitleControl extends TitleControl {
tabContainer.title = title;
// Label
tabLabelWidget.setLabel({ name, description, resource: toResource(editor, { supportSideBySide: true }) }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) });
tabLabelWidget.setResource({ name, description, resource: toResource(editor, { supportSideBySide: true }) }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) });
// {{SQL CARBON EDIT}} -- Display the editor's tab color
const isTabActive = this.group.isActive(editor);
this.setEditorTabColor(editor, tabContainer, isTabActive);
}
private redrawEditorActiveAndDirty(isGroupActive: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel): void {
private redrawEditorActiveAndDirty(isGroupActive: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel): void {
const isTabActive = this.group.isActive(editor);
const hasModifiedBorderTop = this.doRedrawEditorDirty(isGroupActive, isTabActive, editor, tabContainer);
@@ -905,7 +906,7 @@ export class TabsTitleControl extends TitleControl {
this.doRedrawEditorActive(isGroupActive, !hasModifiedBorderTop, editor, tabContainer, tabLabelWidget);
}
private doRedrawEditorActive(isGroupActive: boolean, allowBorderTop: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel): void {
private doRedrawEditorActive(isGroupActive: boolean, allowBorderTop: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel): void {
// Tab is active
if (this.group.isActive(editor)) {
@@ -924,7 +925,7 @@ export class TabsTitleControl extends TitleControl {
tabContainer.style.removeProperty('--tab-border-bottom-color');
}
const activeTabBorderColorTop = allowBorderTop ? this.getColor(isGroupActive ? TAB_ACTIVE_BORDER_TOP : TAB_UNFOCUSED_ACTIVE_BORDER_TOP) : void 0;
const activeTabBorderColorTop = allowBorderTop ? this.getColor(isGroupActive ? TAB_ACTIVE_BORDER_TOP : TAB_UNFOCUSED_ACTIVE_BORDER_TOP) : undefined;
if (activeTabBorderColorTop) {
addClass(tabContainer, 'tab-border-top');
tabContainer.style.setProperty('--tab-border-top-color', activeTabBorderColorTop.toString());
@@ -1008,7 +1009,7 @@ export class TabsTitleControl extends TitleControl {
if (!this.layoutScheduled) {
this.layoutScheduled = scheduleAtNextAnimationFrame(() => {
this.doLayout(this.dimension);
this.layoutScheduled = void 0;
this.layoutScheduled = undefined;
});
}
}
@@ -1073,7 +1074,7 @@ export class TabsTitleControl extends TitleControl {
return this.tabsContainer.children[editorIndex] as HTMLElement;
}
return void 0;
return undefined;
}
private blockRevealActiveTabOnce(): void {
@@ -1094,7 +1095,7 @@ export class TabsTitleControl extends TitleControl {
element = (e as GestureEvent).initialTarget as HTMLElement;
}
return !!findParentWithClass(element, 'monaco-action-bar', 'tab');
return !!findParentWithClass(element, 'action-item', 'tab');
}
private onDrop(e: DragEvent, targetIndex: number): void {
@@ -1185,21 +1186,21 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const activeContrastBorderColor = theme.getColor(activeContrastBorder);
if (activeContrastBorderColor) {
collector.addRule(`
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover {
outline: 1px solid;
outline-offset: -5px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
outline: 1px dashed;
outline-offset: -5px;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label,
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label {
opacity: 1 !important;
}
`);
@@ -1209,7 +1210,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabHoverBackground = theme.getColor(TAB_HOVER_BACKGROUND);
if (tabHoverBackground) {
collector.addRule(`
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover {
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover {
background-color: ${tabHoverBackground} !important;
}
`);
@@ -1218,7 +1219,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabUnfocusedHoverBackground = theme.getColor(TAB_UNFOCUSED_HOVER_BACKGROUND);
if (tabUnfocusedHoverBackground) {
collector.addRule(`
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
background-color: ${tabUnfocusedHoverBackground} !important;
}
`);
@@ -1228,7 +1229,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabHoverBorder = theme.getColor(TAB_HOVER_BORDER);
if (tabHoverBorder) {
collector.addRule(`
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover {
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover {
box-shadow: ${tabHoverBorder} 0 -1px inset !important;
}
`);
@@ -1237,7 +1238,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabUnfocusedHoverBorder = theme.getColor(TAB_UNFOCUSED_HOVER_BORDER);
if (tabUnfocusedHoverBorder) {
collector.addRule(`
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
box-shadow: ${tabUnfocusedHoverBorder} 0 -1px inset !important;
}
`);
@@ -1265,12 +1266,12 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const adjustedColor = tabHoverBackground.flatten(adjustedTabBackground);
const adjustedColorDrag = tabHoverBackground.flatten(adjustedTabDragBackground);
collector.addRule(`
.monaco-workbench > .part.editor > .content:not(.dragged-over) .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
background: linear-gradient(to left, ${adjustedColor}, transparent) !important;
}
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
}
`);
@@ -1281,11 +1282,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const adjustedColor = tabUnfocusedHoverBackground.flatten(adjustedTabBackground);
const adjustedColorDrag = tabUnfocusedHoverBackground.flatten(adjustedTabDragBackground);
collector.addRule(`
.monaco-workbench > .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
background: linear-gradient(to left, ${adjustedColor}, transparent) !important;
}
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
}
`);
@@ -1295,8 +1296,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
if (editorDragAndDropBackground && adjustedTabDragBackground) {
const adjustedColorDrag = editorDragAndDropBackground.flatten(adjustedTabDragBackground);
collector.addRule(`
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged) > .tab-label::after,
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged) > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged) > .tab-label::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged) > .tab-label::after {
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
}
`);
@@ -1308,11 +1309,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const adjustedColor = tabActiveBackground.flatten(adjustedTabBackground);
const adjustedColorDrag = tabActiveBackground.flatten(adjustedTabDragBackground);
collector.addRule(`
.monaco-workbench > .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink.active:not(.dragged) > .tab-label::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink.active:not(.dragged) > .tab-label::after {
background: linear-gradient(to left, ${adjustedColor}, transparent);
}
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink.active:not(.dragged) > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink.active:not(.dragged) > .tab-label::after {
background: linear-gradient(to left, ${adjustedColorDrag}, transparent);
}
`);
@@ -1324,11 +1325,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const adjustedColor = tabInactiveBackground.flatten(adjustedTabBackground);
const adjustedColorDrag = tabInactiveBackground.flatten(adjustedTabDragBackground);
collector.addRule(`
.monaco-workbench > .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged) > .tab-label::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged) > .tab-label::after {
background: linear-gradient(to left, ${adjustedColor}, transparent);
}
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged) > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged) > .tab-label::after {
background: linear-gradient(to left, ${adjustedColorDrag}, transparent);
}
`);

View File

@@ -26,7 +26,7 @@ import { ScrollType, IDiffEditorViewState, IDiffEditorModel } from 'vs/editor/co
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { URI } from 'vs/base/common/uri';
import { once } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { CancellationToken } from 'vs/base/common/cancellation';
@@ -73,7 +73,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration);
}
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
// Dispose previous diff navigator
this.diffNavigatorDisposables = dispose(this.diffNavigatorDisposables);
@@ -87,12 +87,12 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
// Check for cancellation
if (token.isCancellationRequested) {
return void 0;
return undefined;
}
// Assert Model Instance
if (!(resolvedModel instanceof TextDiffEditorModel) && this.openAsBinary(input, options)) {
return void 0;
return undefined;
}
// Set Editor Model
@@ -282,7 +282,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
super.saveTextEditorViewState(resource);
// Make sure to clean up when the input gets disposed
once(input.onDispose)(() => {
Event.once(input.onDispose)(() => {
super.clearTextEditorViewState([resource]);
});
}

View File

@@ -40,7 +40,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
private editorControl: IEditor;
private _editorContainer: HTMLElement;
private hasPendingConfigurationChange: boolean;
private lastAppliedEditorOptions: IEditorOptions;
private lastAppliedEditorOptions?: IEditorOptions;
private editorMemento: IEditorMemento<IEditorViewState>;
constructor(
@@ -53,13 +53,17 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
@ITextFileService private readonly _textFileService: ITextFileService,
@IEditorService protected editorService: IEditorService,
@IEditorGroupsService protected editorGroupService: IEditorGroupsService,
@IWindowService private windowService: IWindowService
@IWindowService private readonly windowService: IWindowService
) {
super(id, telemetryService, themeService, storageService);
this.editorMemento = this.getEditorMemento<IEditorViewState>(editorGroupService, TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY, 100);
this._register(this.configurationService.onDidChangeConfiguration(e => this.handleConfigurationChangeEvent(this.configurationService.getValue<IEditorConfiguration>(this.getResource()))));
this._register(this.configurationService.onDidChangeConfiguration(e => {
const resource = this.getResource();
const value = resource ? this.configurationService.getValue<IEditorConfiguration>(resource) : undefined;
return this.handleConfigurationChangeEvent(value);
}));
}
protected get instantiationService(): IInstantiationService {
@@ -129,7 +133,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
// Editor for Text
this._editorContainer = parent;
this.editorControl = this._register(this.createEditorControl(parent, this.computeConfiguration(this.configurationService.getValue<IEditorConfiguration>(this.getResource()))));
this.editorControl = this._register(this.createEditorControl(parent, this.computeConfiguration(this.configurationService.getValue<IEditorConfiguration>(this.getResource()!))));
// Model & Language changes
const codeEditor = getCodeEditor(this.editorControl);
@@ -170,7 +174,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
(reason === SaveReason.FOCUS_CHANGE && mode === AutoSaveMode.ON_FOCUS_CHANGE)
) {
if (this.textFileService.isDirty()) {
this.textFileService.saveAll(void 0, { reason });
this.textFileService.saveAll(undefined, { reason });
}
}
}
@@ -187,7 +191,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
return this.instantiationService.createInstance(CodeEditorWidget, parent, configuration, {});
}
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
return super.setInput(input, options, token).then(() => {
// Update editor options after having set the input. We do this because there can be
@@ -229,14 +233,14 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
*/
protected saveTextEditorViewState(resource: URI): void {
const editorViewState = this.retrieveTextEditorViewState(resource);
if (!editorViewState) {
if (!editorViewState || !this.group) {
return;
}
this.editorMemento.saveEditorState(this.group, resource, editorViewState);
}
protected retrieveTextEditorViewState(resource: URI): IEditorViewState {
protected retrieveTextEditorViewState(resource: URI): IEditorViewState | null {
const control = this.getControl() as ICodeEditor;
const model = control.getModel();
if (!model) {
@@ -267,12 +271,18 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
/**
* Loads the text editor view state for the given resource and returns it.
*/
protected loadTextEditorViewState(resource: URI): IEditorViewState {
return this.editorMemento.loadEditorState(this.group, resource);
protected loadTextEditorViewState(resource: URI): IEditorViewState | undefined {
return this.group ? this.editorMemento.loadEditorState(this.group, resource) : undefined;
}
private updateEditorConfiguration(configuration = this.configurationService.getValue<IEditorConfiguration>(this.getResource())): void {
if (!this.editorControl) {
private updateEditorConfiguration(configuration?: IEditorConfiguration): void {
if (!configuration) {
const resource = this.getResource();
if (resource) {
configuration = this.configurationService.getValue<IEditorConfiguration>(resource);
}
}
if (!this.editorControl || !configuration) {
return;
}
@@ -292,7 +302,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
}
}
protected getResource(): URI {
protected getResource(): URI | null {
const codeEditor = getCodeEditor(this.editorControl);
if (codeEditor) {
const model = codeEditor.getModel();
@@ -311,7 +321,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
protected abstract getAriaLabel(): string;
dispose(): void {
this.lastAppliedEditorOptions = void 0;
this.lastAppliedEditorOptions = undefined;
super.dispose();
}

View File

@@ -18,7 +18,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { once } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
import { ScrollType } from 'vs/editor/common/editorCommon';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { CancellationToken } from 'vs/base/common/cancellation';
@@ -54,7 +54,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
return nls.localize('textEditor', "Text Editor");
}
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
// Remember view settings if input changes
this.saveTextResourceEditorViewState(this.input);
@@ -65,7 +65,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
// Check for cancellation
if (token.isCancellationRequested) {
return void 0;
return undefined;
}
// Assert Model instance
@@ -90,7 +90,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
this.restoreTextResourceEditorViewState(input);
}
return void 0;
return undefined;
});
});
}
@@ -136,19 +136,14 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
/**
* Reveals the last line of this editor if it has a model set.
* When smart is true only scroll if the cursor is currently on the last line of the output panel.
* This allows users to click on the output panel to stop scrolling when they see something of interest.
* To resume, they should scroll to the end of the output panel again.
*/
revealLastLine(smart: boolean): void {
revealLastLine(): void {
const codeEditor = <ICodeEditor>this.getControl();
const model = codeEditor.getModel();
if (model) {
const lastLine = model.getLineCount();
if (!smart || codeEditor.getPosition().lineNumber === lastLine) {
codeEditor.revealPosition({ lineNumber: lastLine, column: model.getLineMaxColumn(lastLine) }, ScrollType.Smooth);
}
codeEditor.revealPosition({ lineNumber: lastLine, column: model.getLineMaxColumn(lastLine) }, ScrollType.Smooth);
}
}
@@ -190,7 +185,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
super.saveTextEditorViewState(resource);
// Make sure to clean up when the input gets disposed
once(input.onDispose)(() => {
Event.once(input.onDispose)(() => {
super.clearTextEditorViewState([resource]);
});
}

View File

@@ -65,17 +65,17 @@ export abstract class TitleControl extends Themable {
parent: HTMLElement,
protected accessor: IEditorGroupsAccessor,
protected group: IEditorGroupView,
@IContextMenuService private contextMenuService: IContextMenuService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IInstantiationService protected instantiationService: IInstantiationService,
@IContextKeyService private contextKeyService: IContextKeyService,
@IKeybindingService private keybindingService: IKeybindingService,
@ITelemetryService private telemetryService: ITelemetryService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
// {{SQL CARBON EDIT}} -- need to make the notification service protected
@INotificationService protected notificationService: INotificationService,
@IMenuService private menuService: IMenuService,
@INotificationService protected readonly notificationService: INotificationService,
@IMenuService private readonly menuService: IMenuService,
@IQuickOpenService protected quickOpenService: IQuickOpenService,
@IThemeService themeService: IThemeService,
@IExtensionService private extensionService: IExtensionService,
@IExtensionService private readonly extensionService: IExtensionService,
@IConfigurationService protected configurationService: IConfigurationService,
@IFileService private readonly fileService: IFileService,
) {
@@ -320,11 +320,9 @@ export abstract class TitleControl extends Themable {
protected getKeybindingLabel(action: IAction): string {
const keybinding = this.getKeybinding(action);
return keybinding ? keybinding.getLabel() : void 0;
return keybinding ? keybinding.getLabel() : undefined;
}
//#region ITitleAreaControl
abstract openEditor(editor: IEditorInput): void;
abstract closeEditor(editor: IEditorInput): void;
@@ -348,8 +346,6 @@ export abstract class TitleControl extends Themable {
abstract updateStyles(): void;
layout(dimension: Dimension): void {
// Optionally implemented in subclasses
if (this.breadcrumbsControl) {
this.breadcrumbsControl.layout(undefined);
}
@@ -365,8 +361,6 @@ export abstract class TitleControl extends Themable {
super.dispose();
}
//#endregion
}
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {

View File

@@ -3,15 +3,15 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench > .part > .content > .composite {
.monaco-workbench .part > .content > .composite {
height: 100%;
}
.monaco-workbench > .part > .composite.title {
.monaco-workbench .part > .composite.title {
display: flex;
}
.monaco-workbench > .part > .composite.title > .title-actions {
.monaco-workbench .part > .composite.title > .title-actions {
flex: 1;
padding-left: 5px;
}

View File

@@ -21,7 +21,7 @@ export class ClearNotificationAction extends Action {
constructor(
id: string,
label: string,
@ICommandService private commandService: ICommandService
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, 'clear-notification-action');
}
@@ -29,7 +29,7 @@ export class ClearNotificationAction extends Action {
run(notification: INotificationViewItem): Promise<any> {
this.commandService.executeCommand(CLEAR_NOTIFICATION, notification);
return Promise.resolve(void 0);
return Promise.resolve();
}
}
@@ -41,7 +41,7 @@ export class ClearAllNotificationsAction extends Action {
constructor(
id: string,
label: string,
@ICommandService private commandService: ICommandService
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, 'clear-all-notifications-action');
}
@@ -49,7 +49,7 @@ export class ClearAllNotificationsAction extends Action {
run(notification: INotificationViewItem): Promise<any> {
this.commandService.executeCommand(CLEAR_ALL_NOTIFICATIONS);
return Promise.resolve(void 0);
return Promise.resolve();
}
}
@@ -61,7 +61,7 @@ export class HideNotificationsCenterAction extends Action {
constructor(
id: string,
label: string,
@ICommandService private commandService: ICommandService
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, 'hide-all-notifications-action');
}
@@ -69,7 +69,7 @@ export class HideNotificationsCenterAction extends Action {
run(notification: INotificationViewItem): Promise<any> {
this.commandService.executeCommand(HIDE_NOTIFICATIONS_CENTER);
return Promise.resolve(void 0);
return Promise.resolve();
}
}
@@ -81,7 +81,7 @@ export class ExpandNotificationAction extends Action {
constructor(
id: string,
label: string,
@ICommandService private commandService: ICommandService
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, 'expand-notification-action');
}
@@ -89,7 +89,7 @@ export class ExpandNotificationAction extends Action {
run(notification: INotificationViewItem): Promise<any> {
this.commandService.executeCommand(EXPAND_NOTIFICATION, notification);
return Promise.resolve(void 0);
return Promise.resolve();
}
}
@@ -101,7 +101,7 @@ export class CollapseNotificationAction extends Action {
constructor(
id: string,
label: string,
@ICommandService private commandService: ICommandService
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, 'collapse-notification-action');
}
@@ -109,7 +109,7 @@ export class CollapseNotificationAction extends Action {
run(notification: INotificationViewItem): Promise<any> {
this.commandService.executeCommand(COLLAPSE_NOTIFICATION, notification);
return Promise.resolve(void 0);
return Promise.resolve();
}
}
@@ -139,7 +139,7 @@ export class CopyNotificationMessageAction extends Action {
constructor(
id: string,
label: string,
@IClipboardService private clipboardService: IClipboardService
@IClipboardService private readonly clipboardService: IClipboardService
) {
super(id, label);
}
@@ -147,15 +147,15 @@ export class CopyNotificationMessageAction extends Action {
run(notification: INotificationViewItem): Promise<any> {
this.clipboardService.writeText(notification.message.raw);
return Promise.resolve(void 0);
return Promise.resolve();
}
}
export class NotificationActionRunner extends ActionRunner {
constructor(
@ITelemetryService private telemetryService: ITelemetryService,
@INotificationService private notificationService: INotificationService
@ITelemetryService private readonly telemetryService: ITelemetryService,
@INotificationService private readonly notificationService: INotificationService
) {
super();
}
@@ -171,8 +171,8 @@ export class NotificationActionRunner extends ActionRunner {
this.telemetryService.publicLog('workbenchActionExecuted', { id: action.id, from: 'message' });
// Run and make sure to notify on any error again
super.runAction(action, context).then(null, error => this.notificationService.error(error));
super.runAction(action, context).then(undefined, error => this.notificationService.error(error));
return Promise.resolve(void 0);
return Promise.resolve();
}
}

View File

@@ -9,7 +9,7 @@ import { INotificationViewItem, INotificationsModel, NotificationChangeType, INo
import { Disposable } from 'vs/base/common/lifecycle';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { Severity } from 'vs/platform/notification/common/notification';
import { once } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
export class NotificationsAlerts extends Disposable {
@@ -52,7 +52,7 @@ export class NotificationsAlerts extends Disposable {
}
});
once(notifiation.onDidClose)(() => listener.dispose());
Event.once(notifiation.onDidClose)(() => listener.dispose());
this.doTriggerAriaAlert(notifiation);
}

View File

@@ -42,11 +42,11 @@ export class NotificationsCenter extends Themable {
private container: HTMLElement,
private model: INotificationsModel,
@IThemeService themeService: IThemeService,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private partService: IPartService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IPartService private readonly partService: IPartService,
@IContextKeyService contextKeyService: IContextKeyService,
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
@IKeybindingService private keybindingService: IKeybindingService
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) {
super(themeService);
@@ -152,10 +152,10 @@ export class NotificationsCenter extends Themable {
this.container.appendChild(this.notificationsCenterContainer);
}
private getKeybindingLabel(action: IAction): string {
private getKeybindingLabel(action: IAction): string | null {
const keybinding = this.keybindingService.lookupKeybinding(action.id);
return keybinding ? keybinding.getLabel() : void 0;
return keybinding ? keybinding.getLabel() : null;
}
private onDidNotificationChange(e: INotificationChangeEvent): void {

View File

@@ -62,7 +62,7 @@ export interface INotificationsToastController {
export function registerNotificationCommands(center: INotificationsCenterController, toasts: INotificationsToastController): void {
function getNotificationFromContext(listService: IListService, context?: any): INotificationViewItem {
function getNotificationFromContext(listService: IListService, context?: any): INotificationViewItem | undefined {
if (isNotificationViewItem(context)) {
return context;
}
@@ -75,7 +75,7 @@ export function registerNotificationCommands(center: INotificationsCenterControl
}
}
return void 0;
return undefined;
}
// Show Notifications Cneter

View File

@@ -26,9 +26,9 @@ export class NotificationsList extends Themable {
constructor(
private container: HTMLElement,
private options: IListOptions<INotificationViewItem>,
@IInstantiationService private instantiationService: IInstantiationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IContextMenuService private contextMenuService: IContextMenuService
@IContextMenuService private readonly contextMenuService: IContextMenuService
) {
super(themeService);
@@ -77,7 +77,8 @@ export class NotificationsList extends Themable {
[renderer],
{
...this.options,
setRowLineHeight: false
setRowLineHeight: false,
horizontalScrolling: false
}
));
@@ -89,7 +90,7 @@ export class NotificationsList extends Themable {
}
this.contextMenuService.showContextMenu({
getAnchor: () => e.anchor,
getAnchor: () => e.anchor!,
getActions: () => [copyAction],
getActionsContext: () => e.element,
actionRunner
@@ -133,7 +134,7 @@ export class NotificationsList extends Themable {
const focusedIndex = this.list.getFocus()[0];
const focusedItem = this.viewModel[focusedIndex];
let focusRelativeTop: number;
let focusRelativeTop: number | null = null;
if (typeof focusedIndex === 'number') {
focusRelativeTop = this.list.getRelativeTop(focusedIndex);
}

View File

@@ -16,7 +16,7 @@ export class NotificationsStatus extends Disposable {
constructor(
private model: INotificationsModel,
@IStatusbarService private statusbarService: IStatusbarService
@IStatusbarService private readonly statusbarService: IStatusbarService
) {
super();

View File

@@ -9,7 +9,7 @@ import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { addClass, removeClass, isAncestor, addDisposableListener, EventType, Dimension } from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { NotificationsList } from 'vs/workbench/browser/parts/notifications/notificationsList';
import { once } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
import { Themable, NOTIFICATIONS_TOAST_BORDER } from 'vs/workbench/common/theme';
import { IThemeService } from 'vs/platform/theme/common/themeService';
@@ -22,6 +22,7 @@ import { Severity } from 'vs/platform/notification/common/notification';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { timeout } from 'vs/base/common/async';
interface INotificationToast {
item: INotificationViewItem;
@@ -53,7 +54,6 @@ export class NotificationsToasts extends Themable {
private notificationsToastsContainer: HTMLElement;
private workbenchDimensions: Dimension;
private windowHasFocus: boolean;
private isNotificationsCenterVisible: boolean;
private mapNotificationToToast: Map<INotificationViewItem, INotificationToast>;
private notificationsToastsVisibleContextKey: IContextKey<boolean>;
@@ -61,28 +61,26 @@ export class NotificationsToasts extends Themable {
constructor(
private container: HTMLElement,
private model: INotificationsModel,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private partService: IPartService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IPartService private readonly partService: IPartService,
@IThemeService themeService: IThemeService,
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IContextKeyService contextKeyService: IContextKeyService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IWindowService private windowService: IWindowService
@ILifecycleService private readonly lifecycleService: ILifecycleService,
@IWindowService private readonly windowService: IWindowService
) {
super(themeService);
this.mapNotificationToToast = new Map<INotificationViewItem, INotificationToast>();
this.notificationsToastsVisibleContextKey = NotificationsToastsVisibleContext.bindTo(contextKeyService);
this.windowService.isFocused().then(isFocused => this.windowHasFocus = isFocused);
this.registerListeners();
}
private registerListeners(): void {
// Wait for the running phase to ensure we can draw notifications properly
this.lifecycleService.when(LifecyclePhase.Ready).then(() => {
// Delay some tasks until after we can show notifications
this.onCanShowNotifications().then(() => {
// Show toast for initial notifications if any
this.model.notifications.forEach(notification => this.addToast(notification));
@@ -90,9 +88,20 @@ export class NotificationsToasts extends Themable {
// Update toasts on notification changes
this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
});
}
// Track window focus
this.windowService.onDidChangeFocus(hasFocus => this.windowHasFocus = hasFocus);
private onCanShowNotifications(): Promise<void> {
// Wait for the running phase to ensure we can draw notifications properly
return this.lifecycleService.when(LifecyclePhase.Ready).then(() => {
// Push notificiations out until either workbench is restored
// or some time has ellapsed to reduce pressure on the startup
return Promise.race([
this.lifecycleService.when(LifecyclePhase.Restored),
timeout(2000)
]);
});
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
@@ -185,7 +194,7 @@ export class NotificationsToasts extends Themable {
}));
// Remove when item gets closed
once(item.onDidClose)(() => {
Event.once(item.onDidClose)(() => {
this.removeToast(item);
});
@@ -226,7 +235,7 @@ export class NotificationsToasts extends Themable {
// the timeout again. This prevents an issue where focussing the window
// could immediately hide the notification because the timeout was triggered
// again.
if ((item.sticky || item.hasPrompt()) && !this.windowHasFocus) {
if ((item.sticky || item.hasPrompt()) && !this.windowService.hasFocus) {
if (!listener) {
listener = this.windowService.onDidChangeFocus(focus => {
if (focus) {
@@ -447,7 +456,7 @@ export class NotificationsToasts extends Themable {
let maxWidth = NotificationsToasts.MAX_WIDTH;
let availableWidth = maxWidth;
let availableHeight: number;
let availableHeight: number | undefined;
if (this.workbenchDimensions) {
@@ -468,7 +477,9 @@ export class NotificationsToasts extends Themable {
availableHeight -= (2 * 12); // adjust for paddings top and bottom
}
availableHeight = Math.round(availableHeight * 0.618); // try to not cover the full height for stacked toasts
availableHeight = typeof availableHeight === 'number'
? Math.round(availableHeight * 0.618) // try to not cover the full height for stacked toasts
: 0;
return new Dimension(Math.min(maxWidth, availableWidth), availableHeight);
}

View File

@@ -16,12 +16,13 @@ import { IAction, IActionRunner } from 'vs/base/common/actions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { DropdownMenuActionItem } from 'vs/base/browser/ui/dropdown/dropdown';
import { DropdownMenuActionItem, IContextMenuProvider } from 'vs/base/browser/ui/dropdown/dropdown';
import { INotificationViewItem, NotificationViewItem, NotificationViewItemLabelKind, INotificationMessage, ChoiceAction } from 'vs/workbench/common/notifications';
import { ClearNotificationAction, ExpandNotificationAction, CollapseNotificationAction, ConfigureNotificationAction } from 'vs/workbench/browser/parts/notifications/notificationsActions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
import { Severity } from 'vs/platform/notification/common/notification';
import { isNonEmptyArray } from 'vs/base/common/arrays';
export class NotificationsListDelegate implements IListVirtualDelegate<INotificationViewItem> {
@@ -61,7 +62,7 @@ export class NotificationsListDelegate implements IListVirtualDelegate<INotifica
}
// Last row: source and buttons if we have any
if (notification.source || notification.actions.primary.length > 0) {
if (notification.source || isNonEmptyArray(notification.actions.primary)) {
expandedHeight += NotificationsListDelegate.ROW_HEIGHT;
}
@@ -81,7 +82,7 @@ export class NotificationsListDelegate implements IListVirtualDelegate<INotifica
if (notification.canCollapse) {
actions++; // expand/collapse
}
if (notification.actions.secondary.length > 0) {
if (isNonEmptyArray(notification.actions.secondary)) {
actions++; // secondary actions
}
this.offsetHelper.style.width = `calc(100% - ${10 /* padding */ + 24 /* severity icon */ + (actions * 24) /* 24px per action */}px)`;
@@ -104,7 +105,7 @@ export class NotificationsListDelegate implements IListVirtualDelegate<INotifica
return NotificationRenderer.TEMPLATE_ID;
}
return void 0;
throw new Error('unknown element type: ' + element);
}
}
@@ -143,8 +144,7 @@ class NotificationMessageRenderer {
// Message has links
else {
let index = 0;
for (let i = 0; i < message.links.length; i++) {
const link = message.links[i];
for (const link of message.links) {
const textBefore = message.value.substring(index, link.offset);
if (textBefore) {
@@ -182,9 +182,9 @@ export class NotificationRenderer implements IListRenderer<INotificationViewItem
constructor(
private actionRunner: IActionRunner,
@IThemeService private themeService: IThemeService,
@IContextMenuService private contextMenuService: IContextMenuService,
@IInstantiationService private instantiationService: IInstantiationService
@IThemeService private readonly themeService: IThemeService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
}
@@ -220,8 +220,8 @@ export class NotificationRenderer implements IListRenderer<INotificationViewItem
{
ariaLabel: localize('notificationActions', "Notification Actions"),
actionItemProvider: action => {
if (action instanceof ConfigureNotificationAction) {
const item = new DropdownMenuActionItem(action, action.configurationActions, this.contextMenuService, null, this.actionRunner, null, action.class);
if (action && action instanceof ConfigureNotificationAction) {
const item = new DropdownMenuActionItem(action, action.configurationActions, this.contextMenuService as IContextMenuProvider, undefined, this.actionRunner, undefined, action.class as string);
data.toDispose.push(item);
return item;
@@ -275,10 +275,6 @@ export class NotificationRenderer implements IListRenderer<INotificationViewItem
data.renderer.setInput(notification);
}
disposeElement(): void {
// noop
}
disposeTemplate(templateData: INotificationTemplateData): void {
templateData.toDispose = dispose(templateData.toDispose);
}
@@ -290,17 +286,17 @@ export class NotificationTemplateRenderer {
private static expandNotificationAction: ExpandNotificationAction;
private static collapseNotificationAction: CollapseNotificationAction;
private static readonly SEVERITIES: ('info' | 'warning' | 'error')[] = ['info', 'warning', 'error'];
private static readonly SEVERITIES: Array<'info' | 'warning' | 'error'> = ['info', 'warning', 'error'];
private inputDisposeables: IDisposable[] = [];
constructor(
private template: INotificationTemplateData,
private actionRunner: IActionRunner,
@IOpenerService private openerService: IOpenerService,
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService private themeService: IThemeService,
@IKeybindingService private keybindingService: IKeybindingService
@IOpenerService private readonly openerService: IOpenerService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IThemeService private readonly themeService: IThemeService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) {
if (!NotificationTemplateRenderer.closeNotificationAction) {
NotificationTemplateRenderer.closeNotificationAction = instantiationService.createInstance(ClearNotificationAction, ClearNotificationAction.ID, ClearNotificationAction.LABEL);
@@ -374,7 +370,7 @@ export class NotificationTemplateRenderer {
const messageOverflows = notification.canCollapse && !notification.expanded && this.template.message.scrollWidth > this.template.message.clientWidth;
if (messageOverflows) {
this.template.message.title = this.template.message.textContent;
this.template.message.title = this.template.message.textContent + '';
} else {
this.template.message.removeAttribute('title');
}
@@ -391,7 +387,7 @@ export class NotificationTemplateRenderer {
const actions: IAction[] = [];
// Secondary Actions
if (notification.actions.secondary.length > 0) {
if (isNonEmptyArray(notification.actions.secondary)) {
const configureNotificationAction = this.instantiationService.createInstance(ConfigureNotificationAction, ConfigureNotificationAction.ID, ConfigureNotificationAction.LABEL, notification.actions.secondary);
actions.push(configureNotificationAction);
this.inputDisposeables.push(configureNotificationAction);
@@ -434,10 +430,10 @@ export class NotificationTemplateRenderer {
private renderButtons(notification: INotificationViewItem): void {
clearNode(this.template.buttonsContainer);
if (notification.expanded) {
if (notification.expanded && notification.actions.primary) {
const buttonGroup = new ButtonGroup(this.template.buttonsContainer, notification.actions.primary.length, { title: true /* assign titles to buttons in case they overflow */ });
buttonGroup.buttons.forEach((button, index) => {
const action = notification.actions.primary[index];
const action = notification.actions.primary![index];
button.label = action.label;
this.inputDisposeables.push(button.onDidClick(e => {
@@ -502,10 +498,10 @@ export class NotificationTemplateRenderer {
}
}
private getKeybindingLabel(action: IAction): string {
private getKeybindingLabel(action: IAction): string | null {
const keybinding = this.keybindingService.lookupKeybinding(action.id);
return keybinding ? keybinding.getLabel() : void 0;
return keybinding ? keybinding.getLabel() : null;
}
dispose(): void {

View File

@@ -3,16 +3,16 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench.nopanel > .part.panel {
.monaco-workbench.nopanel .part.panel {
display: none !important;
visibility: hidden !important;
}
.monaco-workbench > .part.panel {
.monaco-workbench .part.panel {
z-index: initial;
}
.monaco-workbench > .part.panel .title {
.monaco-workbench .part.panel .title {
padding-right: 0px;
height: 35px;
display: flex;
@@ -20,23 +20,23 @@
justify-content: space-between;
}
.monaco-workbench > .part.panel.bottom .title {
.monaco-workbench .part.panel.bottom .title {
border-top-width: 1px;
border-top-style: solid;
}
.monaco-workbench > .part.panel.right {
.monaco-workbench .part.panel.right {
border-left-width: 1px;
border-left-style: solid;
}
.monaco-workbench > .part.panel > .title > .title-actions .monaco-action-bar .action-item .action-label {
.monaco-workbench .part.panel > .title > .title-actions .monaco-action-bar .action-item .action-label {
outline-offset: -2px;
}
/** Panel Switcher */
.monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more {
.monaco-workbench .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more {
background-image: url('ellipsis.svg');
display: block;
height: 28px;
@@ -48,16 +48,16 @@
background-position: center center;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar {
line-height: 27px; /* matches panel titles in settings */
height: 35px;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:first-child {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:first-child {
padding-left: 12px;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item {
text-transform: uppercase;
padding-left: 10px;
padding-right: 10px;
@@ -67,24 +67,24 @@
display: flex;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label{
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label{
margin-right: 0;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:last-child {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:last-child {
padding-right: 10px;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label {
border-bottom: 1px solid;
margin-right: 0;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge {
margin-left: 8px;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge .badge-content {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge .badge-content {
padding: 0.3em 0.5em;
border-radius: 1em;
font-weight: normal;
@@ -152,7 +152,7 @@
background: url('close-inverse.svg') center center no-repeat;
}
.vs-dark .monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more,
.hc-black .monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more {
.vs-dark .monaco-workbench .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more,
.hc-black .monaco-workbench .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more {
background-image: url('ellipsis-inverse.svg');
}

View File

@@ -24,12 +24,12 @@ export class ClosePanelAction extends Action {
constructor(
id: string,
name: string,
@IPartService private partService: IPartService
@IPartService private readonly partService: IPartService
) {
super(id, name, 'hide-panel-action');
}
run(): Thenable<any> {
run(): Promise<any> {
this.partService.setPanelHidden(true);
return Promise.resolve(null);
}
@@ -43,12 +43,12 @@ export class TogglePanelAction extends Action {
constructor(
id: string,
name: string,
@IPartService private partService: IPartService
@IPartService private readonly partService: IPartService
) {
super(id, name, partService.isVisible(Parts.PANEL_PART) ? 'panel expanded' : 'panel');
}
run(): Thenable<any> {
run(): Promise<any> {
this.partService.setPanelHidden(this.partService.isVisible(Parts.PANEL_PART));
return Promise.resolve(null);
}
@@ -62,13 +62,13 @@ class FocusPanelAction extends Action {
constructor(
id: string,
label: string,
@IPanelService private panelService: IPanelService,
@IPartService private partService: IPartService
@IPanelService private readonly panelService: IPanelService,
@IPartService private readonly partService: IPartService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
// Show panel
if (!this.partService.isVisible(Parts.PANEL_PART)) {
@@ -99,7 +99,7 @@ export class TogglePanelPositionAction extends Action {
constructor(
id: string,
label: string,
@IPartService private partService: IPartService,
@IPartService private readonly partService: IPartService,
) {
super(id, label, partService.getPanelPosition() === Position.RIGHT ? 'move-panel-to-bottom' : 'move-panel-to-right');
@@ -116,7 +116,7 @@ export class TogglePanelPositionAction extends Action {
setClassAndLabel();
}
run(): Thenable<any> {
run(): Promise<any> {
const position = this.partService.getPanelPosition();
this.partService.setPanelPosition(position === Position.BOTTOM ? Position.RIGHT : Position.BOTTOM);
@@ -143,7 +143,7 @@ export class ToggleMaximizedPanelAction extends Action {
constructor(
id: string,
label: string,
@IPartService private partService: IPartService
@IPartService private readonly partService: IPartService
) {
super(id, label, partService.isPanelMaximized() ? 'minimize-panel-action' : 'maximize-panel-action');
@@ -156,7 +156,7 @@ export class ToggleMaximizedPanelAction extends Action {
}));
}
run(): Thenable<any> {
run(): Promise<any> {
if (!this.partService.isVisible(Parts.PANEL_PART)) {
this.partService.setPanelHidden(false);
}
@@ -176,12 +176,12 @@ export class PanelActivityAction extends ActivityAction {
constructor(
activity: IActivity,
@IPanelService private panelService: IPanelService
@IPanelService private readonly panelService: IPanelService
) {
super(activity);
}
run(event: any): Thenable<any> {
run(event: any): Promise<any> {
this.panelService.openPanel(this.activity.id, true);
this.activate();
return Promise.resolve(null);
@@ -193,12 +193,12 @@ export class SwitchPanelViewAction extends Action {
constructor(
id: string,
name: string,
@IPanelService private panelService: IPanelService
@IPanelService private readonly panelService: IPanelService
) {
super(id, name);
}
run(offset: number): Thenable<any> {
run(offset: number): Promise<any> {
const pinnedPanels = this.panelService.getPinnedPanels();
const activePanel = this.panelService.getActivePanel();
if (!activePanel) {
@@ -229,7 +229,7 @@ export class PreviousPanelViewAction extends SwitchPanelViewAction {
super(id, name, panelService);
}
run(): Thenable<any> {
run(): Promise<any> {
return super.run(-1);
}
}
@@ -247,7 +247,7 @@ export class NextPanelViewAction extends SwitchPanelViewAction {
super(id, name, panelService);
}
public run(): Thenable<any> {
public run(): Promise<any> {
return super.run(1);
}
}

View File

@@ -5,7 +5,7 @@
import 'vs/css!./media/panelpart';
import { IAction } from 'vs/base/common/actions';
import { Event, mapEvent } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { Registry } from 'vs/platform/registry/common/platform';
import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { IPanel } from 'vs/workbench/common/panel';
@@ -13,7 +13,7 @@ import { CompositePart, ICompositeTitleLabel } from 'vs/workbench/browser/parts/
import { Panel, PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel';
import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService';
import { IPartService, Parts, Position } from 'vs/workbench/services/part/common/partService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
@@ -22,7 +22,7 @@ import { ClosePanelAction, TogglePanelPositionAction, PanelActivityAction, Toggl
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar } from 'vs/workbench/browser/parts/compositeBar';
import { CompositeBar, ICompositeBarItem } from 'vs/workbench/browser/parts/compositeBar';
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -30,11 +30,22 @@ import { Dimension, trackFocus } from 'vs/base/browser/dom';
import { localize } from 'vs/nls';
import { IDisposable } from 'vs/base/common/lifecycle';
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
import { LayoutPriority } from 'vs/base/browser/ui/grid/gridview';
export const ActivePanelContext = new RawContextKey<string>('activePanel', '');
export const PanelFocusContext = new RawContextKey<boolean>('panelFocus', false);
export class PanelPart extends CompositePart<Panel> implements IPanelService {
interface ICachedPanel {
id: string;
pinned: boolean;
order: number;
visible: boolean;
}
export class PanelPart extends CompositePart<Panel> implements IPanelService, ISerializableView {
static readonly activePanelSettingsKey = 'workbench.panelpart.activepanelid';
@@ -50,6 +61,17 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
private compositeActions: { [compositeId: string]: { activityAction: PanelActivityAction, pinnedAction: ToggleCompositePinnedAction } } = Object.create(null);
private dimension: Dimension;
element: HTMLElement;
minimumWidth: number = 300;
maximumWidth: number = Number.POSITIVE_INFINITY;
minimumHeight: number = 77;
maximumHeight: number = Number.POSITIVE_INFINITY;
snapSize: number = 50;
priority: LayoutPriority = LayoutPriority.Low;
private _onDidChange = new Emitter<{ width: number; height: number; }>();
readonly onDidChange = this._onDidChange.event;
constructor(
id: string,
@INotificationService notificationService: INotificationService,
@@ -61,6 +83,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
@IInstantiationService instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService,
@ILifecycleService private readonly lifecycleService: ILifecycleService
) {
super(
notificationService,
@@ -81,9 +104,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
{ hasTitle: true }
);
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, {
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.getCachedPanels(), {
icon: false,
storageId: PanelPart.PINNED_PANELS,
orientation: ActionsOrientation.HORIZONTAL,
openComposite: (compositeId: string) => Promise.resolve(this.openPanel(compositeId, true)),
getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction,
@@ -120,6 +142,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
create(parent: HTMLElement): void {
this.element = parent;
super.create(parent);
const focusTracker = trackFocus(parent);
@@ -137,6 +161,10 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
this._register(this.onDidPanelClose(this._onDidPanelClose, this));
this._register(this.registry.onDidRegister(panelDescriptor => this.compositeBar.addComposite(panelDescriptor)));
this._register(this.registry.onDidDeregister(panelDescriptor => {
this.compositeBar.hideComposite(panelDescriptor.id);
this.removeComposite(panelDescriptor.id);
}));
// Activate panel action on opening of a panel
this._register(this.onDidPanelOpen(({ panel }) => {
@@ -146,6 +174,11 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
// Deactivate panel action on close
this._register(this.onDidPanelClose(panel => this.compositeBar.deactivateComposite(panel.getId())));
this.lifecycleService.when(LifecyclePhase.Eventually).then(() => {
this._register(this.compositeBar.onDidChange(() => this.saveCachedPanels()));
this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e)));
});
}
private _onDidPanelOpen(panel: IPanel): void {
@@ -161,7 +194,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
get onDidPanelOpen(): Event<{ panel: IPanel, focus: boolean }> {
return mapEvent(this._onDidCompositeOpen.event, compositeOpen => ({ panel: compositeOpen.composite, focus: compositeOpen.focus }));
return Event.map(this._onDidCompositeOpen.event, compositeOpen => ({ panel: compositeOpen.composite, focus: compositeOpen.focus }));
}
get onDidPanelClose(): Event<IPanel> {
@@ -207,7 +240,6 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
getPanels(): PanelDescriptor[] {
return Registry.as<PanelRegistry>(PanelExtensions.Panels).getPanels()
.filter(p => p.enabled)
.sort((v1, v2) => v1.order - v2.order);
}
@@ -218,18 +250,6 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
.sort((p1, p2) => pinnedCompositeIds.indexOf(p1.id) - pinnedCompositeIds.indexOf(p2.id));
}
setPanelEnablement(id: string, enabled: boolean): void {
const descriptor = Registry.as<PanelRegistry>(PanelExtensions.Panels).getPanels().filter(p => p.id === id).pop();
if (descriptor && descriptor.enabled !== enabled) {
descriptor.enabled = enabled;
if (enabled) {
this.compositeBar.addComposite(descriptor);
} else {
this.removeComposite(id);
}
}
}
protected getActions(): IAction[] {
return [
this.instantiationService.createInstance(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, ToggleMaximizedPanelAction.LABEL),
@@ -266,21 +286,32 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
};
}
layout(dimension: Dimension): Dimension[] {
layout(dimension: Dimension): Dimension[];
layout(width: number, height: number): void;
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
if (!this.partService.isVisible(Parts.PANEL_PART)) {
return [dimension];
if (dim1 instanceof Dimension) {
return [dim1];
}
return;
}
const { width, height } = dim1 instanceof Dimension ? dim1 : { width: dim1, height: dim2 };
if (this.partService.getPanelPosition() === Position.RIGHT) {
// Take into account the 1px border when layouting
this.dimension = new Dimension(dimension.width - 1, dimension.height);
this.dimension = new Dimension(width - 1, height);
} else {
this.dimension = dimension;
this.dimension = new Dimension(width, height);
}
const sizes = super.layout(this.dimension);
const sizes = super.layout(this.dimension.width, this.dimension.height);
this.layoutCompositeBar();
return sizes;
if (dim1 instanceof Dimension) {
return sizes;
}
}
private layoutCompositeBar(): void {
@@ -306,14 +337,17 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
return compositeActions;
}
private removeComposite(compositeId: string): void {
this.compositeBar.hideComposite(compositeId);
const compositeActions = this.compositeActions[compositeId];
if (compositeActions) {
compositeActions.activityAction.dispose();
compositeActions.pinnedAction.dispose();
delete this.compositeActions[compositeId];
protected removeComposite(compositeId: string): boolean {
if (super.removeComposite(compositeId)) {
const compositeActions = this.compositeActions[compositeId];
if (compositeActions) {
compositeActions.activityAction.dispose();
compositeActions.pinnedAction.dispose();
delete this.compositeActions[compositeId];
}
return true;
}
return false;
}
private getToolbarWidth(): number {
@@ -323,6 +357,89 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
return this.toolBar.getItemsWidth();
}
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
if (e.key === PanelPart.PINNED_PANELS && e.scope === StorageScope.GLOBAL
&& this.cachedPanelsValue !== this.getStoredCachedPanelsValue() /* This checks if current window changed the value or not */) {
this._cachedPanelsValue = null;
const newCompositeItems: ICompositeBarItem[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
const cachedPanels = this.getCachedPanels();
for (const cachedPanel of cachedPanels) {
// Add and update existing items
const existingItem = compositeItems.filter(({ id }) => id === cachedPanel.id)[0];
if (existingItem) {
newCompositeItems.push({
id: existingItem.id,
name: existingItem.name,
order: existingItem.order,
pinned: cachedPanel.pinned,
visible: existingItem.visible
});
}
}
for (let index = 0; index < compositeItems.length; index++) {
// Add items currently exists but does not exist in new.
if (!newCompositeItems.some(({ id }) => id === compositeItems[index].id)) {
newCompositeItems.splice(index, 0, compositeItems[index]);
}
}
this.compositeBar.setCompositeBarItems(newCompositeItems);
}
}
private saveCachedPanels(): void {
const state: ICachedPanel[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
for (const compositeItem of compositeItems) {
state.push({ id: compositeItem.id, pinned: compositeItem.pinned, order: compositeItem.order, visible: compositeItem.visible });
}
this.cachedPanelsValue = JSON.stringify(state);
}
private getCachedPanels(): ICachedPanel[] {
const storedStates = <Array<string | ICachedPanel>>JSON.parse(this.cachedPanelsValue);
const registeredPanels = this.getPanels();
const cachedPanels = <ICachedPanel[]>storedStates.map(c => {
const serialized: ICachedPanel = typeof c === 'string' /* migration from pinned states to composites states */ ? <ICachedPanel>{ id: c, pinned: true, order: undefined, visible: true } : c;
const registered = registeredPanels.some(p => p.id === serialized.id);
serialized.visible = registered ? isUndefinedOrNull(serialized.visible) ? true : serialized.visible : false;
return serialized;
});
return cachedPanels;
}
private _cachedPanelsValue: string;
private get cachedPanelsValue(): string {
if (!this._cachedPanelsValue) {
this._cachedPanelsValue = this.getStoredCachedPanelsValue();
}
return this._cachedPanelsValue;
}
private set cachedPanelsValue(cachedViewletsValue: string) {
if (this.cachedPanelsValue !== cachedViewletsValue) {
this._cachedPanelsValue = cachedViewletsValue;
this.setStoredCachedViewletsValue(cachedViewletsValue);
}
}
private getStoredCachedPanelsValue(): string {
return this.storageService.get(PanelPart.PINNED_PANELS, StorageScope.GLOBAL, '[]');
}
private setStoredCachedViewletsValue(value: string): void {
this.storageService.store(PanelPart.PINNED_PANELS, value, StorageScope.GLOBAL);
}
toJSON(): object {
return {
type: Parts.PANEL_PART
};
}
}
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
@@ -333,9 +450,9 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const panelBackground = theme.getColor(PANEL_BACKGROUND);
if (panelBackground && panelBackground !== theme.getColor(editorBackground)) {
collector.addRule(`
.monaco-workbench > .part.panel > .content .monaco-editor,
.monaco-workbench > .part.panel > .content .monaco-editor .margin,
.monaco-workbench > .part.panel > .content .monaco-editor .monaco-editor-background {
.monaco-workbench .part.panel > .content .monaco-editor,
.monaco-workbench .part.panel > .content .monaco-editor .margin,
.monaco-workbench .part.panel > .content .monaco-editor .monaco-editor-background {
background-color: ${panelBackground};
}
`);
@@ -346,7 +463,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const titleActiveBorder = theme.getColor(PANEL_ACTIVE_TITLE_BORDER);
if (titleActive || titleActiveBorder) {
collector.addRule(`
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:hover .action-label {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:hover .action-label {
color: ${titleActive} !important;
border-bottom-color: ${titleActiveBorder} !important;
}
@@ -357,14 +474,14 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const focusBorderColor = theme.getColor(focusBorder);
if (focusBorderColor) {
collector.addRule(`
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus .action-label {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus .action-label {
color: ${titleActive} !important;
border-bottom-color: ${focusBorderColor} !important;
border-bottom: 1px solid;
}
`);
collector.addRule(`
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus {
outline: none;
}
`);
@@ -376,8 +493,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const outline = theme.getColor(activeContrastBorder);
collector.addRule(`
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label,
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label:hover {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label,
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label:hover {
outline-color: ${outline};
outline-width: 1px;
outline-style: solid;
@@ -386,7 +503,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
outline-offset: 1px;
}
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:not(.checked) .action-label:hover {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:not(.checked) .action-label:hover {
outline-style: dashed;
}
`);

View File

@@ -25,7 +25,7 @@ import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
import { attachBadgeStyler, attachProgressBarStyler, attachButtonStyler } from 'vs/platform/theme/common/styler';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
import { debounceEvent, Emitter, Event } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { Button } from 'vs/base/browser/ui/button/button';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
@@ -252,14 +252,20 @@ class QuickInput implements IQuickInput {
this.ui.leftActionBar.clear();
const leftButtons = this.buttons.filter(button => button === backButton);
this.ui.leftActionBar.push(leftButtons.map((button, index) => {
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => this.onDidTriggerButtonEmitter.fire(button));
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => {
this.onDidTriggerButtonEmitter.fire(button);
return Promise.resolve(null);
});
action.tooltip = button.tooltip;
return action;
}), { icon: true, label: false });
this.ui.rightActionBar.clear();
const rightButtons = this.buttons.filter(button => button !== backButton);
this.ui.rightActionBar.push(rightButtons.map((button, index) => {
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => this.onDidTriggerButtonEmitter.fire(button));
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => {
this.onDidTriggerButtonEmitter.fire(button);
return Promise.resolve(null);
});
action.tooltip = button.tooltip;
return action;
}), { icon: true, label: false });
@@ -306,7 +312,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
private _placeholder;
private onDidChangeValueEmitter = new Emitter<string>();
private onDidAcceptEmitter = new Emitter<string>();
private _items: (T | IQuickPickSeparator)[] = [];
private _items: Array<T | IQuickPickSeparator> = [];
private itemsUpdated = false;
private _canSelectMany = false;
private _matchOnDescription = false;
@@ -360,7 +366,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
return this._items;
}
set items(items: (T | IQuickPickSeparator)[]) {
set items(items: Array<T | IQuickPickSeparator>) {
this._items = items;
this.itemsUpdated = true;
this.update();
@@ -482,7 +488,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this._selectedItems = [this.activeItems[0]];
this.onDidChangeSelectionEmitter.fire(this.selectedItems);
}
this.onDidAcceptEmitter.fire();
this.onDidAcceptEmitter.fire(undefined);
}),
this.ui.list.onDidChangeFocus(focusedItems => {
if (this.activeItemsUpdated) {
@@ -507,7 +513,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this._selectedItems = selectedItems as T[];
this.onDidChangeSelectionEmitter.fire(selectedItems as T[]);
if (selectedItems.length) {
this.onDidAcceptEmitter.fire();
this.onDidAcceptEmitter.fire(undefined);
}
}),
this.ui.list.onChangedCheckedElements(checkedItems => {
@@ -570,7 +576,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
if (wasTriggerKeyPressed && this.activeItems[0]) {
this._selectedItems = [this.activeItems[0]];
this.onDidChangeSelectionEmitter.fire(this.selectedItems);
this.onDidAcceptEmitter.fire();
this.onDidAcceptEmitter.fire(undefined);
}
});
}
@@ -723,7 +729,7 @@ class InputBox extends QuickInput implements IInputBox {
this._value = value;
this.onDidValueChangeEmitter.fire(value);
}),
this.ui.onDidAccept(() => this.onDidAcceptEmitter.fire()),
this.ui.onDidAccept(() => this.onDidAcceptEmitter.fire(undefined)),
);
this.valueSelectionUpdated = true;
}
@@ -788,14 +794,14 @@ export class QuickInputService extends Component implements IQuickInputService {
private controller: QuickInput;
constructor(
@IEnvironmentService private environmentService: IEnvironmentService,
@IConfigurationService private configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private partService: IPartService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
@IKeybindingService private keybindingService: IKeybindingService,
@IContextKeyService private contextKeyService: IContextKeyService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IPartService private readonly partService: IPartService,
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@IStorageService storageService: IStorageService
) {
@@ -1129,7 +1135,7 @@ export class QuickInputService extends Component implements IQuickInputService {
}
});
input.show();
Promise.resolve(picks).then(null, err => {
Promise.resolve(picks).then(undefined, err => {
reject(err);
input.hide();
});
@@ -1143,8 +1149,8 @@ export class QuickInputService extends Component implements IQuickInputService {
return;
}
const input = this.createInputBox();
const validateInput = options.validateInput || (() => <Thenable<undefined>>Promise.resolve(undefined));
const onDidValueChange = debounceEvent(input.onDidChangeValue, (last, cur) => cur, 100);
const validateInput = options.validateInput || (() => <Promise<undefined>>Promise.resolve(undefined));
const onDidValueChange = Event.debounce(input.onDidChangeValue, (last, cur) => cur, 100);
let validationValue = options.value || '';
let validation = Promise.resolve(validateInput(validationValue));
const disposables = [
@@ -1406,7 +1412,7 @@ export class BackAction extends Action {
public static readonly ID = 'workbench.action.quickInputBack';
public static readonly LABEL = localize('back', "Back");
constructor(id: string, label: string, @IQuickInputService private quickInputService: IQuickInputService) {
constructor(id: string, label: string, @IQuickInputService private readonly quickInputService: IQuickInputService) {
super(id, label);
}

View File

@@ -24,7 +24,7 @@ export class QuickInputBox {
private parent: HTMLElement
) {
this.container = dom.append(this.parent, $('.quick-input-box'));
this.inputBox = new InputBox(this.container, null);
this.inputBox = new InputBox(this.container, undefined);
this.disposables.push(this.inputBox);
}
@@ -55,7 +55,7 @@ export class QuickInputBox {
}
get placeholder() {
return this.inputBox.inputElement.getAttribute('placeholder');
return this.inputBox.inputElement.getAttribute('placeholder') || '';
}
set placeholder(placeholder: string) {

View File

@@ -13,7 +13,7 @@ import { IQuickPickItem, IQuickPickItemButtonEvent, IQuickPickSeparator } from '
import { IMatch } from 'vs/base/common/filters';
import { matchesFuzzyOcticonAware, parseOcticons } from 'vs/base/common/octicon';
import { compareAnything } from 'vs/base/common/comparers';
import { Emitter, Event, mapEvent } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { assign } from 'vs/base/common/objects';
import { KeyCode } from 'vs/base/common/keyCodes';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
@@ -32,14 +32,14 @@ import { IListOptions } from 'vs/base/browser/ui/list/listWidget';
const $ = dom.$;
interface IListElement {
index: number;
item: IQuickPickItem;
saneLabel: string;
saneDescription?: string;
saneDetail?: string;
checked: boolean;
separator: IQuickPickSeparator;
fireButtonTriggered: (event: IQuickPickItemButtonEvent<IQuickPickItem>) => void;
readonly index: number;
readonly item: IQuickPickItem;
readonly saneLabel: string;
readonly saneDescription?: string;
readonly saneDetail?: string;
readonly checked: boolean;
readonly separator?: IQuickPickSeparator;
readonly fireButtonTriggered: (event: IQuickPickItemButtonEvent<IQuickPickItem>) => void;
}
class ListElement implements IListElement {
@@ -53,7 +53,7 @@ class ListElement implements IListElement {
onChecked = this._onChecked.event;
_checked?: boolean;
get checked() {
return this._checked;
return !!this._checked;
}
set checked(value: boolean) {
if (value !== this._checked) {
@@ -61,7 +61,7 @@ class ListElement implements IListElement {
this._onChecked.fire(value);
}
}
separator: IQuickPickSeparator;
separator?: IQuickPickSeparator;
labelHighlights?: IMatch[];
descriptionHighlights?: IMatch[];
detailHighlights?: IMatch[];
@@ -144,7 +144,7 @@ class ListElementRenderer implements IListRenderer<ListElement, IListElementTemp
options.descriptionTitle = element.saneDescription;
options.descriptionMatches = descriptionHighlights || [];
options.extraClasses = element.item.iconClasses;
data.label.setValue(element.saneLabel, element.saneDescription, options);
data.label.setLabel(element.saneLabel, element.saneDescription, options);
// Meta
data.detail.set(element.saneDetail, detailHighlights);
@@ -173,14 +173,14 @@ class ListElementRenderer implements IListRenderer<ListElement, IListElementTemp
const buttons = element.item.buttons;
if (buttons && buttons.length) {
data.actionBar.push(buttons.map((button, index) => {
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => {
const action = new Action(`id-${index}`, '', button.iconClass || (button.iconPath ? getIconClass(button.iconPath) : undefined), true, () => {
element.fireButtonTriggered({
button,
item: element.item
});
return null;
return Promise.resolve();
});
action.tooltip = button.tooltip;
action.tooltip = button.tooltip || '';
return action;
}), { icon: true, label: false });
dom.addClass(data.entry, 'has-actions');
@@ -215,7 +215,7 @@ export class QuickInputList {
readonly id: string;
private container: HTMLElement;
private list: WorkbenchList<ListElement>;
private inputElements: (IQuickPickItem | IQuickPickSeparator)[];
private inputElements: Array<IQuickPickItem | IQuickPickSeparator>;
private elements: ListElement[] = [];
private elementsToIndexes = new Map<IQuickPickItem, number>();
matchOnDescription = false;
@@ -239,7 +239,7 @@ export class QuickInputList {
constructor(
private parent: HTMLElement,
id: string,
@IInstantiationService private instantiationService: IInstantiationService
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
this.id = id;
this.container = dom.append(this.parent, $('.quick-input-list'));
@@ -248,7 +248,8 @@ export class QuickInputList {
identityProvider: { getId: element => element.saneLabel },
openController: { shouldOpen: () => false }, // Workaround #58124
setRowLineHeight: false,
multipleSelectionSupport: false
multipleSelectionSupport: false,
horizontalScrolling: false
} as IListOptions<ListElement>) as WorkbenchList<ListElement>;
this.list.getHTMLElement().id = id;
this.disposables.push(this.list);
@@ -294,12 +295,12 @@ export class QuickInputList {
@memoize
get onDidChangeFocus() {
return mapEvent(this.list.onFocusChange, e => e.elements.map(e => e.item));
return Event.map(this.list.onFocusChange, e => e.elements.map(e => e.item));
}
@memoize
get onDidChangeSelection() {
return mapEvent(this.list.onSelectionChange, e => e.elements.map(e => e.item));
return Event.map(this.list.onSelectionChange, e => e.elements.map(e => e.item));
}
getAllVisibleChecked() {
@@ -356,7 +357,7 @@ export class QuickInputList {
}
}
setElements(inputElements: (IQuickPickItem | IQuickPickSeparator)[]): void {
setElements(inputElements: Array<IQuickPickItem | IQuickPickSeparator>): void {
this.elementDisposables = dispose(this.elementDisposables);
const fireButtonTriggered = (event: IQuickPickItemButtonEvent<IQuickPickItem>) => this.fireButtonTriggered(event);
this.inputElements = inputElements;
@@ -395,7 +396,7 @@ export class QuickInputList {
setFocusedElements(items: IQuickPickItem[]) {
this.list.setFocus(items
.filter(item => this.elementsToIndexes.has(item))
.map(item => this.elementsToIndexes.get(item)));
.map(item => this.elementsToIndexes.get(item)!));
}
getActiveDescendant() {
@@ -410,7 +411,7 @@ export class QuickInputList {
setSelectedElements(items: IQuickPickItem[]) {
this.list.setSelection(items
.filter(item => this.elementsToIndexes.has(item))
.map(item => this.elementsToIndexes.get(item)));
.map(item => this.elementsToIndexes.get(item)!));
}
getCheckedElements() {
@@ -484,9 +485,9 @@ export class QuickInputList {
// Filter by value (since we support octicons, use octicon aware fuzzy matching)
else {
this.elements.forEach(element => {
const labelHighlights = matchesFuzzyOcticonAware(query, parseOcticons(element.saneLabel));
const descriptionHighlights = this.matchOnDescription ? matchesFuzzyOcticonAware(query, parseOcticons(element.saneDescription || '')) : undefined;
const detailHighlights = this.matchOnDetail ? matchesFuzzyOcticonAware(query, parseOcticons(element.saneDetail || '')) : undefined;
const labelHighlights = matchesFuzzyOcticonAware(query, parseOcticons(element.saneLabel)) || undefined;
const descriptionHighlights = this.matchOnDescription ? matchesFuzzyOcticonAware(query, parseOcticons(element.saneDescription || '')) || undefined : undefined;
const detailHighlights = this.matchOnDetail ? matchesFuzzyOcticonAware(query, parseOcticons(element.saneDetail || '')) || undefined : undefined;
if (labelHighlights || descriptionHighlights || detailHighlights) {
element.labelHighlights = labelHighlights;

View File

@@ -53,7 +53,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
const HELP_PREFIX = '?';
type ValueCallback<T = any> = (value: T | Thenable<T>) => void;
type ValueCallback<T = any> = (value: T | Promise<T>) => void;
export class QuickOpenController extends Component implements IQuickOpenService {
@@ -86,13 +86,13 @@ export class QuickOpenController extends Component implements IQuickOpenService
private pendingGetResultsInvocation: CancellationTokenSource;
constructor(
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
@INotificationService private notificationService: INotificationService,
@IContextKeyService private contextKeyService: IContextKeyService,
@IConfigurationService private configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private partService: IPartService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@INotificationService private readonly notificationService: INotificationService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IPartService private readonly partService: IPartService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@IThemeService themeService: IThemeService,
@IStorageService storageService: IStorageService
) {
@@ -155,9 +155,9 @@ export class QuickOpenController extends Component implements IQuickOpenService
}
show(prefix?: string, options?: IShowOptions): Promise<void> {
let quickNavigateConfiguration = options ? options.quickNavigateConfiguration : void 0;
let inputSelection = options ? options.inputSelection : void 0;
let autoFocus = options ? options.autoFocus : void 0;
let quickNavigateConfiguration = options ? options.quickNavigateConfiguration : undefined;
let inputSelection = options ? options.inputSelection : undefined;
let autoFocus = options ? options.autoFocus : undefined;
const promiseCompletedOnHide = new Promise<void>(c => {
this.promisesToCompleteOnHide.push(c);
@@ -452,11 +452,11 @@ export class QuickOpenController extends Component implements IQuickOpenService
const previousInput = this.quickOpenWidget.getInput();
const wasShowingHistory = previousInput && previousInput.entries && previousInput.entries.some(e => e instanceof EditorHistoryEntry || e instanceof EditorHistoryEntryGroup);
if (wasShowingHistory || matchingHistoryEntries.length > 0) {
let responseDelay: Thenable<void>;
let responseDelay: Promise<void>;
if (resolvedHandler.hasShortResponseTime()) {
responseDelay = timeout(QuickOpenController.MAX_SHORT_RESPONSE_TIME);
} else {
responseDelay = Promise.resolve(void 0);
responseDelay = Promise.resolve();
}
responseDelay.then(() => {
@@ -490,8 +490,7 @@ export class QuickOpenController extends Component implements IQuickOpenService
// Remove results already showing by checking for a "resource" property
const mapEntryToResource = this.mapEntriesToResource(quickOpenModel);
const additionalHandlerResults: QuickOpenEntry[] = [];
for (let i = 0; i < handlerResults.length; i++) {
const result = handlerResults[i];
for (const result of handlerResults) {
const resource = result.getResource();
if (!result.mergeWithEditorHistory() || !resource || !mapEntryToResource[resource.toString()]) {
@@ -529,7 +528,7 @@ export class QuickOpenController extends Component implements IQuickOpenService
const model = new QuickOpenModel([new PlaceholderQuickOpenEntry(placeHolderLabel)], this.actionProvider);
this.showModel(model, resolvedHandler.getAutoFocus(value, { model, quickNavigateConfiguration: this.quickOpenWidget.getQuickNavigateConfiguration() }), resolvedHandler.getAriaLabel());
return Promise.resolve(null);
return Promise.resolve(undefined);
}
// Support extra class from handler
@@ -646,9 +645,9 @@ class EditorHistoryHandler {
private scorerCache: ScorerCache;
constructor(
@IHistoryService private historyService: IHistoryService,
@IInstantiationService private instantiationService: IInstantiationService,
@IFileService private fileService: IFileService
@IHistoryService private readonly historyService: IHistoryService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IFileService private readonly fileService: IFileService
) {
this.scorerCache = Object.create(null);
}
@@ -709,7 +708,7 @@ class EditorHistoryItemAccessorClass extends QuickOpenItemAccessorClass {
}
getItemDescription(entry: QuickOpenEntry): string {
return this.allowMatchOnDescription ? entry.getDescription() : void 0;
return this.allowMatchOnDescription ? entry.getDescription() : undefined;
}
}
@@ -730,10 +729,10 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry {
constructor(
input: IEditorInput | IResourceInput,
@IEditorService editorService: IEditorService,
@IModeService private modeService: IModeService,
@IModelService private modelService: IModelService,
@ITextFileService private textFileService: ITextFileService,
@IConfigurationService private configurationService: IConfigurationService,
@IModeService private readonly modeService: IModeService,
@IModelService private readonly modelService: IModelService,
@ITextFileService private readonly textFileService: ITextFileService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ILabelService labelService: ILabelService,
@IFileService fileService: IFileService
) {
@@ -808,7 +807,7 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry {
}
function resourceForEditorHistory(input: EditorInput, fileService: IFileService): URI {
const resource = input ? input.getResource() : void 0;
const resource = input ? input.getResource() : undefined;
// For the editor history we only prefer resources that are either untitled or
// can be handled by the file service which indicates they are editable resources.
@@ -816,7 +815,7 @@ function resourceForEditorHistory(input: EditorInput, fileService: IFileService)
return resource;
}
return void 0;
return undefined;
}
export class RemoveFromEditorHistoryAction extends Action {
@@ -827,16 +826,16 @@ export class RemoveFromEditorHistoryAction extends Action {
constructor(
id: string,
label: string,
@IQuickInputService private quickInputService: IQuickInputService,
@IModelService private modelService: IModelService,
@IModeService private modeService: IModeService,
@IInstantiationService private instantiationService: IInstantiationService,
@IHistoryService private historyService: IHistoryService
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IModelService private readonly modelService: IModelService,
@IModeService private readonly modeService: IModeService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IHistoryService private readonly historyService: IHistoryService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
interface IHistoryPickEntry extends IQuickPickItem {
input: IEditorInput | IResourceInput;
}

View File

@@ -23,7 +23,7 @@ CommandsRegistry.registerCommand(QUICKOPEN_ACTION_ID, function (accessor: Servic
const quickOpenService = accessor.get(IQuickOpenService);
return quickOpenService.show(typeof prefix === 'string' ? prefix : undefined).then(() => {
return void 0;
return undefined;
});
});
@@ -32,7 +32,7 @@ CommandsRegistry.registerCommand(QUICKOPEN_FOCUS_SECONDARY_ACTION_ID, function (
const quickOpenService = accessor.get(IQuickOpenService);
return quickOpenService.show(undefined, { autoFocus: { autoFocusSecondEntry: true } }).then(() => {
return void 0;
return undefined;
});
});
@@ -43,16 +43,16 @@ export class BaseQuickOpenNavigateAction extends Action {
label: string,
private next: boolean,
private quickNavigate: boolean,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IQuickInputService private quickInputService: IQuickInputService,
@IKeybindingService private keybindingService: IKeybindingService
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) {
super(id, label);
}
run(event?: any): Thenable<any> {
run(event?: any): Promise<any> {
const keys = this.keybindingService.lookupKeybindings(this.id);
const quickNavigate = this.quickNavigate ? { keybindings: keys } : void 0;
const quickNavigate = this.quickNavigate ? { keybindings: keys } : undefined;
this.quickOpenService.navigate(this.next, quickNavigate);
this.quickInputService.navigate(this.next, quickNavigate);

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench > .sidebar > .content {
.monaco-workbench .sidebar > .content {
overflow: hidden;
}
@@ -12,7 +12,7 @@
visibility: hidden !important;
}
.monaco-workbench > .sidebar > .title > .title-label h2 {
.monaco-workbench .sidebar > .title > .title-label h2 {
text-transform: uppercase;
}

View File

@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform';
import { Action } from 'vs/base/common/actions';
import { CompositePart } from 'vs/workbench/browser/parts/compositePart';
import { Viewlet, ViewletRegistry, Extensions as ViewletExtensions } from 'vs/workbench/browser/viewlet';
import { Viewlet, ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
@@ -20,25 +20,43 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Event, mapEvent } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { SIDE_BAR_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND, SIDE_BAR_BORDER } from 'vs/workbench/common/theme';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { Dimension, EventType, addDisposableListener, trackFocus } from 'vs/base/browser/dom';
import { EventType, addDisposableListener, trackFocus, Dimension } from 'vs/base/browser/dom';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
import { LayoutPriority } from 'vs/base/browser/ui/grid/gridview';
const SideBarFocusContextId = 'sideBarFocus';
export const SidebarFocusContext = new RawContextKey<boolean>(SideBarFocusContextId, false);
export const SidebarFocusContext = new RawContextKey<boolean>('sideBarFocus', false);
export const ActiveViewletContext = new RawContextKey<string>('activeViewlet', '');
export class SidebarPart extends CompositePart<Viewlet> {
export class SidebarPart extends CompositePart<Viewlet> implements ISerializableView, IViewletService {
_serviceBrand: any;
static readonly activeViewletSettingsKey = 'workbench.sidebar.activeviewletid';
private viewletRegistry: ViewletRegistry;
private sideBarFocusContextKey: IContextKey<boolean>;
private activeViewletContextKey: IContextKey<string>;
private blockOpeningViewlet: boolean;
private _onDidViewletDeregister = this._register(new Emitter<ViewletDescriptor>());
element: HTMLElement;
minimumWidth: number = 170;
maximumWidth: number = Number.POSITIVE_INFINITY;
minimumHeight: number = 0;
maximumHeight: number = Number.POSITIVE_INFINITY;
snapSize: number = 50;
priority: LayoutPriority = LayoutPriority.Low;
private _onDidChange = new Emitter<{ width: number; height: number; }>();
readonly onDidChange = this._onDidChange.event;
constructor(
id: string,
@@ -51,6 +69,7 @@ export class SidebarPart extends CompositePart<Viewlet> {
@IInstantiationService instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService,
@IExtensionService private readonly extensionService: IExtensionService
) {
super(
notificationService,
@@ -72,10 +91,32 @@ export class SidebarPart extends CompositePart<Viewlet> {
);
this.sideBarFocusContextKey = SidebarFocusContext.bindTo(contextKeyService);
this.viewletRegistry = Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets);
this.activeViewletContextKey = ActiveViewletContext.bindTo(contextKeyService);
this._register(this.onDidViewletOpen(viewlet => {
this.activeViewletContextKey.set(viewlet.getId());
}));
this._register(this.onDidViewletClose(viewlet => {
if (this.activeViewletContextKey.get() === viewlet.getId()) {
this.activeViewletContextKey.reset();
}
}));
this._register(this.registry.onDidDeregister(async (viewletDescriptor: ViewletDescriptor) => {
if (this.getActiveViewlet().getId() === viewletDescriptor.id) {
await this.openViewlet(this.getDefaultViewletId());
}
this.removeComposite(viewletDescriptor.id);
this._onDidViewletDeregister.fire(viewletDescriptor);
}));
}
get onDidViewletRegister(): Event<ViewletDescriptor> { return <Event<ViewletDescriptor>>this.viewletRegistry.onDidRegister; }
get onDidViewletDeregister(): Event<ViewletDescriptor> { return this._onDidViewletDeregister.event; }
get onDidViewletOpen(): Event<IViewlet> {
return mapEvent(this._onDidCompositeOpen.event, compositeEvent => <IViewlet>compositeEvent.composite);
return Event.map(this._onDidCompositeOpen.event, compositeEvent => <IViewlet>compositeEvent.composite);
}
get onDidViewletClose(): Event<IViewlet> {
@@ -83,6 +124,8 @@ export class SidebarPart extends CompositePart<Viewlet> {
}
create(parent: HTMLElement): void {
this.element = parent;
super.create(parent);
const focusTracker = trackFocus(parent);
@@ -124,7 +167,65 @@ export class SidebarPart extends CompositePart<Viewlet> {
container.style.borderLeftColor = !isPositionLeft ? borderColor : null;
}
openViewlet(id: string, focus?: boolean): Viewlet {
layout(dimension: Dimension): Dimension[];
layout(width: number, height: number): void;
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
if (!this.partService.isVisible(Parts.SIDEBAR_PART)) {
if (dim1 instanceof Dimension) {
return [dim1];
}
return;
}
if (dim1 instanceof Dimension) {
return super.layout(dim1);
}
super.layout(dim1, dim2!);
}
// Viewlet service
getActiveViewlet(): IViewlet {
return <IViewlet>this.getActiveComposite();
}
getLastActiveViewletId(): string {
return this.getLastActiveCompositetId();
}
hideActiveViewlet(): void {
this.hideActiveComposite();
}
openViewlet(id: string, focus?: boolean): Promise<IViewlet | null> {
if (this.getViewlet(id)) {
return Promise.resolve(this.doOpenViewlet(id, focus));
}
return this.extensionService.whenInstalledExtensionsRegistered()
.then(() => {
if (this.getViewlet(id)) {
return this.doOpenViewlet(id, focus);
}
return null;
});
}
getViewlets(): ViewletDescriptor[] {
return this.viewletRegistry.getViewlets()
.sort((v1, v2) => v1.order! - v2.order!);
}
getDefaultViewletId(): string {
return this.viewletRegistry.getDefaultViewletId();
}
getViewlet(id: string): ViewletDescriptor {
return this.getViewlets().filter(viewlet => viewlet.id === id)[0];
}
private doOpenViewlet(id: string, focus?: boolean): Viewlet | null {
if (this.blockOpeningViewlet) {
return null; // Workaround against a potential race condition
}
@@ -142,26 +243,6 @@ export class SidebarPart extends CompositePart<Viewlet> {
return this.openComposite(id, focus) as Viewlet;
}
getActiveViewlet(): IViewlet {
return <IViewlet>this.getActiveComposite();
}
getLastActiveViewletId(): string {
return this.getLastActiveCompositetId();
}
hideActiveViewlet(): void {
this.hideActiveComposite();
}
layout(dimension: Dimension): Dimension[] {
if (!this.partService.isVisible(Parts.SIDEBAR_PART)) {
return [dimension];
}
return super.layout(dimension);
}
protected getTitleAreaDropDownAnchorAlignment(): AnchorAlignment {
return this.partService.getSideBarPosition() === SideBarPosition.LEFT ? AnchorAlignment.LEFT : AnchorAlignment.RIGHT;
}
@@ -181,6 +262,12 @@ export class SidebarPart extends CompositePart<Viewlet> {
}
}
}
toJSON(): object {
return {
type: Parts.SIDEBAR_PART
};
}
}
class FocusSideBarAction extends Action {
@@ -191,13 +278,13 @@ class FocusSideBarAction extends Action {
constructor(
id: string,
label: string,
@IViewletService private viewletService: IViewletService,
@IPartService private partService: IPartService
@IViewletService private readonly viewletService: IViewletService,
@IPartService private readonly partService: IPartService
) {
super(id, label);
}
run(): Thenable<any> {
run(): Promise<any> {
// Show side bar
if (!this.partService.isVisible(Parts.SIDEBAR_PART)) {

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench > .part.statusbar {
.monaco-workbench .part.statusbar {
box-sizing: border-box;
cursor: default;
width: 100%;
@@ -11,18 +11,18 @@
font-size: 12px;
}
.monaco-workbench > .part.statusbar > .statusbar-item {
.monaco-workbench .part.statusbar > .statusbar-item {
display: inline-block;
line-height: 22px;
height: 100%;
vertical-align: top;
}
.monaco-workbench > .part.statusbar > .statusbar-item.has-beak {
.monaco-workbench .part.statusbar > .statusbar-item.has-beak {
position: relative;
}
.monaco-workbench > .part.statusbar > .statusbar-item.has-beak:before {
.monaco-workbench .part.statusbar > .statusbar-item.has-beak:before {
content: '';
position: absolute;
left: 11px;
@@ -33,48 +33,48 @@
border-right: 5px solid transparent;
}
.monaco-workbench > .part.statusbar > .statusbar-item.left > :first-child {
.monaco-workbench .part.statusbar > .statusbar-item.left > :first-child {
margin-right: 5px;
}
.monaco-workbench > .part.statusbar > .statusbar-item.right {
.monaco-workbench .part.statusbar > .statusbar-item.right {
float: right;
}
.monaco-workbench > .part.statusbar > .statusbar-item.right > :first-child {
.monaco-workbench .part.statusbar > .statusbar-item.right > :first-child {
margin-left: 5px;
}
/* adding padding to the most left status bar item */
.monaco-workbench > .part.statusbar > .statusbar-item.left:first-child, .monaco-workbench > .part.statusbar > .statusbar-item.right + .statusbar-item.left {
.monaco-workbench .part.statusbar > .statusbar-item.left:first-child, .monaco-workbench .part.statusbar > .statusbar-item.right + .statusbar-item.left {
padding-left: 10px;
}
/* adding padding to the most right status bar item */
.monaco-workbench > .part.statusbar > .statusbar-item.right:first-child {
.monaco-workbench .part.statusbar > .statusbar-item.right:first-child {
padding-right: 10px;
}
.monaco-workbench > .part.statusbar > .statusbar-item a {
.monaco-workbench .part.statusbar > .statusbar-item a {
cursor: pointer;
display: inline-block;
height: 100%;
}
.monaco-workbench > .part.statusbar > .statusbar-entry > span {
.monaco-workbench .part.statusbar > .statusbar-entry > span {
height: 100%;
}
.monaco-workbench > .part.statusbar > .statusbar-entry > span,
.monaco-workbench > .part.statusbar > .statusbar-entry > a {
.monaco-workbench .part.statusbar > .statusbar-entry > span,
.monaco-workbench .part.statusbar > .statusbar-entry > a {
padding: 0 5px 0 5px;
white-space: pre; /* gives some degree of styling */
}
.monaco-workbench > .part.statusbar > .statusbar-entry span.octicon {
.monaco-workbench .part.statusbar > .statusbar-entry span.octicon {
text-align: center;
font-size: 14px;
}
.monaco-workbench > .part.statusbar > .statusbar-item a:hover {
.monaco-workbench .part.statusbar > .statusbar-item a:hover {
text-decoration: none;
}

View File

@@ -24,27 +24,39 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { isThemeColor } from 'vs/editor/common/editorCommon';
import { Color } from 'vs/base/common/color';
import { addClass, EventHelper, createStyleSheet, addDisposableListener } from 'vs/base/browser/dom';
import { addClass, EventHelper, createStyleSheet, addDisposableListener, Dimension } from 'vs/base/browser/dom';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { Emitter } from 'vs/base/common/event';
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
import { Parts } from 'vs/workbench/services/part/common/partService';
export class StatusbarPart extends Part implements IStatusbarService {
export class StatusbarPart extends Part implements IStatusbarService, ISerializableView {
_serviceBrand: any;
private static readonly PRIORITY_PROP = 'statusbar-entry-priority';
private static readonly ALIGNMENT_PROP = 'statusbar-entry-alignment';
private statusItemsContainer: HTMLElement;
element: HTMLElement;
private statusMsgDispose: IDisposable;
minimumWidth: number = 0;
maximumWidth: number = Number.POSITIVE_INFINITY;
minimumHeight: number = 22;
maximumHeight: number = 22;
private _onDidChange = new Emitter<{ width: number; height: number; }>();
readonly onDidChange = this._onDidChange.event;
private styleElement: HTMLStyleElement;
constructor(
id: string,
@IInstantiationService private instantiationService: IInstantiationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IStorageService storageService: IStorageService
) {
super(id, { hasTitle: false }, themeService, storageService);
@@ -59,16 +71,15 @@ export class StatusbarPart extends Part implements IStatusbarService {
addEntry(entry: IStatusbarEntry, alignment: StatusbarAlignment, priority: number = 0): IDisposable {
// Render entry in status bar
const el = this.doCreateStatusItem(alignment, priority, entry.showBeak ? 'has-beak' : void 0);
const el = this.doCreateStatusItem(alignment, priority, entry.showBeak ? 'has-beak' : undefined);
const item = this.instantiationService.createInstance(StatusBarEntryItem, entry);
const toDispose = item.render(el);
// Insert according to priority
const container = this.statusItemsContainer;
const container = this.element;
const neighbours = this.getEntries(alignment);
let inserted = false;
for (let i = 0; i < neighbours.length; i++) {
const neighbour = neighbours[i];
for (const neighbour of neighbours) {
const nPriority = Number(neighbour.getAttribute(StatusbarPart.PRIORITY_PROP));
if (
alignment === StatusbarAlignment.LEFT && nPriority < priority ||
@@ -96,7 +107,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
private getEntries(alignment: StatusbarAlignment): HTMLElement[] {
const entries: HTMLElement[] = [];
const container = this.statusItemsContainer;
const container = this.element;
const children = container.children;
for (let i = 0; i < children.length; i++) {
const childElement = <HTMLElement>children.item(i);
@@ -109,7 +120,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
}
createContentArea(parent: HTMLElement): HTMLElement {
this.statusItemsContainer = parent;
this.element = parent;
// Fill in initial items that were contributed from the registry
const registry = Registry.as<IStatusbarRegistry>(Extensions.Statusbar);
@@ -135,10 +146,10 @@ export class StatusbarPart extends Part implements IStatusbarService {
const el = this.doCreateStatusItem(descriptor.alignment, descriptor.priority);
this._register(item.render(el));
this.statusItemsContainer.appendChild(el);
this.element.appendChild(el);
}
return this.statusItemsContainer;
return this.element;
}
protected updateStyles(): void {
@@ -162,7 +173,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
this.styleElement = createStyleSheet(container);
}
this.styleElement.innerHTML = `.monaco-workbench > .part.statusbar > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`;
this.styleElement.innerHTML = `.monaco-workbench .part.statusbar > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`;
}
private doCreateStatusItem(alignment: StatusbarAlignment, priority: number = 0, extraClass?: string): HTMLElement {
@@ -191,7 +202,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
// Create new
let statusDispose: IDisposable;
let showHandle = setTimeout(() => {
let showHandle: any = setTimeout(() => {
statusDispose = this.addEntry({ text: message }, StatusbarAlignment.LEFT, -Number.MAX_VALUE /* far right on left hand side */);
showHandle = null;
}, delayBy);
@@ -221,6 +232,22 @@ export class StatusbarPart extends Part implements IStatusbarService {
return dispose;
}
layout(dimension: Dimension): Dimension[];
layout(width: number, height: number): void;
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
if (dim1 instanceof Dimension) {
return super.layout(dim1);
} else {
super.layout(new Dimension(dim1, dim2!));
}
}
toJSON(): object {
return {
type: Parts.STATUSBAR_PART
};
}
}
let manageExtensionAction: ManageExtensionAction;
@@ -228,13 +255,13 @@ class StatusBarEntryItem implements IStatusbarItem {
constructor(
private entry: IStatusbarEntry,
@ICommandService private commandService: ICommandService,
@IInstantiationService private instantiationService: IInstantiationService,
@INotificationService private notificationService: INotificationService,
@ITelemetryService private telemetryService: ITelemetryService,
@IContextMenuService private contextMenuService: IContextMenuService,
@IEditorService private editorService: IEditorService,
@IThemeService private themeService: IThemeService
@ICommandService private readonly commandService: ICommandService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@INotificationService private readonly notificationService: INotificationService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IEditorService private readonly editorService: IEditorService,
@IThemeService private readonly themeService: IThemeService
) {
this.entry = entry;
@@ -252,7 +279,7 @@ class StatusBarEntryItem implements IStatusbarItem {
if (this.entry.command) {
textContainer = document.createElement('a');
toDispose.push(addDisposableListener(textContainer, 'click', () => this.executeCommand(this.entry.command, this.entry.arguments)));
toDispose.push(addDisposableListener(textContainer, 'click', () => this.executeCommand(this.entry.command!, this.entry.arguments)));
} else {
textContainer = document.createElement('span');
}
@@ -286,7 +313,7 @@ class StatusBarEntryItem implements IStatusbarItem {
this.contextMenuService.showContextMenu({
getAnchor: () => el,
getActionsContext: () => this.entry.extensionId,
getActionsContext: () => this.entry.extensionId!.value,
getActions: () => [manageExtensionAction]
});
}));
@@ -324,12 +351,12 @@ class StatusBarEntryItem implements IStatusbarItem {
class ManageExtensionAction extends Action {
constructor(
@ICommandService private commandService: ICommandService
@ICommandService private readonly commandService: ICommandService
) {
super('statusbar.manage.extension', nls.localize('manageExtension', "Manage Extension"));
}
run(extensionId: string): Thenable<any> {
run(extensionId: string): Promise<any> {
return this.commandService.executeCommand('_extensions.manage', extensionId);
}
}
@@ -337,21 +364,21 @@ class ManageExtensionAction extends Action {
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND);
if (statusBarItemHoverBackground) {
collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`);
collector.addRule(`.monaco-workbench .part.statusbar > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`);
}
const statusBarItemActiveBackground = theme.getColor(STATUS_BAR_ITEM_ACTIVE_BACKGROUND);
if (statusBarItemActiveBackground) {
collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a:active { background-color: ${statusBarItemActiveBackground}; }`);
collector.addRule(`.monaco-workbench .part.statusbar > .statusbar-item a:active { background-color: ${statusBarItemActiveBackground}; }`);
}
const statusBarProminentItemBackground = theme.getColor(STATUS_BAR_PROMINENT_ITEM_BACKGROUND);
if (statusBarProminentItemBackground) {
collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item .status-bar-info { background-color: ${statusBarProminentItemBackground}; }`);
collector.addRule(`.monaco-workbench .part.statusbar > .statusbar-item .status-bar-info { background-color: ${statusBarProminentItemBackground}; }`);
}
const statusBarProminentItemHoverBackground = theme.getColor(STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND);
if (statusBarProminentItemHoverBackground) {
collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a.status-bar-info:hover { background-color: ${statusBarProminentItemHoverBackground}; }`);
collector.addRule(`.monaco-workbench .part.statusbar > .statusbar-item a.status-bar-info:hover { background-color: ${statusBarProminentItemHoverBackground}; }`);
}
});

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench > .part.titlebar {
.monaco-workbench .part.titlebar {
box-sizing: border-box;
width: 100%;
padding: 0 70px;
@@ -18,7 +18,7 @@
display: flex;
}
.monaco-workbench > .part.titlebar > .titlebar-drag-region {
.monaco-workbench .part.titlebar > .titlebar-drag-region {
top: 0;
left: 0;
display: block;
@@ -29,7 +29,7 @@
-webkit-app-region: drag;
}
.monaco-workbench > .part.titlebar > .window-title {
.monaco-workbench .part.titlebar > .window-title {
flex: 0 1 auto;
font-size: 12px;
overflow: hidden;
@@ -42,8 +42,8 @@
/* Windows/Linux: Rules for custom title (icon, window controls) */
.monaco-workbench.windows > .part.titlebar,
.monaco-workbench.linux > .part.titlebar {
.windows > .monaco-workbench .part.titlebar,
.linux > .monaco-workbench .part.titlebar {
padding: 0;
height: 30px;
line-height: 30px;
@@ -51,17 +51,17 @@
overflow: visible;
}
.monaco-workbench.windows > .part.titlebar > .window-title,
.monaco-workbench.linux > .part.titlebar > .window-title {
.windows > .monaco-workbench .part.titlebar > .window-title,
.linux > .monaco-workbench .part.titlebar > .window-title {
cursor: default;
}
.monaco-workbench.linux > .part.titlebar > .window-title {
.linux > .monaco-workbench .part.titlebar > .window-title {
font-size: inherit;
}
.monaco-workbench.windows > .part.titlebar > .resizer,
.monaco-workbench.linux > .part.titlebar > .resizer {
.windows > .monaco-workbench .part.titlebar > .resizer,
.linux > .monaco-workbench .part.titlebar > .resizer {
-webkit-app-region: no-drag;
position: absolute;
top: 0;
@@ -69,13 +69,13 @@
height: 20%;
}
.monaco-workbench.windows.fullscreen > .part.titlebar > .resizer,
.monaco-workbench.linux.fullscreen > .part.titlebar > .resizer {
.windows > .monaco-workbench.fullscreen .part.titlebar > .resizer,
.linux > .monaco-workbench.fullscreen .part.titlebar > .resizer {
display: none;
}
.monaco-workbench > .part.titlebar > .window-appicon {
.monaco-workbench .part.titlebar > .window-appicon {
width: 35px;
height: 100%;
position: relative;
@@ -87,11 +87,11 @@
flex-shrink: 0;
}
.monaco-workbench.fullscreen > .part.titlebar > .window-appicon {
.monaco-workbench.fullscreen .part.titlebar > .window-appicon {
display: none;
}
.monaco-workbench > .part.titlebar > .window-controls-container {
.monaco-workbench .part.titlebar > .window-controls-container {
display: flex;
flex-grow: 0;
flex-shrink: 0;
@@ -104,56 +104,56 @@
margin-left: auto;
}
.monaco-workbench.fullscreen > .part.titlebar > .window-controls-container {
.monaco-workbench.fullscreen .part.titlebar > .window-controls-container {
display: none;
}
.monaco-workbench > .part.titlebar > .window-controls-container > .window-icon-bg {
.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg {
display: inline-block;
-webkit-app-region: no-drag;
height: 100%;
width: 33.34%;
}
.monaco-workbench > .part.titlebar > .window-controls-container .window-icon svg {
.monaco-workbench .part.titlebar > .window-controls-container .window-icon svg {
shape-rendering: crispEdges;
text-align: center;
}
.monaco-workbench > .part.titlebar.titlebar > .window-controls-container .window-close {
.monaco-workbench .part.titlebar.titlebar > .window-controls-container .window-close {
-webkit-mask: url('chrome-close.svg') no-repeat 50% 50%;
}
.monaco-workbench > .part.titlebar.titlebar > .window-controls-container .window-unmaximize {
.monaco-workbench .part.titlebar.titlebar > .window-controls-container .window-unmaximize {
-webkit-mask: url('chrome-restore.svg') no-repeat 50% 50%;
}
.monaco-workbench > .part.titlebar > .window-controls-container .window-maximize {
.monaco-workbench .part.titlebar > .window-controls-container .window-maximize {
-webkit-mask: url('chrome-maximize.svg') no-repeat 50% 50%;
}
.monaco-workbench > .part.titlebar > .window-controls-container .window-minimize {
.monaco-workbench .part.titlebar > .window-controls-container .window-minimize {
-webkit-mask: url('chrome-minimize.svg') no-repeat 50% 50%;
}
.monaco-workbench > .part.titlebar > .window-controls-container > .window-icon-bg > .window-icon {
.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg > .window-icon {
height: 100%;
width: 100%;
-webkit-mask-size: 23.1%;
}
.monaco-workbench > .part.titlebar > .window-controls-container > .window-icon-bg:hover {
.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.monaco-workbench > .part.titlebar.light > .window-controls-container > .window-icon-bg:hover {
.monaco-workbench .part.titlebar.light > .window-controls-container > .window-icon-bg:hover {
background-color: rgba(0, 0, 0, 0.1);
}
.monaco-workbench > .part.titlebar > .window-controls-container > .window-icon-bg.window-close-bg:hover {
.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg.window-close-bg:hover {
background-color: rgba(232, 17, 35, 0.9);
}
.monaco-workbench > .part.titlebar > .window-controls-container .window-icon.window-close:hover {
.monaco-workbench .part.titlebar > .window-controls-container .window-icon.window-close:hover {
background-color: white;
}
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { IMenubarMenu, IMenubarMenuItemAction, IMenubarMenuItemSubmenu, IMenubarKeybinding, IMenubarService, IMenubarData } from 'vs/platform/menubar/common/menubar';
import { IMenubarMenu, IMenubarMenuItemAction, IMenubarMenuItemSubmenu, IMenubarKeybinding, IMenubarService, IMenubarData, MenubarMenuItem } from 'vs/platform/menubar/common/menubar';
import { IMenuService, MenuId, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions';
import { registerThemingParticipant, ITheme, ICssStyleCollector, IThemeService } from 'vs/platform/theme/common/themeService';
import { IWindowService, MenuBarVisibility, IWindowsService, getTitleBarStyle } from 'vs/platform/windows/common/windows';
@@ -31,6 +31,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { MenuBar } from 'vs/base/browser/ui/menu/menubar';
import { SubmenuAction } from 'vs/base/browser/ui/menu/menu';
import { attachMenuStyler } from 'vs/platform/theme/common/styler';
import { assign } from 'vs/base/common/objects';
export class MenubarControl extends Disposable {
@@ -45,27 +46,29 @@ export class MenubarControl extends Disposable {
'window.nativeTabs'
];
// {{SQL CARBON EDIT}} - Disable unusued menus
private topLevelMenus: {
'File': IMenu;
'Edit': IMenu;
'Selection': IMenu;
// 'Selection': IMenu;
'View': IMenu;
'Go': IMenu;
'Debug': IMenu;
'Terminal': IMenu;
// 'Go': IMenu;
// 'Debug': IMenu;
// 'Terminal': IMenu;
'Window'?: IMenu;
'Help': IMenu;
[index: string]: IMenu;
// [index: string]: IMenu;
};
// {{SQL CARBON EDIT}} - Disable unused menus
private topLevelTitles = {
'File': nls.localize({ key: 'mFile', comment: ['&& denotes a mnemonic'] }, "&&File"),
'Edit': nls.localize({ key: 'mEdit', comment: ['&& denotes a mnemonic'] }, "&&Edit"),
'Selection': nls.localize({ key: 'mSelection', comment: ['&& denotes a mnemonic'] }, "&&Selection"),
// 'Selection': nls.localize({ key: 'mSelection', comment: ['&& denotes a mnemonic'] }, "&&Selection"),
'View': nls.localize({ key: 'mView', comment: ['&& denotes a mnemonic'] }, "&&View"),
'Go': nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Go"),
'Debug': nls.localize({ key: 'mDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug"),
'Terminal': nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal"),
// 'Go': nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Go"),
// 'Debug': nls.localize({ key: 'mDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug"),
// 'Terminal': nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal"),
'Help': nls.localize({ key: 'mHelp', comment: ['&& denotes a mnemonic'] }, "&&Help")
};
@@ -80,32 +83,33 @@ export class MenubarControl extends Disposable {
private static MAX_MENU_RECENT_ENTRIES = 10;
constructor(
@IThemeService private themeService: IThemeService,
@IMenubarService private menubarService: IMenubarService,
@IMenuService private menuService: IMenuService,
@IWindowService private windowService: IWindowService,
@IWindowsService private windowsService: IWindowsService,
@IContextKeyService private contextKeyService: IContextKeyService,
@IKeybindingService private keybindingService: IKeybindingService,
@IConfigurationService private configurationService: IConfigurationService,
@ILabelService private labelService: ILabelService,
@IUpdateService private updateService: IUpdateService,
@IStorageService private storageService: IStorageService,
@INotificationService private notificationService: INotificationService,
@IPreferencesService private preferencesService: IPreferencesService,
@IEnvironmentService private environmentService: IEnvironmentService
@IThemeService private readonly themeService: IThemeService,
@IMenubarService private readonly menubarService: IMenubarService,
@IMenuService private readonly menuService: IMenuService,
@IWindowService private readonly windowService: IWindowService,
@IWindowsService private readonly windowsService: IWindowsService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ILabelService private readonly labelService: ILabelService,
@IUpdateService private readonly updateService: IUpdateService,
@IStorageService private readonly storageService: IStorageService,
@INotificationService private readonly notificationService: INotificationService,
@IPreferencesService private readonly preferencesService: IPreferencesService,
@IEnvironmentService private readonly environmentService: IEnvironmentService
) {
super();
// {{SQL CARBON EDIT}} - Disable unused menus
this.topLevelMenus = {
'File': this._register(this.menuService.createMenu(MenuId.MenubarFileMenu, this.contextKeyService)),
'Edit': this._register(this.menuService.createMenu(MenuId.MenubarEditMenu, this.contextKeyService)),
'Selection': this._register(this.menuService.createMenu(MenuId.MenubarSelectionMenu, this.contextKeyService)),
// 'Selection': this._register(this.menuService.createMenu(MenuId.MenubarSelectionMenu, this.contextKeyService)),
'View': this._register(this.menuService.createMenu(MenuId.MenubarViewMenu, this.contextKeyService)),
'Go': this._register(this.menuService.createMenu(MenuId.MenubarGoMenu, this.contextKeyService)),
'Debug': this._register(this.menuService.createMenu(MenuId.MenubarDebugMenu, this.contextKeyService)),
'Terminal': this._register(this.menuService.createMenu(MenuId.MenubarTerminalMenu, this.contextKeyService)),
// 'Go': this._register(this.menuService.createMenu(MenuId.MenubarGoMenu, this.contextKeyService)),
// 'Debug': this._register(this.menuService.createMenu(MenuId.MenubarDebugMenu, this.contextKeyService)),
// 'Terminal': this._register(this.menuService.createMenu(MenuId.MenubarTerminalMenu, this.contextKeyService)),
'Help': this._register(this.menuService.createMenu(MenuId.MenubarHelpMenu, this.contextKeyService))
};
@@ -263,6 +267,9 @@ export class MenubarControl extends Disposable {
this.menubar.blur();
}));
}
// Update recent menu items on formatter registration
this._register(this.labelService.onDidChangeFormatters(() => { this.onRecentlyOpenedChange(); }));
}
private doUpdateMenubar(firstTime: boolean): void {
@@ -315,7 +322,7 @@ export class MenubarControl extends Disposable {
return label;
}
private createOpenRecentMenuAction(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI, commandId: string, isFile: boolean): IAction {
private createOpenRecentMenuAction(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI, commandId: string, isFile: boolean): IAction & { uri: URI } {
let label: string;
let uri: URI;
@@ -331,7 +338,7 @@ export class MenubarControl extends Disposable {
label = this.labelService.getUriLabel(uri);
}
return new Action(commandId, label, undefined, undefined, (event) => {
const ret: IAction = new Action(commandId, label, undefined, undefined, (event) => {
const openInNewWindow = event && ((!isMacintosh && (event.ctrlKey || event.shiftKey)) || (isMacintosh && (event.metaKey || event.altKey)));
return this.windowService.openWindow([uri], {
@@ -339,8 +346,11 @@ export class MenubarControl extends Disposable {
forceOpenWorkspaceAsFile: isFile
});
});
return assign(ret, { uri: uri });
}
/* Custom Menu takes actions */
private getOpenRecentActions(): IAction[] {
if (!this.recentlyOpened) {
return [];
@@ -369,6 +379,19 @@ export class MenubarControl extends Disposable {
return result;
}
private transformOpenRecentAction(action: Separator | (IAction & { uri: URI })): MenubarMenuItem {
if (action instanceof Separator) {
return { id: 'vscode.menubar.separator' };
}
return {
id: action.id,
uri: action.uri,
enabled: action.enabled,
label: action.label
};
}
private getUpdateAction(): IAction | null {
const state = this.updateService.state;
@@ -501,13 +524,13 @@ export class MenubarControl extends Disposable {
// first try to resolve a native accelerator
const electronAccelerator = binding.getElectronAccelerator();
if (electronAccelerator) {
return { label: electronAccelerator };
return { label: electronAccelerator, userSettingsLabel: binding.getUserSettingsLabel() };
}
// we need this fallback to support keybindings that cannot show in electron menus (e.g. chords)
const acceleratorLabel = binding.getLabel();
if (acceleratorLabel) {
return { label: acceleratorLabel, isNative: false };
return { label: acceleratorLabel, isNative: false, userSettingsLabel: binding.getUserSettingsLabel() };
}
return null;
@@ -534,6 +557,11 @@ export class MenubarControl extends Disposable {
menuToPopulate.items.push(menubarSubmenuItem);
menuToDispose.dispose();
} else {
if (menuItem.id === 'workbench.action.openRecent') {
const actions = this.getOpenRecentActions().map(this.transformOpenRecentAction);
menuToPopulate.items.push(...actions);
}
let menubarMenuItem: IMenubarMenuItemAction = {
id: menuItem.id,
label: menuItem.label

View File

@@ -5,6 +5,7 @@
import 'vs/css!./media/titlebarpart';
import * as paths from 'vs/base/common/paths';
import * as resources from 'vs/base/common/resources';
import { Part } from 'vs/workbench/browser/part';
import { ITitleService, ITitleProperties } from 'vs/workbench/services/title/common/titleService';
import { getZoomFactor } from 'vs/base/browser/browser';
@@ -25,15 +26,17 @@ import { isMacintosh, isWindows, isLinux } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { Color } from 'vs/base/common/color';
import { trim } from 'vs/base/common/strings';
import { EventType, EventHelper, Dimension, isAncestor, hide, show, removeClass, addClass, append, $, addDisposableListener } from 'vs/base/browser/dom';
import { EventType, EventHelper, Dimension, isAncestor, hide, show, removeClass, addClass, append, $, addDisposableListener, runAtThisOrScheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
import { MenubarControl } from 'vs/workbench/browser/parts/titlebar/menubarControl';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { template, getBaseLabel } from 'vs/base/common/labels';
import { ILabelService } from 'vs/platform/label/common/label';
import { Event } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
import { Parts } from 'vs/workbench/services/part/common/partService';
export class TitlebarPart extends Part implements ITitleService {
export class TitlebarPart extends Part implements ITitleService, ISerializableView {
_serviceBrand: any;
@@ -43,7 +46,7 @@ export class TitlebarPart extends Part implements ITitleService {
private static readonly TITLE_DIRTY = '\u25cf ';
private static readonly TITLE_SEPARATOR = isMacintosh ? ' — ' : ' - '; // macOS uses special - separator
private titleContainer: HTMLElement;
element: HTMLElement;
private title: HTMLElement;
private dragRegion: HTMLElement;
private windowControls: HTMLElement;
@@ -61,18 +64,26 @@ export class TitlebarPart extends Part implements ITitleService {
private properties: ITitleProperties;
private activeEditorListeners: IDisposable[];
minimumWidth: number = 0;
maximumWidth: number = Number.POSITIVE_INFINITY;
get minimumHeight(): number { return isMacintosh ? 22 / getZoomFactor() : (30 / (this.configurationService.getValue<MenuBarVisibility>('window.menuBarVisibility') === 'hidden' ? getZoomFactor() : 1)); }
get maximumHeight(): number { return isMacintosh ? 22 / getZoomFactor() : (30 / (this.configurationService.getValue<MenuBarVisibility>('window.menuBarVisibility') === 'hidden' ? getZoomFactor() : 1)); }
private _onDidChange = new Emitter<{ width: number; height: number; }>();
readonly onDidChange = this._onDidChange.event;
constructor(
id: string,
@IContextMenuService private contextMenuService: IContextMenuService,
@IWindowService private windowService: IWindowService,
@IConfigurationService private configurationService: IConfigurationService,
@IWindowsService private windowsService: IWindowsService,
@IEditorService private editorService: IEditorService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IInstantiationService private instantiationService: IInstantiationService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IWindowService private readonly windowService: IWindowService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWindowsService private readonly windowsService: IWindowsService,
@IEditorService private readonly editorService: IEditorService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@ILabelService private labelService: ILabelService,
@ILabelService private readonly labelService: ILabelService,
@IStorageService storageService: IStorageService
) {
super(id, { hasTitle: false }, themeService, storageService);
@@ -90,7 +101,7 @@ export class TitlebarPart extends Part implements ITitleService {
this._register(this.contextService.onDidChangeWorkspaceFolders(() => this.doUpdateTitle()));
this._register(this.contextService.onDidChangeWorkbenchState(() => this.doUpdateTitle()));
this._register(this.contextService.onDidChangeWorkspaceName(() => this.doUpdateTitle()));
this._register(this.labelService.onDidRegisterFormatter(() => this.doUpdateTitle()));
this._register(this.labelService.onDidChangeFormatters(() => this.doUpdateTitle()));
}
private onBlur(): void {
@@ -107,6 +118,12 @@ export class TitlebarPart extends Part implements ITitleService {
if (event.affectsConfiguration('window.title')) {
this.doUpdateTitle();
}
if (event.affectsConfiguration('window.doubleClickIconToClose')) {
if (this.appIcon) {
this.onUpdateAppIconDragBehavior();
}
}
}
private onMenubarVisibilityChanged(visible: boolean) {
@@ -184,7 +201,7 @@ export class TitlebarPart extends Part implements ITitleService {
this.pendingTitle = title;
}
if (isWindows || isLinux) {
if ((isWindows || isLinux) && this.title) {
this.adjustTitleMarginToCenter();
}
}
@@ -222,21 +239,25 @@ export class TitlebarPart extends Part implements ITitleService {
/**
* Possible template values:
*
* {activeEditorLong}: e.g. /Users/Development/myProject/myFolder/myFile.txt
* {activeEditorMedium}: e.g. myFolder/myFile.txt
* {activeEditorLong}: e.g. /Users/Development/myFolder/myFileFolder/myFile.txt
* {activeEditorMedium}: e.g. myFolder/myFileFolder/myFile.txt
* {activeEditorShort}: e.g. myFile.txt
* {activeFolderLong}: e.g. /Users/Development/myFolder/myFileFolder
* {activeFolderMedium}: e.g. myFolder/myFileFolder
* {activeFolderShort}: e.g. myFileFolder
* {rootName}: e.g. myFolder1, myFolder2, myFolder3
* {rootPath}: e.g. /Users/Development/myProject
* {rootPath}: e.g. /Users/Development
* {folderName}: e.g. myFolder
* {folderPath}: e.g. /Users/Development/myFolder
* {appName}: e.g. VS Code
* {dirty}: indiactor
* {dirty}: indicator
* {separator}: conditional separator
*/
private doGetWindowTitle(): string {
const editor = this.editorService.activeEditor;
const workspace = this.contextService.getWorkspace();
// Compute root
let root: URI;
if (workspace.configuration) {
root = workspace.configuration;
@@ -244,15 +265,25 @@ export class TitlebarPart extends Part implements ITitleService {
root = workspace.folders[0].uri;
}
// Compute active editor folder
const editorResource = editor ? toResource(editor) : undefined;
let editorFolderResource = editorResource ? resources.dirname(editorResource) : undefined;
if (editorFolderResource && editorFolderResource.path === '.') {
editorFolderResource = undefined;
}
// Compute folder resource
// Single Root Workspace: always the root single workspace in this case
// Otherwise: root folder of the currently active file if any
let folder = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.folders[0] : this.contextService.getWorkspaceFolder(toResource(editor, { supportSideBySide: true }));
const folder = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.folders[0] : this.contextService.getWorkspaceFolder(toResource(editor, { supportSideBySide: true }));
// Variables
const activeEditorShort = editor ? editor.getTitle(Verbosity.SHORT) : '';
const activeEditorMedium = editor ? editor.getTitle(Verbosity.MEDIUM) : activeEditorShort;
const activeEditorLong = editor ? editor.getTitle(Verbosity.LONG) : activeEditorMedium;
const activeFolderShort = editorFolderResource ? resources.basename(editorFolderResource) : '';
const activeFolderMedium = editorFolderResource ? this.labelService.getUriLabel(editorFolderResource, { relative: true }) : '';
const activeFolderLong = editorFolderResource ? this.labelService.getUriLabel(editorFolderResource) : '';
const rootName = this.labelService.getWorkspaceLabel(workspace);
const rootPath = root ? this.labelService.getUriLabel(root) : '';
const folderName = folder ? folder.name : '';
@@ -266,6 +297,9 @@ export class TitlebarPart extends Part implements ITitleService {
activeEditorShort,
activeEditorLong,
activeEditorMedium,
activeFolderShort,
activeFolderMedium,
activeFolderLong,
rootName,
rootPath,
folderName,
@@ -277,19 +311,24 @@ export class TitlebarPart extends Part implements ITitleService {
}
createContentArea(parent: HTMLElement): HTMLElement {
this.titleContainer = parent;
this.element = parent;
// Draggable region that we can manipulate for #52522
this.dragRegion = append(this.titleContainer, $('div.titlebar-drag-region'));
this.dragRegion = append(this.element, $('div.titlebar-drag-region'));
// App Icon (Windows/Linux)
if (!isMacintosh) {
this.appIcon = append(this.titleContainer, $('div.window-appicon'));
this.appIcon = append(this.element, $('div.window-appicon'));
this.onUpdateAppIconDragBehavior();
this._register(addDisposableListener(this.appIcon, EventType.DBLCLICK, (e => {
this.windowService.closeWindow();
})));
}
// Menubar: the menubar part which is responsible for populating both the custom and native menubars
this.menubarPart = this.instantiationService.createInstance(MenubarControl);
this.menubar = append(this.titleContainer, $('div.menubar'));
this.menubar = append(this.element, $('div.menubar'));
this.menubar.setAttribute('role', 'menubar');
this.menubarPart.create(this.menubar);
@@ -300,7 +339,7 @@ export class TitlebarPart extends Part implements ITitleService {
}
// Title
this.title = append(this.titleContainer, $('div.window-title'));
this.title = append(this.element, $('div.window-title'));
if (this.pendingTitle) {
this.title.innerText = this.pendingTitle;
} else {
@@ -309,7 +348,7 @@ export class TitlebarPart extends Part implements ITitleService {
// Maximize/Restore on doubleclick
if (isMacintosh) {
this._register(addDisposableListener(this.titleContainer, EventType.DBLCLICK, e => {
this._register(addDisposableListener(this.element, EventType.DBLCLICK, e => {
EventHelper.stop(e);
this.onTitleDoubleclick();
@@ -329,7 +368,7 @@ export class TitlebarPart extends Part implements ITitleService {
// Window Controls (Windows/Linux)
if (!isMacintosh) {
this.windowControls = append(this.titleContainer, $('div.window-controls-container'));
this.windowControls = append(this.element, $('div.window-controls-container'));
// Minimize
@@ -364,7 +403,7 @@ export class TitlebarPart extends Part implements ITitleService {
}));
// Resizer
this.resizer = append(this.titleContainer, $('div.resizer'));
this.resizer = append(this.element, $('div.resizer'));
const isMaximized = this.windowService.getConfiguration().maximized ? true : false;
this.onDidChangeMaximized(isMaximized);
@@ -373,7 +412,7 @@ export class TitlebarPart extends Part implements ITitleService {
// Since the title area is used to drag the window, we do not want to steal focus from the
// currently active element. So we restore focus after a timeout back to where it was.
this._register(addDisposableListener(this.titleContainer, EventType.MOUSE_DOWN, e => {
this._register(addDisposableListener(this.element, EventType.MOUSE_DOWN, e => {
if (e.target && isAncestor(e.target as HTMLElement, this.menubar)) {
return;
}
@@ -388,7 +427,7 @@ export class TitlebarPart extends Part implements ITitleService {
this.updateStyles();
return this.titleContainer;
return this.element;
}
private onDidChangeMaximized(maximized: boolean) {
@@ -417,26 +456,26 @@ export class TitlebarPart extends Part implements ITitleService {
super.updateStyles();
// Part container
if (this.titleContainer) {
if (this.element) {
if (this.isInactive) {
addClass(this.titleContainer, 'inactive');
addClass(this.element, 'inactive');
} else {
removeClass(this.titleContainer, 'inactive');
removeClass(this.element, 'inactive');
}
const titleBackground = this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_BACKGROUND : TITLE_BAR_ACTIVE_BACKGROUND);
this.titleContainer.style.backgroundColor = titleBackground;
this.element.style.backgroundColor = titleBackground;
if (Color.fromHex(titleBackground).isLighter()) {
addClass(this.titleContainer, 'light');
addClass(this.element, 'light');
} else {
removeClass(this.titleContainer, 'light');
removeClass(this.element, 'light');
}
const titleForeground = this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_FOREGROUND : TITLE_BAR_ACTIVE_FOREGROUND);
this.titleContainer.style.color = titleForeground;
this.element.style.color = titleForeground;
const titleBorder = this.getColor(TITLE_BAR_BORDER);
this.titleContainer.style.borderBottom = titleBorder ? `1px solid ${titleBorder}` : null;
this.element.style.borderBottom = titleBorder ? `1px solid ${titleBorder}` : null;
}
}
@@ -444,6 +483,16 @@ export class TitlebarPart extends Part implements ITitleService {
this.windowService.onWindowTitleDoubleClick();
}
private onUpdateAppIconDragBehavior() {
const setting = this.configurationService.getValue('window.doubleClickIconToClose');
if (setting) {
this.appIcon.style['-webkit-app-region'] = 'no-drag';
}
else {
this.appIcon.style['-webkit-app-region'] = 'drag';
}
}
private onContextMenu(e: MouseEvent): void {
// Find target anchor
@@ -491,30 +540,27 @@ export class TitlebarPart extends Part implements ITitleService {
}
private adjustTitleMarginToCenter(): void {
setTimeout(() => {
// Cannot center
if (!isMacintosh &&
(this.appIcon.clientWidth + this.menubar.clientWidth + 10 > (this.titleContainer.clientWidth - this.title.clientWidth) / 2 ||
this.titleContainer.clientWidth - this.windowControls.clientWidth - 10 < (this.titleContainer.clientWidth + this.title.clientWidth) / 2)) {
this.title.style.position = null;
this.title.style.left = null;
this.title.style.transform = null;
} else {
this.title.style.position = 'absolute';
this.title.style.left = '50%';
this.title.style.transform = 'translate(-50%, 0)';
}
}, 0); // delay so that we can get accurate information about widths
if (!isMacintosh &&
(this.appIcon.clientWidth + this.menubar.clientWidth + 10 > (this.element.clientWidth - this.title.clientWidth) / 2 ||
this.element.clientWidth - this.windowControls.clientWidth - 10 < (this.element.clientWidth + this.title.clientWidth) / 2)) {
this.title.style.position = null;
this.title.style.left = null;
this.title.style.transform = null;
} else {
this.title.style.position = 'absolute';
this.title.style.left = '50%';
this.title.style.transform = 'translate(-50%, 0)';
}
}
layout(dimension: Dimension): Dimension[] {
updateLayout(dimension: Dimension): void {
if (getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') {
// Only prevent zooming behavior on macOS or when the menubar is not visible
if (isMacintosh || this.configurationService.getValue<MenuBarVisibility>('window.menuBarVisibility') === 'hidden') {
this.title.style.zoom = `${1.0 / getZoomFactor()}`;
this.title.style.zoom = `${1 / getZoomFactor()}`;
if (isWindows || isLinux) {
this.appIcon.style.zoom = `${1.0 / getZoomFactor()}`;
this.windowControls.style.zoom = `${1.0 / getZoomFactor()}`;
this.appIcon.style.zoom = `${1 / getZoomFactor()}`;
this.windowControls.style.zoom = `${1 / getZoomFactor()}`;
}
} else {
this.title.style.zoom = null;
@@ -524,15 +570,34 @@ export class TitlebarPart extends Part implements ITitleService {
}
}
this.adjustTitleMarginToCenter();
runAtThisOrScheduleAtNextAnimationFrame(() => this.adjustTitleMarginToCenter());
if (this.menubarPart) {
const menubarDimension = new Dimension(undefined, dimension.height);
this.menubarPart.layout(menubarDimension);
}
}
}
return super.layout(dimension);
layout(dimension: Dimension): Dimension[];
layout(width: number, height: number): void;
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
if (dim1 instanceof Dimension) {
this.updateLayout(dim1);
return super.layout(dim1);
}
const dimensions = new Dimension(dim1, dim2);
this.updateLayout(dimensions);
super.layout(dimensions);
}
toJSON(): object {
return {
type: Parts.TITLEBAR_PART
};
}
}
@@ -542,7 +607,7 @@ class ShowItemInFolderAction extends Action {
super('showItemInFolder.action.id', label);
}
run(): Thenable<void> {
run(): Promise<void> {
return this.windowsService.showItemInFolder(this.path);
}
}
@@ -551,7 +616,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const titlebarActiveFg = theme.getColor(TITLE_BAR_ACTIVE_FOREGROUND);
if (titlebarActiveFg) {
collector.addRule(`
.monaco-workbench > .part.titlebar > .window-controls-container .window-icon {
.monaco-workbench .part.titlebar > .window-controls-container .window-icon {
background-color: ${titlebarActiveFg};
}
`);
@@ -560,7 +625,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const titlebarInactiveFg = theme.getColor(TITLE_BAR_INACTIVE_FOREGROUND);
if (titlebarInactiveFg) {
collector.addRule(`
.monaco-workbench > .part.titlebar.inactive > .window-controls-container .window-icon {
.monaco-workbench .part.titlebar.inactive > .window-controls-container .window-icon {
background-color: ${titlebarInactiveFg};
}
`);

View File

@@ -13,7 +13,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
import { ContextAwareMenuItemActionItem, fillInActionBarActions, fillInContextMenuActions } from 'vs/platform/actions/browser/menuItemActionItem';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IViewsService, ITreeView, ITreeItem, TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ICustomViewDescriptor, ViewsRegistry, ViewContainer, ITreeItemLabel } from 'vs/workbench/common/views';
import { IViewsService, ITreeView, ITreeItem, TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ITreeViewDescriptor, ViewsRegistry, ViewContainer, ITreeItemLabel } from 'vs/workbench/common/views';
import { IViewletViewOptions, FileIconThemableWorkbenchTree } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -23,7 +23,7 @@ import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/work
import { ICommandService } from 'vs/platform/commands/common/commands';
import * as DOM from 'vs/base/browser/dom';
import { IDataSource, ITree, IRenderer, ContextMenuEvent } from 'vs/base/parts/tree/browser/tree';
import { ResourceLabel } from 'vs/workbench/browser/labels';
import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels';
import { ActionBar, IActionItemProvider, ActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { URI } from 'vs/base/common/uri';
import { basename } from 'vs/base/common/paths';
@@ -51,22 +51,18 @@ export class CustomTreeViewPanel extends ViewletPanel {
constructor(
options: IViewletViewOptions,
@INotificationService private notificationService: INotificationService,
@INotificationService private readonly notificationService: INotificationService,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IViewsService viewsService: IViewsService,
) {
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService);
const { treeView } = (<ICustomViewDescriptor>ViewsRegistry.getView(options.id));
const { treeView } = (<ITreeViewDescriptor>ViewsRegistry.getView(options.id));
this.treeView = treeView;
this.treeView.onDidChangeActions(() => this.updateActions(), this, this.disposables);
this.disposables.push(toDisposable(() => this.treeView.setVisibility(false)));
this.updateTreeVisibility();
}
setVisible(visible: boolean): void {
super.setVisible(visible);
this.disposables.push(this.onDidChangeBodyVisibility(() => this.updateTreeVisibility()));
this.updateTreeVisibility();
}
@@ -79,11 +75,6 @@ export class CustomTreeViewPanel extends ViewletPanel {
this.treeView.show(container);
}
setExpanded(expanded: boolean): void {
this.treeView.setVisibility(this.isVisible() && expanded);
super.setExpanded(expanded);
}
layoutBody(size: number): void {
this.treeView.layout(size);
}
@@ -105,7 +96,7 @@ export class CustomTreeViewPanel extends ViewletPanel {
}
private updateTreeVisibility(): void {
this.treeView.setVisibility(this.isVisible() && this.isExpanded());
this.treeView.setVisibility(this.isBodyVisible());
}
dispose(): void {
@@ -126,8 +117,8 @@ class TitleMenus implements IDisposable {
constructor(
id: string,
@IContextKeyService private contextKeyService: IContextKeyService,
@IMenuService private menuService: IMenuService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IMenuService private readonly menuService: IMenuService,
) {
if (this.titleDisposable) {
this.titleDisposable.dispose();
@@ -175,7 +166,7 @@ class Root implements ITreeItem {
handle = '0';
parentHandle = null;
collapsibleState = TreeItemCollapsibleState.Expanded;
children = void 0;
children = undefined;
}
const noDataProviderMessage = localize('no-dataprovider', "There is no data provider registered that can provide view data.");
@@ -194,6 +185,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
private _messageValue: string | IMarkdownString | undefined;
private messageElement: HTMLDivElement;
private tree: FileIconThemableWorkbenchTree;
private treeLabels: ResourceLabels;
private root: ITreeItem;
private elementsToRefresh: ITreeItem[] = [];
private menus: TitleMenus;
@@ -218,13 +210,13 @@ export class CustomTreeView extends Disposable implements ITreeView {
constructor(
private id: string,
private container: ViewContainer,
@IExtensionService private extensionService: IExtensionService,
@IWorkbenchThemeService private themeService: IWorkbenchThemeService,
@IInstantiationService private instantiationService: IInstantiationService,
@ICommandService private commandService: ICommandService,
@IConfigurationService private configurationService: IConfigurationService,
@IProgressService2 private progressService: IProgressService2
private viewContainer: ViewContainer,
@IExtensionService private readonly extensionService: IExtensionService,
@IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ICommandService private readonly commandService: ICommandService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProgressService2 private readonly progressService: IProgressService2
) {
super();
this.root = new Root();
@@ -243,6 +235,11 @@ export class CustomTreeView extends Disposable implements ITreeView {
this.markdownResult.dispose();
}
}));
this._register(ViewsRegistry.onDidChangeContainer(({ views, from, to }) => {
if (from === this.viewContainer && views.some(v => v.id === this.id)) {
this.viewContainer = to;
}
}));
this.create();
}
@@ -382,13 +379,13 @@ export class CustomTreeView extends Disposable implements ITreeView {
private createTree() {
const actionItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuItemActionItem, action) : undefined;
const menus = this.instantiationService.createInstance(TreeMenus, this.id);
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, this.container);
const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, menus, actionItemProvider);
const menus = this._register(this.instantiationService.createInstance(TreeMenus, this.id));
this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this));
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, <T>(task: Promise<T>) => this.progressService.withProgress({ location: this.viewContainer.id }, () => task));
const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, menus, this.treeLabels, actionItemProvider);
const controller = this.instantiationService.createInstance(TreeController, this.id, menus);
this.tree = this.instantiationService.createInstance(FileIconThemableWorkbenchTree, this.treeContainer, { dataSource, renderer, controller }, {});
this.tree = this._register(this.instantiationService.createInstance(FileIconThemableWorkbenchTree, this.treeContainer, { dataSource, renderer, controller }, {}));
this.tree.contextKeyService.createKey<boolean>(this.id, true);
this._register(this.tree);
this._register(this.tree.onDidChangeSelection(e => this.onSelection(e)));
this._register(this.tree.onDidExpandItem(e => this._onDidExpandItem.fire(e.item.getElement())));
this._register(this.tree.onDidCollapseItem(e => this._onDidCollapseItem.fire(e.item.getElement())));
@@ -451,7 +448,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
getOptimalWidth(): number {
if (this.tree) {
const parentNode = this.tree.getHTMLElement();
const childNodes = ([] as Element[]).slice.call(parentNode.querySelectorAll('.outline-item-label > a'));
const childNodes = ([] as HTMLElement[]).slice.call(parentNode.querySelectorAll('.outline-item-label > a'));
return DOM.getLargestChildWidth(parentNode, childNodes);
}
return 0;
@@ -459,25 +456,39 @@ export class CustomTreeView extends Disposable implements ITreeView {
refresh(elements?: ITreeItem[]): Promise<void> {
if (this.dataProvider && this.tree) {
elements = elements || [this.root];
if (!elements) {
elements = [this.root];
// remove all waiting elements to refresh if root is asked to refresh
this.elementsToRefresh = [];
}
for (const element of elements) {
element.children = null; // reset children
}
if (this.isVisible) {
return this.doRefresh(elements);
} else {
this.elementsToRefresh.push(...elements);
if (this.elementsToRefresh.length) {
const seen: Set<string> = new Set<string>();
this.elementsToRefresh.forEach(element => seen.add(element.handle));
for (const element of elements) {
if (!seen.has(element.handle)) {
this.elementsToRefresh.push(element);
}
}
} else {
this.elementsToRefresh.push(...elements);
}
}
}
return Promise.resolve(null);
return Promise.resolve(undefined);
}
expand(itemOrItems: ITreeItem | ITreeItem[]): Thenable<void> {
expand(itemOrItems: ITreeItem | ITreeItem[]): Promise<void> {
if (this.tree) {
itemOrItems = Array.isArray(itemOrItems) ? itemOrItems : [itemOrItems];
return this.tree.expandAll(itemOrItems);
}
return Promise.arguments(null);
return Promise.resolve(undefined);
}
setSelection(items: ITreeItem[]): void {
@@ -493,17 +504,17 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
}
reveal(item: ITreeItem): Thenable<void> {
reveal(item: ITreeItem): Promise<void> {
if (this.tree) {
return this.tree.reveal(item);
}
return Promise.arguments(null);
return Promise.resolve(null);
}
private activate() {
if (!this.activated) {
this.createTree();
this.progressService.withProgress({ location: this.container.id }, () => this.extensionService.activateByEvent(`onView:${this.id}`))
this.progressService.withProgress({ location: this.viewContainer.id }, () => this.extensionService.activateByEvent(`onView:${this.id}`))
.then(() => timeout(2000))
.then(() => {
this.updateMessage();
@@ -525,7 +536,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
}
});
}
return Promise.resolve(null);
return Promise.resolve(undefined);
}
private updateContentAreas(): void {
@@ -563,8 +574,7 @@ class TreeDataSource implements IDataSource {
constructor(
private treeView: ITreeView,
private container: ViewContainer,
@IProgressService2 private progressService: IProgressService2
private withProgress: <T>(task: Promise<T>) => Promise<T>
) {
}
@@ -578,7 +588,7 @@ class TreeDataSource implements IDataSource {
getChildren(tree: ITree, node: ITreeItem): Promise<any[]> {
if (this.treeView.dataProvider) {
return this.progressService.withProgress({ location: this.container.id }, () => this.treeView.dataProvider.getChildren(node));
return this.withProgress(this.treeView.dataProvider.getChildren(node));
}
return Promise.resolve([]);
}
@@ -593,7 +603,7 @@ class TreeDataSource implements IDataSource {
}
interface ITreeExplorerTemplateData {
resourceLabel: ResourceLabel;
resourceLabel: IResourceLabel;
icon: HTMLElement;
actionBar: ActionBar;
aligner: Aligner;
@@ -605,10 +615,12 @@ registerThemingParticipant((theme, collector) => {
const findMatchHighlightColor = theme.getColor(editorFindMatchHighlight);
if (findMatchHighlightColor) {
collector.addRule(`.file-icon-themable-tree .monaco-tree-row .content .monaco-highlighted-label .highlight { color: unset !important; background-color: ${findMatchHighlightColor}; }`);
collector.addRule(`.monaco-tl-contents .monaco-highlighted-label .highlight { color: unset !important; background-color: ${findMatchHighlightColor}; }`);
}
const findMatchHighlightColorBorder = theme.getColor(editorFindMatchHighlightBorder);
if (findMatchHighlightColorBorder) {
collector.addRule(`.file-icon-themable-tree .monaco-tree-row .content .monaco-highlighted-label .highlight { color: unset !important; border: 1px dotted ${findMatchHighlightColorBorder}; box-sizing: border-box; }`);
collector.addRule(`.monaco-tl-contents .monaco-highlighted-label .highlight { color: unset !important; border: 1px dotted ${findMatchHighlightColorBorder}; box-sizing: border-box; }`);
}
const link = theme.getColor(textLinkForeground);
if (link) {
@@ -632,11 +644,11 @@ class TreeRenderer implements IRenderer {
constructor(
private treeViewId: string,
private menus: TreeMenus,
private labels: ResourceLabels,
private actionItemProvider: IActionItemProvider,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkbenchThemeService private themeService: IWorkbenchThemeService,
@IConfigurationService private configurationService: IConfigurationService,
@ILabelService private labelService: ILabelService
@IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ILabelService private readonly labelService: ILabelService
) {
}
@@ -652,7 +664,7 @@ class TreeRenderer implements IRenderer {
DOM.addClass(container, 'custom-view-tree-node-item');
const icon = DOM.append(container, DOM.$('.custom-view-tree-node-item-icon'));
const resourceLabel = this.instantiationService.createInstance(ResourceLabel, container, { supportHighlights: true, donotSupportOcticons: true });
const resourceLabel = this.labels.create(container, { supportHighlights: true, donotSupportOcticons: true });
DOM.addClass(resourceLabel.element, 'custom-view-tree-node-item-resourceLabel');
const actionsContainer = DOM.append(resourceLabel.element, DOM.$('.actions'));
const actionBar = new ActionBar(actionsContainer, {
@@ -665,23 +677,22 @@ class TreeRenderer implements IRenderer {
renderElement(tree: ITree, node: ITreeItem, templateId: string, templateData: ITreeExplorerTemplateData): void {
const resource = node.resourceUri ? URI.revive(node.resourceUri) : null;
const treeItemLabel: ITreeItemLabel = node.label ? node.label : resource ? { label: basename(resource.path) } : void 0;
const description = isString(node.description) ? node.description : resource && node.description === true ? this.labelService.getUriLabel(dirname(resource), { relative: true }) : void 0;
const label = treeItemLabel ? treeItemLabel.label : void 0;
const matches = treeItemLabel && treeItemLabel.highlights ? treeItemLabel.highlights.map(([start, end]) => ({ start, end })) : void 0;
const treeItemLabel: ITreeItemLabel = node.label ? node.label : resource ? { label: basename(resource.path) } : undefined;
const description = isString(node.description) ? node.description : resource && node.description === true ? this.labelService.getUriLabel(dirname(resource), { relative: true }) : undefined;
const label = treeItemLabel ? treeItemLabel.label : undefined;
const matches = treeItemLabel && treeItemLabel.highlights ? treeItemLabel.highlights.map(([start, end]) => ({ start, end })) : undefined;
const icon = this.themeService.getTheme().type === LIGHT ? node.icon : node.iconDark;
const iconUrl = icon ? URI.revive(icon) : null;
const title = node.tooltip ? node.tooltip : resource ? void 0 : label;
const title = node.tooltip ? node.tooltip : resource ? undefined : label;
// reset
templateData.resourceLabel.clear();
templateData.actionBar.clear();
if (resource || node.themeIcon) {
const fileDecorations = this.configurationService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
templateData.resourceLabel.setLabel({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
templateData.resourceLabel.setResource({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
} else {
templateData.resourceLabel.setLabel({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
templateData.resourceLabel.setResource({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
}
templateData.icon.style.backgroundImage = iconUrl ? `url('${iconUrl.toString(true)}')` : '';
@@ -772,7 +783,7 @@ class TreeController extends WorkbenchTreeController {
constructor(
private treeViewId: string,
private menus: TreeMenus,
@IContextMenuService private contextMenuService: IContextMenuService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@IConfigurationService configurationService: IConfigurationService
) {
@@ -827,7 +838,7 @@ class MultipleSelectionActionRunner extends ActionRunner {
super();
}
runAction(action: IAction, context: any): Thenable<any> {
runAction(action: IAction, context: any): Promise<any> {
if (action instanceof MenuItemAction) {
const selection = this.getSelectedResources();
const filteredSelection = selection.filter(s => s !== context);
@@ -847,9 +858,9 @@ class TreeMenus extends Disposable implements IDisposable {
constructor(
private id: string,
@IContextKeyService private contextKeyService: IContextKeyService,
@IMenuService private menuService: IMenuService,
@IContextMenuService private contextMenuService: IContextMenuService
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IMenuService private readonly menuService: IMenuService,
@IContextMenuService private readonly contextMenuService: IContextMenuService
) {
super();
}
@@ -914,4 +925,4 @@ class MarkdownRenderer {
dispose: () => dispose(disposeables)
};
}
}
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* File icon themeable tree style */
/* File icon themeable OLD tree style */
.file-icon-themable-tree .monaco-tree-row .content {
display: flex;
}
@@ -50,6 +50,17 @@
display: none;
}
/* File icons in trees */
.file-icon-themable-tree.align-icons-and-twisties .monaco-tl-twistie:not(.collapsible),
.file-icon-themable-tree.hide-arrows .monaco-tl-twistie {
background-image: none !important;
width: 0 !important;
margin-right: 0 !important;
}
/* Misc */
.monaco-workbench .tree-explorer-viewlet-tree-view {
height: 100%;
}

View File

@@ -5,7 +5,7 @@
import 'vs/css!./media/panelviewlet';
import * as nls from 'vs/nls';
import { Event, Emitter, filterEvent } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry';
import { attachStyler, IColorMapping } from 'vs/platform/theme/common/styler';
import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER } from 'vs/workbench/common/theme';
@@ -52,14 +52,17 @@ export abstract class ViewletPanel extends Panel implements IView {
private _onDidBlur = new Emitter<void>();
readonly onDidBlur: Event<void> = this._onDidBlur.event;
private _onDidChangeBodyVisibility = new Emitter<boolean>();
readonly onDidChangeBodyVisibility: Event<boolean> = this._onDidChangeBodyVisibility.event;
protected _onDidChangeTitleArea = new Emitter<void>();
readonly onDidChangeTitleArea: Event<void> = this._onDidChangeTitleArea.event;
private _isVisible: boolean = true;
private _isVisible: boolean = false;
readonly id: string;
readonly title: string;
protected actionRunner: IActionRunner;
protected actionRunner?: IActionRunner;
protected toolbar: ToolBar;
private headerContainer: HTMLElement;
@@ -74,11 +77,17 @@ export abstract class ViewletPanel extends Panel implements IView {
this.id = options.id;
this.title = options.title;
this.actionRunner = options.actionRunner;
this.disposables.push(this._onDidFocus, this._onDidBlur, this._onDidChangeBodyVisibility, this._onDidChangeTitleArea);
}
setVisible(visible: boolean): void {
if (this._isVisible !== visible) {
this._isVisible = visible;
if (this.isExpanded()) {
this._onDidChangeBodyVisibility.fire(visible);
}
}
}
@@ -86,6 +95,19 @@ export abstract class ViewletPanel extends Panel implements IView {
return this._isVisible;
}
isBodyVisible(): boolean {
return this._isVisible && this.isExpanded();
}
setExpanded(expanded: boolean): boolean {
const changed = super.setExpanded(expanded);
if (changed) {
this._onDidChangeBodyVisibility.fire(expanded);
}
return changed;
}
render(): void {
super.render();
@@ -105,20 +127,20 @@ export abstract class ViewletPanel extends Panel implements IView {
orientation: ActionsOrientation.HORIZONTAL,
actionItemProvider: action => this.getActionItem(action),
ariaLabel: nls.localize('viewToolbarAriaLabel', "{0} actions", this.title),
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id) || undefined,
actionRunner: this.actionRunner
});
this.disposables.push(this.toolbar);
this.setActions();
const onDidRelevantConfigurationChange = filterEvent(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ViewletPanel.AlwaysShowActionsConfig));
const onDidRelevantConfigurationChange = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ViewletPanel.AlwaysShowActionsConfig));
onDidRelevantConfigurationChange(this.updateActionsVisibility, this, this.disposables);
this.updateActionsVisibility();
}
protected renderHeaderTitle(container: HTMLElement, title: string): void {
append(container, $('h3.title', null, title));
append(container, $('h3.title', undefined, title));
}
focus(): void {
@@ -151,7 +173,7 @@ export abstract class ViewletPanel extends Panel implements IView {
return [];
}
getActionItem(action: IAction): IActionItem {
getActionItem(action: IAction): IActionItem | null {
return null;
}
@@ -237,7 +259,7 @@ export class PanelViewlet extends Viewlet {
let title = Registry.as<ViewletRegistry>(Extensions.Viewlets).getViewlet(this.getId()).name;
if (this.isSingleView()) {
title += ': ' + this.panelItems[0].panel.title;
title = `${title}: ${this.panelItems[0].panel.title}`;
}
return title;
@@ -259,7 +281,7 @@ export class PanelViewlet extends Viewlet {
return [];
}
getActionItem(action: IAction): IActionItem {
getActionItem(action: IAction): IActionItem | null {
if (this.isSingleView()) {
return this.panelItems[0].panel.getActionItem(action);
}
@@ -283,7 +305,7 @@ export class PanelViewlet extends Viewlet {
}
layout(dimension: Dimension): void {
this.panelview.layout(dimension.height);
this.panelview.layout(dimension.height, dimension.width);
}
getOptimalWidth(): number {

View File

@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/views';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { IViewsService, ViewsRegistry, IViewsViewlet, ViewContainer, IViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, IView, IViewDescriptorCollection } from 'vs/workbench/common/views';
import { Registry } from 'vs/platform/registry/common/platform';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IContextKeyService, IContextKeyChangeEvent, IReadableSet, IContextKey, RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { Event, chain, filterEvent, Emitter } from 'vs/base/common/event';
import { sortedDiff, firstIndex, move } from 'vs/base/common/arrays';
import { Event, Emitter } from 'vs/base/common/event';
import { sortedDiff, firstIndex, move, isNonEmptyArray } from 'vs/base/common/arrays';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { MenuId, MenuRegistry, ICommandAction } from 'vs/platform/actions/common/actions';
@@ -19,14 +19,23 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { localize } from 'vs/nls';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { values } from 'vs/base/common/map';
import { IFileIconTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { toggleClass, addClass } from 'vs/base/browser/dom';
function filterViewEvent(container: ViewContainer, event: Event<IViewDescriptor[]>): Event<IViewDescriptor[]> {
return chain(event)
.map(views => views.filter(view => view.container === container))
function filterViewRegisterEvent(container: ViewContainer, event: Event<{ viewContainer: ViewContainer, views: IViewDescriptor[] }>): Event<IViewDescriptor[]> {
return Event.chain(event)
.map(({ views, viewContainer }) => viewContainer === container ? views : [])
.filter(views => views.length > 0)
.event;
}
function filterViewMoveEvent(container: ViewContainer, event: Event<{ from: ViewContainer, to: ViewContainer, views: IViewDescriptor[] }>): Event<{ added?: IViewDescriptor[], removed?: IViewDescriptor[] }> {
return Event.chain(event)
.map(({ views, from, to }) => from === container ? { removed: views } : to === container ? { added: views } : {})
.filter(({ added, removed }) => isNonEmptyArray(added) || isNonEmptyArray(removed))
.event;
}
class CounterSet<T> implements IReadableSet<T> {
private map = new Map<T, number>();
@@ -84,16 +93,26 @@ class ViewDescriptorCollection extends Disposable implements IViewDescriptorColl
constructor(
container: ViewContainer,
@IContextKeyService private contextKeyService: IContextKeyService
@IContextKeyService private readonly contextKeyService: IContextKeyService
) {
super();
const onRelevantViewsRegistered = filterViewEvent(container, ViewsRegistry.onViewsRegistered);
const onRelevantViewsRegistered = filterViewRegisterEvent(container, ViewsRegistry.onViewsRegistered);
this._register(onRelevantViewsRegistered(this.onViewsRegistered, this));
const onRelevantViewsDeregistered = filterViewEvent(container, ViewsRegistry.onViewsDeregistered);
const onRelevantViewsMoved = filterViewMoveEvent(container, ViewsRegistry.onDidChangeContainer);
this._register(onRelevantViewsMoved(({ added, removed }) => {
if (isNonEmptyArray(added)) {
this.onViewsRegistered(added);
}
if (isNonEmptyArray(removed)) {
this.onViewsDeregistered(removed);
}
}));
const onRelevantViewsDeregistered = filterViewRegisterEvent(container, ViewsRegistry.onViewsDeregistered);
this._register(onRelevantViewsDeregistered(this.onViewsDeregistered, this));
const onRelevantContextChange = filterEvent(contextKeyService.onDidChangeContext, e => e.affectsSome(this.contextKeys));
const onRelevantContextChange = Event.filter(contextKeyService.onDidChangeContext, e => e.affectsSome(this.contextKeys));
this._register(onRelevantContextChange(this.onContextChanged, this));
this.onViewsRegistered(ViewsRegistry.getViews(container));
@@ -204,7 +223,7 @@ export class ContributableViewsModel extends Disposable {
readonly viewDescriptors: IViewDescriptor[] = [];
get visibleViewDescriptors(): IViewDescriptor[] {
return this.viewDescriptors.filter(v => this.viewStates.get(v.id).visible);
return this.viewDescriptors.filter(v => this.viewStates.get(v.id)!.visible);
}
private _onDidAdd = this._register(new Emitter<IAddedViewDescriptorRef[]>());
@@ -224,8 +243,10 @@ export class ContributableViewsModel extends Disposable {
super();
const viewDescriptorCollection = viewsService.getViewDescriptors(container);
this._register(viewDescriptorCollection.onDidChangeActiveViews(() => this.onDidChangeViewDescriptors(viewDescriptorCollection.activeViewDescriptors)));
this.onDidChangeViewDescriptors(viewDescriptorCollection.activeViewDescriptors);
if (viewDescriptorCollection) {
this._register(viewDescriptorCollection.onDidChangeActiveViews(() => this.onDidChangeViewDescriptors(viewDescriptorCollection.activeViewDescriptors)));
this.onDidChangeViewDescriptors(viewDescriptorCollection.activeViewDescriptors);
}
}
isVisible(id: string): boolean {
@@ -298,7 +319,7 @@ export class ContributableViewsModel extends Disposable {
move(this.viewDescriptors, fromIndex, toIndex);
for (let index = 0; index < this.viewDescriptors.length; index++) {
const state = this.viewStates.get(this.viewDescriptors[index].id);
const state = this.viewStates.get(this.viewDescriptors[index].id)!;
state.order = index;
}
@@ -312,6 +333,9 @@ export class ContributableViewsModel extends Disposable {
for (let i = 0, visibleIndex = 0; i < this.viewDescriptors.length; i++) {
const viewDescriptor = this.viewDescriptors[i];
const state = this.viewStates.get(viewDescriptor.id);
if (!state) {
throw new Error(`View state for ${id} not found`);
}
if (viewDescriptor.id === id) {
return { index: i, visibleIndex, viewDescriptor, state };
@@ -357,7 +381,7 @@ export class ContributableViewsModel extends Disposable {
} else {
this.viewStates.set(viewDescriptor.id, {
visible: !viewDescriptor.hideByDefault,
collapsed: viewDescriptor.collapsed
collapsed: !!viewDescriptor.collapsed
});
}
}
@@ -369,7 +393,7 @@ export class ContributableViewsModel extends Disposable {
).reverse();
const toRemove: { index: number, viewDescriptor: IViewDescriptor }[] = [];
const toAdd: { index: number, viewDescriptor: IViewDescriptor, size: number, collapsed: boolean }[] = [];
const toAdd: { index: number, viewDescriptor: IViewDescriptor, size?: number, collapsed: boolean }[] = [];
for (const splice of splices) {
const startViewDescriptor = this.viewDescriptors[splice.start];
@@ -384,9 +408,8 @@ export class ContributableViewsModel extends Disposable {
}
}
for (let i = 0; i < splice.toInsert.length; i++) {
const viewDescriptor = splice.toInsert[i];
const state = this.viewStates.get(viewDescriptor.id);
for (const viewDescriptor of splice.toInsert) {
const state = this.viewStates.get(viewDescriptor.id)!;
if (state.visible) {
toAdd.push({ index: startIndex++, viewDescriptor, size: state.size, collapsed: state.collapsed });
@@ -437,7 +460,7 @@ export class PersistentContributableViewsModel extends ContributableViewsModel {
}
private saveViewsStates(): void {
const storedViewsStates: { [id: string]: { collapsed: boolean, size: number, order: number } } = {};
const storedViewsStates: { [id: string]: { collapsed: boolean, size?: number, order?: number } } = {};
let hasState = false;
for (const viewDescriptor of this.viewDescriptors) {
@@ -460,7 +483,7 @@ export class PersistentContributableViewsModel extends ContributableViewsModel {
for (const viewDescriptor of viewDescriptors) {
if (viewDescriptor.canToggleVisibility) {
const viewState = this.viewStates.get(viewDescriptor.id);
storedViewsVisibilityStates.set(viewDescriptor.id, { id: viewDescriptor.id, isHidden: viewState ? !viewState.visible : void 0 });
storedViewsVisibilityStates.set(viewDescriptor.id, { id: viewDescriptor.id, isHidden: viewState ? !viewState.visible : false });
}
}
this.storageService.store(this.hiddenViewsStorageId, JSON.stringify(values(storedViewsVisibilityStates)), StorageScope.GLOBAL);
@@ -513,34 +536,49 @@ export class ViewsService extends Disposable implements IViewsService {
_serviceBrand: any;
private readonly viewDescriptorCollections: Map<ViewContainer, IViewDescriptorCollection>;
private readonly viewDescriptorCollections: Map<ViewContainer, { viewDescriptorCollection: IViewDescriptorCollection, disposable: IDisposable }>;
private readonly viewDisposable: Map<IViewDescriptor, IDisposable>;
private readonly activeViewContextKeys: Map<string, IContextKey<boolean>>;
constructor(
@IViewletService private viewletService: IViewletService,
@IContextKeyService private contextKeyService: IContextKeyService
@IViewletService private readonly viewletService: IViewletService,
@IContextKeyService private readonly contextKeyService: IContextKeyService
) {
super();
this.viewDescriptorCollections = new Map<ViewContainer, IViewDescriptorCollection>();
this.viewDescriptorCollections = new Map<ViewContainer, { viewDescriptorCollection: IViewDescriptorCollection, disposable: IDisposable }>();
this.viewDisposable = new Map<IViewDescriptor, IDisposable>();
this.activeViewContextKeys = new Map<string, IContextKey<boolean>>();
this.onDidRegisterViews(ViewsRegistry.getAllViews());
this._register(ViewsRegistry.onViewsRegistered(views => this.onDidRegisterViews(views)));
const viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
viewContainersRegistry.all.forEach(viewContainer => this.onDidRegisterViewContainer(viewContainer));
viewContainersRegistry.all.forEach(viewContainer => {
this.onDidRegisterViews(viewContainer, ViewsRegistry.getViews(viewContainer));
this.onDidRegisterViewContainer(viewContainer);
});
this._register(ViewsRegistry.onViewsRegistered(({ views, viewContainer }) => this.onDidRegisterViews(viewContainer, views)));
this._register(ViewsRegistry.onViewsDeregistered(({ views }) => this.onDidDeregisterViews(views)));
this._register(ViewsRegistry.onDidChangeContainer(({ views, to }) => { this.onDidDeregisterViews(views); this.onDidRegisterViews(to, views); }));
this._register(toDisposable(() => {
this.viewDisposable.forEach(disposable => disposable.dispose());
this.viewDisposable.clear();
}));
this._register(viewContainersRegistry.onDidRegister(viewContainer => this.onDidRegisterViewContainer(viewContainer)));
this._register(viewContainersRegistry.onDidDeregister(viewContainer => this.onDidDeregisterViewContainer(viewContainer)));
this._register(toDisposable(() => {
this.viewDescriptorCollections.forEach(({ disposable }) => disposable.dispose());
this.viewDescriptorCollections.clear();
}));
}
getViewDescriptors(container: ViewContainer): IViewDescriptorCollection {
return this.viewDescriptorCollections.get(container);
getViewDescriptors(container: ViewContainer): IViewDescriptorCollection | null {
const viewDescriptorCollectionItem = this.viewDescriptorCollections.get(container);
return viewDescriptorCollectionItem ? viewDescriptorCollectionItem.viewDescriptorCollection : null;
}
openView(id: string, focus: boolean): Thenable<IView> {
const viewDescriptor = ViewsRegistry.getView(id);
if (viewDescriptor) {
const viewletDescriptor = this.viewletService.getViewlet(viewDescriptor.container.id);
openView(id: string, focus: boolean): Promise<IView | null> {
const viewContainer = ViewsRegistry.getViewContainer(id);
if (viewContainer) {
const viewletDescriptor = this.viewletService.getViewlet(viewContainer.id);
if (viewletDescriptor) {
return this.viewletService.openViewlet(viewletDescriptor.id, focus)
.then((viewlet: IViewsViewlet) => {
@@ -555,12 +593,21 @@ export class ViewsService extends Disposable implements IViewsService {
}
private onDidRegisterViewContainer(viewContainer: ViewContainer): void {
const viewDescriptorCollection = this._register(new ViewDescriptorCollection(viewContainer, this.contextKeyService));
const viewDescriptorCollection = new ViewDescriptorCollection(viewContainer, this.contextKeyService);
const disposables: IDisposable[] = [viewDescriptorCollection];
this.onDidChangeActiveViews({ added: viewDescriptorCollection.activeViewDescriptors, removed: [] });
this._register(viewDescriptorCollection.onDidChangeActiveViews(changed => this.onDidChangeActiveViews(changed)));
viewDescriptorCollection.onDidChangeActiveViews(changed => this.onDidChangeActiveViews(changed), this, disposables);
this.viewDescriptorCollections.set(viewContainer, viewDescriptorCollection);
this.viewDescriptorCollections.set(viewContainer, { viewDescriptorCollection, disposable: toDisposable(() => dispose(disposables)) });
}
private onDidDeregisterViewContainer(viewContainer: ViewContainer): void {
const viewDescriptorCollectionItem = this.viewDescriptorCollections.get(viewContainer);
if (viewDescriptorCollectionItem) {
viewDescriptorCollectionItem.disposable.dispose();
this.viewDescriptorCollections.delete(viewContainer);
}
}
private onDidChangeActiveViews({ added, removed }: { added: IViewDescriptor[], removed: IViewDescriptor[] }): void {
@@ -568,9 +615,10 @@ export class ViewsService extends Disposable implements IViewsService {
removed.forEach(viewDescriptor => this.getOrCreateActiveViewContextKey(viewDescriptor).set(false));
}
private onDidRegisterViews(viewDescriptors: IViewDescriptor[]): void {
for (const viewDescriptor of viewDescriptors) {
const viewlet = this.viewletService.getViewlet(viewDescriptor.container.id);
private onDidRegisterViews(container: ViewContainer, views: IViewDescriptor[]): void {
const viewlet = this.viewletService.getViewlet(container.id);
for (const viewDescriptor of views) {
const disposables: IDisposable[] = [];
const command: ICommandAction = {
id: viewDescriptor.focusCommand ? viewDescriptor.focusCommand.id : `${viewDescriptor.id}.focus`,
title: { original: `Focus on ${viewDescriptor.name} View`, value: localize('focus view', "Focus on {0} View", viewDescriptor.name) },
@@ -578,12 +626,12 @@ export class ViewsService extends Disposable implements IViewsService {
};
const when = ContextKeyExpr.has(`${viewDescriptor.id}.active`);
CommandsRegistry.registerCommand(command.id, () => this.openView(viewDescriptor.id, true).then(() => null));
disposables.push(CommandsRegistry.registerCommand(command.id, () => this.openView(viewDescriptor.id, true).then(() => null)));
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
disposables.push(MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command,
when
});
}));
if (viewDescriptor.focusCommand && viewDescriptor.focusCommand.keybindings) {
KeybindingsRegistry.registerKeybindingRule({
@@ -597,6 +645,18 @@ export class ViewsService extends Disposable implements IViewsService {
win: viewDescriptor.focusCommand.keybindings.win
});
}
this.viewDisposable.set(viewDescriptor, toDisposable(() => dispose(disposables)));
}
}
private onDidDeregisterViews(views: IViewDescriptor[]): void {
for (const view of views) {
const disposable = this.viewDisposable.get(view);
if (disposable) {
disposable.dispose();
this.viewDisposable.delete(view);
}
}
}
@@ -610,3 +670,16 @@ export class ViewsService extends Disposable implements IViewsService {
return contextKey;
}
}
export function createFileIconThemableTreeContainerScope(container: HTMLElement, themeService: IWorkbenchThemeService): IDisposable {
addClass(container, 'file-icon-themable-tree');
addClass(container, 'show-file-icons');
const onDidChangeFileIconTheme = (theme: IFileIconTheme) => {
toggleClass(container, 'align-icons-and-twisties', theme.hasFileIcons && !theme.hasFolderIcons);
toggleClass(container, 'hide-arrows', theme.hidesExplorerArrows === true);
};
onDidChangeFileIconTheme(themeService.getFileIconTheme());
return themeService.onDidFileIconThemeChange(onDidChangeFileIconTheme);
}

View File

@@ -23,83 +23,13 @@ import { DefaultPanelDndController } from 'vs/base/browser/ui/splitview/panelvie
import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService';
import { IWorkbenchThemeService, IFileIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree';
import { latch, mapEvent } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { localize } from 'vs/nls';
import { IAddedViewDescriptorRef, IViewDescriptorRef, PersistentContributableViewsModel } from 'vs/workbench/browser/parts/views/views';
import { Registry } from 'vs/platform/registry/common/platform';
export abstract class TreeViewsViewletPanel extends ViewletPanel {
protected tree: WorkbenchTree;
setExpanded(expanded: boolean): void {
if (this.isExpanded() !== expanded) {
this.updateTreeVisibility(this.tree, expanded);
super.setExpanded(expanded);
}
}
setVisible(visible: boolean): void {
if (this.isVisible() !== visible) {
super.setVisible(visible);
this.updateTreeVisibility(this.tree, visible && this.isExpanded());
}
}
focus(): void {
super.focus();
this.focusTree();
}
layoutBody(size: number): void {
if (this.tree) {
this.tree.layout(size);
}
}
protected updateTreeVisibility(tree: WorkbenchTree, isVisible: boolean): void {
if (!tree) {
return;
}
if (isVisible) {
DOM.show(tree.getHTMLElement());
} else {
DOM.hide(tree.getHTMLElement()); // make sure the tree goes out of the tabindex world by hiding it
}
if (isVisible) {
tree.onVisible();
} else {
tree.onHidden();
}
}
private focusTree(): void {
if (!this.tree) {
return; // return early if viewlet has not yet been created
}
// Make sure the current selected element is revealed
const selectedElement = this.tree.getSelection()[0];
if (selectedElement) {
this.tree.reveal(selectedElement);
}
// Pass Focus to Viewer
this.tree.domFocus();
}
dispose(): void {
if (this.tree) {
this.tree.dispose();
}
super.dispose();
}
}
export interface IViewletViewOptions extends IViewletPanelOptions {
viewletState: object;
}
@@ -274,7 +204,7 @@ export abstract class ViewContainerViewlet extends PanelViewlet implements IView
this.onContextMenu(new StandardMouseEvent(e), viewDescriptor);
});
const collapseDisposable = latch(mapEvent(panel.onDidChange, () => !panel.isExpanded()))(collapsed => {
const collapseDisposable = Event.latch(Event.map(panel.onDidChange, () => !panel.isExpanded()))(collapsed => {
this.viewsModel.setCollapsed(viewDescriptor.id, collapsed);
});
@@ -284,7 +214,13 @@ export abstract class ViewContainerViewlet extends PanelViewlet implements IView
this.addPanels(panelsToAdd);
this.restoreViewSizes();
return panelsToAdd.map(({ panel }) => panel);
const panels: ViewletPanel[] = [];
for (const { panel } of panelsToAdd) {
panel.setVisible(this.isVisible());
panels.push(panel);
}
return panels;
}
private onDidRemoveViews(removed: IViewDescriptorRef[]): void {