提交 fd50714f 编写于 作者: J Johannes Rieken

let the keybinding service act as scope when creating a menu

上级 b6f56489
......@@ -31,10 +31,10 @@ class ContextMenuController implements IEditorContribution {
public static ID = 'editor.contrib.contextmenu';
private _toDispose: IDisposable[] = [];
private _contextMenuIsBeingShownCount: number = 0;
private _editor: ICodeEditor;
private _contextMenu: IMenu;
private _toDispose: IDisposable[];
private _contextMenuIsBeingShownCount: number;
constructor(
editor: ICodeEditor,
......@@ -45,8 +45,8 @@ class ContextMenuController implements IEditorContribution {
) {
this._editor = editor;
this._toDispose = [];
this._contextMenuIsBeingShownCount = 0;
this._contextMenu = this._menuService.createMenu(MenuId.EditorContext, this._keybindingService);
this._toDispose.push(this._contextMenu);
this._toDispose.push(this._editor.onContextMenu((e: IEditorMouseEvent) => this._onContextMenu(e)));
this._toDispose.push(this._editor.onKeyDown((e: IKeyboardEvent) => {
......@@ -79,12 +79,6 @@ class ContextMenuController implements IEditorContribution {
return; // only support mouse click into text or native context menu key for now
}
// Ensure menu is there
if (!this._contextMenu) {
this._contextMenu = this._menuService.createMenu(MenuId.EditorContext, this._editor.getDomNode());
this._toDispose.push(this._contextMenu);
}
// Ensure the editor gets focus if it hasn't, so the right events are being sent to other contributions
this._editor.focus();
......
......@@ -10,7 +10,7 @@ import Event, {Emitter} from 'vs/base/common/event';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IAction} from 'vs/base/common/actions';
import {values} from 'vs/base/common/collections';
import {KbExpr, IKeybindingScopeLocation, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {KbExpr, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {MenuId, CommandAction, MenuItemAction, IMenu, IMenuItem, IMenuService} from 'vs/platform/actions/common/actions';
import {IExtensionService} from 'vs/platform/extensions/common/extensions';
import {ResourceContextKey} from 'vs/platform/actions/common/resourceContextKey';
......@@ -67,14 +67,13 @@ export class MenuService implements IMenuService {
serviceId = IMenuService;
constructor(
@IKeybindingService private _keybindingService: IKeybindingService,
@IExtensionService private _extensionService: IExtensionService
) {
//
}
createMenu(id: MenuId, scope: IKeybindingScopeLocation): IMenu {
return new Menu(scope, id, this._keybindingService, this._extensionService);
createMenu(id: MenuId, keybindingService: IKeybindingService): IMenu {
return new Menu(id, keybindingService, this._extensionService);
}
getCommandActions(): CommandAction[] {
......@@ -84,18 +83,15 @@ export class MenuService implements IMenuService {
class Menu implements IMenu {
private _scope: IKeybindingScopeLocation;
private _menuItems: IMenuItem[] = [];
private _disposables: IDisposable[] = [];
private _onDidChange = new Emitter<IMenu>();
constructor(
scope: IKeybindingScopeLocation,
id: MenuId,
@IKeybindingService private _keybindingService: IKeybindingService,
@IExtensionService private _extensionService: IExtensionService
) {
this._scope = scope;
this._extensionService.onReady().then(_ => {
let menuItems = _registry.getMenuItems(id);
......@@ -139,9 +135,9 @@ class Menu implements IMenu {
getActions(): IAction[] {
const result: IAction[] = [];
for (let item of this._menuItems) {
if (this._keybindingService.contextMatchesRules(this._scope, item.when)) {
if (this._keybindingService.contextMatchesRules(item.when)) {
result.push(new MenuItemAction(item,
this._keybindingService.getContextValue<URI>(this._scope, ResourceContextKey.Resource),
this._keybindingService.getContextValue<URI>(ResourceContextKey.Resource),
this._keybindingService));
}
}
......
......@@ -10,7 +10,7 @@ import WinJS = require('vs/base/common/winjs.base');
import Assert = require('vs/base/common/assert');
import Descriptors = require('vs/platform/instantiation/common/descriptors');
import Instantiation = require('vs/platform/instantiation/common/instantiation');
import {KbExpr, IKeybindings, IKeybindingService, IKeybindingScopeLocation} from 'vs/platform/keybinding/common/keybindingService';
import {KbExpr, IKeybindings, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {IDisposable} from 'vs/base/common/lifecycle';
import {createDecorator} from 'vs/platform/instantiation/common/instantiation';
import Event from 'vs/base/common/event';
......@@ -45,7 +45,7 @@ export interface IMenuService {
serviceId: any;
createMenu(id: MenuId, scope: IKeybindingScopeLocation): IMenu;
createMenu(id: MenuId, scopedKeybindingService: IKeybindingService): IMenu;
getCommandActions(): CommandAction[];
}
......
......@@ -27,9 +27,9 @@ import Event, {Emitter, debounceEvent} from 'vs/base/common/event';
let KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';
export class KeybindingContext {
private _parent: KeybindingContext;
private _value: any;
private _id: number;
protected _parent: KeybindingContext;
protected _value: any;
protected _id: number;
constructor(id: number, parent: KeybindingContext) {
this._id = id;
......@@ -51,6 +51,14 @@ export class KeybindingContext {
return delete this._value[key];
}
public getValue<T>(key: string): T {
const ret = this._value[key];
if (typeof ret === 'undefined' && this._parent) {
return this._parent.getValue<T>(key);
}
return ret;
}
public fillInContext(bucket: any): void {
if (this._parent) {
this._parent.fillInContext(bucket);
......@@ -61,12 +69,15 @@ export class KeybindingContext {
}
}
export class ConfigurationContext {
class ConfigAwareKeybindingContext extends KeybindingContext {
private _emitter: Emitter<string>;
private _subscription: IDisposable;
private _values: any;
constructor(configurationService: IConfigurationService) {
constructor(id: number, configurationService: IConfigurationService, emitter:Emitter<string>) {
super(id, null);
this._emitter = emitter;
this._subscription = configurationService.onDidUpdateConfiguration(e => this._updateConfigurationContext(e.config));
this._updateConfigurationContext(configurationService.getConfiguration());
}
......@@ -76,14 +87,24 @@ export class ConfigurationContext {
}
private _updateConfigurationContext(config: any) {
this._values = Object.create(null);
// remove old config.xyz values
for (let key in this._value) {
if (key.indexOf('config.') === 0) {
delete this._value[key];
}
}
// add new value from config
const walk = (obj: any, keys: string[]) => {
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
keys.push(key);
let value = obj[key];
if (typeof value === 'boolean') {
this._values[keys.join('.')] = value;
const configKey = keys.join('.');
this._value[configKey] = value;
this._emitter.fire(configKey);
} else if (typeof value === 'object') {
walk(value, keys);
}
......@@ -93,15 +114,6 @@ export class ConfigurationContext {
};
walk(config, ['config']);
}
public fillInContext(bucket: any): void {
if (this._values) {
for (let key in this._values) {
bucket[key] = this._values[key];
}
}
}
}
class KeybindingContextKey<T> implements IKeybindingContextKey<T> {
......@@ -151,10 +163,6 @@ export abstract class AbstractKeybindingService {
return new KeybindingContextKey(this, key, defaultValue);
}
public abstract contextMatchesRules(domNode: HTMLElement, rules: KbExpr): boolean;
public abstract getContextValue<T>(domNode: HTMLElement, key: string): T;
public get onDidChangeContext(): Event<string[]> {
if (!this._onDidChangeContext) {
this._onDidChangeContext = debounceEvent(this._onDidChangeContextKey.event, (prev: string[], cur) => {
......@@ -177,6 +185,17 @@ export abstract class AbstractKeybindingService {
return new ScopedKeybindingService(this, this._onDidChangeContextKey, domNode);
}
public contextMatchesRules(rules: KbExpr): boolean {
const ctx = Object.create(null);
this.getContext(this._myContextId).fillInContext(ctx);
// console.log(JSON.stringify(ctx, null, '\t'));
return KeybindingResolver.contextMatchesRules(ctx, rules);
}
public getContextValue<T>(key: string): T {
return this.getContext(this._myContextId).getValue<T>(key);
}
public setContext(key: string, value: any): void {
if(this.getContext(this._myContextId).setValue(key, value)) {
this._onDidChangeContextKey.fire(key);
......@@ -215,7 +234,6 @@ export abstract class KeybindingService extends AbstractKeybindingService implem
};
private _toDispose: IDisposable[] = [];
private _configurationContext: ConfigurationContext;
private _cachedResolver: KeybindingResolver;
private _firstTimeComputingResolver: boolean;
private _currentChord: number;
......@@ -227,13 +245,15 @@ export abstract class KeybindingService extends AbstractKeybindingService implem
super(0);
this._lastContextId = 0;
this._contexts = Object.create(null);
this._contexts[String(this._myContextId)] = new KeybindingContext(this._myContextId, null);
const myContext = new ConfigAwareKeybindingContext(this._myContextId, configurationService, this._onDidChangeContextKey);
this._contexts[String(this._myContextId)] = myContext;
this._toDispose.push(myContext);
this._cachedResolver = null;
this._firstTimeComputingResolver = true;
this._currentChord = 0;
this._currentChordStatusMessage = null;
this._configurationContext = new ConfigurationContext(configurationService);
this._toDispose.push(this._configurationContext);
this._statusService = statusService;
this._messageService = messageService;
}
......@@ -257,21 +277,6 @@ export abstract class KeybindingService extends AbstractKeybindingService implem
this._toDispose = dispose(this._toDispose);
}
public contextMatchesRules(domNode: HTMLElement, rules: KbExpr): boolean {
const ctx = Object.create(null);
this.getContext(this._findContextAttr(domNode)).fillInContext(ctx);
this._configurationContext.fillInContext(ctx);
// console.log(JSON.stringify(ctx, null, '\t'));
return KeybindingResolver.contextMatchesRules(ctx, rules);
}
public getContextValue<T>(domNode: HTMLElement, key: string): T {
const ctx = Object.create(null);
this.getContext(this._findContextAttr(domNode)).fillInContext(ctx);
this._configurationContext.fillInContext(ctx);
return <T>ctx[key];
}
public getLabelFor(keybinding: Keybinding): string {
return keybinding._toUSLabel();
}
......@@ -344,7 +349,6 @@ export abstract class KeybindingService extends AbstractKeybindingService implem
let contextValue = Object.create(null);
this.getContext(this._findContextAttr(e.target)).fillInContext(contextValue);
this._configurationContext.fillInContext(contextValue);
// console.log(JSON.stringify(contextValue, null, '\t'));
let resolveResult = this._getResolver().resolve(contextValue, this._currentChord, e.asKeybinding());
......@@ -459,14 +463,6 @@ class ScopedKeybindingService extends AbstractKeybindingService {
return this._parent.onDidChangeContext;
}
public contextMatchesRules(domNode: HTMLElement, rules: KbExpr): boolean {
return this._parent.contextMatchesRules(domNode, rules);
}
public getContextValue<T>(domNode: HTMLElement, key: string): T {
return this._parent.getContextValue<T>(domNode, key);
}
public getLabelFor(keybinding: Keybinding): string {
return this._parent.getLabelFor(keybinding);
}
......
......@@ -436,8 +436,6 @@ export let IKeybindingService = createDecorator<IKeybindingService>('keybindingS
export interface IKeybindingScopeLocation {
setAttribute(attr: string, value: string): void;
removeAttribute(attr: string): void;
hasAttribute(attr: string): boolean;
getAttribute(attr: string): string;
}
export interface IKeybindingService {
......@@ -446,8 +444,8 @@ export interface IKeybindingService {
onDidChangeContext: Event<string[]>;
createKey<T>(key: string, defaultValue: T): IKeybindingContextKey<T>;
contextMatchesRules(domNode: IKeybindingScopeLocation, rules: KbExpr): boolean;
getContextValue<T>(domNode: IKeybindingScopeLocation, key: string): T;
contextMatchesRules(rules: KbExpr): boolean;
getContextValue<T>(key: string): T;
createScoped(domNode: IKeybindingScopeLocation): IKeybindingService;
......
......@@ -40,13 +40,13 @@ export class MockKeybindingService implements IKeybindingService {
public createKey<T>(key: string, defaultValue: T): IKeybindingContextKey<T> {
return new MockKeybindingContextKey(key, defaultValue);
}
public contextMatchesRules(domNode: HTMLElement, rules: KbExpr): boolean {
public contextMatchesRules(rules: KbExpr): boolean {
return false;
}
public get onDidChangeContext(): Event<string[]> {
return Event.None;
}
public getContextValue(domNode: HTMLElement, key: string) {
public getContextValue(key: string) {
return;
}
......
......@@ -33,7 +33,6 @@ export class NoTabsTitleControl extends TitleControl {
}
public create(parent: HTMLElement): void {
super.create(parent);
this.titleContainer = parent;
// Pin on double click
......
......@@ -75,7 +75,6 @@ export class TabsTitleControl extends TitleControl {
}
public create(parent: HTMLElement): void {
super.create(parent);
this.titleContainer = parent;
// Tabs Container
......
......@@ -101,6 +101,10 @@ export abstract class TitleControl implements ITitleAreaControl {
this.resourceContext = instantiationService.createInstance(ResourceContextKey);
this.contributedTitleBarMenu = this.menuService.createMenu(MenuId.EditorTitle, this.keybindingService);
this.toDispose.push(this.contributedTitleBarMenu);
this.toDispose.push(this.contributedTitleBarMenu.onDidChange(e => this.refresh()));
this.initActions();
this.registerListeners();
}
......@@ -178,11 +182,8 @@ export abstract class TitleControl implements ITitleAreaControl {
}
}
public create(parent: HTMLElement): void {
this.contributedTitleBarMenu = this.menuService.createMenu(MenuId.EditorTitle, parent);
this.toDispose.push(this.contributedTitleBarMenu);
this.toDispose.push(this.contributedTitleBarMenu.onDidChange(e => this.refresh()));
}
public abstract create(parent: HTMLElement): void;
protected abstract doRefresh(): void;
......
......@@ -38,6 +38,7 @@ import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/edito
import {IPartService} from 'vs/workbench/services/part/common/partService';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IWorkspace} from 'vs/platform/workspace/common/workspace';
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {IContextViewService, IContextMenuService} from 'vs/platform/contextview/browser/contextView';
import {IEventService} from 'vs/platform/event/common/event';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
......@@ -367,10 +368,13 @@ export class FileController extends DefaultController {
@IInstantiationService private instantiationService: IInstantiationService,
@ITelemetryService private telemetryService: ITelemetryService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IMenuService private menuService: IMenuService
@IMenuService menuService: IMenuService,
@IKeybindingService keybindingService: IKeybindingService
) {
super({ clickBehavior: ClickBehavior.ON_MOUSE_DOWN });
this.contributedContextMenu = menuService.createMenu(MenuId.ExplorerContext, keybindingService);
this.workspace = contextService.getWorkspace();
this.didCatchEnterDown = false;
......@@ -466,10 +470,6 @@ export class FileController extends DefaultController {
return false;
}
if (!this.contributedContextMenu) {
this.contributedContextMenu = this.menuService.createMenu(MenuId.ExplorerContext, tree.getHTMLElement());
}
event.preventDefault();
event.stopPropagation();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册