Saturday, December 27, 2008

Should we fork swing-layout project?

The swing-layout project was the initial effort to bring Swing a better layout system that would in particular take into account the specificities of the installed Look & Feel, alongside baseline alignment support.
Swing-layout works with Java5 (maybe Java1.4, I don't know, I have never checked).

This is where the new Java6 GroupLayout has been elaborated before integration into Java6.

Besides bringing a new LayoutManager that provides better layouts (at the expense of higher complexity in use, except if you use NetBeans Matisse designer), swing-layout also brought utilities available to other third-party layouts, in particular the aforementioned baseline support.

DesignGridLayout is one of those LayoutManagers that relies on swing-layout for baseline alignment. It is also one of my Open Source projects.

Swing-layout was available before Java 6 and, of course, the release of Java 6 has made it somewhat irrelevant (at least for the rare developers who could jump to Java 6 immediately).

Now it is strange to discover that Java 6 baseline support is better than swing-layout itself (when using Java 5). Indeed, the swing-layout project on java.net has been left in limbo for about 2 years, and it looks nobody is really responsible for it, several issues are still open and nobody cares!

So what should happen to this project? Should it definitly be buried in favor of Java 6?
Or, stated differently:
Do we necessarily need to upgrade to Java 6 to have good Swing layouts?

I don't think so! Java 5 is still mainstream nowadays, and it is planned to reach EOSL in one year (that's still some amout of time!). So I strongly believe Java 5 users should not be left behind.

Why do I talk about this topic here? As a matter of fact, I have hit swing-layout bugs in DesignGridLayout and I am facing a tough decision:

Should I leave DesignGridLayout Java 5 support behind and require Java 6 as a minimum?

Or should I try my best to keep Java 5 support -with no difference in the provided features- at least for one more year?

If so, how should I deal with swing-layout bugs?

One idea I had was to fork the swing-layout project and create my own, with the same license (LGPL). Although it seemed to me a good idea, the problems I got with this is that:
  • I don't have the facilities to test all cases (MacOSX, Linux GTK)
  • I don't have much time left for Open Source (I already have 4 OSS projects and I can't deal with them all, I always have to put one in top priority -currently DesignGridLayout- while the others have to wait, sometimes for several months)
  • I don't want to support GroupLayout which I don't use and which is a competitor of my own DesignGridLayout!
Indeed, yesterday I have refactored the whole baseline support in swing-layout (because currently everything is in one huge class with a lot of terrible code, very difficult to maintain and extend). I have fixed the two problems I have in DesignGridLayout (JScrollPane and JTableHeader baselines). This works but I don't know yet if I'll keep it (because it is LGPL and DesignGridLayout is Apache License 2) as part of DesignGridLayout source code.

Thus I think that, unfortunately, I'll have to throw away this code (is there someone interested out there?) and try to stick with the "official" swing-layout release and find some workaround that can be implemented directly in DesignGridLayout as a caller (no license incompatibility).

Of course, if someone is motivated and ready to take over the effort of forking swing-layout, then I would happily give back my work to that new project. Just drop me a note.

The rant

Now the status of this library, sponsored by Sun, reminds me of other "currently on-going" (:->) efforts such as: JSR-295 (beans-binding), JSR-296 (Swing Application Framework).
Once again, although Sun claims they don't leave Swing behind, they actually do, in favor of that half-baked JavaFX thingy, which is not even comparable to its competitors, which we may wonder if it deserves the "1.0" version number. Layout support in JavaFX made me laugh big times (it all boils down to HBox and VBox).

Maybe it's time to start forgetting Java (and Swing?) and learn something new (anything but JavaFX).

Sunday, December 07, 2008

Announce: DesignGridLayout 1.0 released!

One month after the third release candidate of DesignGridLayout 1.0 (1.0-rc3), no new bugs being received, I have decided to release the official 1.0 version of DesignGridLayout.

I trust this version to be stable and bug-free (however, if you do encounter a bug with it, do not hesitate to report it, I will be glad to provide a fix in a timely manner).

For me, this means I can now start seriously working on the next enhancement (for 1.1 version) that will allow users to define some components spanning several rows. You can already have an overview of the future API (up to the current state of my reflection) if you are interested.

If you have further questions about DesignGridLayout, please don't hesitate to ask in the corresponding project lists.

Sunday, November 16, 2008

My presentation on JSR-296 at Jazoon 08

I have just seen that Jazoon has removed all presentations files of Jazoon 08 talks.
That's the occasion for me to post the content of my talk on "JSR-296 Swing AppFramework from the trenches".

