MODULE editor ; (* m2-GTK4 example - a small editor built from the second input batch. A GtkSearchEntry, a GtkTextView (in a GtkScrolledWindow) backed by a GtkTextBuffer, a GtkDropDown that selects the wrap mode, and a GtkSpinButton that sets the text padding. The signals use the GtkClosures helper (2- and 3-argument forms). Build: make examples Run: ./build/examples/editor *) FROM Gio IMPORT g_application_run; 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, gtk_box_set_spacing; FROM GtkEnums IMPORT GtkVertical, GtkHorizontal, GtkWrapWord; FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text; FROM GtkWidget IMPORT gtk_widget_set_margin_top, gtk_widget_set_margin_bottom, gtk_widget_set_margin_start, gtk_widget_set_margin_end, gtk_widget_set_vexpand; FROM GtkSearchEntry IMPORT gtk_search_entry_new, gtk_search_entry_set_placeholder_text; FROM GtkEditable IMPORT gtk_editable_get_text; FROM GtkScrolledWindow IMPORT gtk_scrolled_window_new, gtk_scrolled_window_set_child, gtk_scrolled_window_set_policy, GtkPolicyNever, GtkPolicyAutomatic; FROM GtkTextView IMPORT gtk_text_view_new, gtk_text_view_get_buffer, gtk_text_view_set_wrap_mode, gtk_text_view_set_monospace, gtk_text_view_set_left_margin, gtk_text_view_set_right_margin; FROM GtkTextBuffer IMPORT gtk_text_buffer_set_text; FROM GtkStringList IMPORT gtk_string_list_new, gtk_string_list_append; FROM GtkDropDown IMPORT gtk_drop_down_new, gtk_drop_down_get_selected, gtk_drop_down_set_selected; FROM GtkSpinButton IMPORT gtk_spin_button_new_with_range, gtk_spin_button_get_value, gtk_spin_button_set_value; FROM GtkClosures IMPORT Connect2, Connect3; FROM GtkUtils IMPORT CStrToM2, StrAppend; FROM SYSTEM IMPORT ADDRESS, ADR; FROM libc IMPORT printf; CONST AppId = "org.example.m2gtk4.Editor"; VAR view, status: ADDRESS; PROCEDURE OnSearch (entry: ADDRESS; user: ADDRESS); VAR text: ARRAY [0..63] OF CHAR; line: ARRAY [0..95] OF CHAR; BEGIN line[0] := 0C; StrAppend(line, "search: "); CStrToM2(gtk_editable_get_text(entry), text); IF text[0] = 0C THEN StrAppend(line, "(none)") ELSE StrAppend(line, text) END; gtk_label_set_text(status, line) END OnSearch; (* 3-argument form: "notify::selected" carries the GParamSpec *) PROCEDURE OnWrap (dd: ADDRESS; pspec: ADDRESS; user: ADDRESS); BEGIN gtk_text_view_set_wrap_mode(view, gtk_drop_down_get_selected(dd)) END OnWrap; PROCEDURE OnPad (spin: ADDRESS; user: ADDRESS); VAR margin: INTEGER; BEGIN margin := TRUNC(gtk_spin_button_get_value(spin)); gtk_text_view_set_left_margin(view, margin); gtk_text_view_set_right_margin(view, margin) END OnPad; PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS); VAR window, box, search, scroller, bottom, wrapLabel, padLabel, dd, list, spin, buffer: ADDRESS; BEGIN status := gtk_label_new("Type in the box or search"); (* text view inside a scrolled window *) view := gtk_text_view_new(); gtk_text_view_set_monospace(view, 1); buffer := gtk_text_view_get_buffer(view); gtk_text_buffer_set_text(buffer, "Edit me!", -1); gtk_text_view_set_left_margin(view, 6); gtk_text_view_set_right_margin(view, 6); scroller := gtk_scrolled_window_new(); gtk_scrolled_window_set_policy(scroller, GtkPolicyNever, GtkPolicyAutomatic); gtk_scrolled_window_set_child(scroller, view); gtk_widget_set_vexpand(scroller, 1); (* search entry *) search := gtk_search_entry_new(); gtk_search_entry_set_placeholder_text(search, "search the text"); Connect2(search, "search-changed", OnSearch, NIL); (* wrap-mode drop-down *) list := gtk_string_list_new(NIL); gtk_string_list_append(list, "No wrap"); gtk_string_list_append(list, "Wrap chars"); gtk_string_list_append(list, "Wrap words"); gtk_string_list_append(list, "Wrap words/chars"); dd := gtk_drop_down_new(list, NIL); gtk_drop_down_set_selected(dd, 2); gtk_text_view_set_wrap_mode(view, GtkWrapWord); Connect3(dd, "notify::selected", OnWrap, NIL); (* padding spin button *) spin := gtk_spin_button_new_with_range(0.0, 40.0, 1.0); gtk_spin_button_set_value(spin, 6.0); Connect2(spin, "value-changed", OnPad, NIL); wrapLabel := gtk_label_new("Wrap:"); padLabel := gtk_label_new("Padding:"); bottom := gtk_box_new(GtkHorizontal, 8); gtk_box_append(bottom, wrapLabel); gtk_box_append(bottom, dd); gtk_box_append(bottom, padLabel); gtk_box_append(bottom, spin); box := gtk_box_new(GtkVertical, 8); gtk_box_set_spacing(box, 8); gtk_widget_set_margin_top(box, 12); gtk_widget_set_margin_bottom(box, 12); gtk_widget_set_margin_start(box, 12); gtk_widget_set_margin_end(box, 12); gtk_box_append(box, search); gtk_box_append(box, scroller); gtk_box_append(box, bottom); gtk_box_append(box, status); window := gtk_application_window_new(application); gtk_window_set_title(window, "m2-GTK4 Editor"); gtk_window_set_default_size(window, 520, 360); gtk_window_set_child(window, box); gtk_window_present(window) END OnActivate; VAR app: ADDRESS; BEGIN app := gtk_application_new(AppId, 0); IF app = NIL THEN printf("gtk_application_new failed\n"); HALT(1) END; Connect2(app, "activate", OnActivate, NIL); g_application_run(app, 0, NIL) END editor.