提交 9acebf63 编写于 作者: S Sandeep Somavarapu

#27823

- Debt reduction. Clean up views.
- Implement Composed views viewlet
- Adopt explorer debug viewlet to composed views viewlet
上级 ed5bc914
......@@ -9,7 +9,6 @@ import 'vs/css!./splitview';
import lifecycle = require('vs/base/common/lifecycle');
import ee = require('vs/base/common/eventEmitter');
import types = require('vs/base/common/types');
import objects = require('vs/base/common/objects');
import dom = require('vs/base/browser/dom');
import numbers = require('vs/base/common/numbers');
import sash = require('vs/base/browser/ui/sash/sash');
......@@ -240,10 +239,9 @@ export abstract class HeaderView extends View {
}
export interface ICollapsibleViewOptions {
ariaHeaderLabel?: string;
fixedSize?: number;
minimumSize?: number;
headerSize?: number;
sizing: ViewSizing;
ariaHeaderLabel: string;
bodySize?: number;
initialState?: CollapsibleState;
}
......@@ -260,14 +258,43 @@ export abstract class AbstractCollapsibleView extends HeaderView {
private headerClickListener: lifecycle.IDisposable;
private headerKeyListener: lifecycle.IDisposable;
private focusTracker: dom.IFocusTracker;
private _bodySize: number;
private _previousSize: number = null;
private readonly viewSizing: ViewSizing;
constructor(opts: ICollapsibleViewOptions) {
super(opts);
this.viewSizing = opts.sizing;
this.ariaHeaderLabel = opts.ariaHeaderLabel;
this.ariaHeaderLabel = opts && opts.ariaHeaderLabel;
this.setBodySize(types.isUndefined(opts.bodySize) ? 22 : opts.bodySize);
this.changeState(types.isUndefined(opts.initialState) ? CollapsibleState.EXPANDED : opts.initialState);
}
get previousSize(): number {
return this._previousSize;
}
setBodySize(bodySize: number) {
this._bodySize = bodySize;
this.updateSize();
}
private updateSize() {
if (this.viewSizing === ViewSizing.Fixed) {
this.setFixed(this.state === CollapsibleState.EXPANDED ? this._bodySize + this.headerSize : this.headerSize);
} else {
this._minimumSize = this._bodySize + this.headerSize;
this._previousSize = !this.previousSize || this._previousSize < this._minimumSize ? this._minimumSize : this._previousSize;
if (this.state === CollapsibleState.EXPANDED) {
this.setFlexible(this._previousSize || this._minimumSize);
} else {
this._previousSize = this.size || this._minimumSize;
this.setFixed(this.headerSize);
}
}
}
render(container: HTMLElement, orientation: Orientation): void {
super.render(container, orientation);
......@@ -377,6 +404,7 @@ export abstract class AbstractCollapsibleView extends HeaderView {
}
this.layoutHeader();
this.updateSize();
}
dispose(): void {
......@@ -399,55 +427,6 @@ export abstract class AbstractCollapsibleView extends HeaderView {
}
}
export abstract class CollapsibleView extends AbstractCollapsibleView {
private previousSize: number;
constructor(opts: ICollapsibleViewOptions) {
super(opts);
this.previousSize = null;
}
protected changeState(state: CollapsibleState): void {
super.changeState(state);
if (state === CollapsibleState.EXPANDED) {
this.setFlexible(this.previousSize || this._minimumSize);
} else {
this.previousSize = this.size;
this.setFixed();
}
}
}
export interface IFixedCollapsibleViewOptions extends ICollapsibleViewOptions {
expandedBodySize?: number;
}
export abstract class FixedCollapsibleView extends AbstractCollapsibleView {
private _expandedBodySize: number;
constructor(opts: IFixedCollapsibleViewOptions) {
super(objects.mixin({ sizing: ViewSizing.Fixed }, opts));
this._expandedBodySize = types.isUndefined(opts.expandedBodySize) ? 22 : opts.expandedBodySize;
}
get fixedSize(): number { return this.state === CollapsibleState.EXPANDED ? this.expandedSize : this.headerSize; }
private get expandedSize(): number { return this.expandedBodySize + this.headerSize; }
get expandedBodySize(): number { return this._expandedBodySize; }
set expandedBodySize(size: number) {
this._expandedBodySize = size;
this.setFixed(this.fixedSize);
}
protected changeState(state: CollapsibleState): void {
super.changeState(state);
this.setFixed(this.fixedSize);
}
}
class PlainView extends View {
render() { }
focus() { }
......@@ -555,7 +534,7 @@ export class SplitView implements
}
/**
* Reset size to null. This will layout newly added viees to initial weights.
* Reset size to null. This will layout newly added views to initial weights.
*/
this.size = null;
......@@ -599,6 +578,14 @@ export class SplitView implements
this.viewFocusNextListeners.splice(index, 0, view.addListener('focusNext', () => index < this.views.length && this.views[index + 1].focus()));
}
updateWeight(view: IView, weight: number) {
let index = this.views.indexOf(view);
if (index < 0) {
return;
}
this.initialWeights[index] = weight;
}
removeView(view: IView): void {
let index = this.views.indexOf(view);
......@@ -606,6 +593,7 @@ export class SplitView implements
return;
}
this.size = null;
let deadView = new DeadView(view);
this.views[index] = deadView;
this.onViewChange(deadView, 0);
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IActionRunner } from 'vs/base/common/actions';
import { IViewletView } from 'vs/workbench/parts/views/browser/views';
// Debug view registration
export interface IDebugViewConstructorSignature {
new (actionRunner: IActionRunner, viewletSetings: any, ...services: { _serviceBrand: any; }[]): IViewletView;
}
export interface IDebugViewRegistry {
registerDebugView(view: IDebugViewConstructorSignature, order: number, weight: number): void;
getDebugViews(): { view: IDebugViewConstructorSignature, weight: number }[];
}
class DebugViewRegistryImpl implements IDebugViewRegistry {
private debugViews: { view: IDebugViewConstructorSignature, order: number, weight: number }[];
constructor() {
this.debugViews = [];
}
public registerDebugView(view: IDebugViewConstructorSignature, order: number, weight: number): void {
this.debugViews.push({ view, order, weight });
}
public getDebugViews(): { view: IDebugViewConstructorSignature, weight: number }[] {
return this.debugViews.sort((first, second) => first.order - second.order)
.map(viewWithOrder => ({ view: viewWithOrder.view, weight: viewWithOrder.weight }));
}
}
export const DebugViewRegistry = <IDebugViewRegistry>new DebugViewRegistryImpl();
......@@ -4,108 +4,49 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/debugViewlet';
import { Builder, Dimension } from 'vs/base/browser/builder';
import { Builder } from 'vs/base/browser/builder';
import * as DOM from 'vs/base/browser/dom';
import { TPromise } from 'vs/base/common/winjs.base';
import * as lifecycle from 'vs/base/common/lifecycle';
import { IAction } from 'vs/base/common/actions';
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { SplitView, HeaderView } from 'vs/base/browser/ui/splitview/splitview';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { Scope } from 'vs/workbench/common/memento';
import { Viewlet } from 'vs/workbench/browser/viewlet';
import { IViewletView } from 'vs/workbench/parts/views/browser/views';
import { ComposedViewsViewlet } from 'vs/workbench/parts/views/browser/views';
import { IDebugService, VIEWLET_ID, State } from 'vs/workbench/parts/debug/common/debug';
import { DebugViewRegistry } from 'vs/workbench/parts/debug/browser/debugViewRegistry';
import { StartAction, ToggleReplAction, ConfigureAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { StartDebugActionItem } from 'vs/workbench/parts/debug/browser/debugActionItems';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachHeaderViewStyler } from 'vs/platform/theme/common/styler';
import { ViewLocation } from 'vs/workbench/parts/views/browser/viewsRegistry';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
const DEBUG_VIEWS_WEIGHTS = 'debug.viewsweights';
export class DebugViewlet extends ComposedViewsViewlet {
export class DebugViewlet extends Viewlet {
private toDispose: lifecycle.IDisposable[];
private actions: IAction[];
private startDebugActionItem: StartDebugActionItem;
private progressRunner: IProgressRunner;
private viewletSettings: any;
private $el: Builder;
private splitView: SplitView;
private views: IViewletView[];
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IProgressService private progressService: IProgressService,
@IDebugService private debugService: IDebugService,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IStorageService private storageService: IStorageService,
@ILifecycleService lifecycleService: ILifecycleService,
@IThemeService themeService: IThemeService
@IInstantiationService instantiationService: IInstantiationService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IStorageService storageService: IStorageService,
@IThemeService themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService
) {
super(VIEWLET_ID, telemetryService, themeService);
super(VIEWLET_ID, ViewLocation.Debug, `${VIEWLET_ID}.state`, telemetryService, storageService, instantiationService, themeService, contextService, contextKeyService);
this.progressRunner = null;
this.viewletSettings = this.getMemento(storageService, Scope.WORKSPACE);
this.toDispose = [];
this.views = [];
this.toDispose.push(this.debugService.onDidChangeState(state => {
this.onDebugServiceStateChange(state);
}));
lifecycleService.onShutdown(this.store, this);
}
// viewlet
public create(parent: Builder): TPromise<void> {
super.create(parent);
this.$el = parent.div().addClass('debug-viewlet');
const actionRunner = this.getActionRunner();
const registeredViews = DebugViewRegistry.getDebugViews();
this.views = registeredViews.map(viewConstructor => this.instantiationService.createInstance(
viewConstructor.view,
actionRunner,
this.viewletSettings)
);
this.views.forEach((view, index) => {
if (view instanceof HeaderView) {
attachHeaderViewStyler(view, this.themeService, { noContrastBorder: index === 0 });
}
});
this.splitView = new SplitView(this.$el.getHTMLElement());
this.toDispose.push(this.splitView);
let weights: number[] = JSON.parse(this.storageService.get(DEBUG_VIEWS_WEIGHTS, StorageScope.WORKSPACE, '[]'));
if (!weights.length) {
weights = registeredViews.map(v => v.weight);
}
for (let i = 0; i < this.views.length; i++) {
this.splitView.addView(this.views[i], Math.max(weights[i], 1));
}
return TPromise.as(null);
}
public setVisible(visible: boolean): TPromise<any> {
return super.setVisible(visible).then(() => {
return TPromise.join(this.views.map(view => view.setVisible(visible)));
});
this._register(this.debugService.onDidChangeState(state => this.onDebugServiceStateChange(state)));
}
public layout(dimension: Dimension): void {
if (this.splitView) {
this.splitView.layout(dimension.height);
}
public create(parent: Builder): TPromise<void> {
return super.create(parent).then(() => DOM.addClass(this.viewletContainer, 'debug-viewlet'));
}
public focus(): void {
......@@ -127,16 +68,16 @@ export class DebugViewlet extends Viewlet {
if (this.contextService.hasWorkspace()) {
this.actions.push(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL));
}
this.actions.push(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL));
this.actions.forEach(a => {
this.toDispose.push(a);
});
this.actions.push(this._register(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL)));
}
return this.actions;
}
public getSecondaryActions(): IAction[] {
return [];
}
public getActionItem(action: IAction): IActionItem {
if (action.id === StartAction.ID && this.contextService.hasWorkspace()) {
this.startDebugActionItem = this.instantiationService.createInstance(StartDebugActionItem, null, action);
......@@ -157,19 +98,4 @@ export class DebugViewlet extends Viewlet {
this.progressRunner = null;
}
}
private store(): void {
this.storageService.store(DEBUG_VIEWS_WEIGHTS, JSON.stringify(this.views.map(view => view.size)), StorageScope.WORKSPACE);
}
public dispose(): void {
this.toDispose = lifecycle.dispose(this.toDispose);
super.dispose();
}
public shutdown(): void {
this.views.forEach(v => v.shutdown());
super.shutdown();
}
}
......@@ -15,7 +15,6 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'v
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionRegistryExtensions } from 'vs/workbench/common/actionRegistry';
import { ToggleViewletAction, Extensions as ViewletExtensions, ViewletRegistry, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { TogglePanelAction, Extensions as PanelExtensions, PanelRegistry, PanelDescriptor } from 'vs/workbench/browser/panel';
import { DebugViewRegistry } from 'vs/workbench/parts/debug/browser/debugViewRegistry';
import { VariablesView, WatchExpressionsView, CallStackView, BreakpointsView } from 'vs/workbench/parts/debug/electron-browser/debugViews';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { IDebugService, VIEWLET_ID, REPL_ID, CONTEXT_NOT_IN_DEBUG_MODE, CONTEXT_IN_DEBUG_MODE, INTERNAL_CONSOLE_OPTIONS_SCHEMA } from 'vs/workbench/parts/debug/common/debug';
......@@ -35,6 +34,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi
import * as debugCommands from 'vs/workbench/parts/debug/electron-browser/debugCommands';
import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
import { StatusBarColorProvider } from 'vs/workbench/parts/debug/electron-browser/statusbarColorProvider';
import { ViewLocation, ViewsRegistry } from 'vs/workbench/parts/views/browser/viewsRegistry';
class OpenDebugViewletAction extends ToggleViewletAction {
public static ID = VIEWLET_ID;
......@@ -94,10 +94,10 @@ Registry.as<PanelRegistry>(PanelExtensions.Panels).registerPanel(new PanelDescri
Registry.as<PanelRegistry>(PanelExtensions.Panels).setDefaultPanelId(REPL_ID);
// Register default debug views
DebugViewRegistry.registerDebugView(VariablesView, 10, 40);
DebugViewRegistry.registerDebugView(WatchExpressionsView, 20, 10);
DebugViewRegistry.registerDebugView(CallStackView, 30, 30);
DebugViewRegistry.registerDebugView(BreakpointsView, 40, 20);
ViewsRegistry.registerViews([{ id: 'workbench.debug.variablesView', name: '', ctor: VariablesView, order: 10, size: 40, location: ViewLocation.Debug }]);
ViewsRegistry.registerViews([{ id: 'workbench.debug.watchExpressionsView', name: '', ctor: WatchExpressionsView, order: 20, size: 10, location: ViewLocation.Debug }]);
ViewsRegistry.registerViews([{ id: 'workbench.debug.callStackView', name: '', ctor: CallStackView, order: 30, size: 30, location: ViewLocation.Debug }]);
ViewsRegistry.registerViews([{ id: 'workbench.debug.breakPointsView', name: '', ctor: BreakpointsView, order: 40, size: 20, location: ViewLocation.Debug }]);
// register action to open viewlet
const registry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionRegistryExtensions.WorkbenchActions);
......
......@@ -11,13 +11,13 @@ import * as builder from 'vs/base/browser/builder';
import { TPromise } from 'vs/base/common/winjs.base';
import * as errors from 'vs/base/common/errors';
import { EventType } from 'vs/base/common/events';
import { IActionRunner, IAction } from 'vs/base/common/actions';
import { IAction } from 'vs/base/common/actions';
import { prepareActions } from 'vs/workbench/browser/actions';
import { IHighlightEvent, ITree } from 'vs/base/parts/tree/browser/tree';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
import { CollapsibleState } from 'vs/base/browser/ui/splitview/splitview';
import { CollapsibleState, ViewSizing } from 'vs/base/browser/ui/splitview/splitview';
import { CollapseAction } from 'vs/workbench/browser/viewlet';
import { CollapsibleViewletView, AdaptiveCollapsibleViewletView } from 'vs/workbench/parts/views/browser/views';
import { CollapsibleView, IViewletViewOptions } from 'vs/workbench/parts/views/browser/views';
import { IDebugService, State, IBreakpoint, IExpression, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED } from 'vs/workbench/parts/debug/common/debug';
import { Expression, Variable, ExceptionBreakpoint, FunctionBreakpoint, Thread, StackFrame, Breakpoint, ThreadAndProcessIds } from 'vs/workbench/parts/debug/common/debugModel';
import * as viewer from 'vs/workbench/parts/debug/electron-browser/debugViewer';
......@@ -26,7 +26,6 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { MenuId } from 'vs/platform/actions/common/actions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IMessageService } from 'vs/platform/message/common/message';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IListService } from 'vs/platform/list/browser/listService';
......@@ -43,16 +42,15 @@ function renderViewTree(container: HTMLElement): HTMLElement {
const $ = builder.$;
const twistiePixels = 20;
export class VariablesView extends CollapsibleViewletView {
export class VariablesView extends CollapsibleView {
private static MEMENTO = 'variablesview.memento';
private onFocusStackFrameScheduler: RunOnceScheduler;
private variablesFocusedContext: IContextKey<boolean>;
private settings: any;
constructor(
actionRunner: IActionRunner,
private settings: any,
@IMessageService messageService: IMessageService,
options: IViewletViewOptions,
@IContextMenuService contextMenuService: IContextMenuService,
@ITelemetryService private telemetryService: ITelemetryService,
@IDebugService private debugService: IDebugService,
......@@ -62,8 +60,9 @@ export class VariablesView extends CollapsibleViewletView {
@IListService private listService: IListService,
@IThemeService private themeService: IThemeService
) {
super(actionRunner, !!settings[VariablesView.MEMENTO], nls.localize('variablesSection', "Variables Section"), messageService, keybindingService, contextMenuService);
super({ ...options, sizing: ViewSizing.Flexible, ariaHeaderLabel: nls.localize('variablesSection', "Variables Section") }, keybindingService, contextMenuService);
this.settings = options.viewletSettings;
this.variablesFocusedContext = CONTEXT_VARIABLES_FOCUSED.bindTo(contextKeyService);
// Use scheduler to prevent unnecessary flashing
this.onFocusStackFrameScheduler = new RunOnceScheduler(() => {
......@@ -151,17 +150,16 @@ export class VariablesView extends CollapsibleViewletView {
}
}
export class WatchExpressionsView extends CollapsibleViewletView {
export class WatchExpressionsView extends CollapsibleView {
private static MEMENTO = 'watchexpressionsview.memento';
private onWatchExpressionsUpdatedScheduler: RunOnceScheduler;
private toReveal: IExpression;
private watchExpressionsFocusedContext: IContextKey<boolean>;
private settings: any;
constructor(
actionRunner: IActionRunner,
private settings: any,
@IMessageService messageService: IMessageService,
options: IViewletViewOptions,
@IContextMenuService contextMenuService: IContextMenuService,
@IDebugService private debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
......@@ -170,7 +168,8 @@ export class WatchExpressionsView extends CollapsibleViewletView {
@IListService private listService: IListService,
@IThemeService private themeService: IThemeService
) {
super(actionRunner, !!settings[WatchExpressionsView.MEMENTO], nls.localize('expressionsSection', "Expressions Section"), messageService, keybindingService, contextMenuService);
super({ ...options, ariaHeaderLabel: nls.localize('expressionsSection', "Expressions Section"), sizing: ViewSizing.Flexible }, keybindingService, contextMenuService);
this.settings = options.viewletSettings;
this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(we => {
// only expand when a new watch expression is added.
......@@ -250,17 +249,16 @@ export class WatchExpressionsView extends CollapsibleViewletView {
}
}
export class CallStackView extends CollapsibleViewletView {
export class CallStackView extends CollapsibleView {
private static MEMENTO = 'callstackview.memento';
private pauseMessage: builder.Builder;
private pauseMessageLabel: builder.Builder;
private onCallStackChangeScheduler: RunOnceScheduler;
private settings: any;
constructor(
actionRunner: IActionRunner,
private settings: any,
@IMessageService messageService: IMessageService,
options: IViewletViewOptions,
@IContextMenuService contextMenuService: IContextMenuService,
@ITelemetryService private telemetryService: ITelemetryService,
@IDebugService private debugService: IDebugService,
......@@ -269,7 +267,8 @@ export class CallStackView extends CollapsibleViewletView {
@IListService private listService: IListService,
@IThemeService private themeService: IThemeService
) {
super(actionRunner, !!settings[CallStackView.MEMENTO], nls.localize('callstackSection', "Call Stack Section"), messageService, keybindingService, contextMenuService);
super({ ...options, ariaHeaderLabel: nls.localize('callstackSection', "Call Stack Section"), sizing: ViewSizing.Flexible }, keybindingService, contextMenuService);
this.settings = options.viewletSettings;
// Create scheduler to prevent unnecessary flashing of tree when reacting to changes
this.onCallStackChangeScheduler = new RunOnceScheduler(() => {
......@@ -385,15 +384,15 @@ export class CallStackView extends CollapsibleViewletView {
}
}
export class BreakpointsView extends AdaptiveCollapsibleViewletView {
export class BreakpointsView extends CollapsibleView {
private static MAX_VISIBLE_FILES = 9;
private static MEMENTO = 'breakopintsview.memento';
private breakpointsFocusedContext: IContextKey<boolean>;
private settings: any;
constructor(
actionRunner: IActionRunner,
private settings: any,
options: IViewletViewOptions,
@IContextMenuService contextMenuService: IContextMenuService,
@IDebugService private debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
......@@ -402,10 +401,14 @@ export class BreakpointsView extends AdaptiveCollapsibleViewletView {
@IListService private listService: IListService,
@IThemeService private themeService: IThemeService
) {
super(actionRunner, BreakpointsView.getExpandedBodySize(
debugService.getModel().getBreakpoints().length + debugService.getModel().getFunctionBreakpoints().length + debugService.getModel().getExceptionBreakpoints().length),
!!settings[BreakpointsView.MEMENTO], nls.localize('breakpointsSection', "Breakpoints Section"), keybindingService, contextMenuService);
super({
...options,
ariaHeaderLabel: nls.localize('breakpointsSection', "Breakpoints Section"),
sizing: ViewSizing.Fixed, initialBodySize: BreakpointsView.getExpandedBodySize(
debugService.getModel().getBreakpoints().length + debugService.getModel().getFunctionBreakpoints().length + debugService.getModel().getExceptionBreakpoints().length)
}, keybindingService, contextMenuService);
this.settings = options.viewletSettings;
this.breakpointsFocusedContext = CONTEXT_BREAKPOINTS_FOCUSED.bindTo(contextKeyService);
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.onBreakpointsChange()));
}
......@@ -503,8 +506,8 @@ export class BreakpointsView extends AdaptiveCollapsibleViewletView {
private onBreakpointsChange(): void {
const model = this.debugService.getModel();
this.expandedBodySize = BreakpointsView.getExpandedBodySize(
model.getBreakpoints().length + model.getExceptionBreakpoints().length + model.getFunctionBreakpoints().length);
this.setBodySize(BreakpointsView.getExpandedBodySize(
model.getBreakpoints().length + model.getExceptionBreakpoints().length + model.getFunctionBreakpoints().length));
if (this.tree) {
this.tree.refresh();
......
......@@ -11,7 +11,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import * as DOM from 'vs/base/browser/dom';
import { Builder } from 'vs/base/browser/builder';
import { VIEWLET_ID, ExplorerViewletVisibleContext, IFilesConfiguration } from 'vs/workbench/parts/files/common/files';
import { ComposedViewsViewlet, IViewletView, IViewletViewOptions } from 'vs/workbench/parts/views/browser/views';
import { ComposedViewsViewlet, IView, IViewletViewOptions } from 'vs/workbench/parts/views/browser/views';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ActionRunner, FileViewletState } from 'vs/workbench/parts/files/browser/views/explorerViewer';
import { ExplorerView, IExplorerViewOptions } from 'vs/workbench/parts/files/browser/views/explorerView';
......@@ -49,7 +49,7 @@ export class ExplorerViewlet extends ComposedViewsViewlet {
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService
) {
super(VIEWLET_ID, ViewLocation.Explorer, ExplorerViewlet.EXPLORER_VIEWS_STATE, telemetryService, storageService, instantiationService, themeService, contextService);
super(VIEWLET_ID, ViewLocation.Explorer, ExplorerViewlet.EXPLORER_VIEWS_STATE, telemetryService, storageService, instantiationService, themeService, contextService, contextKeyService);
this.viewletState = new FileViewletState();
this.viewletVisibleContextKey = ExplorerViewletVisibleContext.bindTo(contextKeyService);
......@@ -124,7 +124,7 @@ export class ExplorerViewlet extends ComposedViewsViewlet {
return !this.contextService.hasWorkspace() || (<IFilesConfiguration>this.configurationService.getConfiguration()).explorer.openEditors.visible !== 0;
}
protected createView(viewDescriptor: IViewDescriptor, options: IViewletViewOptions): IViewletView {
protected createView(viewDescriptor: IViewDescriptor, options: IViewletViewOptions): IView {
if (viewDescriptor.id === ExplorerView.ID) {
// Create a delegating editor service for the explorer to be able to delay the refresh in the opened
// editors view above. This is a workaround for being able to double click on a file to make it pinned
......@@ -164,7 +164,7 @@ export class ExplorerViewlet extends ComposedViewsViewlet {
});
const explorerInstantiator = this.instantiationService.createChild(new ServiceCollection([IWorkbenchEditorService, delegatingEditorService]));
return explorerInstantiator.createInstance(ExplorerView, viewDescriptor.id, <IExplorerViewOptions>{ ...options, viewletState: this.viewletState });
return explorerInstantiator.createInstance(ExplorerView, <IExplorerViewOptions>{ ...options, viewletState: this.viewletState });
}
return super.createView(viewDescriptor, options);
}
......@@ -222,7 +222,7 @@ export class ExplorerViewlet extends ComposedViewsViewlet {
super.focus();
}
private hasSelectionOrFocus(view: IViewletView): boolean {
private hasSelectionOrFocus(view: IView): boolean {
if (!view) {
return false;
}
......
......@@ -13,32 +13,29 @@ import { IAction } from 'vs/base/common/actions';
import { Button } from 'vs/base/browser/ui/button/button';
import { $ } from 'vs/base/browser/builder';
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { CollapsibleViewletView } from 'vs/workbench/parts/views/browser/views';
import { CollapsibleView, IViewletViewOptions } from 'vs/workbench/parts/views/browser/views';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { OpenFolderAction, OpenFileFolderAction } from 'vs/workbench/browser/actions/fileActions';
import { attachButtonStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IViewOptions } from 'vs/workbench/parts/views/browser/viewsRegistry';
import { IMessageService } from 'vs/platform/message/common/message';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { ViewSizing } from 'vs/base/browser/ui/splitview/splitview';
export class EmptyView extends CollapsibleViewletView {
export class EmptyView extends CollapsibleView {
public static ID: string = 'workbench.explorer.emptyView';
private openFolderButton: Button;
constructor(
readonly id: string,
options: IViewOptions,
options: IViewletViewOptions,
@IThemeService private themeService: IThemeService,
@IInstantiationService private instantiationService: IInstantiationService,
@IMessageService messageService: IMessageService,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService
) {
super(options.actionRunner, options.collapsed, nls.localize('explorerSection', "Files Explorer Section"), messageService, keybindingService, contextMenuService, void 0, 5 * 22);
super({ ...options, ariaHeaderLabel: nls.localize('explorerSection', "Files Explorer Section"), sizing: ViewSizing.Flexible }, keybindingService, contextMenuService);
}
public renderHeader(container: HTMLElement): void {
......
......@@ -25,7 +25,7 @@ import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import * as DOM from 'vs/base/browser/dom';
import { CollapseAction } from 'vs/workbench/browser/viewlet';
import { CollapsibleViewletView, IViewletViewOptions } from 'vs/workbench/parts/views/browser/views';
import { CollapsibleView, IViewletViewOptions } from 'vs/workbench/parts/views/browser/views';
import { FileStat } from 'vs/workbench/parts/files/common/explorerViewModel';
import { IListService } from 'vs/platform/list/browser/listService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -43,12 +43,13 @@ import { IWorkbenchThemeService, IFileIconTheme } from 'vs/workbench/services/th
import { isLinux } from 'vs/base/common/platform';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { ViewSizing } from 'vs/base/browser/ui/splitview/splitview';
export interface IExplorerViewOptions extends IViewletViewOptions {
viewletState: FileViewletState;
}
export class ExplorerView extends CollapsibleViewletView {
export class ExplorerView extends CollapsibleView {
public static ID: string = 'workbench.explorer.fileView';
private static EXPLORER_FILE_CHANGES_REACT_DELAY = 500; // delay in ms to react to file changes to give our internal events a chance to react first
......@@ -82,9 +83,8 @@ export class ExplorerView extends CollapsibleViewletView {
private settings: any;
constructor(
id: string,
options: IExplorerViewOptions,
@IMessageService messageService: IMessageService,
@IMessageService private messageService: IMessageService,
@IContextMenuService contextMenuService: IContextMenuService,
@IInstantiationService private instantiationService: IInstantiationService,
@IEditorGroupService private editorGroupService: IEditorGroupService,
......@@ -100,7 +100,7 @@ export class ExplorerView extends CollapsibleViewletView {
@IWorkbenchThemeService private themeService: IWorkbenchThemeService,
@IEnvironmentService private environmentService: IEnvironmentService
) {
super(options.actionRunner, options.collapsed, nls.localize('explorerSection', "Files Explorer Section"), messageService, keybindingService, contextMenuService);
super({ ...options, ariaHeaderLabel: nls.localize('explorerSection', "Files Explorer Section"), sizing: ViewSizing.Flexible }, keybindingService, contextMenuService);
this.settings = options.viewletSettings;
this.viewletState = options.viewletState;
......
......@@ -18,7 +18,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IEditorStacksModel, IStacksModelChangeEvent, IEditorGroup } from 'vs/workbench/common/editor';
import { SaveAllAction } from 'vs/workbench/parts/files/browser/fileActions';
import { AdaptiveCollapsibleViewletView } from 'vs/workbench/parts/views/browser/views';
import { CollapsibleView, IViewletViewOptions } from 'vs/workbench/parts/views/browser/views';
import { IFilesConfiguration, VIEWLET_ID, OpenEditorsFocussedContext, ExplorerFocussedContext } from 'vs/workbench/parts/files/common/files';
import { ITextFileService, AutoSaveMode } from 'vs/workbench/services/textfile/common/textfiles';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
......@@ -33,11 +33,11 @@ import { EditorGroup } from 'vs/workbench/common/editor/editorStacksModel';
import { attachListStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { badgeBackground, badgeForeground, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { IViewOptions } from 'vs/workbench/parts/views/browser/viewsRegistry';
import { ViewSizing } from 'vs/base/browser/ui/splitview/splitview';
const $ = dom.$;
export class OpenEditorsView extends AdaptiveCollapsibleViewletView {
export class OpenEditorsView extends CollapsibleView {
private static DEFAULT_VISIBLE_OPEN_EDITORS = 9;
private static DEFAULT_DYNAMIC_HEIGHT = true;
......@@ -56,7 +56,7 @@ export class OpenEditorsView extends AdaptiveCollapsibleViewletView {
private openEditorsFocussedContext: IContextKey<boolean>;
private explorerFocussedContext: IContextKey<boolean>;
constructor(readonly id: string, options: IViewOptions,
constructor(options: IViewletViewOptions,
@IInstantiationService private instantiationService: IInstantiationService,
@IContextMenuService contextMenuService: IContextMenuService,
@ITextFileService private textFileService: ITextFileService,
......@@ -69,7 +69,12 @@ export class OpenEditorsView extends AdaptiveCollapsibleViewletView {
@IViewletService private viewletService: IViewletService,
@IThemeService private themeService: IThemeService
) {
super(options.actionRunner, OpenEditorsView.computeExpandedBodySize(editorGroupService.getStacksModel()), options.collapsed, nls.localize({ key: 'openEditosrSection', comment: ['Open is an adjective'] }, "Open Editors Section"), keybindingService, contextMenuService);
super({
...options,
ariaHeaderLabel: nls.localize({ key: 'openEditosrSection', comment: ['Open is an adjective'] }, "Open Editors Section"),
sizing: ViewSizing.Fixed,
initialBodySize: OpenEditorsView.computeExpandedBodySize(editorGroupService.getStacksModel())
}, keybindingService, contextMenuService);
this.model = editorGroupService.getStacksModel();
......@@ -223,7 +228,7 @@ export class OpenEditorsView extends AdaptiveCollapsibleViewletView {
private structuralTreeUpdate(): void {
// View size
this.expandedBodySize = this.getExpandedBodySize(this.model);
this.setBodySize(this.getExpandedBodySize(this.model));
// Show groups only if there is more than 1 group
const treeInput = this.model.groups.length === 1 ? this.model.groups[0] : this.model;
// TODO@Isidor temporary workaround due to a partial tree refresh issue
......@@ -277,7 +282,7 @@ export class OpenEditorsView extends AdaptiveCollapsibleViewletView {
}
// Adjust expanded body size
this.expandedBodySize = this.getExpandedBodySize(this.model);
this.setBodySize(this.getExpandedBodySize(this.model));
}
private updateDirtyIndicator(): void {
......
......@@ -6,7 +6,6 @@
import 'vs/css!./media/views';
import Event, { Emitter } from 'vs/base/common/event';
import { IDisposable, dispose, empty as EmptyDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { CollapsibleViewletView } from 'vs/workbench/parts/views/browser/views';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { TPromise } from 'vs/base/common/winjs.base';
import * as DOM from 'vs/base/browser/dom';
......@@ -26,13 +25,14 @@ import { IProgressService } from 'vs/platform/progress/common/progress';
import { ITree, IDataSource, IRenderer, ContextMenuEvent } from 'vs/base/parts/tree/browser/tree';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { ActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { ViewsRegistry, IViewOptions } from 'vs/workbench/parts/views/browser/viewsRegistry';
import { ViewsRegistry } from 'vs/workbench/parts/views/browser/viewsRegistry';
import { ITreeViewDataProvider, ITreeItem, TreeItemCollapsibleState, TreeViewItemHandleArg } from 'vs/workbench/parts/views/common/views';
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
import { CollapsibleState } from 'vs/base/browser/ui/splitview/splitview';
import { CollapsibleState, ViewSizing } from 'vs/base/browser/ui/splitview/splitview';
import { CollapsibleView, IViewletViewOptions } from 'vs/workbench/parts/views/browser/views';
import { ICommandService } from 'vs/platform/commands/common/commands';
export class TreeView extends CollapsibleViewletView {
export class TreeView extends CollapsibleView {
private menus: Menus;
private viewFocusContext: IContextKey<boolean>;
......@@ -44,9 +44,8 @@ export class TreeView extends CollapsibleViewletView {
private disposables: IDisposable[] = [];
constructor(
readonly id: string,
private options: IViewOptions,
@IMessageService messageService: IMessageService,
private options: IViewletViewOptions,
@IMessageService private messageService: IMessageService,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IInstantiationService private instantiationService: IInstantiationService,
......@@ -56,7 +55,7 @@ export class TreeView extends CollapsibleViewletView {
@IExtensionService private extensionService: IExtensionService,
@ICommandService private commandService: ICommandService
) {
super(options.actionRunner, options.collapsed, options.name, messageService, keybindingService, contextMenuService);
super({ ...options, ariaHeaderLabel: options.name, sizing: ViewSizing.Flexible, collapsed: options.collapsed === void 0 ? true : options.collapsed }, keybindingService, contextMenuService);
this.menus = this.instantiationService.createInstance(Menus, this.id);
this.viewFocusContext = this.contextKeyService.createKey<boolean>(this.id, void 0);
this.menus.onDidChangeTitle(() => this.updateActions(), this, this.disposables);
......@@ -128,21 +127,27 @@ export class TreeView extends CollapsibleViewletView {
return super.setVisible(visible);
}
public setInput(): TPromise<void> {
if (this.listenToDataProvider()) {
this.treeInputPromise = this.tree.setInput(new Root());
return this.treeInputPromise;
}
this.treeInputPromise = new TPromise<void>((c, e) => {
this.dataProviderRegisteredListener = ViewsRegistry.onTreeViewDataProviderRegistered(id => {
if (this.id === id) {
if (this.listenToDataProvider()) {
this.tree.setInput(new Root()).then(() => c(null));
this.dataProviderRegisteredListener.dispose();
public create(): TPromise<void> {
return super.create().then(() => this.setInput());
}
private setInput(): TPromise<void> {
if (this.tree && !this.treeInputPromise) {
if (this.listenToDataProvider()) {
this.treeInputPromise = this.tree.setInput(new Root());
return this.treeInputPromise;
}
this.treeInputPromise = new TPromise<void>((c, e) => {
this.dataProviderRegisteredListener = ViewsRegistry.onTreeViewDataProviderRegistered(id => {
if (this.id === id) {
if (this.listenToDataProvider()) {
this.tree.setInput(new Root()).then(() => c(null));
this.dataProviderRegisteredListener.dispose();
}
}
}
});
});
});
}
return TPromise.as(null);
}
......
......@@ -10,6 +10,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
import { ViewLocation, ViewsRegistry } from 'vs/workbench/parts/views/browser/viewsRegistry';
import { TreeView } from 'vs/workbench/parts/views/browser/treeView';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
namespace schema {
......@@ -18,6 +19,7 @@ namespace schema {
export interface IUserFriendlyViewDescriptor {
id: string;
name: string;
when?: string;
}
export function parseLocation(value: string): ViewLocation {
......@@ -42,6 +44,10 @@ namespace schema {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'label'));
return false;
}
if (descriptor.when && typeof descriptor.when !== 'string') {
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
return false;
}
}
return true;
......@@ -57,7 +63,11 @@ namespace schema {
name: {
description: localize('vscode.extension.contributes.view.name', 'The human-readable name of the view. Will be shown'),
type: 'string'
}
},
when: {
description: localize('vscode.extension.contributes.view.when', 'Condition which must be true to show this view'),
type: 'string'
},
}
};
......@@ -93,7 +103,8 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyV
id: item.id,
name: item.name,
ctor: TreeView,
location
location,
when: ContextKeyExpr.deserialize(item.when)
}));
ViewsRegistry.registerViews(viewDescriptors);
});
......
......@@ -4,13 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import Event, { Emitter } from 'vs/base/common/event';
import { IActionRunner } from 'vs/base/common/actions';
import { IViewletView as IView } from 'vs/workbench/parts/views/browser/views';
import { IViewConstructorSignature } from 'vs/workbench/parts/views/browser/views';
import { ITreeViewDataProvider } from 'vs/workbench/parts/views/common/views';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
export class ViewLocation {
static readonly Explorer = new ViewLocation('explorer');
static readonly Debug = new ViewLocation('debug');
constructor(private _id: string) {
}
......@@ -20,18 +21,6 @@ export class ViewLocation {
}
}
export interface IViewOptions {
name: string;
actionRunner: IActionRunner;
collapsed: boolean;
}
export interface IViewConstructorSignature {
new (id: string, options: IViewOptions, ...services: { _serviceBrand: any; }[]): IView;
}
export interface IViewDescriptor {
readonly id: string;
......@@ -42,8 +31,11 @@ export interface IViewDescriptor {
readonly ctor: IViewConstructorSignature;
readonly when?: ContextKeyExpr;
readonly order?: number;
readonly size?: number;
}
export interface IViewsRegistry {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册