Skip to content

Commit f76a2cb

Browse files
authored
Example custom views (#499)
* Add example for custom views * Clean up
1 parent 07776a0 commit f76a2cb

File tree

10 files changed

+1745
-0
lines changed

10 files changed

+1745
-0
lines changed

examples/browser-app.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import runFlowchart from "./flowchart/src/standalone";
2626
import runJsxample from "./jsxample/src/standalone";
2727
import runStylingShowcase from "./styling-showcase/src/standalone";
2828
import runMicroLayoutShowcase from "./micro-layout-showcase/src/standalone";
29+
import runCustomViewsShowcase from "./custom-views-showcase/src/standalone";
2930

3031
const appDiv = document.getElementById('sprotty-app');
3132
if (appDiv) {
@@ -50,6 +51,8 @@ if (appDiv) {
5051
runStylingShowcase();
5152
else if (appMode === 'micro-layout-showcase')
5253
runMicroLayoutShowcase();
54+
else if (appMode === 'custom-views-showcase')
55+
runCustomViewsShowcase();
5356
else
5457
throw new Error('Dunno what to do :-(');
5558
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Custom Views Showcase
2+
3+
This example demonstrates various patterns for creating custom views in Sprotty. It serves as a companion to the [Custom Views Recipe](../../hugo/content/docs/recipes/custom-views.md) in the documentation.
4+
5+
## What This Example Demonstrates
6+
7+
### 🔵 Basic Custom Views
8+
9+
- **Circle, Triangle, Diamond shapes** - Simple geometric views created from scratch
10+
- **Dynamic styling** - Color and shape properties controlled by model data
11+
- **TSX syntax** - Clean declarative SVG rendering with TypeScript expressions
12+
13+
### ⭐ Enhanced Views
14+
15+
- **Extended base views** - Building upon `RectangularNodeView` with custom decorations
16+
- **Status indicators** - Visual status badges (normal, warning, error, success)
17+
- **Conditional decorations** - Borders and styling based on model properties
18+
19+
### 🏗️ Compositional Views
20+
21+
- **Complex node structure** - Headers, bodies, and footers as separate components
22+
- **Reusable patterns** - Breaking down complex views into manageable methods
23+
- **Icon and text integration** - Combining symbols, titles, and subtitles
24+
25+
### 🔄 Stateful Views
26+
27+
- **Conditional rendering** - Different visual representations based on node state
28+
- **Loading states** - Progress bars and dynamic content updates
29+
- **Error handling** - Visual feedback for different states (idle, loading, success, error)
30+
31+
### ↗️ Custom Edge Views
32+
33+
- **Line styles** - Solid, dashed, and dotted edge patterns
34+
- **Visual properties** - Custom colors, thickness, and stroke patterns
35+
- **Animations** - Animated edges with CSS keyframes
36+
- **Arrow heads** - Custom edge termination rendering
37+
38+
### 🏷️ Custom Label Views
39+
40+
- **Enhanced text rendering** - Labels with backgrounds and borders
41+
- **Typography control** - Custom fonts, sizes, and styling
42+
- **Visual integration** - Labels that complement their parent elements
43+
44+
## Key Learning Objectives
45+
46+
After exploring this example, you should understand:
47+
48+
1. **View Creation Patterns** - How to implement `IView` interface effectively
49+
2. **TSX Best Practices** - Proper use of Sprotty's JSX syntax and class system
50+
3. **View Registry Configuration** - How to register custom views with dependency injection
51+
4. **Rendering Context Usage** - Leveraging `RenderingContext` for child rendering and services
52+
5. **Performance Considerations** - Visibility checks and efficient rendering techniques
53+
6. **View Composition** - Breaking complex views into manageable, reusable components
54+
55+
## Running the Example
56+
57+
1. **Build the example:**
58+
59+
```bash
60+
npm run build
61+
```
62+
63+
2. **Start the development server:**
64+
65+
```bash
66+
npm run serve
67+
```
68+
69+
3. **Open in browser:**
70+
Navigate to `http://localhost:8080`
71+
72+
## Interactive Features
73+
74+
- **Selection** - Click on nodes to see selection highlighting
75+
- **Hover Effects** - Mouse over elements for visual feedback
76+
- **Live Updates** - Watch the loading node progress animate automatically
77+
- **State Changes** - Observe different visual states across stateful nodes
78+
79+
## Code Structure
80+
81+
```
82+
src/
83+
├── model.ts # Custom model classes with properties
84+
├── views.tsx # All custom view implementations
85+
├── di.config.ts # Dependency injection configuration
86+
└── standalone.ts # Application setup and sample data
87+
88+
css/
89+
└── styles.css # Comprehensive styling for all views
90+
91+
index.html # Demo page with documentation
92+
```
93+
94+
## View Implementation Highlights
95+
96+
### Basic Shape View Pattern
97+
98+
```typescript
99+
@injectable()
100+
export class BasicShapeView implements IView {
101+
render(node: Readonly<BasicShapeNode>, context: RenderingContext): VNode | undefined {
102+
// Visibility check
103+
if (!this.isVisible(node, context)) return undefined;
104+
105+
// Dynamic shape rendering based on model properties
106+
switch (node.shape) {
107+
case 'circle': return this.renderCircle(node);
108+
case 'triangle': return this.renderTriangle(node);
109+
// ...
110+
}
111+
}
112+
}
113+
```
114+
115+
### Enhanced View Pattern
116+
117+
```typescript
118+
@injectable()
119+
export class EnhancedNodeView extends RectangularNodeView {
120+
override render(node: Readonly<EnhancedNode>, context: RenderingContext): VNode | undefined {
121+
// Base rendering + custom decorations
122+
return <g>
123+
<rect /* base rectangle */ />
124+
{this.renderStatusIndicator(node)}
125+
{node.showBorder && this.renderBorder(node)}
126+
{context.renderChildren(node)}
127+
</g>;
128+
}
129+
}
130+
```
131+
132+
### Compositional View Pattern
133+
134+
```typescript
135+
@injectable()
136+
export class ComplexNodeView implements IView {
137+
render(node: Readonly<ComplexNode>, context: RenderingContext): VNode | undefined {
138+
return <g>
139+
{node.showHeader && this.renderHeader(node)}
140+
{this.renderBody(node, context)}
141+
{node.showFooter && this.renderFooter(node)}
142+
</g>;
143+
}
144+
145+
protected renderHeader(node: ComplexNode): VNode { /* ... */ }
146+
protected renderBody(node: ComplexNode, context: RenderingContext): VNode { /* ... */ }
147+
protected renderFooter(node: ComplexNode): VNode { /* ... */ }
148+
}
149+
```
150+
151+
## Next Steps
152+
153+
After exploring this example:
154+
155+
1. **Experiment** with the view implementations - modify colors, shapes, and behaviors
156+
2. **Create your own** custom view types following these patterns
157+
3. **Explore related recipes** - [Styling](../styling.md), [Micro-layout](../micro-layout.md)
158+
4. **Build complex diagrams** using these view patterns as foundations
159+
160+
## Related Documentation
161+
162+
- [Custom Views Recipe](../../hugo/content/docs/recipes/custom-views.md) - Complete guide to custom view creation
163+
- [Styling Recipe](../../hugo/content/docs/recipes/styling.md) - Advanced CSS techniques
164+
- [Micro-layout Recipe](../../hugo/content/docs/recipes/micro-layout.md) - Child element organization
165+
- [TSX Syntax Guide](../../hugo/content/docs/concepts/tsx-syntax.md) - Deep dive into Sprotty's JSX usage

0 commit comments

Comments
 (0)