package org.activityinfo.ui.client.component.table;
import com.google.common.collect.Lists;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.*;
import org.activityinfo.core.client.ResourceLocator;
import org.activityinfo.core.shared.criteria.Criteria;
import org.activityinfo.model.form.FormClass;
import org.activityinfo.i18n.shared.I18N;
import org.activityinfo.ui.client.widget.AlertPanel;
import org.activityinfo.ui.client.widget.Templates;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Displays the this classes' FormInstances in a table format
*/
public class InstanceTableView implements IsWidget, RequiresResize {
private static final int DEFAULT_MAX_COLUMN_COUNT = 5;
private static final Logger LOGGER = Logger.getLogger(InstanceTableView.class.getName());
private final ResourceLocator resourceLocator;
private final HTMLPanel panel;
private List<FieldColumn> columns;
private List<FieldColumn> selectedColumns;
private Collection<FormClass> rootFormClasses;
@UiField
DivElement emRuler;
@UiField
AlertPanel columnAlert;
@UiField(provided = true)
InstanceTable table;
@UiField
AlertPanel errorMessages;
@UiField
Button loadMoreButton;
@UiField
HTML loadFailureMessageContainer;
interface InstanceTableViewUiBinder extends UiBinder<HTMLPanel, InstanceTableView> {
}
private static InstanceTableViewUiBinder ourUiBinder = GWT.create(InstanceTableViewUiBinder.class);
public InstanceTableView(ResourceLocator resourceLocator) {
InstanceTableStyle.INSTANCE.ensureInjected();
this.resourceLocator = resourceLocator;
this.table = new InstanceTable(this);
this.panel = ourUiBinder.createAndBindUi(this);
addLoadMoreButtonHandler();
}
private void addLoadMoreButtonHandler() {
table.getTable().getEventBus().addHandler(InstanceTableDataLoader.DataLoadEvent.TYPE, new InstanceTableDataLoader.DataLoadHandler() {
@Override
public void onLoad(final InstanceTableDataLoader.DataLoadEvent event) {
if (event.isFailed()) {
// Show failure message only after a short fixed delay to ensure that
// the progress stage is displayed. Otherwise if we have a synchronous error, clicking
// the retry button will look like it's not working.
Scheduler.get().scheduleFixedDelay(new Scheduler.RepeatingCommand() {
@Override
public boolean execute() {
handleLoadMoreButton(event);
return false;
}
}, 500);
} else {
handleLoadMoreButton(event);
}
}
});
}
private void handleLoadMoreButton(final InstanceTableDataLoader.DataLoadEvent event) {
loadFailureMessageContainer.setVisible(event.isFailed());
loadMoreButton.setText(event.isFailed() ? I18N.CONSTANTS.retryLoading() : I18N.CONSTANTS.loadMore());
final int totalCount = event.getTotalCount();
final int loadedDataCount = event.getLoadedDataCount();
loadMoreButton.setEnabled(loadedDataCount < totalCount);
}
public void setCriteria(Criteria criteria) {
table.setCriteria(criteria);
}
public void setColumns(final List<FieldColumn> columns) {
this.columns = columns;
Scheduler.get().scheduleDeferred(new Command() {
@Override
public void execute() {
calculateSelectedColumns();
}
});
}
public void setSelectedColumns(final List<FieldColumn> selectedColumns) {
this.selectedColumns = selectedColumns;
table.setColumns(selectedColumns);
final int allColumns = columns.size();
final int visibleColumns = selectedColumns.size();
if (visibleColumns < allColumns) {
columnAlert.showMessages(I18N.MESSAGES.notAllColumnsAreShown(visibleColumns, allColumns, I18N.CONSTANTS.chooseColumns()));
} else {
columnAlert.setVisible(false);
}
}
private void calculateSelectedColumns() {
if (columns.size() <= getMaxNumberOfColumns()) {
setSelectedColumns(Lists.newArrayList(columns));
} else {
setSelectedColumns(Lists.newArrayList(columns.subList(0, getMaxNumberOfColumns())));
}
}
public int getMaxNumberOfColumns() {
double emSizeInPixels = ((double) emRuler.getOffsetWidth()) / 100d;
LOGGER.log(Level.FINE, "emSizeInPixels = " + emSizeInPixels);
double columnWidthInPixels = InstanceTable.COLUMN_WIDTH * emSizeInPixels;
int columnLimit = (int) Math.floor(panel.getElement().getClientWidth() / columnWidthInPixels);
LOGGER.log(Level.FINE, "columnLimit = " + columnLimit);
if (columnLimit <= 0) { // fallback : yuriyz: check calculations above
columnLimit = DEFAULT_MAX_COLUMN_COUNT;
}
return columnLimit;
}
public InstanceTable getTable() {
return table;
}
@Override
public Widget asWidget() {
return panel;
}
@Override
public void onResize() {
}
@UiHandler("loadMoreButton")
public void onLoadMore(ClickEvent event) {
loadMoreButton.setHTML(Templates.OK_BTN_TEMPLATE.html(I18N.CONSTANTS.loading()));
loadMoreButton.setEnabled(false);
loadFailureMessageContainer.setVisible(false);
table.loadMore();
}
public String getFormClassLabel() {
if (rootFormClasses != null && !rootFormClasses.isEmpty()) {
final FormClass formClass = rootFormClasses.iterator().next();
return formClass.getLabel();
}
return "";
}
public List<FieldColumn> getColumns() {
if (columns == null) {
columns = Lists.newArrayList();
}
return columns;
}
public List<FieldColumn> getSelectedColumns() {
if (selectedColumns == null) {
selectedColumns = Lists.newArrayList();
}
return selectedColumns;
}
public ResourceLocator getResourceLocator() {
return resourceLocator;
}
public void setRootFormClasses(Collection<FormClass> rootFormClasses) {
this.rootFormClasses = rootFormClasses;
if (rootFormClasses != null && !rootFormClasses.isEmpty()) {
table.setRootFormClass(rootFormClasses.iterator().next());
}
}
}