How to sort CheckBox Column of cellTable in GWT? - gwt

I know how to sort the TextColumn of cellTable in GWT.
That is setSortable(true) for textColumn
then declare ListHandler<String[]> columnSortHandler = new ListHandler<String[]>(myTableList);
then columnSortHandler.setComparator(textColumn, new MyCellTableColumnComparator(1));,
finally getView().getMyCellTable().addColumnSortHandler(columnSortHandler);
But what if we have CheckBox column & we want to sort CheckBox column. That is when user clicks the header of CheckBox column it will bring all the rows that has CheckBox checked to top. If user clicks the header of CheckBox column again it will bring all the rows that has CheckBox unchecked to top. So there are only 2 possible options for sorting CheckBox column, that is checked & unchecked.
We declare CheckBox column as following:
Column<String[], Boolean> checkBoxColumn = new Column<String[], Boolean>(
new CheckboxCell(true, false)) {
#Override
public Boolean getValue(String[] object) {
return mySelectionModel.isSelected(object);
}
};
ckColumn.setSortable(true);
But then how can we setComparator for checkBoxColumn?
Or can you find a better solution?

I wrote an example table, which should work out of the box :
public class ExampleTable extends CellTable<MyObject> {
private ArrayList<MyObject> list;
private ListDataProvider<MyObject> dataProvider = new ListDataProvider<MyObject>();
public ExampleTable() {
super();
dataProvider.addDataDisplay(this);
list = new ArrayList<MyObject>();
for (int i = 0; i < 15; i++) {
list.add(new MyObject("Value" + i, false));
}
dataProvider.setList(list);
TextColumn<MyObject> textColumn = new TextColumn<MyObject>() {
#Override
public String getValue(MyObject object) {
return object.getValue();
}
};
this.addColumn(textColumn, "String");
Column<MyObject, Boolean> checkBoxColumn = new Column<MyObject, Boolean>(
new CheckboxCell(true, true)) {
#Override
public Boolean getValue(MyObject object) {
return object.isEnabled();
}
};
checkBoxColumn.setFieldUpdater(new FieldUpdater<MyObject, Boolean>() {
#Override
public void update(int index, MyObject object, Boolean value) {
object.setEnabled(value);
}
});
this.addColumn(checkBoxColumn, "Boolean");
checkBoxColumn.setSortable(true);
ListHandler<MyObject> columnSortHandler = new ListHandler<MyObject>(
dataProvider.getList());
columnSortHandler.setComparator(checkBoxColumn,
new Comparator<MyObject>() {
#Override
public int compare(MyObject arg0, MyObject arg1) {
return (arg0.isEnabled() == arg1.isEnabled() ? 0
: (arg1.isEnabled() ? 1 : -1));
}
});
this.addColumnSortHandler(columnSortHandler);
}
};
The MyObject is just a simple Pojo :
public class MyObject {
private String value;
private boolean enabled;
public MyObject(String value, boolean status) {
this.value = value;
this.enabled = status;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean status) {
this.enabled = status;
}
}
It's important to use a filled list when creating the ListHandler. If you don't want updateable boolean column, just remove the FieldUpdater.

Related

checkbox in pageablelistview in wicket

