Ability to reset sort order for tables #PL-2298

This commit is contained in:
Yuriy Artamonov 2013-07-24 12:07:23 +00:00
parent 672d8a632e
commit 6a76e2a5fc
20 changed files with 326 additions and 34 deletions

View File

@ -59,7 +59,7 @@ def webModule = project(':cuba-web')
def desktopModule = project(':cuba-desktop')
def portalModule = project(':cuba-portal')
def vaadinVersion = '7.1.0.h.M4'
def vaadinVersion = '7.1.1.h.M2'
def servletApi = [group: 'org.apache.tomcat', name: 'servlet-api', version: '6.0.20']
def groovyArtifact = [group: 'org.codehaus.groovy', name: 'groovy', version: '1.7.10']

View File

@ -276,6 +276,11 @@ public interface CollectionDatasource<T extends Entity<K>, K> extends Datasource
* Perform sorting
*/
void sort(SortInfo[] sortInfos);
/**
* Remove sort infos
*/
void resetSortOrder();
}
/**

View File

@ -214,6 +214,11 @@ public class CollectionDatasourceImpl<T extends Entity<K>, K>
}
}
@Override
public void resetSortOrder() {
this.sortInfos = null;
}
protected boolean containsAllDataFromDb() {
return firstResult == 0 && data.size() < maxResults;
}

View File

@ -89,7 +89,7 @@ public class CollectionPropertyDatasourceImpl<T extends Entity<K>, K>
@Override
public void stateChanged(Datasource<Entity> ds, State prevState, State state) {
for (DatasourceListener dsListener : new ArrayList<DatasourceListener>(dsListeners)) {
for (DatasourceListener dsListener : new ArrayList<>(dsListeners)) {
dsListener.stateChanged(CollectionPropertyDatasourceImpl.this, prevState, state);
}
fireCollectionChanged(CollectionDatasourceListener.Operation.REFRESH, Collections.<Entity>emptyList());
@ -211,7 +211,7 @@ public class CollectionPropertyDatasourceImpl<T extends Entity<K>, K>
UserSession userSession = AppBeans.get(UserSessionSource.class).getUserSession();
if (!userSession.isEntityOpPermitted(metaProperty.getRange().asClass(), EntityOp.READ)
|| !userSession.isEntityAttrPermitted(metaProperty.getDomain(), metaProperty.getName(), EntityAttrAccess.VIEW))
return new ArrayList<T>(); // Don't use Collections.emptyList() to avoid confusing UnsupportedOperationExceptions
return new ArrayList<>(); // Don't use Collections.emptyList() to avoid confusing UnsupportedOperationExceptions
else {
final Instance master = masterDs.getItem();
return master == null ? null : (Collection<T>) master.getValue(metaProperty.getName());
@ -596,6 +596,11 @@ public class CollectionPropertyDatasourceImpl<T extends Entity<K>, K>
}
}
@Override
public void resetSortOrder() {
this.sortInfos = null;
}
protected void doSort() {
Collection<T> collection = __getCollection();
if (collection == null)
@ -605,7 +610,7 @@ public class CollectionPropertyDatasourceImpl<T extends Entity<K>, K>
final boolean asc = Order.ASC.equals(sortInfos[0].getOrder());
@SuppressWarnings({"unchecked"})
List<T> list = new LinkedList<T>(collection);
List<T> list = new LinkedList<>(collection);
Collections.sort(list, new EntityComparator<T>(propertyPath, asc));
collection.clear();
collection.addAll(list);
@ -646,7 +651,7 @@ public class CollectionPropertyDatasourceImpl<T extends Entity<K>, K>
if (itemId == null) return null;
Collection<T> collection = __getCollection();
if ((collection != null) && !collection.isEmpty() && !itemId.equals(firstItemId())) {
List<T> list = new ArrayList<T>(collection);
List<T> list = new ArrayList<>(collection);
T currentItem = getItem(itemId);
return list.get(list.indexOf(currentItem) - 1).getId();
}

View File

@ -431,6 +431,11 @@ public class LazyCollectionDatasource<T extends Entity<K>, K>
}
}
@Override
public void resetSortOrder() {
this.sortInfos = null;
}
private void doSort() {
if (isCompletelyLoaded()) {
sortInMemory();

View File

@ -241,15 +241,15 @@ public class CubaGroupTableWidget extends CubaScrollTableWidget {
return new GroupTableFooter();
}
protected class GroupTableHead extends TableHead {
protected class GroupTableHead extends CubaScrollTableHead {
public GroupTableHead() {
super();
availableCells.put(GROUP_DIVIDER_COLUMN_KEY, new GroupDividerHeaderCell());
}
@Override
public void clear() {
super.clear();
availableCells.put(GROUP_DIVIDER_COLUMN_KEY, new GroupDividerHeaderCell());
}
@ -282,8 +282,7 @@ public class CubaGroupTableWidget extends CubaScrollTableWidget {
protected VScrollTableRow createRow(UIDL uidl, char[] aligns2) {
if (uidl.hasAttribute("groupKey")) {
return new CubaGroupTableGroupRow(uidl, aligns2); //creates a group row
}
else
} else
return new CubaGroupTableRow(uidl, aligns2);
}
@ -495,7 +494,7 @@ public class CubaGroupTableWidget extends CubaScrollTableWidget {
}
}
protected class GroupDividerHeaderCell extends HeaderCell {
protected class GroupDividerHeaderCell extends CubaScrollTableHeaderCell {
public GroupDividerHeaderCell() {
super(GROUP_DIVIDER_COLUMN_KEY, null);
addStyleName(CLASSNAME + "-group-divider-header");

View File

@ -39,6 +39,8 @@ public class CubaScrollTableWidget extends VScrollTable implements ShortcutActio
protected boolean textSelectionEnabled = false;
protected boolean isAllowPopupMenu = true;
protected int sortClickCounter = 0;
protected ClientLogger logger = ClientLoggerFactory.getLogger("CubaScrollTableWidget");
protected CubaScrollTableWidget() {
@ -101,6 +103,96 @@ public class CubaScrollTableWidget extends VScrollTable implements ShortcutActio
super.handleBodyContextMenu(event);
}
@Override
protected TableHead createTableHead() {
return new CubaScrollTableHead();
}
protected class CubaScrollTableHead extends TableHead {
@Override
protected HeaderCell createHeaderCell(String cid, String caption) {
return new CubaScrollTableHeaderCell(cid, caption);
}
}
protected class CubaScrollTableHeaderCell extends HeaderCell {
public CubaScrollTableHeaderCell(String colId, String headerText) {
super(colId, headerText);
}
@Override
protected void sortColumn() {
// CAUTION copied from superclass
// Added ability to reset sort order
boolean reloadDataFromServer = true;
if (cid.equals(sortColumn)) {
if (sortColumn == null) {
// anyway sort ascending
client.updateVariable(paintableId, "sortascending", !sortAscending, false);
} else if (sortAscending) {
if (sortClickCounter < 2) {
// special case for initial revert sorting instead of reset sort order
if (sortClickCounter == 0) {
client.updateVariable(paintableId, "sortascending", !sortAscending, false);
} else {
reloadDataFromServer = false;
sortClickCounter = 0;
sortColumn = null;
sortAscending = true;
client.updateVariable(paintableId, "resetsortorder", "", true);
}
} else {
client.updateVariable(paintableId, "sortascending", !sortAscending, false);
}
} else {
if (sortClickCounter < 2) {
// special case for initial revert sorting instead of reset sort order
if (sortClickCounter == 0) {
client.updateVariable(paintableId, "sortascending", !sortAscending, false);
} else {
reloadDataFromServer = false;
sortClickCounter = 0;
sortColumn = null;
sortAscending = true;
client.updateVariable(paintableId, "resetsortorder", "", true);
}
} else {
reloadDataFromServer = false;
sortClickCounter = 0;
sortColumn = null;
sortAscending = true;
client.updateVariable(paintableId, "resetsortorder", "", true);
}
}
sortClickCounter++;
} else {
sortClickCounter = 0;
// set table sorted by this column
client.updateVariable(paintableId, "sortcolumn", cid, false);
}
if (reloadDataFromServer) {
// get also cache columns at the same request
scrollBodyPanel.setScrollPosition(0);
firstvisible = 0;
rowRequestHandler.setReqFirstRow(0);
rowRequestHandler.setReqRows((int) (2 * pageLength
* cache_rate + pageLength));
rowRequestHandler.deferRowFetch(); // some validation +
// defer 250ms
rowRequestHandler.cancel(); // instead of waiting
rowRequestHandler.run(); // run immediately
}
}
}
protected class CubaScrollTableBody extends VScrollTableBody {
protected Widget lastFocusedWidget = null;

View File

@ -15,12 +15,10 @@ import com.google.gwt.user.client.ui.Widget;
import com.haulmont.cuba.web.toolkit.ui.client.Tools;
import com.vaadin.client.UIDL;
import com.vaadin.client.Util;
import com.vaadin.client.VConsole;
import com.vaadin.client.ui.VEmbedded;
import com.vaadin.client.ui.VLabel;
import com.vaadin.client.ui.VTextField;
import com.vaadin.client.ui.VTreeTable;
import com.vaadin.client.ui.layout.VLayoutSlot;
/**
* @author artamonov
@ -33,6 +31,8 @@ public class CubaTreeTableWidget extends VTreeTable {
protected boolean textSelectionEnabled = false;
protected boolean allowPopupMenu = true;
protected int sortClickCounter = 0;
@Override
protected void handleBodyContextMenu(ContextMenuEvent event) {
if (allowPopupMenu)
@ -44,6 +44,96 @@ public class CubaTreeTableWidget extends VTreeTable {
return new CubaTreeTableBody();
}
@Override
protected TableHead createTableHead() {
return new CubaTreeTableTableHead();
}
protected class CubaTreeTableTableHead extends TableHead {
@Override
protected HeaderCell createHeaderCell(String cid, String caption) {
return new CubaTreeTableHeaderCell(cid, caption);
}
}
protected class CubaTreeTableHeaderCell extends HeaderCell {
public CubaTreeTableHeaderCell(String colId, String headerText) {
super(colId, headerText);
}
@Override
protected void sortColumn() {
// CAUTION copied from superclass
// Added ability to reset sort order
boolean reloadDataFromServer = true;
if (cid.equals(sortColumn)) {
if (sortColumn == null) {
// anyway sort ascending
client.updateVariable(paintableId, "sortascending", !sortAscending, false);
} else if (sortAscending) {
if (sortClickCounter < 2) {
// special case for initial revert sorting instead of reset sort order
if (sortClickCounter == 0) {
client.updateVariable(paintableId, "sortascending", !sortAscending, false);
} else {
reloadDataFromServer = false;
sortClickCounter = 0;
sortColumn = null;
sortAscending = true;
client.updateVariable(paintableId, "resetsortorder", "", true);
}
} else {
client.updateVariable(paintableId, "sortascending", !sortAscending, false);
}
} else {
if (sortClickCounter < 2) {
// special case for initial revert sorting instead of reset sort order
if (sortClickCounter == 0) {
client.updateVariable(paintableId, "sortascending", !sortAscending, false);
} else {
reloadDataFromServer = false;
sortClickCounter = 0;
sortColumn = null;
sortAscending = true;
client.updateVariable(paintableId, "resetsortorder", "", true);
}
} else {
reloadDataFromServer = false;
sortClickCounter = 0;
sortColumn = null;
sortAscending = true;
client.updateVariable(paintableId, "resetsortorder", "", true);
}
}
sortClickCounter++;
} else {
sortClickCounter = 0;
// set table sorted by this column
client.updateVariable(paintableId, "sortcolumn", cid, false);
}
if (reloadDataFromServer) {
// get also cache columns at the same request
scrollBodyPanel.setScrollPosition(0);
firstvisible = 0;
rowRequestHandler.setReqFirstRow(0);
rowRequestHandler.setReqRows((int) (2 * pageLength
* cache_rate + pageLength));
rowRequestHandler.deferRowFetch(); // some validation +
// defer 250ms
rowRequestHandler.cancel(); // instead of waiting
rowRequestHandler.run(); // run immediately
}
}
}
protected class CubaTreeTableBody extends VTreeTableScrollBody {
@Override

View File

@ -262,14 +262,6 @@ public interface WebConfig extends Config {
@DefaultBoolean(false)
boolean getAllowIdSuffix();
/**
* @return Whether to enable cancel sorting of table columns. If true, each third click on the column will cancel
* sorting instead of reversing it.
*/
@Property("cuba.web.enableCancelTableSorting")
@DefaultBoolean(true)
boolean getEnableCancelTableSorting();
/**
* Supports automatic testing.
* @return a name of request parameter that marks a request from an automatic testing tool, for example jMeter.

View File

@ -441,9 +441,6 @@ public abstract class WebAbstractTable<T extends com.vaadin.ui.Table> extends We
component.setSizeFull();
componentComposition.setExpandRatio(component, 1);
// vaadin7
// component.setEnableCancelSorting(ConfigProvider.getConfig(WebConfig.class).getEnableCancelTableSorting());
ClientConfig clientConfig = AppBeans.get(Configuration.class).getConfig(ClientConfig.class);
addShortcutActionBridge(INSERT_SHORTCUT_ID, clientConfig.getTableInsertShortcut(), ListActionType.CREATE);

View File

@ -603,6 +603,13 @@ public class WebGroupTable extends WebAbstractTable<CubaGroupTable> implements G
return new GroupDataSourceRefreshListener();
}
@Override
public void resetSortOrder() {
if (datasource instanceof CollectionDatasource.Sortable) {
((CollectionDatasource.Sortable) datasource).resetSortOrder();
}
}
protected class GroupDataSourceRefreshListener extends DataSourceRefreshListener {
@Override
public void stateChanged(Datasource<Entity> ds, Datasource.State prevState, Datasource.State state) {

View File

@ -16,6 +16,7 @@ import com.haulmont.cuba.web.gui.data.ItemWrapper;
import com.haulmont.cuba.web.gui.data.PropertyWrapper;
import com.haulmont.cuba.web.gui.data.SortableCollectionDsWrapper;
import com.haulmont.cuba.web.toolkit.data.AggregationContainer;
import com.haulmont.cuba.web.toolkit.data.TableContainer;
import com.haulmont.cuba.web.toolkit.ui.CubaTable;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
@ -157,7 +158,7 @@ public class WebTable extends WebAbstractTable<CubaTable> implements Component.W
}
protected class SortableTableDsWrapper extends SortableCollectionDsWrapper
implements AggregationContainer {
implements AggregationContainer, TableContainer {
private List<Object> aggregationProperties = null;
@ -208,7 +209,7 @@ public class WebTable extends WebAbstractTable<CubaTable> implements Component.W
@Override
public void addContainerPropertyAggregation(Object propertyId, Type type) {
if (aggregationProperties == null) {
aggregationProperties = new LinkedList<Object>();
aggregationProperties = new LinkedList<>();
} else if (aggregationProperties.contains(propertyId)) {
throw new IllegalStateException("Such aggregation property is already exists");
}
@ -230,5 +231,12 @@ public class WebTable extends WebAbstractTable<CubaTable> implements Component.W
public Map<Object, Object> aggregate(Context context) {
return __aggregate(this, context);
}
@Override
public void resetSortOrder() {
if (datasource instanceof CollectionDatasource.Sortable) {
((CollectionDatasource.Sortable) datasource).resetSortOrder();
}
}
}
}

View File

@ -298,6 +298,13 @@ public class WebTreeTable extends WebAbstractTable<CubaTreeTable> implements Tre
public Map<Object, Object> aggregate(Context context) {
return __aggregate(this, context);
}
@Override
public void resetSortOrder() {
if (datasource instanceof CollectionDatasource.Sortable) {
((CollectionDatasource.Sortable) datasource).resetSortOrder();
}
}
}
protected class CubaTreeTableExt extends CubaTreeTable {

View File

@ -13,7 +13,7 @@ import java.util.Collection;
* @author gorodnov
* @version $Id$
*/
public interface GroupTableContainer extends Container.Sortable {
public interface GroupTableContainer extends TableContainer {
void groupBy(Object[] properties);
boolean isGroup(Object id);

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2013 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.web.toolkit.data;
import com.vaadin.data.Container;
/**
* @author artamonov
* @version $Id$
*/
public interface TableContainer extends Container.Sortable {
void resetSortOrder();
}

View File

@ -11,7 +11,7 @@ import com.vaadin.data.Container;
* @author gorodnov
* @version $Id$
*/
public interface TreeTableContainer extends Container.Hierarchical {
public interface TreeTableContainer extends TableContainer, Container.Hierarchical {
boolean isCaption(Object itemId);
String getCaption(Object itemId);

View File

@ -233,4 +233,9 @@ public class GroupTableContainerWrapper extends ContainerOrderedWrapper
throw new IllegalStateException("Wrapped container is not Sortable: "
+ container.getClass());
}
@Override
public void resetSortOrder() {
groupTableContainer.resetSortOrder();
}
}

View File

@ -18,7 +18,6 @@ import java.util.*;
* @author gorodnov
* @version $Id$
*/
@SuppressWarnings("serial")
public class TreeTableContainerWrapper
extends ContainerHierarchicalWrapper
implements TreeTableContainer, AggregationContainer, Container.Ordered, Container.Sortable {
@ -470,4 +469,11 @@ public class TreeTableContainerWrapper
throw new IllegalStateException("Wrapped container is not AggregationContainer: "
+ container.getClass());
}
@Override
public void resetSortOrder() {
if (treeTableContainer) {
((TreeTableContainer)container).resetSortOrder();
}
}
}

View File

@ -7,6 +7,7 @@
package com.haulmont.cuba.web.toolkit.ui;
import com.haulmont.cuba.web.gui.data.PropertyValueStringify;
import com.haulmont.cuba.web.toolkit.data.TableContainer;
import com.haulmont.cuba.web.toolkit.ui.client.table.CubaTableState;
import com.vaadin.data.Property;
import com.vaadin.event.Action;
@ -26,7 +27,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* @author artamonov
* @version $Id$
*/
public class CubaTable extends com.vaadin.ui.Table {
public class CubaTable extends com.vaadin.ui.Table implements TableContainer {
protected LinkedList<Object> editableColumns = null;
@ -52,19 +53,21 @@ public class CubaTable extends com.vaadin.ui.Table {
}
}
public boolean isAllowPopupMenu(){
public boolean isAllowPopupMenu() {
return getState(false).allowPopupMenu;
}
public void setAllowPopupMenu(boolean allowPopupMenu){
if (isAllowPopupMenu() != allowPopupMenu)
public void setAllowPopupMenu(boolean allowPopupMenu) {
if (isAllowPopupMenu() != allowPopupMenu) {
getState(true).allowPopupMenu = allowPopupMenu;
}
}
@Override
protected String formatPropertyValue(Object rowId, Object colId, Property<?> property) {
if (property instanceof PropertyValueStringify)
if (property instanceof PropertyValueStringify) {
return ((PropertyValueStringify) property).getFormattedValue();
}
return super.formatPropertyValue(rowId, colId, property);
}
@ -149,6 +152,19 @@ public class CubaTable extends com.vaadin.ui.Table {
shortcutsManager.paintActions(null, target);
}
@Override
protected boolean changeVariables(Map<String, Object> variables) {
boolean clientNeedsContentRefresh = super.changeVariables(variables);
if (variables.containsKey("resetsortorder")) {
resetSortOrder();
markAsDirty();
}
return clientNeedsContentRefresh;
}
@Override
public void addShortcutListener(ShortcutListener listener) {
/*if (listener.getKeyCode() != 13 || !(listener.getModifiers() == null || listener.getModifiers().length > 0)) {*/
@ -158,8 +174,18 @@ public class CubaTable extends com.vaadin.ui.Table {
}
@Override
public void removeShortcutListener(ShortcutListener listener){
public void removeShortcutListener(ShortcutListener listener) {
/*shortcutListeners.remove(listener);*/
shortcutsManager.removeAction(listener);
}
@Override
public void resetSortOrder() {
sortContainerPropertyId = null;
sortAscending = true;
if (items instanceof TableContainer) {
((TableContainer) items).resetSortOrder();
}
}
}

View File

@ -7,6 +7,7 @@
package com.haulmont.cuba.web.toolkit.ui;
import com.haulmont.cuba.web.gui.data.PropertyValueStringify;
import com.haulmont.cuba.web.toolkit.data.TableContainer;
import com.haulmont.cuba.web.toolkit.data.TreeTableContainer;
import com.haulmont.cuba.web.toolkit.data.util.TreeTableContainerWrapper;
import com.haulmont.cuba.web.toolkit.ui.client.treetable.CubaTreeTableState;
@ -16,6 +17,7 @@ import com.vaadin.data.util.HierarchicalContainer;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
@ -142,6 +144,19 @@ public class CubaTreeTable extends com.vaadin.ui.TreeTable implements TreeTableC
}
}
@Override
protected boolean changeVariables(Map<String, Object> variables) {
boolean clientNeedsContentRefresh = super.changeVariables(variables);
if (variables.containsKey("resetsortorder")) {
resetSortOrder();
markAsDirty();
}
return clientNeedsContentRefresh;
}
@Override
protected String formatPropertyValue(Object rowId, Object colId, Property<?> property) {
if (property instanceof PropertyValueStringify)
@ -176,4 +191,14 @@ public class CubaTreeTable extends com.vaadin.ui.TreeTable implements TreeTableC
public boolean isExpanded(Object itemId) {
return !isCollapsed(itemId);
}
@Override
public void resetSortOrder() {
sortContainerPropertyId = null;
sortAscending = true;
if (items instanceof TableContainer) {
((TableContainer) items).resetSortOrder();
}
}
}