Since last time, most of my coding has either been blogged elsewhere, has been web pages which are their own thing, or just tools for my own use (including a lot of recursive tools to assist with tool building).
It was the last of these that took a lot of the time -- especially when I realised I needed to write something with a GUI that couldn't easily be done via HTML report generation. After a lot of experimentation, I eventually settled on GTK# because that provided a text control that made it easiest to do things like paint background colours given line/column start and end-points (for highlighting properties of source code, as it happens) -- plus, bonus, it also had a designer that was language agnostic (unlike WinForms or WPF).
Unlike easily automated library code, GUI really needs manual prodding to exercise, and also unpicking the under-documented assumptions that go along with every toolkit; so I stalled for many months at the point where I had a Glade based UI with all the widgets in place, to doing things like populating tree controls and wiring up events.
Once I'd done that, things went more quickly, but there was a long spell where all I was doing was refactoring what I had, and adjusting the balance between the F# native reactive event handling (e.g. consolidating and filtering all the possible ways a file could be selected -- browsing, from an MRU list or by refreshing the current value), and then a self-resetting
async block to push the real work off the UI thread.
So for a while I was really glad to be done with the GUI stuff there for the moment, even if playing with the event handling was an interesting learning experience -- and had started considering doing something in Swing (using Scala) to get back into my GUI comfort zone.
So, for the few other people who are using it, here's something I've not found elsewhere on the web -- a worked example of how to use the
Global.RegisterWidget facility to pick up a widget known to Glade the tool, but not to the GTK# Glade wrapper.
Note that we have to work around deficiencies in the
ChildInfo types -- reflecting to get the pointers to what are array properties in the underlying native object, and then walking the array by pointer arithmetic.
As we are in .net here, I've also made the assumption that string resources and localization are handled through embedded resources, with string and image values in the Glade file corresponding to resource names in a nominated assembly.