Ferada / cl-cffi-gtk

#cl-cffi-gtk on Freenode. A Lisp binding to GTK+3. SBCL/CCL/ABCL (ECL/CLISP unstable)
http://www.crategus.com/books/cl-cffi-gtk
41 stars 8 forks source link

Can't use positive Response ID's in GtkDialog #23

Closed kierangrant closed 6 years ago

kierangrant commented 6 years ago

gtk-response-type is defined as a foreign enum with fixed negative values. But GTK Docs says all positive values or allowed and are reserved to the user. The way gtk-response-type is implemented in gtk/gtk.dialog.lisp prevents this. You get an error when setting response ID or if one is returned not within scope of: "... is not defined as a value for enum type #<CFFI::FOREIGN-ENUM GTK:GTK-RESPONSE-TYPE>." For example, in a signal handler for a custom widget in a dialog:

(defun preferencs->apply (widget)
  (declare (ignore widget))
  (format t "Applying Preferencs~%!")
  (gtk-dialog-response (get-handle :preferences :dialog) 1)

Errors when selecting the button associated with this callback.

Is there a way to define it so we can still use the enum technique on responses and when passing, but also allow user defined values?

Might require the defcfun function being used indirectly... like

(defcfun ("gtk_dialog_response" %gtk-dialog-response) :void
  (dialog (g-object gtk-dialog))
  (response-id :int))

(defun gtk-dialog-response (dialog response-id)
  (%gtk-dialog-response
   dialog
   (case response-id
     (:none -1)
     (:reject -2)
     (:accept -3)
     (:delete-event -4)
     (:ok -5)
     (:cancel -6)
     (:close -7)
     (:yes -8)
     (:no -9)
     (:apply -10)
     (:help -11)
     (t response-id))))

(export 'gtk-dialog-response)

(defcfun ("gtk_dialog_run" %gtk-dialog-run) :int
  (dialog (g-object gtk-dialog)))

(defun gtk-dialog-run (dialog)
  (let ((response (%gtk-dialog-run dialog)))
    (case response
      (-1 :none)
      (-2 :reject)
      (-3 :accept)
      (-4 :delete-event)
      (-5 :ok)
      (-6 :cancel)
      (-7 :close)
      (-8 :yes)
      (-9 :no)
      (-10 :apply)
      (-11 :help)
      (t response))))

(export 'gtk-dialog-run)

There are other functions with the same problem.

Ferada commented 6 years ago

Sure sounds good to do it indirectly, except that I don't want to duplicate the case statements, I'd like to find a way that the case statements don't have to be duplicated from the enumeration definition though.

kierangrant commented 6 years ago

Fair point, I made a simple patch to fix (hopefully) all uses to use case statements... https://github.com/kierangrant/cl-cffi-gtk/commit/a25c15b48aebfbbbf38c77bdac123df558733f8b I don't know how we can eliminate the duplication though... Maybe a macro to define these "special" enum's that are open ended?

Ferada commented 6 years ago

I think you can get the range of the enums from CFFI, maybe via that, test for lower/upper range and use the "native" CFFI conversion if so.

kierangrant commented 6 years ago

Yes, looks like foreign-enum-keyword and foreign-enum-value could be used. If we get an error getting the value from enum or finding enum for value, we could then pass the user's value directly...

Ferada commented 6 years ago

Hmm yeah, I was thinking that CFFI had a better option. Anyway, yes, I'd say do it like that, that keeps the code short and it might be possible to optimise it later.

kierangrant commented 6 years ago

Better approach: https://github.com/Ferada/cl-cffi-gtk/compare/master...kierangrant:attempt-to-fix-issue-23

Ferada commented 6 years ago

Cool, PR? Otherwise I'll take that branch later and merge it.

Ferada commented 6 years ago

Merged, thank you!

kierangrant commented 6 years ago

Yeah, sure... went out of my timezone... I'm awake now! :) I'm using this library for a cross-platform GTK app for work... I don't see any problems on Windows 10 so far, but developing on Linux... Though I am currently using very old GTK on Winodws (3.10)... I will need to fetch a new version from msys2 project...