11/********************************************************************************
2- * Copyright (c) 2019-2023 EclipseSource and others.
2+ * Copyright (c) 2019-2025 EclipseSource and others.
33 *
44 * This program and the accompanying materials are made available under the
55 * terms of the Eclipse Public License v. 2.0 which is available at
1313 *
1414 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515 ********************************************************************************/
16- import { Decoration , DecorationPlacer , GChildElement , GModelElement , GRoutableElement , Point , isSizeable } from '@eclipse-glsp/sprotty' ;
17- import { injectable } from 'inversify' ;
16+ import {
17+ Action ,
18+ DOMHelper ,
19+ Decoration ,
20+ DecorationPlacer ,
21+ GChildElement ,
22+ GModelElement ,
23+ GRoutableElement ,
24+ ISvgExportPostProcessor ,
25+ LazyInjector ,
26+ Point ,
27+ TYPES ,
28+ isDecoration ,
29+ isSizeable
30+ } from '@eclipse-glsp/sprotty' ;
31+ import { inject , injectable } from 'inversify' ;
32+ import { EditorContextService } from '../../base/editor-context-service' ;
33+ import { filter } from '../../utils/gmodel-util' ;
1834
1935@injectable ( )
20- export class GlspDecorationPlacer extends DecorationPlacer {
36+ export class GlspDecorationPlacer extends DecorationPlacer implements ISvgExportPostProcessor {
2137 protected static readonly DECORATION_OFFSET : Point = { x : 12 , y : 10 } ;
38+ @inject ( TYPES . DOMHelper )
39+ protected domHelper : DOMHelper ;
40+
41+ @inject ( LazyInjector )
42+ protected lazyInjector : LazyInjector ;
43+
44+ get editorContextService ( ) : EditorContextService {
45+ return this . lazyInjector . get ( EditorContextService ) ;
46+ }
2247
2348 protected override getPosition ( element : GModelElement & Decoration ) : Point {
2449 if ( element instanceof GChildElement && element . parent instanceof GRoutableElement ) {
@@ -32,4 +57,24 @@ export class GlspDecorationPlacer extends DecorationPlacer {
3257 }
3358 return Point . ORIGIN ;
3459 }
60+ // HiddenVNodePostprocessor implementation
61+ override postUpdate ( cause ?: Action ) : void ;
62+ // ISvgExportPostProcessor implementation
63+ override postUpdate ( element : SVGSVGElement , cause ?: Action ) : void ;
64+ override postUpdate ( elementOrCause ?: SVGSVGElement | Action , _cause ?: Action ) : void {
65+ // Called as HiddenVNodePostprocessor => no-op
66+ if ( ! elementOrCause || Action . is ( elementOrCause ) ) {
67+ return ;
68+ }
69+
70+ // Called as ISvgExportPostProcessor
71+ // Adjust the position of all decorations in the exported SVG
72+ const svg = elementOrCause ;
73+ const translate = `translate(-${ GlspDecorationPlacer . DECORATION_OFFSET . x } px, -${ GlspDecorationPlacer . DECORATION_OFFSET . y } px)` ;
74+ filter ( this . editorContextService . modelRoot . index , isDecoration ) . forEach ( decoration => {
75+ const domId = this . domHelper . createUniqueDOMElementId ( decoration ) ;
76+ const element = svg . querySelector < SVGElement > ( `#${ domId } ` ) ;
77+ element ! . style . transform = translate ;
78+ } ) ;
79+ }
3580}
0 commit comments