Kaynağa Gözat

feat: GtkAssistant, GtkIconView and GtkEmojiChooser

- GtkAssistant (wizard; append/insert pages, per-page title/type/
  complete, current-page navigation, commit)
- GtkIconView (deprecated, GtkTreeModel-based; construction + properties)
- GtkEmojiChooser (emoji picker popover; "emoji-picked" signal)
- test_lastwidgets

40 tests pass; 159 src modules, 26 examples.
Eric Streit 3 gün önce
ebeveyn
işleme
8bbcca6237
7 değiştirilmiş dosya ile 311 ekleme ve 5 silme
  1. 1 1
      Makefile
  2. 3 2
      README.md
  3. 96 0
      src/GtkAssistant.def
  4. 25 0
      src/GtkEmojiChooser.def
  5. 66 0
      src/GtkIconView.def
  6. 2 2
      tests/run_tests.sh
  7. 118 0
      tests/test_lastwidgets.mod

+ 1 - 1
Makefile

@@ -20,7 +20,7 @@ OBJS    := $(OBJDIR)/GtkUtils.o $(OBJDIR)/GtkClosures.o $(OBJDIR)/m2gtkshim.o
 
 INCLUDES := -I$(SRC_DIR) -I$(LIB_DIR)
 
-TESTS    := test_glib test_version test_widgets test_inputs test_inputs2 test_containers test_containers2 test_actions test_closure test_headerbar test_gio test_gerror test_filedialog test_views test_builder test_utility test_css test_popover test_dialogs test_models test_cairo test_drawing test_gestures test_models2 test_widgets3 test_shim test_shim2 test_shim3 test_dnd test_media test_gl test_print test_text test_expr test_constraints test_shortcuts test_snapshot test_application
+TESTS    := test_glib test_version test_widgets test_inputs test_inputs2 test_containers test_containers2 test_actions test_closure test_headerbar test_gio test_gerror test_filedialog test_views test_builder test_utility test_css test_popover test_dialogs test_models test_cairo test_drawing test_gestures test_models2 test_widgets3 test_shim test_shim2 test_shim3 test_dnd test_media test_gl test_print test_text test_expr test_constraints test_shortcuts test_snapshot test_lastwidgets test_application
 EXAMPLES := hello counter inputs containers actions headerbar editor layouts files views builder feedback styling popover dialogs drawing demo gestures customwidget customlayout media clipboard gl richtext snapshot
 
 # Include the libadwaita test/example only when libadwaita is installed.

+ 3 - 2
README.md

@@ -14,7 +14,7 @@ Verified with `gm2` 16.0.1 (experimental), GTK 4.18.6 and libadwaita 1.7.6.
 
 ## Features
 
-- **156 hand-written binding modules** across GLib, GObject, Gio, GTK4
+- **159 hand-written binding modules** across GLib, GObject, Gio, GTK4
   and libadwaita — windows, widgets, inputs, containers, model-backed
   views, actions/menus/accelerators, dialogs, CSS, drawing (Cairo/Pango),
   rich text, gestures, drag-and-drop, media, OpenGL, printing,
@@ -22,7 +22,7 @@ Verified with `gm2` 16.0.1 (experimental), GTK 4.18.6 and libadwaita 1.7.6.
 - **Pure-Modula-2 helpers**: `GtkUtils` (string/number conversion,
   `Connect`, `SetAccel`, ownership and `GError` helpers) and
   `GtkClosures` (per-connection signal contexts with cleanup).
-- **39 tests** and **26 runnable examples**.
+- **40 tests** and **26 runnable examples**.
 - **Generator + verifier**: `tools/gir2def.py` turns a `.gir` file into
   `.def` files; `tools/gir_verify.py` checks every generated identifier
   against the installed library. Verified clean across 8602 identifiers.
@@ -187,6 +187,7 @@ gm2 -fiso -Isrc -Ilib myprog.mod \
 | `GtkCssProvider`, `GtkStyleContext` | CSS styling for the display |
 | `GtkStackSidebar`, `GtkSearchBar`, `GtkRevealer`, `GtkAspectFrame` | sidebar/search/animation/layout helpers |
 | `GtkFlowBox`, `GtkFixed`, `GtkPicture`, `GtkToggleButton`, `GtkLinkButton`, `GtkCalendar`, `GtkLevelBar`, `GtkScrollbar` | reflowing grid, fixed/abs, image, toggle/link, date, level, scrollbar |
