Java tutorial
/******************************************************************************* * Copyright (c) 2014, 2015 Scott Clarke (scott@dawg6.com). * * This file is part of Dawg6's Common GWT Libary. * * Dawg6's Common GWT Libary is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Dawg6's Common GWT Libary 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ package com.dawg6.gwt.client.widgets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Vector; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.FlexTable; public class SortableTable<T> extends FlexTable { protected List<T> data; protected int numHeaderRows; protected Renderer<T> renderer; public enum Direction { Forward, Reverse; public Direction change() { return Direction.values()[1 - this.ordinal()]; } } public static class Column<T> { String title; String style; Comparator<T> comparator; public Column(String title, String style, Comparator<T> comparator) { this.title = title; this.style = style; this.comparator = comparator; } } public interface Renderer<T> { void renderHeader(SortableTable<T> table); void beforeTable(SortableTable<T> table); void renderRow(SortableTable<T> table, int row, T item); void afterTable(SortableTable<T> table); } public static abstract class DefaultRenderer<T> implements Renderer<T> { private final List<Column<T>> columns; private Column<T> selected; private Direction direction; public DefaultRenderer(Collection<Column<T>> columns) { this(columns, 0); } public DefaultRenderer(Collection<Column<T>> columns, int selected) { this(columns, selected, Direction.Forward); } public DefaultRenderer(Collection<Column<T>> columns, int selected, Direction direction) { this.columns = new ArrayList<Column<T>>(columns); this.selected = this.columns.get(selected); this.direction = direction; } @Override public void beforeTable(SortableTable<T> table) { } @Override public void afterTable(SortableTable<T> table) { } @Override public void renderHeader(final SortableTable<T> table) { int i = 0; for (Column<T> c : columns) { final Column<T> col = c; final Comparator<T> comp = col.comparator; String style = col.style; String title = col.title; if (comp == null) { StyledLabel label = new StyledLabel(title, false, style); table.setWidget(0, i, label); } else { Anchor anchor = new Anchor(); anchor.setText(title); anchor.setHref("javascript:void(0)"); anchor.setTitle("Click to Sort/Reverse"); table.setWidget(0, i, anchor); if (style != null) anchor.addStyleName(style); anchor.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { sort(table, col, comp); } }); } i++; } } protected void sort(SortableTable<T> table, Column<T> col, final Comparator<T> comp) { if ((this.selected != null) && (col == this.selected)) { this.direction = this.direction.change(); } else { this.selected = col; this.direction = Direction.Forward; } if (this.direction == Direction.Forward) table.sortData(comp); else table.sortData(new Comparator<T>() { @Override public int compare(T o1, T o2) { return -comp.compare(o1, o2); } }); } } public SortableTable(Renderer<T> renderer) { this(renderer, new Vector<T>()); } public SortableTable(Renderer<T> renderer, List<T> data) { this.renderer = renderer; renderer.renderHeader(this); this.numHeaderRows = this.getRowCount(); setData(data); } public void setData(List<T> data) { if ((data != null) && !data.isEmpty()) this.data = new Vector<T>(data); else this.data = new Vector<T>(); } public List<T> getData() { if ((data != null) && !data.isEmpty()) return Collections.unmodifiableList(data); else return new Vector<T>(); } public void clearTable() { while (this.getRowCount() > numHeaderRows) this.removeRow(numHeaderRows); } public void fillTable() { clearTable(); int row = numHeaderRows; renderer.beforeTable(this); if ((data != null) && !data.isEmpty()) { for (T item : data) { renderer.renderRow(this, row++, item); } } renderer.afterTable(this); } public void sortData(Comparator<? super T> comparator) { if ((data != null) && !data.isEmpty()) { Collections.sort(data, comparator); } fillTable(); } }