[Gtk-sharp-list] Gnome.App.CreateMenus: take 2

Carlo Salinari csali@tiscali.it
Wed, 17 Nov 2004 13:17:44 +0100


This is a multi-part message in MIME format.
--------------070105090504070808020704
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hello list,

I finally worked out a semi-functional example (see attachment) of
Gnome.App.CreateMenus invocation, wich I need to port the C version of
gnome-hello to C#.

compile: mcs -pkg:gnome-sharp-2.0 gnome-sharp-hello.cs
execute: mono gnome-sharp-hello.exe

Basically, I'd like to create a simple "hello" gnome program with no 
direct calls to gtk.

Otherwise, what's the sake of having a gnome and gnomeui library, if all 
"gnome"
programs go with gtk or glade as to interface building?

This confuses my quite a bit.

I had to create a new class, basically to handle the lack of any clear 
method to create
an UIInfo from the managed side. Here is the interface:

class GnomeAppHelper
{
    // byte-equivalent to UIInfo, all members accessible by CreateUIInfo
    [StructLayout(LayoutKind.Sequential)]
    protected struct DummyUIInfo; // byte-equivalent to UIInfo, all 
members accessible

    public static Gnome.UIInfo CreateUIInfo ( Gnome.UIInfoType    Type,
                                        string              Label,
                                        string              Hint,
                                        IntPtr              _moreinfo,
                                        IntPtr              _user_data,
                                        IntPtr              _unused_data,
                                        Gnome.UIPixmapType  PixmapType,
                                        IntPtr              _pixmap_info,
                                        uint                AcceleratorKey,
                                        Gdk.ModifierType    AcMods,
                                        IntPtr              _widget)

    public static Gnome.UIInfo CreateMenuConfigurableItem (string label)

    protected static HandleRef UIInfoArrayToHandleRef (Gnome.UIInfo[] arr)

    public static Gnome.UIInfo MenuMain (Gnome.UIInfo[] arr)

    public static Gnome.UIInfo CreateMenuItem (string label, string hint,
                                                
Gnome.UIInfoConfigurableTypes t)

    public static Gnome.UIInfo Endofinfo ()
    public static Gnome.UIInfo MenuFileTree (Gnome.UIInfo[] tree)

    public static Gnome.UIInfo MenuSubtree (Gnome.UIInfo[] tree)
    public static Gnome.UIInfo MenuInclude (Gnome.UIInfo[] tree)
}


This builds the menus as expected, but produces some nasty warnings
telling there's some incorrectly set C pointer somewhere.

I wasn't able to track the problem down, and at this point I really need
directions from some more experienced mono/gnome hacker.

cheers,
    Carlo



--------------070105090504070808020704
Content-Type: text/x-csharp;
 name="gnome-sharp-hello.cs"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="gnome-sharp-hello.cs"

using System;
using System.Runtime.InteropServices;

class GnomeSharpHello : Gnome.Program
{
    static public void Main (string[] args)
    {
        GnomeSharpHello hello = new GnomeSharpHello(args);
    }

    public GnomeSharpHello (string[] args)
    : base ("GnomeSharpHello", "0.1", Gnome.Modules.UI, args)
    {
        Gnome.App app = new Gnome.App ("test", "TEST");

        app.SetDefaultSize (400, 300);
        app.DeleteEvent += Window_Delete;

        Gtk.AccelGroup agrp = new Gtk.AccelGroup ();
        app.AddAccelGroup (agrp);

        app.Statusbar = new Gnome.AppBar (true, true,
                            Gnome.PreferencesType.Never);

        Gnome.UIInfo[] file_menu = {
            GnomeAppHelper.CreateMenuConfigurableItem ("_New"),
            GnomeAppHelper.CreateMenuConfigurableItem ("_Open"),
            GnomeAppHelper.CreateMenuConfigurableItem ("_Save"),
            GnomeAppHelper.CreateMenuConfigurableItem ("Save _As..."),
            GnomeAppHelper.CreateMenuConfigurableItem ("_Quit"),
            GnomeAppHelper.Endofinfo (),
        };

        Gnome.UIInfo[] edit_menu = {
            // we duplicate the file_menu here, just to test
            GnomeAppHelper.MenuFileTree (file_menu),
            GnomeAppHelper.MenuFileTree (file_menu),
            GnomeAppHelper.Endofinfo (),
        };

        Gnome.UIInfo[] wrapper_menu = {
            GnomeAppHelper.MenuFileTree (file_menu),
            GnomeAppHelper.MenuFileTree (edit_menu),
            GnomeAppHelper.Endofinfo (),
        };

        Gnome.UIInfo main_menu = GnomeAppHelper.MenuMain (wrapper_menu);

        app.CreateMenus (main_menu);

        app.ShowAll ();

        Run ();
    }