private ArrayList<MFRList> list;
private ArrayList<STUList> list1 = new ArrayList<STUList>();
public ResultPage(PageParameters params) throws APIException {
Form form = new Form("form");
PageableListView view = new PageableListView("view", list, 10) {
#Override
public void onConfigure() {
super.onConfigure();
setVisible(list.size() > 0);
}
#Override
protected void populateItem(ListItem item) {
final StuList stu= (StuList) item.getModelObject();
item.add(new CheckBox("check", item.getModel()));
item.add(new Label("name", stu.getName()));
item.add(new Label("num", stu.getNumber()));
item.add(new Label("age", stu.getAge()));
item.add(new Label("sex", stu.getSex()));
}
};
Button backtosearchbutton = new Button("backtosearchbutton") {
#Override
public void onSubmit() {
setResponsePage(SearchPage.class);
}
}.setDefaultFormProcessing(false);
Button groupcheckbutton = new Button("groupcheckbutton") {
#Override
public void onSubmit() {
}
}.setDefaultFormProcessing(false);
Button groupuncheckbutton = new Button("groupuncheckbutton") {
#Override
public void onSubmit() {
}
}.setDefaultFormProcessing(false);
Button submitselectionbutton = new Button("submitselectionbutton") {
#Override
public void onSubmit() {
}
}.setDefaultFormProcessing(true);
form.add(view);
form.add(backtosearchbutton);
form.add(submitselectionbutton);
form.add(groupuncheckbutton);
form.add(groupcheckbutton);
add(form);
add(new CustomPagingNavigator("navigator", view));
how are the selected records stored and how can i use it. i understand that on form submission these records are submitted but i am not clear on how and where.
and my pojo is
public class MFRList implements Serializable {
private String name;
private String num;
private String age;
private String sex;
private Boolean selected = Boolean.FALSE;
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
public String getnum() {
return num;
}
public void setnum(String num) {
this.num = num;
}
public String getAge() {
return age;
}
public void setsex(String sex) {
this.sex= sex;
}
public String getsex() {
return sex;
}
public void setage(String age) {
this.age = age;
}
public Boolean getSelected() {
return selected;
}
public void setSelected(Boolean selected) {
this.selected = selected;
}
}
where is the selected row saved and how can i retrieve and use it.
Thanks in Advance
You should use a CheckGroup with Checks instead:
public ResultPage(PageParameters params) throws APIException {
Form form = new Form("form");
CheckGroup selection = new CheckGroup("selection", new ArrayList());
selection.setRenderBodyOnly(false);
form.add(selection);
PageableListView view = new PageableListView("view", list, 10) {
#Override
public void onConfigure() {
super.onConfigure();
setVisible(list.size() > 0);
}
#Override
protected void populateItem(ListItem item) {
final StuList stu= (StuList) item.getModelObject();
item.add(new Check("check", item.getModel()));
item.add(new Label("name", stu.getName()));
item.add(new Label("num", stu.getNumber()));
item.add(new Label("age", stu.getAge()));
item.add(new Label("sex", stu.getSex()));
}
};
selection.add(view);
This way the arrayList passed to the CheckGroup constructor will always contain the selected objects.
I got what i was trying to acheive but i am not su7re if it is optimal solution.
I created my own Model and added the object to a list when check box is selected.
class SelectedCheckBoxModel extends AbstractCheckBoxModel {
private final STUList info;
private ArrayList<STUList> list1;
public SelectedCheckBoxModel(STUList info, ArrayList<STUList> list1) {
super();
this.info = info;
this.list1 = list1;
}
#Override
public boolean isSelected() {
// TODO Auto-generated method stub
return list1.contains(info);
}
#Override
public void select() {
// TODO Auto-generated method stub
list1.add(info);
}
#Override
public void unselect() {
// TODO Auto-generated method stub
list1.remove(info);
}
and i called it in my listview
check = new CheckBox("check", new SelectedCheckBoxModel(stu, list1));
item.add(check);
if this is not optimal please suggest
Thank You

TableViewer not refreshing in RAP

I tried to run my Eclipse RCP code to run in Eclipse RAP environment. In my Eclipse RCP code, there is functionality to add the rows in to table. But
adding the code does not work in Eclipse RAP. I am using TableViewer.
Following is my code.
public class BasicEntryPoint extends AbstractEntryPoint {
private static final int COLUMNS = 2;
private TableViewer viewer;
private class ViewContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object inputElement) {
List<Person> list = (List<Person>) inputElement;
return list.toArray();
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
private class ViewLabelProvider extends LabelProvider implements
ITableLabelProvider {
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public String getColumnText(Object element, int columnIndex) {
Person p = (Person) element;
if (columnIndex == 0) {
return p.getName();
}
return p.getPlace();
}
}
private class Person{
String name;
String place;
public void setName(String name) {
this.name = name;
}
public void setPlace(String place) {
this.place = place;
}
public String getName() {
return name;
}
public String getPlace() {
return place;
}
}
public List<Person> persons() {
List<Person> list = new ArrayList<Person>();
Person person = new Person();
person.setName("bb");
person.setPlace("jjj");
list.add(person);
person = new Person();
person.setName("sss");
person.setPlace("fff");
list.add(person);
return list;
}
#Override
protected void createContents(Composite parent) {
parent.setLayout(new GridLayout(2, false));
viewer = new TableViewer(parent, SWT.NONE);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
final Table table = viewer.getTable();
viewer.setColumnProperties(initColumnProperties(table));
viewer.setInput(persons());
viewer.getTable().setHeaderVisible(true);
Button checkbox = new Button(parent, SWT.CHECK);
checkbox.setText("Hello");
Button button = new Button(parent, SWT.PUSH);
button.setText("World");
button.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
System.out.println("Button clicked");
Person p = new Person();
p.setName("Dee");
p.setPlace("TCR");
persons().add(p);
String prop[] ={"name","place"};
viewer.update(p, prop);
//viewer.refresh();
}
});
}
private String[] initColumnProperties(Table table) {
String[] result = new String[COLUMNS];
for (int i = 0; i < COLUMNS; i++) {
TableColumn tableColumn = new TableColumn(table, SWT.NONE);
result[i] = "Column" + i;
tableColumn.setText(result[i]);
if (i == 2) {
tableColumn.setWidth(190);
} else {
tableColumn.setWidth(70);
}
}
return result;
}
}
You should use:
viewer.add(p);
rather than update to add a new item to a table (both for SWT and RAP).
You must also update your model to contain the new item.

