example-06-table.scm 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. ;;; Example adapted from:
  2. ;;; https://github.com/spk121/guile-gi/files/7915746/gtk-tree-store.scm.txt
  3. ;;; Some formatting by me. Most comments by me.
  4. (import (gi)
  5. (gi repository)
  6. (gi types)
  7. (gi util)
  8. ;; receive multiple values
  9. (ice-9 receive)
  10. (prefix (srfi srfi-1) srfi-1:))
  11. ;; guile-gi internally creates GOOPS classes for GTK and other GObject
  12. ;; Introspection things. Methods of such classes can have the same name. The
  13. ;; question is how those methods are named, when importing methods of same name
  14. ;; into the same module. The following like tells Guile how to handle that
  15. ;; case. For more detail see:
  16. ;; https://www.gnu.org/software/guile/manual/html_node/Merging-Generics.html
  17. (push-duplicate-handler! 'merge-generics)
  18. (use-typelibs ("GLib" "2.0")
  19. ;; Which thing is renamed to what?
  20. (("Gio" "2.0") #:renamer (protect* '(application:new receive)))
  21. ;; Which thing is renamed to what?
  22. (("Gtk" "3.0") #:renamer (protect* '(tree-store:new) 'gtk::))
  23. ("Gdk" "3.0"))
  24. (define treeview-append-column
  25. (lambda* (treeview
  26. column
  27. model-column-index
  28. renderer
  29. renderer-attribute
  30. title
  31. #:key
  32. (pack 'start)
  33. (expand #f))
  34. (set-title column title)
  35. ;; Make the rendered content align to the start or end
  36. ;; and either make the column "expand" or not expand to
  37. ;; take available space, if more space exists, than the
  38. ;; rendered content would require.
  39. (when (eq? pack 'start)
  40. ;; See: https://docs.gtk.org/gtk3/method.TreeViewColumn.pack_start.html
  41. (pack-start column renderer expand))
  42. (when (eq? pack 'end)
  43. (pack-end column renderer expand))
  44. ;; See: https://docs.gtk.org/gtk3/method.TreeViewColumn.add_attribute.html
  45. (add-attribute
  46. ;; Specify the GtkTreeViewColumn widget, of which the
  47. ;; contents shall be rendered. This first the GOOPS
  48. ;; object to work with. add-attribute is like a method,
  49. ;; which expects as its first argument the object,
  50. ;; which it does belong to. This is like calling the
  51. ;; add-attribute method of the GtkTreeViewColumn
  52. ;; widget.
  53. column
  54. ;; Specify which GtkCellRenderer to use for the
  55. ;; GtkTreeViewColumn.
  56. renderer
  57. ;; Tell the GtkCellRenderer to get the value for its
  58. ;; "text" attribute.
  59. renderer-attribute
  60. ;; Tell the GtkCellRenderer to get the value of its
  61. ;; "text" attribute from column 0 of "the model" of the
  62. ;; GtkTreeModel. The GtkTreeModel is not known at the
  63. ;; time of this call, because the column has not yet
  64. ;; been appended to a GtkTreeView. However, once it is
  65. ;; appended to a GtkTreeView it will know where to get
  66. ;; the value from, which it will let the
  67. ;; GtkCellRenderer render.
  68. ;; Question: What sense would it make to not choose the
  69. ;; column in the model at the same index, as this
  70. ;; column is going to be added? Answer: Column widgets
  71. ;; may be shifted around, while the model, which holds
  72. ;; the data keeps indices unchanged. This means that
  73. ;; the index given here will keep pointing to the same
  74. ;; data, unless the data itself is changed.
  75. model-column-index)
  76. ;; Add the column to the tree view.
  77. (append-column treeview column)))
  78. (define (activate app)
  79. (let* (#|main window|#
  80. [window (application-window:new app)]
  81. ;; layout manager: grid layout
  82. [grid (grid:new)]
  83. [store
  84. ;; Create a store, which accepts the types, which
  85. ;; the columns will contain. The store will back
  86. ;; the tree view and contain the actual data. The
  87. ;; data will be rendered by renderers, which one
  88. ;; needs to specify. The rendered data will be
  89. ;; displayed in the tree view.
  90. (gtk::tree-store:new (vector G_TYPE_INT G_TYPE_STRING G_TYPE_STRING))]
  91. [treeview (tree-view:new-with-model store)]
  92. [column-titles '("Column 1" "Column 2" "Column 3")]
  93. [column-renderer-attributes '("text" "text" "text")]
  94. #;[data ])
  95. ;; Connect the window delete event with a closure, which
  96. ;; destroys the window and quits the main loop.
  97. (connect window
  98. delete-event
  99. ;; The callback gets 2 arguments. The widget
  100. ;; from which the event originated and the
  101. ;; event itself.
  102. (λ (window event)
  103. (gtk-widget-destroy window)
  104. (gtk-main-quit)
  105. #f)) ;; do not stop the event propagation
  106. (let loop ([index 0]
  107. [titles column-titles]
  108. [renderer-attributes column-renderer-attributes])
  109. (cond
  110. [(null? titles) 'done]
  111. [else
  112. (let ([title (srfi-1:first titles)]
  113. [renderer-attribute (srfi-1:first renderer-attributes)])
  114. (treeview-append-column treeview
  115. (tree-view-column:new)
  116. index
  117. (cell-renderer-text:new)
  118. renderer-attribute
  119. title
  120. #:pack 'start #:expand #t))
  121. (loop (+ index 1)
  122. (srfi-1:drop titles 1)
  123. (srfi-1:drop renderer-attributes 1))]))
  124. (let ([iter (make <GtkTreeIter>)]
  125. [val1 (make <GValue>)]
  126. [val2 (make <GValue>)])
  127. ;; Set an integer value to val1.
  128. (set! (val1 G_TYPE_INT) 0)
  129. ;; Set an integer value to val2.
  130. (set! (val2 G_TYPE_STRING) "hello world")
  131. ;; Insert the values into the store, which is backing
  132. ;; the tree view.
  133. (tree-store:insert-with-values! store
  134. iter
  135. #f
  136. 0
  137. (list->int-vector '(0 1))
  138. (vector val1 val2)))
  139. ;; Compose widgets.
  140. (add window grid)
  141. (add grid treeview)
  142. ;; Display the whole thing.
  143. (show-all window)))
  144. (define (main)
  145. (let ((app (application:new "org.gtk.example" (number->application-flags 0))))
  146. ;; Connect the application:activate function/method with the activate
  147. ;; function defined above.
  148. (connect app application:activate activate)
  149. (exit
  150. ;; Call application:run. If there are no arguments in the command line
  151. ;; args, this will send the `activate' signal.
  152. (run app (command-line)))))
  153. (main)