The full content (in PPT format) is here (I have just removed the Jazoon template stuff). If you don't have PowerPoint, here is a PDF version (unfortunately without the original animations). Unfortunately I could find no way to convert it to ODP format (for OpenOffice users) without big losses in animations but also in diagrams (most of them got terribly ugly after conversion). I am afraid I'll have to give up on that one (if anyone can convert the original PPT to ODP please email me the result and I'll post it here).

If you want to have an idea of the content before download, here is the agenda:
  • Introduction
    • why do we need a Swing framework
    • what is JSR-296? what does it bring (in a nutshell)?
    • about the presented applications
  • Application Lifecycle
    • standard application lifecycle
    • adding dependency injection (Spring, Hivemind, Guice)
    • adding docking capability (MyDoggy)
    • tips & pitfalls
  • Resources & I18N
    • resource injection principles
    • what about JTable?
    • tips & pitfalls
  • Actions & Tasks
    • a better, more responsive, javax.swing.Action
    • where should I put my @Action?
    • when should I use a Task?
    • what about Exception handling?
    • tips & pitfalls
  • Persistent Session State
    • state restoration (or users' happiness)
    • what is stored? what is not? where?
    • tips & pitfalls
  • What is missing for a complete GUI framework?
    • GUI framework architecture
    • Example: EL4J Swing stack
  • Future
    • JSR-296 standpoint
    • what's likely to change?
Please note that, considering the recent events about Sun in general, and Swing in particular, the "Future" section of the presentation is probably largely obsolete:-(
Still, I believe that Swing is a better platform for GUI development than many others (not just talking about Java here), and developers will still use it for a couple of years more (maybe not in pure Java, though, other options exist: Groovy, Scala). Wait and see...

Enjoy!

Wednesday, November 05, 2008

Announce: DesignGridLayout 1.0-rc1 released!

I am particulaly glad to announce the first release candidate of DesignGridLayout V1.0.

DesignGridLayout is a Swing LayoutManager, revolutionary by its API, simple but powerful. Its main advantages are:
  • Good looking forms (alignment, spacing, sizing, visual balance): this is entirely taken over by DesignGridLayout itself without any special hint from the developer
  • Reduced learning curve for developers, thanks to its fluent API which is simple, effective, compile-safe and IDE code-completion friendly
  • No graphics designer needed: the API is the graphical designer
  • Readability and maintainability: you can literally "visualize" the layout by browsing the code that sets it up; inserting a new row of components is done by simply inserting a new line of code in the layout setup code...
  • Free: the project is open source and released under Apache License 2.0
Version 1.0-rc1 is available here or through the java net maven 2 repository (for more info, you can check my previous post and replace "0.9" with "1.0-rc1").
This version brings the following improvements:
  • #13: support for multiple groups of fields, each with its own label column
  • #5: smart vertical resize: DesignGridLayout automatically determines which rows should grow vertically and also make sure that components height is suitable to display an entire line of information (useful for JList, JTable, JTextArea)
  • #18: smarter horizontal resize behavior: now DesignGridLayout won't resize components under their minimum size
  • #9: automatic support of right-to-left text orientation based on Locale
  • #16: smarter gaps for empty rows
  • #15: resolution independence
  • #20: fixed ugly layout problem when container has a border
  • #12: now setLayout() is automatically called by DesignGridLayout constructor
Please note that V1.0 required API changes that I could unfortunately not keep compatible with previous 0.9 release. This should be the last time that happens (V1.1 should only extend the current API).

I consider the current version ready for production as the current test suite of DesignGridLayout is quite comprehensive and covers all its features.
However, I have decided to prepare a release candidate to give myself a chance to fix any problems that users may find but that I could not discover by myself (in particular, problems related to platforms that I don't have: MacOS-X, Linux, Solaris).

If needed, I will create further release candidates. I will wait about one month after a rc until I cut a final release.

What's next?
  • first of all, I'll get some rest;-)
  • then I'll spend some weeks on my other open source project, guice-gui
  • finally I'll start working on DesignGridLayout V1.1, which should include just one improvement (issue #10: support for components spanning several rows) which should be released as a Christmas present;-)
Enjoy it and don't hesitate to report any problems or enhancements!

Monday, November 03, 2008

In search of the perfect API (final part)

This is the last post of my series on DesignGridLayout API evolutions. As mentioned before, although I use DesignGridLayout to illustrate it, this series might be useful to any developer of libraries.

In the first, second, third and fourth posts, I have described the evolution of DesignGridLayout API from its original release to the latest -soon released now- V1.0.

This last post is more a reflection on the next probable evolution of this API. This means that anything shown in this post has not been implemented (and might be difficult to implement), but thinking in terms of API first rather than implementation should be your mantra when writing a library with a large users base (I'm dreaming aloud;-))

Immediately after releasing V1.0 (in a few days), I'll start working on V1.1, which main enhancement will be issue #10 (add support for components spanning several rows).

This is not an easy problem, API-wise; indeed, you have to keep in mind the following principles that DesignGridLayout project adheres to:
  • the feature (API) must be easy to understand and use
  • the code visually represents the actual layout
  • developer mistakes must be avoided or can be found (and eradicated) at compile-time
I would also add an important point here:
  • don't break the current API (and the existing code that uses DesignGridLayout library V1.0)!
With this in mind, let's try to sketch what we would like the user to write (in terms of code), starting from a layout that is possible in V1.0:
layout.row().grid(lbl1).add(table1).add(field2);
layout.row().grid() .empty() .add(field3);
layout.row().grid(lbl4).add(field4);
Note that table1 represents a JList in a JScrollPane with a preferred size of a few rows (let's say 2 for this example).

Here is a snapshot of the displayed layout for this snippet:


Here we can see that with DesignGridLayout V1.0, table1 is displayed at its preferred height but this fixes the height of its whole row. Hence a lot of empty space is lost on the second column of the layout. Instead, wee would like to have table1 span on the second row as well (that's why we have already put an empty() column in the same column in row 2).

Now how can we let the user indicate that table1 should span on 2nd row?

One option I have in mind is something like this:
layout.row().grid(lbl1).add(table1).add(field2);
layout.row().grid() .spanRow() .add(field3);
layout.row().grid(lbl4).add(field4);
Using "spanRow()" on the second row would have the following meaning:
  1. the component on the previous row at the same column position in the same sub-grid will span this row
  2. the horizontal span of this component will be the same as the column span defined for that same component on the previous row
  3. the sub-grid in which spanRow() appears will have its gridspan forced to the same value as the sub-grid in the same position of the previous row
  4. if the matching component in the previous row is empty() or empty(n), then spanRow() is also empty() or empty(n)
  5. if this is the first row in the layout, then spanRow() is equivalent to empty()
This definition solves some problematic cases when using column spans in a grid:
layout.row().grid(lbl1).add(table1, 2).add(field2);
layout.row().grid() .spanRow() .add(field3);
layout.row().grid(lbl4).add(field4);
Or even when using multiple sub-grids:
layout.row().grid(lbl1, 2).add(table1).add(field2);
layout.row().grid(1) .spanRow().add(field3);
layout.row().grid(lbl4) .add(field4) .grid(lbl5).add(field5);
However, there is a problem in this latter example: in second row, we specify a gridspan of 1, but the actual gridspan will be 2 (the same as in the first row)! This looks counter-intuitive.

One approach to solving this problem would be to prevent the possible call to grid(int gridspan) or grid(JLabel label, int gridspan).

But the only way to prevent it would be to explicitly indicate that, when we create a new sub-grid in a row, this row will include row-spanning components, and in this case we can restrict the interface to prevent setting explicitly gridspans.

For this we could simply change the signature of grid methods in ISubGridStarter interface:
public interface ISubGridStarter {
public ISpannableGridRow grid(JLabel);
public ISpannableGridRow grid();
public IGridRow grid(JLabel, int gridspan);
public IGridRow grid(int gridspan);
}
Here we introduce a new interface ISpannableGridRow which is defined as follows:
public interface ISpannableGridRow extends IGridRow {
public ISpannableGridRow spanRow();
}
This is just an extension of the normal IGridRow with one extra method that allows spanning of components.

Now there is another problem (unsolved yet, else this issue would be fixed in V1.0 already;-)), related to vertical resize feature.
DesignGridLayout has the notion of rows that can vary in height or not (based on the components they hold); in addition, it allows you to define a vertical grow weight factor for those rows with variable height (see DesignGridLayout.row(double weight) method).
Now that components can possibly span several rows, how should we address the way individual rows will be shared vertical space?
Or is this really a problem? Can't the current algorithm work as well? Only a prototype for issue #10 will tell us...

For the definitive API of DesignGridLayout V1.1, well, I guess we'll have to wait until official release;-) maybe as a Christmas present, or sooner if I can manage!

This post closes my long discussion on searching the best possible API for a library. Maybe, in a later post, I'll show implementation details for this API (in particular, how return co-variance (Java 5+) has helped me much for that).

Hope you found this series interesting. Don't hesitate to comment! Enjoy.