    private void dummy_response ()
    {
        Console.WriteLine("dummy_response");
    }

    private void Window_Delete (object o, Gtk.DeleteEventArgs args)
    {
        this.Quit ();
    }
}

class GnomeAppHelper
{
    [StructLayout(LayoutKind.Sequential)]
    protected struct DummyUIInfo {

        public Gnome.UIInfoType Type;
        public string Label;
        public string Hint;
        public IntPtr _moreinfo;
        public IntPtr _user_data;
        public IntPtr _unused_data;
        public Gnome.UIPixmapType PixmapType;
        public IntPtr _pixmap_info;
        public uint AcceleratorKey;
        public Gdk.ModifierType AcMods;
        public IntPtr _widget;
    }

    public static Gnome.UIInfo CreateUIInfo ( Gnome.UIInfoType    Type,
                                        string              Label,
                                        string              Hint,
                                        IntPtr              _moreinfo,
                                        IntPtr              _user_data,
                                        IntPtr              _unused_data,
                                        Gnome.UIPixmapType  PixmapType,
                                        IntPtr              _pixmap_info,
                                        uint                AcceleratorKey,
                                        Gdk.ModifierType    AcMods,
                                        IntPtr              _widget)
    {
        DummyUIInfo dummy   = new DummyUIInfo ();
        // let's leak!
        IntPtr ptr = Marshal.AllocHGlobal (Marshal.SizeOf (dummy));

        HandleRef handle = new HandleRef (dummy, ptr);

        dummy.Type              = Type;
        dummy.Label             = Label;
        dummy.Hint              = Hint;
        dummy._moreinfo         = _moreinfo;
        dummy._user_data        = _user_data;
        dummy._unused_data      = _unused_data;
        dummy.PixmapType        = PixmapType;
        dummy._pixmap_info      = _pixmap_info;
        dummy.AcceleratorKey    = AcceleratorKey;
        dummy.AcMods            = AcMods;
        dummy._widget           = _widget;

        Marshal.StructureToPtr (dummy, ptr, false);

        return Gnome.UIInfo.New (handle.Handle);
    }

    public static Gnome.UIInfo CreateMenuConfigurableItem (string label)
    {
        Gnome.UIInfoConfigurableTypes item_type = 0;

        switch (label) {
            case "_New":
                item_type = Gnome.UIInfoConfigurableTypes.New;
                break;
            case "_Open":
                item_type = Gnome.UIInfoConfigurableTypes.Open;
                break;
            case "_Save":
                item_type = Gnome.UIInfoConfigurableTypes.Save;
                break;
            case "Save _As...":
                item_type = Gnome.UIInfoConfigurableTypes.SaveAs;
                break;
            case "_Revert":
                item_type = Gnome.UIInfoConfigurableTypes.Revert;
                break;
            case "_Print":
                item_type = Gnome.UIInfoConfigurableTypes.Print;
                break;
            case "Print Set_up":
                item_type = Gnome.UIInfoConfigurableTypes.PrintSetup;
                break;
            case "_Close":
                item_type = Gnome.UIInfoConfigurableTypes.Close;
                break;
            case "E_xit":
            case "_Quit":
                item_type = Gnome.UIInfoConfigurableTypes.Quit;
                break;
        }
        return CreateUIInfo (   Gnome.UIInfoType.ItemConfigurable,
                                label,
                                null,
                                IntPtr.Zero, // cb
                                IntPtr.Zero, // data
                                IntPtr.Zero,
                                Gnome.UIPixmapType.None,
                                IntPtr.Zero,
                                (uint) item_type,
                                (Gdk.ModifierType) 0,
                                IntPtr.Zero);
    }

