@eclipse-glsp/client 2.3.0-next.317 → 2.3.0-next.319

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/css/ghost-element.css +3 -1
  2. package/css/glsp-sprotty.css +0 -5
  3. package/lib/base/action-handler-registry.d.ts +10 -1
  4. package/lib/base/action-handler-registry.d.ts.map +1 -1
  5. package/lib/base/action-handler-registry.js +40 -2
  6. package/lib/base/action-handler-registry.js.map +1 -1
  7. package/lib/base/default.module.d.ts.map +1 -1
  8. package/lib/base/default.module.js +5 -0
  9. package/lib/base/default.module.js.map +1 -1
  10. package/lib/base/feedback/feedback-action-dispatcher.d.ts +28 -1
  11. package/lib/base/feedback/feedback-action-dispatcher.d.ts.map +1 -1
  12. package/lib/base/feedback/feedback-action-dispatcher.js +23 -1
  13. package/lib/base/feedback/feedback-action-dispatcher.js.map +1 -1
  14. package/lib/base/feedback/feedback-command.d.ts +8 -3
  15. package/lib/base/feedback/feedback-command.d.ts.map +1 -1
  16. package/lib/base/feedback/feedback-command.js +13 -2
  17. package/lib/base/feedback/feedback-command.js.map +1 -1
  18. package/lib/base/feedback/index.d.ts +1 -0
  19. package/lib/base/feedback/index.d.ts.map +1 -1
  20. package/lib/base/feedback/index.js +1 -0
  21. package/lib/base/feedback/index.js.map +1 -1
  22. package/lib/base/feedback/set-model-command.d.ts +25 -0
  23. package/lib/base/feedback/set-model-command.d.ts.map +1 -0
  24. package/lib/base/feedback/set-model-command.js +65 -0
  25. package/lib/base/feedback/set-model-command.js.map +1 -0
  26. package/lib/base/feedback/update-model-command.d.ts +17 -6
  27. package/lib/base/feedback/update-model-command.d.ts.map +1 -1
  28. package/lib/base/feedback/update-model-command.js +8 -28
  29. package/lib/base/feedback/update-model-command.js.map +1 -1
  30. package/lib/base/ranked.d.ts +10 -0
  31. package/lib/base/ranked.d.ts.map +1 -1
  32. package/lib/base/ranked.js +6 -0
  33. package/lib/base/ranked.js.map +1 -1
  34. package/lib/base/selection-service.spec.js +4 -0
  35. package/lib/base/selection-service.spec.js.map +1 -1
  36. package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts +5 -3
  37. package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts.map +1 -1
  38. package/lib/features/bounds/glsp-hidden-bounds-updater.js +19 -2
  39. package/lib/features/bounds/glsp-hidden-bounds-updater.js.map +1 -1
  40. package/lib/features/bounds/local-bounds.d.ts +7 -3
  41. package/lib/features/bounds/local-bounds.d.ts.map +1 -1
  42. package/lib/features/bounds/local-bounds.js +8 -4
  43. package/lib/features/bounds/local-bounds.js.map +1 -1
  44. package/lib/features/bounds/set-bounds-feedback-command.d.ts +1 -1
  45. package/lib/features/bounds/set-bounds-feedback-command.d.ts.map +1 -1
  46. package/lib/features/bounds/set-bounds-feedback-command.js +4 -2
  47. package/lib/features/bounds/set-bounds-feedback-command.js.map +1 -1
  48. package/lib/features/element-template/add-template-element.d.ts.map +1 -1
  49. package/lib/features/element-template/add-template-element.js +5 -4
  50. package/lib/features/element-template/add-template-element.js.map +1 -1
  51. package/lib/features/hints/type-hint-provider.d.ts +17 -2
  52. package/lib/features/hints/type-hint-provider.d.ts.map +1 -1
  53. package/lib/features/hints/type-hint-provider.js +12 -12
  54. package/lib/features/hints/type-hint-provider.js.map +1 -1
  55. package/lib/tsconfig.tsbuildinfo +1 -1
  56. package/lib/utils/contribution-provider.d.ts +27 -0
  57. package/lib/utils/contribution-provider.d.ts.map +1 -0
  58. package/lib/utils/contribution-provider.js +56 -0
  59. package/lib/utils/contribution-provider.js.map +1 -0
  60. package/lib/utils/gmodel-util.d.ts +1 -0
  61. package/lib/utils/gmodel-util.d.ts.map +1 -1
  62. package/lib/utils/gmodel-util.js +14 -4
  63. package/lib/utils/gmodel-util.js.map +1 -1
  64. package/package.json +3 -3
  65. package/src/base/action-handler-registry.ts +41 -2
  66. package/src/base/default.module.ts +7 -0
  67. package/src/base/feedback/feedback-action-dispatcher.ts +49 -1
  68. package/src/base/feedback/feedback-command.ts +15 -4
  69. package/src/base/feedback/index.ts +2 -0
  70. package/src/base/feedback/set-model-command.ts +45 -0
  71. package/src/base/feedback/update-model-command.ts +8 -45
  72. package/src/base/ranked.ts +14 -0
  73. package/src/base/selection-service.spec.ts +7 -1
  74. package/src/features/bounds/glsp-hidden-bounds-updater.ts +26 -4
  75. package/src/features/bounds/local-bounds.ts +23 -6
  76. package/src/features/bounds/set-bounds-feedback-command.ts +4 -2
  77. package/src/features/element-template/add-template-element.ts +5 -4
  78. package/src/features/hints/type-hint-provider.ts +5 -5
  79. package/src/utils/contribution-provider.ts +65 -0
  80. package/src/utils/gmodel-util.ts +15 -4
