package org.gwtoolbox.widget.client.table.datagrid;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.event.dom.client.KeyDownEvent;
import org.gwtoolbox.commons.collections.client.Page;
import org.gwtoolbox.commons.conversion.client.TextConverterManager;
import org.gwtoolbox.widget.client.WidgetImages;
import org.gwtoolbox.commons.ui.client.event.EnterKeyHandler;
import org.gwtoolbox.widget.client.data.DataSource;
import org.gwtoolbox.widget.client.data.FieldSort;
import org.gwtoolbox.widget.client.data.Record;
import org.gwtoolbox.widget.client.data.SortSpec;
import org.gwtoolbox.widget.client.menu.MenuBuilder;
import org.gwtoolbox.widget.client.notification.AbstractCallback;
import static org.gwtoolbox.widget.client.panel.LayoutUtils.addGap;
import org.gwtoolbox.widget.client.table.basic.BasicTable;
import org.gwtoolbox.widget.client.table.basic.CellListener;
import org.gwtoolbox.widget.client.table.basic.sort.TableSorter;
import org.gwtoolbox.widget.client.table.datagrid.column.CellRenderer;
import org.gwtoolbox.widget.client.table.datagrid.column.Column;
import org.gwtoolbox.widget.client.table.datagrid.column.ColumnSpec;
import org.gwtoolbox.widget.client.table.datagrid.column.FieldColumn;
import org.gwtoolbox.widget.client.table.datagrid.selection.NoOpRecordSelectionModel;
import org.gwtoolbox.widget.client.table.datagrid.selection.RecordSelectionModel;
import java.util.*;
/**
* @author Uri Boness
*/
public class OldDataGrid extends Composite {
private final static RecordRowDecorator NO_OP_ROW_DECORATOR = new RecordRowDecorator() {
public void decorateRow(int row, Record record, BasicTable.BasicTableRowFormatter rowFormatter) {
}
};
private ColumnSpec columnSpec;
private DataSource dataSource;
private BasicTable table;
private TableStatusBar statusBar;
private Integer pageSize;
private Page<Record> currentPage;
private Collection<Record> currentRecords;
private SortSpec currentSortSpec;
private MessagePopup loadingPopup = new MessagePopup(false, true);
private RecordSelectionListenerCollection selectionListeners = new RecordSelectionListenerCollection();
private DataGridListenerCollection dataGridListeners = new DataGridListenerCollection();
private RecordRowDecorator rowDecorator = NO_OP_ROW_DECORATOR;
private FieldGroup currentFieldGroup;
private RecordSelectionModel selectionModel;
/**
* Constructs a new OldDataGrid with the given columns specification. The columns spec. defines what columns should this
* data grid have and how they should be rendered.
*
* @param columnSpec The given columns specification.
*/
public OldDataGrid(ColumnSpec columnSpec) {
this(columnSpec, null);
}
/**
* Constructs a new OldDataGrid with the given columns specification. The columns spec. defines what columns should this
* data grid have and how they should be rendered. This constructor also accepts a data source from which the data
* will be fetched.
*
* @param columnSpec The given columns specification.
* @param dataSource The data source from which the records will be fetched.
* @see #setDataSource(org.gwtoolbox.widget.client.data.DataSource)
*/
public OldDataGrid(final ColumnSpec columnSpec, DataSource dataSource) {
this.columnSpec = columnSpec;
VerticalPanel main = new VerticalPanel();
table = new BasicTable();
table.setSize("100%", "100%");
table.setSorter(new InternalTableSorter());
setSelectionModel(NoOpRecordSelectionModel.getInstance());
table.addCellListener(new CellListener() {
public void onDoubleClick(int row, int column, Event event) {
Record record = (Record) table.getUserData(row, 0);
dataGridListeners.notifyRecordDoubleClicked(record, event);
}
public void onRightClick(int row, int column, Event event) {
Record record = (Record) table.getUserData(row, 0);
dataGridListeners.notifyRecordRightClicked(record, event);
}
});
int index = 0;
for (Column column : columnSpec.getColumns()) {
table.setHeaderText(index, column.getName());
table.getHeaderFormatter().setHorizontalAlignment(index, column.getHorizontalAlignment());
table.getHeaderFormatter().setSortable(index, column.isSortable());
MenuBuilder menuBuilder = column.getMenuBuilder(this);
if (menuBuilder != null) {
table.getHeaderFormatter().setMenuBar(index, menuBuilder);
}
String width = column.getWidth();
if (width != null) {
table.getColumnFormatter().setWidth(index, width);
}
index++;
}
SimplePanel simplePanel = new SimplePanel();
simplePanel.setWidget(table);
table.setWidth("100%");
main.add(simplePanel);
statusBar = new TableStatusBar();
statusBar.setHeight("25px");
main.add(statusBar);
statusBar.setVisible(false);
setDataSource(dataSource);
initWidget(main);
setStyleName("DataGrid");
}
/**
* Sets the data source this grid will be using to fetch the records from. The given data source does not need to be
* fully implemented. If this data grid operates in a paginated mode, only the paginated queries of the data source
* should be implemented. In a list mode, only the list queries must be implemented. To make your life easier, you can
* extend the {@code DataSourceAdapter} class and only implement the methods you really need. Furthermore, the
* {@code PaginatedDataSource}, {@code ReadOnlyPaginatedDataSource}, {@code CollectionDataSource} and
* {@code ReadOnlyCollectionDataSource} can be used as well as a parent type.
*
* @param dataSource The data source this grid will be using to fetch the records from.
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* Sets the page size to be displays. Calling this method will practically put this data grid in a paginated mode,
* meaning that the data will be fetched in pages from the data source, rather then the complete list of records at
* once.
*
* @param pageSize The size of the page this data grid should show.
*/
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
if (pageSize != null && currentRecords != null) {
currentRecords = null;
fetch(true);
return;
}
if (pageSize == null && currentPage != null) {
currentPage = null;
fetch(true);
return;
}
redraw();
}
public void setSelectionModel(RecordSelectionModel selectionModel) {
if (this.selectionModel != null) {
this.selectionModel.uninstall();
}
this.selectionModel = selectionModel;
selectionModel.install(this, table);
}
public void clearSelectionModel() {
setSelectionModel(NoOpRecordSelectionModel.getInstance());
}
/**
* Refreshes the data in the grid based on the attached data source. This method actually queries the data source
* for the grid's content. By default, calling this method will not show a loading message for the user, it is mainly
* ment to initialize the table before it is actually shown on the screen. To show the loading message use the
* {@code #fetch(boolean)} version of the fetch method. If you only need to refresh the view of the current data
* shown in the table (without actually fetching it from the data source), use the {@code #redraw()} method instead.
*/
public void fetch() {
fetch(null);
}
/**
* Refreshes the data in the grid based on the attached data source. This method actually queries the data source
* for the grid's content. The given argument indicates whether a loading message should be presented to the user
* while the request is being made.
*
* @param showLoadingMessage Indicate whether a loading message should be presented to the user while the content is
* being fetched.
*/
public void fetch(boolean showLoadingMessage) {
fetch(showLoadingMessage, null);
}
/**
* Refreshes the data in the grid based on the attached data source. This method actually queries the data source
* for the grid's content. This method enables you to provide a callback to this method that will be called once
* the data is fetched and the table is initialized with it.
*
* @param callback The callback that will be called once the data was fetched the the table was initialized with it.
*/
public void fetch(AsyncCallback<Void> callback) {
fetch(false, callback);
}
/**
* Redraws the current table based on the currently viewd page (in a pagianted mode) or the currently views list
* of records (in a non-paginated mode. This method differs from {@code #fetch()} as it does not re-retrieves any
* data from the attached data source.
*/
public void redraw() {
if (currentPage != null) {
statusBar.setVisible(true);
updateData(currentPage);
return;
}
if (currentRecords != null){
statusBar.setVisible(false);
updateData(currentRecords);
}
}
/**
* Sorts the table based on the given field and sort direction.
*
* @param fieldName The record field to sort on.
* @param asc The direction of the sort, {@code true} for Ascendint and {@code false} for Descending.
*/
public void sort(String fieldName, boolean asc) {
int column = columnSpec.getColumnIndex(fieldName);
table.sort(column, asc);
}
/**
* Adds a records selection listener to this table. It is via the selection listener that one can listen to record
* selection events.
*
* @param listener The record selection listener to register.
*/
public void addRecordSelectionListener(RecordSelectionListener listener) {
selectionListeners.add(listener);
}
/**
* Removes the given record selection listener from this data grid.
*
* @param listener The record selection listener to be removed
* @see #addRecordSelectionListener(RecordSelectionListener)
*/
public void removeRecordSelectionListener(RecordSelectionListener listener) {
selectionListeners.remove(listener);
}
/**
* Clears all record selection listeners registered in this data grid.
*/
public void clearRecordSelectionListeners() {
selectionListeners.clear();
}
/**
* Add the given data grid listener to this data grid. It is via this listener that once can listen to various event
* related to the records show on this grid (e.g. record double clicked, record right click).
*
* @param listener The data grid listener to be registered.
*/
public void addDataGridListener(DataGridListener listener) {
dataGridListeners.add(listener);
}
/**
* Removes the given data grid listener from this data grid.
*
* @param listener The listener to be removed.
* @see #addDataGridListener(DataGridListener)
*/
public void removeDataGridListener(DataGridListener listener) {
dataGridListeners.remove(listener);
}
/**
* Clears all data grid listeners registered in this data grid.
*/
public void clearDataGridListeners() {
dataGridListeners.clear();
}
/**
* Returns the number of rows currently shown by this data grid.
*
* @return The number of rows currently shown by this data grid.
*/
public int getRowCount() {
return table.getRowCount();
}
/**
* Sets the row decorator that will be used by this grid to decorate the rows. It is via the row decorator that one
* can customize the look (decorate) of a row in the table based on teh row index and the record associated with that
* row.
*
* @param rowDecorator The row decorator this grid will be using.
*/
public void setRowDecorator(RecordRowDecorator rowDecorator) {
this.rowDecorator = rowDecorator;
redraw();
}
/**
* Returns the currenly configured row decorator for this grid.
*
* @return The currenly configured row decorator for this grid.
* @see #setRowDecorator(RecordRowDecorator)
*/
public RecordRowDecorator getRowDecorator() {
return rowDecorator;
}
/**
* Clears the currently configured row decorator for this data grid.
*/
public void clearRowDecorator() {
setRowDecorator(NO_OP_ROW_DECORATOR);
}
public void setGroupBy(FieldGroup fieldGroup) {
this.currentFieldGroup = fieldGroup;
redraw();
}
public FieldGroup getGroupBy() {
return currentFieldGroup;
}
//============================================== Helper Methods ====================================================
private CellRenderer getCellRenderer(String fieldName) {
Column column = columnSpec.getColumn(fieldName);
return column.getCellRenderer();
}
private void updateData(Collection<Record> records) {
updateData((Iterable<Record>) records);
currentRecords = records;
}
private void updateData(Page<Record> page) {
updateData((Iterable<Record>)page);
if (page.isSingle()) {
statusBar.setVisible(false);
} else {
statusBar.update(page);
statusBar.setVisible(true);
}
currentPage = page;
}
private void updateData(Iterable<Record> records) {
if (currentFieldGroup == null) {
selectionModel.getSelection().clear();
table.removeAllRows();
for (Record record : records) {
addRecord(record);
}
} else {
// apply grouping:
// first we create the record groups and put them all in a sorted set. The set will be sorted by the
// group comparator (comparing groups by their values). Then, we'll add all groups and their associated
// records to the table where for each group we'll add a tool row (GroupTitle)
Set<RecordGroup> groups = new TreeSet<RecordGroup>(new Comparator<RecordGroup>() {
public int compare(RecordGroup g1, RecordGroup g2) {
Object v1 = g1.getValue();
Object v2 = g2.getValue();
return currentFieldGroup.getComparator().compare(v1, v2);
}
});
for (Record record : records) {
// first we're looking if there's already a group for this record, if not then we create one.
RecordGroup group = null;
for (RecordGroup currrentGroup : groups) {
if (currrentGroup.shouldContain(record)) {
group = currrentGroup;
break;
}
}
if (group == null) {
group = new RecordGroup(currentFieldGroup, record.getValue(currentFieldGroup.getFieldName()));
groups.add(group);
}
group.addRecord(record);
}
// adding all the groups and their associated records to the table.
selectionModel.getSelection().clear();
table.removeAllRows();
for (RecordGroup group : groups) {
Object value = group.getValue();
CellRenderer renderer = getCellRenderer(group.getFieldGroup().getFieldName());
GroupTitle groupTitle = new GroupTitle(currentFieldGroup, renderer.render(value), group.getRecords().size());
groupTitle.setWidth("100%");
table.insertToolRow(table.getRowCount(), groupTitle);
final int[] rows = new int[group.getRecords().size()];
int i = 0;
for (Record record : group.getRecords()) {
int row = addRecord(record);
rows[i] = row;
i++;
}
groupTitle.setListener(new GroupTitle.Listener() {
public void onCollapse() {
for (int i = 0; i < rows.length; i++) {
table.getRowFormatter().setVisible(rows[i], false);
}
}
public void onExpand() {
for (int i = 0; i < rows.length; i++) {
table.getRowFormatter().setVisible(rows[i], true);
}
}
});
}
}
}
// returns the row to which the record was added
private int addRecord(Record record) {
int row = getRowCount();
addRecord(row, record);
return row;
}
private void addRecord(int row, Record record) {
int column = 0;
for (Column c : columnSpec.getColumns()) {
Object value = c.getValueExtractor().extractValue(row, record);
Widget widget = c.getCellRenderer().render(value);
table.setWidet(row, column, widget);
table.getCellFormatter().setHorizontalAlignment(row, column, c.getHorizontalAlignment());
rowDecorator.decorateRow(row, record, table.getRowFormatter());
column++;
}
// we're associating the record with the first cell of each row. This way we'll be able to handle selection
// events
table.setUserData(row, 0, record);
}
private void showProgress() {
if (table.isAttached()) {
loadingPopup.setMessage("Loading...", true);
loadingPopup.showCentered();
}
}
private void hideProgress() {
loadingPopup.hide();
}
public void fetch(final boolean showProgress, final AsyncCallback<Void> callback) {
if (pageSize != null) {
fetchPage(showProgress, callback);
statusBar.setVisible(true);
} else {
statusBar.setVisible(false);
fetchCollection(showProgress, callback);
}
}
private void fetchPage(final boolean showProgress, final AsyncCallback<Void> callback) {
if (showProgress) {
showProgress();
}
dataSource.getPage(0, pageSize, currentSortSpec, new AbstractCallback<Page<Record>>() {
public void onFailure(Throwable caught) {
super.onFailure(caught);
if (showProgress) {
hideProgress();
}
if (callback != null) {
callback.onFailure(caught);
}
}
public void onSuccess(Page<Record> result) {
updateData(result);
if (showProgress) {
hideProgress();
}
if (callback != null) {
callback.onSuccess(null);
}
}
});
}
private void fetchCollection(final boolean showProgress, final AsyncCallback<Void> callback) {
if (showProgress) {
showProgress();
}
dataSource.getAll(currentSortSpec, new AbstractCallback<Collection<Record>>() {
public void onFailure(Throwable caught) {
super.onFailure(caught);
if (showProgress) {
hideProgress();
}
if (callback != null) {
callback.onFailure(caught);
}
}
public void onSuccess(Collection<Record> result) {
updateData(result);
if (showProgress) {
hideProgress();
}
if (callback != null) {
callback.onSuccess(null);
}
}
});
}
//============================================== Inner Classes =====================================================
public interface FetchCallback {
void onError(String message, boolean html);
void onSuccess();
}
protected class TableStatusBar extends Composite {
private PushButton firstButton;
private PushButton prevButton;
private PushButton nextButton;
private PushButton lastButton;
private PushButton refreshButton;
private TextBox pageBox;
private Label pageCountLabel;
private Label infoLabel;
public TableStatusBar() {
HorizontalPanel main = new HorizontalPanel();
firstButton = new PushButton();
firstButton.setStylePrimaryName("Button");
firstButton.getUpFace().setImage(DataGridImages.Instance.get().button_pageFirst().createImage());
firstButton.getUpDisabledFace().setImage(DataGridImages.Instance.get().button_pageFirstDisabled().createImage());
firstButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
handleGoToFirst();
}
});
main.add(firstButton);
main.setCellHorizontalAlignment(firstButton, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(firstButton, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
prevButton = new PushButton();
prevButton.setStylePrimaryName("Button");
prevButton.getUpFace().setImage(DataGridImages.Instance.get().button_pagePrev().createImage());
prevButton.getUpDisabledFace().setImage(DataGridImages.Instance.get().button_pagePrevDisabled().createImage());
prevButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
handleGoToPrev();
}
});
main.add(prevButton);
main.setCellHorizontalAlignment(prevButton, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(prevButton, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
Image separator = WidgetImages.Instance.get().separator().createImage();
main.add(separator);
main.setCellHorizontalAlignment(separator, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(separator, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
Label label = new Label("Page");
main.add(label);
main.setCellHorizontalAlignment(label, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(label, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
pageBox = new TextBox();
pageBox.setWidth("30px");
pageBox.setHeight("25px");
pageBox.addKeyDownHandler(new EnterKeyHandler() {
protected void onEnter(KeyDownEvent event) {
int page = resolvePage(pageBox.getText());
if (page < 0 || page > currentPage.getLastPage()) {
pageBox.setText(String.valueOf(currentPage.getIndex() + 1));
} else {
goToPage(page);
}
}
});
main.add(pageBox);
main.setCellHorizontalAlignment(pageBox, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(pageBox, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
label = new Label("of");
main.add(label);
main.setCellHorizontalAlignment(label, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(label, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
pageCountLabel = new Label();
main.add(pageCountLabel);
main.setCellHorizontalAlignment(pageCountLabel, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(pageCountLabel, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
separator = WidgetImages.Instance.get().separator().createImage();
main.add(separator);
main.setCellHorizontalAlignment(separator, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(separator, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
nextButton = new PushButton();
nextButton.setStylePrimaryName("Button");
nextButton.getUpFace().setImage(DataGridImages.Instance.get().button_pageNext().createImage());
nextButton.getUpDisabledFace().setImage(DataGridImages.Instance.get().button_pageNextDisabled().createImage());
nextButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
handleGoToNext();
}
});
main.add(nextButton);
main.setCellHorizontalAlignment(nextButton, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(nextButton, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
lastButton = new PushButton();
lastButton.setStylePrimaryName("Button");
lastButton.getUpFace().setImage(DataGridImages.Instance.get().button_pageLast().createImage());
lastButton.getUpDisabledFace().setImage(DataGridImages.Instance.get().button_pageLastDisabled().createImage());
lastButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
handleGoToLast();
}
});
main.add(lastButton);
main.setCellHorizontalAlignment(lastButton, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(lastButton, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
separator = WidgetImages.Instance.get().separator().createImage();
main.add(separator);
main.setCellHorizontalAlignment(separator, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(separator, HorizontalPanel.ALIGN_MIDDLE);
main.add(hGap("3px"));
refreshButton = new PushButton();
refreshButton.setStylePrimaryName("Button");
refreshButton.getUpFace().setImage(DataGridImages.Instance.get().button_refresh().createImage());
refreshButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
handleRefresh();
}
});
main.add(refreshButton);
main.setCellHorizontalAlignment(refreshButton, HorizontalPanel.ALIGN_CENTER);
main.setCellVerticalAlignment(refreshButton, HorizontalPanel.ALIGN_MIDDLE);
infoLabel = new Label();
main.add(infoLabel);
main.setCellWidth(infoLabel, "100%");
main.setCellHorizontalAlignment(infoLabel, HorizontalPanel.ALIGN_RIGHT);
main.setCellVerticalAlignment(infoLabel, HorizontalPanel.ALIGN_MIDDLE);
initWidget(main);
setStyleName("StatusBar");
}
public void update(Page<Record> page) {
firstButton.setEnabled(!page.isFirst());
prevButton.setEnabled(!page.isFirst());
lastButton.setEnabled(!page.isLast());
nextButton.setEnabled(!page.isLast());
pageBox.setText(String.valueOf(page.getIndex() + 1));
pageCountLabel.setText(String.valueOf(page.getTotalPageCount()));
infoLabel.setText("Displaying " + (page.getFirstItemIndex() + 1) + " - " + (page.getLastItemIndex() + 1) + " of " + page.getTotalCount());
}
//============================================== Helper Methods ====================================================
private void handleGoToFirst() {
goToPage(0);
}
private void handleGoToPrev() {
if (currentPage != null) {
goToPage(currentPage.getIndex() - 1);
}
}
private void handleGoToNext() {
if (currentPage != null) {
goToPage(currentPage.getIndex() + 1);
}
}
private void handleGoToLast() {
if (currentPage != null) {
goToPage(currentPage.getLastPage());
}
}
private void handleRefresh() {
if (currentPage != null) {
goToPage(currentPage.getIndex());
}
}
private void goToPage(int index) {
showProgress();
dataSource.getPage(index, pageSize, currentSortSpec, new AbstractCallback<Page<Record>>() {
public void onFailure(Throwable caught) {
super.onFailure(caught);
hideProgress();
}
public void onSuccess(Page<Record> result) {
updateData(result);
hideProgress();
}
});
}
private Widget hGap(String width) {
Label label = new Label();
label.setWidth(width);
return label;
}
private int resolvePage(String text) {
try {
int page = TextConverterManager.getGlobalConverter().toValue(Integer.class, text);
return page - 1;
} catch (Throwable t) {
return -1;
}
}
}
private class InternalTableSorter implements TableSorter {
public void sort(BasicTable table, int column, boolean asc) {
Column c = columnSpec.getColumn(column);
if (!(c instanceof FieldColumn)) {
return;
}
FieldSort sort = new FieldSort(((FieldColumn)c).getFieldName(), asc);
currentSortSpec = new SortSpec().addSort(sort);
showProgress();
fetch(true, null);
}
}
private class MessagePopup extends PopupPanel {
private HTML loadingLabel;
private Image loadingImage;
public MessagePopup(boolean autoHide) {
this(autoHide, false);
}
public MessagePopup(boolean autoHide, boolean modal) {
super(autoHide, modal);
HorizontalPanel content = new HorizontalPanel();
loadingImage = new Image("gwtoolbox/images/loading.gif");
content.add(loadingImage);
content.setCellHorizontalAlignment(loadingImage, HorizontalPanel.ALIGN_CENTER);
content.setCellVerticalAlignment(loadingImage, HorizontalPanel.ALIGN_MIDDLE);
loadingLabel = new HTML();
loadingLabel.setStylePrimaryName("Label");
content.add(loadingLabel);
content.setCellHorizontalAlignment(loadingLabel, HorizontalPanel.ALIGN_CENTER);
content.setCellVerticalAlignment(loadingLabel, HorizontalPanel.ALIGN_MIDDLE);
Grid grid = new Grid(1, 1);
grid.setStylePrimaryName("DataGridMessagePopup");
grid.setWidget(0, 0, content);
grid.setCellSpacing(0);
grid.getCellFormatter().setStyleName(0, 0, "Content");
grid.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_MIDDLE);
grid.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
setWidget(grid);
}
public void setMessage(String message, boolean html) {
setMessage(message, html, false);
}
public void setMessage(String message, boolean html, boolean showProgress) {
if (html) {
loadingLabel.setHTML(message);
} else {
loadingLabel.setText(message);
}
loadingImage.setVisible(showProgress);
}
public void showCentered() {
setPopupPositionAndShow(new PopupPanel.PositionCallback() {
public void setPosition(int offsetWidth, int offsetHeight) {
int left = ((table.getOffsetWidth() - offsetWidth) / 2) + table.getAbsoluteLeft();
int top = ((table.getOffsetHeight() - offsetHeight) / 2) + table.getAbsoluteTop();
setPopupPosition(left, top);
}
});
}
}
private static class GroupTitle extends Composite {
private boolean collapsed = false;
private Listener listener;
private Image image;
private GroupTitle(FieldGroup group, Widget value, int groupSize) {
Label label = new Label(group.getTitle() + ":");
HorizontalPanel main = new HorizontalPanel();
main.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT);
main.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
image = WidgetImages.Instance.get().datagrid_GroupCollapse().createImage();
main.add(image);
addGap(main, "5px");
main.add(label);
addGap(main, "3px");
main.add(value);
if (group.isShowCounts()) {
addGap(main, "3px");
main.add(new Label("(" + String.valueOf(groupSize) + (groupSize > 1 ? " items)" : " item)")));
}
SimplePanel sp = new SimplePanel();
sp.setWidget(main);
sp.setWidth("100%");
initWidget(sp);
setStylePrimaryName("GroupTitle");
sinkEvents(Event.ONCLICK);
}
public void onBrowserEvent(Event event) {
if (collapsed) {
listener.onExpand();
WidgetImages.Instance.get().datagrid_GroupCollapse().applyTo(image);
collapsed = false;
} else {
listener.onCollapse();
WidgetImages.Instance.get().datagrid_GroupExpand().applyTo(image);
collapsed = true;
}
}
public void setListener(Listener listener) {
this.listener = listener;
}
public interface Listener {
void onCollapse();
void onExpand();
}
}
private static class RecordGroup {
private final FieldGroup fieldGroup;
private final Object value;
private List<Record> records = new ArrayList<Record>();
private RecordGroup(FieldGroup fieldGroup, Object value) {
this.fieldGroup = fieldGroup;
this.value = value;
}
public boolean shouldContain(Record record) {
return value.equals(record.getValue(fieldGroup.getFieldName()));
}
public void addRecord(Record record) {
records.add(record);
}
public FieldGroup getFieldGroup() {
return fieldGroup;
}
public Object getValue() {
return value;
}
public List<Record> getRecords() {
return records;
}
}
}