blob: e2c29854fbf5b31e125ae71316588f366b4b6fe2 [file] [log] [blame]
/*
* Copyright 2010 Google Inc.
*
* 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.google.gwt.user.cellview.client;
import java.util.ArrayList;
import java.util.List;
/**
* An ordered list containing the sort history of {@link Column}s in a table.
* The 0th item is the {@link ColumnSortInfo} of the most recently sorted
* column.
*/
public class ColumnSortList {
/**
* Information about the sort order of a specific column in a table.
*/
public static class ColumnSortInfo {
private final boolean ascending;
private final Column<?, ?> column;
/**
* Construct a new {@link ColumnSortInfo}.
*
* @param column the column index
* @param ascending true if sorted ascending
*/
public ColumnSortInfo(Column<?, ?> column, boolean ascending) {
this.column = column;
this.ascending = ascending;
}
/**
* Default constructor used for RPC.
*/
ColumnSortInfo() {
this(null, true);
}
/**
* Check if this object is equal to another. The objects are equal if the
* column and ascending values are the equal.
*
* @param obj the object to check for equality
* @return true if objects are the same
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (!(obj instanceof ColumnSortInfo)) {
return false;
}
ColumnSortInfo other = (ColumnSortInfo) obj;
return equalsOrBothNull(getColumn(), other.getColumn())
&& isAscending() == other.isAscending();
}
/**
* Get the {@link Column} that was sorted.
*
* @return the {@link Column}
*/
public Column<?, ?> getColumn() {
return column;
}
@Override
public int hashCode() {
return 31 * (column == null ? 0 : column.hashCode())
+ (ascending ? 1 : 0);
}
/**
* Check if the column was sorted in ascending or descending order.
*
* @return true if ascending, false if descending
*/
public boolean isAscending() {
return ascending;
}
private boolean equalsOrBothNull(Object a, Object b) {
return a == null ? b == null : a.equals(b);
}
}
/**
* The delegate that handles modifications to the list.
*/
public static interface Delegate {
/**
* Called when the list is modified.
*/
void onModification();
}
/**
* The delegate that handles modifications.
*/
private final Delegate delegate;
/**
* A List used to manage the insertion/removal of {@link ColumnSortInfo}.
*/
private final List<ColumnSortInfo> infos = new ArrayList<ColumnSortInfo>();
/**
* Construct a new {@link ColumnSortList} without a {@link Delegate}.
*/
public ColumnSortList() {
this(null);
}
/**
* Construct a new {@link ColumnSortList} with the specified {@link Delegate}.
*
* @param delegate the {@link Delegate} to inform of modifications
*/
public ColumnSortList(Delegate delegate) {
this.delegate = delegate;
}
/**
* Removes all of the elements from this list.
*/
public void clear() {
infos.clear();
fireDelegate();
}
/**
* Check if the specified object equals this list. Two {@link ColumnSortList}
* are equals if they are the same size, and all entries are
* <code>equals</code> and in the same order.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (!(obj instanceof ColumnSortList)) {
return false;
}
// Check the size of the lists.
ColumnSortList other = (ColumnSortList) obj;
return infos.equals(other.infos);
}
/**
* Get the {@link ColumnSortInfo} at the specified index.
*
* @param index the index
* @return the {@link ColumnSortInfo}
*/
public ColumnSortInfo get(int index) {
return infos.get(index);
}
@Override
public int hashCode() {
return 31 * infos.hashCode() + 13;
}
/**
* Inserts the specified {@link ColumnSortInfo} at the specified position in
* this list. If the column already exists in the sort info, the index will be
* adjusted to account for any removed entries.
*
* @param sortInfo the {@link ColumnSortInfo} to add
*/
public void insert(int index, ColumnSortInfo sortInfo) {
if (sortInfo == null) {
throw new IllegalArgumentException("sortInfo cannot be null");
}
// Remove sort info for duplicate columns
Column<?, ?> column = sortInfo.getColumn();
for (int i = 0; i < infos.size(); i++) {
ColumnSortInfo curInfo = infos.get(i);
if (curInfo.getColumn() == column) {
infos.remove(i);
if (i < index) {
index--;
}
i--;
}
}
// Insert the new sort info
infos.add(index, sortInfo);
fireDelegate();
}
/**
* Push a {@link Column} onto the list at index zero, setting ascending to
* true. If the column already exists, it will be removed from its current
* position and placed at the start of the list. If the Column is already at
* the start of the list, its ascending bit will be flipped (ascending to
* descending and vice versa).
*
* @param column the {@link Column} to push
* @return the {@link ColumnSortInfo} that was pushed
*/
public ColumnSortInfo push(Column<?, ?> column) {
// If the column matches the primary column, toggle the order.
boolean ascending = true;
if (size() > 0 && get(0).getColumn() == column) {
ascending = !get(0).isAscending();
}
// Push the new column.
ColumnSortInfo toRet = new ColumnSortInfo(column, ascending);
push(toRet);
return toRet;
}
/**
* Push a {@link ColumnSortInfo} onto the list at index zero. If the column
* already exists, it will be removed from its current position and placed at
* the start of the list.
*
* @param sortInfo the {@link ColumnSortInfo} to push
*/
public void push(ColumnSortInfo sortInfo) {
insert(0, sortInfo);
}
/**
* Remove a {@link ColumnSortInfo} from the list.
*
* @param sortInfo the {@link ColumnSortInfo} to remove
*/
public boolean remove(ColumnSortInfo sortInfo) {
boolean toRet = infos.remove(sortInfo);
fireDelegate();
return toRet;
}
/**
* Get the size of the list.
*
* @return the number of {@link ColumnSortInfo} in the list
*/
public int size() {
return infos.size();
}
private void fireDelegate() {
if (delegate != null) {
delegate.onModification();
}
}
}