I absolutely understand that it is extensive, though I would distinguish what I would like to see from the approach @damien.boissat is attempting. (More than a bit insane/misguided, IMNSHO. Automating bindings from within components is just wrong. I've recommended an alternate approach a couple times now, and it isn't getting through. ) What I want might be more palatable.
Let me elaborate:
I would like support for extensible container types. Or more precisely, I'd like to see changes to BasicContainer to make it extensible. The changes would only impact the designer. No client runtime impact at all.
I do not want to move away from the Swing component model. That's just crazy. In fact, I think such an extensible interface should only accept JComponents that implement VisionComponent.
When I was poking around while attempting to implement a "ScrollingContainer" (a while back), I was stymied by the designer's use of the Swing component enumeration methods for designer tree population, too. In other words, I couldn't distinguish a runtime call to .getComponent(int i) (client or designer rendering) from a design-time call from the designer tree or from the designer's mouse-coordinate to component selection infrastructure.
After some headscratching, I decided to instrument my subclass's .getComponent() method to expose the all design-time callers. I came up with:
- com.jidesoft.utils.JideFocusTracker
- com.inductiveautomation.factorypmi.application.components.util.ComponentVisitor
- com.inductiveautomation.factorypmi.designer.workspace.LayoutManipulator
- com.inductiveautomation.factorypmi.designer.workspace.WindowWorkspace$Delegate
As a proof of concept, I played with this instrumentation to LIE to selected callers, whereupon I was able to display and manipulate a subtree for my test component's functionality. (But not mouse selection in design mode. Didn't look practical.) It definitely wasn't a production solution, as backtraces are expensive in the rendering path.
After some more headscratching, I noticed that shape groups behaved differently. And have a .getChild() method (IIRC) for the designer to use. (Other methods, too, I think.) Anyways, after a peek at some of the designer tree's bytecode, I realized that it hardcodes calling .getComponent() for anything other than a shape group.
That's where I threw up my hands and abandoned the effort, as I noted over here:
What I would like is to see BasicContainer grow a set of public methods for designer use, .getChild(..)
, .addChild(..)
, .removeChild(..)
, .getChildren()
, .getChildCount()
, etc, that just call the existing Swing method. And then have all the hardcoded designer call sites that involve designable components call the new methods. You don't even have to factor it out into a new interface, as it just becomes something subclasses of BasicContainer could override.
Very low risk for existing stuff, since anything using BasicContainer would get the same results whichever method is called. If you miss a designer call site, you only prevent new users from succeeding.
I would argue that it isn't very risky, if approached as above.