mirror of
https://github.com/Microsoft/vscode
synced 2024-10-30 19:48:09 +00:00
debt - more builder cleanup
This commit is contained in:
parent
c4aa2b5da3
commit
dbd3e70395
17 changed files with 276 additions and 301 deletions
|
@ -5,7 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import * as DomUtils from 'vs/base/browser/dom';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
|
||||
|
@ -64,7 +64,7 @@ interface TouchEvent extends Event {
|
|||
changedTouches: TouchList;
|
||||
}
|
||||
|
||||
export class Gesture implements IDisposable {
|
||||
export class Gesture extends Disposable {
|
||||
|
||||
private static readonly SCROLL_FRICTION = -0.005;
|
||||
private static INSTANCE: Gesture;
|
||||
|
@ -72,19 +72,19 @@ export class Gesture implements IDisposable {
|
|||
|
||||
private dispatched: boolean;
|
||||
private targets: HTMLElement[];
|
||||
private toDispose: IDisposable[];
|
||||
private handle: IDisposable;
|
||||
|
||||
private activeTouches: { [id: number]: TouchData; };
|
||||
|
||||
private constructor() {
|
||||
this.toDispose = [];
|
||||
super();
|
||||
|
||||
this.activeTouches = {};
|
||||
this.handle = null;
|
||||
this.targets = [];
|
||||
this.toDispose.push(DomUtils.addDisposableListener(document, 'touchstart', (e) => this.onTouchStart(e)));
|
||||
this.toDispose.push(DomUtils.addDisposableListener(document, 'touchend', (e) => this.onTouchEnd(e)));
|
||||
this.toDispose.push(DomUtils.addDisposableListener(document, 'touchmove', (e) => this.onTouchMove(e)));
|
||||
this._register(DomUtils.addDisposableListener(document, 'touchstart', (e) => this.onTouchStart(e)));
|
||||
this._register(DomUtils.addDisposableListener(document, 'touchend', (e) => this.onTouchEnd(e)));
|
||||
this._register(DomUtils.addDisposableListener(document, 'touchmove', (e) => this.onTouchMove(e)));
|
||||
}
|
||||
|
||||
public static addTarget(element: HTMLElement): void {
|
||||
|
@ -106,9 +106,10 @@ export class Gesture implements IDisposable {
|
|||
public dispose(): void {
|
||||
if (this.handle) {
|
||||
this.handle.dispose();
|
||||
dispose(this.toDispose);
|
||||
this.handle = null;
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private onTouchStart(e: TouchEvent): void {
|
||||
|
|
|
@ -35,23 +35,23 @@ export interface IBaseActionItemOptions {
|
|||
isMenu?: boolean;
|
||||
}
|
||||
|
||||
export class BaseActionItem implements IActionItem {
|
||||
export class BaseActionItem extends lifecycle.Disposable implements IActionItem {
|
||||
|
||||
public builder: HTMLElement;
|
||||
public _callOnDispose: lifecycle.IDisposable[];
|
||||
public element: HTMLElement;
|
||||
public _context: any;
|
||||
public _action: IAction;
|
||||
|
||||
private _actionRunner: IActionRunner;
|
||||
|
||||
constructor(context: any, action: IAction, protected options?: IBaseActionItemOptions) {
|
||||
this._callOnDispose = [];
|
||||
super();
|
||||
|
||||
this._context = context || this;
|
||||
this._action = action;
|
||||
|
||||
if (action instanceof Action) {
|
||||
this._callOnDispose.push(action.onDidChange(event => {
|
||||
if (!this.builder) {
|
||||
this._register(action.onDidChange(event => {
|
||||
if (!this.element) {
|
||||
// we have not been rendered yet, so there
|
||||
// is no point in updating the UI
|
||||
return;
|
||||
|
@ -80,10 +80,6 @@ export class BaseActionItem implements IActionItem {
|
|||
}
|
||||
}
|
||||
|
||||
public get callOnDispose() {
|
||||
return this._callOnDispose;
|
||||
}
|
||||
|
||||
public set actionRunner(actionRunner: IActionRunner) {
|
||||
this._actionRunner = actionRunner;
|
||||
}
|
||||
|
@ -105,7 +101,7 @@ export class BaseActionItem implements IActionItem {
|
|||
}
|
||||
|
||||
public render(container: HTMLElement): void {
|
||||
this.builder = container;
|
||||
this.element = container;
|
||||
Gesture.addTarget(container);
|
||||
|
||||
const enableDragging = this.options && this.options.draggable;
|
||||
|
@ -113,20 +109,20 @@ export class BaseActionItem implements IActionItem {
|
|||
container.draggable = true;
|
||||
}
|
||||
|
||||
this._callOnDispose.push(DOM.addDisposableListener(this.builder, EventType.Tap, e => this.onClick(e)));
|
||||
this._register(DOM.addDisposableListener(this.element, EventType.Tap, e => this.onClick(e)));
|
||||
|
||||
this._callOnDispose.push(DOM.addDisposableListener(this.builder, DOM.EventType.MOUSE_DOWN, e => {
|
||||
this._register(DOM.addDisposableListener(this.element, DOM.EventType.MOUSE_DOWN, e => {
|
||||
if (!enableDragging) {
|
||||
DOM.EventHelper.stop(e, true); // do not run when dragging is on because that would disable it
|
||||
}
|
||||
|
||||
const mouseEvent = e as MouseEvent;
|
||||
if (this._action.enabled && mouseEvent.button === 0) {
|
||||
DOM.addClass(this.builder, 'active');
|
||||
DOM.addClass(this.element, 'active');
|
||||
}
|
||||
}));
|
||||
|
||||
this._callOnDispose.push(DOM.addDisposableListener(this.builder, DOM.EventType.CLICK, e => {
|
||||
this._register(DOM.addDisposableListener(this.element, DOM.EventType.CLICK, e => {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
// See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard
|
||||
// > Writing to the clipboard
|
||||
|
@ -144,9 +140,9 @@ export class BaseActionItem implements IActionItem {
|
|||
}));
|
||||
|
||||
[DOM.EventType.MOUSE_UP, DOM.EventType.MOUSE_OUT].forEach(event => {
|
||||
this._callOnDispose.push(DOM.addDisposableListener(this.builder, event, e => {
|
||||
this._register(DOM.addDisposableListener(this.element, event, e => {
|
||||
DOM.EventHelper.stop(e);
|
||||
DOM.removeClass(this.builder, 'active');
|
||||
DOM.removeClass(this.element, 'active');
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
@ -169,16 +165,16 @@ export class BaseActionItem implements IActionItem {
|
|||
}
|
||||
|
||||
public focus(): void {
|
||||
if (this.builder) {
|
||||
this.builder.focus();
|
||||
DOM.addClass(this.builder, 'focused');
|
||||
if (this.element) {
|
||||
this.element.focus();
|
||||
DOM.addClass(this.element, 'focused');
|
||||
}
|
||||
}
|
||||
|
||||
public blur(): void {
|
||||
if (this.builder) {
|
||||
this.builder.blur();
|
||||
DOM.removeClass(this.builder, 'focused');
|
||||
if (this.element) {
|
||||
this.element.blur();
|
||||
DOM.removeClass(this.element, 'focused');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,12 +199,12 @@ export class BaseActionItem implements IActionItem {
|
|||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this.builder) {
|
||||
DOM.removeNode(this.builder);
|
||||
this.builder = null;
|
||||
if (this.element) {
|
||||
DOM.removeNode(this.element);
|
||||
this.element = null;
|
||||
}
|
||||
|
||||
this._callOnDispose = lifecycle.dispose(this._callOnDispose);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,8 +229,9 @@ export interface IActionItemOptions extends IBaseActionItemOptions {
|
|||
|
||||
export class ActionItem extends BaseActionItem {
|
||||
|
||||
protected $e: HTMLElement;
|
||||
protected label: HTMLElement;
|
||||
protected options: IActionItemOptions;
|
||||
|
||||
private cssClass: string;
|
||||
|
||||
constructor(context: any, action: IAction, options: IActionItemOptions = {}) {
|
||||
|
@ -249,20 +246,20 @@ export class ActionItem extends BaseActionItem {
|
|||
public render(container: HTMLElement): void {
|
||||
super.render(container);
|
||||
|
||||
this.$e = DOM.append(this.builder, DOM.$('a.action-label'));
|
||||
this.label = DOM.append(this.element, DOM.$('a.action-label'));
|
||||
if (this._action.id === Separator.ID) {
|
||||
// A separator is a presentation item
|
||||
this.$e.setAttribute('role', 'presentation');
|
||||
this.label.setAttribute('role', 'presentation');
|
||||
} else {
|
||||
if (this.options.isMenu) {
|
||||
this.$e.setAttribute('role', 'menuitem');
|
||||
this.label.setAttribute('role', 'menuitem');
|
||||
} else {
|
||||
this.$e.setAttribute('role', 'button');
|
||||
this.label.setAttribute('role', 'button');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.label && this.options.keybinding) {
|
||||
DOM.append(this.builder, DOM.$('span.keybinding')).textContent = this.options.keybinding;
|
||||
DOM.append(this.element, DOM.$('span.keybinding')).textContent = this.options.keybinding;
|
||||
}
|
||||
|
||||
this._updateClass();
|
||||
|
@ -274,12 +271,12 @@ export class ActionItem extends BaseActionItem {
|
|||
|
||||
public focus(): void {
|
||||
super.focus();
|
||||
this.$e.focus();
|
||||
this.label.focus();
|
||||
}
|
||||
|
||||
public _updateLabel(): void {
|
||||
if (this.options.label) {
|
||||
this.$e.textContent = this.getAction().label;
|
||||
this.label.textContent = this.getAction().label;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,43 +295,43 @@ export class ActionItem extends BaseActionItem {
|
|||
}
|
||||
|
||||
if (title) {
|
||||
this.$e.title = title;
|
||||
this.label.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
public _updateClass(): void {
|
||||
if (this.cssClass) {
|
||||
DOM.removeClasses(this.$e, this.cssClass);
|
||||
DOM.removeClasses(this.label, this.cssClass);
|
||||
}
|
||||
if (this.options.icon) {
|
||||
this.cssClass = this.getAction().class;
|
||||
DOM.addClass(this.$e, 'icon');
|
||||
DOM.addClass(this.label, 'icon');
|
||||
if (this.cssClass) {
|
||||
DOM.addClasses(this.$e, this.cssClass);
|
||||
DOM.addClasses(this.label, this.cssClass);
|
||||
}
|
||||
this._updateEnabled();
|
||||
} else {
|
||||
DOM.removeClass(this.$e, 'icon');
|
||||
DOM.removeClass(this.label, 'icon');
|
||||
}
|
||||
}
|
||||
|
||||
public _updateEnabled(): void {
|
||||
if (this.getAction().enabled) {
|
||||
DOM.removeClass(this.builder, 'disabled');
|
||||
DOM.removeClass(this.$e, 'disabled');
|
||||
this.$e.tabIndex = 0;
|
||||
DOM.removeClass(this.element, 'disabled');
|
||||
DOM.removeClass(this.label, 'disabled');
|
||||
this.label.tabIndex = 0;
|
||||
} else {
|
||||
DOM.addClass(this.builder, 'disabled');
|
||||
DOM.addClass(this.$e, 'disabled');
|
||||
DOM.removeTabIndexAndUpdateFocus(this.$e);
|
||||
DOM.addClass(this.element, 'disabled');
|
||||
DOM.addClass(this.label, 'disabled');
|
||||
DOM.removeTabIndexAndUpdateFocus(this.label);
|
||||
}
|
||||
}
|
||||
|
||||
public _updateChecked(): void {
|
||||
if (this.getAction().checked) {
|
||||
DOM.addClass(this.$e, 'checked');
|
||||
DOM.addClass(this.label, 'checked');
|
||||
} else {
|
||||
DOM.removeClass(this.$e, 'checked');
|
||||
DOM.removeClass(this.label, 'checked');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,7 +365,7 @@ export interface IActionOptions extends IActionItemOptions {
|
|||
index?: number;
|
||||
}
|
||||
|
||||
export class ActionBar implements IActionRunner {
|
||||
export class ActionBar extends lifecycle.Disposable implements IActionRunner {
|
||||
|
||||
public options: IActionBarOptions;
|
||||
|
||||
|
@ -384,26 +381,25 @@ export class ActionBar implements IActionRunner {
|
|||
public domNode: HTMLElement;
|
||||
protected actionsList: HTMLElement;
|
||||
|
||||
private toDispose: lifecycle.IDisposable[];
|
||||
|
||||
private _onDidBlur = new Emitter<void>();
|
||||
private _onDidCancel = new Emitter<void>();
|
||||
private _onDidRun = new Emitter<IRunEvent>();
|
||||
private _onDidBeforeRun = new Emitter<IRunEvent>();
|
||||
|
||||
constructor(container: HTMLElement, options: IActionBarOptions = defaultOptions) {
|
||||
super();
|
||||
|
||||
this.options = options;
|
||||
this._context = options.context;
|
||||
this.toDispose = [];
|
||||
this._actionRunner = this.options.actionRunner;
|
||||
|
||||
if (!this._actionRunner) {
|
||||
this._actionRunner = new ActionRunner();
|
||||
this.toDispose.push(this._actionRunner);
|
||||
this._register(this._actionRunner);
|
||||
}
|
||||
|
||||
this.toDispose.push(this._actionRunner.onDidRun(e => this._onDidRun.fire(e)));
|
||||
this.toDispose.push(this._actionRunner.onDidBeforeRun(e => this._onDidBeforeRun.fire(e)));
|
||||
this._register(this._actionRunner.onDidRun(e => this._onDidRun.fire(e)));
|
||||
this._register(this._actionRunner.onDidBeforeRun(e => this._onDidBeforeRun.fire(e)));
|
||||
|
||||
this.items = [];
|
||||
this.focusedItem = undefined;
|
||||
|
@ -440,7 +436,7 @@ export class ActionBar implements IActionRunner {
|
|||
break;
|
||||
}
|
||||
|
||||
this.toDispose.push(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_DOWN, e => {
|
||||
this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_DOWN, e => {
|
||||
let event = new StandardKeyboardEvent(e as KeyboardEvent);
|
||||
let eventHandled = true;
|
||||
|
||||
|
@ -462,7 +458,7 @@ export class ActionBar implements IActionRunner {
|
|||
}
|
||||
}));
|
||||
|
||||
this.toDispose.push(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_UP, e => {
|
||||
this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_UP, e => {
|
||||
let event = new StandardKeyboardEvent(e as KeyboardEvent);
|
||||
|
||||
// Run action on Enter/Space
|
||||
|
@ -478,15 +474,15 @@ export class ActionBar implements IActionRunner {
|
|||
}
|
||||
}));
|
||||
|
||||
this.focusTracker = DOM.trackFocus(this.domNode);
|
||||
this.toDispose.push(this.focusTracker.onDidBlur(() => {
|
||||
this.focusTracker = this._register(DOM.trackFocus(this.domNode));
|
||||
this._register(this.focusTracker.onDidBlur(() => {
|
||||
if (document.activeElement === this.domNode || !DOM.isAncestor(document.activeElement, this.domNode)) {
|
||||
this._onDidBlur.fire();
|
||||
this.focusedItem = undefined;
|
||||
}
|
||||
}));
|
||||
|
||||
this.toDispose.push(this.focusTracker.onDidFocus(() => this.updateFocusedItem()));
|
||||
this._register(this.focusTracker.onDidFocus(() => this.updateFocusedItem()));
|
||||
|
||||
this.actionsList = document.createElement('ul');
|
||||
this.actionsList.className = 'actions-container';
|
||||
|
@ -571,7 +567,7 @@ export class ActionBar implements IActionRunner {
|
|||
actionItemElement.setAttribute('role', 'presentation');
|
||||
|
||||
// Prevent native context menu on actions
|
||||
this.toDispose.push(DOM.addDisposableListener(actionItemElement, DOM.EventType.CONTEXT_MENU, (e: DOM.EventLike) => {
|
||||
this._register(DOM.addDisposableListener(actionItemElement, DOM.EventType.CONTEXT_MENU, (e: DOM.EventLike) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}));
|
||||
|
@ -750,28 +746,22 @@ export class ActionBar implements IActionRunner {
|
|||
}
|
||||
this.items = null;
|
||||
|
||||
if (this.focusTracker) {
|
||||
this.focusTracker.dispose();
|
||||
this.focusTracker = null;
|
||||
}
|
||||
|
||||
this.toDispose = lifecycle.dispose(this.toDispose);
|
||||
|
||||
DOM.removeNode(this.getContainer());
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectActionItem extends BaseActionItem {
|
||||
protected selectBox: SelectBox;
|
||||
protected toDispose: lifecycle.IDisposable[];
|
||||
|
||||
constructor(ctx: any, action: IAction, options: string[], selected: number, contextViewProvider: IContextViewProvider, selectBoxOptions?: ISelectBoxOptions
|
||||
) {
|
||||
super(ctx, action);
|
||||
|
||||
this.selectBox = new SelectBox(options, selected, contextViewProvider, null, selectBoxOptions);
|
||||
|
||||
this.toDispose = [];
|
||||
this.toDispose.push(this.selectBox);
|
||||
this._register(this.selectBox);
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
|
@ -784,7 +774,7 @@ export class SelectActionItem extends BaseActionItem {
|
|||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this.toDispose.push(this.selectBox.onDidSelect(e => {
|
||||
this._register(this.selectBox.onDidSelect(e => {
|
||||
this.actionRunner.run(this._action, this.getActionContext(e.selected)).done();
|
||||
}));
|
||||
}
|
||||
|
@ -808,10 +798,4 @@ export class SelectActionItem extends BaseActionItem {
|
|||
public render(container: HTMLElement): void {
|
||||
this.selectBox.render(container);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.toDispose = lifecycle.dispose(this.toDispose);
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ const defaultOptions: IButtonStyles = {
|
|||
|
||||
export class Button extends Disposable {
|
||||
|
||||
private $el: HTMLElement;
|
||||
private _element: HTMLElement;
|
||||
private options: IButtonOptions;
|
||||
|
||||
private buttonBackground: Color;
|
||||
|
@ -58,16 +58,16 @@ export class Button extends Disposable {
|
|||
this.buttonForeground = this.options.buttonForeground;
|
||||
this.buttonBorder = this.options.buttonBorder;
|
||||
|
||||
this.$el = document.createElement('a');
|
||||
DOM.addClass(this.$el, 'monaco-button');
|
||||
this.$el.tabIndex = 0;
|
||||
this.$el.setAttribute('role', 'button');
|
||||
this._element = document.createElement('a');
|
||||
DOM.addClass(this._element, 'monaco-button');
|
||||
this._element.tabIndex = 0;
|
||||
this._element.setAttribute('role', 'button');
|
||||
|
||||
container.appendChild(this.$el);
|
||||
container.appendChild(this._element);
|
||||
|
||||
Gesture.addTarget(this.$el);
|
||||
Gesture.addTarget(this._element);
|
||||
|
||||
this._register(DOM.addDisposableListener(this.$el, DOM.EventType.CLICK, e => {
|
||||
this._register(DOM.addDisposableListener(this._element, DOM.EventType.CLICK, e => {
|
||||
if (!this.enabled) {
|
||||
DOM.EventHelper.stop(e);
|
||||
return;
|
||||
|
@ -76,14 +76,14 @@ export class Button extends Disposable {
|
|||
this._onDidClick.fire(e);
|
||||
}));
|
||||
|
||||
this._register(DOM.addDisposableListener(this.$el, DOM.EventType.KEY_DOWN, e => {
|
||||
this._register(DOM.addDisposableListener(this._element, DOM.EventType.KEY_DOWN, e => {
|
||||
const event = new StandardKeyboardEvent(e as KeyboardEvent);
|
||||
let eventHandled = false;
|
||||
if (this.enabled && event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
||||
this._onDidClick.fire(e);
|
||||
eventHandled = true;
|
||||
} else if (event.equals(KeyCode.Escape)) {
|
||||
this.$el.blur();
|
||||
this._element.blur();
|
||||
eventHandled = true;
|
||||
}
|
||||
|
||||
|
@ -92,18 +92,18 @@ export class Button extends Disposable {
|
|||
}
|
||||
}));
|
||||
|
||||
this._register(DOM.addDisposableListener(this.$el, DOM.EventType.MOUSE_OVER, e => {
|
||||
if (!DOM.hasClass(this.$el, 'disabled')) {
|
||||
this._register(DOM.addDisposableListener(this._element, DOM.EventType.MOUSE_OVER, e => {
|
||||
if (!DOM.hasClass(this._element, 'disabled')) {
|
||||
this.setHoverBackground();
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(DOM.addDisposableListener(this.$el, DOM.EventType.MOUSE_OUT, e => {
|
||||
this._register(DOM.addDisposableListener(this._element, DOM.EventType.MOUSE_OUT, e => {
|
||||
this.applyStyles(); // restore standard styles
|
||||
}));
|
||||
|
||||
// Also set hover background when button is focused for feedback
|
||||
this.focusTracker = this._register(DOM.trackFocus(this.$el));
|
||||
this.focusTracker = this._register(DOM.trackFocus(this._element));
|
||||
this._register(this.focusTracker.onDidFocus(() => this.setHoverBackground()));
|
||||
this._register(this.focusTracker.onDidBlur(() => this.applyStyles())); // restore standard styles
|
||||
|
||||
|
@ -113,7 +113,7 @@ export class Button extends Disposable {
|
|||
private setHoverBackground(): void {
|
||||
const hoverBackground = this.buttonHoverBackground ? this.buttonHoverBackground.toString() : null;
|
||||
if (hoverBackground) {
|
||||
this.$el.style.backgroundColor = hoverBackground;
|
||||
this._element.style.backgroundColor = hoverBackground;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,56 +127,56 @@ export class Button extends Disposable {
|
|||
}
|
||||
|
||||
private applyStyles(): void {
|
||||
if (this.$el) {
|
||||
if (this._element) {
|
||||
const background = this.buttonBackground ? this.buttonBackground.toString() : null;
|
||||
const foreground = this.buttonForeground ? this.buttonForeground.toString() : null;
|
||||
const border = this.buttonBorder ? this.buttonBorder.toString() : null;
|
||||
|
||||
this.$el.style.color = foreground;
|
||||
this.$el.style.backgroundColor = background;
|
||||
this._element.style.color = foreground;
|
||||
this._element.style.backgroundColor = background;
|
||||
|
||||
this.$el.style.borderWidth = border ? '1px' : null;
|
||||
this.$el.style.borderStyle = border ? 'solid' : null;
|
||||
this.$el.style.borderColor = border;
|
||||
this._element.style.borderWidth = border ? '1px' : null;
|
||||
this._element.style.borderStyle = border ? 'solid' : null;
|
||||
this._element.style.borderColor = border;
|
||||
}
|
||||
}
|
||||
|
||||
get element(): HTMLElement {
|
||||
return this.$el;
|
||||
return this._element;
|
||||
}
|
||||
|
||||
set label(value: string) {
|
||||
if (!DOM.hasClass(this.$el, 'monaco-text-button')) {
|
||||
DOM.addClass(this.$el, 'monaco-text-button');
|
||||
if (!DOM.hasClass(this._element, 'monaco-text-button')) {
|
||||
DOM.addClass(this._element, 'monaco-text-button');
|
||||
}
|
||||
this.$el.innerText = value;
|
||||
this._element.textContent = value;
|
||||
if (this.options.title) {
|
||||
this.$el.title = value;
|
||||
this._element.title = value;
|
||||
}
|
||||
}
|
||||
|
||||
set icon(iconClassName: string) {
|
||||
DOM.addClass(this.$el, iconClassName);
|
||||
DOM.addClass(this._element, iconClassName);
|
||||
}
|
||||
|
||||
set enabled(value: boolean) {
|
||||
if (value) {
|
||||
DOM.removeClass(this.$el, 'disabled');
|
||||
this.$el.setAttribute('aria-disabled', String(false));
|
||||
this.$el.tabIndex = 0;
|
||||
DOM.removeClass(this._element, 'disabled');
|
||||
this._element.setAttribute('aria-disabled', String(false));
|
||||
this._element.tabIndex = 0;
|
||||
} else {
|
||||
DOM.addClass(this.$el, 'disabled');
|
||||
this.$el.setAttribute('aria-disabled', String(true));
|
||||
DOM.removeTabIndexAndUpdateFocus(this.$el);
|
||||
DOM.addClass(this._element, 'disabled');
|
||||
this._element.setAttribute('aria-disabled', String(true));
|
||||
DOM.removeTabIndexAndUpdateFocus(this._element);
|
||||
}
|
||||
}
|
||||
|
||||
get enabled() {
|
||||
return !DOM.hasClass(this.$el, 'disabled');
|
||||
return !DOM.hasClass(this._element, 'disabled');
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
this.$el.focus();
|
||||
this._element.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import 'vs/css!./contextview';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IDisposable, dispose, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose, toDisposable, combinedDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export interface IAnchor {
|
||||
x: number;
|
||||
|
@ -95,55 +95,54 @@ export function layout(viewportSize: number, viewSize: number, anchor: ILayoutAn
|
|||
}
|
||||
}
|
||||
|
||||
export class ContextView {
|
||||
export class ContextView extends Disposable {
|
||||
|
||||
private static readonly BUBBLE_UP_EVENTS = ['click', 'keydown', 'focus', 'blur'];
|
||||
private static readonly BUBBLE_DOWN_EVENTS = ['click'];
|
||||
|
||||
private $container: HTMLElement;
|
||||
private $view: HTMLElement;
|
||||
private container: HTMLElement;
|
||||
private view: HTMLElement;
|
||||
private delegate: IDelegate;
|
||||
private toDispose: IDisposable[];
|
||||
private toDisposeOnClean: IDisposable;
|
||||
private toDisposeOnSetContainer: IDisposable;
|
||||
|
||||
constructor(container: HTMLElement) {
|
||||
this.$view = DOM.$('.context-view');
|
||||
super();
|
||||
|
||||
DOM.hide(this.$view);
|
||||
this.view = DOM.$('.context-view');
|
||||
|
||||
DOM.hide(this.view);
|
||||
|
||||
this.setContainer(container);
|
||||
|
||||
this.toDispose = [toDisposable(() => {
|
||||
this.setContainer(null);
|
||||
})];
|
||||
this._register(toDisposable(() => this.setContainer(null)));
|
||||
}
|
||||
|
||||
public setContainer(container: HTMLElement): void {
|
||||
if (this.$container) {
|
||||
if (this.container) {
|
||||
this.toDisposeOnSetContainer = dispose(this.toDisposeOnSetContainer);
|
||||
this.$container.removeChild(this.$view);
|
||||
this.$container = null;
|
||||
this.container.removeChild(this.view);
|
||||
this.container = null;
|
||||
}
|
||||
if (container) {
|
||||
this.$container = container;
|
||||
this.$container.appendChild(this.$view);
|
||||
this.container = container;
|
||||
this.container.appendChild(this.view);
|
||||
|
||||
const toDispose: IDisposable[] = [];
|
||||
const toDisposeOnSetContainer: IDisposable[] = [];
|
||||
|
||||
ContextView.BUBBLE_UP_EVENTS.forEach(event => {
|
||||
toDispose.push(DOM.addStandardDisposableListener(this.$container, event, (e: Event) => {
|
||||
toDisposeOnSetContainer.push(DOM.addStandardDisposableListener(this.container, event, (e: Event) => {
|
||||
this.onDOMEvent(e, <HTMLElement>document.activeElement, false);
|
||||
}));
|
||||
});
|
||||
|
||||
ContextView.BUBBLE_DOWN_EVENTS.forEach(event => {
|
||||
toDispose.push(DOM.addStandardDisposableListener(this.$container, event, (e: Event) => {
|
||||
toDisposeOnSetContainer.push(DOM.addStandardDisposableListener(this.container, event, (e: Event) => {
|
||||
this.onDOMEvent(e, <HTMLElement>document.activeElement, true);
|
||||
}, true));
|
||||
});
|
||||
|
||||
this.toDisposeOnSetContainer = combinedDisposable(toDispose);
|
||||
this.toDisposeOnSetContainer = combinedDisposable(toDisposeOnSetContainer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,14 +152,14 @@ export class ContextView {
|
|||
}
|
||||
|
||||
// Show static box
|
||||
DOM.clearNode(this.$view);
|
||||
this.$view.className = 'context-view';
|
||||
this.$view.style.top = '0px';
|
||||
this.$view.style.left = '0px';
|
||||
DOM.show(this.$view);
|
||||
DOM.clearNode(this.view);
|
||||
this.view.className = 'context-view';
|
||||
this.view.style.top = '0px';
|
||||
this.view.style.left = '0px';
|
||||
DOM.show(this.view);
|
||||
|
||||
// Render content
|
||||
this.toDisposeOnClean = delegate.render(this.$view);
|
||||
this.toDisposeOnClean = delegate.render(this.view);
|
||||
|
||||
// Set active delegate
|
||||
this.delegate = delegate;
|
||||
|
@ -219,8 +218,8 @@ export class ContextView {
|
|||
};
|
||||
}
|
||||
|
||||
const viewSizeWidth = DOM.getTotalWidth(this.$view);
|
||||
const viewSizeHeight = DOM.getTotalHeight(this.$view);
|
||||
const viewSizeWidth = DOM.getTotalWidth(this.view);
|
||||
const viewSizeHeight = DOM.getTotalHeight(this.view);
|
||||
|
||||
const anchorPosition = this.delegate.anchorPosition || AnchorPosition.BELOW;
|
||||
const anchorAlignment = this.delegate.anchorAlignment || AnchorAlignment.LEFT;
|
||||
|
@ -235,17 +234,17 @@ export class ContextView {
|
|||
horizontalAnchor = { offset: around.left + around.width, size: 0, position: LayoutAnchorPosition.After };
|
||||
}
|
||||
|
||||
const containerPosition = DOM.getDomNodePagePosition(this.$container);
|
||||
const containerPosition = DOM.getDomNodePagePosition(this.container);
|
||||
const top = layout(window.innerHeight, viewSizeHeight, verticalAnchor) - containerPosition.top;
|
||||
const left = layout(window.innerWidth, viewSizeWidth, horizontalAnchor) - containerPosition.left;
|
||||
|
||||
DOM.removeClasses(this.$view, 'top', 'bottom', 'left', 'right');
|
||||
DOM.addClass(this.$view, anchorPosition === AnchorPosition.BELOW ? 'bottom' : 'top');
|
||||
DOM.addClass(this.$view, anchorAlignment === AnchorAlignment.LEFT ? 'left' : 'right');
|
||||
DOM.removeClasses(this.view, 'top', 'bottom', 'left', 'right');
|
||||
DOM.addClass(this.view, anchorPosition === AnchorPosition.BELOW ? 'bottom' : 'top');
|
||||
DOM.addClass(this.view, anchorAlignment === AnchorAlignment.LEFT ? 'left' : 'right');
|
||||
|
||||
this.$view.style.top = `${top}px`;
|
||||
this.$view.style.left = `${left}px`;
|
||||
this.$view.style.width = 'initial';
|
||||
this.view.style.top = `${top}px`;
|
||||
this.view.style.left = `${left}px`;
|
||||
this.view.style.width = 'initial';
|
||||
}
|
||||
|
||||
public hide(data?: any): void {
|
||||
|
@ -260,7 +259,7 @@ export class ContextView {
|
|||
this.toDisposeOnClean = null;
|
||||
}
|
||||
|
||||
DOM.hide(this.$view);
|
||||
DOM.hide(this.view);
|
||||
}
|
||||
|
||||
private isVisible(): boolean {
|
||||
|
@ -271,7 +270,7 @@ export class ContextView {
|
|||
if (this.delegate) {
|
||||
if (this.delegate.onDOMEvent) {
|
||||
this.delegate.onDOMEvent(e, <HTMLElement>document.activeElement);
|
||||
} else if (onCapture && !DOM.isAncestor(<HTMLElement>e.target, this.$container)) {
|
||||
} else if (onCapture && !DOM.isAncestor(<HTMLElement>e.target, this.container)) {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
@ -280,6 +279,6 @@ export class ContextView {
|
|||
public dispose(): void {
|
||||
this.hide();
|
||||
|
||||
this.toDispose = dispose(this.toDispose);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
|
@ -29,18 +29,18 @@ export interface IBaseDropdownOptions {
|
|||
export class BaseDropdown extends ActionRunner {
|
||||
private _toDispose: IDisposable[] = [];
|
||||
|
||||
private $el: HTMLElement;
|
||||
private $boxContainer: HTMLElement;
|
||||
private $label: HTMLElement;
|
||||
private $contents: HTMLElement;
|
||||
private _element: HTMLElement;
|
||||
private boxContainer: HTMLElement;
|
||||
private _label: HTMLElement;
|
||||
private contents: HTMLElement;
|
||||
private visible: boolean;
|
||||
|
||||
constructor(container: HTMLElement, options: IBaseDropdownOptions) {
|
||||
super();
|
||||
|
||||
this.$el = append(container, $('.monaco-dropdown'));
|
||||
this._element = append(container, $('.monaco-dropdown'));
|
||||
|
||||
this.$label = append(this.$el, $('.dropdown-label'));
|
||||
this._label = append(this._element, $('.dropdown-label'));
|
||||
|
||||
let labelRenderer = options.labelRenderer;
|
||||
if (!labelRenderer) {
|
||||
|
@ -52,11 +52,11 @@ export class BaseDropdown extends ActionRunner {
|
|||
}
|
||||
|
||||
[EventType.CLICK, EventType.MOUSE_DOWN, GestureEventType.Tap].forEach(event => {
|
||||
this._toDispose.push(addDisposableListener(this.$label, event, e => EventHelper.stop(e, true))); // prevent default click behaviour to trigger
|
||||
this._toDispose.push(addDisposableListener(this._label, event, e => EventHelper.stop(e, true))); // prevent default click behaviour to trigger
|
||||
});
|
||||
|
||||
[EventType.MOUSE_DOWN, GestureEventType.Tap].forEach(event => {
|
||||
this._toDispose.push(addDisposableListener(this.$label, event, e => {
|
||||
this._toDispose.push(addDisposableListener(this._label, event, e => {
|
||||
if (e instanceof MouseEvent && e.detail > 1) {
|
||||
return; // prevent multiple clicks to open multiple context menus (https://github.com/Microsoft/vscode/issues/41363)
|
||||
}
|
||||
|
@ -69,12 +69,12 @@ export class BaseDropdown extends ActionRunner {
|
|||
}));
|
||||
});
|
||||
|
||||
const cleanupFn = labelRenderer(this.$label);
|
||||
const cleanupFn = labelRenderer(this._label);
|
||||
if (cleanupFn) {
|
||||
this._toDispose.push(cleanupFn);
|
||||
}
|
||||
|
||||
Gesture.addTarget(this.$label);
|
||||
Gesture.addTarget(this._label);
|
||||
}
|
||||
|
||||
get toDispose(): IDisposable[] {
|
||||
|
@ -82,15 +82,15 @@ export class BaseDropdown extends ActionRunner {
|
|||
}
|
||||
|
||||
get element(): HTMLElement {
|
||||
return this.$el;
|
||||
return this._element;
|
||||
}
|
||||
|
||||
get label(): HTMLElement {
|
||||
return this.$label;
|
||||
return this._label;
|
||||
}
|
||||
|
||||
set tooltip(tooltip: string) {
|
||||
this.$label.title = tooltip;
|
||||
this._label.title = tooltip;
|
||||
}
|
||||
|
||||
show(): void {
|
||||
|
@ -111,19 +111,19 @@ export class BaseDropdown extends ActionRunner {
|
|||
|
||||
this._toDispose = dispose(this.toDispose);
|
||||
|
||||
if (this.$boxContainer) {
|
||||
removeNode(this.$boxContainer);
|
||||
this.$boxContainer = null;
|
||||
if (this.boxContainer) {
|
||||
removeNode(this.boxContainer);
|
||||
this.boxContainer = null;
|
||||
}
|
||||
|
||||
if (this.$contents) {
|
||||
removeNode(this.$contents);
|
||||
this.$contents = null;
|
||||
if (this.contents) {
|
||||
removeNode(this.contents);
|
||||
this.contents = null;
|
||||
}
|
||||
|
||||
if (this.$label) {
|
||||
removeNode(this.$label);
|
||||
this.$label = null;
|
||||
if (this._label) {
|
||||
removeNode(this._label);
|
||||
this._label = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -283,13 +283,13 @@ export class DropdownMenuActionItem extends BaseActionItem {
|
|||
|
||||
render(container: HTMLElement): void {
|
||||
const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable => {
|
||||
this.builder = append(el, $('a.action-label'));
|
||||
addClasses(this.builder, this.clazz);
|
||||
this.element = append(el, $('a.action-label'));
|
||||
addClasses(this.element, this.clazz);
|
||||
|
||||
this.builder.tabIndex = 0;
|
||||
this.builder.setAttribute('role', 'button');
|
||||
this.builder.setAttribute('aria-haspopup', 'true');
|
||||
this.builder.title = this._action.label || '';
|
||||
this.element.tabIndex = 0;
|
||||
this.element.setAttribute('role', 'button');
|
||||
this.element.setAttribute('aria-haspopup', 'true');
|
||||
this.element.title = this._action.label || '';
|
||||
|
||||
return null;
|
||||
};
|
||||
|
|
|
@ -245,7 +245,7 @@ class MenuActionItem extends BaseActionItem {
|
|||
|
||||
this.container = container;
|
||||
|
||||
this.$e = $('a.action-menu-item').appendTo(this.builder);
|
||||
this.$e = $('a.action-menu-item').appendTo(this.element);
|
||||
if (this._action.id === Separator.ID) {
|
||||
// A separator is a presentation item
|
||||
this.$e.attr({ role: 'presentation' });
|
||||
|
@ -335,11 +335,11 @@ class MenuActionItem extends BaseActionItem {
|
|||
|
||||
_updateEnabled(): void {
|
||||
if (this.getAction().enabled) {
|
||||
removeClass(this.builder, 'disabled');
|
||||
removeClass(this.element, 'disabled');
|
||||
this.$e.removeClass('disabled');
|
||||
this.$e.attr({ tabindex: 0 });
|
||||
} else {
|
||||
addClass(this.builder, 'disabled');
|
||||
addClass(this.element, 'disabled');
|
||||
this.$e.addClass('disabled');
|
||||
removeTabIndexAndUpdateFocus(this.$e.getHTMLElement());
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ class SubmenuActionItem extends MenuActionItem {
|
|||
}, 250);
|
||||
|
||||
this.hideScheduler = new RunOnceScheduler(() => {
|
||||
if ((!isAncestor(document.activeElement, this.builder) && this.parentData.submenu === this.mysubmenu)) {
|
||||
if ((!isAncestor(document.activeElement, this.element) && this.parentData.submenu === this.mysubmenu)) {
|
||||
this.parentData.parent.focus(false);
|
||||
this.cleanupExistingSubmenu(true);
|
||||
}
|
||||
|
@ -397,7 +397,7 @@ class SubmenuActionItem extends MenuActionItem {
|
|||
this.$e.attr('aria-haspopup', 'true');
|
||||
$('span.submenu-indicator').attr('aria-hidden', 'true').text('\u25B6').appendTo(this.$e);
|
||||
|
||||
$(this.builder).on(EventType.KEY_UP, (e) => {
|
||||
$(this.element).on(EventType.KEY_UP, (e) => {
|
||||
let event = new StandardKeyboardEvent(e as KeyboardEvent);
|
||||
if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) {
|
||||
EventHelper.stop(e, true);
|
||||
|
@ -406,14 +406,14 @@ class SubmenuActionItem extends MenuActionItem {
|
|||
}
|
||||
});
|
||||
|
||||
$(this.builder).on(EventType.KEY_DOWN, (e) => {
|
||||
$(this.element).on(EventType.KEY_DOWN, (e) => {
|
||||
let event = new StandardKeyboardEvent(e as KeyboardEvent);
|
||||
if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) {
|
||||
EventHelper.stop(e, true);
|
||||
}
|
||||
});
|
||||
|
||||
$(this.builder).on(EventType.MOUSE_OVER, (e) => {
|
||||
$(this.element).on(EventType.MOUSE_OVER, (e) => {
|
||||
if (!this.mouseOver) {
|
||||
this.mouseOver = true;
|
||||
|
||||
|
@ -421,12 +421,12 @@ class SubmenuActionItem extends MenuActionItem {
|
|||
}
|
||||
});
|
||||
|
||||
$(this.builder).on(EventType.MOUSE_LEAVE, (e) => {
|
||||
$(this.element).on(EventType.MOUSE_LEAVE, (e) => {
|
||||
this.mouseOver = false;
|
||||
});
|
||||
|
||||
$(this.builder).on(EventType.FOCUS_OUT, (e) => {
|
||||
if (!isAncestor(document.activeElement, this.builder)) {
|
||||
$(this.element).on(EventType.FOCUS_OUT, (e) => {
|
||||
if (!isAncestor(document.activeElement, this.element)) {
|
||||
this.hideScheduler.schedule();
|
||||
}
|
||||
});
|
||||
|
@ -454,10 +454,10 @@ class SubmenuActionItem extends MenuActionItem {
|
|||
|
||||
private createSubmenu(selectFirstItem = true) {
|
||||
if (!this.parentData.submenu) {
|
||||
this.submenuContainer = $(this.builder).div({ class: 'monaco-submenu menubar-menu-items-holder context-view' });
|
||||
this.submenuContainer = $(this.element).div({ class: 'monaco-submenu menubar-menu-items-holder context-view' });
|
||||
|
||||
$(this.submenuContainer).style({
|
||||
'left': `${$(this.builder).getClientArea().width}px`
|
||||
'left': `${$(this.element).getClientArea().width}px`
|
||||
});
|
||||
|
||||
$(this.submenuContainer).on(EventType.KEY_UP, (e) => {
|
||||
|
|
|
@ -199,17 +199,17 @@ export class MenuItemActionItem extends ActionItem {
|
|||
}
|
||||
};
|
||||
|
||||
this._callOnDispose.push(alternativeKeyEmitter.event(value => {
|
||||
this._register(alternativeKeyEmitter.event(value => {
|
||||
alternativeKeyDown = value;
|
||||
updateAltState();
|
||||
}));
|
||||
|
||||
this._callOnDispose.push(domEvent(container, 'mouseleave')(_ => {
|
||||
this._register(domEvent(container, 'mouseleave')(_ => {
|
||||
mouseOver = false;
|
||||
updateAltState();
|
||||
}));
|
||||
|
||||
this._callOnDispose.push(domEvent(container, 'mouseenter')(e => {
|
||||
this._register(domEvent(container, 'mouseenter')(e => {
|
||||
mouseOver = true;
|
||||
updateAltState();
|
||||
}));
|
||||
|
@ -217,12 +217,12 @@ export class MenuItemActionItem extends ActionItem {
|
|||
|
||||
_updateLabel(): void {
|
||||
if (this.options.label) {
|
||||
this.$e.textContent = this._commandAction.label;
|
||||
this.label.textContent = this._commandAction.label;
|
||||
}
|
||||
}
|
||||
|
||||
_updateTooltip(): void {
|
||||
const element = this.$e;
|
||||
const element = this.label;
|
||||
const keybinding = this._keybindingService.lookupKeybinding(this._commandAction.id);
|
||||
const keybindingLabel = keybinding && keybinding.getLabel();
|
||||
|
||||
|
@ -259,8 +259,8 @@ export class MenuItemActionItem extends ActionItem {
|
|||
MenuItemActionItem.ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
|
||||
}
|
||||
|
||||
addClasses(this.$e, 'icon', iconClass);
|
||||
this._itemClassDispose = toDisposable(() => removeClasses(this.$e, 'icon', iconClass));
|
||||
addClasses(this.label, 'icon', iconClass);
|
||||
this._itemClassDispose = toDisposable(() => removeClasses(this.label, 'icon', iconClass));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ export class ContextMenuHandler {
|
|||
private notificationService: INotificationService;
|
||||
private telemetryService: ITelemetryService;
|
||||
|
||||
private $el: HTMLElement;
|
||||
private $elDisposable: IDisposable;
|
||||
private element: HTMLElement;
|
||||
private elementDisposable: IDisposable;
|
||||
private menuContainerElement: HTMLElement;
|
||||
private focusToReturn: HTMLElement;
|
||||
|
||||
|
@ -39,13 +39,13 @@ export class ContextMenuHandler {
|
|||
}
|
||||
|
||||
public setContainer(container: HTMLElement): void {
|
||||
if (this.$el) {
|
||||
this.$elDisposable = dispose(this.$elDisposable);
|
||||
this.$el = null;
|
||||
if (this.element) {
|
||||
this.elementDisposable = dispose(this.elementDisposable);
|
||||
this.element = null;
|
||||
}
|
||||
if (container) {
|
||||
this.$el = container;
|
||||
this.$elDisposable = addDisposableListener(this.$el, 'mousedown', (e) => this.onMouseDown(e as MouseEvent));
|
||||
this.element = container;
|
||||
this.elementDisposable = addDisposableListener(this.element, 'mousedown', (e) => this.onMouseDown(e as MouseEvent));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,23 +123,23 @@ export class GlobalActivityActionItem extends ActivityActionItem {
|
|||
// Context menus are triggered on mouse down so that an item can be picked
|
||||
// and executed with releasing the mouse over it
|
||||
|
||||
this.callOnDispose.push(DOM.addDisposableListener(this.$container, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => {
|
||||
this._register(DOM.addDisposableListener(this.container, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
|
||||
const event = new StandardMouseEvent(e);
|
||||
this.showContextMenu({ x: event.posx, y: event.posy });
|
||||
}));
|
||||
|
||||
this.callOnDispose.push(DOM.addDisposableListener(this.$container, DOM.EventType.KEY_UP, (e: KeyboardEvent) => {
|
||||
this._register(DOM.addDisposableListener(this.container, DOM.EventType.KEY_UP, (e: KeyboardEvent) => {
|
||||
let event = new StandardKeyboardEvent(e);
|
||||
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
|
||||
this.showContextMenu(this.$container);
|
||||
this.showContextMenu(this.container);
|
||||
}
|
||||
}));
|
||||
|
||||
this.callOnDispose.push(DOM.addDisposableListener(this.$container, TouchEventType.Tap, (e: GestureEvent) => {
|
||||
this._register(DOM.addDisposableListener(this.container, TouchEventType.Tap, (e: GestureEvent) => {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
|
||||
const event = new StandardMouseEvent(e);
|
||||
|
|
|
@ -124,12 +124,12 @@ export interface IActivityActionItemOptions extends IBaseActionItemOptions {
|
|||
}
|
||||
|
||||
export class ActivityActionItem extends BaseActionItem {
|
||||
protected $container: HTMLElement;
|
||||
protected $label: HTMLElement;
|
||||
protected $badge: HTMLElement;
|
||||
protected container: HTMLElement;
|
||||
protected label: HTMLElement;
|
||||
protected badge: HTMLElement;
|
||||
protected options: IActivityActionItemOptions;
|
||||
|
||||
private $badgeContent: HTMLElement;
|
||||
private badgeContent: HTMLElement;
|
||||
private badgeDisposable: IDisposable = Disposable.None;
|
||||
private mouseUpTimeout: number;
|
||||
|
||||
|
@ -140,9 +140,9 @@ export class ActivityActionItem extends BaseActionItem {
|
|||
) {
|
||||
super(null, action, options);
|
||||
|
||||
this.themeService.onThemeChange(this.onThemeChange, this, this._callOnDispose);
|
||||
action.onDidChangeActivity(this.updateActivity, this, this._callOnDispose);
|
||||
action.onDidChangeBadge(this.updateBadge, this, this._callOnDispose);
|
||||
this._register(this.themeService.onThemeChange(this.onThemeChange, this));
|
||||
this._register(action.onDidChangeActivity(this.updateActivity, this));
|
||||
this._register(action.onDidChangeBadge(this.updateBadge, this));
|
||||
}
|
||||
|
||||
protected get activity(): IActivity {
|
||||
|
@ -153,59 +153,59 @@ export class ActivityActionItem extends BaseActionItem {
|
|||
const theme = this.themeService.getTheme();
|
||||
|
||||
// Label
|
||||
if (this.$label && this.options.icon) {
|
||||
if (this.label && this.options.icon) {
|
||||
const background = theme.getColor(this.options.colors.backgroundColor);
|
||||
|
||||
this.$label.style.backgroundColor = background ? background.toString() : null;
|
||||
this.label.style.backgroundColor = background ? background.toString() : null;
|
||||
}
|
||||
|
||||
// Badge
|
||||
if (this.$badgeContent) {
|
||||
if (this.badgeContent) {
|
||||
const badgeForeground = theme.getColor(this.options.colors.badgeForeground);
|
||||
const badgeBackground = theme.getColor(this.options.colors.badgeBackground);
|
||||
const contrastBorderColor = theme.getColor(contrastBorder);
|
||||
|
||||
this.$badgeContent.style.color = badgeForeground ? badgeForeground.toString() : null;
|
||||
this.$badgeContent.style.backgroundColor = badgeBackground ? badgeBackground.toString() : null;
|
||||
this.badgeContent.style.color = badgeForeground ? badgeForeground.toString() : null;
|
||||
this.badgeContent.style.backgroundColor = badgeBackground ? badgeBackground.toString() : null;
|
||||
|
||||
this.$badgeContent.style.borderStyle = contrastBorderColor ? 'solid' : null;
|
||||
this.$badgeContent.style.borderWidth = contrastBorderColor ? '1px' : null;
|
||||
this.$badgeContent.style.borderColor = contrastBorderColor ? contrastBorderColor.toString() : null;
|
||||
this.badgeContent.style.borderStyle = contrastBorderColor ? 'solid' : null;
|
||||
this.badgeContent.style.borderWidth = contrastBorderColor ? '1px' : null;
|
||||
this.badgeContent.style.borderColor = contrastBorderColor ? contrastBorderColor.toString() : null;
|
||||
}
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
super.render(container);
|
||||
|
||||
this.$container = container;
|
||||
this.container = container;
|
||||
|
||||
// Make the container tab-able for keyboard navigation
|
||||
this.$container.tabIndex = 0;
|
||||
this.$container.setAttribute('role', 'button');
|
||||
this.container.tabIndex = 0;
|
||||
this.container.setAttribute('role', 'button');
|
||||
|
||||
// Try hard to prevent keyboard only focus feedback when using mouse
|
||||
this.callOnDispose.push(dom.addDisposableListener(this.$container, dom.EventType.MOUSE_DOWN, () => {
|
||||
dom.addClass(this.$container, 'clicked');
|
||||
this._register(dom.addDisposableListener(this.container, dom.EventType.MOUSE_DOWN, () => {
|
||||
dom.addClass(this.container, 'clicked');
|
||||
}));
|
||||
|
||||
this.callOnDispose.push(dom.addDisposableListener(this.$container, dom.EventType.MOUSE_UP, () => {
|
||||
this._register(dom.addDisposableListener(this.container, dom.EventType.MOUSE_UP, () => {
|
||||
if (this.mouseUpTimeout) {
|
||||
clearTimeout(this.mouseUpTimeout);
|
||||
}
|
||||
|
||||
this.mouseUpTimeout = setTimeout(() => {
|
||||
dom.removeClass(this.$container, 'clicked');
|
||||
dom.removeClass(this.container, 'clicked');
|
||||
}, 800); // delayed to prevent focus feedback from showing on mouse up
|
||||
}));
|
||||
|
||||
// Label
|
||||
this.$label = dom.append(this.builder, dom.$('a.action-label'));
|
||||
this.label = dom.append(this.element, dom.$('a.action-label'));
|
||||
|
||||
// Badge
|
||||
this.$badge = dom.append(this.builder, dom.$('.badge'));
|
||||
this.$badgeContent = dom.append(this.$badge, dom.$('.badge-content'));
|
||||
this.badge = dom.append(this.element, dom.$('.badge'));
|
||||
this.badgeContent = dom.append(this.badge, dom.$('.badge-content'));
|
||||
|
||||
dom.hide(this.$badge);
|
||||
dom.hide(this.badge);
|
||||
|
||||
this.updateActivity();
|
||||
this.updateStyles();
|
||||
|
@ -223,7 +223,7 @@ export class ActivityActionItem extends BaseActionItem {
|
|||
|
||||
protected updateBadge(): void {
|
||||
const action = this.getAction();
|
||||
if (!this.$badge || !this.$badgeContent || !(action instanceof ActivityAction)) {
|
||||
if (!this.badge || !this.badgeContent || !(action instanceof ActivityAction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -233,8 +233,8 @@ export class ActivityActionItem extends BaseActionItem {
|
|||
this.badgeDisposable.dispose();
|
||||
this.badgeDisposable = Disposable.None;
|
||||
|
||||
dom.clearNode(this.$badgeContent);
|
||||
dom.hide(this.$badge);
|
||||
dom.clearNode(this.badgeContent);
|
||||
dom.hide(this.badge);
|
||||
|
||||
if (badge) {
|
||||
|
||||
|
@ -247,30 +247,30 @@ export class ActivityActionItem extends BaseActionItem {
|
|||
} else if (badge.number > 999) {
|
||||
number = number.charAt(0) + 'k';
|
||||
}
|
||||
this.$badgeContent.textContent = number;
|
||||
dom.show(this.$badge);
|
||||
this.badgeContent.textContent = number;
|
||||
dom.show(this.badge);
|
||||
}
|
||||
}
|
||||
|
||||
// Text
|
||||
else if (badge instanceof TextBadge) {
|
||||
this.$badgeContent.textContent = badge.text;
|
||||
dom.show(this.$badge);
|
||||
this.badgeContent.textContent = badge.text;
|
||||
dom.show(this.badge);
|
||||
}
|
||||
|
||||
// Text
|
||||
else if (badge instanceof IconBadge) {
|
||||
dom.show(this.$badge);
|
||||
dom.show(this.badge);
|
||||
}
|
||||
|
||||
// Progress
|
||||
else if (badge instanceof ProgressBadge) {
|
||||
dom.show(this.$badge);
|
||||
dom.show(this.badge);
|
||||
}
|
||||
|
||||
if (clazz) {
|
||||
dom.addClasses(this.$badge, clazz);
|
||||
this.badgeDisposable = toDisposable(() => dom.removeClasses(this.$badge, clazz));
|
||||
dom.addClasses(this.badge, clazz);
|
||||
this.badgeDisposable = toDisposable(() => dom.removeClasses(this.badge, clazz));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,15 +290,15 @@ export class ActivityActionItem extends BaseActionItem {
|
|||
|
||||
private updateLabel(): void {
|
||||
if (this.activity.cssClass) {
|
||||
dom.addClasses(this.$label, this.activity.cssClass);
|
||||
dom.addClasses(this.label, this.activity.cssClass);
|
||||
}
|
||||
if (!this.options.icon) {
|
||||
this.$label.textContent = this.getAction().label;
|
||||
this.label.textContent = this.getAction().label;
|
||||
}
|
||||
}
|
||||
|
||||
private updateTitle(title: string): void {
|
||||
[this.$label, this.$badge, this.$container].forEach(element => {
|
||||
[this.label, this.badge, this.container].forEach(element => {
|
||||
if (element) {
|
||||
element.setAttribute('aria-label', title);
|
||||
element.title = title;
|
||||
|
@ -313,7 +313,7 @@ export class ActivityActionItem extends BaseActionItem {
|
|||
clearTimeout(this.mouseUpTimeout);
|
||||
}
|
||||
|
||||
dom.removeNode(this.$badge);
|
||||
dom.removeNode(this.badge);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,7 +360,7 @@ export class CompositeOverflowActivityActionItem extends ActivityActionItem {
|
|||
this.actions = this.getActions();
|
||||
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => this.builder,
|
||||
getAnchor: () => this.element,
|
||||
getActions: () => TPromise.as(this.actions),
|
||||
onHide: () => dispose(this.actions)
|
||||
});
|
||||
|
@ -445,7 +445,7 @@ export class CompositeActionItem extends ActivityActionItem {
|
|||
CompositeActionItem.manageExtensionAction = instantiationService.createInstance(ManageExtensionAction);
|
||||
}
|
||||
|
||||
compositeActivityAction.onDidChangeActivity(() => { this.compositeActivity = null; this.updateActivity(); }, this, this._callOnDispose);
|
||||
this._register(compositeActivityAction.onDidChangeActivity(() => { this.compositeActivity = null; this.updateActivity(); }, this));
|
||||
}
|
||||
|
||||
protected get activity(): IActivity {
|
||||
|
@ -483,14 +483,14 @@ export class CompositeActionItem extends ActivityActionItem {
|
|||
this._updateChecked();
|
||||
this._updateEnabled();
|
||||
|
||||
this.callOnDispose.push(dom.addDisposableListener(this.$container, dom.EventType.CONTEXT_MENU, e => {
|
||||
this._register(dom.addDisposableListener(this.container, dom.EventType.CONTEXT_MENU, e => {
|
||||
dom.EventHelper.stop(e, true);
|
||||
|
||||
this.showContextMenu(container);
|
||||
}));
|
||||
|
||||
// Allow to drag
|
||||
this.callOnDispose.push(dom.addDisposableListener(this.$container, dom.EventType.DRAG_START, (e: DragEvent) => {
|
||||
this._register(dom.addDisposableListener(this.container, dom.EventType.DRAG_START, (e: DragEvent) => {
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
|
||||
// Registe as dragged to local transfer
|
||||
|
@ -502,7 +502,7 @@ export class CompositeActionItem extends ActivityActionItem {
|
|||
}
|
||||
}));
|
||||
|
||||
this.callOnDispose.push(new DragAndDropObserver(this.$container, {
|
||||
this._register(new DragAndDropObserver(this.container, {
|
||||
onDragEnter: e => {
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) && this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype)[0].id !== this.activity.id) {
|
||||
this.updateFromDragging(container, true);
|
||||
|
@ -539,7 +539,7 @@ export class CompositeActionItem extends ActivityActionItem {
|
|||
}));
|
||||
|
||||
// Activate on drag over to reveal targets
|
||||
[this.$badge, this.$label].forEach(b => new DelayedDragHandler(b, () => {
|
||||
[this.badge, this.label].forEach(b => new DelayedDragHandler(b, () => {
|
||||
if (!this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) && !this.getAction().checked) {
|
||||
this.getAction().run();
|
||||
}
|
||||
|
@ -578,35 +578,35 @@ export class CompositeActionItem extends ActivityActionItem {
|
|||
}
|
||||
|
||||
focus(): void {
|
||||
this.$container.focus();
|
||||
this.container.focus();
|
||||
}
|
||||
|
||||
protected _updateClass(): void {
|
||||
if (this.cssClass) {
|
||||
dom.removeClasses(this.$label, this.cssClass);
|
||||
dom.removeClasses(this.label, this.cssClass);
|
||||
}
|
||||
|
||||
this.cssClass = this.getAction().class;
|
||||
if (this.cssClass) {
|
||||
dom.addClasses(this.$label, this.cssClass);
|
||||
dom.addClasses(this.label, this.cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
protected _updateChecked(): void {
|
||||
if (this.getAction().checked) {
|
||||
dom.addClass(this.$container, 'checked');
|
||||
this.$container.setAttribute('aria-label', nls.localize('compositeActive', "{0} active", this.$container.title));
|
||||
dom.addClass(this.container, 'checked');
|
||||
this.container.setAttribute('aria-label', nls.localize('compositeActive', "{0} active", this.container.title));
|
||||
} else {
|
||||
dom.removeClass(this.$container, 'checked');
|
||||
this.$container.setAttribute('aria-label', this.$container.title);
|
||||
dom.removeClass(this.container, 'checked');
|
||||
this.container.setAttribute('aria-label', this.container.title);
|
||||
}
|
||||
}
|
||||
|
||||
protected _updateEnabled(): void {
|
||||
if (this.getAction().enabled) {
|
||||
dom.removeClass(this.builder, 'disabled');
|
||||
dom.removeClass(this.element, 'disabled');
|
||||
} else {
|
||||
dom.addClass(this.builder, 'disabled');
|
||||
dom.addClass(this.element, 'disabled');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -615,7 +615,7 @@ export class CompositeActionItem extends ActivityActionItem {
|
|||
|
||||
this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype);
|
||||
|
||||
dom.removeNode(this.$label);
|
||||
dom.removeNode(this.label);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -106,9 +106,9 @@ export class NotificationsCenter extends Themable {
|
|||
|
||||
private updateTitle(): void {
|
||||
if (this.model.notifications.length === 0) {
|
||||
this.notificationsCenterTitle.innerText = localize('notificationsEmpty', "No new notifications");
|
||||
this.notificationsCenterTitle.textContent = localize('notificationsEmpty', "No new notifications");
|
||||
} else {
|
||||
this.notificationsCenterTitle.innerText = localize('notifications', "Notifications");
|
||||
this.notificationsCenterTitle.textContent = localize('notifications', "Notifications");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -426,10 +426,10 @@ export class NotificationTemplateRenderer {
|
|||
|
||||
private renderSource(notification): void {
|
||||
if (notification.expanded && notification.source) {
|
||||
this.template.source.innerText = localize('notificationSource', "Source: {0}", notification.source);
|
||||
this.template.source.textContent = localize('notificationSource', "Source: {0}", notification.source);
|
||||
this.template.source.title = notification.source;
|
||||
} else {
|
||||
this.template.source.innerText = '';
|
||||
this.template.source.textContent = '';
|
||||
this.template.source.removeAttribute('title');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ import * as paths from 'vs/base/common/paths';
|
|||
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
export class ResourceContextKey implements IContextKey<URI>, IDisposable {
|
||||
export class ResourceContextKey extends Disposable implements IContextKey<URI> {
|
||||
|
||||
static Scheme = new RawContextKey<string>('resourceScheme', undefined);
|
||||
static Filename = new RawContextKey<string>('resourceFilename', undefined);
|
||||
|
@ -32,13 +32,14 @@ export class ResourceContextKey implements IContextKey<URI>, IDisposable {
|
|||
private _hasResource: IContextKey<boolean>;
|
||||
private _isfileSystemResource: IContextKey<boolean>;
|
||||
private _isFileSystemResourceOrUntitled: IContextKey<boolean>;
|
||||
private toDispose: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@IModeService private readonly _modeService: IModeService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._schemeKey = ResourceContextKey.Scheme.bindTo(contextKeyService);
|
||||
this._filenameKey = ResourceContextKey.Filename.bindTo(contextKeyService);
|
||||
this._langIdKey = ResourceContextKey.LangId.bindTo(contextKeyService);
|
||||
|
@ -47,7 +48,8 @@ export class ResourceContextKey implements IContextKey<URI>, IDisposable {
|
|||
this._hasResource = ResourceContextKey.HasResource.bindTo(contextKeyService);
|
||||
this._isfileSystemResource = ResourceContextKey.IsFileSystemResource.bindTo(contextKeyService);
|
||||
this._isFileSystemResourceOrUntitled = ResourceContextKey.IsFileSystemResourceOrUntitled.bindTo(contextKeyService);
|
||||
this.toDispose.push(_fileService.onDidChangeFileSystemProviderRegistrations(() => {
|
||||
|
||||
this._register(_fileService.onDidChangeFileSystemProviderRegistrations(() => {
|
||||
const resource = this._resourceKey.get();
|
||||
this._isfileSystemResource.set(resource && _fileService.canHandleResource(resource));
|
||||
this._isFileSystemResourceOrUntitled.set(this._isfileSystemResource.get() || this._schemeKey.get() === Schemas.untitled);
|
||||
|
@ -77,10 +79,6 @@ export class ResourceContextKey implements IContextKey<URI>, IDisposable {
|
|||
get(): URI {
|
||||
return this._resourceKey.get();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.toDispose = dispose(this.toDispose);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -377,7 +377,7 @@ export class DropDownMenuActionItem extends ActionItem {
|
|||
|
||||
public showMenu(): void {
|
||||
const actions = this.getActions();
|
||||
let elementPosition = DOM.getDomNodePagePosition(this.builder);
|
||||
let elementPosition = DOM.getDomNodePagePosition(this.element);
|
||||
const anchor = { x: elementPosition.left, y: elementPosition.top + elementPosition.height + 10 };
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => anchor,
|
||||
|
|
|
@ -93,14 +93,12 @@ export interface IMarkersFilterActionItemOptions {
|
|||
|
||||
export class MarkersFilterActionItem extends BaseActionItem {
|
||||
|
||||
private _toDispose: IDisposable[] = [];
|
||||
|
||||
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
private delayedFilterUpdate: Delayer<void>;
|
||||
private container: HTMLElement;
|
||||
private element: HTMLElement;
|
||||
private filterContainer: HTMLElement;
|
||||
private filterInputBox: HistoryInputBox;
|
||||
private controlsContainer: HTMLInputElement;
|
||||
private filterBadge: HTMLInputElement;
|
||||
|
@ -123,7 +121,7 @@ export class MarkersFilterActionItem extends BaseActionItem {
|
|||
render(container: HTMLElement): void {
|
||||
this.container = container;
|
||||
DOM.addClass(this.container, 'markers-panel-action-filter-container');
|
||||
DOM.append(this.container, this.element);
|
||||
DOM.append(this.container, this.filterContainer);
|
||||
this.adjustInputBox();
|
||||
}
|
||||
|
||||
|
@ -157,9 +155,9 @@ export class MarkersFilterActionItem extends BaseActionItem {
|
|||
}
|
||||
|
||||
private create(itemOptions: IMarkersFilterActionItemOptions): void {
|
||||
this.element = DOM.$('.markers-panel-action-filter');
|
||||
this.createInput(this.element, itemOptions);
|
||||
this.createControls(this.element, itemOptions);
|
||||
this.filterContainer = DOM.$('.markers-panel-action-filter');
|
||||
this.createInput(this.filterContainer, itemOptions);
|
||||
this.createControls(this.filterContainer, itemOptions);
|
||||
}
|
||||
|
||||
private createInput(container: HTMLElement, itemOptions: IMarkersFilterActionItemOptions): void {
|
||||
|
@ -271,11 +269,6 @@ export class MarkersFilterActionItem extends BaseActionItem {
|
|||
*/
|
||||
this.telemetryService.publicLog('problems.filter', data);
|
||||
}
|
||||
|
||||
private _register<T extends IDisposable>(t: T): T {
|
||||
this._toDispose.push(t);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickFixAction extends Action {
|
||||
|
@ -354,7 +347,7 @@ export class QuickFixActionItem extends ActionItem {
|
|||
|
||||
public onClick(event: DOM.EventLike): void {
|
||||
DOM.EventHelper.stop(event, true);
|
||||
const elementPosition = DOM.getDomNodePagePosition(this.builder);
|
||||
const elementPosition = DOM.getDomNodePagePosition(this.element);
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => ({ x: elementPosition.left + 10, y: elementPosition.top + elementPosition.height }),
|
||||
getActions: () => TPromise.wrap((<QuickFixAction>this.getAction()).getQuickFixActions()),
|
||||
|
|
|
@ -317,7 +317,7 @@ export class FolderSettingsActionItem extends BaseActionItem {
|
|||
}
|
||||
|
||||
public render(container: HTMLElement): void {
|
||||
this.builder = container;
|
||||
this.element = container;
|
||||
|
||||
this.container = container;
|
||||
this.labelElement = DOM.$('.action-title');
|
||||
|
|
|
@ -109,7 +109,7 @@ class StatusBarActionItem extends ActionItem {
|
|||
|
||||
_updateLabel(): void {
|
||||
if (this.options.label) {
|
||||
this.$e.innerHTML = renderOcticons(this.getAction().label);
|
||||
this.label.innerHTML = renderOcticons(this.getAction().label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue