sprotty
Version:
A next-gen framework for graphical views
290 lines • 13.2 kB
JavaScript
"use strict";
/********************************************************************************
* Copyright (c) 2017-2021 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
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 __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SelectKeyboardListener = exports.GetSelectionCommand = exports.SelectMouseListener = exports.SelectAllCommand = exports.SelectCommand = void 0;
const inversify_1 = require("inversify");
const actions_1 = require("sprotty-protocol/lib/actions");
const command_1 = require("../../base/commands/command");
const request_command_1 = require("../../base/commands/request-command");
const smodel_1 = require("../../base/model/smodel");
const smodel_utils_1 = require("../../base/model/smodel-utils");
const types_1 = require("../../base/types");
const key_tool_1 = require("../../base/views/key-tool");
const mouse_tool_1 = require("../../base/views/mouse-tool");
const vnode_utils_1 = require("../../base/views/vnode-utils");
const browser_1 = require("../../utils/browser");
const iterable_1 = require("../../utils/iterable");
const keyboard_1 = require("../../utils/keyboard");
const button_handler_1 = require("../button/button-handler");
const model_1 = require("../button/model");
const edit_routing_1 = require("../edit/edit-routing");
const model_2 = require("../routing/model");
const model_3 = require("../routing/model");
const scroll_1 = require("../viewport/scroll");
const model_4 = require("./model");
let SelectCommand = class SelectCommand extends command_1.Command {
constructor(action) {
super();
this.action = action;
this.selected = [];
this.deselected = [];
}
execute(context) {
const model = context.root;
this.action.selectedElementsIDs.forEach(id => {
const element = model.index.getById(id);
if (element instanceof smodel_1.SChildElementImpl && (0, model_4.isSelectable)(element)) {
this.selected.push(element);
}
});
this.action.deselectedElementsIDs.forEach(id => {
const element = model.index.getById(id);
if (element instanceof smodel_1.SChildElementImpl && (0, model_4.isSelectable)(element)) {
this.deselected.push(element);
}
});
return this.redo(context);
}
undo(context) {
for (const element of this.selected) {
element.selected = false;
}
for (const element of this.deselected) {
element.selected = true;
}
return context.root;
}
redo(context) {
for (const element of this.deselected) {
element.selected = false;
}
for (const element of this.selected) {
element.selected = true;
}
return context.root;
}
};
exports.SelectCommand = SelectCommand;
SelectCommand.KIND = actions_1.SelectAction.KIND;
exports.SelectCommand = SelectCommand = __decorate([
(0, inversify_1.injectable)(),
__param(0, (0, inversify_1.inject)(types_1.TYPES.Action)),
__metadata("design:paramtypes", [Object])
], SelectCommand);
let SelectAllCommand = class SelectAllCommand extends command_1.Command {
constructor(action) {
super();
this.action = action;
this.previousSelection = {};
}
execute(context) {
this.selectAll(context.root, this.action.select);
return context.root;
}
selectAll(element, newState) {
if ((0, model_4.isSelectable)(element)) {
this.previousSelection[element.id] = element.selected;
element.selected = newState;
}
for (const child of element.children) {
this.selectAll(child, newState);
}
}
undo(context) {
const index = context.root.index;
Object.keys(this.previousSelection).forEach(id => {
const element = index.getById(id);
if (element !== undefined && (0, model_4.isSelectable)(element))
element.selected = this.previousSelection[id];
});
return context.root;
}
redo(context) {
this.selectAll(context.root, this.action.select);
return context.root;
}
};
exports.SelectAllCommand = SelectAllCommand;
SelectAllCommand.KIND = actions_1.SelectAllAction.KIND;
exports.SelectAllCommand = SelectAllCommand = __decorate([
(0, inversify_1.injectable)(),
__param(0, (0, inversify_1.inject)(types_1.TYPES.Action)),
__metadata("design:paramtypes", [Object])
], SelectAllCommand);
class SelectMouseListener extends mouse_tool_1.MouseListener {
constructor() {
super(...arguments);
this.wasSelected = false;
this.hasDragged = false;
this.isMouseDown = false;
}
mouseDown(target, event) {
if (event.button !== 0) {
return [];
}
this.isMouseDown = true;
const buttonHandled = this.handleButton(target, event);
if (buttonHandled) {
return buttonHandled;
}
const selectableTarget = (0, smodel_utils_1.findParentByFeature)(target, model_4.isSelectable);
if (selectableTarget !== undefined || target instanceof smodel_1.SModelRootImpl) {
this.hasDragged = false;
}
if (selectableTarget !== undefined) {
let deselectedElements = [];
// multi-selection?
if (!(0, browser_1.isCtrlOrCmd)(event)) {
deselectedElements = this.collectElementsToDeselect(target, selectableTarget);
}
if (!selectableTarget.selected) {
this.wasSelected = false;
return this.handleSelectTarget(selectableTarget, deselectedElements, event);
}
else if ((0, browser_1.isCtrlOrCmd)(event)) {
this.wasSelected = false;
return this.handleDeselectTarget(selectableTarget, event);
}
else {
this.wasSelected = true;
}
}
return [];
}
collectElementsToDeselect(target, selectableTarget) {
return (0, iterable_1.toArray)(target.root.index.all()
.filter(element => (0, model_4.isSelectable)(element) && element.selected
&& !(selectableTarget instanceof model_2.SRoutingHandleImpl && element === selectableTarget.parent)));
}
handleButton(target, event) {
if (this.buttonHandlerRegistry !== undefined && target instanceof model_1.SButtonImpl && target.enabled) {
const buttonHandler = this.buttonHandlerRegistry.get(target.type);
if (buttonHandler !== undefined) {
return buttonHandler.buttonPressed(target);
}
}
return undefined;
}
handleSelectTarget(selectableTarget, deselectedElements, event) {
const result = [];
result.push(actions_1.SelectAction.create({ selectedElementsIDs: [selectableTarget.id], deselectedElementsIDs: deselectedElements.map(e => e.id) }));
result.push(actions_1.BringToFrontAction.create([selectableTarget.id]));
const routableDeselect = deselectedElements.filter(e => e instanceof model_3.SRoutableElementImpl).map(e => e.id);
if (selectableTarget instanceof model_3.SRoutableElementImpl) {
result.push(edit_routing_1.SwitchEditModeAction.create({ elementsToActivate: [selectableTarget.id], elementsToDeactivate: routableDeselect }));
}
else if (routableDeselect.length > 0) {
result.push(edit_routing_1.SwitchEditModeAction.create({ elementsToDeactivate: routableDeselect }));
}
return result;
}
handleDeselectTarget(selectableTarget, event) {
const result = [];
result.push(actions_1.SelectAction.create({ selectedElementsIDs: [], deselectedElementsIDs: [selectableTarget.id] }));
if (selectableTarget instanceof model_3.SRoutableElementImpl) {
result.push(edit_routing_1.SwitchEditModeAction.create({ elementsToDeactivate: [selectableTarget.id] }));
}
return result;
}
handleDeselectAll(deselectedElements, event) {
const result = [];
result.push(actions_1.SelectAction.create({ selectedElementsIDs: [], deselectedElementsIDs: deselectedElements.map(e => e.id) }));
const routableDeselect = deselectedElements.filter(e => e instanceof model_3.SRoutableElementImpl).map(e => e.id);
if (routableDeselect.length > 0) {
result.push(edit_routing_1.SwitchEditModeAction.create({ elementsToDeactivate: routableDeselect }));
}
return result;
}
mouseMove(target, event) {
this.hasDragged = this.isMouseDown;
return [];
}
mouseUp(target, event) {
if (event.button === 0) {
if (!this.hasDragged) {
const selectableTarget = (0, smodel_utils_1.findParentByFeature)(target, model_4.isSelectable);
if (selectableTarget !== undefined) {
if (this.wasSelected) {
return [actions_1.SelectAction.create({ selectedElementsIDs: [selectableTarget.id], deselectedElementsIDs: [] })];
}
}
else if ((target instanceof smodel_1.SModelRootImpl && !(0, scroll_1.findViewportScrollbar)(event)) || !(target instanceof smodel_1.SModelRootImpl)) {
// Mouse up on everything that's not root or root but not over ViewPort's scroll bars > deselect all
return this.handleDeselectAll(this.collectElementsToDeselect(target, undefined), event);
}
}
}
this.isMouseDown = false;
this.hasDragged = false;
return [];
}
decorate(vnode, element) {
const selectableTarget = (0, smodel_utils_1.findParentByFeature)(element, model_4.isSelectable);
if (selectableTarget !== undefined) {
(0, vnode_utils_1.setClass)(vnode, 'selected', selectableTarget.selected);
}
return vnode;
}
}
exports.SelectMouseListener = SelectMouseListener;
__decorate([
(0, inversify_1.inject)(button_handler_1.ButtonHandlerRegistry),
(0, inversify_1.optional)(),
__metadata("design:type", button_handler_1.ButtonHandlerRegistry)
], SelectMouseListener.prototype, "buttonHandlerRegistry", void 0);
let GetSelectionCommand = class GetSelectionCommand extends request_command_1.ModelRequestCommand {
constructor(action) {
super();
this.action = action;
this.previousSelection = {};
}
retrieveResult(context) {
const selection = context.root.index.all()
.filter(e => (0, model_4.isSelectable)(e) && e.selected)
.map(e => e.id);
return actions_1.SelectionResult.create((0, iterable_1.toArray)(selection), this.action.requestId);
}
};
exports.GetSelectionCommand = GetSelectionCommand;
GetSelectionCommand.KIND = actions_1.GetSelectionAction.KIND;
exports.GetSelectionCommand = GetSelectionCommand = __decorate([
(0, inversify_1.injectable)(),
__param(0, (0, inversify_1.inject)(types_1.TYPES.Action)),
__metadata("design:paramtypes", [Object])
], GetSelectionCommand);
class SelectKeyboardListener extends key_tool_1.KeyListener {
keyDown(element, event) {
if ((0, keyboard_1.matchesKeystroke)(event, 'KeyA', 'ctrlCmd')) {
return [actions_1.SelectAllAction.create()];
}
return [];
}
}
exports.SelectKeyboardListener = SelectKeyboardListener;
//# sourceMappingURL=select.js.map