@@ -16,20 +16,21 @@
16
16
 
17
17
  import {
18
18
  Action,
19
+ BoundsData,
19
20
  ComputedBoundsAction,
20
21
  Deferred,
21
22
  EdgeRouterRegistry,
22
23
  ElementAndRoutingPoints,
23
24
  GModelElement,
24
- GRoutableElement,
25
25
  HiddenBoundsUpdater,
26
26
  IActionDispatcher,
27
+ ModelIndexImpl,
27
28
  RequestAction,
28
29
  ResponseAction
29
30
  } from '@eclipse-glsp/sprotty';
30
31
  import { inject, injectable, optional } from 'inversify';
31
32
  import { VNode } from 'snabbdom';
32
- import { calcElementAndRoute, isRoutable } from '../../utils/gmodel-util';
33
+ import { BoundsAwareModelElement, calcElementAndRoute, getDescendantIds, isRoutable } from '../../utils/gmodel-util';
33
34
  import { LocalComputedBoundsAction, LocalRequestBoundsAction } from './local-bounds';
34
35
 
35
36
  /**
@@ -42,8 +43,10 @@ export class GLSPHiddenBoundsUpdater extends HiddenBoundsUpdater {
42
43
  @inject(EdgeRouterRegistry) @optional() protected readonly edgeRouterRegistry?: EdgeRouterRegistry;
43
44
 
44
45
  protected element2route: ElementAndRoutingPoints[] = [];
45
- protected edges: GRoutableElement[] = [];
46
- protected nodes: VNode[] = [];
46
+
47
+ protected getElement2BoundsData(): Map<BoundsAwareModelElement, BoundsData> {
48
+ return this['element2boundsData'];
49
+ }
47
50
 
48
51
  override decorate(vnode: VNode, element: GModelElement): VNode {
49
52
  super.decorate(vnode, element);
@@ -54,6 +57,9 @@ export class GLSPHiddenBoundsUpdater extends HiddenBoundsUpdater {
54
57
  }
55
58
 
56
59
  override postUpdate(cause?: Action): void {
60
+ if (LocalRequestBoundsAction.is(cause) && cause.elementIDs) {
61
+ this.focusOnElements(cause.elementIDs);
62
+ }
57
63
  const actions = this.captureActions(() => super.postUpdate(cause));
58
64
  actions
59
65
  .filter(action => ComputedBoundsAction.is(action))
@@ -61,6 +67,22 @@ export class GLSPHiddenBoundsUpdater extends HiddenBoundsUpdater {
61
67
  this.element2route = [];
62
68
  }
63
69
 
70
+ protected focusOnElements(elementIDs: string[]): void {
71
+ const data = this.getElement2BoundsData();
72
+ if (data.size > 0) {
73
+ // expand given IDs to their descendent element IDs as we need their bounding boxes as well
74
+ const index = [...data.keys()][0].index;
75
+ const relevantIds = new Set(elementIDs.flatMap(elementId => this.expandElementId(elementId, index, elementIDs)));
76
+
77
+ // ensure we only keep the bounds of the elements we are interested in
78
+ data.forEach((_bounds, element) => !relevantIds.has(element.id) && data.delete(element));
79
+ }
80
+ }
81
+
82
+ protected expandElementId(id: string, index: ModelIndexImpl, elementIDs: string[]): string[] {
83
+ return getDescendantIds(index.getById(id));
84
+ }
85
+
64
86
  protected captureActions(call: () => void): Action[] {
65
87
  const capturingActionDispatcher = new CapturingActionDispatcher();
66
88
  const actualActionDispatcher = this.actionDispatcher;
@@ -26,21 +26,38 @@ import {
26
26
  GModelRootSchema,
27
27
  RequestBoundsAction,
28
28
  TYPES,
29
- ViewerOptions
29
+ ViewerOptions,
30
+ hasArrayProp
30
31
  } from '@eclipse-glsp/sprotty';
31
32
  import { inject, injectable } from 'inversify';
32
33
  import { ServerAction } from '../../base/model/glsp-model-source';
33
34
 
35
+ export interface LocalRequestBoundsAction extends RequestBoundsAction {
36
+ elementIDs?: string[];
37
+ }
38
+
34
39
  export namespace LocalRequestBoundsAction {
35
- export function is(object: unknown): object is RequestBoundsAction {
36
- return RequestBoundsAction.is(object) && !ServerAction.is(object);
40
+ export function is(object: unknown): object is LocalRequestBoundsAction {
41
+ return RequestBoundsAction.is(object) && !ServerAction.is(object) && hasArrayProp(object, 'elementIDs', true);
42
+ }
43
+
44
+ export function create(newRoot: GModelRootSchema, elementIDs?: string[]): LocalRequestBoundsAction {
45
+ return {
46
+ ...RequestBoundsAction.create(newRoot),
47
+ elementIDs
48
+ };
37
49
  }
38
50
 
39
- export function fromCommand(context: CommandExecutionContext, actionDispatcher: ActionDispatcher, cause?: Action): CommandResult {
51
+ export function fromCommand(
52
+ { root }: CommandExecutionContext,
53
+ actionDispatcher: ActionDispatcher,
54
+ cause?: Action,
55
+ elementIDs?: string[]
56
+ ): CommandResult {
40
57
  // do not modify the main model (modelChanged = false) but request local bounds calculation on hidden model
41
- actionDispatcher.dispatch(RequestBoundsAction.create(context.root as unknown as GModelRootSchema));
58
+ actionDispatcher.dispatch(LocalRequestBoundsAction.create(root as unknown as GModelRootSchema, elementIDs));
42
59
  return {
43
- model: context.root,
60
+ model: root,
44
61
  modelChanged: false,
45
62
  cause
46
63
  };
@@ -24,6 +24,7 @@ import {
24
24
  isLayoutContainer
25
25
  } from '@eclipse-glsp/sprotty';
26
26
  import { inject, injectable } from 'inversify';
27
+ import { Ranked } from '../../base';
27
28
  import { GLSPActionDispatcher } from '../../base/action-dispatcher';
28
29
  import { FeedbackCommand } from '../../base/feedback/feedback-command';
29
30
  import { LocalRequestBoundsAction } from './local-bounds';
@@ -48,7 +49,7 @@ export namespace SetBoundsFeedbackAction {
48
49
  export class SetBoundsFeedbackCommand extends SetBoundsCommand implements FeedbackCommand {
49
50
  static override readonly KIND: string = SetBoundsFeedbackAction.KIND;
50
51
 
51
- readonly priority: number = 0;
52
+ readonly rank: number = Ranked.DEFAULT_RANK;
52
53
 
53
54
  @inject(TYPES.IActionDispatcher) protected actionDispatcher: GLSPActionDispatcher;
54
55
 
@@ -65,6 +66,7 @@ export class SetBoundsFeedbackCommand extends SetBoundsCommand implements Feedba
65
66
  element.layoutOptions = options;
66
67
  }
67
68
  });
68
- return LocalRequestBoundsAction.fromCommand(context, this.actionDispatcher, this.action);
69
+ const elementIDs = this.action.bounds.map(bounds => bounds.elementId);
70
+ return LocalRequestBoundsAction.fromCommand(context, this.actionDispatcher, this.action, elementIDs);
69
71
  }
70
72
  }
@@ -64,13 +64,14 @@ export class AddTemplateElementsFeedbackCommand extends FeedbackCommand {
64
64
  }
65
65
 
66
66
  override execute(context: CommandExecutionContext): CommandResult {
67
- this.action.templates
67
+ const templateElements = this.action.templates
68
68
  .map(template => templateToSchema(template, context))
69
69
  .filter(isNotUndefined)
70
70
  .map(schema => context.modelFactory.createElement(schema))
71
- .map(element => this.applyRootCssClasses(element, this.action.addClasses, this.action.removeClasses))
72
- .forEach(templateElement => context.root.add(templateElement));
73
- return LocalRequestBoundsAction.fromCommand(context, this.actionDispatcher, this.action);
71
+ .map(element => this.applyRootCssClasses(element, this.action.addClasses, this.action.removeClasses));
72
+ templateElements.forEach(templateElement => context.root.add(templateElement));
73
+ const templateElementIDs = templateElements.map(element => element.id);
74
+ return LocalRequestBoundsAction.fromCommand(context, this.actionDispatcher, this.action, templateElementIDs);
74
75
  }
75
76
 
76
77
  protected applyRootCssClasses(element: GChildElement, addClasses?: string[], removeClasses?: string[]): GChildElement {
@@ -13,19 +13,18 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { inject, injectable } from 'inversify';
17
16
  import {
18
17
  Action,
19
18
  CommandExecutionContext,
20
19
  Connectable,
21
20
  EdgeTypeHint,
22
- IActionHandler,
23
- RequestTypeHintsAction,
24
21
  GModelElement,
25
22
  GModelElementSchema,
26
23
  GModelRoot,
27
24
  GRoutableElement,
28
25
  GShapeElement,
26
+ IActionHandler,
27
+ RequestTypeHintsAction,
29
28
  SetTypeHintsAction,
30
29
  ShapeTypeHint,
31
30
  TYPES,
@@ -36,16 +35,17 @@ import {
36
35
  isConnectable,
37
36
  moveFeature
38
37
  } from '@eclipse-glsp/sprotty';
38
+ import { inject, injectable } from 'inversify';
39
39
 
40
40
  import { GLSPActionDispatcher } from '../../base/action-dispatcher';
41
41
  import { IFeedbackActionDispatcher } from '../../base/feedback/feedback-action-dispatcher';
42
42
  import { FeedbackCommand } from '../../base/feedback/feedback-command';
43
43
  import { IDiagramStartup } from '../../base/model/diagram-loader';
44
+ import { GEdge } from '../../model';
44
45
  import { getElementTypeId } from '../../utils/gmodel-util';
45
46
  import { resizeFeature } from '../change-bounds/model';
46
47
  import { reconnectFeature } from '../reconnect/model';
47
48
  import { containerFeature, isContainable, reparentFeature } from './model';
48
- import { GEdge } from '../../model';
49
49
 
50
50
  /**
51
51
  * Is dispatched by the {@link TypeHintProvider} to apply the type hints received from the server
@@ -78,7 +78,7 @@ type CanConnectFn = Connectable['canConnect'];
78
78
  @injectable()
79
79
  export class ApplyTypeHintsCommand extends FeedbackCommand {
80
80
  public static KIND = ApplyTypeHintsAction.KIND;
81
- public override readonly priority = 10;
81
+ public override readonly rank: number = -10;
82
82
 
83
83
  @inject(TYPES.ITypeHintProvider)
84
84
  protected typeHintProvider: ITypeHintProvider;
@@ -0,0 +1,65 @@
1
+ /*******************************************************************************
2
+ * Copyright (C) 2017 TypeFox and others.
3
+ * Modifications: (c) 2024 EclipseSource and others.
4
+ *
5
+ * This program and the accompanying materials are made available under the
6
+ * terms of the Eclipse Public License v. 2.0 which is available at
7
+ * http://www.eclipse.org/legal/epl-2.0.
8
+ *
9
+ * This Source Code may also be made available under the following Secondary
10
+ * Licenses when the conditions for such availability set forth in the Eclipse
11
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ * with the GNU Classpath Exception which is available at
13
+ * https://www.gnu.org/software/classpath/license.html.
14
+ *
15
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ *******************************************************************************/
17
+ // eslint-disable-next-line max-len
18
+ // based on https://github.com/eclipse-theia/theia/blob/9ff0cedff1d591b0eb4be97a05f6d992789d0a24/packages/core/src/common/contribution-provider.ts
19
+
20
+ import { BindingContext, TYPES } from '@eclipse-glsp/sprotty';
21
+ import { interfaces } from 'inversify';
22
+
23
+ export interface IContributionProvider<T extends object> {
24
+ /**
25
+ * @param recursive `true` if the contributions should be collected from the parent containers as well. Otherwise, `false`.
26
+ * It is `false` by default.
27
+ */
28
+ getContributions(recursive?: boolean): T[];
29
+ }
30
+
31
+ class ContainerBasedContributionProvider<T extends object> implements IContributionProvider<T> {
32
+ protected services: T[] | undefined;
33
+
34
+ constructor(
35
+ protected readonly serviceIdentifier: interfaces.ServiceIdentifier<T>,
36
+ protected readonly container: interfaces.Container
37
+ ) {}
38
+
39
+ getContributions(recursive?: boolean): T[] {
40
+ if (this.services === undefined) {
41
+ const currentServices: T[] = [];
42
+ let currentContainer: interfaces.Container | undefined = this.container;
43
+ while (currentContainer !== undefined) {
44
+ if (currentContainer.isBound(this.serviceIdentifier)) {
45
+ try {
46
+ currentServices.push(...currentContainer.getAll(this.serviceIdentifier));
47
+ } catch (error) {
48
+ console.error(error);
49
+ }
50
+ }
51
+ currentContainer = recursive === true && currentContainer.parent ? currentContainer.parent : undefined;
52
+ }
53
+ this.services = currentServices;
54
+ }
55
+ return this.services;
56
+ }
57
+ }
58
+
59
+ export function bindContributionProvider(context: Pick<BindingContext, 'bind'> | interfaces.Bind, id: symbol): void {
60
+ const bind = typeof context === 'object' ? context.bind.bind(context) : context;
61
+ bind(TYPES.IContributionProvider)
62
+ .toDynamicValue(ctx => new ContainerBasedContributionProvider(id, ctx.container))
63
+ .inSingletonScope()
64
+ .whenTargetNamed(id);
65
+ }
@@ -22,6 +22,7 @@ import {
22
22
  GChildElement,
23
23
  GModelElement,
24
24
  GModelElementSchema,
25
+ GParentElement,
25
26
  GRoutableElement,
26
27
  GRoutingHandle,
27
28
  ModelIndexImpl,
@@ -30,13 +31,12 @@ import {
30
31
  Selectable,
31
32
  TypeGuard,
32
33
  distinctAdd,
33
- findParentByFeature,
34
34
  getAbsoluteBounds,
35
+ getZoom,
35
36
  isBoundsAware,
36
37
  isMoveable,
37
38
  isSelectable,
38
39
  isSelected,
39
- isViewport,
40
40
  remove
41
41
  } from '@eclipse-glsp/sprotty';
42
42
 
@@ -346,8 +346,7 @@ export function findTopLevelElementByFeature<T>(
346
346
 
347
347
  export function calculateDeltaBetweenPoints(target: Point, source: Point, element: GModelElement): Point {
348
348
  const delta = Point.subtract(target, source);
349
- const viewport = findParentByFeature(element, isViewport);
350
- const zoom = viewport?.zoom ?? 1;
349
+ const zoom = getZoom(element);
351
350
  const adaptedDelta = { x: delta.x / zoom, y: delta.y / zoom };
352
351
  return adaptedDelta;
353
352
  }
@@ -362,3 +361,15 @@ export function isVisibleOnCanvas(model: BoundsAwareModelElement): boolean {
362
361
  modelBounds.y + modelBounds.height >= 0
363
362
  );
364
363
  }
364
+
365
+ export function getDescendantIds(element?: GModelElement, skip?: (t: GModelElement) => boolean): string[] {
366
+ if (!element || skip?.(element)) {
367
+ return [];
368
+ }
369
+ const parent = element;
370
+ const ids = [parent.id];
371
+ if (parent instanceof GParentElement) {
372
+ ids.push(...parent.children.flatMap(child => getDescendantIds(child, skip)));
373
+ }
374
+ return ids;
375
+ }