April 04, 2006

IntelliJ IDEA 6.0 "Demetra" UI Designer: Custom component creation

One of the problems which made it impossible for people to use previous versions of the IntelliJ IDEA UI Designer in their projects was the lack of support for custom component creation code. The designer could only work with components which had no-argument public constructors, and could not handle components created by constructors with arguments, component factories and so on.

We continued to receive feedback on this issue during our work on the version 6.0, and finally we’ve come to a solution for this issue that doesn’t break any of our design principles. The solution works equally well for source code generation and bytecode instrumentation, and does not involve storing source code in the form files.

The solution is in fact very simple. Every component now has a property called “Custom Create”:

CustomCreate

If the property is set for a component, the UI Designer does not generate the constructor call for this component. Instead, if at least one component has the “Custom Create” flag set, IntelliJ IDEA creates a special method called createUIComponents(), and inserts a call to this method in the beginning of the generated UI initialization method. The code of createUIComponents() is written by the user, and the user needs to assign values to fields bound to all custom-created components. (A component with the “Custom Create” flag must be bound to a field.)

CreateUIComponents

In design time, components which do not have a public default constructor are represented by instances of superclasses which do have such a constructor, or by JPanel instances if there is no such superclass. The property list shown in the inspector is still taken from the exact class of the component, so you’ll be able to set the values for all properties (although the values of properties that don’t exist in the superclass will not affect the design-time appearance of the component).

A related change that also makes the UI Designer more flexible is a small modification to the source code generation algorithm. Now, if any of the user-written constructors of a class bound to a form calls the UI initialization method explicitly, IntelliJ IDEA no longer generate a class initializer block with a call to the UI initialization method. This allows to initialize the UI at a somewhat later time (for example, after values of the parameters passed to the bound class constructor have been processed).

This solution will become available in the next EAP build of Demetra. In the meantime, feel free to leave feedback here, particularly if the solution does not cover some of the scenarios found in your projects.

Posted by Dmitry Jemerov at April 4, 2006 08:20 PM
Comments

Для форсирования инициализации надо бы аннотации типа final @NotNull или @FactoryMethod

Posted by: Доброжелатель at April 6, 2006 05:50 PM

This is great. And I love the new way you make a group and add components to it.

But I'm very confused about why the class bound to a form isn't itslef a JComponent. Instead it has a JPanel as a field. All the Swing GUI Builder components are themselves JComponents. But if I try to make my own component that is a subclass of some JComponent, I still get that JPanel inside it. I can't bind the class itself as the container. Please illuminate.

Also, there needs to be updated documentation on making your own component inside the project and adding it to the palette. One thing I always forget (until now) is that you have to compile a class before it will work as a palette component. In fact, I think that the process of adding it to a palette group should force it to be compiled, so this weird situation will not bite people.

Thanks

Posted by: Dave Yost at April 15, 2006 11:31 AM

Here's another way of putting it: Say I have made MyComponent and have put it in the palette. It would seem natural in FormAClass, to have a bound field, myComponent1, and to say
private void createUIComponents() {
myComponent1 = new MyComponent(1, 3);
}
but this won't work because MyComponent is not a subclass of JComponent. What does one do here?

Thanks

Posted by: Dave Yost at April 15, 2006 01:32 PM
Post a comment









Remember personal info?