Wednesday, June 23, 2010

Headon That Table



A couple of important news before I begin, Terrence Barr has written a great new LWUIT introductory article for java.net and its at the top of java.sun.com... Great for introducing people to LWUIT!



Ofir has just passed a significant milestone of 1000 commits into our java.net SVN repository, take into consideration that we had an internal repository where we are passed the 56k version number... Its not strictly LWUIT commits though ;-)



The main subject of this post though is fixed table headers. The default LWUIT table implementation scrolls the title together with the table body, we made that choice since we assume small tables as the main use case. Fixing a column or a row (such as the titles of the table) into place isn't trivial in an efficient way. However, its possible to do something like that by using two tables and keeping their scrolling in sync.



This works great and pretty seamlessly for touch/keyboard usages however the approach has one major drawback that the size of the title might differ from the size of the cells thus causing the table titles to be misaligned from the table columns.



The solution I chose was to hardcode the cell sizes based on the size of the titles, you can obviously adapt that approach to something more appropriate for your need.



public class FixedTableDemo extends MIDlet {

private static final String[] TITLES = {"Title 1", "Title 2", "Title 3", "Title 4", "Title 5", "Title 6", "Title 7", "Title 8", "Title 9"};

private static final int ROWS = 100;

private static Dimension[] TITLE_SIZES;



static class MirroredTable extends Table {

private MirroredTable mirrorTo;

public MirroredTable(TableModel m) {

super(m);

}



public MirroredTable(TableModel m, boolean b) {

super(m, b);

}



public void setScrollX(int x) {

super.setScrollX(x);

if(isDragActivated()) {

mirrorTo.setScrollX(x);

}

}



/**

* @param mirrorTo the mirrorTo to set

*/


public void setMirrorTo(MirroredTable mirrorTo) {

this.mirrorTo = mirrorTo;

}



public Component createCell(Object value, int row, int column, boolean editable) {

Component c = super.createCell(value, row, column, editable);

if(TITLE_SIZES != null && TITLE_SIZES[column] != null) {

c.setPreferredSize(TITLE_SIZES[column]);

}

return c;

}

}



public void startApp() {

Display.init(this);

Resources r;

try {

r = Resources.open("/LWUITtheme.res");

UIManager.getInstance().setThemeProps(r.getTheme(r.getThemeResourceNames()[0]));

} catch (IOException ex) {

ex.printStackTrace();

}

Form f = new Form("Table Title");

MirroredTable titlesTable = new MirroredTable(new DefaultTableModel(TITLES, new Object[0][0]));

TITLE_SIZES = new Dimension[TITLES.length];

for(int iter = 0 ; iter < TITLES.length ; iter++) {

TITLE_SIZES[iter] = titlesTable.createCell(TITLES[iter], -1, iter, false).getPreferredSize();

}



Object[][] body = new Object[ROWS][TITLES.length];

for(int rows = 0 ; rows < body.length ; rows++) {

for(int cols = 0 ; cols < body[rows].length ; cols++) {

body[rows][cols] = "" + rows + ", " + cols;

}

}

MirroredTable bodyTable = new MirroredTable(new DefaultTableModel(TITLES, body), false);

bodyTable.setMirrorTo(titlesTable);

titlesTable.setMirrorTo(bodyTable);

bodyTable.setScrollable(true);

titlesTable.setScrollableX(true);

f.setScrollable(false);

f.setLayout(new BorderLayout());

titlesTable.setTensileDragEnabled(false);

bodyTable.setTensileDragEnabled(false);

titlesTable.setIsScrollVisible(false);

f.addComponent(BorderLayout.NORTH, titlesTable);

f.addComponent(BorderLayout.CENTER, bodyTable);

f.show();

}



public void pauseApp() {

}



public void destroyApp(boolean unconditional) {

}

}





4 comments:

  1. Hi Shai, I hope you can help me with a question: I want to display two Lists on Screen (simultaneosly) and I want to show 4 elements in first one and 2 elements in second one. So, how can I modify the size of displayed elements in List?

    ReplyDelete
  2. @cachola: make sure your preferred size for the entries and the titles is identical.

    @alvaroneto: List.setMinElementHeight will determine a minimum number of visible elements if possible. However, it won't prevent a list from growing if the layout manager chooses to ignore the preferred size. You can use box Y which should work as you want.

    ReplyDelete
  3. Hi shai

    im new in lwuit, but im very happy of the capabilities it offers, like @alvaroneto i have the same question about how can i reduce of the items show in a list. List.setMinElementHeigth doesnt work, and how is the box Y that you metioned?

    ReplyDelete