    protected static HandleRef UIInfoArrayToHandleRef (Gnome.UIInfo[] arr)
    {
        int     element_size        = Marshal.SizeOf (typeof (Gnome.UIInfo));
        int     buffer_size         = element_size * arr.Length;
        IntPtr  unmanaged_buffer    = Marshal.AllocHGlobal (buffer_size);

        HandleRef   href    = new HandleRef (arr, unmanaged_buffer);
        int         membase = href.Handle.ToInt32 ();

        // copy managed array of UIInfo structs to contiguous unmanaged mem regions
        foreach (Gnome.UIInfo chunk in arr) {
            Marshal.StructureToPtr (chunk, (IntPtr) membase, false);
            membase += element_size;
        }

        return href;
    }

    public static Gnome.UIInfo MenuMain (Gnome.UIInfo[] arr)
    {
        Gnome.UIInfo[] main_menu = {
            MenuInclude (arr),
            Endofinfo (),
        };

        HandleRef href = UIInfoArrayToHandleRef (main_menu);
        return Gnome.UIInfo.New (href.Handle);
    }

    public static Gnome.UIInfo CreateMenuItem (string label, string hint,
                                                Gnome.UIInfoConfigurableTypes t)
    {
         return CreateUIInfo (  Gnome.UIInfoType.ItemConfigurable,
                                label,
                                hint,
                                IntPtr.Zero, // cb
                                IntPtr.Zero, // data
                                IntPtr.Zero,
                                Gnome.UIPixmapType.None,
                                IntPtr.Zero,
                                (uint) t,
                                (Gdk.ModifierType) 0,
                                IntPtr.Zero);
    }

    public static Gnome.UIInfo Endofinfo ()
    {
         return CreateUIInfo (  Gnome.UIInfoType.Endofinfo,
                                null,
                                null,
                                IntPtr.Zero,
                                IntPtr.Zero,
                                IntPtr.Zero,
                                Gnome.UIPixmapType.None,
                                IntPtr.Zero,
                                0,
                                (Gdk.ModifierType) 0,
                                IntPtr.Zero);
    }

    public static Gnome.UIInfo MenuFileTree (Gnome.UIInfo[] tree)
    {
        HandleRef href = UIInfoArrayToHandleRef (tree);
        return CreateUIInfo (  Gnome.UIInfoType.SubtreeStock,
                                "_File",
                                null,
                                href.Handle,
                                IntPtr.Zero,
                                IntPtr.Zero,
                                Gnome.UIPixmapType.None,
                                IntPtr.Zero,
                                0,
                                (Gdk.ModifierType) 0,
                                IntPtr.Zero);
    }

    public static Gnome.UIInfo MenuSubtree (Gnome.UIInfo[] tree)
    {
        HandleRef href = UIInfoArrayToHandleRef (tree);
        return CreateUIInfo (  Gnome.UIInfoType.Subtree,
                                null,
                                null,
                                href.Handle,
                                IntPtr.Zero,
                                IntPtr.Zero,
                                Gnome.UIPixmapType.None,
                                IntPtr.Zero,
                                0,
                                (Gdk.ModifierType) 0,
                                IntPtr.Zero);
    }

    public static Gnome.UIInfo MenuInclude (Gnome.UIInfo[] tree)
    {
        HandleRef href = UIInfoArrayToHandleRef (tree);
        return CreateUIInfo (  Gnome.UIInfoType.Include,
                                null,
                                null,
                                href.Handle,
                                IntPtr.Zero,
                                IntPtr.Zero,
                                Gnome.UIPixmapType.None,
                                IntPtr.Zero,
                                0,
                                (Gdk.ModifierType) 0,
                                IntPtr.Zero);
    }
}

--------------070105090504070808020704--