Giter Club home page Giter Club logo

Comments (25)

bohonghuang avatar bohonghuang commented on August 20, 2024 1

Also, why did we have to put a (let ((i index))) around tthe bind lambda function?

Since the loop variables in loop are mutable in most implementations, we need to make the closure immutably capture the index so that different columns can access data with different column indexes.

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024 1

I wasn't even using that version of cl-gobject-introspection. I spend hours debuggin that, It works now, thanks a bunch!

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

The (gobject:type-from-name "GtkLabel") in your code returns 0, which causes (gtk:make-list-store ...) to return a null pointer.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

To make (gobject:type-from-name "GtkLabel") return a non-zero value, you need to get this type registered by the GObject system first. For example, you can move the (item1 (make-label :str "BRUHSEIDh")) or add a seemingly meaningless (gtk:make-label :str "") before it.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

BTW, Gtk.ListStore has been deprecated in version 4.10, and you should use gio:make-list-store to create it instead.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

I just added an example of a ListView for your reference:

cl-gtk4/examples/gtk4.lisp

Lines 187 to 230 in ee766c2

(define-application (:name string-list-view
:id "org.bohonghuang.gtk4-example.string-list-view")
(define-main-window (window (make-application-window :application *application*))
(let ((box (make-box :orientation +orientation-vertical+ :spacing 1)))
(let* ((model (make-string-list :strings (loop :for i :from 1 :to 10 :collect (format nil "Item ~D" i))))
(factory (make-signal-list-item-factory))
(list-view (make-list-view :model (make-single-selection :model model) :factory factory)))
(flet ((setup (factory item)
(declare (ignore factory))
(setf (list-item-child item) (make-label :str "")))
(bind (factory item)
(declare (ignore factory))
(setf (label-text (gobj:coerce (list-item-child item) 'label))
(string-object-string (gobj:coerce (list-item-item item) 'string-object))))
(unbind (factory item)
(declare (ignore factory item)))
(teardown (factory item)
(declare (ignore factory item))))
(connect factory "setup" #'setup)
(connect factory "bind" #'bind)
(connect factory "unbind" #'unbind)
(connect factory "teardown" #'teardown))
(let ((scrolled-window (make-scrolled-window)))
(setf (widget-size-request scrolled-window) '(250 250)
(widget-vexpand-p scrolled-window) t
(widget-hexpand-p scrolled-window) t
(scrolled-window-child scrolled-window) list-view)
(box-append box scrolled-window))
(let ((button-append (make-button :label "Append"))
(button-remove (make-button :label "Remove")))
(connect button-append "clicked" (lambda (button)
(declare (ignore button))
(string-list-append model (format nil "Item ~D" (1+ (gio:list-model-n-items model))))))
(box-append box button-append)
(connect button-remove "clicked" (lambda (button)
(declare (ignore button))
(when (plusp (gio:list-model-n-items model))
(string-list-remove model (1- (gio:list-model-n-items model))))))
(box-append box button-remove)))
(setf (window-title window) "String List View"
(window-child window) box
(window-default-size window) '(300 300)))
(unless (widget-visible-p window)
(window-present window))))

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Thank you so much! I wasn't expecting an answer. That's awesome, I will try it out right now.

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

In your example, gobj:coerce is not found. I will try and download from latest commit.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

In your example, gobj:coerce is not found. I will try and download from latest commit.

It's in cl-glib. You may need to clone it manually or update your Ultralisp distribution.

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Yup, I cloned cl-gtk4 and cl-glib and the example works now.

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Okay, so ultimately I wanted to create a GtkColumnView. I got to this code:

(gtk:define-application (:name closting
                         :id "com.closting")
  (gtk:define-main-window (window (gtk:make-application-window :application gtk:*application*))
    (setf (gtk:window-title window) "Closting")
    (let* ((main-model (gtk:make-string-list :strings '("HP Zbook 15" "250$" "300$"
                                                        "Infinix S90" "40$" "60$"
                                                        "Casio Calculator" "50$" "80$")))
           (column-view (gtk:make-column-view :model (gtk:make-single-selection :model main-model)))
           (col1-factory (gtk:make-signal-list-item-factory))
           (col1 (gtk:make-column-view-column :title "First Col!" :factory col1-factory))
           (col2-factory (gtk:make-signal-list-item-factory))
           (col2 (gtk:make-column-view-column :title "Second Col!" :factory col2-factory))
           (col3-factory (gtk:make-signal-list-item-factory))
           (col3 (gtk:make-column-view-column :title "Third Col!" :factory col3-factory)))
      (gtk:column-view-append-column column-view col1)
      (gtk:column-view-append-column column-view col2)
      (gtk:column-view-append-column column-view col3)
      (setf (gtk:widget-vexpand-p column-view) t
            (gtk:widget-hexpand-p column-view) t)
      (flet ((setup (factory item)
               (declare (ignore factory))
               (setf (gtk:list-item-child item) (gtk:make-label :str "")))
             (bind (factory item) 
               (declare (ignore factory))
               (format t "POSSSS: ~a~%" (gtk:list-item-position item))
               (when (zerop (mod (1+ (gtk:list-item-position item)) 3))
                 (setf (gtk:label-text (gobj:coerce (gtk:list-item-child item) 'gtk:label))
                       (gobj:value-string (gobj:coerce (gtk:list-item-item item) 'gtk:string-object)))))
             (unbind (factory item) (declare (ignore factory item)))
             (teardown (factory item) (declare (ignore factory item))))
        (gtk:connect col1-factory "setup" #'setup)
        (gtk:connect col1-factory "bind" #'bind)
        (gtk:connect col1-factory "unbind" #'unbind)
        (gtk:connect col1-factory "teardown" #'teardown))
      (setf (gtk:window-child window) column-view))
    (unless (gtk:widget-visible-p window)
      (gtk:window-present window))))

But instead of getting every third value in each cell. I get a lot of blank cells. What I need is to somehow skip over elements in the model. Or how should I go about just creating a simple column view at all? Maybe I am doing it wrong. Also kindly inform me if this comment is out of the scope of this issue. I figured it isn't as ColumnView uses ListView. Thanks

Regards,
Hamza

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

You can use StringList as the elements of your ListModel:

(gtk:define-application (:name closting
                         :id "com.closting")
  (gtk:define-main-window (window (gtk:make-application-window :application gtk:*application*))
    (setf (gtk:window-title window) "Closting")
    (let* ((rows (loop :for row :in '(("HP Zbook 15" "250$" "300$")
                                      ("Infinix S90" "40$" "60$")
                                      ("Casio Calculator" "50$" "80$"))
                       :collect (gtk:make-string-list :strings row)))
           (main-model (gio:make-list-store :item-type (gobj:type-from-name "GtkStringList")))
           (column-view (gtk:make-column-view :model (gtk:make-single-selection :model main-model)))
           (col1-factory (gtk:make-signal-list-item-factory))
           (col1 (gtk:make-column-view-column :title "First Col!" :factory col1-factory))
           (col2-factory (gtk:make-signal-list-item-factory))
           (col2 (gtk:make-column-view-column :title "Second Col!" :factory col2-factory))
           (col3-factory (gtk:make-signal-list-item-factory))
           (col3 (gtk:make-column-view-column :title "Third Col!" :factory col3-factory)))
      (gtk:column-view-append-column column-view col1)
      (gtk:column-view-append-column column-view col2)
      (gtk:column-view-append-column column-view col3)
      (loop :for row :in rows :do (gio:list-store-append main-model row))
      (setf (gtk:widget-vexpand-p column-view) t
            (gtk:widget-hexpand-p column-view) t)
      (flet ((setup (factory item)
               (declare (ignore factory))
               (setf (gtk:list-item-child item) (gtk:make-label :str "")))
             (unbind (factory item) (declare (ignore factory item)))
             (teardown (factory item) (declare (ignore factory item))))
        (loop :for factory :in (list col1-factory col2-factory col3-factory)
              :for index :from 0
              :do (gtk:connect factory "setup" #'setup)
                  (gtk:connect factory "unbind" #'unbind)
                  (gtk:connect factory "teardown" #'teardown)
                  (gtk:connect factory "bind"
                               (let ((i index))
                                 (lambda (factory item) 
                                   (declare (ignore factory))
                                   (setf (gtk:label-text (gobj:coerce (gtk:list-item-child item) 'gtk:label))
                                         (gtk:string-list-get-string (gobj:coerce (gtk:list-item-item item) 'gtk:string-list) i)))))))
      (setf (gtk:window-child window) column-view))
    (unless (gtk:widget-visible-p window)
      (gtk:window-present window))))

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Thanks a lot! Just one final question, do you have any idea of how to store custom types in a list store? For example:
Instead of every row being a StringList, how can I make it something like:

(defclass product-info (gobject:object)
  ((name :initarg :name
		 :accessor name)
   (cost :initarg :cost
		 :accessor cost)
   (sale :initarg :sale
		 :accessor sale)))

This does not work as it says something about gobject:object being a forward referenced class, whatever that means...

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

If you don't require eql to guarantee object equality, using print1-to-string and read-from-string seems to be the simplest way. Otherwise, you may need some mechanism to identify objects. For example:

  1. You can put objects in an array and use the array index to retrieve the object.
  2. Use a UUID library or similar to generate a unique integer or string identifier for an object, and use it as a key in a hash table to retrieve the object.

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Also, why did we have to put a (let ((i index))) around tthe bind lambda function?

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

If you don't require eql to guarantee object equality, using print1-to-string and read-from-string seems to be the simplest way. Otherwise, you may need some mechanism to identify objects. For example:

  1. You can put objects in an array and use the array index to retrieve the object.
  2. Use a UUID library or similar to generate a unique integer or string identifier for an object, and use it as a key in a hash table to retrieve the object.

Wait, so what does equality have to do with having custom types?

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

Wait, so what does equality have to do with having custom types?

(eql (read-from-string (prin1-to-string '(1 2 3))) '(1 2 3)) ; => NIL
(equal (read-from-string (prin1-to-string '(1 2 3))) '(1 2 3)) ; => T

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Okay, I get that, but I still don't understand how I would go about implementing this to make a new custom type.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

This is a simple way you can use when you don't need eql to guarantee object equality:

(defstruct product-info
  name cost sale)

(gtk:define-application (:name closting
                         :id "com.closting")
  (gtk:define-main-window (window (gtk:make-application-window :application gtk:*application*))
    (setf (gtk:window-title window) "Closting")
    (let* ((rows (loop :for (name cost sale) :in '(("HP Zbook 15" "250$" "300$")
                                                   ("Infinix S90" "40$" "60$")
                                                   ("Casio Calculator" "50$" "80$"))
                       :collect (prin1-to-string (make-product-info :name name :cost cost :sale sale))))
           (main-model (gtk:make-string-list :strings rows))
           (column-view (gtk:make-column-view :model (gtk:make-single-selection :model main-model)))
           (col1-factory (gtk:make-signal-list-item-factory))
           (col1 (gtk:make-column-view-column :title "First Col!" :factory col1-factory))
           (col2-factory (gtk:make-signal-list-item-factory))
           (col2 (gtk:make-column-view-column :title "Second Col!" :factory col2-factory))
           (col3-factory (gtk:make-signal-list-item-factory))
           (col3 (gtk:make-column-view-column :title "Third Col!" :factory col3-factory)))
      (gtk:column-view-append-column column-view col1)
      (gtk:column-view-append-column column-view col2)
      (gtk:column-view-append-column column-view col3)
      (setf (gtk:widget-vexpand-p column-view) t
            (gtk:widget-hexpand-p column-view) t)
      (flet ((setup (factory item)
               (declare (ignore factory))
               (setf (gtk:list-item-child item) (gtk:make-label :str "")))
             (unbind (factory item) (declare (ignore factory item)))
             (teardown (factory item) (declare (ignore factory item))))
        (loop :for factory :in (list col1-factory col2-factory col3-factory)
              :for accessor :in (list #'product-info-name #'product-info-cost #'product-info-sale)
              :do (gtk:connect factory "setup" #'setup)
                  (gtk:connect factory "unbind" #'unbind)
                  (gtk:connect factory "teardown" #'teardown)
                  (gtk:connect factory "bind"
                               (let ((accessor accessor))
                                 (lambda (factory item) 
                                   (declare (ignore factory))
                                   (let ((row (read-from-string (gtk:string-object-string (gobj:coerce (gtk:list-item-item item) 'gtk:string-object)))))
                                     (setf (gtk:label-text (gobj:coerce (gtk:list-item-child item) 'gtk:label)) (funcall accessor row))))))))
      (setf (gtk:window-child window) column-view))
    (unless (gtk:widget-visible-p window)
      (gtk:window-present window))))

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Ohhhhhhh, Thanks once again! I couldn't have thought of that.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

If you want to get the same object under EQL comparison, or other unreadable objects in the bind signal handler, I prefer using UUIDs to identify objects:

(defstruct product-info
  name cost sale)

(gtk:define-application (:name closting
                         :id "com.closting")
  (gtk:define-main-window (window (gtk:make-application-window :application gtk:*application*))
    (setf (gtk:window-title window) "Closting")
    (let ((product-table (make-hash-table :test #'equal)))
      (let* ((rows (loop :for (name cost sale) :in '(("HP Zbook 15" "250$" "300$")
                                                     ("Infinix S90" "40$" "60$")
                                                     ("Casio Calculator" "50$" "80$"))
                         :for product-info := (make-product-info :name name :cost cost :sale sale)
                         :for uuid := (prin1-to-string (uuid:make-v1-uuid))
                         :do (setf (gethash uuid product-table) product-info)
                         :collect uuid))
             (main-model (gtk:make-string-list :strings rows))
             (column-view (gtk:make-column-view :model (gtk:make-single-selection :model main-model)))
             (col1-factory (gtk:make-signal-list-item-factory))
             (col1 (gtk:make-column-view-column :title "First Col!" :factory col1-factory))
             (col2-factory (gtk:make-signal-list-item-factory))
             (col2 (gtk:make-column-view-column :title "Second Col!" :factory col2-factory))
             (col3-factory (gtk:make-signal-list-item-factory))
             (col3 (gtk:make-column-view-column :title "Third Col!" :factory col3-factory)))
        (gtk:column-view-append-column column-view col1)
        (gtk:column-view-append-column column-view col2)
        (gtk:column-view-append-column column-view col3)
        (setf (gtk:widget-vexpand-p column-view) t
              (gtk:widget-hexpand-p column-view) t)
        (flet ((setup (factory item)
                 (declare (ignore factory))
                 (setf (gtk:list-item-child item) (gtk:make-label :str "")))
               (unbind (factory item) (declare (ignore factory item)))
               (teardown (factory item) (declare (ignore factory item))))
          (loop :for factory :in (list col1-factory col2-factory col3-factory)
                :for accessor :in (list #'product-info-name #'product-info-cost #'product-info-sale)
                :do (gtk:connect factory "setup" #'setup)
                    (gtk:connect factory "unbind" #'unbind)
                    (gtk:connect factory "teardown" #'teardown)
                    (gtk:connect factory "bind"
                                 (let ((accessor accessor))
                                   (lambda (factory item) 
                                     (declare (ignore factory))
                                     (let* ((uuid (gtk:string-object-string (gobj:coerce (gtk:list-item-item item) 'gtk:string-object)))
                                            (row (gethash uuid product-table)))
                                       (setf (gtk:label-text (gobj:coerce (gtk:list-item-child item) 'gtk:label)) (funcall accessor row))))))))
        (setf (gtk:window-child window) column-view)))
    (unless (gtk:widget-visible-p window)
      (gtk:window-present window))))

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Oh, that's a really cool solution. Will definitely use that!

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Okay, even though you closed this, I get unhandled memory errors from this:

(defun create-financial-module-column-view (columns data)
  (let* ((string-list-data (loop :for row :in data
                                 :collect (gtk:make-string-list :strings row)))
         (main-model (gio:make-list-store :item-type (gobj:type-from-name "GtkStringList")))
         (column-view (gtk:make-column-view :model (gtk:make-single-selection :model main-model))))
    (setf (gtk:widget-vexpand-p column-view) t
          (gtk:widget-hexpand-p column-view) t)
    ;; TEMPORARY
    (setf (gtk:column-view-reorderable-p column-view) t)
    (loop :for row :in string-list-data
          :do (gio:list-store-append main-model row))
    (loop :for column-name :in columns
          :for index :from 0
          :do (let* ((col-factory (gtk:make-signal-list-item-factory))
                     (column (gtk:make-column-view-column :title column-name :factory col-factory)))
                (setf (gtk:column-view-column-resizable-p column) t)
                (flet ((setup (factory item)
                         (declare (ignore factory))
                         (setf (gtk:list-item-child item) (gtk:make-label :str "DEFAULT")))
                       (unbind (factory item) (declare (ignore factory item)))
                       (teardown (factory item) (declare (ignore factory item))))
                  (gtk:connect col-factory "setup" #'setup)
                  (gtk:connect col-factory "unbind" #'unbind)
                  (gtk:connect col-factory "teardown" #'teardown)
                  (gtk:connect col-factory "bind" ;(lambda (factory item) (declare (ignore factory item)))
                               (let ((i index))
                                 (lambda (factory item)
                                   (declare (ignore factory))
                                   (format t "PLEAAAAAASEWORKKKK: ~a~%" (gobj:coerce (gtk:list-item-child item) 'gtk:label))
                                   ;; (setf (gtk:label-text (gobj:coerce (gtk:list-item-child item) 'gtk:label))
                                   ;;        (format nil "BRUHRHRUHRUHRUHR, ~a~%" i)
                                   ;;        ;; (gtk:string-list-get-string (gobj:coerce (gtk:list-item-item item)
                                   ;;        ;;                                           'gtk:string-list)
                                   ;;        ;;                              i)
                                   ;;        )
                                   ))))
                (gtk:column-view-append-column column-view column)))
    column-view))

I narrowed the error down to using gobj:coerce to convert from (gtk:list-item-item item) to 'gtk:label. Why does this happen? As a hint, when run another time, it runs normally. Weirdly this causes annoying sbcl errors and I have to restart the REPL.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on August 20, 2024

This may be a memory issue caused by the garbage collector. Please refer to #20 (comment). Could you update cl-gobject-introspection and try again?

from cl-gtk4.

hamzashahid-blit avatar hamzashahid-blit commented on August 20, 2024

Okay.

from cl-gtk4.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.