Skip to content

Commit

Permalink
Enhance Grid functionality and customizability (#359)
Browse files Browse the repository at this point in the history
* Enhance Grid functionality and customizability

- Ensure grid is applied on normal graph view without projections
- Allow grid color to be specified through CSS
- Add more properties to the graph for re-use

* Properly escape grid color values

Color definitions with a # need to be escaped to be properly rendered
when used in a background image url
  • Loading branch information
martin-fleck-at authored Jun 15, 2024
1 parent dd2a425 commit d49f704
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 15 deletions.
7 changes: 6 additions & 1 deletion packages/client/css/grid.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

:root {
--grid-color: rgba(0, 0, 0, 0.1);
}

/** Control visibility of background image through CSS class on parent */
.grid-background .sprotty-graph {
.grid-background .sprotty-graph,
.grid-background.sprotty-graph {
background-image: var(--grid-background-image);
}
25 changes: 25 additions & 0 deletions packages/client/src/features/grid/grid-style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/********************************************************************************
* Copyright (c) 2024 Axon Ivy AG 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
********************************************************************************/

export namespace GridProperty {
export const GRID_BACKGROUND_X = '--grid-background-x';
export const GRID_BACKGROUND_Y = '--grid-background-y';
export const GRID_BACKGROUND_WIDTH = '--grid-background-width';
export const GRID_BACKGROUND_HEIGHT = '--grid-background-height';
export const GRID_BACKGROUND_ZOOM = '--grid-background-zoom';
export const GRID_BACKGROUND_IMAGE = '--grid-background-image';
export const GRID_COLOR = '--grid-color';
}
1 change: 1 addition & 0 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export * from './features/grid/grid-manager';
export * from './features/grid/grid-model';
export * from './features/grid/grid-module';
export * from './features/grid/grid-snapper';
export * from './features/grid/grid-style';
export * from './features/helper-lines/helper-line-feedback';
export * from './features/helper-lines/helper-line-manager';
export * from './features/helper-lines/helper-line-manager-default';
Expand Down
21 changes: 14 additions & 7 deletions packages/client/src/views/ggraph-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Bounds, Dimension, Point, RenderingContext, SGraphImpl, SGraphView, Wri
import { inject, injectable, optional } from 'inversify';
import { VNode } from 'snabbdom';
import { GridManager, GridStyle } from '../features/grid/grid-manager';
import { GridProperty } from '../features/grid/grid-style';

@injectable()
export class GGraphView extends SGraphView {
Expand All @@ -30,16 +31,21 @@ export class GGraphView extends SGraphView {
return graph;
}

protected getGridStyle(model: Readonly<SGraphImpl>, context: RenderingContext): GridStyle {
protected getGridStyle(viewport: Readonly<SGraphImpl>, context: RenderingContext): GridStyle {
if (context.targetKind === 'hidden' || !this.gridManager?.isGridVisible) {
return {};
}
const bounds = this.getBackgroundBounds(model, context, this.gridManager);
const bounds = this.getBackgroundBounds(viewport, context, this.gridManager);
return {
[GridProperty.GRID_BACKGROUND_X]: bounds.x + 'px',
[GridProperty.GRID_BACKGROUND_Y]: bounds.y + 'px',
[GridProperty.GRID_BACKGROUND_WIDTH]: bounds.width + 'px',
[GridProperty.GRID_BACKGROUND_HEIGHT]: bounds.height + 'px',
[GridProperty.GRID_BACKGROUND_ZOOM]: viewport.zoom + '',
[GridProperty.GRID_BACKGROUND_IMAGE]: this.getBackgroundImage(viewport, context, this.gridManager),
backgroundPosition: `${bounds.x}px ${bounds.y}px`,
backgroundSize: `${bounds.width}px ${bounds.height}px`,
// we do not set the background image directly in the style object, because we want to toggle it on and off via CSS
'--grid-background-image': this.getBackgroundImage(model, context, this.gridManager)
backgroundSize: `${bounds.width}px ${bounds.height}px`
// we do not set the background-image directly in the style object, because we want to toggle it on and off via CSS
};
}

Expand All @@ -49,8 +55,9 @@ export class GGraphView extends SGraphView {
return { ...position, ...size };
}

protected getBackgroundImage(model: Readonly<SGraphImpl>, context: RenderingContext, gridManager: GridManager): string {
protected getBackgroundImage(viewport: Readonly<SGraphImpl>, context: RenderingContext, gridManager: GridManager): string {
const color = getComputedStyle(document.documentElement).getPropertyValue(GridProperty.GRID_COLOR).trim().replace(/#/g, '%23');
// eslint-disable-next-line max-len
return `url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${gridManager.grid.x} ${gridManager.grid.y}"><rect width="${gridManager.grid.x}" height="${gridManager.grid.y}" x="0" y="0" fill="none" stroke="black" stroke-width="1" stroke-opacity="0.10" /></svg>')`;
return `url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${gridManager.grid.x} ${gridManager.grid.y}"><rect width="${gridManager.grid.x}" height="${gridManager.grid.y}" x="0" y="0" fill="none" stroke="${color}" stroke-width="1" /></svg>')`;
}
}
21 changes: 14 additions & 7 deletions packages/client/src/views/glsp-projection-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
import { inject, injectable, optional } from 'inversify';
import { VNode, VNodeStyle, h } from 'snabbdom';
import { GridManager, GridStyle } from '../features/grid/grid-manager';
import { GridProperty } from '../features/grid/grid-style';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const JSX = { createElement: html };
Expand Down Expand Up @@ -71,16 +72,21 @@ export class GLSPProjectionView extends ProjectedViewportView {
return svg;
}

protected getGridStyle(model: Readonly<SGraphImpl>, context: RenderingContext): GridStyle {
protected getGridStyle(viewport: Readonly<SGraphImpl>, context: RenderingContext): GridStyle {
if (context.targetKind === 'hidden' || !this.gridManager?.isGridVisible) {
return {};
}
const bounds = this.getBackgroundBounds(model, context, this.gridManager);
const bounds = this.getBackgroundBounds(viewport, context, this.gridManager);
return {
[GridProperty.GRID_BACKGROUND_X]: bounds.x + 'px',
[GridProperty.GRID_BACKGROUND_Y]: bounds.y + 'px',
[GridProperty.GRID_BACKGROUND_WIDTH]: bounds.width + 'px',
[GridProperty.GRID_BACKGROUND_HEIGHT]: bounds.height + 'px',
[GridProperty.GRID_BACKGROUND_ZOOM]: viewport.zoom + '',
[GridProperty.GRID_BACKGROUND_IMAGE]: this.getBackgroundImage(viewport, context, this.gridManager),
backgroundPosition: `${bounds.x}px ${bounds.y}px`,
backgroundSize: `${bounds.width}px ${bounds.height}px`,
// we do not set the background image directly in the style object, because we want to toggle it on and off via CSS
'--grid-background-image': this.getBackgroundImage(model, context, this.gridManager)
backgroundSize: `${bounds.width}px ${bounds.height}px`
// we do not set the background-image directly in the style object, because we want to toggle it on and off via CSS
};
}

Expand All @@ -90,9 +96,10 @@ export class GLSPProjectionView extends ProjectedViewportView {
return { ...position, ...size };
}

protected getBackgroundImage(model: Readonly<SGraphImpl>, context: RenderingContext, gridManager: GridManager): string {
protected getBackgroundImage(viewport: Readonly<SGraphImpl>, context: RenderingContext, gridManager: GridManager): string {
const color = getComputedStyle(document.documentElement).getPropertyValue(GridProperty.GRID_COLOR).trim().replace(/#/g, '%23');
// eslint-disable-next-line max-len
return `url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${gridManager.grid.x} ${gridManager.grid.y}"><rect width="${gridManager.grid.x}" height="${gridManager.grid.y}" x="0" y="0" fill="none" stroke="black" stroke-width="1" stroke-opacity="0.10" /></svg>')`;
return `url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${gridManager.grid.x} ${gridManager.grid.y}"><rect width="${gridManager.grid.x}" height="${gridManager.grid.y}" x="0" y="0" fill="none" stroke="${color}" stroke-width="1" /></svg>')`;
}

protected override renderProjectionBar(
Expand Down

0 comments on commit d49f704

Please sign in to comment.