Sign up

Troubles with UIManager

Hi! Sorry to be troublesome yet again, but I'm trying to work with gtk.UIManager--again on the Gtk2 branch--and I've stumbled across a couple issues, and I'm not sure if either are bugs, or if I'm doing something wrong.

The first is that UIManager.getWidget() returns widgets that cannot be downcast. This isn't disastrous for menubars or toolbars, that can just be added to whatever container is necessary. But for popups, it makes them unusable--Since you need the popup() and possible attachToWidget() methods. It can be worked around by using UIManager.getTopLevels(), but that's very inelegant when multiple popups are defined.

The second, is that UIManager.getToplevels(), if told to retrieve GtkUIManagerItemType.MENUBAR or .TOOLBAR, will return a null list, unless UIManager.getUi() has been called first. The return value doesn't even need to be stored; simply calling the method works.

Here's a little test program I put together that shows off the problems.

module uimanagertest;
import std.stdio;

import gtk.UIManager;
import gtk.Menu;
import gtk.MenuBar;
import gtk.Action;
import gtk.ActionGroup;
import gtk.MainWindow;
import gtk.Main;
import gtk.Window;
import gtk.Widget;
import glib.ListSG;
import gtk.Box;
import gtk.VBox;
import gtk.Button;

version (DigitalMars) {
	version (Windows) pragma (lib, "GtkD.lib");
	version (Posix) pragma (lib, "gtkd-1");
}	

class W : MainWindow {
	ActionGroup actions;
	UIManager uiman;
	Button button;
	Menu popup;
	Widget menubar;
	Widget toolbar;
	
	enum uistring = `
		<ui>
		<menubar>
			<menu action="Menu">
				<menuitem action="Click"/>
			</menu>
		</menubar>
		<popup name="Context">
			<menuitem action="Click"/>
		</popup>
		<toolbar name="Toolbar">
			<toolitem action="Click"/>
		</toolbar>
		</ui>
	`;
	
	this() {
		super("UIManager Test");
		actions = new ActionGroup("Test");
		uiman = new UIManager();
		
		auto action = new Action("Click", "Click me", "This is clickable.", StockID.ABOUT);
		action.addOnActivate((Action a) {
			writeln("I've been activated!");
		});
		actions.addAction(action);
		
		action = new Action("Menu", "Menu", "This is a placeholder.", "");
		actions.addAction(action);
		
		uiman.insertActionGroup(actions, 0);
		uiman.addUiFromString(uistring, uistring.length);
		
		auto wincontents = new VBox(false, 0);
		add(wincontents);
		
		auto button = new Button("Click me too!");
		wincontents.packEnd(button, true, true, 0);
		
		//uiman.getUi(); //If this line is commented out, an exception is thrown below. 
		ListSG menulist = uiman.getToplevels(GtkUIManagerItemType.MENUBAR);
		if (menulist is null) writeln("menulist is null");
		
		//These work, since they don't require downcasting.
		menubar = uiman.getWidget("/ui/menubar");
		wincontents.packStart(menubar, false, true, 0);
		
		toolbar = uiman.getWidget("/ui/Toolbar");
		wincontents.packStart(toolbar, false, true, 0);
		
		//This, however, doesn't work. The downcast from Widget to Menu fails.
		
		popup = cast(Menu)(uiman.getWidget("/ui/ Context"));
		if (popup is null) writeln("Returned menu is null.");
		
		//Weirdly, *this* works without calling getUi first. It's a possible
		//workaround to the getWidget() downcasting problem, but less so if there's
		//More than one popup defined.
		ListSG popuplist = uiman.getToplevels(GtkUIManagerItemType.POPUP);
		popup = new Menu(cast(GtkMenu*)(popuplist.data())); 
		
		
		popup.attachToWidget(button, null);
		button.addOnClicked((Button b) {
			popup.popup(1, 0); //The popup menu must be downcast to gtk.Menu for this to work.
		});
		
		wincontents.showAll();
		
	}
}

void main(string[] args) {
	
	Main.init(args);

	auto win = new W();
	
	win.show();
	Main.run();
}

Re: Troubles with UIManager

On 01/29/2014 10:09 PM, E.S. Quinn wrote:

Hi! Sorry to be troublesome yet again, but I'm trying to work with gtk.UIManager--again on the Gtk2 branch--and I've stumbled across a couple issues, and I'm not sure if either are bugs, or if I'm doing something wrong.

UIManager.getWidget isn't implemented correctly currently, is needs to
do something similar to Builder.getWidget or D/GtkD wont know what type
of object it is actually returning.

For now you will need to work around it.

I'll need to check whats going on with getToplevels/GetUI.

Re: Troubles with UIManager

On Thu, 30 Jan 2014 22:39:28 +0100, Mike Wey wrote:

On 01/29/2014 10:09 PM, E.S. Quinn wrote:

Hi! Sorry to be troublesome yet again, but I'm trying to work with gtk.UIManager--again on the Gtk2 branch--and I've stumbled across a couple issues, and I'm not sure if either are bugs, or if I'm doing something wrong.

UIManager.getWidget isn't implemented correctly currently, is needs to
do something similar to Builder.getWidget or D/GtkD wont know what type
of object it is actually returning.

