The first post discussed the original V0.1 API and its related issues.
The second post has shown how to solve most V0.1 issues.
The third post has dealt with API improvements driven by new features. In particular, one interesting change to the API has been to introduce a new interface ISubGridStarter to reduce the list of available methods in a context, these methods then returning the "full" interface IGridRow.
In this installment, I will talk about the latest changes made to the API before V1.0 is released (which should happen very soon now).
Latest 1.0-SNAPSHOT: back to 0.1?
First of all, I was not very happy with the new methods I introduced in DesignGridLayout class in one of both previous snapshots:
public class DesignGridLayout {There is a lot of repeat here. In addition, it is not clear why "row()" is not "gridRow()" (lack of consistency).
public INonGridRow leftRow();
public INonGridRow leftRow(double weight);
public INonGridRow rightRow();
public INonGridRow rightRow(double weight);
public INonGridRow centerRow();
public INonGridRow centerRow(double weight);
public IGridRow row();
public IGridRow row(double weight);
}
In addition, the ISubGridStarter interface uses methods all named "label()" to actually do 2 things:
- Start a new canonical sub-grid
- Set a label to this new sub-grid (or no label at all)
Actually, I prefer something like that (in terms of usage):
layout.row().left().add(...);Several changes have occurred to make this kind of code possible.
layout.row(1.0).grid(lbl1).add(...).grid(lbl2).add(...);
layout.row(0.5).grid() .add(...).grid(lbl3).add(...);
First I introduced (once again) a new interface:
public interface IRowCreator extends ISubGridStarter {I also modified ISubGridStarter (only the method names):
public INonGridRow left();
public INonGridRow right();
public INonGridRow center();
}
public interface ISubGridStarter {You have to remember that IGridRow extends ISubGridStarter (which allows to later start new sub-grids in a row).
public IGridRow gridJLabel);
public IGridRow grid();
}
Finally, I simplified DesignGridLayout API:
public class DesignGridLayout implements LayoutManager {Now we have only 2 general methods to create a new row (whatever its type), one allows you to specify the vertical growth weight factor (the no-arg row() will automatically determine if the actual row should have variable height and, if so, assign it a default weight of 1.0).
...
public IRowCreator row();
public IRowCreator row(double weight);
public void emptyRow();
}
Also note that we still keep emptyRow(), but it has lost its "int height" argument, this is due to an improvement of the behavior (issue #16: make emptyRow smarter).
Now we can code our layouts like that:
layout.row().grid(lbl1).add(field1) .grid(lbl2) .add(field2).add(field3);The snippet above will exhibit the following layout:
layout.row().grid() .add(field4).add(field5) .grid(lbl3) .add(field6);
layout.row().grid() .grid(lbl4) .add(field7).add(field8).add(field9);
layout.emptyRow();
layout.row().center().add(ok).add(cancel);
The source code reflects the way the container will be laid out.
Code completion is helpful in that it does not authorize useless, or erroneous, method calls.
In fact, we have just built a simple "DSL" for laying out a Swing container!
To summarize, here is what we have gained in consistency (compared with previous 1.0-SNAPSHOT):
- you add a new row to your form with one of two methods, named the same (row())
- once a new row has been created, you can only choose its type in a clear way (left(), right(), center() or grid())
- on a grid row, you can start a new sub-grid at any time with grid(), this is consistent with the way you started the grid row (because a grid row starts with a sub-grid)
- it is never possible for users to call a meaningless API (e.g. add(JComponent child, int span) in a non-grid row)
- thus the number of options (callable methods) to the user in a context is restricted to its minimum (easing the search of methods through code completion in your IDE)
This API should now be considered stabilized and there should be no change until the first official release candidate 1.0-rc1 of DesignGridLayout (which should be in a few days now).
In the next (and last) installment, I will talk about the future extensions of DesignGridLayout API (due for V1.1), necessary to implement the issue #10 (Support for components spanning several rows).
No comments:
Post a Comment