What’s in a name?

Quite a bit, if you’re Gtk#.

I’ve implemented the popup user menu in WikiBench.MediaWikiIntegration, along with the extension points for other addins to insert their own menu items into the menu. They can either provide a type extension using a class that derives Gtk.MenuItem, or a custom extension node provided by MediaWikiIntegration to add a separator. It was working perfectly… well, almost.

If you are using the Clearlooks GTK+ engine then you know that when you hover over a menu item, the text color changes from black to white. Lots of other themes do this too. Well, the text on one of the menu items in my popup menu was not, and it happened to be a menu item provided by an addin. So, naturally, I start poking at this phenomenon.

Is it because the class I’m instantiating is in another assembly? Nope.

What about the fact that it’s instantiated using reflection? Nope again.

So I gave up and went to bed. Today I started digging around a bit more, and finally gave up again.

Later I decided to refactor a few classes, and one of the ones on the list was the menu item that was acting funky. The class was named BlacklistUserMenu, and since the other classes I’d defined were named things like TalkMenuItem and BlockLogMenuItem, I renamed it to BlacklistMenuItem for consistency. Then I compiled and ran the program to make sure my changes worked.

They did. In fact they really worked, because now the menu item text was correctly turning white when the mouse was on it. Just to make sure I wasn’t imagining it, I renamed the class back and sure enough the text color didn’t change.

I’m not sure whose fault this is, GTK+ or Gtk#, but it’s certainly one of the more interesting bugs I’ve seen. Who would have thought that the name you give a class could affect its behavior?

6 Replies to “What’s in a name?”

  1. If that custom Gtk.MenuItem is doing its own drawing (sounds like it is), it needs to ensure that it sets the correct text color (Style.TextGC) based on the Gtk.StateType.Selected state, which should result in white text in clearlooks.

    Although if I remember correctly, if you embed a Gtk.Label into a Gtk.MenuItem, it should be handled automagically.

    Either way, this shouldn’t be a Gtk# issue – this is a common issue with custom widgets derived from GtkMenuItem.

    I’ve been working lately on some really strange and complex custom menu items that handle all the proper theming, so you may find this helpful:


    Good luck!

  2. The class I wrote is like ten lines. I simply chained to the base(String) constructor and overrode OnActivated, so no custom drawing. The graphical error only happens when the name of the class doesn’t end with “MenuItem”.

  3. Oh wow, this is interesting.

    // Proper text color when item is selected (actually is “prelit”)
    public class CustomMenuItem : MenuItem
    { public CustomMenuItem(string label) : base(label) { } }

    // Text color always remains Text(StateType.Normal)
    public class CustomBlah : MenuItem
    { public CustomBlah(string label) : base(label) { } }

    I’ll look into where and why this happens – quite intriguing.

  4. It’s a theme/RC issue. gtkrc files do pattern matching on GTK+ class names to set the proper theme class for a widget. The Gtk# binding sets the GTK+ widget path/class name via reflection to something like “__gtksharp_3_MyClassName”. You can see what it is by checking the Name property in Gtk.Widget.

    So straight from the Clearlooks gtkrc file:

    widget_class “*MenuItem.*” style “clearlooks-menu-item”

    That is, the “clearlooks-menu-item” style is only applied to widgets whose class name ends in MenuItem. So the easy fix is to just tack on MenuItem to your class name, which is good form for naming convention anyway.

    If you do not want to break API, you can probably manually override the widget path that Gtk# sets to something ending in “MenuItem”.

  5. On your second comment, yes, I knew that this was the issue. (That’s what I was trying to illustrate in my post.)

    Good job on the research. That at least explains this phenomenon. Stuff like this should be included somewhere in the Gtk# docs so other people don’t shoot themselves in the foot too.

Comments are closed.