====== Tutorial: Menü- und Toolbar-Integration ======
Dieses Tutorial zeigt, wie ein Add-in seine Commands in die Menüleiste, die Toolbar, die ActionBar und die QuickBar der Shell integriert. Der Schwerpunkt liegt auf dem Merge-Verfahren: Wie werden Beiträge mehrerer Add-ins zusammengeführt, und wie steuern ''group'', ''order'' und ''when'' das Ergebnis.
Zurück zur [[..:start|Übersicht]].
===== Ausgangssituation =====
Drei Add-ins sollen ihre Funktionalität in die Shell einbringen:
* **Assets** — Anlageverwaltung (Öffnen, Speichern, Drucken)
* **Reports** — Berichtswesen (Monatsbericht, Jahresbericht)
* **Export** — Datenexport (CSV, PDF)
Jedes Add-in hat ein eigenes Top-Level-Menü, und alle drei tragen Buttons zur Haupt-Toolbar und zur ActionBar bei.
===== Schritt 1: Top-Level-Menüs anlegen =====
Jedes Add-in deklariert ein Submenü und platziert es in der Menüleiste:
**Assets:**
"submenus": [
{ "id": "assets", "label": "Assets" }
],
"menus": {
"menuBar": [
{ "submenu": "assets", "group": "modules", "order": 100 }
],
"assets": [
{ "command": "assets.open", "group": "file", "order": 1 },
{ "command": "assets.save", "group": "file", "order": 2 },
{ "command": "assets.print", "group": "output", "order": 1 }
]
}
**Reports:**
"submenus": [
{ "id": "reports", "label": "Berichte" }
],
"menus": {
"menuBar": [
{ "submenu": "reports", "group": "modules", "order": 200 }
],
"reports": [
{ "command": "reports.monthly", "group": "standard", "order": 1 },
{ "command": "reports.yearly", "group": "standard", "order": 2 },
{ "command": "reports.custom", "group": "custom", "order": 1 }
]
}
**Export:**
"submenus": [
{ "id": "export", "label": "Export" }
],
"menus": {
"menuBar": [
{ "submenu": "export", "group": "tools", "order": 100 }
],
"export": [
{ "command": "export.csv", "group": "formats", "order": 1 },
{ "command": "export.pdf", "group": "formats", "order": 2 }
]
}
==== Ergebnis in der Menüleiste ====
[ Datei ] [ Assets ] [ Berichte ] [ Export ] [ Hilfe ]
(modules/100) (modules/200) (tools/100)
Assets und Berichte stehen nebeneinander, weil beide die Gruppe ''modules'' verwenden. Innerhalb der Gruppe bestimmt ''order'' die Reihenfolge (100 < 200). Export steht in der Gruppe ''tools'', die alphabetisch nach ''modules'' kommt.
==== Ergebnis im Assets-Menü ====
Assets
├── Anlage öffnen (file / 1)
├── Anlage speichern (file / 2)
├── ───────────────── (Trennstrich)
└── Drucken (output / 1)
Die Gruppen ''file'' und ''output'' werden durch einen Trennstrich getrennt.
===== Schritt 2: In bestehende Menüs einfügen =====
Ein Add-in kann auch in ein Menü eines anderen Add-ins einfügen. Das Export-Add-in möchte etwa einen Eintrag im Assets-Menü platzieren:
"menus": {
"assets": [
{ "command": "export.asset-csv", "group": "output", "order": 2,
"when": "activeDocument == assets.editor" }
]
}
Dieser Eintrag landet in der Gruppe ''output'' des Assets-Menüs, direkt nach dem Drucken-Eintrag (''order'' 2 > 1). Er ist nur sichtbar, wenn ein Asset-Editor aktiv ist.
Assets
├── Anlage öffnen (file / 1)
├── Anlage speichern (file / 2)
├── ─────────────────
├── Drucken (output / 1)
└── Als CSV exportieren (output / 2) ← Vom Export-Add-in
Dieses Cross-Plugin-Merging funktioniert, weil der Host alle Manifest-Beiträge sammelt und nach Location-Schlüssel zusammenführt. Dem Assets-Menü ist es egal, von welchem Add-in der Eintrag kommt — die Sortierung nach Gruppe und Order gilt einheitlich.
===== Schritt 3: Toolbar-Integration =====
Die drei Add-ins tragen Buttons zu verschiedenen Toolbar-Bereichen bei:
**Haupt-Toolbar (immer sichtbar):**
// Assets
{ "toolbarId": "main", "command": "assets.open", "icon": "media/asset.svg",
"group": "modules", "order": 1 }
// Reports
{ "toolbarId": "main", "command": "reports.monthly", "icon": "media/report.svg",
"group": "modules", "order": 2 }
**ActionBar (kontextabhängig):**
// Assets — nur sichtbar bei aktivem Asset-Editor
{ "toolbarId": "actionbar", "command": "assets.save", "icon": "media/save.svg",
"when": "activeDocument == assets.editor && isDirty" }
{ "toolbarId": "actionbar", "command": "assets.print", "icon": "media/print.svg",
"when": "activeDocument == assets.editor" }
// Export — nur sichtbar bei aktivem Asset-Editor
{ "toolbarId": "actionbar", "command": "export.asset-csv", "icon": "media/csv.svg",
"when": "activeDocument == assets.editor" }
**QuickBar (benutzerdefinierbar):**
// Assets — Schnellzugriff
{ "toolbarId": "quickbar", "command": "assets.open", "icon": "media/asset.svg" }
==== Ergebnis ====
Haupt-Toolbar:
[ Asset öffnen ] [ Monatsbericht ]
(modules/1) (modules/2)
ActionBar (wenn Asset-Editor aktiv und dirty):
[ Speichern ] [ Drucken ] [ CSV Export ]
Die ActionBar-Buttons erscheinen und verschwinden automatisch, wenn der Benutzer zwischen Tabs wechselt. Das liegt an den ''when''-Ausdrücken, die der Host bei jedem Kontextwechsel neu auswertet.
===== Schritt 4: CommandPalette =====
Standardmäßig erscheinen alle Commands in der CommandPalette. Commands, die nur über andere Wege erreichbar sein sollen, werden ausgeblendet:
"menus": {
"commandPalette": [
{ "command": "assets.internal.cleanup", "when": "false" }
]
}
Der Ausdruck ''when'': ''"false"'' ist immer falsch — der Command erscheint nie in der Palette. Er bleibt aber über ''ExecuteCommand'' und Menüs erreichbar.
===== Schritt 5: Kontextmenüs =====
Kontextmenüs für TreeView-Elemente verwenden den Ort ''view/item/context'':
"menus": {
"view/item/context": [
{
"command": "assets.nav.open",
"when": "view == assets.navigator && viewItem == asset",
"group": "navigation", "order": 1
},
{
"command": "export.asset-csv",
"when": "view == assets.navigator && viewItem == asset",
"group": "export", "order": 1
},
{
"command": "assets.nav.delete",
"when": "view == assets.navigator && viewItem == asset",
"group": "modification", "order": 1
}
]
}
Das Kontextmenü für einen Asset-Baumknoten:
├── Anlage öffnen (navigation / 1) ← Vom Assets-Add-in
├── ─────────────────
├── Als CSV exportieren (export / 1) ← Vom Export-Add-in
├── ─────────────────
└── Löschen (modification / 1) ← Vom Assets-Add-in
Auch hier werden Beiträge verschiedener Add-ins nach Gruppe und Order zusammengeführt. Das Export-Add-in fügt seinen Eintrag in das Kontextmenü des Assets-Navigators ein, ohne dass das Assets-Add-in davon wissen muss.
===== Zusammenfassung der Merge-Regeln =====
- Jeder Beitrag hat einen **Ort** (Location): ''menuBar'', ''commandPalette'', ''view/title'', ''view/item/context'' oder eine Submenu-Id.
- Innerhalb eines Orts sortiert der Host nach **Gruppe** (alphabetisch), dann nach **Order** (numerisch).
- Zwischen verschiedenen Gruppen fügt der Host einen **Trennstrich** ein.
- **When-Ausdrücke** steuern die Sichtbarkeit dynamisch. Ändert sich ein Kontextwert, aktualisiert der Host sofort alle betroffenen Einträge.
- **Cross-Plugin-Merging** funktioniert automatisch: Ein Add-in kann in das Menü oder Kontextmenü eines anderen Add-ins einfügen, indem es denselben Location-Schlüssel verwendet.
- Die **Installationsreihenfolge** spielt keine Rolle. Das Ergebnis ist deterministisch, weil es nur von Gruppe und Order abhängt.
Zurück zur [[..:start|Übersicht]].