That looks really good - one question, does "depressable" mean that you are also animating the underlying texture to show clicks ?
I mean just how interactive is the whole thing from a feedback standpoint, i.e. I know you have code to support tooltips and cursor changes, are you also changing the button (scale/color/background) to make it obvious that the button is getting clicked, i.e. is there any visual feedback ?
Apart from that, I am not sure if I mentioned this already or not - but this is freakingly similar to the way the existing 2D panel system works. I don't know if you have done a 2D panel because they are considered a legacy thing, or if you are familiar with the approach - but it's a really straightforward mechanism that sets up an arbitrary number of textures that can respond to events (mouse clicks), so that arbitrary fgcommands are triggered that can then be used to animate the textures by rotating/transforming/scaling the sheet of textures as desired.
The point of this being that it may be interesting to look at README.xmlpanel and README.minipanel - it's a rather simple mechanism that is pretty useful, and that could help you make up your mind on how to proceed from here. For instance, xml panels use texture maps to extract sub-textures into separately addressable textures, which is also something that the Canvas system can do.
I am mentioning this, because you highlighted how your mechanism greatly benefits from existing aircraft textures, and I believe that this could be very promising to pursue further, i.e. determining how much is overlapping here.
Besides, such dialogs could even be trivially rendered by _any_ front-end, including even Phi.
The only major suggestion I can make at this point is to encapsulate all event handlers by registering custom fgcommands using the addcommand API.
This is something that Stuart's fg1000 is also doing, and the key benefit here is that this makes it possible to share all the back-end logic (same file, same function) without having to duplicate stuff at all:
addcommand() APINote that there is no technical restrictions here - because any piece of Nasal code can be registered to be a fgcommand, but once it's an fgcommand, it is well encapsulated and can be called/invoked by any front-end, no matter if that's a 3D cockpit, Canvas dialog, PUI dialog, Phi dialog or external mechanism/front-end (think FGQCanvas, telnet or whatever else people come up with)
I made a posting in the fg1000 topic summarizing the key advantages, and Stuart ended up agreeing with them and also extended the concept even further to adopt Richard's Emesary framework there - at that point, the sky is the limit, because the front-end stuff has to know nothing about Nasal/Emesary at all, because it's all just fgcommands that are invoked:
fgcommands & Canvas FG1000