package org.yaac.client.ui;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Lists.transform;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import org.yaac.client.service.CRUDServiceAsync;
import org.yaac.client.ui.EditorPropertyManager.PropertyEditCallback;
import org.yaac.client.util.AutoBeanUtil;
import org.yaac.client.util.ExceptionManager;
import org.yaac.client.widget.BlockingAsyncCallback;
import org.yaac.shared.file.CacheUploadResult;
import org.yaac.shared.file.CacheUploadResult.Status;
import org.yaac.shared.file.FileDownloadPath;
import org.yaac.shared.property.PropertyInfo;
import org.yaac.shared.property.PropertyInfo.FilePlaceHolder;
import com.google.common.base.Function;
import com.google.gwt.cell.client.ActionCell;
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.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
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.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
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.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.TextArea;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
/**
* @author Max Zhu (thebbsky@gmail.com)
*
*/
public class EditorPropertyPanel extends Composite {
private static EditorPropertyPanelUiBinder uiBinder = GWT.create(EditorPropertyPanelUiBinder.class);
interface EditorPropertyPanelUiBinder extends UiBinder<Widget, EditorPropertyPanel> {
}
static interface CloseBtnHandler {
void onCloseBtnClick();
}
@UiField
TextArea expTxt;
// =======================file upload related========================
@UiField(provided=true)
CellTable<FileDownloadPath> uploadTable;
private ListDataProvider<FileDownloadPath> dataProvider;
@UiField
FormPanel form;
@UiField
FileUpload upload;
// ========================control panel =========================
@UiField
Button saveBtn;
@UiField
Button closeBtn;
private CloseBtnHandler closeHandler;
private String currKeyString;
/**
* current edit callback
*/
private PropertyEditCallback callback;
private final CRUDServiceAsync service;
private final ExceptionManager exceptionMgr;
@Inject
EditorPropertyPanel(CRUDServiceAsync service, ExceptionManager exceptionMgr) {
this.service = service;
this.exceptionMgr = exceptionMgr;
// init upload table
uploadTable = new CellTable<FileDownloadPath>();
uploadTable.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
uploadTable.addColumn(new Column<FileDownloadPath, String>(new TextCell()) {
@Override
public String getValue(FileDownloadPath object) {
// 0 --> 1
// ...
// n --> n+1
return String.valueOf(dataProvider.getList().indexOf(object) + 1);
}
}, "Param Name");
uploadTable.addColumn(new Column<FileDownloadPath, String>(new TextCell()) {
@Override
public String getValue(FileDownloadPath object) {
return object.getFileName();
}
}, "File Name");
uploadTable.addColumn(new Column<FileDownloadPath, String>(new TextCell()) {
@Override
public String getValue(FileDownloadPath object) {
return object.getSize().toString();
}
}, "Size");
// download
uploadTable.addColumn(new Column<FileDownloadPath, SafeHtml>(new SafeHtmlCell()) {
@Override
public SafeHtml getValue(FileDownloadPath file) {
String pathStr = AutoBeanUtil.encode(FileDownloadPath.class, file);
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant("<a href='/download?path=" + pathStr + "' target='blank'>Click to download</a>");
return sb.toSafeHtml();
}
});
// delete
{
ActionCell.Delegate<FileDownloadPath> delegate = new ActionCell.Delegate<FileDownloadPath>() {
@Override
public void execute(FileDownloadPath object) {
dataProvider.getList().remove(object);
dataProvider.refresh();
}
};
uploadTable.addColumn(new Column<FileDownloadPath, FileDownloadPath>(
new ActionCell<FileDownloadPath>("Delete", delegate)) {
@Override
public FileDownloadPath getValue(FileDownloadPath object) {
return object;
}
});
}
// data provider
dataProvider = new ListDataProvider<FileDownloadPath>();
dataProvider.addDataDisplay(uploadTable);
initWidget(uiBinder.createAndBindUi(this));
}
public void setCloseHandler(CloseBtnHandler closeHandler) {
this.closeHandler = closeHandler;
}
/**
* @param event
*/
@UiHandler("form")
void onFormSubmit(SubmitEvent event) {
if (validateFileUpload()) {
BlockingAsyncCallback.block("Uploading");
} else {
event.cancel();
}
}
private boolean validateFileUpload() {
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
CacheUploadResult result = AutoBeanUtil.decode(CacheUploadResult.class, event.getResults());
if (result.getStatus() == Status.SUCCESS) {
this.dataProvider.getList().add(result.getPath());
this.dataProvider.refresh();
this.form.reset();
} else { // upload failed
Window.alert("Can't upload file"); // TODO : i18n
}
}
}
@UiHandler("saveBtn")
void onSaveBtnClick(ClickEvent event) {
String expression = expTxt.getText();
List<String> filePaths = transform(this.dataProvider.getList(), new Function<FileDownloadPath, String>(){
@Override
public String apply(FileDownloadPath input) {
return AutoBeanUtil.encode(FileDownloadPath.class, input);
}
});
service.parsePropertyExp(currKeyString, expression, new ArrayList<String>(filePaths),
new BlockingAsyncCallback<PropertyInfo>() {
@Override
public void onBlockingCallSuccess(PropertyInfo result) {
callback.onEditSuccess(result);
quitEdit();
}
@Override
public void onBlockingCallFailure(Throwable caught) {
exceptionMgr.handle(caught);
}
});
}
@UiHandler("closeBtn")
void onCloseBtnClick(ClickEvent event) {
quitEdit();
}
private void quitEdit() {
this.closeHandler.onCloseBtnClick();
}
/**
* apply default editor and start edit
*
* @param info
*/
public void edit(String keyString, PropertyInfo info, final PropertyEditCallback callback) {
this.callback = callback;
this.currKeyString = keyString;
// init status
this.expTxt.setText(info.asExpression(new FilePlaceHolder()));
List<String> paths = info.downloadPaths();
List<FileDownloadPath> fileItems = transform(paths, new Function<String, FileDownloadPath>(){
@Override
public FileDownloadPath apply(String input) {
return AutoBeanUtil.decode(FileDownloadPath.class, input);
}
});
this.dataProvider.getList().clear();
this.dataProvider.getList().addAll(fileItems);
this.dataProvider.refresh();
}
}