How can we filter the table viewer in JFace based on the entered text

I have created a table using table viewer and now i need to filter based on the text entered in the text box so how can we filter the table the code to create table is as follows
TableViewerColumn message = new TableViewerColumn(viewer, SWT.NONE);
message.getColumn().setWidth(800);
message.getColumn().setText("Message");
message.setLabelProvider(new ColumnLabelProvider()
{
#Override
public void update(ViewerCell cell)
{
Object element = cell.getElement();
if(element instanceof MyObject)
{
MyObject obj = (MyObject) element;
cell.setText(obj.getMessage());
}
}
});
}
private static class MyObject
{
private String first;
private String second;
private String message;
public MyObject(String first, String second,String message)
{
this.first = first;
this.second = second;
this.message = message;
}
public String getFirst()
{
return first;
}
public void setFirst(String first)
{
this.first = first;
}
public String getSecond()
{
return second;
}
public void setSecond(String message)
{
this.second = second;
}
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
this.message = message;
}
so now how can we filter the table. Please help me as I am new to jface table viewer
Use a class derived from ViewerFilter to add a filter:
class MyFilter extends ViewerFilter
{
#Override
public boolean select(Viewer viewer, Object parentElement, Object element)
{
MyObject obj = (MyObject)element;
// TODO return true to include the object, false to exclude
}
}
Add this to the table with:
viewer.addFilter(new MyFilter());
Call
viewer.refresh();
to get the viewer to rerun the filter when the text changes.

Programmatically refresh a Gwt CellTree

