I'm just digging into menus. I wrote several tests for a menubar by itself, a single menu with a single item, a single menu with several items, two menus (each with several items, and one with mnemonics attached to some items.

But when I moved on to do a test with submenus, I ran into something odd. Everything compiles and runs normally except that when the window appears and I click on the File menu, a blue line appears under the word File, but the menu doesn't drop. I click it a second time and everything's normal.

I stripped it down to just one menu, one item on the menu which is a submenu, and one item on the submenu. The behaviour is still the same. Here's the boiled down code:

import std.stdio;

import gtk.MainWindow;
import gtk.Box;
import gtk.Main;
import gtk.Menu;
import gtk.MenuBar;
import gtk.MenuItem;
import gtk.Widget;
import gdk.Event;

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

    TestRigWindow testRig = new TestRigWindow();
    
    Main.run();
    
} // main()


class TestRigWindow : MainWindow
{
	string title = "Multiple Menus Example";

	this()
	{
		super(title);
		setDefaultSize(640, 480);
		addOnDestroy(&quitApp);

		AppBox appBox = new AppBox();
		add(appBox);
		
		showAll();
		
	} // this()
	
	
	void quitApp(Widget w)
	{
		// do other exit stuff here if necessary
		
		Main.quit();
		
	} // quitApp()
	
} // TestRigWindow


class AppBox : Box
{
	int padding = 10;
	MyMenuBar menuBar;
	
	this()
	{
		super(Orientation.VERTICAL, padding);
		
		menuBar = new MyMenuBar();
    	packStart(menuBar, false, false, 0);		
		
	} // this()
	
} // class AppBox


class MyMenuBar : MenuBar
{
	string fileHeaderLabel = "File";
	
	FileHeader fileHeader;
	
	this()
	{
		super();
		
		fileHeader = new FileHeader(fileHeaderLabel);
		append(fileHeader);
		
	} // this()

	
} // class MyMenuBar


class FileHeader : MenuItem
{
	FileMenu fileMenu;
	
	// arg: a Menu object
	this(string headerTitle)
	{
		super(headerTitle);
		
		fileMenu = new FileMenu();
		setSubmenu(fileMenu);
		
	} // this()
	
} // class MenuHeader


class FileMenu : Menu
{
	NewFileItem newFileItem;
	
	// arg: an array of items
	this()
	{
		super();
		
		newFileItem = new NewFileItem();
		append(newFileItem);
		
	} // this()
	
	
} // class FileMenu


class NewFileItem : MenuItem
{
	string itemLabel = "New";
	NewFileSubMenu newFileSubMenu;
   
	this()
	{
		super(itemLabel);
		addOnActivate(&doSomething);
		
		newFileSubMenu = new NewFileSubMenu();
		setSubmenu(newFileSubMenu);
		
	} // this()
	
	
	void doSomething(MenuItem mi)
	{
		writeln("New file created.");
		
	} // doSomethingNew()
	
} // class NewFileItem


class NewFileSubMenu : Menu
{
	DFileItem dFileItem;
	
	this()
	{
		super();
		
		dFileItem = new DFileItem();
		append(dFileItem);

	} // this()
	
} // class NewFileSubMenu


class DFileItem : MenuItem
{
	string itemLabel = "D Source File";
   
	this()
	{
		super(itemLabel);
		addOnActivate(&doSomething);
		
	} // this()
	
	
	void doSomething(MenuItem mi)
	{
		writeln("Dialog appears with filter: '*.d'");
		
	} // doSomething()
	
} // class UndoItem