====== Vega — Menüs, Werkzeugleiste, Befehle, Hinweise ======
Derselbe Befehl steht in einer Anwendung meist an drei Stellen: im Menü, auf der Werkzeugleiste und hinter einem Tastenkürzel. Vega hat dafür ''TAction'' — den Befehl als eigenes Ding. Beschriftung, Kürzel, Hinweistext und der gesperrte Zustand stehen **einmal** dort und gelten überall, wo er verknüpft ist.
→ [[lyx_-_programmiersprache:vega:guides|Vega-Guides]] · [[lyx_-_programmiersprache:vega:guides:komponenten|Komponenten]] · [[lyx_-_programmiersprache:vega:guides:events|Ereignisse]]
----
===== Menü =====
var mm: TMainMenu := new TMainMenu();
var mDatei: TMenuItem := mm.Add("Datei");
mDatei.Add("Neu").OnClick := OnNeu;
mDatei.AddSeparator();
mDatei.Add("Beenden").OnClick := OnBeenden;
mDatei.Item(2).SetShortcut(113, MOD_CTRL); // Strg+Q
f.SetMenu(mm);
''Add'' liefert den neuen Eintrag zurück — daher die kurze Schreibweise. Untermenüs entstehen, indem man an einem Eintrag wieder ''Add'' ruft. Auf bestehende Einträge kommt man über ''Item(index)''; ''Checked'' und ''Enabled'' setzen den Zustand.
Die Menüleiste **nimmt am Layout nicht teil**: sie liegt auf ''0/0'' und wird zuletzt gezeichnet. Zwei Folgen — Platz darunter selbst freihalten (''f.MenuHeight()'') und im ''OnResize'' die Breite nachziehen (''f.Menu.Width := f.Width'').
Ein Kontextmenü ist ein ''TPopupMenu'', zugewiesen über ''PopupMenuPtr''.
----
===== Werkzeugleiste =====
var tb: TToolBar := new TToolBar();
tb.SetBounds(0, f.MenuHeight(), 520, 34);
tb.ButtonWidth := 120;
tb.SetParent(f);
var t1: TButton := new TButton("");
t1.Width := 0; // 0 = die Leiste bestimmt die Breite
t1.SetParent(tb);
tb.ArrangeButtons();
''TToolBar'' ordnet ihre Kinder selbst an: ''ButtonWidth'', ''ButtonHeight'', ''Spacing'', ''Flat'', ''ShowCaptions'', ''Wrapable''. Ein Knopf mit ''Width := 0'' übernimmt die Vorgabebreite der Leiste; ein Knopf mit eigener Breite behält sie. ''ArrangeButtons()'' nach dem Befüllen.
----
===== Befehle (TAction) =====
g_al := new TActionList();
g_app.AddActionList(g_al);
var aSp: TAction := g_al.Add("Speichern");
aSp.SetHint("Schreibt die Datei");
aSp.SetShortcut(83, MOD_CTRL); // Strg+S
aSp.OnExecute := TueSpeichern; // fn(action: TAction): void
aSp.OnUpdate := PruefeSpeichern; // setzt action.Enabled
Verknüpft wird in beide Richtungen:
* ''aSp.LinkMenuItem(mDatei.Add(""))'' — der Eintrag bekommt Beschriftung, Kürzel und Zustand vom Befehl; deshalb der leere Text.
* ''aSp.LinkControl(knopf as TControl)'' — dasselbe für einen Knopf.
''OnUpdate'' läuft, bevor die Oberfläche gezeigt wird. Dort steht **eine** Bedingung, und Menüeintrag wie Knopf werden gemeinsam gesperrt — statt an jeder Stelle dieselbe Prüfung zu wiederholen.
Ein ''TAction'' trägt außerdem ''Checked'', ''Visible'', ''ImageIndex'' und ''Tag''.
----
===== Hinweise (Hints) =====
Jedes Control hat ''Hint'' und ''ShowHint''. Gesetzt wird der Text mit ''SetHint("…")''; ''ShowHint := false'' schaltet ihn für einen Bereich ab — auch für dessen Kinder. Die Anzeige selbst übernimmt der ''THintController'' der Anwendung; ein Klick räumt den Hinweis sofort weg.
Ein ''TAction'' gibt seinen ''Hint'' an alles weiter, was mit ihm verknüpft ist.
----
===== Beispiel =====
Ein Befehl, drei Bedienwege — Menü, Leiste, Tastenkürzel — plus Kontextmenü und Hinweistext:
unit Main;
import std.io;
import Vega.Types;
import Vega.Events;
import Vega.Canvas;
import Vega.Theme;
import Vega.Control;
import Vega.Font;
import Vega.Strings;
import Vega.Lists;
import Vega.Style;
import Vega.StdCtrls;
import Vega.Layout;
import Vega.Menus;
import Vega.Actions;
import Vega.Backend;
import Vega.BackendAuto;
import Vega.Forms;
var g_app: TApplication;
var g_form: TForm;
var g_al: TActionList;
var g_status: TLabel;
var g_geaendert: bool;
// Ein Befehl fuehrt aus …
fn TueSpeichern(action: TAction): void {
g_geaendert := false;
g_status.SetCaption("gespeichert");
}
// … und sagt selbst, wann er verfuegbar ist. OnUpdate laeuft vor dem
// Anzeigen — Menueeintrag UND Knopf werden gemeinsam gesperrt.
fn PruefeSpeichern(action: TAction): void {
action.Enabled := g_geaendert;
}
fn TueAendern(action: TAction): void {
g_geaendert := true;
g_status.SetCaption("geaendert");
}
fn TueBeenden(action: TAction): void {
g_app.Terminate();
}
// Ein Menueeintrag ohne Befehl bekommt einen gewoehnlichen TNotifyEvent.
fn OnKontext(sender: TControl): void {
g_status.SetCaption("aus dem Kontextmenue");
}
fn main(): int64 {
g_app := new TApplication(NewPlatformBackend());
if (!g_app.Ready) { PrintLn("Kein Fenstersystem erreichbar."); return 1; }
g_form := new TForm(520, 240, "Menue, Leiste, Befehle");
g_geaendert := false;
g_al := new TActionList();
g_app.AddActionList(g_al);
var aSp: TAction := g_al.Add("Speichern");
aSp.SetHint("Schreibt die Datei");
aSp.SetShortcut(83, MOD_CTRL); // Strg+S
aSp.OnExecute := TueSpeichern;
aSp.OnUpdate := PruefeSpeichern;
var aAe: TAction := g_al.Add("Aendern");
aAe.SetHint("Markiert das Dokument als geaendert");
aAe.OnExecute := TueAendern;
var aEn: TAction := g_al.Add("Beenden");
aEn.SetShortcut(81, MOD_CTRL); // Strg+Q
aEn.OnExecute := TueBeenden;
// Menue: der Eintrag bekommt Beschriftung, Kuerzel und Zustand vom Befehl
var mm: TMainMenu := new TMainMenu();
var mDatei: TMenuItem := mm.Add("Datei");
aSp.LinkMenuItem(mDatei.Add(""));
aAe.LinkMenuItem(mDatei.Add(""));
mDatei.AddSeparator();
aEn.LinkMenuItem(mDatei.Add(""));
g_form.SetMenu(mm);
// Werkzeugleiste: Width auf 0 heisst "die Leiste bestimmt die Breite"
var tb: TToolBar := new TToolBar();
tb.SetBounds(0, g_form.MenuHeight(), 520, 34);
tb.ButtonWidth := 120;
tb.SetParent(g_form);
var t1: TButton := new TButton("");
t1.Width := 0;
t1.SetParent(tb);
aSp.LinkControl(t1 as TControl);
var t2: TButton := new TButton("");
t2.Width := 0;
t2.SetParent(tb);
aAe.LinkControl(t2 as TControl);
tb.ArrangeButtons();
g_status := new TLabel("bereit");
g_status.SetBounds(16, 100, 480, 18);
g_status.SetHint("Zeigt, was zuletzt geschah");
g_status.SetParent(g_form);
// Kontextmenue am Fenster
var pm: TPopupMenu := new TPopupMenu();
pm.Add("Was war zuletzt?").OnClick := OnKontext;
g_form.PopupMenuPtr := pm as int64;
if (!g_app.ShowForm(g_form)) { return 2; }
g_app.Run();
g_app.Shutdown();
return 0;
}
Übersetzen: ''lyxc befehle.lyx -I . -I platform/linux -o befehle''. Nachgemessen mit ''lyxc 1.1.3I'', übersetzt fehlerfrei.
----
===== Fallstricke =====
* **''AddActionList'' vergessen.** Ohne sie läuft kein ''OnUpdate'' und kein Kürzel.
* **Beschriftung doppelt gepflegt.** Wer den Menüeintrag mit Text anlegt **und** einen Befehl verknüpft, hat zwei Wahrheiten. Mit Befehl: ''Add("")''.
* **''ArrangeButtons()'' vergessen.** Die Leiste bleibt leer aussehend, obwohl die Knöpfe da sind.
* **Platz unter der Menüleiste.** Sie nimmt am Layout nicht teil; ohne eigenen Streifen liegt die erste Zeile darunter.
Letzte Aktualisierung: 2026-08-19 — API gegen ''Vega/Menus.lyx'', ''Vega/Layout.lyx'', ''Vega/Actions.lyx'' und ''Vega/Hints.lyx'' erhoben; Beispiel mit ''lyxc 1.1.3I'' übersetzt.