Skip to content
This repository has been archived by the owner on Jul 26, 2021. It is now read-only.

Connect the signals to the protocol of a class #47

Open
asarch opened this issue Jul 28, 2020 · 1 comment
Open

Connect the signals to the protocol of a class #47

asarch opened this issue Jul 28, 2020 · 1 comment

Comments

@asarch
Copy link

asarch commented Jul 28, 2020

If you would have:

dialog.glade

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkDialog" id="dialog">
    <property name="can_focus">False</property>
    <property name="type_hint">dialog</property>
    <child>
      <placeholder/>
    </child>
    <child internal-child="vbox">
      <object class="GtkBox">
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">2</property>
        <child internal-child="action_area">
          <object class="GtkButtonBox">
            <property name="can_focus">False</property>
            <property name="layout_style">end</property>
            <child>
              <object class="GtkButton" id="cancel">
                <property name="label">gtk-cancel</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="use_stock">True</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="apply">
                <property name="label">gtk-apply</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="use_stock">True</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <property name="spacing">5</property>
            <child>
              <object class="GtkLabel" id="label">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">label</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="button">
                <property name="label">gtk-yes</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="use_stock">True</property>
                <signal name="clicked" handler="saludo" swapped="no"/>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="padding">5</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

and this piece of code:

(ql:quickload :cl-cffi-gtk)

(defpackage :aplicacion
  (:use :gtk :gdk :gdk-pixbuf :gobject
	:glib :gio :pango :cairo :common-lisp))

(in-package :aplicacion)

(defclass beer ()
  ((widget :initarg :widget :initform nil :accessor widget)
   (boton :initarg :boton :initform nil :accessor boton)))

(defgeneric cheers (beer))

(defmethod cheers ((instance beer))
  (format t "Click!~%"))

(defmethod initialize-instance :after ((instance beer) &key)
  (let ((builder (make-instance 'gtk-builder)))
    (gtk-builder-add-from-file builder "dialog.glade")
    (setf (widget instance) (gtk-builder-get-object builder "dialog"))
    (setf (boton instance) (gtk-builder-get-object builder "button")))
  (g-signal-connect (widget instance) "destroy" (lambda (msg) (declare (ignore msg)) (leave-gtk-main)))
  (g-signal-connect (boton instance) "clicked" (lambda (msg) (declare (ignore msg) (cheers instance)))))

(within-main-loop
 (let ((app (make-instance 'beer)))
   (gtk-widget-show-all (widget app))))

How would you connect the "clicked" signal to the cheers function of the class' protocol without actually using anonymous functions (just like the gtk-builder-connect-signals function to the package does)?

@Ferada
Copy link
Owner

Ferada commented Jul 28, 2020

Well, the problem is that the handler receives the msg, no? I suppose that's also why there's no library function for it yet, no clear idea of how this should look like.

Something like (g-signal-connect-instance (boton instance) #'cheers)?

Though of course now you'd likely have to have a way of specifying where event arguments go in the call. Or they're always discarded? I don't see how that's a good case to make for a dedicated function. But maybe I'm wrong. Could you write up how you'd deal with those cases, or why it's not a problem?

There are also some libraries to generate anonymous functions more succinctly, maybe that's another way of approaching it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants