sprotty
Version:
A next-gen framework for graphical views
249 lines • 11.2 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var CommandPalette_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandPaletteKeyListener = exports.CommandPalette = void 0;
const inversify_1 = require("inversify");
const actions_1 = require("sprotty-protocol/lib/actions");
const action_1 = require("../../base/actions/action");
const types_1 = require("../../base/types");
const ui_extension_1 = require("../../base/ui-extensions/ui-extension");
const ui_extension_registry_1 = require("../../base/ui-extensions/ui-extension-registry");
const dom_helper_1 = require("../../base/views/dom-helper");
const key_tool_1 = require("../../base/views/key-tool");
const codicon_1 = require("../../utils/codicon");
const iterable_1 = require("../../utils/iterable");
const keyboard_1 = require("../../utils/keyboard");
const model_1 = require("../bounds/model");
const model_2 = require("../select/model");
const action_providers_1 = require("./action-providers");
const mouse_tool_1 = require("../../base/views/mouse-tool");
const autocompleter_1 = __importDefault(require("autocompleter"));
let CommandPalette = CommandPalette_1 = class CommandPalette extends ui_extension_1.AbstractUIExtension {
constructor() {
super(...arguments);
this.loadingIndicatorClasses = (0, codicon_1.codiconCSSClasses)('loading', false, true, ['loading']);
this.xOffset = 20;
this.yOffset = 20;
this.defaultWidth = 400;
this.debounceWaitMs = 100;
this.noCommandsMsg = "No commands available";
this.paletteIndex = 0;
}
id() { return CommandPalette_1.ID; }
containerClass() { return "command-palette"; }
show(root, ...contextElementIds) {
super.show(root, ...contextElementIds);
this.paletteIndex = 0;
this.contextActions = undefined;
this.inputElement.value = "";
this.autoCompleteResult = (0, autocompleter_1.default)(this.autocompleteSettings(root));
this.inputElement.focus();
}
initializeContents(containerElement) {
containerElement.style.position = "absolute";
this.inputElement = document.createElement('input');
this.inputElement.style.width = '100%';
this.inputElement.addEventListener('keydown', (event) => this.hideIfEscapeEvent(event));
this.inputElement.addEventListener('keydown', (event) => this.cylceIfInvokePaletteKey(event));
this.inputElement.onblur = () => window.setTimeout(() => this.hide(), 200);
containerElement.appendChild(this.inputElement);
}
hideIfEscapeEvent(event) {
if ((0, keyboard_1.matchesKeystroke)(event, 'Escape')) {
this.hide();
}
}
cylceIfInvokePaletteKey(event) {
if (CommandPalette_1.isInvokePaletteKey(event)) {
this.cycle();
}
}
cycle() {
this.contextActions = undefined;
this.paletteIndex++;
}
onBeforeShow(containerElement, root, ...selectedElementIds) {
let x = this.xOffset;
let y = this.yOffset;
const selectedElements = (0, iterable_1.toArray)(root.index.all().filter(e => (0, model_2.isSelectable)(e) && e.selected));
if (selectedElements.length === 1) {
const bounds = (0, model_1.getAbsoluteClientBounds)(selectedElements[0], this.domHelper, this.viewerOptions);
x += bounds.x + bounds.width;
y += bounds.y;
}
else {
const bounds = (0, model_1.getAbsoluteClientBounds)(root, this.domHelper, this.viewerOptions);
x += bounds.x;
y += bounds.y;
}
containerElement.style.left = `${x}px`;
containerElement.style.top = `${y}px`;
containerElement.style.width = `${this.defaultWidth}px`;
}
autocompleteSettings(root) {
return {
input: this.inputElement,
emptyMsg: this.noCommandsMsg,
className: "command-palette-suggestions",
debounceWaitMs: this.debounceWaitMs,
showOnFocus: true,
minLength: -1,
fetch: (text, update) => this.updateAutoCompleteActions(update, text, root),
onSelect: (item) => this.onSelect(item),
render: (item, currentValue) => this.renderLabeledActionSuggestion(item, currentValue),
customize: (input, inputRect, container, maxHeight) => {
this.customizeSuggestionContainer(container, inputRect, maxHeight);
}
};
}
onSelect(item) {
this.executeAction(item);
this.hide();
}
updateAutoCompleteActions(update, text, root) {
this.onLoading();
if (this.contextActions) {
update(this.filterActions(text, this.contextActions));
this.onLoaded('success');
}
else {
this.actionProviderRegistry
.getActions(root, text, this.mousePositionTracker.lastPositionOnDiagram, this.paletteIndex)
.then(actions => {
this.contextActions = actions;
update(this.filterActions(text, actions));
this.onLoaded('success');
})
.catch((reason) => {
this.logger.error(this, "Failed to obtain actions from command palette action providers", reason);
this.onLoaded('error');
});
}
}
onLoading() {
if (this.loadingIndicator && this.containerElement.contains(this.loadingIndicator)) {
return;
}
this.loadingIndicator = document.createElement('span');
this.loadingIndicator.classList.add(...this.loadingIndicatorClasses);
this.containerElement.appendChild(this.loadingIndicator);
}
onLoaded(success) {
if (this.containerElement.contains(this.loadingIndicator)) {
this.containerElement.removeChild(this.loadingIndicator);
}
}
renderLabeledActionSuggestion(item, value) {
const itemElement = document.createElement("div");
const wordMatcher = espaceForRegExp(value).split(" ").join("|");
const regex = new RegExp(wordMatcher, "gi");
if (item.icon) {
this.renderIcon(itemElement, item.icon);
}
if (value.length > 0) {
itemElement.innerHTML += item.label.replace(regex, (match) => "<em>" + match + "</em>").replace(/ /g, ' ');
}
else {
itemElement.innerHTML += item.label.replace(/ /g, ' ');
}
return itemElement;
}
renderIcon(itemElement, iconId) {
itemElement.innerHTML += `<span class="icon ${this.getCodicon(iconId)}"></span>`;
}
getFontAwesomeIcon(iconId) {
return `fa fa-${iconId}`;
}
getCodicon(iconId) {
return (0, codicon_1.codiconCSSString)(iconId);
}
filterActions(filterText, actions) {
return (0, iterable_1.toArray)(actions.filter(action => {
const label = action.label.toLowerCase();
const searchWords = filterText.split(' ');
return searchWords.every(word => label.indexOf(word.toLowerCase()) !== -1);
}));
}
customizeSuggestionContainer(container, inputRect, maxHeight) {
// move container into our command palette container as this is already positioned correctly
container.style.position = "fixed";
if (this.containerElement) {
this.containerElement.appendChild(container);
}
}
hide() {
super.hide();
if (this.autoCompleteResult) {
this.autoCompleteResult.destroy();
}
}
executeAction(input) {
this.actionDispatcherProvider()
.then((actionDispatcher) => actionDispatcher.dispatchAll(toActionArray(input)))
.catch((reason) => this.logger.error(this, 'No action dispatcher available to execute command palette action', reason));
}
};
exports.CommandPalette = CommandPalette;
CommandPalette.ID = "command-palette";
CommandPalette.isInvokePaletteKey = (event) => (0, keyboard_1.matchesKeystroke)(event, 'Space', 'ctrl');
__decorate([
(0, inversify_1.inject)(types_1.TYPES.IActionDispatcherProvider),
__metadata("design:type", Function)
], CommandPalette.prototype, "actionDispatcherProvider", void 0);
__decorate([
(0, inversify_1.inject)(types_1.TYPES.ICommandPaletteActionProviderRegistry),
__metadata("design:type", action_providers_1.CommandPaletteActionProviderRegistry)
], CommandPalette.prototype, "actionProviderRegistry", void 0);
__decorate([
(0, inversify_1.inject)(types_1.TYPES.ViewerOptions),
__metadata("design:type", Object)
], CommandPalette.prototype, "viewerOptions", void 0);
__decorate([
(0, inversify_1.inject)(types_1.TYPES.DOMHelper),
__metadata("design:type", dom_helper_1.DOMHelper)
], CommandPalette.prototype, "domHelper", void 0);
__decorate([
(0, inversify_1.inject)(mouse_tool_1.MousePositionTracker),
__metadata("design:type", mouse_tool_1.MousePositionTracker)
], CommandPalette.prototype, "mousePositionTracker", void 0);
exports.CommandPalette = CommandPalette = CommandPalette_1 = __decorate([
(0, inversify_1.injectable)()
], CommandPalette);
function toActionArray(input) {
if ((0, action_1.isLabeledAction)(input)) {
return input.actions;
}
else if ((0, actions_1.isAction)(input)) {
return [input];
}
return [];
}
function espaceForRegExp(value) {
return value.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
}
class CommandPaletteKeyListener extends key_tool_1.KeyListener {
keyDown(element, event) {
if ((0, keyboard_1.matchesKeystroke)(event, 'Escape')) {
return [ui_extension_registry_1.SetUIExtensionVisibilityAction.create({ extensionId: CommandPalette.ID, visible: false, contextElementsId: [] })];
}
else if (CommandPalette.isInvokePaletteKey(event)) {
const selectedElements = (0, iterable_1.toArray)(element.index.all().filter(e => (0, model_2.isSelectable)(e) && e.selected).map(e => e.id));
return [ui_extension_registry_1.SetUIExtensionVisibilityAction.create({ extensionId: CommandPalette.ID, visible: true, contextElementsId: selectedElements })];
}
return [];
}
}
exports.CommandPaletteKeyListener = CommandPaletteKeyListener;
//# sourceMappingURL=command-palette.js.map