75. GUIs III: Ein Menü

Wir wollen eine Standard-Menüzeile haben. Die zweitbequemste Art, das in GTK zu machen, ist über eine Item Factory:

static void doLs(GtkWidget *w, gpointer data)
{
  if (data) system("ls -l");
  else system("ls");
}

GtkWidget *makeMenuBar(GtkWindow *window)
{
  static GtkItemFactoryEntry menu_items[] = {
    { "/_File", NULL, NULL, 0, "<Branch>"},
    { "/File/_Dir", "<control>d", doLs, 0, NULL},
    { "/File/_Long dir", "<control>l", doLs, 1, NULL},
    { "/File/_Quit", "<control>q", gtk_main_quit,
      0, NULL},
  };
  GtkAccelGroup *accel_group = gtk_accel_group_new();
  GtkItemFactory *item_factory = gtk_item_factory_new(
    GTK_TYPE_MENU_BAR, "<main>", accel_group);

  gtk_item_factory_create_items(item_factory,
    sizeof(menu_items)/sizeof(GtkItemFactoryEntry),
    menu_items, NULL);
  gtk_window_add_accel_group(window, accel_group);
  return gtk_item_factory_get_widget(item_factory,
    "<main>");
}

Es wird ein Array von structs angelegt; in jedem struct steht vorne ein “Pfad” zum Menüeintrag, dann ein Tastatur-Shortcut, ein Callback (vgl. doLs), zusätzliche Daten, die dem Callback übergeben werden sollen (hier zur Unterscheidung von ls und ls -l) und ein Typ, hier entweder NULL für einen Menüeintrag oder <Branch> für einen Menütitel.

Die Factory wird angewiesen, aus diesen Daten das Widget <main> zu erstellen. Das Ergebnis holen wir mit gtk item_factory_get_widget und geben es zurück.

Das ganze Geeiere mit der accel_group ist nötig, weil die Tastaturereignisse vom Fenster und nicht von der Menüzeile empfangen und verarbeitet werden – sonst würden sie nur “gesehen”, wenn die Menüzeile den Fokus hat.

Dass bei der Konstruktion der item_factory gesagt werden muss, dass eine Menüzeile rauskommen soll, deutet schon an, dass die Funktion auch zu anderen, ähnlichen Zwecken verwendet werden kann. Solche Factories, die Objekte erzeugen, sind wieder mal klassische Patterns.

Dateien zu diesem Abschnitt


Markus Demleitner

Copyright Notice