@eclipse-glsp/client 0.10.0-next.c94277c.176 → 1.0.0

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 (62) hide show
  1. package/css/decoration.css +5 -1
  2. package/css/glsp-sprotty.css +39 -0
  3. package/css/tool-palette.css +2 -2
  4. package/lib/base/container-modules.js +8 -8
  5. package/lib/base/container-modules.js.map +1 -1
  6. package/lib/features/context-menu/selection-service-aware-context-menu-mouse-listener.d.ts +5 -7
  7. package/lib/features/context-menu/selection-service-aware-context-menu-mouse-listener.d.ts.map +1 -1
  8. package/lib/features/context-menu/selection-service-aware-context-menu-mouse-listener.js +7 -14
  9. package/lib/features/context-menu/selection-service-aware-context-menu-mouse-listener.js.map +1 -1
  10. package/lib/features/hover/hover.d.ts +1 -2
  11. package/lib/features/hover/hover.d.ts.map +1 -1
  12. package/lib/features/hover/hover.js +2 -15
  13. package/lib/features/hover/hover.js.map +1 -1
  14. package/lib/features/mouse-tool/mouse-tool.d.ts +0 -1
  15. package/lib/features/mouse-tool/mouse-tool.d.ts.map +1 -1
  16. package/lib/features/mouse-tool/mouse-tool.js +0 -3
  17. package/lib/features/mouse-tool/mouse-tool.js.map +1 -1
  18. package/lib/features/select/select-mouse-listener.d.ts +3 -1
  19. package/lib/features/select/select-mouse-listener.d.ts.map +1 -1
  20. package/lib/features/select/select-mouse-listener.js +62 -0
  21. package/lib/features/select/select-mouse-listener.js.map +1 -1
  22. package/lib/features/source-model-watcher/di.config.d.ts +4 -0
  23. package/lib/features/{model-source-watcher → source-model-watcher}/di.config.d.ts.map +1 -1
  24. package/lib/features/{model-source-watcher → source-model-watcher}/di.config.js +4 -4
  25. package/lib/features/{model-source-watcher → source-model-watcher}/di.config.js.map +1 -1
  26. package/lib/features/{model-source-watcher/model-source-changed-action-handler.d.ts → source-model-watcher/source-model-changed-action-handler.d.ts} +9 -9
  27. package/lib/features/{model-source-watcher/model-source-changed-action-handler.d.ts.map → source-model-watcher/source-model-changed-action-handler.d.ts.map} +1 -1
  28. package/lib/features/{model-source-watcher/model-source-changed-action-handler.js → source-model-watcher/source-model-changed-action-handler.js} +19 -19
  29. package/lib/features/{model-source-watcher/model-source-changed-action-handler.js.map → source-model-watcher/source-model-changed-action-handler.js.map} +1 -1
  30. package/lib/features/validation/issue-marker.d.ts +11 -5
  31. package/lib/features/validation/issue-marker.d.ts.map +1 -1
  32. package/lib/features/validation/issue-marker.js +25 -5
  33. package/lib/features/validation/issue-marker.js.map +1 -1
  34. package/lib/features/validation/validate.d.ts.map +1 -1
  35. package/lib/features/validation/validate.js +6 -3
  36. package/lib/features/validation/validate.js.map +1 -1
  37. package/lib/index.d.ts +3 -3
  38. package/lib/index.d.ts.map +1 -1
  39. package/lib/index.js +11 -11
  40. package/lib/index.js.map +1 -1
  41. package/lib/views/glsp-projection-view.d.ts +30 -0
  42. package/lib/views/glsp-projection-view.d.ts.map +1 -0
  43. package/lib/views/glsp-projection-view.js +142 -0
  44. package/lib/views/glsp-projection-view.js.map +1 -0
  45. package/lib/views/index.d.ts +1 -0
  46. package/lib/views/index.d.ts.map +1 -1
  47. package/lib/views/index.js +1 -0
  48. package/lib/views/index.js.map +1 -1
  49. package/package.json +4 -4
  50. package/src/base/container-modules.ts +2 -2
  51. package/src/features/context-menu/selection-service-aware-context-menu-mouse-listener.ts +19 -25
  52. package/src/features/hover/hover.ts +2 -24
  53. package/src/features/mouse-tool/mouse-tool.ts +0 -4
  54. package/src/features/select/select-mouse-listener.ts +81 -1
  55. package/src/features/{model-source-watcher → source-model-watcher}/di.config.ts +5 -5
  56. package/src/features/{model-source-watcher/model-source-changed-action-handler.ts → source-model-watcher/source-model-changed-action-handler.ts} +12 -12
  57. package/src/features/validation/issue-marker.ts +34 -12
  58. package/src/features/validation/validate.ts +6 -4
  59. package/src/index.ts +3 -3
  60. package/src/views/glsp-projection-view.tsx +166 -0
  61. package/src/views/index.ts +2 -0
  62. package/lib/features/model-source-watcher/di.config.d.ts +0 -4
