Skip to content

Commit

Permalink
Better developer expereience for missing views (#395)
Browse files Browse the repository at this point in the history
Signed-off-by: Jonah Iden <jonah.iden@typefox.io>
  • Loading branch information
jonah-iden committed Nov 6, 2023
1 parent 6d43db2 commit 5c4476b
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 30 deletions.
9 changes: 0 additions & 9 deletions examples/circlegraph/css/diagram.css
Expand Up @@ -38,13 +38,4 @@
.sprotty-node.selected {
stroke: #dd8;
stroke-width: 6;
}

.sprotty-missing {
stroke-width: 1;
stroke: #f00;
fill: #f00;
font-family: SansSerif;
font-size: 14pt;
text-anchor: middle;
}
8 changes: 0 additions & 8 deletions examples/classdiagram/css/diagram.css
Expand Up @@ -123,14 +123,6 @@
stroke-width: 1;
}

.sprotty-missing {
stroke-width: 1;
stroke: #f00;
fill: #f00;
font-size: 14pt;
text-anchor: middle;
}

.sprotty-popup-title {
font-weight: bold;
margin-bottom: 10px;
Expand Down
8 changes: 0 additions & 8 deletions examples/multicore/css/diagram.css
Expand Up @@ -62,14 +62,6 @@
text-align: start;
}

.sprotty-missing {
stroke-width: 1;
stroke: #f00;
fill: #f00;
font-size: 14pt;
text-anchor: middle;
}

.sprotty-popup-title {
font-weight: bold;
margin-bottom: 10px;
Expand Down
8 changes: 8 additions & 0 deletions packages/sprotty/css/sprotty.css
Expand Up @@ -93,3 +93,11 @@
.animation-spin {
animation: spin 1.5s linear infinite;
}

.sprotty-missing {
stroke-width: 1;
stroke: #f00;
fill: #f00;
font-size: 14pt;
text-anchor: start;
}
4 changes: 2 additions & 2 deletions packages/sprotty/src/base/views/view.spec.ts
Expand Up @@ -45,7 +45,7 @@ describe('base views', () => {

it('missing view', () => {
const vnode = missingView.render(emptyRoot, context);
expect(toHTML(vnode)).to.be.equal('<text class="sprotty-missing" x="0" y="0">?EMPTY?</text>');
expect(toHTML(vnode)).to.be.equal('<text class="sprotty-missing" x="0" y="0">missing &quot;NONE&quot; view</text>');
const model = new SNodeImpl();
model.bounds = {
x: 42,
Expand All @@ -56,7 +56,7 @@ describe('base views', () => {
model.id = 'foo';
model.type = 'type';
const vnode1 = missingView.render(model, context);
expect(toHTML(vnode1)).to.be.equal('<text class="sprotty-missing" x="42" y="41">?foo?</text>');
expect(toHTML(vnode1)).to.be.equal('<text class="sprotty-missing" x="42" y="41">missing &quot;type&quot; view</text>');
});
});

Expand Down
23 changes: 20 additions & 3 deletions packages/sprotty/src/base/views/view.tsx
Expand Up @@ -17,7 +17,7 @@
/** @jsx svg */
import { svg } from '../../lib/jsx';

import { injectable, multiInject, optional, interfaces } from 'inversify';
import { injectable, multiInject, optional, interfaces, inject } from 'inversify';
import { VNode } from 'snabbdom';
import { TYPES } from '../types';
import { InstanceRegistry } from '../../utils/registry';
Expand All @@ -26,6 +26,7 @@ import { SModelElementImpl, SModelRootImpl, SParentElementImpl } from '../model/
import { EMPTY_ROOT, CustomFeatures } from '../model/smodel-factory';
import { registerModelElement } from '../model/smodel-utils';
import { Point } from 'sprotty-protocol';
import { ILogger } from '../../utils/logging';

/**
* Arguments for `IView` rendering.
Expand Down Expand Up @@ -94,6 +95,9 @@ export type ViewRegistrationFactory = () => ViewRegistration;
*/
@injectable()
export class ViewRegistry extends InstanceRegistry<IView> {

@inject(TYPES.ILogger) protected logger: ILogger;

constructor(@multiInject(TYPES.ViewRegistration) @optional() registrations: ViewRegistration[]) {
super();
this.registerDefaults();
Expand All @@ -107,6 +111,7 @@ export class ViewRegistry extends InstanceRegistry<IView> {
}

override missing(key: string): IView {
this.logger.warn(this, `no registered view for type '${key}', please configure a view in the ContainerModule`);
return new MissingView();
}
}
Expand Down Expand Up @@ -155,8 +160,20 @@ export class EmptyView implements IView {
*/
@injectable()
export class MissingView implements IView {
private static positionMap = new Map<string, Point>();

render(model: Readonly<SModelElementImpl>, context: RenderingContext): VNode {
const position: Point = (model as any).position || Point.ORIGIN;
return <text class-sprotty-missing={true} x={position.x} y={position.y}>?{model.id}?</text>;
const position: Point = (model as any).position || this.getPostion(model.type);
return <text class-sprotty-missing={true} x={position.x} y={position.y}>missing "{model.type}" view</text>;
}

getPostion(type: string) {
let position = MissingView.positionMap.get(type);
if (!position) {
position = Point.ORIGIN;
MissingView.positionMap.forEach(value => position = value.y >= position!.y ? {x: 0, y: value.y + 20} : position);
MissingView.positionMap.set(type, position);
}
return position;
}
}

0 comments on commit 5c4476b

Please sign in to comment.