Thursday, January 01, 2009

DesignGridLayout: row-span support soon ready!

December 2008 has been a busy month for me on DesignGridLayout.

Although not yet completely ready for a first 1.1 release candidate, the current Subversion trunk already includes some interesting changes:
  • added support for components spanning multiple rows (issue #10): this is further discussed below
  • fixed several problems with baseline alignment (only on Java 5): issues #3 and #27
  • fixed a problem with smart vertical resize of JList (issue #28)
  • fixed an exception with multi-grid feature (issue #26)
  • optimized the size of the example jar (removed all screenshots that are used during automatic tests)
  • completely refactored the examples application: see below

New showcase application

Much of my past efforts on DesignGridLayout were spent on reworking the original examples application which was overly simplistic and not a very good way to "sell" DesignGridLayout. Hence I have written from scratch a new showdown application that:
  • demonstrates all DesignGridLayout features from the basics to the more advanced uses (arranged in a tutorial-oriented way)
  • describes each feature
  • always shows the relevant source code that produces every sample
  • allows you to launch the layout in a separate frame in order to test its resize behavior
  • asks you to choose your preferred Look & Feel so that you are not limited to the old-fashioned default Metal look & feel
Here is a screenshot of this new showdown application (with Windows XP look & feel):


Now the good news is that, although there is no official release of this new DesignGridLayout application, you can already launch it today! Just click the jnlp link below:


Multiple row span

This is the main improvement to the future DesignGridLayout 1.1.
I had to slightly change the API (completely backward compatible with 1.0), as described in one previous post on this blog. As a reminder, here is a simple example:
layout.row().grid(label("lbl11")).add(field("field11")).grid(label("lbl12")).add(list());
layout.row().grid(label("lbl21")).add(field("field21")).grid().spanRow();
layout.row().center().add(button());

Note the spanRow() call on the second line of code. This states that "in this position of the current row, span the component that is in the same position on the row above".

The result looks like this:


Please note there's a catch in this snapshot: the list size does not obey the "smart vertical resize" feature of DesignGridLayout (first introduced here). That's one open point in the current source code.

This open point is to decide whether the layout should keep the "smart height" for a multi row span component or not:
  • if we don't keep it, then at preferred size, the bottom border of the list is aligned with the bottom border of the field (example above)
  • if we keep it, then there won't be such alignment, which may look quite ugly as in the snapshot below


I am currently inferring about what to do here. I wonder if this should be left as an option (new API) to the end user. Among the available options:
  1. disable smart vertical size for multi row span components (current situation)
  2. enable smart height with loss of bottom border alignment (as in snapshot above)
  3. enable smart height but keep bottom border alignment (or baseline alignment with the last visible row of the list). This means that there will be a strange vertical spacing between first and second field. I am not even sure that this is feasible actually, I'll need to investigate further.
Additional decisions would concern the form of the API to select the behavior, in particular, I have to find out a light API (that does not make the current one heavier) and which granularity to give this API, more precisely, at which level the behavior should be selectable: the whole layout, each row, or every single multi row span component? The finer the level, the heavier the API, the more complex it is to use...

The behavior of spanRow() is described in the future 1.1 javadoc (not released, but you can already build it from the Subversion trunk).

A second catch (not visible in the example above) with the "spanRow()" API is that, unfortunately, it is now possible to code (and compile) a layout that cannot be rendered at runtime, because it just makes no sense, as in the following example:
// spanrow() called on a subgrid with different number of columns
layout.row().grid(label("lbl1")).add(field("field1"), field("field2"), field("field3"));
layout.row().grid(label("lbl4")).add(field("field4")).spanRow();

The spanRow() call on the second row does not match a single component of the first row, but there are 2 candidate components to be spanned: field2 and field3.

Since there is no way to discover this problem at compile-time, DesignGridLayout performs the check at runtime and will replace each incorrect spanRow() call with a special "marker" component (with a tooltip that gives further information) to show that the original source code has to be reworked.

The following screenshot shows many examples of incorrect API usage:


This screen is also available from the showdown application.

Roadmap

Once I can progress on the open point presented above, I will be able to propose a first release candidate of version 1.1. That should be ready by mid-january hopefully. The final 1.1 version will be released 3-4 weeks after the latest stable (no open bug) release candidate.

Enjoy!

9 comments:

  1. After further tests, option 2 is the best:
    - always keep smart vertical (re)size
    - this shall not even be user-selectable
    - in addition, in a set of rows sharing a spanned component (that can vary in height), only the last row should grow in height, the other rows should have fixed height.

    I have just committed this change to the Subversion trunk (rev. 201).

    Now I still have documentation to update, plus a few more tests (special situations I fear might not work well yet).

    ReplyDelete
  2. Hello Jean-Fracois,

    I don't want to rain on your parade in any way, yet I feel obliged to note that the features you want in your layout manager is in MigLayout already, and then some. I just say this to give you a proposition. The thing that DGL does that MigLayout doesn't is creating the widgets. In that way DGL is a builder and not really just a layout manager, DGL is more than just a layout manager.

    Instead of creating a new layout manager+builder you could just leverage MigLayout's layout enginge and wrap it in a cleaver way to add the building support. I think that would mean a lot less double effort and stop the "Not Invented Here"-syndrome.

    MigLayout handles a lot more things than DGL. For instance your layout manager does not at all adhere to design guidelines for the platform, while MigLayout does (notions such as "related" and "unrelated" per platform for instance).

    So, my suggestion is to stop the double effort here and instead create a builder tool that leverages MigLayout.

    I know of course that I'm saying that "mine is better than yours" and I'm sorry for that. But I think that a lot of unnecessary effort can be avoided and double effort is just time and effort thrown away.

    If you think that the layout engine of DGL can handle more things than MigLayout you should continue your work, at least if it is important things that are missing. Otherwise, let's work together instead.

    Cheers,
    Mikael Grev
    Creator of MigLayout

    ReplyDelete
  3. Dear Mikael,

    I appreciate your proposition but I have to refuse it because:

    - I owe it to DesignGridLayout users (even though they may be less numerous than MigLayout users)

    - I also owe it to DGL original author, Jason Osgood, who has made a formidable work with the initial releases of DGL

    - competition is sane, and sane competition is good (some "special" features that DGL has but Mig doesn't -see below- would not exist if I was just writing a builder over Mig): this fosters innovation, and I truly believe DGL innovates in terms of layout

    - I feel I "own DGL code", I mean that I know every single line of code so I can easily enhance it, I don't think participating in Mig code would be that straightforward for me (and I'm a bit too lazy to do so)

    - I don't think writing an equivalent builder as a wrapper over Mig would be as easy as you think, I mean, if I wanted to keep the current DGL API (and I would not want to change it)

    Now I would like to comment some of your points that are just wrong:

    1. You mention "the features I want", you mean "the features DGL already have", it looks you consider DGL to be the new kid on the block, which is incorrect, see below.

    2. The only added value of DGL over Mig is "the builder thingy": that's plain wrong! There are a few features (in particular, the "smart vertical resize") that are unique to DGL.

    3. NIH syndrome: first of all, if I was victim of NIH then I would have created my own layout from scratch; I have taken over the DGL effort just 6 months ago, but DGL has been existing since January 2006)

    4. Platform guidelines adherence: the latest release of DGL is compliant to the "related/unrelated" gaps (both horizontal and vertical)

    5. Double effort: I don't get the impression of wasted effort on DGL. I think my efforts are worth, there are things in DGL that Mig doesn't do (or don't do very well as far as I could see, eg the vertical span has a strange behavior on you example application). The original idea of DGL was to ease the layout work while giving the developer a tool that guides him in designing layouts with a good look & feel. That's what I consider an advantage of DGL, while Mig allows ANY layout (which some people may consider an advantage, while others would disagree)

    Make no mistake: I don't claim that DGL is better than Mig, it is simply different and brings some advantages (eg impossible to have an ugly GUI) plus some unique features worthy of a layout (smart vertical resize). Thus I believe it is sane to have it as another option for GUI developers.

    That's the exact reason why, 2 years ago, I have selected it (as a user) over Mig while I was trying to replace the terrible GridBagLayout. The layout showdown of John O'Conner gave me enough clues to perform the selection I found best for me.

    So for the time being, I think I'll go on improving DGL until I consider it perfect for its normal usage (and it should be in 1.2).

    Please fill free to borrow DGL ideas & concepts in Mig if you like, DGL is open source after all!

    Cheers, Jean-Francois

    ReplyDelete
  4. It seems that the "codebase" is missing in the jnlp file:

    MissingFieldException[ Das folgende erforderliche Feld fehlt in der Startdatei: <jnlp&ght;(<codebase>|InternalError(thisCodebase)]
    at com.sun.javaws.jnl.XMLFormat.parse(Unknown Source)
    at com.sun.javaws.jnl.LaunchDescFactory.buildDescriptor(Unknown Source)
    at com.sun.javaws.jnl.LaunchDescFactory.buildDescriptor(Unknown Source)
    at com.sun.javaws.Main.launchApp(Unknown Source)
    at com.sun.javaws.Main.continueInSecureThread(Unknown Source)
    at com.sun.javaws.Main$1.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

    ReplyDelete
  5. Well that's strange I have absolutely no problem launching it from FF3 with the Java Sun plugin (1.6u11).
    On what environment do you get this error (Browser, Java plugin, OS)?
    Did you try to download the JNLP and launch it outside the browser? Does it work or not?
    Do you have a fix to propose (I am no JNLP expert unfortunately) so that I can update it and make the example application available to more people?

    ReplyDelete
  6. I had a similar problem, found the solution at
    http://forums.sun.com/thread.jspa?threadID=77683&&tstart=1876
    which was to set codebase="file:."

    ReplyDelete
  7. Ha, Mikael Grev comes on to your blog and rudely insults your efforts, telling you that you are wasting your time because MIGLayout is better. MIG doesn't even do canonical grids, so WTF is he talking about? What an asshole!

    MIGLayout is overly complex at best. It looks like more and more features were added and now it is just bloated. The string syntax is much more complicated than it needs to be, and a 300kb JAR for a layout manager?

    ReplyDelete
  8. Thnaks n4te for your support of DesignGridLayout. I generally agree with you that MigLayout string syntax is too complicated in general.

    I don't care much about what Mikael said above, I just continue working with DesignGridLayout because I think it is worth.

    ReplyDelete
  9. Hi man I been use DesignGridLayout for two year now very easy to use and fast i can have mock-up done very fast for the boss.Now i try out more GIF images on the DesignGridLayout to created animation with the DesignGridLayout. But I have no idea how the repaint and revalidate work on DesignGridLayout the only way is to delete and created a new frame.So how do repaint work on DesignGridLayout .

    ReplyDelete