I want to fire the "open root node" event on my current working CellTree, which now has the following behaviour:
#Override
public <T> NodeInfo<?> getNodeInfo(final T value) {
return new DefaultNodeInfo<Categoria>(
(value instanceof Categoria) ?
createBranchDataProvider((Categoria)value) :
rootDataProvider,
new CategoriaCell()
);
}
private AsyncDataProvider<Categoria> createRootDataProvider() {
AsyncDataProvider<Categoria> dataProvider = new AsyncDataProvider<Categoria>() {
#Override
protected void onRangeChanged(HasData<Categoria> display) {
AsyncCallback<Categoria[]> cb = new AsyncCallback<Categoria[]>() {
#Override
public void onSuccess(Categoria[] result) {
updateRowCount(result.length, true);
updateRowData(0, Arrays.asList(result));
}
#Override
public void onFailure(Throwable caught) {
Window.alert(caught.toString());
}
};
rpcService.getCategorie(cb);
}
};
return dataProvider;
}
How can I fire that "onRangeChanged" event, to refresh my level-1 nodes?
What is my convenience method missing?
private void updateTree() {
TreeNode rootTreeNode = cellTree.getRootTreeNode();
for (int i = 0; i < rootTreeNode.getChildCount(); i++) {
rootTreeNode.setChildOpen(i, false);
}
// HOW TO REFRESH LEVEL-1 NODES?
}
Working example. Add reference to DataProvider (and parent Node) (MyMenuItem and MyCell with DataProvider in my code). After adding element refresh parent.
public class MyMenuItem {
private String name;
private String action; //some data
private int level; //if needed
private ArrayList<MyMenuItem> list; //nodes childrens
private MyMenuItem parent; //track internal parent
private MyCell cell; //for refresh - reference to visual component
public void setCell(MyCell cell) {
this.cell = cell;
}
public void refresh() {
if(parent!=null) {
parent.refresh();
}
if (cell!=null) {
cell.refresh(); //refresh tree
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public MyMenuItem(String name, String action) {
super();
parent = null;
level = 0;
this.name = name;
this.action = action;
list = new ArrayList<MyMenuItem>();
}
public MyMenuItem(String name) {
this(name, "");
}
public void addSubMenu(MyMenuItem m) {
m.level = this.level+1;
m.parent = this;
list.add(m);
}
public boolean hasChildrens() {
return list.size()>0;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public ArrayList<MyMenuItem> getList() {
return list;
}
public MyMenuItem getParent() {
return parent;
}
}
public class MyTreeModel implements TreeViewModel {
private MyMenuItem officialRoot; //default not dynamic
private MyMenuItem studentRoot; //default not dynamic
private MyMenuItem testRoot; //default not dynamic
private MyMenuItem root;
public MyMenuItem getRoot() { // to set CellTree root
return root;
}
public MyTreeModel() {
root = new MyMenuItem("root");
// Default items
officialRoot = new MyMenuItem("Official"); //some basic static data
studentRoot = new MyMenuItem("Student");
testRoot = new MyMenuItem("Test");
root.addSubMenu(officialRoot);
root.addSubMenu(studentRoot);
root.addSubMenu(testRoot);
}
//example of add add logic
private void addNew(MyMenuItem myparent, String name, String uid) {
myparent.addSubMenu(new MyMenuItem(name, uid));
myparent.refresh(); //HERE refresh tree
}
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
ListDataProvider<MyMenuItem> dataProvider;
MyMenuItem myValue = null;
if (value == null) { // root is not set
dataProvider = new ListDataProvider<MyMenuItem>(root.getList());
} else {
myValue = (MyMenuItem) value;
dataProvider = new ListDataProvider<MyMenuItem>(myValue.getList());
}
MyCell cell = new MyCell(dataProvider); //HERE Add reference
if (myValue != null)
myValue.setCell(cell);
return new DefaultNodeInfo<MyMenuItem>(dataProvider, cell);
}
#Override
public boolean isLeaf(Object value) {
if (value instanceof MyMenuItem) {
MyMenuItem t = (MyMenuItem) value;
if (!t.hasChildrens())
return true;
return false;
}
return false;
}
}
public class MyCell extends AbstractCell<MyMenuItem> {
ListDataProvider<MyMenuItem> dataProvider; //for refresh
public MyCell(ListDataProvider<MyMenuItem> dataProvider) {
super("keydown","dblclick");
this.dataProvider = dataProvider;
}
public void refresh() {
dataProvider.refresh();
}
#Override
public void onBrowserEvent(Context context, Element parent, MyMenuItem value,
NativeEvent event, ValueUpdater<MyMenuItem> valueUpdater) {
if (value == null) {
return;
}
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType())) {
this.onEnterKeyDown(context, parent, value, event, valueUpdater);
}
if ("dblclick".equals(event.getType())) {
this.onEnterKeyDown(context, parent, value, event, valueUpdater);
}
}
#Override
public void render(Context context, MyMenuItem value, SafeHtmlBuilder sb) {
if (value == null) {
return;
}
sb.appendEscaped(value.getName());
//add HERE for better formating
}
#Override
protected void onEnterKeyDown(Context context, Element parent,
MyMenuItem value, NativeEvent event, ValueUpdater<MyMenuItem> valueUpdater) {
Window.alert("You clicked "+event.getType()+" " + value.getName());
}
}
in module add
treeModel = new MyTreeModel();
tree = new CellTree(treeModel,treeModel.getRoot());
The Level-1 nodes (I suppose you the mean below the root node) can not be refreshed the way you are doing it.
You have to store the instance of your dataProvider for the level-1 nodes somewhere.
Later when you refresh your list you have to update your stored dataProvider for your level-1 nodes.
The nodes below the level-1 can be refreshed the way you are doing it. Because as soon as you close the level 1 nodes (that is what you are doing in the updateTree method) and the next time you open it getNodeInfo will be called and the updated Subcategories will be retrieved and displayed in the CellTree.
UPDATE
For refreshing the CellWidgets which is attached to AsyncDataProvider you will probably have to extend the AsyncDataProvider and either extract the RPC call to a getData() method which is called in the onRangeChanged() method or create an interface with a refresh method and implement it in your custom AsyncDataProvider which calls the protected onRangeChanged() method.

