package org.yaac.client.ui;
import static com.google.common.base.Strings.isNullOrEmpty;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import javax.inject.Inject;
import org.yaac.client.activity.BlobActivity;
import org.yaac.client.util.AutoBeanUtil;
import org.yaac.client.widget.BlockingAsyncCallback;
import org.yaac.client.widget.SortHandler;
import org.yaac.client.widget.SortableColumn;
import org.yaac.shared.blob.BlobInfoDTO;
import org.yaac.shared.file.BlobUploadResult;
import org.yaac.shared.file.BlobUploadResult.Status;
import org.yaac.shared.file.FileDownloadPath;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.EditTextCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.SafeHtmlCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
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.uibinder.client.UiTemplate;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.SelectionModel;
/**
* @author Max Zhu (thebbsky@gmail.com)
*
*/
// TODO : add delete all / send all to me feature
public class BlobViewImpl extends Composite implements BlobView {
private static BlobViewUiBinder uiBinder = GWT.create(BlobViewUiBinder.class);
@UiTemplate("BlobView.ui.xml")
interface BlobViewUiBinder extends UiBinder<Widget, BlobViewImpl> {
}
// ============blob filter and data============
@UiField
TextBox filterTxt;
// internal status for filters text
private boolean filterTxtWaitingForFirstClick;
@UiField(provided=true)
DataGrid<BlobInfoDTO> blobInfoTable;
private SelectionModel<BlobInfoDTO> selectionModel;
private ListDataProvider<BlobInfoDTO> dataProvider;
private SortHandler<BlobInfoDTO> sortHandler;
// =============blob upload============
@UiField
FormPanel form;
@UiField
CheckBox selectAllCb;
@UiField
Button deleteBtn;
@UiField
TextBox nameTxt;
// internal status for filters text
private boolean nameTxtWaitingForFirstClick;
@UiField
FileUpload upload;
private BlobActivity listenr;
@Inject
BlobViewImpl() {
// init blobInfoTable
initBlobInfoTable();
initWidget(uiBinder.createAndBindUi(this));
this.filterTxtWaitingForFirstClick = true;
this.nameTxtWaitingForFirstClick = true;
}
private void initBlobInfoTable() {
// step 1
sortHandler = new SortHandler<BlobInfoDTO>();
blobInfoTable = new DataGrid<BlobInfoDTO>();
blobInfoTable.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
blobInfoTable.addColumnSortHandler(sortHandler);
blobInfoTable.setVisibleRange(0, Integer.MAX_VALUE);
selectionModel = new MultiSelectionModel<BlobInfoDTO>(BlobInfoDTO.KEY_PROVIDER);
blobInfoTable.setSelectionModel(selectionModel, DefaultSelectionEventManager.<BlobInfoDTO>createCheckboxManager());
// step 2 : add columns
// checkbox for multi selection, unsortable
{
Column<BlobInfoDTO, Boolean> checkColumn = new Column<BlobInfoDTO, Boolean>(
new CheckboxCell(true, false)) {
@Override
public Boolean getValue(BlobInfoDTO object) {
return selectionModel.isSelected(object);
}
};
//empty nothing
blobInfoTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
}
// filename
{
SortableColumn<BlobInfoDTO, SafeHtml> column =
new SortableColumn<BlobInfoDTO, SafeHtml>(new SafeHtmlCell()) {
@Override
public SafeHtml getValue(BlobInfoDTO o) {
FileDownloadPath path = AutoBeanUtil.blobDownloadPath(o.getBlobKeyStr());
String pathStr = AutoBeanUtil.encode(FileDownloadPath.class, path);
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant("<a href='/download?path=" + SafeHtmlUtils.htmlEscape(pathStr) + "' target='blank'>");
sb.appendHtmlConstant(o.getFilename());
sb.appendHtmlConstant("</a>");
return sb.toSafeHtml();
}
};
sortHandler.setComparator(column, new Comparator<BlobInfoDTO>() {
@Override
public int compare(BlobInfoDTO o1, BlobInfoDTO o2) {
return o1.getFilename().compareTo(o2.getFilename());
}
});
blobInfoTable.addColumn(column, "File Name");
}
// contentType
{
SortableColumn<BlobInfoDTO, String> column =
new SortableColumn<BlobInfoDTO, String>(new TextCell()) {
@Override
public String getValue(BlobInfoDTO o) {
return o.getContentType();
}
};
sortHandler.setComparator(column, new Comparator<BlobInfoDTO>() {
@Override
public int compare(BlobInfoDTO o1, BlobInfoDTO o2) {
return o1.getContentType().compareTo(o2.getContentType());
}
});
blobInfoTable.addColumn(column, "Content Type");
}
// size
{
SortableColumn<BlobInfoDTO, String> column =
new SortableColumn<BlobInfoDTO, String>(new TextCell()) {
@Override
public String getValue(BlobInfoDTO o) {
return o.getSize().toString();
}
};
sortHandler.setComparator(column, new Comparator<BlobInfoDTO>() {
@Override
public int compare(BlobInfoDTO o1, BlobInfoDTO o2) {
return o1.getSize().compareTo(o2.getSize());
}
});
blobInfoTable.addColumn(column, "Size");
}
// creation date
{
SortableColumn<BlobInfoDTO, String> column =
new SortableColumn<BlobInfoDTO, String>(new TextCell()) {
@Override
public String getValue(BlobInfoDTO o) {
return o.getCreation().toString();
}
};
sortHandler.setComparator(column, new Comparator<BlobInfoDTO>() {
@Override
public int compare(BlobInfoDTO o1, BlobInfoDTO o2) {
return o1.getCreation().compareTo(o2.getCreation());
}
});
blobInfoTable.addColumn(column, "Creation Date");
}
// blob key hash
{
SortableColumn<BlobInfoDTO, String> column =
new SortableColumn<BlobInfoDTO, String>(new EditTextCell()) {
@Override
public String getValue(BlobInfoDTO o) {
return o.getBlobKeyStr();
}
};
column.setFieldUpdater(new FieldUpdater<BlobInfoDTO, String>() {
@Override
public void update(int index, BlobInfoDTO object, String value) {
// do nothing, simply provide a way for users to copy value
}
});
blobInfoTable.addColumn(column, SafeHtmlUtils.fromSafeConstant("Key String<br/>(click to select)"));
blobInfoTable.setColumnWidth(column, "100pt");
}
// md5 hash
{
SortableColumn<BlobInfoDTO, String> column =
new SortableColumn<BlobInfoDTO, String>(new EditTextCell()) {
@Override
public String getValue(BlobInfoDTO o) {
return o.getMd5Hash();
}
};
column.setFieldUpdater(new FieldUpdater<BlobInfoDTO, String>() {
@Override
public void update(int index, BlobInfoDTO object, String value) {
// do nothing, simply provide a way for users to copy value
}
});
blobInfoTable.addColumn(column, SafeHtmlUtils.fromSafeConstant("MD5 Hash<br/>(click to select)"));
blobInfoTable.setColumnWidth(column, "100pt");
}
}
@Override
public void setPresenter(BlobActivity listener) {
this.listenr = listener;
}
@UiHandler("filterTxt")
void onFilterTxtClick(ClickEvent event) {
if (filterTxtWaitingForFirstClick) {
filterTxt.setText("");
filterTxtWaitingForFirstClick = false;
}
}
private String filterTxtContent() {
if (filterTxtWaitingForFirstClick) {
return "";
} else {
return filterTxt.getText();
}
}
@UiHandler("filterTxt")
void onFilterTxtKeyPress(KeyPressEvent event) {
char key = event.getCharCode();
if (KeyCodes.KEY_ENTER == key) {
this.listenr.refreshBlobInfo();
}
}
@Override
public void updateBlobInfoList(List<BlobInfoDTO> result) {
if (dataProvider == null) {
dataProvider = new ListDataProvider<BlobInfoDTO>(new LinkedList<BlobInfoDTO>());
dataProvider.addDataDisplay(blobInfoTable);
sortHandler.setDataProvider(dataProvider);
}
dataProvider.getList().clear();
dataProvider.getList().addAll(result);
}
@UiHandler("selectAllCb")
void onSelectAllCbChange(ValueChangeEvent<Boolean> event) {
for (BlobInfoDTO blob : blobInfoTable.getVisibleItems()) {
selectionModel.setSelected(blob, event.getValue());
}
}
@UiHandler("deleteBtn")
void onDeleteBtnClick(ClickEvent event) {
Collection<BlobInfoDTO> selectedBlobs =
Collections2.filter(dataProvider.getList(), new Predicate<BlobInfoDTO>() {
@Override
public boolean apply(BlobInfoDTO input) {
return selectionModel.isSelected(input);
}
});
if (selectedBlobs.isEmpty()) {
Window.alert("No record selected");
return;
}
if (Window.confirm("Are you sure you want to delete " + selectedBlobs.size() + " file(s)")) {
listenr.delete(selectedBlobs);
}
}
@UiHandler("nameTxt")
void onNameTxtClick(ClickEvent event) {
if (nameTxtWaitingForFirstClick) {
nameTxt.setText("");
nameTxtWaitingForFirstClick = false;
}
}
private String nameTxtContent() {
if (nameTxtWaitingForFirstClick) {
return "";
} else {
return nameTxt.getText();
}
}
/**
* @param event
*/
@UiHandler("form")
void onFormSubmit(SubmitEvent event) {
if (validate()) {
BlockingAsyncCallback.block("Uploading");
} else {
event.cancel();
}
}
private boolean validate() {
if (isNullOrEmpty(nameTxtContent().trim())) {
Window.alert("You must specify the filename"); // TODO : i18n
return false;
}
if (isNullOrEmpty(upload.getFilename().trim())) {
Window.alert("You must select a file to upload"); // TODO : i18n
return false;
}
return true;
}
@UiHandler("form")
void onFormSubmitComplete(SubmitCompleteEvent event) {
BlockingAsyncCallback.unblock();
// if event.getResults returns null, then the form is not even submitted
if (!isNullOrEmpty(event.getResults())) { // print out result
BlobUploadResult result = AutoBeanUtil.decode(BlobUploadResult.class, event.getResults());
if (result.getStatus() == Status.SUCCESS) {
// TODO : i18n
Window.alert("File " + result.getFileName() + " (size = " + result.getSize() + ") is successfully uploaded");
form.reset();
listenr.refreshBlobInfo();
} else { // upload failed
Window.alert("Can't upload file"); // TODO : i18n
}
}
}
@Override
public String filterStr() {
return filterTxtContent();
}
}