test_closure.mod 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. MODULE test_closure ;
  2. (*
  3. m2-GTK4 test - per-connection closures (GtkClosures).
  4. Two buttons share one handler but carry independent counters; a
  5. payload is attached to a GSimpleAction through the 3-argument form;
  6. and disconnecting an "owned" connection runs its destroy procedure.
  7. Requires a display and the ISO dialect (-fiso).
  8. *)
  9. FROM Gio IMPORT g_application_run, g_application_quit;
  10. FROM GtkApplication IMPORT gtk_application_new;
  11. FROM GtkWindow IMPORT gtk_application_window_new, gtk_window_set_child;
  12. FROM GtkBox IMPORT gtk_box_new, gtk_box_append;
  13. FROM GtkEnums IMPORT GtkVertical;
  14. FROM GtkButton IMPORT gtk_button_new_with_label;
  15. FROM GObject IMPORT g_signal_emit_by_name, g_signal_handler_disconnect;
  16. FROM GSimpleAction IMPORT g_simple_action_new;
  17. FROM GAction IMPORT g_action_activate;
  18. FROM GtkUtils IMPORT Connect;
  19. FROM GtkClosures IMPORT Connect2, Connect3, Connect2Owned;
  20. FROM SYSTEM IMPORT ADDRESS, CAST, ADR;
  21. FROM Storage IMPORT ALLOCATE, DEALLOCATE;
  22. FROM libc IMPORT printf;
  23. CONST
  24. AppId = "org.example.m2gtk4.TestClosure";
  25. TYPE
  26. Counter = POINTER TO CounterRec;
  27. CounterRec = RECORD
  28. n: INTEGER;
  29. END;
  30. VAR
  31. app: ADDRESS;
  32. passed: BOOLEAN;
  33. ownedDestroyed: BOOLEAN;
  34. PROCEDURE OnClick (instance: ADDRESS; user: ADDRESS);
  35. VAR
  36. c: Counter;
  37. BEGIN
  38. c := CAST(Counter, user);
  39. INC(c^.n)
  40. END OnClick;
  41. PROCEDURE OnGo (instance, param: ADDRESS; user: ADDRESS);
  42. VAR
  43. c: Counter;
  44. BEGIN
  45. c := CAST(Counter, user);
  46. INC(c^.n)
  47. END OnGo;
  48. PROCEDURE DestroyCounter (user: ADDRESS);
  49. VAR
  50. c: Counter;
  51. BEGIN
  52. ownedDestroyed := TRUE;
  53. c := CAST(Counter, user);
  54. DISPOSE(c)
  55. END DestroyCounter;
  56. PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
  57. VAR
  58. window, box, buttonA, buttonB, buttonC, action: ADDRESS;
  59. ca, cb, cc, cgo: Counter;
  60. idC: LONGCARD;
  61. ok: BOOLEAN;
  62. BEGIN
  63. ok := TRUE;
  64. NEW(ca); ca^.n := 0;
  65. NEW(cb); cb^.n := 0;
  66. NEW(cgo); cgo^.n := 0;
  67. (* two connections, one handler, independent state *)
  68. buttonA := gtk_button_new_with_label("A");
  69. buttonB := gtk_button_new_with_label("B");
  70. Connect2(buttonA, "clicked", OnClick, CAST(ADDRESS, ca));
  71. Connect2(buttonB, "clicked", OnClick, CAST(ADDRESS, cb));
  72. g_signal_emit_by_name(buttonA, "clicked");
  73. g_signal_emit_by_name(buttonA, "clicked");
  74. g_signal_emit_by_name(buttonB, "clicked");
  75. IF ca^.n # 2 THEN printf("button A count wrong\n"); ok := FALSE END;
  76. IF cb^.n # 1 THEN printf("button B count wrong\n"); ok := FALSE END;
  77. (* 3-argument form: action "activate" carries a parameter *)
  78. action := g_simple_action_new("go", NIL);
  79. Connect3(action, "activate", OnGo, CAST(ADDRESS, cgo));
  80. g_action_activate(action, NIL);
  81. IF cgo^.n # 1 THEN printf("action count wrong\n"); ok := FALSE END;
  82. (* owned connection: destroy runs on explicit disconnect *)
  83. NEW(cc); cc^.n := 0;
  84. ownedDestroyed := FALSE;
  85. buttonC := gtk_button_new_with_label("C");
  86. idC := Connect2Owned(buttonC, "clicked", OnClick,
  87. CAST(ADDRESS, cc), DestroyCounter);
  88. g_signal_emit_by_name(buttonC, "clicked");
  89. IF cc^.n # 1 THEN printf("owned count wrong\n"); ok := FALSE END;
  90. g_signal_handler_disconnect(buttonC, idC);
  91. IF NOT ownedDestroyed THEN printf("destroy not called\n"); ok := FALSE END;
  92. box := gtk_box_new(GtkVertical, 4);
  93. gtk_box_append(box, buttonA);
  94. gtk_box_append(box, buttonB);
  95. gtk_box_append(box, buttonC);
  96. window := gtk_application_window_new(application);
  97. gtk_window_set_child(window, box);
  98. passed := ok;
  99. g_application_quit(application)
  100. END OnActivate;
  101. VAR
  102. rc: INTEGER;
  103. BEGIN
  104. passed := FALSE;
  105. app := gtk_application_new(AppId, 0);
  106. IF app = NIL THEN
  107. printf("test_closure: FAIL (no app)\n");
  108. HALT(1)
  109. END;
  110. Connect(app, "activate", ADR(OnActivate), NIL);
  111. rc := g_application_run(app, 0, NIL);
  112. IF passed THEN
  113. printf("test_closure: PASS\n");
  114. HALT(0)
  115. ELSE
  116. printf("test_closure: FAIL\n");
  117. HALT(1)
  118. END
  119. END test_closure.