@@ -15,53 +15,47 @@
15
15
  ********************************************************************************/
16
16
  import { Action } from '@eclipse-glsp/protocol';
17
17
  import { inject, injectable, optional } from 'inversify';
18
- import {
19
- ContextMenuProviderRegistry,
20
- findParentByFeature,
21
- IContextMenuServiceProvider,
22
- isSelectable,
23
- MouseListener,
24
- SModelElement
25
- } from 'sprotty';
18
+ import { ContextMenuProviderRegistry, IContextMenuServiceProvider, MouseListener, SModelElement } from 'sprotty';
26
19
  import { FocusStateChangedAction } from '../../base/actions/focus-change-action';
27
20
  import { TYPES } from '../../base/types';
28
21
  import { SelectionService } from '../select/selection-service';
29
22
 
30
23
  @injectable()
31
24
  export class SelectionServiceAwareContextMenuMouseListener extends MouseListener {
32
- @inject(TYPES.IContextMenuServiceProvider) @optional() protected readonly contextMenuService: IContextMenuServiceProvider;
33
- @inject(TYPES.IContextMenuProviderRegistry) @optional() protected readonly menuProvider: ContextMenuProviderRegistry;
34
- @inject(TYPES.SelectionService) protected selectionService: SelectionService;
25
+ @inject(TYPES.IContextMenuServiceProvider)
26
+ @optional()
27
+ protected readonly contextMenuService?: IContextMenuServiceProvider;
28
+
29
+ @inject(TYPES.IContextMenuProviderRegistry)
30
+ @optional()
31
+ protected readonly menuProvider?: ContextMenuProviderRegistry;
32
+
33
+ @inject(TYPES.SelectionService)
34
+ protected selectionService: SelectionService;
35
35
 
36
36
  /**
37
- * Opens the context menu on right-click.
37
+ * Opens the context menu.
38
38
  */
39
- override mouseDown(target: SModelElement, event: MouseEvent): (Action | Promise<Action>)[] {
40
- if (event.button === 2 && this.contextMenuService && this.menuProvider) {
41
- return this.openContextMenu(event, target);
42
- }
43
- return [];
39
+ override contextMenu(target: SModelElement, event: MouseEvent): (Action | Promise<Action>)[] {
40
+ return this.openContextMenu(target, event);
44
41
  }
45
42
 
46
43
  /**
47
44
  * Opens the context menu.
48
45
  *
49
- * - query the element on the click-target
50
- * - select the element
51
46
  * - query the context menu service and the context menu elements
52
47
  * - show the context menu
53
48
  * - send a focus state change to indicate that the diagram becomes inactive, once the context menu is shown
54
49
  *
55
50
  * When the context menu is closed, we focus the diagram element again.
56
51
  */
57
- protected openContextMenu(event: MouseEvent, target: SModelElement): Promise<Action>[] {
58
- const mousePosition = { x: event.x, y: event.y };
59
- const selectableTarget = findParentByFeature(target, isSelectable);
60
- if (selectableTarget) {
61
- selectableTarget.selected = true;
62
- this.selectionService.updateSelection(target.root, [selectableTarget.id], []);
52
+ protected openContextMenu(target: SModelElement, event: MouseEvent): Promise<Action>[] {
53
+ if (!this.contextMenuService || !this.menuProvider) {
54
+ return [];
63
55
  }
64
56
 
57
+ const mousePosition = { x: event.x, y: event.y };
58
+
65
59
  const result = Promise.all([this.contextMenuService(), this.menuProvider.getItems(target.root, mousePosition)])
66
60
  .then(([menuService, menuItems]) => menuService.show(menuItems, mousePosition, () => this.focusEventTarget(event)))
67
61
  .then((): Action => FocusStateChangedAction.create(false));
@@ -23,20 +23,11 @@ import {
23
23
  SModelRootSchema
24
24
  } from '@eclipse-glsp/protocol';
25
25
  import { injectable } from 'inversify';
26
- import {
27
- EMPTY_ROOT,
28
- HoverFeedbackAction,
29
- HoverMouseListener,
30
- IActionHandler,
31
- ICommand,
32
- SIssueMarker,
33
- SIssueSeverity,
34
- SModelElement
35
- } from 'sprotty';
26
+ import { EMPTY_ROOT, HoverFeedbackAction, HoverMouseListener, IActionHandler, ICommand, SModelElement } from 'sprotty';
36
27
  import { FocusStateChangedAction } from '../../base/actions/focus-change-action';
37
28
  import { EnableDefaultToolsAction, EnableToolsAction } from '../../base/tool-manager/tool-actions';
38
29
  import { EdgeCreationTool } from '../tools/edge-creation-tool';
39
- import { GIssueMarker } from '../validation/issue-marker';
30
+ import { getSeverity, GIssueMarker } from '../validation/issue-marker';
40
31
  @injectable()
41
32
  export class GlspHoverMouseListener extends HoverMouseListener implements IActionHandler {
42
33
  protected enableHover = true;
@@ -117,16 +108,3 @@ export class GlspHoverMouseListener extends HoverMouseListener implements IActio
117
108
  return bounds;
118
109
  }
119
110
  }
120
-
121
- export function getSeverity(marker: SIssueMarker): SIssueSeverity {
122
- let currentSeverity: SIssueSeverity = 'info';
123
- for (const severity of marker.issues.map(s => s.severity)) {
124
- if (severity === 'error') {
125
- return severity;
126
- }
127
- if (severity === 'warning' && currentSeverity === 'info') {
128
- currentSeverity = severity;
129
- }
130
- }
131
- return currentSeverity;
132
- }
@@ -49,10 +49,6 @@ export class RankingMouseTool extends MouseTool implements IMouseTool {
49
49
  this.rankedMouseListeners = groupBy(this.mouseListeners, listener => getRank(listener));
50
50
  }
51
51
 
52
- contextMenu(model: SModelRoot, event: MouseEvent): void {
53
- event.preventDefault();
54
- }
55
-
56
52
  protected override handleEvent<K extends MouseListenerMethods>(methodName: K, model: SModelRoot, event: MouseEvent): void {
57
53
  this.focusOnMouseEvent(methodName, model);
58
54
  const element = this.getTargetElement(model, event);
@@ -13,7 +13,21 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { SelectMouseListener } from 'sprotty';
16
+ import { Action, SelectAction } from '@eclipse-glsp/protocol';
17
+ import {
18
+ BringToFrontAction,
19
+ findParentByFeature,
20
+ isCtrlOrCmd,
21
+ isSelectable,
22
+ SButton,
23
+ SelectMouseListener,
24
+ SModelElement,
25
+ SModelRoot,
26
+ SRoutableElement,
27
+ SRoutingHandle,
28
+ SwitchEditModeAction
29
+ } from 'sprotty';
30
+ import { toArray } from 'sprotty/lib/utils/iterable';
17
31
  import { DEFAULT_RANK, Ranked } from '../rank/model';
18
32
 
19
33
  /**
@@ -22,4 +36,70 @@ import { DEFAULT_RANK, Ranked } from '../rank/model';
22
36
  */
23
37
  export class RankedSelectMouseListener extends SelectMouseListener implements Ranked {
24
38
  rank: number = DEFAULT_RANK - 1; /* we want to be executed before all default mouse listeners */
39
+
40
+ override mouseDown(target: SModelElement, event: MouseEvent): Action[] {
41
+ const result: Action[] = [];
42
+ if (this.buttonHandlerRegistry !== undefined && target instanceof SButton && target.enabled) {
43
+ const buttonHandler = this.buttonHandlerRegistry.get(target.type);
44
+ if (buttonHandler !== undefined) {
45
+ return buttonHandler.buttonPressed(target);
46
+ }
47
+ }
48
+ const selectableTarget = findParentByFeature(target, isSelectable);
49
+ if (selectableTarget !== undefined || target instanceof SModelRoot) {
50
+ this.hasDragged = false;
51
+ let deselect: SModelElement[] = [];
52
+ // multi-selection?
53
+ if (!isCtrlOrCmd(event)) {
54
+ deselect = toArray(
55
+ target.root.index
56
+ .all()
57
+ .filter(
58
+ element =>
59
+ isSelectable(element) &&
60
+ element.selected &&
61
+ !(selectableTarget instanceof SRoutingHandle && element === (selectableTarget.parent as SModelElement))
62
+ )
63
+ );
64
+ }
65
+ if (selectableTarget !== undefined) {
66
+ if (!selectableTarget.selected) {
67
+ this.wasSelected = false;
68
+ result.push(
69
+ SelectAction.create({
70
+ selectedElementsIDs: [selectableTarget.id],
71
+ deselectedElementsIDs: deselect.map(e => e.id)
72
+ })
73
+ );
74
+ result.push(BringToFrontAction.create([selectableTarget.id]));
75
+ const routableDeselect = deselect.filter(e => e instanceof SRoutableElement).map(e => e.id);
76
+ if (selectableTarget instanceof SRoutableElement) {
77
+ result.push(
78
+ SwitchEditModeAction.create({
79
+ elementsToActivate: [selectableTarget.id],
80
+ elementsToDeactivate: routableDeselect
81
+ })
82
+ );
83
+ } else if (routableDeselect.length > 0) {
84
+ result.push(SwitchEditModeAction.create({ elementsToDeactivate: routableDeselect }));
85
+ }
86
+ } else if (isCtrlOrCmd(event)) {
87
+ this.wasSelected = false;
88
+ result.push(SelectAction.create({ deselectedElementsIDs: [selectableTarget.id] }));
89
+ if (selectableTarget instanceof SRoutableElement) {
90
+ result.push(SwitchEditModeAction.create({ elementsToDeactivate: [selectableTarget.id] }));
91
+ }
92
+ } else {
93
+ this.wasSelected = true;
94
+ }
95
+ } else {
96
+ result.push(SelectAction.create({ deselectedElementsIDs: deselect.map(e => e.id) }));
97
+ const routableDeselect = deselect.filter(e => e instanceof SRoutableElement).map(e => e.id);
98
+ if (routableDeselect.length > 0) {
99
+ result.push(SwitchEditModeAction.create({ elementsToDeactivate: routableDeselect }));
100
+ }
101
+ }
102
+ }
103
+ return result;
104
+ }
25
105
  }
@@ -13,13 +13,13 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { ModelSourceChangedAction } from '@eclipse-glsp/protocol';
16
+ import { SourceModelChangedAction } from '@eclipse-glsp/protocol';
17
17
  import { ContainerModule } from 'inversify';
18
18
  import { configureActionHandler } from 'sprotty';
19
- import { ModelSourceChangedActionHandler } from './model-source-changed-action-handler';
19
+ import { SourceModelChangedActionHandler } from './source-model-changed-action-handler';
20
20
 
21
- const modelSourceWatcherModule = new ContainerModule((bind, _unbind, isBound) => {
22
- configureActionHandler({ bind, isBound }, ModelSourceChangedAction.KIND, ModelSourceChangedActionHandler);
21
+ const sourceModelWatcherModule = new ContainerModule((bind, _unbind, isBound) => {
22
+ configureActionHandler({ bind, isBound }, SourceModelChangedAction.KIND, SourceModelChangedActionHandler);
23
23
  });
24
24
 
25
- export default modelSourceWatcherModule;
25
+ export default sourceModelWatcherModule;
@@ -13,43 +13,43 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { Action, ModelSourceChangedAction, ServerMessageAction, ServerStatusAction } from '@eclipse-glsp/protocol';
16
+ import { Action, ServerMessageAction, ServerStatusAction, SourceModelChangedAction } from '@eclipse-glsp/protocol';
17
17
  import { inject, injectable, optional } from 'inversify';
18
18
  import { IActionDispatcher, IActionHandler, ViewerOptions } from 'sprotty';
19
19
  import { TYPES } from '../../base/types';
20
20
 
21
21
  /**
22
- * An external handler of the model source change event.
22
+ * An external handler of the source model change event.
23
23
  *
24
24
  * This allows external applications to react specifically to this event, e.g. by bringing up the diagram,
25
25
  * check their dirty state, show a dialog, etc.
26
26
  */
27
27
  @injectable()
28
- export abstract class ExternalModelSourceChangedHandler {
28
+ export abstract class ExternalSourceModelChangedHandler {
29
29
  /**
30
- * Notifies about a change of the model source.
30
+ * Notifies about a change of the source model.
31
31
  * @returns actions to be dispatched after the notification.
32
32
  */
33
- abstract notifyModelSourceChange(modelSourceName: string, options: ViewerOptions): Promise<Action[]>;
33
+ abstract notifySourceModelChange(sourceModelName: string, options: ViewerOptions): Promise<Action[]>;
34
34
  }
35
35
 
36
36
  @injectable()
37
- export class ModelSourceChangedActionHandler implements IActionHandler {
37
+ export class SourceModelChangedActionHandler implements IActionHandler {
38
38
  @inject(TYPES.IActionDispatcher)
39
39
  protected dispatcher: IActionDispatcher;
40
40
 
41
41
  @inject(TYPES.ViewerOptions)
42
42
  protected options: ViewerOptions;
43
43
 
44
- @inject(ExternalModelSourceChangedHandler)
44
+ @inject(ExternalSourceModelChangedHandler)
45
45
  @optional()
46
- protected externalModelSourceChangedHandler?: ExternalModelSourceChangedHandler;
46
+ protected externalModelSourceChangedHandler?: ExternalSourceModelChangedHandler;
47
47
 
48
48
  handle(action: Action): void {
49
- if (ModelSourceChangedAction.is(action)) {
49
+ if (SourceModelChangedAction.is(action)) {
50
50
  if (this.externalModelSourceChangedHandler) {
51
51
  this.externalModelSourceChangedHandler
52
- .notifyModelSourceChange(action.modelSourceName, this.options)
52
+ .notifySourceModelChange(action.sourceModelName, this.options)
53
53
  .then(actions => this.dispatcher.dispatchAll(actions));
54
54
  return;
55
55
  }
@@ -57,8 +57,8 @@ export class ModelSourceChangedActionHandler implements IActionHandler {
57
57
  }
58
58
  }
59
59
 
60
- protected showSimpleNotification(action: ModelSourceChangedAction): void {
61
- const message = `The model source ${action.modelSourceName} has changed. You might want to consider reloading.`;
60
+ protected showSimpleNotification(action: SourceModelChangedAction): void {
61
+ const message = `The source model ${action.sourceModelName} has changed. You might want to consider reloading.`;
62
62
  const timeout = 0;
63
63
  const severity = 'WARNING';
64
64
  this.dispatcher.dispatchAll([
@@ -13,14 +13,23 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { Marker, MarkerKind } from '@eclipse-glsp/protocol';
17
- import { SDecoration, SIssue, SIssueMarker, SParentElement } from 'sprotty';
16
+ import { Bounds, Marker, MarkerKind } from '@eclipse-glsp/protocol';
17
+ import { isBoundsAware, Projectable, SDecoration, SIssue, SIssueMarker, SIssueSeverity, SParentElement } from 'sprotty';
18
18
 
19
- export class GIssueMarker extends SIssueMarker {
19
+ export class GIssueMarker extends SIssueMarker implements Projectable {
20
20
  constructor() {
21
21
  super();
22
22
  this.features = new Set<symbol>(SDecoration.DEFAULT_FEATURES);
23
23
  }
24
+ projectionCssClasses: string[];
25
+ projectedBounds?: Bounds;
26
+ override issues: SIssue[] = [];
27
+ override type = 'marker';
28
+
29
+ computeProjectionCssClasses(): void {
30
+ const severityCss = getSeverity(this);
31
+ this.projectionCssClasses = ['sprotty-issue', 'sprotty-' + severityCss];
32
+ }
24
33
  }
25
34
 
26
35
  /**
@@ -31,14 +40,15 @@ export class GIssueMarker extends SIssueMarker {
31
40
  * @returns the child `SIssueMarker` or a new `SIssueMarker` if no such child exists.
32
41
  */
33
42
  export function getOrCreateSIssueMarker(modelElement: SParentElement): SIssueMarker {
34
- let issueMarker: SIssueMarker | undefined;
43
+ let issueMarker: GIssueMarker | undefined;
35
44
 
36
45
  issueMarker = getSIssueMarker(modelElement);
37
46
 
38
47
  if (issueMarker === undefined) {
39
48
  issueMarker = new GIssueMarker();
40
- issueMarker.type = 'marker';
41
- issueMarker.issues = new Array<SIssue>();
49
+ if (isBoundsAware(modelElement)) {
50
+ issueMarker.projectedBounds = modelElement.parentToLocal(modelElement.bounds);
51
+ }
42
52
  modelElement.add(issueMarker);
43
53
  }
44
54
 
@@ -51,11 +61,11 @@ export function getOrCreateSIssueMarker(modelElement: SParentElement): SIssueMar
51
61
  * @param modelElement for which the `SIssueMarker` should be retrieved.
52
62
  * @returns the child `SIssueMarker` or `undefined` if no such child exists.
53
63
  */
54
- export function getSIssueMarker(modelElement: SParentElement): SIssueMarker | undefined {
55
- let issueMarker: SIssueMarker | undefined;
64
+ export function getSIssueMarker(modelElement: SParentElement): GIssueMarker | undefined {
65
+ let issueMarker: GIssueMarker | undefined;
56
66
 
57
67
  for (const child of modelElement.children) {
58
- if (child instanceof SIssueMarker) {
68
+ if (child instanceof GIssueMarker) {
59
69
  issueMarker = child;
60
70
  }
61
71
  }
@@ -69,8 +79,8 @@ export function getSIssueMarker(modelElement: SParentElement): SIssueMarker | un
69
79
  * @param marker `Marker` for that an `SIssue` should be created.
70
80
  * @returns the created `SIssue`.
71
81
  */
72
- export function createSIssue(marker: Marker): SIssue {
73
- const issue: SIssue = new SIssue();
82
+ export function createSIssue(marker: Marker, parent?: SParentElement): SIssue {
83
+ const issue = new SIssue();
74
84
  issue.message = marker.description;
75
85
 
76
86
  switch (marker.kind) {
@@ -87,6 +97,18 @@ export function createSIssue(marker: Marker): SIssue {
87
97
  break;
88
98
  }
89
99
  }
90
-
91
100
  return issue;
92
101
  }
102
+
103
+ export function getSeverity(marker: SIssueMarker): SIssueSeverity {
104
+ let currentSeverity: SIssueSeverity = 'info';
105
+ for (const severity of marker.issues.map(s => s.severity)) {
106
+ if (severity === 'error') {
107
+ return severity;
108
+ }
109
+ if (severity === 'warning' && currentSeverity === 'info') {
110
+ currentSeverity = severity;
111
+ }
112
+ }
113
+ return currentSeverity;
114
+ }
@@ -19,10 +19,9 @@ import { CommandExecutionContext, CommandReturn, IActionDispatcher, IActionHandl
19
19
  import { EditorContextService } from '../../base/editor-context-service';
20
20
  import { TYPES } from '../../base/types';
21
21
  import { removeCssClasses } from '../../utils/smodel-util';
22
- import { getSeverity } from '../hover/hover';
23
22
  import { IFeedbackActionDispatcher, IFeedbackEmitter } from '../tool-feedback/feedback-action-dispatcher';
24
23
  import { FeedbackCommand } from '../tool-feedback/model';
25
- import { createSIssue, getOrCreateSIssueMarker, getSIssueMarker } from './issue-marker';
24
+ import { createSIssue, getOrCreateSIssueMarker, getSeverity, getSIssueMarker, GIssueMarker } from './issue-marker';
26
25
 
27
26
  /**
28
27
  * Feedback emitter sending actions for visualizing model validation feedback and
@@ -151,6 +150,9 @@ export class ApplyMarkersCommand extends FeedbackCommand {
151
150
  const issueMarker = getOrCreateSIssueMarker(modelElement);
152
151
  const issue = createSIssue(marker);
153
152
  issueMarker.issues.push(issue);
153
+ if (issueMarker instanceof GIssueMarker) {
154
+ issueMarker.computeProjectionCssClasses();
155
+ }
154
156
  addMaxSeverityCSSClassToIssueParent(modelElement, issueMarker);
155
157
  }
156
158
  });
@@ -160,7 +162,6 @@ export class ApplyMarkersCommand extends FeedbackCommand {
160
162
 
161
163
  function addMaxSeverityCSSClassToIssueParent(modelElement: SParentElement, issueMarker: SIssueMarker): void {
162
164
  const maxSeverityCSSClass = getSeverity(issueMarker);
163
-
164
165
  if (!modelElement.cssClasses) {
165
166
  modelElement.cssClasses = [maxSeverityCSSClass];
166
167
  } else {
@@ -170,7 +171,8 @@ function addMaxSeverityCSSClassToIssueParent(modelElement: SParentElement, issue
170
171
  }
171
172
 
172
173
  function removeCSSClassFromIssueParent(modelElement: SParentElement, issueMarker: SIssueMarker): void {
173
- removeCssClasses(modelElement, [getSeverity(issueMarker)]);
174
+ const severity = getSeverity(issueMarker);
175
+ removeCssClasses(modelElement, [severity]);
174
176
  }
175
177
 
176
178
  /**
package/src/index.ts CHANGED
@@ -22,11 +22,11 @@ import glspEditLabelModule from './features/edit-label/di.config';
22
22
  import modelHintsModule from './features/hints/di.config';
23
23
  import glspHoverModule from './features/hover/di.config';
24
24
  import layoutModule from './features/layout/di.config';
25
- import modelSourceWatcherModule from './features/model-source-watcher/di.config';
26
25
  import glspMouseToolModule from './features/mouse-tool/di.config';
27
26
  import { navigationModule } from './features/navigation/di.config';
28
27
  import saveModule from './features/save/di.config';
29
28
  import glspSelectModule from './features/select/di.config';
29
+ import sourceModelWatcherModule from './features/source-model-watcher/di.config';
30
30
  import toolFeedbackModule from './features/tool-feedback/di.config';
31
31
  import paletteModule from './features/tool-palette/di.config';
32
32
  import { enableDefaultToolsOnFocusLossModule, toolsModule } from './features/tools/di.config';
@@ -66,7 +66,6 @@ export * from './features/hints/model';
66
66
  export * from './features/hints/type-hints';
67
67
  export * from './features/hover/hover';
68
68
  export * from './features/layout/layout-elements-action';
69
- export * from './features/model-source-watcher/model-source-changed-action-handler';
70
69
  export * from './features/mouse-tool/mouse-tool';
71
70
  export * from './features/navigation/navigation-action-handler';
72
71
  export * from './features/navigation/navigation-target-resolver';
@@ -74,6 +73,7 @@ export * from './features/rank/model';
74
73
  export * from './features/reconnect/model';
75
74
  export * from './features/save/model';
76
75
  export * from './features/save/save-keylistener';
76
+ export * from './features/source-model-watcher/source-model-changed-action-handler';
77
77
  export * from './features/tool-feedback/change-bounds-tool-feedback';
78
78
  export * from './features/tool-feedback/creation-tool-feedback';
79
79
  export * from './features/tool-feedback/css-feedback';
@@ -121,6 +121,6 @@ export {
121
121
  navigationModule,
122
122
  markerNavigatorModule,
123
123
  glspDecorationModule,
124
- modelSourceWatcherModule,
124
+ sourceModelWatcherModule as modelSourceWatcherModule,
125
125
  glspViewportModule
126
126
  };
@@ -0,0 +1,166 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2017-2018 TypeFox and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ /** @jsx html */
18
+ import { Bounds } from '@eclipse-glsp/protocol';
19
+ import { injectable } from 'inversify';
20
+ import { h, VNode, VNodeStyle } from 'snabbdom';
21
+ import {
22
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
23
+ html,
24
+ IViewArgs,
25
+ ProjectedViewportView,
26
+ ProjectionParams,
27
+ RenderingContext,
28
+ setClass,
29
+ ViewportRootElement,
30
+ ViewProjection
31
+ } from 'sprotty';
32
+
33
+ /**
34
+ * Special viewport root view that renders horizontal and vertical projection bars for quick navigation.
35
+ */
36
+ @injectable()
37
+ export class GLSPProjectionView extends ProjectedViewportView {
38
+ override render(model: Readonly<ViewportRootElement>, context: RenderingContext, args?: IViewArgs): VNode {
39
+ return (
40
+ <div class-sprotty-graph={true} style={{ width: '100%' }}>
41
+ {this.renderSvg(model, context, args)}
42
+ {this.renderProjections(model, context, args)}
43
+ </div>
44
+ );
45
+ }
46
+
47
+ protected override renderSvg(model: Readonly<ViewportRootElement>, context: RenderingContext, args?: IViewArgs): VNode {
48
+ const transform = `scale(${model.zoom}) translate(${-model.scroll.x},${-model.scroll.y})`;
49
+ const ns = 'http://www.w3.org/2000/svg';
50
+ const svg = h('svg', { ns, style: { height: '100%' } }, h('g', { ns, attrs: { transform } }, context.renderChildren(model)));
51
+ return svg;
52
+ }
53
+
54
+ protected override renderProjectionBar(
55
+ projections: ViewProjection[],
56
+ model: Readonly<ViewportRootElement>,
57
+ modelBounds: Bounds,
58
+ orientation: 'horizontal' | 'vertical'
59
+ ): VNode {
60
+ const params: ProjectionParams = { modelBounds, orientation } as ProjectionParams;
61
+ // NOTE: Here we assume that the projection bars have the same size as the diagram canvas,
62
+ // i.e. they are drawn as overlay above the canvas.
63
+ params.factor =
64
+ orientation === 'horizontal' ? model.canvasBounds.width / modelBounds.width : model.canvasBounds.height / modelBounds.height;
65
+ params.zoomedFactor = params.factor / model.zoom;
66
+ return (
67
+ <div
68
+ class-sprotty-projection-bar={true}
69
+ class-horizontal={orientation === 'horizontal'}
70
+ class-vertical={orientation === 'vertical'}
71
+ class-bordered-projection-bar={true}
72
+ >
73
+ {this.renderViewport(model, params)}
74
+ {projections.map(p => this.renderProjection(p, model, params))}
75
+ </div>
76
+ );
77
+ }
78
+
79
+ protected override renderViewport(model: Readonly<ViewportRootElement>, params: ProjectionParams): VNode {
80
+ let canvasSize;
81
+ let viewportPos: number;
82
+ if (params.orientation === 'horizontal') {
83
+ canvasSize = model.canvasBounds.width;
84
+ viewportPos = (model.scroll.x - params.modelBounds.x) * params.factor;
85
+ } else {
86
+ canvasSize = model.canvasBounds.height;
87
+ viewportPos = (model.scroll.y - params.modelBounds.y) * params.factor;
88
+ }
89
+ let viewportSize = canvasSize * params.zoomedFactor;
90
+ if (viewportPos < 0) {
91
+ viewportSize += viewportPos;
92
+ viewportPos = 0;
93
+ } else if (viewportPos > canvasSize) {
94
+ viewportPos = canvasSize;
95
+ }
96
+ if (viewportSize < 0) {
97
+ viewportSize = 0;
98
+ } else if (viewportPos + viewportSize > canvasSize) {
99
+ viewportSize = canvasSize - viewportPos;
100
+ }
101
+ if (Math.abs(viewportSize - canvasSize) < 1) {
102
+ viewportSize = 0;
103
+ }
104
+ const style: VNodeStyle =
105
+ params.orientation === 'horizontal'
106
+ ? {
107
+ left: `${viewportPos}px`,
108
+ width: `${viewportSize}px`,
109
+ border: 'none'
110
+ }
111
+ : {
112
+ top: `${viewportPos}px`,
113
+ height: `${viewportSize}px`,
114
+ border: 'none'
115
+ };
116
+ return <div class-sprotty-viewport={viewportSize !== 0} class-projection-scroll-bar={true} style={style} />;
117
+ }
118
+
119
+ protected override renderProjection(projection: ViewProjection, model: Readonly<ViewportRootElement>, params: ProjectionParams): VNode {
120
+ let canvasSize;
121
+ let projPos;
122
+ let projSize: number;
123
+ if (params.orientation === 'horizontal') {
124
+ canvasSize = model.canvasBounds.width;
125
+ projPos = (projection.projectedBounds.x - params.modelBounds.x) * params.factor;
126
+ projSize = projection.projectedBounds.width * params.factor;
127
+ } else {
128
+ canvasSize = model.canvasBounds.height;
129
+ projPos = (projection.projectedBounds.y - params.modelBounds.y) * params.factor;
130
+ projSize = projection.projectedBounds.height * params.factor;
131
+ }
132
+ if (projPos < 0) {
133
+ projSize += projPos;
134
+ projPos = 0;
135
+ } else if (projPos > canvasSize) {
136
+ projPos = canvasSize;
137
+ }
138
+ if (projSize < 0) {
139
+ projSize = 0;
140
+ } else if (projPos + projSize > canvasSize) {
141
+ projSize = canvasSize - projPos;
142
+ }
143
+ const style: VNodeStyle =
144
+ params.orientation === 'horizontal'
145
+ ? {
146
+ left: `${projPos}px`,
147
+ width: `${projSize}px`,
148
+ height: '60%'
149
+ }
150
+ : {
151
+ top: `${projPos}px`,
152
+ height: `${projSize}px`,
153
+ width: '60%'
154
+ };
155
+ const result = (
156
+ <div
157
+ id={`${params.orientation}-projection:${projection.elementId}`}
158
+ class-sprotty-projection={true}
159
+ class-glsp-projection={true}
160
+ style={style}
161
+ />
162
+ );
163
+ projection.cssClasses.forEach(cl => setClass(result, cl, true));
164
+ return result;
165
+ }
166
+ }
@@ -16,6 +16,8 @@
16
16
  export * from './base-view-module';
17
17
  export * from './compartments';
18
18
  export * from './glsp-edge-view';
19
+ export * from './glsp-projection-view';
19
20
  export * from './issue-marker-view';
20
21
  export * from './rounded-corner';
21
22
  export * from './rounded-corner-view';
23
+
@@ -1,4 +0,0 @@
1
- import { ContainerModule } from 'inversify';
2
- declare const modelSourceWatcherModule: ContainerModule;
3
- export default modelSourceWatcherModule;
4
- //# sourceMappingURL=di.config.d.ts.map