@eclipse-glsp/client
Version:
A sprotty-based client for GLSP
230 lines • 11.3 kB
JavaScript
;
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);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarkerNavigatorKeyListener = exports.MarkerNavigatorContextMenuItemProvider = exports.NavigateToMarkerActionHandler = exports.MarkerNavigator = exports.LeftToRightTopToBottomComparator = exports.GModelElementComparator = exports.NavigateToMarkerAction = void 0;
/********************************************************************************
* Copyright (c) 2020-2024 EclipseSource 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
********************************************************************************/
const sprotty_1 = require("@eclipse-glsp/sprotty");
const inversify_1 = require("inversify");
const selection_service_1 = require("../../base/selection-service");
const gmodel_util_1 = require("../../utils/gmodel-util");
const marker_1 = require("../../utils/marker");
var NavigateToMarkerAction;
(function (NavigateToMarkerAction) {
NavigateToMarkerAction.KIND = 'navigateToMarker';
function is(object) {
return sprotty_1.Action.hasKind(object, NavigateToMarkerAction.KIND) && (0, sprotty_1.hasStringProp)(object, 'direction') && (0, sprotty_1.hasArrayProp)(object, 'severities');
}
NavigateToMarkerAction.is = is;
function create(options) {
return {
kind: NavigateToMarkerAction.KIND,
direction: 'next',
severities: MarkerNavigator.ALL_SEVERITIES,
...options
};
}
NavigateToMarkerAction.create = create;
})(NavigateToMarkerAction || (exports.NavigateToMarkerAction = NavigateToMarkerAction = {}));
class GModelElementComparator {
compare(_one, _other) {
return 0;
}
}
exports.GModelElementComparator = GModelElementComparator;
/** Specifies the order of two selectable and bounds-aware elements left-to-right and top-to-bottom. */
let LeftToRightTopToBottomComparator = class LeftToRightTopToBottomComparator {
compare(one, other) {
const boundsOne = (0, sprotty_1.findParentByFeature)(one, gmodel_util_1.isSelectableAndBoundsAware);
const boundsOther = (0, sprotty_1.findParentByFeature)(other, gmodel_util_1.isSelectableAndBoundsAware);
if (boundsOne && boundsOther) {
if (boundsOne.bounds.y !== boundsOther.bounds.y) {
return boundsOne.bounds.y - boundsOther.bounds.y;
}
if (boundsOne.bounds.x !== boundsOther.bounds.x) {
return boundsOne.bounds.x - boundsOther.bounds.x;
}
}
return 0;
}
};
exports.LeftToRightTopToBottomComparator = LeftToRightTopToBottomComparator;
exports.LeftToRightTopToBottomComparator = LeftToRightTopToBottomComparator = __decorate([
(0, inversify_1.injectable)()
], LeftToRightTopToBottomComparator);
/**
* Specifies the next/previous marker in a graph model.
*
* This navigator uses a `MarkerComparator` to determine the order of markers. It can also return next/previous
*/
let MarkerNavigator = class MarkerNavigator {
next(root, current, predicate = marker_1.MarkerPredicates.ALL) {
const markers = this.getMarkers(root, predicate);
if (current === undefined) {
return markers.length > 0 ? markers[0] : undefined;
}
return markers[this.getNextIndex(current, markers) % markers.length];
}
previous(root, current, predicate = marker_1.MarkerPredicates.ALL) {
const markers = this.getMarkers(root, predicate);
if (current === undefined) {
return markers.length > 0 ? markers[0] : undefined;
}
return markers[this.getPreviousIndex(current, markers) % markers.length];
}
getMarkers(root, predicate) {
const markers = (0, marker_1.collectIssueMarkers)(root);
return markers.filter(predicate).sort(this.markerComparator.compare);
}
getNextIndex(current, markers) {
for (let index = 0; index < markers.length; index++) {
if (this.markerComparator.compare(markers[index], current) > 0) {
return index;
}
}
return 0;
}
getPreviousIndex(current, markers) {
for (let index = markers.length - 1; index >= 0; index--) {
if (this.markerComparator.compare(markers[index], current) < 0) {
return index;
}
}
return markers.length - 1;
}
};
exports.MarkerNavigator = MarkerNavigator;
MarkerNavigator.ALL_SEVERITIES = ['error', 'warning', 'info'];
__decorate([
(0, inversify_1.inject)(GModelElementComparator),
__metadata("design:type", GModelElementComparator)
], MarkerNavigator.prototype, "markerComparator", void 0);
exports.MarkerNavigator = MarkerNavigator = __decorate([
(0, inversify_1.injectable)()
], MarkerNavigator);
let NavigateToMarkerActionHandler = class NavigateToMarkerActionHandler {
handle(action) {
const selected = this.getSelectedElements(action);
const target = this.getTarget(action, selected);
const selectableTarget = target ? (0, sprotty_1.findParentByFeature)(target, sprotty_1.isSelectable) : undefined;
if (selectableTarget) {
const deselectedElementsIDs = selected.map(e => e.id).filter(id => id !== selectableTarget.id);
this.actionDispatcher.dispatch(sprotty_1.SelectAction.create({ selectedElementsIDs: [selectableTarget.id], deselectedElementsIDs }));
this.actionDispatcher.dispatch(sprotty_1.CenterAction.create([selectableTarget.id]));
}
}
getSelectedElements(action) {
if (action.selectedElementIds && action.selectedElementIds.length > 0) {
return (0, gmodel_util_1.getElements)(this.selectionService.getModelRoot().index, action.selectedElementIds, sprotty_1.isSelectable);
}
return this.selectionService.getSelectedElements();
}
getTarget(action, selected) {
const root = this.selectionService.getModelRoot();
const target = selected.sort(this.markerComparator.compare).find(sprotty_1.isBoundsAware);
if (action.direction === 'previous') {
return this.markerNavigator.previous(root, target, marker => this.matchesSeverities(action, marker));
}
else {
return this.markerNavigator.next(root, target, marker => this.matchesSeverities(action, marker));
}
}
matchesSeverities(action, marker) {
return marker.issues.find(issue => action.severities.includes(issue.severity)) !== undefined;
}
};
exports.NavigateToMarkerActionHandler = NavigateToMarkerActionHandler;
__decorate([
(0, inversify_1.inject)(GModelElementComparator),
__metadata("design:type", GModelElementComparator)
], NavigateToMarkerActionHandler.prototype, "markerComparator", void 0);
__decorate([
(0, inversify_1.inject)(MarkerNavigator),
__metadata("design:type", MarkerNavigator)
], NavigateToMarkerActionHandler.prototype, "markerNavigator", void 0);
__decorate([
(0, inversify_1.inject)(selection_service_1.SelectionService),
__metadata("design:type", selection_service_1.SelectionService)
], NavigateToMarkerActionHandler.prototype, "selectionService", void 0);
__decorate([
(0, inversify_1.inject)(sprotty_1.TYPES.IActionDispatcher),
__metadata("design:type", Object)
], NavigateToMarkerActionHandler.prototype, "actionDispatcher", void 0);
exports.NavigateToMarkerActionHandler = NavigateToMarkerActionHandler = __decorate([
(0, inversify_1.injectable)()
], NavigateToMarkerActionHandler);
let MarkerNavigatorContextMenuItemProvider = class MarkerNavigatorContextMenuItemProvider {
getItems(root, lastMousePosition) {
const selectedElementIds = Array.from(this.selectionService.getSelectedElementIDs());
const hasMarkers = (0, marker_1.collectIssueMarkers)(root).length > 0;
return Promise.resolve([
{
id: 'navigate',
label: 'Go to',
group: 'navigate',
actions: [],
children: [
{
id: 'next-marker',
label: 'Next marker',
group: 'marker',
actions: [NavigateToMarkerAction.create({ direction: 'next', selectedElementIds })],
isEnabled: () => hasMarkers
},
{
id: 'previous-marker',
label: 'Previous marker',
group: 'marker',
actions: [NavigateToMarkerAction.create({ direction: 'previous', selectedElementIds })],
isEnabled: () => hasMarkers
}
]
}
]);
}
};
exports.MarkerNavigatorContextMenuItemProvider = MarkerNavigatorContextMenuItemProvider;
__decorate([
(0, inversify_1.inject)(selection_service_1.SelectionService),
__metadata("design:type", selection_service_1.SelectionService)
], MarkerNavigatorContextMenuItemProvider.prototype, "selectionService", void 0);
exports.MarkerNavigatorContextMenuItemProvider = MarkerNavigatorContextMenuItemProvider = __decorate([
(0, inversify_1.injectable)()
], MarkerNavigatorContextMenuItemProvider);
let MarkerNavigatorKeyListener = class MarkerNavigatorKeyListener extends sprotty_1.KeyListener {
keyDown(_element, event) {
if ((0, sprotty_1.matchesKeystroke)(event, 'Period', 'ctrl')) {
return [NavigateToMarkerAction.create({ direction: 'next' })];
}
else if ((0, sprotty_1.matchesKeystroke)(event, 'Comma', 'ctrl')) {
return [NavigateToMarkerAction.create({ direction: 'previous' })];
}
return [];
}
};
exports.MarkerNavigatorKeyListener = MarkerNavigatorKeyListener;
exports.MarkerNavigatorKeyListener = MarkerNavigatorKeyListener = __decorate([
(0, inversify_1.injectable)()
], MarkerNavigatorKeyListener);
//# sourceMappingURL=marker-navigator.js.map