MODULE actions ; (* m2-GTK4 example - application actions, a menu bar and accelerators. A GtkApplicationWindow with an in-window GtkPopoverMenuBar built from a GMenu: File > New (app.new, Ctrl+N) File > Quit (app.quit, Ctrl+Q) View > Bold (win.bold, Ctrl+B, a stateful toggle) "app." actions live on the GtkApplication; "win." actions live on the GtkApplicationWindow (which implements GActionMap). Each handler updates a status label. Build: make examples Run: ./build/examples/actions *) FROM Gio IMPORT g_application_run, g_application_quit; FROM GtkApplication IMPORT gtk_application_new; FROM GtkApplicationWindow IMPORT gtk_application_window_new; FROM GtkWindow IMPORT gtk_window_set_title, gtk_window_set_default_size, gtk_window_set_child, gtk_window_present; FROM GtkBox IMPORT gtk_box_new, gtk_box_append; FROM GtkEnums IMPORT GtkVertical; FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text; FROM GtkPopoverMenuBar IMPORT gtk_popover_menu_bar_new_from_model; FROM GSimpleAction IMPORT g_simple_action_new, g_simple_action_new_stateful; FROM GActionMap IMPORT g_action_map_add_action; FROM GMenu IMPORT g_menu_new, g_menu_append, g_menu_append_submenu; FROM GVariant IMPORT g_variant_new_boolean, g_variant_get_boolean; FROM GtkUtils IMPORT Connect, SetAccel; FROM SYSTEM IMPORT ADDRESS, ADR; FROM libc IMPORT printf; CONST AppId = "org.example.m2gtk4.Actions"; VAR app, status: ADDRESS; PROCEDURE OnQuit (action: ADDRESS; param: ADDRESS; data: ADDRESS); BEGIN g_application_quit(app) END OnQuit; PROCEDURE OnNew (action: ADDRESS; param: ADDRESS; data: ADDRESS); BEGIN gtk_label_set_text(status, "New selected") END OnNew; (* void change_state(GSimpleAction *action, GVariant *value, gpointer data) *) PROCEDURE OnBold (action: ADDRESS; param: ADDRESS; data: ADDRESS); BEGIN IF g_variant_get_boolean(param) # 0 THEN gtk_label_set_text(status, "Bold on") ELSE gtk_label_set_text(status, "Bold off") END END OnBold; PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS); VAR window, box, bar, fileMenu, viewMenu, menubar, action: ADDRESS; BEGIN (* app-scoped actions: new, quit *) action := g_simple_action_new("new", NIL); Connect(action, "activate", ADR(OnNew), NIL); g_action_map_add_action(application, action); action := g_simple_action_new("quit", NIL); Connect(action, "activate", ADR(OnQuit), NIL); g_action_map_add_action(application, action); window := gtk_application_window_new(application); (* window-scoped stateful action: bold *) action := g_simple_action_new_stateful("bold", NIL, g_variant_new_boolean(0)); Connect(action, "change-state", ADR(OnBold), NIL); g_action_map_add_action(window, action); (* menu model *) fileMenu := g_menu_new(); g_menu_append(fileMenu, "New", "app.new"); g_menu_append(fileMenu, "Quit", "app.quit"); viewMenu := g_menu_new(); g_menu_append(viewMenu, "Bold", "win.bold"); menubar := g_menu_new(); g_menu_append_submenu(menubar, "File", fileMenu); g_menu_append_submenu(menubar, "View", viewMenu); bar := gtk_popover_menu_bar_new_from_model(menubar); status := gtk_label_new("Ready"); box := gtk_box_new(GtkVertical, 8); gtk_box_append(box, bar); gtk_box_append(box, status); (* accelerators *) SetAccel(application, "app.new", "n"); SetAccel(application, "app.quit", "q"); SetAccel(application, "win.bold", "b"); gtk_window_set_title(window, "m2-GTK4 Actions"); gtk_window_set_default_size(window, 420, 220); gtk_window_set_child(window, box); gtk_window_present(window) END OnActivate; VAR rc: INTEGER; BEGIN app := gtk_application_new(AppId, 0); IF app = NIL THEN printf("gtk_application_new failed\n"); HALT(1) END; Connect(app, "activate", ADR(OnActivate), NIL); rc := g_application_run(app, 0, NIL) END actions.