diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/INewObject.java b/navalplanner-business/src/main/java/org/navalplanner/business/INewObject.java new file mode 100644 index 000000000..186187ac7 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/INewObject.java @@ -0,0 +1,5 @@ +package org.navalplanner.business; + +public interface INewObject { + public boolean isNewObject(); +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/BaseEntity.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/BaseEntity.java index cbbc7592f..63136c492 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/common/BaseEntity.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/BaseEntity.java @@ -20,6 +20,8 @@ package org.navalplanner.business.common; +import org.navalplanner.business.INewObject; + /** * Base class for all the application entities. @@ -28,7 +30,7 @@ package org.navalplanner.business.common; * * @author Manuel Rego Casasnovas */ -public abstract class BaseEntity { +public abstract class BaseEntity implements INewObject { private Long id; @@ -60,7 +62,7 @@ public abstract class BaseEntity { this.newObject = newObject; } - protected boolean isNewObject() { + public boolean isNewObject() { return newObject; } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/NewDataSortableColumn.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/NewDataSortableColumn.java new file mode 100644 index 000000000..116242a31 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/NewDataSortableColumn.java @@ -0,0 +1,139 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e + * Desenvolvemento Tecnolóxico de Galicia + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.navalplanner.web.common.components; + +import java.util.Comparator; + +import org.navalplanner.business.INewObject; +import org.zkoss.zk.ui.ext.AfterCompose; +import org.zkoss.zul.Column; +import org.zkoss.zul.api.Grid; + +/** + * {@link NewDataSortableColumn} is a macrocomponent which extends {@link Column} + *

+ * NewDataSortableColumn extends the {@link Column} component and adds the + * following behaviour: It creates a {@link Comparator} which is a + * decorator of the comparator the component has configured. This comparator + * delegates in the encapsulated comparator configured by the user, except + * when the objects implement the interface {@link INewObject}. In that case, + * the new objects are considered always that are placed before than the + * object which are not new. + *

+ * The {@link NewDataSortableColumn} must be included inside {@link NewDataSortableGrid} + * in order to work properly. They notify the {@link NewDataSortableGrid} in which are + * included when they are requested to be sorted. + *

+ * @author Javier Moran Rua + */ + +public class NewDataSortableColumn extends Column implements AfterCompose { + + private static class NewObjectDecoratorComparator implements Comparator { + private Comparator decoratedComparator; + + public NewObjectDecoratorComparator(Comparator c) { + this.decoratedComparator = c; + } + + @Override + public int compare(Object o1, Object o2) { + if (!doComparingObjectsSupportInterface(o1, o2)) { + return decoratedComparator.compare(o1, o2); + } else { + return decorateBehaviour((INewObject) o1, (INewObject) o2); + } + } + + private boolean doComparingObjectsSupportInterface(Object o1, Object o2) { + if ((o1 instanceof INewObject) && (o2 instanceof INewObject)) { + return true; + } else { + return false; + } + } + + private int decorateBehaviour(INewObject o1, INewObject o2) { + int result; + + if ((o1.isNewObject()) && (o2.isNewObject())) { + result = 0; + } else if ((o1.isNewObject()) && (!o2.isNewObject())) { + result = -1; + } else if ((!o1.isNewObject()) && (o2.isNewObject())) { + result = 1; + } else { + result = decoratedComparator.compare(o1, o2); + } + + return result; + } + } + + @Override + public void setSortAscending(Comparator c) { + super.setSortAscending(new NewObjectDecoratorComparator(c)); + } + + @Override + public void setSortDescending(Comparator c) { + super.setSortDescending(new NewObjectDecoratorComparator(c)); + } + + @Override + public boolean sort(boolean ascending) { + Grid grid = getGrid(); + if (grid instanceof NewDataSortableGrid) { + ((NewDataSortableGrid) grid).setSortedColumn(this); + ((NewDataSortableGrid) grid).setLastSortedColumnAscending(ascending); + } + return super.sort(ascending); + } + + @Override + public void afterCompose() { + Grid g = getGrid(); + + if ((g instanceof NewDataSortableGrid)) { + NewDataSortableGrid castedGrid = (NewDataSortableGrid) g; + + // The first registered column is responsible for ordering + if (castedGrid.getSortedColumn() == null) { + markInGridAsColumnToOrder(castedGrid); + } + } + } + + private void markInGridAsColumnToOrder(NewDataSortableGrid parentGrid) { + parentGrid.setSortedColumn(this); + + if ("ascending".equals(getSortDirection())) { + System.out.println("Ascending order"); + parentGrid.setLastSortedColumnAscending( + Boolean.TRUE.booleanValue()); + } else if ("descending".equals(getSortDirection())) { + System.out.println("Descending order"); + parentGrid.setLastSortedColumnAscending( + Boolean.FALSE.booleanValue()); + } + } + +} \ No newline at end of file diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/NewDataSortableGrid.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/NewDataSortableGrid.java new file mode 100644 index 000000000..ec3905e84 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/components/NewDataSortableGrid.java @@ -0,0 +1,113 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e + * Desenvolvemento Tecnolóxico de Galicia + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.navalplanner.web.common.components; + +import static org.navalplanner.web.I18nHelper._; + +import java.util.Comparator; + +import org.apache.commons.lang.Validate; +import org.navalplanner.business.INewObject; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.ext.AfterCompose; +import org.zkoss.zul.Grid; +import org.zkoss.zul.ListModel; +import org.zkoss.zul.ListModelExt; +import org.zkoss.zul.api.Column; + +/** + * NewDataSortableGrid is a macrocomponent which extends {@link Grid} + *

+ * NewDataSortableGrid objects must include inside it + * {@link NewDataSortableColumn} components. They notify their grid when they + * are sorted. The first time it is rendered the NewDataSortableGrid the first + * of the {@link Column} is used to order the model. So, in the case the model + * is not given in a proper order, it is ordered before showing the data. + *

+ * + * @author Javier Moran Rua + */ + +public class NewDataSortableGrid extends Grid implements AfterCompose { + + private Column lastSortedColumn; + private boolean lastSortedColumnAscending; + + public NewDataSortableGrid() { + addEventListener(Events.ON_SORT, new EventListener() { + @Override + public void onEvent(Event event) throws Exception { + sortByLastColumn(); + } + }); + } + + public void setSortedColumn(Column c) { + if (c == null) { + throw new IllegalArgumentException("The column parameter cannot" + + "cannot be null"); + } + this.lastSortedColumn = c; + } + + public Column getSortedColumn() { + return lastSortedColumn; + } + + public void setLastSortedColumnAscending(boolean ascending) { + this.lastSortedColumnAscending = ascending; + } + + + public boolean getLastSortedColumnAscending() { + return lastSortedColumnAscending; + } + + public void afterCompose() { + // We post the ON_SORT event to order the grid. It is needed + // to use an event because at this point the columns + // inside the component are not still accessible + Events.postEvent(Events.ON_SORT, this, null); + } + + @Override + public void setModel(ListModel listModel) { + super.setModel(listModel); + sortByLastColumn(); + } + + private void sortByLastColumn() { + if (!(getModel() instanceof ListModelExt)) { + return; + } + + ListModelExt model = (ListModelExt) getModel(); + if (lastSortedColumnAscending == true) { + model.sort(lastSortedColumn.getSortAscending(), + lastSortedColumnAscending); + } else { + model.sort(lastSortedColumn.getSortDescending(), + lastSortedColumnAscending); + } + } +} \ No newline at end of file diff --git a/navalplanner-webapp/src/main/resources/metainfo/zk/lang-addon.xml b/navalplanner-webapp/src/main/resources/metainfo/zk/lang-addon.xml index e1ba59653..1b5426890 100755 --- a/navalplanner-webapp/src/main/resources/metainfo/zk/lang-addon.xml +++ b/navalplanner-webapp/src/main/resources/metainfo/zk/lang-addon.xml @@ -35,4 +35,24 @@ /common/components/bandbox_search.zul + + newdatasortablecolumn + org.navalplanner.web.common.components.NewDataSortableColumn + column + + + + newdatasortablegrid + org.navalplanner.web.common.components.NewDataSortableGrid + grid + + default-bind + model + + converter + org.zkoss.zkplus.databind.ListModelConverter + + + +