Skip to Content
StudioExtensionsEntwicklungTutorial: Custom Editor

Tutorial: Custom Editor

In diesem Tutorial erstellen Sie einen eigenen Editor-Dokumenttyp mit Model und Renderer — die Grundlage für jeden spezialisierten Editor im Studio.

Was Sie lernen

  • EditorDocumentModel implementieren (Datenschicht)
  • React-Renderer erstellen (UI-Schicht)
  • Dokumenttyp registrieren
  • Undo/Redo implementieren
  • Dokument öffnen und speichern

Architektur

Jeder Editor-Dokumenttyp besteht aus drei Teilen:

Projektstruktur

    • index.ts
    • MeinEditorModel.ts
    • MeinEditorRenderer.tsx
    • package.json

Schritt 1: Model erstellen

Das Model erbt von EditorDocumentModel und verwaltet die Daten:

// MeinEditorModel.ts import { EditorDocumentModel } from '@5minds/processcube_studio_sdk'; export class MeinEditorModel extends EditorDocumentModel { private text: string = ''; // Lifecycle: Wird aufgerufen, wenn das Model registriert wird onEditorDocumentModelDidRegister(): void { const initialData = this.getInitialData(); if (initialData) { this.text = initialData; } this.updateOriginalAndCurrentData(this.text, this.text); } // Getter für den aktuellen Text getValue(): string { return this.text; } // Setter — aktualisiert den State und markiert als "geändert" setValue(newText: string): void { this.text = newText; this.updateCurrentData(this.text); this.emit('change', this.text); } // Lifecycle: Vor dem Speichern onEditorDocumentWillSave(): void { // Hier können Daten vor dem Speichern transformiert werden } // Lifecycle: Nach dem Speichern onEditorDocumentDidSave(): void { // Original-Daten aktualisieren (kein "unsaved"-Indikator mehr) this.updateOriginalAndCurrentData(this.text, this.text); } }

Wichtige Model-Methoden:

  • updateCurrentData(data) — Setzt die aktuellen Daten (zeigt unsaved-Indikator)
  • updateOriginalAndCurrentData(original, current) — Setzt beide (entfernt unsaved-Indikator)
  • emit(event, data) — Benachrichtigt den Renderer über Änderungen
  • getInitialData() — Gibt die beim Erstellen übergebenen Daten zurück

Schritt 2: Renderer erstellen

Der Renderer ist eine React-Komponente, die das Model anzeigt und bearbeitbar macht:

// MeinEditorRenderer.tsx import React, { useState, useEffect } from 'react'; import { EditorDocumentRendererProps } from '@5minds/processcube_studio_sdk'; import { MeinEditorModel } from './MeinEditorModel'; export function MeinEditorRenderer(props: EditorDocumentRendererProps): JSX.Element { const model = props.editorDocumentModel as MeinEditorModel; const [text, setText] = useState(model.getValue()); useEffect(() => { // Auf Änderungen vom Model hören const handler = (newText: string) => setText(newText); model.on('change', handler); return () => { model.off('change', handler); }; }, [model]); const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => { model.setValue(event.target.value); }; return ( <div style={{ padding: '16px', height: '100%' }}> <textarea value={text} onChange={handleChange} style={{ width: '100%', height: '100%', fontFamily: 'monospace', fontSize: '14px', backgroundColor: 'var(--background)', color: 'var(--foreground)', border: '1px solid var(--border)', padding: '8px', resize: 'none', }} /> </div> ); }

Schritt 3: Dokumenttyp registrieren

Im Entry-Point wird alles zusammengebracht:

// index.ts import { Studio } from '@5minds/processcube_studio_sdk'; import { MeinEditorModel } from './MeinEditorModel'; import { MeinEditorRenderer } from './MeinEditorRenderer'; export function onLoad(studio: Studio): void { // Icon registrieren studio.icons.registerIcons({ 'meinEditor/icon': 'fad fa-file-alt', }); // Dokumenttyp registrieren studio.editors.registerDocumentType('mein-editor', { uriMatch: /meinEditor:/, // URI-Pattern für diesen Typ modelKey: 'MeinEditorModel', modelConstructor: MeinEditorModel, rendererKey: 'MeinEditorRenderer', rendererConstructor: MeinEditorRenderer, icon: 'meinEditor/icon', }); // Command zum Erstellen eines neuen Dokuments studio.commands.registerInCommandSearch( 'meinEditor.neu', 'Mein Editor: Neues Dokument erstellen', () => { const uri = `meinEditor:Neues-Dokument-${studio.getGuid()}`; studio.editors.createNewEditorDocumentAsBuffer('mein-editor', 'Hier Text eingeben...'); }, ); }

URI-Patterns

Das uriMatch-Feld bestimmt, welche URIs von diesem Editor geöffnet werden. Es ist ein regulärer Ausdruck:

// Eigenes Protokoll (für Buffer-Dokumente) uriMatch: /meinEditor:/ // Datei-Endung (für Datei-basierte Editoren) uriMatch: /\.myext$/ // Spezifisches Muster uriMatch: /^custom:\/\/mein-editor\//

Lifecycle-Übersicht

Optional: Inspector-Pane

Sie können zusätzlich einen Inspector registrieren, der rechts neben dem Editor angezeigt wird:

studio.editors.registerDocumentType('mein-editor', { uriMatch: /meinEditor:/, modelConstructor: MeinEditorModel, rendererConstructor: MeinEditorRenderer, // Inspector hinzufügen: inspectorKey: 'MeinEditorInspector', inspectorConstructor: MeinEditorInspector, });

Der Inspector ist ebenfalls eine React-Komponente, die dasselbe Model erhält und z.B. Metadaten oder Eigenschaften anzeigt.

Nächste Schritte