Files
azuredatastudio/src/vs/workbench/browser/actions/developerActions.ts

284 lines
10 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/actions';
import * as nls from 'vs/nls';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { domEvent } from 'vs/base/browser/event';
import { Event } from 'vs/base/common/event';
import { IDisposable, toDisposable, dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { getDomNodePagePosition, createStyleSheet, createCSSRule, append, $ } from 'vs/base/browser/dom';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Context } from 'vs/platform/contextkey/browser/contextKeyService';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { timeout } from 'vs/base/common/async';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { Registry } from 'vs/platform/registry/common/platform';
import { registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { clamp } from 'vs/base/common/numbers';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
const developerCategory = { value: nls.localize({ key: 'developer', comment: ['A developer on Code itself or someone diagnosing issues in Code'] }, "Developer"), original: 'Developer' };
class InspectContextKeysAction extends Action2 {
constructor() {
super({
id: 'workbench.action.inspectContextKeys',
title: { value: nls.localize('inspect context keys', "Inspect Context Keys"), original: 'Inspect Context Keys' },
category: developerCategory,
f1: true
});
}
run(accessor: ServicesAccessor): void {
const contextKeyService = accessor.get(IContextKeyService);
const disposables = new DisposableStore();
const stylesheet = createStyleSheet();
disposables.add(toDisposable(() => {
if (stylesheet.parentNode) {
stylesheet.parentNode.removeChild(stylesheet);
}
}));
createCSSRule('*', 'cursor: crosshair !important;', stylesheet);
const hoverFeedback = document.createElement('div');
document.body.appendChild(hoverFeedback);
disposables.add(toDisposable(() => document.body.removeChild(hoverFeedback)));
hoverFeedback.style.position = 'absolute';
hoverFeedback.style.pointerEvents = 'none';
hoverFeedback.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
hoverFeedback.style.zIndex = '1000';
const onMouseMove = domEvent(document.body, 'mousemove', true);
disposables.add(onMouseMove(e => {
const target = e.target as HTMLElement;
const position = getDomNodePagePosition(target);
hoverFeedback.style.top = `${position.top}px`;
hoverFeedback.style.left = `${position.left}px`;
hoverFeedback.style.width = `${position.width}px`;
hoverFeedback.style.height = `${position.height}px`;
}));
const onMouseDown = Event.once(domEvent(document.body, 'mousedown', true));
onMouseDown(e => { e.preventDefault(); e.stopPropagation(); }, null, disposables);
const onMouseUp = Event.once(domEvent(document.body, 'mouseup', true));
onMouseUp(e => {
e.preventDefault();
e.stopPropagation();
const context = contextKeyService.getContext(e.target as HTMLElement) as Context;
console.log(context.collectAllValues());
dispose(disposables);
}, null, disposables);
}
}
class ToggleScreencastModeAction extends Action2 {
static disposable: IDisposable | undefined;
constructor() {
super({
id: 'workbench.action.toggleScreencastMode',
title: { value: nls.localize('toggle screencast mode', "Toggle Screencast Mode"), original: 'Toggle Screencast Mode' },
category: developerCategory,
f1: true
});
}
run(accessor: ServicesAccessor): void {
if (ToggleScreencastModeAction.disposable) {
ToggleScreencastModeAction.disposable.dispose();
ToggleScreencastModeAction.disposable = undefined;
return;
}
const layoutService = accessor.get(ILayoutService);
const configurationService = accessor.get(IConfigurationService);
const keybindingService = accessor.get(IKeybindingService);
const disposables = new DisposableStore();
const container = layoutService.container;
const mouseMarker = append(container, $('.screencast-mouse'));
disposables.add(toDisposable(() => mouseMarker.remove()));
const onMouseDown = domEvent(container, 'mousedown', true);
const onMouseUp = domEvent(container, 'mouseup', true);
const onMouseMove = domEvent(container, 'mousemove', true);
disposables.add(onMouseDown(e => {
mouseMarker.style.top = `${e.clientY - 10}px`;
mouseMarker.style.left = `${e.clientX - 10}px`;
mouseMarker.style.display = 'block';
const mouseMoveListener = onMouseMove(e => {
mouseMarker.style.top = `${e.clientY - 10}px`;
mouseMarker.style.left = `${e.clientX - 10}px`;
});
Event.once(onMouseUp)(() => {
mouseMarker.style.display = 'none';
mouseMoveListener.dispose();
});
}));
const keyboardMarker = append(container, $('.screencast-keyboard'));
disposables.add(toDisposable(() => keyboardMarker.remove()));
const updateKeyboardFontSize = () => {
keyboardMarker.style.fontSize = `${clamp(configurationService.getValue<number>('screencastMode.fontSize') || 56, 20, 100)}px`;
};
const updateKeyboardMarker = () => {
keyboardMarker.style.bottom = `${clamp(configurationService.getValue<number>('screencastMode.verticalOffset') || 0, 0, 90)}%`;
};
updateKeyboardFontSize();
updateKeyboardMarker();
disposables.add(configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('screencastMode.verticalOffset')) {
updateKeyboardMarker();
}
if (e.affectsConfiguration('screencastMode.fontSize')) {
updateKeyboardFontSize();
}
}));
const onKeyDown = domEvent(window, 'keydown', true);
let keyboardTimeout: IDisposable = Disposable.None;
let length = 0;
disposables.add(onKeyDown(e => {
keyboardTimeout.dispose();
const event = new StandardKeyboardEvent(e);
const shortcut = keybindingService.softDispatch(event, event.target);
if (shortcut || !configurationService.getValue<boolean>('screencastMode.onlyKeyboardShortcuts')) {
if (
event.ctrlKey || event.altKey || event.metaKey || event.shiftKey
|| length > 20
|| event.keyCode === KeyCode.Backspace || event.keyCode === KeyCode.Escape
) {
keyboardMarker.innerText = '';
length = 0;
}
const keybinding = keybindingService.resolveKeyboardEvent(event);
const label = keybinding.getLabel();
const key = $('span.key', {}, label || '');
length++;
append(keyboardMarker, key);
}
const promise = timeout(800);
keyboardTimeout = toDisposable(() => promise.cancel());
promise.then(() => {
keyboardMarker.textContent = '';
length = 0;
});
}));
ToggleScreencastModeAction.disposable = disposables;
}
}
class LogStorageAction extends Action2 {
constructor() {
super({
id: 'workbench.action.logStorage',
title: { value: nls.localize({ key: 'logStorage', comment: ['A developer only action to log the contents of the storage for the current window.'] }, "Log Storage Database Contents"), original: 'Log Storage Database Contents' },
category: developerCategory,
f1: true
});
}
run(accessor: ServicesAccessor): void {
accessor.get(IStorageService).logStorage();
}
}
class LogWorkingCopiesAction extends Action2 {
constructor() {
super({
id: 'workbench.action.logWorkingCopies',
title: { value: nls.localize({ key: 'logWorkingCopies', comment: ['A developer only action to log the working copies that exist.'] }, "Log Working Copies"), original: 'Log Working Copies' },
category: developerCategory,
f1: true
});
}
run(accessor: ServicesAccessor): void {
const workingCopyService = accessor.get(IWorkingCopyService);
const logService = accessor.get(ILogService);
const msg = [
`Dirty Working Copies:`,
...workingCopyService.dirtyWorkingCopies.map(workingCopy => workingCopy.resource.toString(true)),
``,
`All Working Copies:`,
...workingCopyService.workingCopies.map(workingCopy => workingCopy.resource.toString(true)),
];
logService.info(msg.join('\n'));
}
}
// --- Actions Registration
registerAction2(InspectContextKeysAction);
registerAction2(ToggleScreencastModeAction);
registerAction2(LogStorageAction);
registerAction2(LogWorkingCopiesAction);
// Screencast Mode
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
id: 'screencastMode',
order: 9,
title: nls.localize('screencastModeConfigurationTitle', "Screencast Mode"),
type: 'object',
properties: {
'screencastMode.verticalOffset': {
type: 'number',
default: 20,
minimum: 0,
maximum: 90,
description: nls.localize('screencastMode.location.verticalPosition', "Controls the vertical offset of the screencast mode overlay from the bottom as a percentage of the workbench height.")
},
'screencastMode.fontSize': {
type: 'number',
default: 56,
minimum: 20,
maximum: 100,
description: nls.localize('screencastMode.fontSize', "Controls the font size (in pixels) of the screencast mode keyboard.")
},
'screencastMode.onlyKeyboardShortcuts': {
type: 'boolean',
description: nls.localize('screencastMode.onlyKeyboardShortcuts', "Only show keyboard shortcuts in Screencast Mode."),
default: false
}
}
});