+| `GtkAssistant`, `GtkIconView`, `GtkEmojiChooser` | wizard, icon grid (deprecated), emoji picker |
 | `GtkEventController`, `GtkGestures` | event controllers and gestures (click/drag/swipe/zoom/rotate/pan/long-press) |
 | `GtkDrawingArea` + `Cairo` + `Pango` + `PangoCairo` | custom drawing with Cairo and text layout |
 | `GtkListBox`, `GtkListView`, `GtkGridView`, `GtkColumnView`, `GtkColumnViewColumn`, `GtkColumnViewCell`, `GtkListItem`, `GtkSignalListItemFactory`, `GtkSelectionModel`, `GtkSingleSelection`, `GtkNoSelection` | lists, grids and tables |

+ 96 - 0
src/GtkAssistant.def

@@ -0,0 +1,96 @@
+DEFINITION MODULE FOR "C" GtkAssistant ;
+
+(*
+   m2-GTK4 - GtkAssistant: a multi-page wizard.  Mapped onto
+   <gtk/deprecated/gtkassistant.h> (deprecated).
+
+   Add pages with append_page/insert_page; each returns the page index.
+   Per-page title/type/complete state are set with the set_page_* calls.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkAssistant, GtkAssistantPageType,
+   AssistantPageContent, AssistantPageIntro, AssistantPageConfirm,
+   AssistantPageSummary, AssistantPageProgress, AssistantPageCustom,
+   gtk_assistant_new,
+   gtk_assistant_append_page, gtk_assistant_prepend_page,
+   gtk_assistant_insert_page, gtk_assistant_remove_page,
+   gtk_assistant_add_action_widget,
+   gtk_assistant_set_current_page, gtk_assistant_get_current_page,
+   gtk_assistant_get_n_pages, gtk_assistant_get_nth_page,
+   gtk_assistant_set_page_title, gtk_assistant_set_page_complete,
+   gtk_assistant_set_page_type,
+   gtk_assistant_commit, gtk_assistant_next_page, gtk_assistant_previous_page;
+
+
+TYPE
+   GtkAssistant = ADDRESS;
+   GtkAssistantPageType = CARDINAL;
+
+CONST
+   AssistantPageContent  = 0;
+   AssistantPageIntro    = 1;
+   AssistantPageConfirm  = 2;
+   AssistantPageSummary  = 3;
+   AssistantPageProgress = 4;
+   AssistantPageCustom   = 5;
+
+(* GtkWidget *gtk_assistant_new(void) *)
+PROCEDURE gtk_assistant_new () : GtkAssistant;
+
+(* int gtk_assistant_append_page(GtkAssistant *assistant, GtkWidget *page) *)
+PROCEDURE gtk_assistant_append_page (assistant: GtkAssistant; page: ADDRESS) : [ INTEGER ];
+
+(* int gtk_assistant_prepend_page(GtkAssistant *assistant, GtkWidget *page) *)
+PROCEDURE gtk_assistant_prepend_page (assistant: GtkAssistant; page: ADDRESS) : [ INTEGER ];
+
+(* int gtk_assistant_insert_page(GtkAssistant *assistant, GtkWidget *page, int position) *)
+PROCEDURE gtk_assistant_insert_page (assistant: GtkAssistant; page: ADDRESS;
+                                     position: INTEGER) : [ INTEGER ];
+
+(* void gtk_assistant_remove_page(GtkAssistant *assistant, int page_num) *)
+PROCEDURE gtk_assistant_remove_page (assistant: GtkAssistant; page_num: INTEGER);
+
+(* void gtk_assistant_add_action_widget(GtkAssistant *assistant, GtkWidget *child) *)
+PROCEDURE gtk_assistant_add_action_widget (assistant: GtkAssistant; child: ADDRESS);
+
+(* void gtk_assistant_set_current_page(GtkAssistant *assistant, int page_num) *)
+PROCEDURE gtk_assistant_set_current_page (assistant: GtkAssistant; page_num: INTEGER);
+
+(* int gtk_assistant_get_current_page(GtkAssistant *assistant) *)
+PROCEDURE gtk_assistant_get_current_page (assistant: GtkAssistant) : INTEGER;
+
+(* int gtk_assistant_get_n_pages(GtkAssistant *assistant) *)
+PROCEDURE gtk_assistant_get_n_pages (assistant: GtkAssistant) : INTEGER;
+
+(* GtkWidget *gtk_assistant_get_nth_page(GtkAssistant *assistant, int page_num) *)
+PROCEDURE gtk_assistant_get_nth_page (assistant: GtkAssistant;
+                                      page_num: INTEGER) : ADDRESS;
+
+(* void gtk_assistant_set_page_title(GtkAssistant *assistant, GtkWidget *page,
+                                      const char *title) *)
+PROCEDURE gtk_assistant_set_page_title (assistant: GtkAssistant; page: ADDRESS;
+                                        title: ARRAY OF CHAR);
+
+(* void gtk_assistant_set_page_complete(GtkAssistant *assistant, GtkWidget *page,
+                                         gboolean complete) *)
+PROCEDURE gtk_assistant_set_page_complete (assistant: GtkAssistant;
+                                           page: ADDRESS; complete: INTEGER);
+
+(* void gtk_assistant_set_page_type(GtkAssistant *assistant, GtkWidget *page,
+                                     GtkAssistantPageType type) *)
+PROCEDURE gtk_assistant_set_page_type (assistant: GtkAssistant; page: ADDRESS;
+                                       type: GtkAssistantPageType);
+
+(* void gtk_assistant_commit(GtkAssistant *assistant) *)
+PROCEDURE gtk_assistant_commit (assistant: GtkAssistant);
+
+(* void gtk_assistant_next_page(GtkAssistant *assistant) *)
+PROCEDURE gtk_assistant_next_page (assistant: GtkAssistant);
+
+(* void gtk_assistant_previous_page(GtkAssistant *assistant) *)
+PROCEDURE gtk_assistant_previous_page (assistant: GtkAssistant);
+
+END GtkAssistant.

+ 25 - 0
src/GtkEmojiChooser.def

@@ -0,0 +1,25 @@
+DEFINITION MODULE FOR "C" GtkEmojiChooser ;
+
+(*
+   m2-GTK4 - GtkEmojiChooser: a popover for picking an emoji.  Mapped
+   onto <gtk/gtkemoji...> (gtkemojichooser.h).
+
+   It is a GtkPopover; add it to a widget with GtkWidget.set_parent and
+   call GtkPopover.gtk_popover_popup.  Signal: "emoji-picked"
+   (void (GtkEmojiChooser*, const char *text, gpointer)).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkEmojiChooser,
+   gtk_emoji_chooser_new;
+
+
+TYPE
+   GtkEmojiChooser = ADDRESS;
+
+(* GtkWidget *gtk_emoji_chooser_new(void) *)
+PROCEDURE gtk_emoji_chooser_new () : GtkEmojiChooser;
+
+END GtkEmojiChooser.

+ 66 - 0
src/GtkIconView.def

@@ -0,0 +1,66 @@
+DEFINITION MODULE FOR "C" GtkIconView ;
+
+(*
+   m2-GTK4 - GtkIconView: a grid of icons from a GtkTreeModel.  Mapped
+   onto <gtk/deprecated/gtkiconview.h> (deprecated; it uses the
+   deprecated GtkTreeModel).
+
+   Prefer GtkGridView on a GListModel for new code.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkSelectionMode;
+
+EXPORT UNQUALIFIED
+   GtkIconView,
+   gtk_icon_view_new, gtk_icon_view_new_with_model,
+   gtk_icon_view_set_model, gtk_icon_view_get_model,
+   gtk_icon_view_set_text_column, gtk_icon_view_get_text_column,
+   gtk_icon_view_set_markup_column,
+   gtk_icon_view_set_columns, gtk_icon_view_get_columns,
+   gtk_icon_view_set_item_width, gtk_icon_view_set_spacing,
+   gtk_icon_view_set_selection_mode;
+
+
+TYPE
+   GtkIconView = ADDRESS;
+
+(* GtkWidget *gtk_icon_view_new(void) *)
+PROCEDURE gtk_icon_view_new () : GtkIconView;
+
+(* GtkWidget *gtk_icon_view_new_with_model(GtkTreeModel *model) *)
+PROCEDURE gtk_icon_view_new_with_model (model: ADDRESS) : GtkIconView;
+
+(* void gtk_icon_view_set_model(GtkIconView *icon_view, GtkTreeModel *model) *)
+PROCEDURE gtk_icon_view_set_model (icon_view: GtkIconView; model: ADDRESS);
+
+(* GtkTreeModel *gtk_icon_view_get_model(GtkIconView *icon_view) *)
+PROCEDURE gtk_icon_view_get_model (icon_view: GtkIconView) : ADDRESS;
+
+(* void gtk_icon_view_set_text_column(GtkIconView *icon_view, int column) *)
+PROCEDURE gtk_icon_view_set_text_column (icon_view: GtkIconView; column: INTEGER);
+
+(* int gtk_icon_view_get_text_column(GtkIconView *icon_view) *)
+PROCEDURE gtk_icon_view_get_text_column (icon_view: GtkIconView) : INTEGER;
+
+(* void gtk_icon_view_set_markup_column(GtkIconView *icon_view, int column) *)
+PROCEDURE gtk_icon_view_set_markup_column (icon_view: GtkIconView; column: INTEGER);
+
+(* void gtk_icon_view_set_columns(GtkIconView *icon_view, int columns) *)
+PROCEDURE gtk_icon_view_set_columns (icon_view: GtkIconView; columns: INTEGER);
+
+(* int gtk_icon_view_get_columns(GtkIconView *icon_view) *)
+PROCEDURE gtk_icon_view_get_columns (icon_view: GtkIconView) : INTEGER;
+
+(* void gtk_icon_view_set_item_width(GtkIconView *icon_view, int item_width) *)
+PROCEDURE gtk_icon_view_set_item_width (icon_view: GtkIconView; item_width: INTEGER);
+
+(* void gtk_icon_view_set_spacing(GtkIconView *icon_view, int spacing) *)
+PROCEDURE gtk_icon_view_set_spacing (icon_view: GtkIconView; spacing: INTEGER);
+
+(* void gtk_icon_view_set_selection_mode(GtkIconView *icon_view,
+                                          GtkSelectionMode mode) *)
+PROCEDURE gtk_icon_view_set_selection_mode (icon_view: GtkIconView;
+                                            mode: GtkSelectionMode);
+
+END GtkIconView.

+ 2 - 2
tests/run_tests.sh

@@ -13,7 +13,7 @@ CFLAGS=$(pkg-config --cflags gtk4)
 LIBS=$(pkg-config --libs gtk4)
 
 # libadwaita is optional: add its flags and test when available.
-TESTS="test_glib test_version test_widgets test_inputs test_inputs2 test_containers test_containers2 test_actions test_closure test_headerbar test_gio test_gerror test_filedialog test_views test_builder test_utility test_css test_popover test_dialogs test_models test_cairo test_drawing test_gestures test_models2 test_widgets3 test_shim test_shim2 test_shim3 test_dnd test_media test_gl test_print test_text test_expr test_constraints test_shortcuts test_snapshot test_application"
+TESTS="test_glib test_version test_widgets test_inputs test_inputs2 test_containers test_containers2 test_actions test_closure test_headerbar test_gio test_gerror test_filedialog test_views test_builder test_utility test_css test_popover test_dialogs test_models test_cairo test_drawing test_gestures test_models2 test_widgets3 test_shim test_shim2 test_shim3 test_dnd test_media test_gl test_print test_text test_expr test_constraints test_shortcuts test_snapshot test_lastwidgets test_application"
 if pkg-config --exists libadwaita-1 2>/dev/null; then
   CFLAGS="$CFLAGS $(pkg-config --cflags libadwaita-1)"
   LIBS="$LIBS $(pkg-config --libs libadwaita-1)"
@@ -53,7 +53,7 @@ for t in $TESTS; do
        "$ROOT/tests/$t.mod" "$OBJ/GtkUtils.o" "$OBJ/GtkClosures.o" \
        "$OBJ/m2gtkshim.o" -o "$BIN/$t" $LIBS
   case "$t" in
-    test_widgets|test_inputs|test_inputs2|test_containers|test_containers2|test_actions|test_closure|test_headerbar|test_filedialog|test_views|test_builder|test_utility|test_css|test_popover|test_dialogs|test_models|test_drawing|test_gestures|test_models2|test_widgets3|test_shim|test_shim2|test_shim3|test_dnd|test_media|test_gl|test_print|test_text|test_expr|test_constraints|test_shortcuts|test_snapshot|test_adw|test_application) needs_display=1 ;;
+    test_widgets|test_inputs|test_inputs2|test_containers|test_containers2|test_actions|test_closure|test_headerbar|test_filedialog|test_views|test_builder|test_utility|test_css|test_popover|test_dialogs|test_models|test_drawing|test_gestures|test_models2|test_widgets3|test_shim|test_shim2|test_shim3|test_dnd|test_media|test_gl|test_print|test_text|test_expr|test_constraints|test_shortcuts|test_snapshot|test_lastwidgets|test_adw|test_application) needs_display=1 ;;
     *) needs_display=0 ;;
   esac
   if [ "$needs_display" = 1 ] && [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then

+ 118 - 0
tests/test_lastwidgets.mod

@@ -0,0 +1,118 @@
+MODULE test_lastwidgets ;
+
+(*
+   m2-GTK4 test - the last few widgets: GtkAssistant, GtkIconView and
+   GtkEmojiChooser.  Requires a display.
+*)
+
+FROM Gio IMPORT g_application_run, g_application_quit;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkWindow IMPORT gtk_application_window_new, gtk_window_set_child,
+   gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append;
+FROM GtkEnums IMPORT GtkVertical, GtkSelectionMultiple;
+FROM GtkLabel IMPORT gtk_label_new;
+FROM GtkAssistant IMPORT gtk_assistant_new, gtk_assistant_append_page,
+   gtk_assistant_get_n_pages, gtk_assistant_get_nth_page,
+   gtk_assistant_set_page_title, gtk_assistant_set_page_complete,
+   gtk_assistant_set_page_type, gtk_assistant_set_current_page,
+   gtk_assistant_get_current_page, gtk_assistant_previous_page,
+   gtk_assistant_commit, AssistantPageContent;
+FROM GtkIconView IMPORT gtk_icon_view_new, gtk_icon_view_set_columns,
+   gtk_icon_view_get_columns, gtk_icon_view_set_text_column,
+   gtk_icon_view_get_text_column, gtk_icon_view_set_item_width,
+   gtk_icon_view_set_spacing, gtk_icon_view_set_selection_mode;
+FROM GtkEmojiChooser IMPORT gtk_emoji_chooser_new;
+FROM GtkUtils IMPORT Connect;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.TestLastWidgets";
+
+VAR
+   app: ADDRESS;
+   passed: BOOLEAN;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, box, assistant, p1, p2, iconview, emoji: ADDRESS;
+   ok: BOOLEAN;
+BEGIN
+   ok := TRUE;
+
+   (* GtkAssistant *)
+   assistant := gtk_assistant_new();
+   IF assistant = NIL THEN printf("assistant NIL\n"); ok := FALSE END;
+   p1 := gtk_label_new("Step one");
+   p2 := gtk_label_new("Step two");
+   IF gtk_assistant_append_page(assistant, p1) # 0 THEN
+      printf("first page index wrong\n"); ok := FALSE
+   END;
+   IF gtk_assistant_append_page(assistant, p2) # 1 THEN
+      printf("second page index wrong\n"); ok := FALSE
+   END;
+   IF gtk_assistant_get_n_pages(assistant) # 2 THEN
+      printf("assistant page count wrong\n"); ok := FALSE
+   END;
+   IF gtk_assistant_get_nth_page(assistant, 1) # p2 THEN
+      printf("assistant nth page wrong\n"); ok := FALSE
+   END;
+   gtk_assistant_set_page_title(assistant, p1, "One");
+   gtk_assistant_set_page_complete(assistant, p1, 1);
+   gtk_assistant_set_page_type(assistant, p1, AssistantPageContent);
+   gtk_assistant_set_current_page(assistant, 1);
+   IF gtk_assistant_get_current_page(assistant) # 1 THEN
+      printf("assistant current page wrong\n"); ok := FALSE
+   END;
+   gtk_assistant_commit(assistant);
+
+   (* GtkIconView *)
+   iconview := gtk_icon_view_new();
+   IF iconview = NIL THEN printf("icon view NIL\n"); ok := FALSE END;
+   gtk_icon_view_set_columns(iconview, 3);
+   IF gtk_icon_view_get_columns(iconview) # 3 THEN
+      printf("icon view columns wrong\n"); ok := FALSE
+   END;
+   gtk_icon_view_set_text_column(iconview, 0);
+   IF gtk_icon_view_get_text_column(iconview) # 0 THEN
+      printf("icon view text column wrong\n"); ok := FALSE
+   END;
+   gtk_icon_view_set_item_width(iconview, 64);
+   gtk_icon_view_set_spacing(iconview, 6);
+   gtk_icon_view_set_selection_mode(iconview, GtkSelectionMultiple);
+
+   (* GtkEmojiChooser *)
+   emoji := gtk_emoji_chooser_new();
+   IF emoji = NIL THEN printf("emoji chooser NIL\n"); ok := FALSE END;
+
+   box := gtk_box_new(GtkVertical, 4);
+   gtk_box_append(box, iconview);
+   window := gtk_application_window_new(application);
+   gtk_window_set_child(window, box);
+   gtk_window_present(window);
+
+   passed := ok;
+   g_application_quit(application)
+END OnActivate;
+
+VAR
+   rc: INTEGER;
+BEGIN
+   passed := FALSE;
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("test_lastwidgets: FAIL (no app)\n");
+      HALT(1)
+   END;
+   Connect(app, "activate", ADR(OnActivate), NIL);
+   rc := g_application_run(app, 0, NIL);
+
+   IF passed THEN
+      printf("test_lastwidgets: PASS\n");
+      HALT(0)
+   ELSE
+      printf("test_lastwidgets: FAIL\n");
+      HALT(1)
+   END
+END test_lastwidgets.