[Gtk-sharp-list] Re: ButtonPressEvent in 0.15

Ecmel Ercan ecmel@ercansoy.com
Fri, 16 Jan 2004 11:07:30 +0200


>> I am developing an application and now I can't do context menus :(
>>
>> Please help,


Hi,

I made a workaround using 0.15 hope helps:

using System;
using System.Collections;
using Gtk;
using GtkSharp;
using System.Runtime.InteropServices;

public class ProjectTree : TreeView
{
    static GLib.GType gtype = GLib.GType.Invalid;
    public static new GLib.GType GType {
        get
        {
            if (gtype == GLib.GType.Invalid)
                gtype = RegisterGType (typeof (ProjectTree));
            return gtype;
        }
    }

    public ProjectTree () : base (GType)
    {

    }

    /* This segfaults
    protected override bool OnButtonPressEvent (ref Gdk.EventButton evnt)
    {
        Console.WriteLine ("Hello");
        base.OnButtonPressEvent (ref evnt);
        return false;
    }
    */

    //
    // CONNECT_AFTER WORKAROUND
    // This Works

    private Hashtable Signals = new Hashtable();

    [GLib.Signal("button_press_event")]
    public new event ButtonPressEventHandler ButtonPressEvent
    {
        add
        {
            if (EventList["button_press_event"] == null)
                Signals["button_press_event"] = new boolObjectEventButtonSignal(this, Handle, "button_press_event", value, System.Type.GetType("GtkSharp.ButtonPressEventArgs,gtk-sharp"));
            else
                ((GtkSharp.SignalCallback) Signals ["button_press_event"]).AddDelegate (value);

            EventList.AddHandler("button_press_event", value);
        }
        remove
        {
            EventList.RemoveHandler("button_press_event", value);
            GtkSharp.SignalCallback cb = Signals ["button_press_event"] as GtkSharp.SignalCallback;
            if (cb == null)
                return;

            cb.RemoveDelegate (value);

            if (EventList["button_press_event"] == null)
            {
                Signals.Remove("button_press_event");
                cb.Dispose ();
            }
        }
    }

    private delegate bool boolObjectEventButtonDelegate(IntPtr arg0, ref Gdk.EventButton arg1, int key);

    private class boolObjectEventButtonSignal : SignalCallback
    {
        private static boolObjectEventButtonDelegate _Delegate;

        private IntPtr _raw;
        private uint _HandlerID;

        private static bool boolObjectEventButtonCallback(IntPtr arg0, ref Gdk.EventButton arg1, int key)
        {
            if (!_Instances.Contains(key))
                throw new Exception("Unexpected signal key " + key);

            boolObjectEventButtonSignal inst = (boolObjectEventButtonSignal) _Instances[key];
            SignalArgs args = (SignalArgs) Activator.CreateInstance (inst._argstype);
            args.Args = new object[1];
            args.Args[0] = arg1;
            object[] argv = new object[2];
            argv[0] = inst._obj;
            argv[1] = args;
            inst._handler.DynamicInvoke(argv);
            if (args.RetVal == null)
                return false;
            return (bool) ((bool)args.RetVal);
        }

        [DllImport("libgobject-2.0-0.dll")]
        static extern uint g_signal_connect_data(IntPtr obj, String name, boolObjectEventButtonDelegate cb, int key, IntPtr p, int flags);

        public boolObjectEventButtonSignal(GLib.Object obj, IntPtr raw, String name, Delegate eh, Type argstype) : base(obj, eh, argstype)
        {
            if (_Delegate == null)
            {
                _Delegate = new boolObjectEventButtonDelegate(boolObjectEventButtonCallback);
            }
            _raw = raw;
            _HandlerID = g_signal_connect_data(raw, name, _Delegate, _key, new IntPtr(0), 0);
        }

        [DllImport("libgobject-2.0-0.dll")]
        static extern void g_signal_handler_disconnect (IntPtr instance, uint handler);

        [DllImport("libgobject-2.0-0.dll")]
        static extern bool g_signal_handler_is_connected (IntPtr instance, uint handler);

        protected override void Dispose (bool disposing)
        {
            _Instances.Remove(_key);
            if(_Instances.Count == 0)
                _Delegate = null;

            if (g_signal_handler_is_connected (_raw, _HandlerID))
                g_signal_handler_disconnect (_raw, _HandlerID);
            base.Dispose (disposing);
        }
    }

}