Tuesday, September 30, 2008

Flash news: RTL support for DesignGridLayout

Tonight, I have just committed into Subversion the support of right-to-left orientation for DesignGridLayout. as a fix for issue #9.

Implementation was easier than foreseen, except for the test part itself (see below).

First of all, here are 2 screenshots with the same layout, but one uses LTR, the other uses RTL.





DesignGridLayout automatically discovers the orientation to be used for the container it is in charge of laying out, and simply inverts x coordinates if container is RTL-based.

Determining component orientation is based on the Component#getComponentOrientation() method which returns a ComponentOrientation instance. This instance determines the orientation of the text, it is not limited to horizontal LTR (eg English) and RTL (eg Arabic) languages, but also defines languages that are written vertically (all from top to bottom) and which "lines" (should we say "columns"?) are written from right to left (eg Chinese, Japanese) or left to right (eg Mongolian).

However, as far as I know, Swing components LAFs do not support components for vertical languages (I have never seen a vertical JLabel or JTextField), hence for these languages, we have to revert to the "usual" horizontal LTR orientation. For this, DesignGridLayout needs a simple trick to determine text orientation:
ComponentOrientation orientation = parent.getComponentOrientation();
boolean rtl = orientation.isHorizontal() && !orientation.isLeftToRight();

Just using orientation.isLeftToRight() is not sufficient because it would render eg Japanese horizontally from right to left, which I doubt any Japanese person can read (just imagine reading English from right to left!).

As mentioned above, implementing this enhancement was quite easy, but writing test cases for it was much more difficult than I expected.

My original idea for tests was just to set the default Locale to one of English, Arabic, Japanese or Mongolian (in order to cover the four possible situations defined in ComponentOrientation). But it turned out that just creating a new Locale through new Locale("JA") will work only if you have this Locale installed with your JRE, else a new Locale will be instantiated but it will be unusable; in particular, ComponentOrientation.getOrientation(Locale locale) will not return the expected value.

Since my JRE does not include Arabic, Hebrew, Japanese, Chinese and Mongolian, I had to find another way for testing. I chose to directly create a ComponentOrientation instance, but this is not possible since it has no public constructor and it is declared final! The only way to directly use ComponentOrientation is to use one of the 2 provided static instances LEFT_TO_RIGHT and RIGHT_TO_LEFT, which is what I did. But it prevented me from testing the new DesignGridLayout RTL support with vertical orientations.

Hence my call to DesignGridLayout users in Japan or China (for vertical right to left) and Mongolia (for vertical left to right) for testing the latest DesignGridLayout (in subversion trunk) with their respective Locale and send me a screenshot of their results. Thanks in advance!

That'll be all for today.

Sunday, September 28, 2008

Using DesignGridLayout 0.9 in Maven projects

Yesterday, I have released the latest official version of DesignGridLayout, almost 2 years after the previous official release (!), and 4 months after being handed over the project (Jason is still project owner but he is much too busy currently).

As mentioned in my previous post, lots of things have changed between these 2 versions.

Maybe one exciting news is that now, Maven users don't have to struggle to use DesignGridLayout in their projects. Indeed, version 0.9 is now uploaded to a maven repository accessible to anyone (no more need to manually install the jar into your local repository).

However, since I didn't use Maven "central" repository (the conditions for uploading an artifact there are too strict: all your dependencies must be present in central repo too), I wanted to briefly show how to use DesignGridLayout in your maven-based project.

DesignGridLayout artifacts have been uploaded to java.net maven repository. Hence you have to add this repository to your pom.xml (you may also add it to settings.xml if you prefer):
<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
</repositories>

Now you just have to declare the dependency as any other artifact used by your project:
<dependencies>
<dependency>
<groupId>net.java.dev.designgridlayout</groupId>
<artifactId>designgridlayout</artifactId>
<version>0.9</version>
</dependency>
</dependencies>

And voila! You are now ready to use DesignGridLayout for your GUI project!

In addition to DesignGridLayout jar artifact, the repository also contains javadoc and source artifacts that you can automatically download, eg for your IDE (for eclipse, you can follow the instructions there).

Note that swing-layout.jar, the only dependency of DesignGridLayout, will be automatically downloaded to your local repository.

That's it for today, enjoy!

Thursday, September 25, 2008

DesignGridLayout news

Two months ago, I had announced my participation to the OSS project DesignGridLayout.