how to add column of ClickableTextCells to cellTable

hi all
i need a simple example show me how to add column of ClickableTextCells to cellTable
thanks.
Column<YerValueObject, String> newCol = new Column<YerValueObject, String>(new ClickableTextCell()) {
#Override
public String getValue(YearValueObject obj) {
return obj.someMethod();
}
};
newCol.setFieldUpdater(new FieldUpdater<YerValueObject, String>() {
#Override
public void update(int index, YerValueObject obj, String value) {
//do whatever you need to here...
}
});
table.addColumn(newCol, "ClickColumn");
this is the solution if you need to add clickableTextCell to cellTable
// ClickableTextCell
ClickableTextCell anchorcolumn = new ClickableTextCell();
table.addColumn(addColumn(anchorcolumn, new GetValue<String>() {
public String getValue(Contact contact) {
return "Click " + contact.anchor;
}
}, new FieldUpdater<Contact, String>() {
public void update(int index, Contact object, String value) {
Window.alert("You clicked " + object.name);
}
}), "Anchor");
private <C> Column<Contact, C> addColumn(Cell<C> cell,final GetValue<C> getter,
FieldUpdater<Contact, C> fieldUpdater) {
Column<Contact, C> column = new Column<Contact, C>(cell) {
#Override
public C getValue(Contact object) {
return getter.getValue(object);
}
};
column.setFieldUpdater(fieldUpdater);
return column;
}
private static interface GetValue<C> {
C getValue(Contact contact);
}
// A simple data type that represents a contact.
private static class Contact {
private final String address;
private final String name;
private final String anchor;
public Contact(String name, String address, String anchor) {
this.name = name;
this.address = address;
this.anchor = anchor;
}
}
Create a Column overriding the onBrowserEvent method.
Like this:
new Column<T, String>(new TextCell()) {
#Override
public String getValue(T object) {
return object.getProperty();
}
#Override
public void onBrowserEvent(Context context, Element elem, T object, NativeEvent event) {
// TODO You can check which event you want to catch
Window.open("http://www.stackoverflow.com", "StackOverFlow", "");
}
};