At the 2010 Google IO it was announced that GWT 2.1 would include new Data Presentation Widgets. 2.1M is available for download, and presumably the widgets are included, but no documentation has yet su开发者_开发技巧rfaced.
Is there a short tutorial or example for how to use them? I've seen a rumor that CellList and CellTable are the classes in question. The Javadoc for them is riddled with lots of TODOs, so quite a bit is still missing in terms of usage.
Google I/O 2010 - GWT's UI overhaul
javadocs package com.google.gwt.cell.client in 2.1
Eclipse update site for milestone 2
While the code is in bikeshed, add this line to your gwt.xml file:
<inherits name='com.google.gwt.requestfactory.RequestFactory'/>
The following examples follow:
- CellList of TextCells with PageSizePager
- CellList of TextCells with a SimplePager
- CellList of TextCells with a SimplePager and PageSizePager(buggy) and
- CellTable with String header and TextCell header
package dpw.client;
import java.util.ArrayList;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.PageSizePager;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.ListViewAdapter;
public class Index implements EntryPoint {
public void onModuleLoad() {
// create some data
ArrayList<String> values = new ArrayList<String>();
values.add("one");
values.add("two");
values.add("three");
values.add("four");
values.add("five");
values.add("six");
// create a ListViewAdapter
ListViewAdapter<String> lva = new ListViewAdapter<String>();
// give the ListViewAdapter our data
lva.setList(values);
{
// CellList of TextCells with PageSizePager
CellList<String> cl = new CellList<String>(new TextCell());
// set the initial pagesize to 2
cl.setPageSize(2);
// add the CellLists to the adaptor
lva.addView(cl);
// create a PageSizePager, giving it a handle to the CellList
PageSizePager<String> psp = new PageSizePager<String>(cl, 2);
// add the CellList to the page
RootPanel.get().add(cl);
// add the PageSizePager to the page
RootPanel.get().add(psp);
}
RootPanel.get().add(new HTML("<hr />"));
{
// CellList of TextCells with a SimplePager
CellList<String> cl = new CellList<String>(new TextCell());
// set the initial pageSize to 2
cl.setPageSize(2);
// add the CellLists to the adaptor
lva.addView(cl);
// create a pager, giving it a handle to the CellList
SimplePager<String> pager = new SimplePager<String>(cl,
SimplePager.TextLocation.CENTER);
// add the CellList to the page
RootPanel.get().add(cl);
// add the Pager to the page
RootPanel.get().add(pager);
}
RootPanel.get().add(new HTML("<hr />"));
{
// CellList of TextCells with a SimplePager and PageSizePager
CellList<String> cl = new CellList<String>(new TextCell());
// set the initial pageSize to 2
cl.setPageSize(2);
// add the CellLists to the adaptor
lva.addView(cl);
// create a PageSizePager, giving it a handle to the CellList
PageSizePager<String> psp = new PageSizePager<String>(cl, 1);
// create a pager, giving it a handle to the CellList
SimplePager<String> pager = new SimplePager<String>(cl,
SimplePager.TextLocation.CENTER);
// add the CellList to the page
RootPanel.get().add(cl);
// add the Pager to the page
RootPanel.get().add(pager);
// add the PageSizePager to the page
RootPanel.get().add(psp);
}
RootPanel.get().add(new HTML("<hr />"));
{
// CellTable
CellTable<String> ct = new CellTable<String>();
ct.setPageSize(2);
lva.addView(ct);
// add a column with a simple string header
ct.addColumn(new TextColumn<String>() {
@Override
public String getValue(String object) {
return object;
}
}, "String Header");
//add a column with a TextCell header
ct.addColumn(new TextColumn<String>() {
@Override
public String getValue(String object) {
return "%" + object + "%";
}
}, new Header<String>(new TextCell()) {
@Override
public String getValue() {
return "TextCell Header";
}
});
// create a pager, giving it a handle to the CellTable
SimplePager<String> pager = new SimplePager<String>(ct,
SimplePager.TextLocation.CENTER);
// add the CellList to the page
RootPanel.get().add(ct);
// add the Pager to the page
RootPanel.get().add(pager);
}
}
}
I have a working prototype of an editable CellTable. The prototype has a Table displaying String, Boolean, Date, Integer columns with editors for each. Editing each cell updates the corresponding model.
public class CellTableDemo implements EntryPoint
{
public void onModuleLoad( )
{
CellTable<SomeDTO> cellTable = createTable( );
addColumns( cellTable );
ListViewAdapter<SomeDTO> listViewAdapter = new ListViewAdapter<SomeDTO>( );
listViewAdapter.setList( getData( ) );
listViewAdapter.addView( cellTable );
RootPanel.get( ).add( new SimplePager<SomeDTO>( cellTable, SimplePager.TextLocation.CENTER ) );
RootPanel.get( ).add( cellTable );
}
private CellTable<SomeDTO> createTable( )
{
CellTable<SomeDTO> cellTable = new CellTable<SomeDTO>( );
cellTable.setSelectionEnabled( true );
cellTable.setSelectionModel( new SingleSelectionModel<SomeDTO>( ) );
cellTable.setPageSize( 5 );
cellTable.setPageStart( 0 );
return cellTable;
}
private void addColumns( CellTable<SomeDTO> cellTable )
{
Column<SomeDTO, String> colA = new Column<SomeDTO, String>( new TextInputCell( ) )
{
public String getValue( SomeDTO object )
{
return object.getA( );
}
};
colA.setFieldUpdater( new FieldUpdater<SomeDTO, String>( ) // updates changes into the backing bean
{
public void update( int index, SomeDTO object, String value )
{
object.setA( value );
}
} );
cellTable.addColumn( colA, "String Column A" );
cellTable.addColumn( new Column<SomeDTO, Integer>( new CurrencyCell( ) )
{
public Integer getValue( SomeDTO object )
{
return object.getB( );
}
}, "Currency Column B" );
Column<SomeDTO, Boolean> colC = new Column<SomeDTO, Boolean>( new CheckboxCell( ) )
{
public Boolean getValue( SomeDTO object )
{
return object.getC( );
}
};
colC.setFieldUpdater( new FieldUpdater<SomeDTO, Boolean>( )
{
public void update( int index, SomeDTO object, Boolean value )
{
object.setC( value );
}
} );
cellTable.addColumn( colC, "Boolean Column C" );
Column<SomeDTO, Date> colD = new Column<SomeDTO, Date>( new DatePickerCell( ) )
{
public Date getValue( SomeDTO object )
{
return object.getD( );
}
};
colD.setFieldUpdater( new FieldUpdater<SomeDTO, Date>( )
{
public void update( int index, SomeDTO object, Date value )
{
object.setD( value );
}
} );
cellTable.addColumn( colD, "Date Column D" );
cellTable.addColumn( new Column<SomeDTO, String>( new ActionCell<String>( "Click of summary of this row", new Delegate<String>( )
{
public void execute( String row )
{
Window.alert( row );
}
} ) )
{
public String getValue( SomeDTO row )
{
return row.getSummary( );
}
} );
}
private ArrayList<SomeDTO> getData( )
{
ArrayList<SomeDTO> tableData = new ArrayList<SomeDTO>( );
tableData.add( new SomeDTO( "A", 10, true, new Date( ) ) );
tableData.add( new SomeDTO( "AA", 200, false, new Date( ) ) );
tableData.add( new SomeDTO( "AAA", 3000, true, new Date( ) ) );
tableData.add( new SomeDTO( "AAAA", 40, false, new Date( ) ) );
tableData.add( new SomeDTO( "AAAAA", 500, true, new Date( ) ) );
tableData.add( new SomeDTO( "AAAAAA", 6000, false, new Date( ) ) );
tableData.add( new SomeDTO( "AAAAAAA", 70, true, new Date( ) ) );
tableData.add( new SomeDTO( "AAAAAAAA", 800, false, new Date( ) ) );
tableData.add( new SomeDTO( "AAAAAAAAA", 9000, true, new Date( ) ) );
tableData.add( new SomeDTO( "AAAAAAAAAA", 10, false, new Date( ) ) );
tableData.add( new SomeDTO( "AAAAAAAAAAA", 11, true, new Date( ) ) );
return tableData;
}
public class SomeDTO
{
private String a;
private Integer b;
private Boolean c;
private Date d;
public SomeDTO( String a, Integer b, Boolean c, Date d )
{
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
public String getA( )
{
return a;
}
public void setA( String a )
{
this.a = a;
}
public Integer getB( )
{
return b;
}
public void setB( Integer b )
{
this.b = b;
}
public Boolean getC( )
{
return c;
}
public void setC( Boolean c )
{
this.c = c;
}
public Date getD( )
{
return d;
}
public void setD( Date d )
{
this.d = d;
}
public String getSummary( )
{
return getA( ) + " " + getB( ) + " " + getC( ) + " " + getD( );
}
}
}
To show multiple column in table you need to put array in list. The reference code to achieve this is:
package com.test.client;
import java.util.ArrayList;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.ListViewAdapter;
import com.google.gwt.view.client.SingleSelectionModel;
public class Index implements EntryPoint {
public void onModuleLoad() {
// create some data
ArrayList<String[]> values = new ArrayList<String[]>();
values.add(new String[] { "1", "a" });
values.add(new String[] { "2", "b" });
values.add(new String[] { "3", "c" });
values.add(new String[] { "4", "d" });
values.add(new String[] { "5", "e" });
values.add(new String[] { "6", "f" });
values.add(new String[] { "7", "g" });
values.add(new String[] { "8", "h" });
values.add(new String[] { "9", "i" });
values.add(new String[] { "10", "j" });
// create a ListViewAdapter
ListViewAdapter<String[]> lva = new ListViewAdapter<String[]>();
// give the ListViewAdapter our data
lva.setList(values);
RootPanel.get().add(new HTML("<hr />"));
{
// CellTable
CellTable<String[]> ct = new CellTable<String[]>();
ct.setSelectionEnabled(true);
ct.setSelectionModel(new SingleSelectionModel());
ct.setPageSize(2);
lva.addView(ct);
ct.addColumn(new TextColumn<String[]>() {
@Override
public String getValue(String[] object) {
return object[0];
}
}, "First");
ct.addColumn(new TextColumn<String[]>() {
@Override
public String getValue(String[] object) {
return "%" + object[1] + "%";
}
}, "Second");
// create a pager, giving it a handle to the CellTable
SimplePager<String[]> pager = new SimplePager<String[]>(ct, SimplePager.TextLocation.CENTER);
// add the Pager to the page
RootPanel.get().add(pager);
// add the CellList to the page
RootPanel.get().add(ct);
}
}
}
The following code is what I'm woking on, hope it'll be helpful:
protected void init() {
VerticalPanel container = new VerticalPanel();
initWidget(container);
int pageSize = 10;
CellTable<User> cellTable = new CellTable<User>(pageSize);
setColumns(cellTable);
setSelectionModel(cellTable);
setDataSize(cellTable);
int pageStart = 0;
loadData(pageStart, pageSize, cellTable);
SimplePager<User> pager = createPager(cellTable);
container.add(cellTable);
container.add(pager);
}
private SimplePager<User> createPager(final CellTable<User> cellTable) {
SimplePager<User> pager = new SimplePager<User>(cellTable,
SimplePager.TextLocation.CENTER) {
public void onRangeOrSizeChanged(PagingListView<User> listView) {
loadData(listView.getPageStart(), listView.getPageSize(),
listView);
super.onRangeOrSizeChanged(listView);
}
};
return pager;
}
private void setColumns(CellTable<User> cellTable) {
cellTable.addColumn(new TextColumn<User>() {
@Override
public String getValue(User user) {
return user.getName();
}
}, new TextHeader("Name"));
cellTable.addColumn(new TextColumn<User>() {
@Override
public String getValue(User user) {
return user.getLocation();
}
}, new TextHeader("Location"));
}
private void setSelectionModel(CellTable<User> cellTable) {
final SingleSelectionModel<User> selectionModel = new SingleSelectionModel<User>();
SelectionChangeHandler selectionHandler = new SelectionChangeHandler() {
@Override
public void onSelectionChange(SelectionChangeEvent event) {
User user = selectionModel.getSelectedObject();
Window.alert(user.getId() + ": " + user.getName());
}
};
selectionModel.addSelectionChangeHandler(selectionHandler);
cellTable.setSelectionEnabled(true);
cellTable.setSelectionModel(selectionModel);
}
private void setDataSize(final PagingListView<User> cellTable) {
employeeRequest.countUsers(new AsyncCallback<Integer>() {
public void onFailure(Throwable caught) {
Window.alert("Request failure: " + caught.getMessage());
}
public void onSuccess(Integer result) {
cellTable.setDataSize(result, true);
}
});
}
private void loadData(int start, int size,
final PagingListView<User> cellTable) {
employeeRequest.getUsers(start, size,
new AsyncCallback<PagingData<User>>() {
public void onFailure(Throwable caught) {
Window.alert("Request failure: " + caught.getMessage());
}
public void onSuccess(PagingData<User> result) {
cellTable.setData(result.getStart(),
result.getLength(), result.getValues());
}
});
}
public class PagingData<T> implements IsSerializable {
private int start;
private int length;
private List<T> values;
public PagingData() {
}
public PagingData(int start, int length, List<T> values) {
super();
this.start = start;
this.length = length;
this.values = values;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public List<T> getValues() {
return values;
}
public void setValues(List<T> values) {
this.values = values;
}
}
Great answer from antony.trupe above.
If you want to have an editable cell, you could add this piece of code to his class, and instanciate such a column instead of the regular TextColumn
.
I'm sure you understand the FieldUpdater
part. It's basically designed to update the underlying model -- which is not possible in the case of String
.
I'll try to post a more complete example later on.
static class EditableColumn<T> extends Column<T, String> {
public EditableColumn()
{
super(new EditTextCell());
// workaround a NPE in EditTextCell.java:75
super.setFieldUpdater( new FieldUpdater<T, String>(){
@Override
public void update( int index, T object, String value ) {
// I think object should be updated with the new value, which cannot be done
// in a generic way (and cannot be done if T is String (immutable)).
// Doing nothing here will at least update the view (probably not the model)
System.out.println(index+":"+object+":"+value);
}
});
}
@Override
public String getValue(T object) {
return "%" + object + "%";
}
}
You may want to take a look at Spring Roo project. Spring Roo in general is used to scaffold Java applications. In the newest version 1.1 it can also scaffold GWT applications (using many GWT 2.1 features).
It can generate a lot of GWT 2.1 code for you and then you can see how everything works together. The information about Spring Roo is also given in GWT 2.1 release notes and the tool was presented in Google I/O Keynote (it is really interesting, the video can be found here).
Edit:
There is even a complete example of GWT 2.1 application (Expenses application) in Spring Roo. To generate this application you only need to install Roo 1.1 and then execute this in roo console:
script -f samples/expenses.roo
精彩评论