For now you will need to work around it.

Fixed in commit: https://github.com/gtkd-developers/GtkD/commit/88b2757d5d7fa760da8db0cdd5a0e7b69d48a7a2

I'll need to check whats going on with getToplevels/GetUI.

Re: Troubles with UIManager

On Sat, 01 Feb 2014 17:00:13 GMT, Mike Wey wrote:

I'll need to check whats going on with getToplevels/GetUI.

You'll need to call ensureUpdate before using getToplevels.

Re: Troubles with UIManager

On Sat, 01 Feb 2014 22:03:19 GMT, Mike Wey wrote:

On Sat, 01 Feb 2014 17:00:13 GMT, Mike Wey wrote:

I'll need to check whats going on with getToplevels/GetUI.

You'll need to call ensureUpdate before using getToplevels.

Awesome! Thank you very much. Hopefully I won't have to bug you too much more. :)

Re: Troubles with UIManager

On Mon, 03 Feb 2014 11:38:28 GMT, E.S. Quinn wrote:

On Sat, 01 Feb 2014 22:03:19 GMT, Mike Wey wrote:

On Sat, 01 Feb 2014 17:00:13 GMT, Mike Wey wrote:

I'll need to check whats going on with getToplevels/GetUI.

You'll need to call ensureUpdate before using getToplevels.

Awesome! Thank you very much. Hopefully I won't have to bug you too much more. :)

:/ Now that I actually have the updated GtkD, the test program doesn't run at all. (I put an .ensureUpdate call in there too, immediately after the addUiFRomString() call. It crashes with an Access Violation, and complains that the Actions weren't added.

Re: Troubles with UIManager

On Tue, 04 Feb 2014 19:16:04 GMT, E.S. Quinn wrote:

:/ Now that I actually have the updated GtkD, the test program doesn't run at all. (I put an .ensureUpdate call in there too, immediately after the addUiFRomString() call. It crashes with an Access Violation, and complains that the Actions weren't added.

Do you have an small example that fails?

Re: Troubles with UIManager

On Tue, 04 Feb 2014 22:23:47 GMT, Mike Wey wrote:

On Tue, 04 Feb 2014 19:16:04 GMT, E.S. Quinn wrote:

:/ Now that I actually have the updated GtkD, the test program doesn't run at all. (I put an .ensureUpdate call in there too, immediately after the addUiFRomString() call. It crashes with an Access Violation, and complains that the Actions weren't added.

Do you have an small example that fails?

I pared down my test program to a very minimal one, and this still fails:

module uimanagertest;
import std.stdio;

import gtk.UIManager;
import gtk.Menu;
import gtk.MenuBar;
import gtk.Action;
import gtk.ActionGroup;
import gtk.MainWindow;
import gtk.Main;
import gtk.Window;
import gtk.Widget;

version (DigitalMars) {
	version (Windows) pragma (lib, "GtkD.lib");
	version (Posix) pragma (lib, "gtkd-1");
}	

class W : MainWindow {
	ActionGroup actions;
	UIManager uiman;
	Widget menubar;
	
	enum uistring = `
		<ui>
		<menubar>
			<menu action="Menu">
				<menuitem action="Click"/>
			</menu>
		</menubar>
		</ui>
	`;
	
	this() {
		super("UIManager Test");
		actions = new ActionGroup("Test");
		uiman = new UIManager();
		
		auto action = new Action("Click", "Click me", "This is clickable.", StockID.ABOUT);
		action.addOnActivate((Action a) {
			writeln("I've been activated!");
		});
		actions.addAction(action);
		
		action = new Action("Menu", "Menu", "This is a placeholder.", "");
		actions.addAction(action);
		
		uiman.insertActionGroup(actions, 0);
		uiman.ensureUpdate();
		uiman.addUiFromString(uistring, uistring.length);
		uiman.ensureUpdate();
		menubar = (uiman.getWidget("/ui/menubar"));
		add (menubar);
		menubar.show();
		
		
	}
}

Re: Troubles with UIManager

On Tue, 04 Feb 2014 23:16:37 GMT, E.S. Quinn wrote:

I pared down my test program to a very minimal one, and this still fails:

... code ...

For me that sample runs without any issues, i've tried both Linux and Windows and both the Gtk2 and master branch.

If i remember correctly you are using Windows, if so what versino of Gtk+ do you have installed?

Re: Troubles with UIManager

On Wed, 05 Feb 2014 21:27:55 GMT, Mike Wey wrote:

On Tue, 04 Feb 2014 23:16:37 GMT, E.S. Quinn wrote:

I pared down my test program to a very minimal one, and this still fails:

... code ...

For me that sample runs without any issues, i've tried both Linux and Windows and both the Gtk2 and master branch.

If i remember correctly you are using Windows, if so what versino of Gtk+ do you have installed?

WHOOPS! Sorry, this one was my fault. I had a brainfart and only installed the new .lib file, rather than also installing the new include files. Once I did that everything works fine. Sorry about that!

(If the answer to your question is still of any interest, I'm using 2.24.10, which is the latestversion that has win32 binaries on the gtk.org site)