As a brief reminder, DesignGridLayout is a LayoutManager for Java Swing GUI, which main advantages are:
  • Good looking dialogs (alignment, spacing, sizing, visual balance): this is taken over by DesignGridLayout itself without any special hint from the developer
  • Reduced learning curve for developers, thanks to the fluent API which is, at the same time, simple, effective, compile-safe (no cryptic strings to express the layout) 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 inserting a new line of code in your layout setup code...
During the past 2 months, after struggling with the switch from CVS to SVN, I have finally finished taking the project over.

In the past few days, I have checked in the latest source code into SVN, and updated the web site.

Several things have changed in this project (as compared with previous 0.1.1 version):
  • License: the original GPL has been changed to ASL 2.0, much more open
  • Build: now the project uses maven 2 for the build and the site generation
  • Package: the old "zappini.designgridlayout" has been changed to a more standard "net.java.dev.designgridlayout"
  • Source code: it has been refactored to improve the API and ease future evolutions
  • Issues: all known bugs have been fixed
  • API: it has been improved on several points (more on this below) such as its narrowing (in order to prevent calls that have no effect, hence potentially pollute source code using DesignGridLayout), as well as the implementation of a few enhancements
  • Javadoc: has been completely rewritten and completed for all public API, along with examples in the package description
Improvements on the API consist essentially in using different interfaces for the different "rows" created by DesignGridLayout:
  • IRow
  • IGridRow extends IRow
  • INonGridRow extends IRow
These interfaces define the exact methods available to each kind of row. Once a row has been created, you cannot change its type (e.g. from Grid to Center) as you could before, which was useless, required more calls and led to some flaws in the API (e.g. what should happen if you set the row type to Grid, then back to Center; and why would you do that?).

Moreover, in DesignGridLayout, methods that create rows have been specialized to determine upfront which kind of row is to be created:
  • DesignGridLayout#row() creates a grid row (IGridRow)
  • DesignGridLayout#centerRow() creates a non grid row, with centered components (INonGridRow)
  • DesignGridLayout#leftRow() creates a non grid row, with left-aligned components (INonGridRow)
  • DesignGridLayout#rightRow() creates a non grid row, with right-aligned components (INonGridRow)
  • DesignGridLayout#emptyRow(int height) creates an empty row, with no component at all (used for introducing vertical spacing between rows)
Other changes in the API are:
  • Removal of IGridRow#label(String) to keep only IGridRow#label(JLabel): this was motivated by the fact a LayoutManager should not create components by itself (arguable opinion, I admit); in addition, this reduces one's options for GUI i18n (one option is to use Component#getName()) to set its text, which is impossible here, since the end-developer code can not get hold of the created JLabel)
  • Row.EMPTY "component" is replaced by IGridRow#empty() methods
  • New INonGridRow#fill() added to allow extreme components to take all remaining space in the row. This is particularly useful to split groups of rows with a label and a separator (as in Karsten Lentzsch FormLayout)
  • New IRow#addMulti() method to add several components in only one grid column, which is useful when you have components that should always "stick together" (eg a JSpinner and a JLabel indicating a unit of measure)
With all these changes, all constants and enum have been removed from the previous version because they serve no purpose now.

You can find the current snapshot (named "0.9-SNAPSHOT") of this version there.

So a further question is "when will the official 0.9 version be released?". That should be short now, we should expect an official release by mid October, including uploaded artifacts to some maven repository (for developers using maven).

What's the roadmap for 1.0?

There are a couple of enhancements requests submitted here.

The main enhancement planned for 1.0 will be the support for variable height rows that would get extra height during resize; this is particularly useful for rows that include components such as JList, JTable, or more generally any component wrapped in a JScrollPane.

Another interesting feature I would like in 1.0 release is components spanning several rows. This is a particularly useful feature and I know several users have been expecting it. The difficult part here will be to define the right API for that, in order to keep this feature easy to use, easy to visualize and safe (reducing potential errors at runtime by catching them at compile-time).

Finally, 1.0 release may include some attempts at right-to-left languages support. This will depend on several factors.

In any case, if you are a DesignGridLayout user or consider it for your next Swing GUI, please take your chance and participate in the discussions on the 3 issues above, so that DesignGridLayout can keep its spirit while bringing important features common in daily GUI design work.

Of course you can also suggest other enhancements and report bugs if you find any.

You can find more details on DesignGridLayout here.

Enjoy GUI design with DesignGridLayout!