Following the first and second parts, this post continues the discussion of key design decisions in the IntelliJ IDEA 6.0 UI Designer.
Form and Code Separation. This decision hasn’t changed since the initial version of the UI Designer. The principle is simple: Java code is never stored in .form files and never edited in the UI Designer. The Java editor in IntelliJ IDEA is a much better environment for editing Java code than anything which could be embedded in the UI Designer dialogs, and having all the code in one place (the Java class file) makes it easier to understand and causes much less surprises.
All of this doesn’t preclude the possibility to navigate between code and form files. The possibility to jump from a field declaration to the corresponding UI component in the form and back has been present since the initial version of the UI Designer. Version 6.0 adds another navigation feature: “Navigate to Listener”, allowing to navigate from a component in the form to the event listener classes attached to the component. Here’s a screenshot showing how this works:
One-Step Layout. This is probably the biggest change to the UI Designer made in version 6.0 – or, at least, the most controversial one.
In previous versions of the UI Designer, building the form layout was a two-step process. First, the user placed components on a form with no layout, with arbitrary positions and sizes. Then, the user selected all or some of the components and invoked one of the layout actions (“Lay Out Horizonally”, “Lay Out Vertically”, “Lay Out in a Grid”). The UI Designer tried to guess the grid structure needed to lay out the components similarly to how the user placed them, and created the grid.
We feel that this approach has a number of problems. First of all, it is confusing for new users: almost no other UI design tools (except for Qt Designer, on which this design was based) have such a two-step process, and there was very little instruction telling the users what they were supposed to do. Second, this procedure inherently lacks feedback. The grid structure is always more limited than the free-form layout, so the layout created by the user is not reproduced exactly. Also, the algorithm is not always predictable, so the user often has to undo the layout process, try to tweak the placement of the components and retry the layout, hoping that the second time will produce better results.
Thus, we have dropped the layout actions in the new version. Now, a grid structure is always created around components placed on a form, and the actions for adding components have been modified so that they can insert grid rows and columns if required. Layout modifications can also be done by dragging components within the grid, and do not require breaking and rebuilding the layout, as was often the case in previous versions.
In fact, the current layout editing experience is considered to be work in progress, and we expect to continue tweaking and improving it in the future EAP builds, to ensure that the behavior always matches user expectations and all necessary operations are easy to accomplish.
UI Inspections. Inspections are heavily used in many areas of IntelliJ IDEA, and we decided to make use of them in the UI Designer as well. Designing forms involves a number of routine operations (assigning mnemonics, placing components in JScrollPanes, grouping radio buttons, linking labels to controls and so on). Of course, we found it desirable to automate the operations. However, rather than doing things fully automatically or popping up modal dialogs asking the user for confirmation, we linked them to the well-used lightbulb and Alt-Enter keyboard shortcut.
For example, here’s how the inspection for assigning mnemonics works:
The designer automatically suggests choices for the text with mnemonics, ensuring that the suggested variants do not overlap with mnemonics of other controls in the form:
Well, looks like I’ve got the major decisions covered, so the following posts will focus on specific new features implemented in the IntelliJ IDEA 6.0 UI Designer. As usual, don’t hesitate to send your feedback – and thanks to everyone who has left comments on previous posts in this blog. :-)
Yesterday I described the main goals with which we approached the UI Designer in IntelliJ IDEA 6.0. Now I’ll describe some of the key decisions we’ve made – part of them are new for version 6.0, and others haven’t changed since the previous versions of UI Designer available in IntelliJ IDEA 4.x and 5.x. As usual, any feedback on the decisions is very much welcome.
Runtime Requirement. In previous versions of IntelliJ IDEA, the code generated by the UI Designer always required the use of a runtime library (forms_rt.jar), which contains a custom layout manager and a number of additional utility functions. This became a major obstacle for many users who didn’t want to introduce extra dependencies in their applications – some of them rejected the UI Designer completely when they learned of the runtime requirement. The problem was made worse by the fact that, until version 5.0, the license for the source code of forms_rt.jar was not clearly defined, which made it hard to use in open-source projects. Now it’s clearly licensed under the Apache license, but other problems with the runtime remained.
In the new version, we’ve made it possible to generate code which uses only the standard Swing layout managers and does not require any additional runtime. We’ve kept the runtime for those who need full compatibility with forms created in earlier versions of IntelliJ IDEA, and we even added a few new features to our layout manager, but you can easily opt out of its use if you don’t need that.
Bytecode Instrumentation. A related issue is the way code is generated by the UI Designer. We decided to keep both of the options available in version 5.0: source code generation and bytecode instrumentation. We consider bytecode instrumentation the best option for projects which are developed using only IntelliJ IDEA, as it’s cleaner (the generated code is never visible to users) and provides better build performance. For other projects, where multiple IDEs are used or when the entire source code of the application needs to be provided to the customer, source code generation can be used.
In version 6.0, we’ve rewritten the bytecode generator to use ASM instead of BCEL, as it provides better performance and better support for new versions of the .class file format. Also, we plan to improve the source code generator so that it produces cleaner and more readable code.
Form Migration. Using forms created in IDEA with other IDEs is one side of the problem – another is importing into IDEA forms created in other IDEs. Before version 6.0, we didn’t provide any solution to this problem – you always had to draw forms from scratch.
There are a number of possibilities to solving this. It’s possible to import the XML form definition files created by specific designers (for example, JFormDesigner .jfd or NetBeans .form). Another option is to reverse-engineer the Java source code used to create the form (either generated or hand-written) and to extract the information about the component layout and properties (this is the approach used by Eclipse Visual Editor).
However, we decided that importing only specific XML form file formats would be too restricted, and creating a general reverse engineering engine that works in a sufficiently broad number of cases (including hand-written code) is too risky and resource-consuming. Instead, we have implemented the possibility to import form files from the most simple and universal structure of the form data: the run-time tree of Swing components. We inject our component, called Swing Inspector, in the Java virtual machine where the user application runs. When the user presses a button or a keyboard shortcut, a window showing the entire hierarchy of Swing components is displayed. The user can choose any part of that tree (the contents of an entire frame or dialog, a panel containing some of the components, and so on), and that part is saved as a .form file. The entire component layout structure and most of the component properties are saved. Later, the user can open the .form file in UI Designer and modify it as required.
The initial version of the Swing Inspector will be included in the next EAP build of IntelliJ IDEA. Here’s a screenshot showing how it works:
Well, that’s enough for today – stay tuned for more design decisions next week. And don’t forget to send feedback! :-)
As simple requests for feedback do not seem to bring too much response, looks like I need to do something more to get the conversation on the UI Designer going. :-) I’ve decided to do a series of posts highlighting the important features of the new UI Designer, and for a start, I’ll describe the main design goals and key decisions that went into our work.
I’m very eager to receive any kind of feedback, positive or negative, on our work and its underlying decisions. Don’t hesitate to leave comments here or come to the forum or newsgroup. It’s still not too late for us to make major and significant changes in the product. And of course, the version of the UI Designer available in recent EAP builds is not final, and we have a lot of work remaining in our plans, and some cool feature ideas too. And if the current EAP version falls short of accomplishing some of the goals, rest assured that the situation will improve a lot in the final release.
So, first of all, let me state our goal: To create the most productive environment for designing and maintaining Swing interfaces of any complexity.
There are a number of key points in it. The first is the most productive. Of course, we would like our UI Designer to be the best in existence (who wouldn’t?), but there are too many ways to decide which one is the best, so we had to focus on one aspect of best. Our choice – productivity – shouldn’t come as a surprise for those familiar with our products.
Productivity, in my view, comes from a number of factors. The actions not essential for accomplishing the most common tasks should be removed from the workflow for those tasks. Every time the IDE can do part of the user’s work by itself, it should do so, or offer the user to do so. Every bit of information that the IDE can use to do its work better should be used. All common errors made by the user should be detected as soon as possible, and the IDE should offer to fix those of them that can be fixed automatically. The interface should always provide adequate feedback on the result of the user’s actions so that the user does not make these errors in the first place.
Later I’ll show how these factors come into play in specific features of the UI Designer.
The second key point is designing and maintaining. A piece of code written in a few hours or days usually gets maintained for many months or even years, so the ease of maintaining (expanding or modifying) existing UI forms is just as important for us as the ease of creating new forms. An interface that allows to build a form from a clean slate very quickly but provides unexpected results when the user starts dropping components into the middle of an existing form would not be acceptable for us. Also, it should be very easy to understand the structure of an existing form and its connections to other code. (Forms are in general much easier to figure out than Java code, but still the UI Designer should help as much as possible.)
The Swing interfaces point represents a limitation of our focus for this release (we’re not touching SWT or midlet form design, for example). It also means that we’re going to significantly expand the coverage of different Swing features in the designer. We’ve already done much work in that area (support for more property types, standard Swing layout managers, button groups and so on), and there’s also much work remaining to do before the final release.
Finally, of any complexity means that the designer should be equally suited for both simple and complex forms. For simple forms, we need to provide very easy ways to accomplish the most common tasks. For complex forms, we need to support building forms from multiple parts, easy possibility to combine hand-written UI components with UI Designer forms, easy ways to modify the form structure, and so on.
In the next post, I’m going to cover the key decisions on which the current UI Designer is based, some of which are new for Demetra and others have remained unchanged since previous versions of IDEA.
Looks like my blog has turned to announce-only mode – not good. However, today’s news is important enough to post regardless of the status of the blog. :-)
Today we have started the EAP for our new product – JetBrains Team Server, codename “Albus”. Its features were announced some time ago in the “Team Support” section of the Demetra roadmap, however, we decided to make it a separate product independent from IntelliJ IDEA. In fact, the product is not tied to Java either – support for building .NET applications will be provided as well.
OK, enough explaining for now – head over to the Download and Installation page to grab the bits, read the FAQ, and send your feedback in the forums and bug tracker. And I wish you many successful builds. :-)