Code Monkey home page Code Monkey logo

Comments (6)

pavouk avatar pavouk commented on June 8, 2024

Thanks for the reminder.

It is very easy to implement, actually Gtk.Builder:connect_signals_full() is introspectable and can be used as is. The point is of course whether to build some nice facade over it. One way would be something like

Gtk.Builder:connect_to(target)

where target is Lua table containing methods named as handlers in builder XML. This would be also very easy to implement in pure Lua (in override/Gtk.lua), but I'm not entirely convinced if this is the right interface to use.

Btw, 'after' is fine and can be easily supported, 'swapped' makes no sense for lgi and should be ignored. I'm not sure how to approach 'object' (don't even know offhand what it means :-)

If you have any comments, suggestions etc. please don't hesitate to share it here.

from lgi.

PabloCabrera avatar PabloCabrera commented on June 8, 2024

The "object" attribute is usefull to pass an object as "user_data" parameter to the signal handler. This is edited using the Glade user interface.

When you call gtk_connect_signals_full, the third parameter must be another user_data. Was a headache for me to discover the difference between the two user_data's.

The prototype for the connector function is:
void (*GtkBuilderConnectFunc) (GtkBuilder *builder,
GObject *object,
const gchar *signal_name,
const gchar *handler_name,
GObject *connect_object, <------ THIS IS THE RIGHT ONE, FROM GLADE
GConnectFlags flags,
gpointer user_data); <-------- THIS IS THE "ANOTHER", NOT REALLY USEFULL

;-) Happy hacking!

from lgi.

pavouk avatar pavouk commented on June 8, 2024

I'm still a bit skeptical about a real value of all this; the whole GtkBuilder is nice idea at the beginning, but

  • glade sucks, always crashes for me and it was a pain for me to have some real work done in it,
  • manual builder XML editing is just a pain, it is much easier to use Lua-native table-based UI description (see lgi Gtk manual and samples how to do it).
  • autoconnection of signals might be useful for C projects (maybe), but IMHO it brings no advantage to Lua-based development

That said, I've worked on adding this feature. I've modeled it after PyGObject's Gtk.Builder.connect_signals(). Before I submit it, add tests for it and write docs, I'd like you to overview (and possibly also try) it whether it suits your needs (as I explained above, I cannot evaluate it because it is useless for my workflow). The sample including implementation of the feature is here:

t1.lua

local lgi = require 'lgi'
local Gtk = lgi.Gtk

--- ### Once finalized will be moved to lgi.override.Gtk
local log = lgi.log.domain('lgi.Gtk')
function Gtk.Builder._method:connect_signals(obj)
   local unconnected
   self:connect_signals_full(
      function(builder, object, signal, handler, connect_object, flags)
     signal = 'on_' .. signal:gsub('%-', '_')
     local target = obj[handler]
     if not target then
        unconnected = unconnected or {}
        unconnected[#unconnected + 1] = handler
        log.warning("%s: failed to connect to `%s' handler",
            signal, handler)
        return
     end
     local f
     if connect_object then
        f = function(_, ...) return target(connect_object, ...) end
     else
        f = target
     end
     object[signal]:connect(f, nil, flags.AFTER)
      end)
   return unconnected
end
--- ###

local builder = Gtk.Builder()
assert(builder:add_from_file('t1.ui'))

builder:connect_signals {
   clicked1_cb = function(...) print('clicked1_cb', ...) end,
   clicked2_cb = function(...) print('clicked2_cb', ...) end,
   keypress = function(...) print('keypress', ...) end,
}

local w = builder:get_object('window1')
w.on_destroy = Gtk.main_quit
w:show_all()

Gtk.main()

t1.ui

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkLabel" id="label1">
            <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="button1">
            <property name="label" translatable="yes">button</property>
            <property name="use_action_appearance">False</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="use_action_appearance">False</property>
            <signal name="key-press-event" handler="keypress" swapped="no"/>
            <signal name="clicked" handler="clicked1_cb" object="label1" swapped="yes"/>
            <signal name="clicked" handler="clicked2_cb" after="yes" swapped="no"/>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

from lgi.

pavouk avatar pavouk commented on June 8, 2024

Just for completness, I attached functionally-identical example written using Lua-table based UI description.

local lgi = require 'lgi'
local Gtk = lgi.Gtk

local w = Gtk.Window {
   Gtk.Box {
      orientation = 'VERTICAL',
      Gtk.Label {
         id = 'label',
         label = "label",
      },
      Gtk.Button {
         id = 'button',
         label = "button",
      },
   },
}

function w.child.button:on_clicked(...) print('clicked1_cb', w.child.label, ...) end
function w.child.button:on_clicked(...) print('clicked2_cb', self, ...) end
function w.child.button:on_key_press_event(...) print('keypress', ...) end

w.on_destroy = Gtk.main_quit
w:show_all()

Gtk.main()

from lgi.

PabloCabrera avatar PabloCabrera commented on June 8, 2024

"connect_object" should replace "object" only if the SWAPPED flag is on.
In this case, "object" should be passed as second argument
Otherwise, "object" should stay as the original object, and "connect_object" should be passed as second argument.

For a behavior like C code, please rewrite the following lines:

      if connect_object then
         f = function(_, ...) return target(connect_object, ...) end

into:

      if connect_object and flags.SWAPPED then
         f = function(_, _, ...) return target(connect_object, object,  ...) end
      elseif connect_object and not flags.SWAPPED then
         f = function(_, _, ...) return target(object, connect_object, ...)  end

Note: I'm not sure if duplicate underscores is right

from lgi.

pavouk avatar pavouk commented on June 8, 2024

I took some time to think about this and decided that I will go with my previous version. all 'swapped' signal business is not supported by lgi, so it would not make much sense to add support for it here. Moreover, the requested effect can be very easily achieved using closures and upvalues, or by rewriting connect_signals method with your custom one (using connect_signals_full as a base functionality). IMO, all the 'swapped' complexity is poor-man's workaround for C lacking these language features.

Committed to master and closing the issue. Thanks a lot for your input and sorry that I decided to resolve it differently than you recommended.

from lgi.

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.