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 Ü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

  1. Jeder Beitrag hat einen Ort (Location): menuBar, commandPalette, view/title, view/item/context oder eine Submenu-Id.
  2. Innerhalb eines Orts sortiert der Host nach Gruppe (alphabetisch), dann nach Order (numerisch).
  3. Zwischen verschiedenen Gruppen fügt der Host einen Trennstrich ein.
  4. When-Ausdrücke steuern die Sichtbarkeit dynamisch. Ändert sich ein Kontextwert, aktualisiert der Host sofort alle betroffenen Einträge.
  5. 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.
  6. Die Installationsreihenfolge spielt keine Rolle. Das Ergebnis ist deterministisch, weil es nur von Gruppe und Order abhängt.

Zurück zur Übersicht.

Zuletzt geändert: den 15.03.2026 um 02:34