Change-Id: Ia6ccd8f7bf7f1f5e0a8c6e5d343148e91d09c5b2feature/vaadin8-book-vol2
@@ -43,7 +43,7 @@ public class ColumnConnector extends AbstractExtensionConnector { | |||
getState().communicationId); | |||
} | |||
}; | |||
getParent().addColumn(column); | |||
getParent().addColumn(column, getState().communicationId); | |||
} | |||
@OnStateChange("caption") | |||
@@ -51,6 +51,11 @@ public class ColumnConnector extends AbstractExtensionConnector { | |||
column.setHeaderCaption(getState().caption); | |||
} | |||
@OnStateChange("sortable") | |||
void updateSortable() { | |||
column.setSortable(getState().sortable); | |||
} | |||
@Override | |||
public void onUnregister() { | |||
super.onUnregister(); |
@@ -15,7 +15,11 @@ | |||
*/ | |||
package com.vaadin.client.tokka.connectors.components.grid; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import com.vaadin.client.data.DataSource; | |||
import com.vaadin.client.renderers.Renderer; | |||
@@ -23,8 +27,13 @@ import com.vaadin.client.tokka.connectors.components.AbstractListingConnector; | |||
import com.vaadin.client.tokka.connectors.data.HasSelection; | |||
import com.vaadin.client.tokka.data.selection.SelectionModel; | |||
import com.vaadin.client.widget.grid.selection.ClickSelectHandler; | |||
import com.vaadin.client.widget.grid.sort.SortEvent; | |||
import com.vaadin.client.widget.grid.sort.SortHandler; | |||
import com.vaadin.client.widget.grid.sort.SortOrder; | |||
import com.vaadin.client.widgets.Grid; | |||
import com.vaadin.client.widgets.Grid.Column; | |||
import com.vaadin.shared.data.sort.SortDirection; | |||
import com.vaadin.shared.tokka.ui.components.grid.GridServerRpc; | |||
import com.vaadin.shared.ui.Connect; | |||
import elemental.json.JsonObject; | |||
@@ -103,6 +112,9 @@ public class GridConnector extends AbstractListingConnector implements | |||
} | |||
} | |||
/* Map to keep track of all added columns */ | |||
private Map<Column<?, JsonObject>, String> columnToIdMap = new HashMap<>(); | |||
@Override | |||
public Grid<JsonObject> getWidget() { | |||
return (Grid<JsonObject>) super.getWidget(); | |||
@@ -113,6 +125,22 @@ public class GridConnector extends AbstractListingConnector implements | |||
super.init(); | |||
new ClickSelectHandler<JsonObject>(getWidget()); | |||
getWidget().addSortHandler(new SortHandler<JsonObject>() { | |||
@Override | |||
public void sort(SortEvent<JsonObject> event) { | |||
List<String> columnIds = new ArrayList<>(); | |||
List<SortDirection> sortDirections = new ArrayList<>(); | |||
for (SortOrder so : event.getOrder()) { | |||
if (columnToIdMap.containsKey(so.getColumn())) { | |||
columnIds.add(columnToIdMap.get(so.getColumn())); | |||
sortDirections.add(so.getDirection()); | |||
} | |||
getRpcProxy(GridServerRpc.class).setSortOrder(columnIds, | |||
sortDirections); | |||
} | |||
} | |||
}); | |||
} | |||
@Override | |||
@@ -128,11 +156,16 @@ public class GridConnector extends AbstractListingConnector implements | |||
.setSelectionModel(new SelectionModelAdapter(selectionModel)); | |||
} | |||
public void addColumn(Column<?, JsonObject> column) { | |||
public void addColumn(Column<?, JsonObject> column, String id) { | |||
assert !columnToIdMap.containsKey(column) | |||
&& !columnToIdMap.containsValue(id) : "Column with given id already exists."; | |||
getWidget().addColumn(column); | |||
columnToIdMap.put(column, id); | |||
} | |||
public void removeColumn(Column<?, JsonObject> column) { | |||
assert columnToIdMap.containsKey(column) : "Given Column does not exist."; | |||
getWidget().removeColumn(column); | |||
columnToIdMap.remove(column); | |||
} | |||
} |
@@ -33,10 +33,14 @@ public class Column<T, V> extends AbstractExtension implements | |||
Column(String caption, Function<T, V> getter) { | |||
this.getter = getter; | |||
getState().caption = caption; | |||
getState().sortable = true; | |||
} | |||
@Override | |||
public void generateData(T data, JsonObject jsonObject) { | |||
assert getState(false).communicationId != null : "No communication ID set for column " | |||
+ getState(false).caption; | |||
if (!jsonObject.hasKey(DataProviderConstants.DATA)) { | |||
jsonObject.put(DataProviderConstants.DATA, Json.createObject()); | |||
} | |||
@@ -64,4 +68,30 @@ public class Column<T, V> extends AbstractExtension implements | |||
void setCommunicationId(String key) { | |||
getState().communicationId = key; | |||
} | |||
/** | |||
* Sets whether the user can sort this Column or not. | |||
* | |||
* @param sortable | |||
* is column sortable | |||
* @return the column | |||
*/ | |||
public Column<T, V> setSortable(boolean sortable) { | |||
getState().sortable = sortable; | |||
return this; | |||
} | |||
/** | |||
* Returns the state of sorting for this Column. | |||
* | |||
* @return {@code true} if column can be sorted by user; {@code false} if | |||
* not | |||
*/ | |||
public boolean isSortable() { | |||
return getState(false).sortable; | |||
} | |||
public String getCaption() { | |||
return getState(false).caption; | |||
} | |||
} |
@@ -16,9 +16,14 @@ | |||
package com.vaadin.tokka.ui.components.grid; | |||
import java.util.HashSet; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import java.util.function.Function; | |||
import com.vaadin.shared.data.sort.SortDirection; | |||
import com.vaadin.shared.tokka.ui.components.grid.GridServerRpc; | |||
import com.vaadin.tokka.server.communication.data.KeyMapper; | |||
import com.vaadin.tokka.server.communication.data.SingleSelection; | |||
import com.vaadin.tokka.ui.components.AbstractListing; | |||
@@ -30,6 +35,23 @@ public class Grid<T> extends AbstractListing<T> { | |||
public Grid() { | |||
setSelectionModel(new SingleSelection<T>()); | |||
registerRpc(new GridServerRpc() { | |||
@Override | |||
public void setSortOrder(List<String> columnIds, | |||
List<SortDirection> sortDirections) { | |||
assert columnIds.size() == sortDirections.size() : "Column and sort direction counts don't match."; | |||
Map<Column<T, ?>, SortDirection> sortOrder = new LinkedHashMap<>(); | |||
for (int i = 0; i < columnIds.size(); ++i) { | |||
sortOrder.put(columnKeys.get(columnIds.get(i)), | |||
sortDirections.get(i)); | |||
} | |||
// FIXME: Handle the sortOrder map so DataSource can understand | |||
sortOrder.forEach((col, dir) -> System.err | |||
.println("Sorting column: " + col.getCaption() + " to " | |||
+ dir)); | |||
} | |||
}); | |||
} | |||
public <V> Column<T, V> addColumn(String caption, Function<T, V> getter) { |
@@ -21,4 +21,5 @@ public class ColumnState extends SharedState { | |||
public String caption; | |||
public String communicationId; | |||
public boolean sortable; | |||
} |
@@ -0,0 +1,27 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | |||
* use this file except in compliance with the License. You may obtain a copy of | |||
* the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations under | |||
* the License. | |||
*/ | |||
package com.vaadin.shared.tokka.ui.components.grid; | |||
import java.util.List; | |||
import com.vaadin.shared.communication.ServerRpc; | |||
import com.vaadin.shared.data.sort.SortDirection; | |||
public interface GridServerRpc extends ServerRpc { | |||
void setSortOrder(List<String> columnIds, List<SortDirection> sortDirections); | |||
} |
@@ -0,0 +1,49 @@ | |||
package com.vaadin.tokka.tests.components; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Random; | |||
class Bean { | |||
static Random r = new Random(13337); | |||
private String value; | |||
private Integer intVal; | |||
public Bean(String value, Integer intVal) { | |||
this.value = value; | |||
this.intVal = intVal; | |||
} | |||
public String getValue() { | |||
return value; | |||
} | |||
public void setValue(String value) { | |||
this.value = value; | |||
} | |||
public Integer getIntVal() { | |||
return intVal; | |||
} | |||
public void setIntVal(Integer intVal) { | |||
this.intVal = intVal; | |||
} | |||
@Override | |||
public String toString() { | |||
return "Bean { value: " + value + ", intVal: " + intVal + " }"; | |||
} | |||
public static List<Bean> generateRandomBeans() { | |||
String[] values = new String[] { "Foo", "Bar", "Baz" }; | |||
List<Bean> beans = new ArrayList<Bean>(); | |||
for (int i = 0; i < 100; ++i) { | |||
beans.add(new Bean(values[r.nextInt(values.length)], r.nextInt(100))); | |||
} | |||
return beans; | |||
} | |||
} |
@@ -0,0 +1,22 @@ | |||
package com.vaadin.tokka.tests.components; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.tokka.server.communication.data.DataSource; | |||
import com.vaadin.tokka.ui.components.grid.Grid; | |||
public class GridSortable extends AbstractTestUI { | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
Grid<Bean> grid = new Grid<Bean>(); | |||
grid.addColumn("Never sortable", Bean::getValue).setSortable(false); | |||
grid.addColumn("Sortable Integer", Bean::getIntVal); | |||
grid.addColumn("Sortable toString()", Bean::toString); | |||
grid.setDataSource(DataSource.create(Bean.generateRandomBeans())); | |||
addComponent(grid); | |||
} | |||
} |
@@ -24,48 +24,6 @@ public class ListingTestUI extends AbstractTestUI { | |||
static Random r = new Random(); | |||
static class Bean { | |||
private String value; | |||
private Integer intVal; | |||
public Bean(String value, Integer intVal) { | |||
this.value = value; | |||
this.intVal = intVal; | |||
} | |||
public String getValue() { | |||
return value; | |||
} | |||
public void setValue(String value) { | |||
this.value = value; | |||
} | |||
public Integer getIntVal() { | |||
return intVal; | |||
} | |||
public void setIntVal(Integer intVal) { | |||
this.intVal = intVal; | |||
} | |||
@Override | |||
public String toString() { | |||
return "Bean { value: " + value + ", intVal: " + intVal + " }"; | |||
} | |||
public static List<Bean> generateRandomBeans() { | |||
String[] values = new String[] { "Foo", "Bar", "Baz" }; | |||
List<Bean> beans = new ArrayList<Bean>(); | |||
for (int i = 0; i < 100; ++i) { | |||
beans.add(new Bean(values[r.nextInt(values.length)], r | |||
.nextInt(100))); | |||
} | |||
return beans; | |||
} | |||
} | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
VerticalLayout layout = new VerticalLayout(); |