package com.constellio.app.ui.framework.components.fields.upload; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.vaadin.dialogs.ConfirmDialog; import org.vaadin.easyuploads.FileBuffer; import com.constellio.app.ui.framework.buttons.DeleteButton; import com.constellio.app.ui.framework.containers.ButtonsContainer; import com.constellio.app.ui.framework.containers.ButtonsContainer.ContainerButton; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.util.IndexedContainer; import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.converter.Converter.ConversionException; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; import com.vaadin.navigator.ViewChangeListener; import com.vaadin.ui.Button; import com.vaadin.ui.Component; import com.vaadin.ui.CustomField; import com.vaadin.ui.DragAndDropWrapper; import com.vaadin.ui.Label; import com.vaadin.ui.Table; import com.vaadin.ui.Table.ColumnHeaderMode; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; @SuppressWarnings("serial") public class BaseUploadField extends CustomField<Object> implements DropHandler { public static final String STYLE_NAME = "base-upload-field"; private static final String CAPTION_PROPERTY_ID = "caption"; private boolean multiValue; private VerticalLayout mainLayout; private BaseMultiFileUpload multiFileUpload; private ButtonsContainer<IndexedContainer> fileUploadsContainer; private Table fileUploadsTable; private Map<Object, Component> itemCaptions = new HashMap<>(); private ViewChangeListener viewChangeListener; public BaseUploadField() { super(); setSizeFull(); mainLayout = new VerticalLayout(); mainLayout.setSizeFull(); mainLayout.setSpacing(true); multiFileUpload = new BaseMultiFileUpload() { @SuppressWarnings("unchecked") @Override protected void handleFile(File file, String fileName, String mimeType, long length) { file.deleteOnExit(); TempFileUpload newTempFileUpload = new TempFileUpload(fileName, mimeType, length, file); Object newConvertedValue; Converter<Object, Object> converter = BaseUploadField.this.getConverter(); if (converter != null) { newConvertedValue = converter.convertToModel(newTempFileUpload, Object.class, getLocale()); } else { newConvertedValue = newTempFileUpload; } if (!isMultiValue()) { if (!newConvertedValue.equals(getConvertedValue())) { deleteTempFiles(); BaseUploadField.this.setValue(newConvertedValue); } } else { List<Object> previousListValue = (List<Object>) BaseUploadField.this.getValue(); List<Object> newListValue = new ArrayList<Object>(); if (previousListValue != null) { newListValue.addAll(previousListValue); } if (!newListValue.contains(newConvertedValue)) { newListValue.add(newConvertedValue); } BaseUploadField.this.setValue(newListValue); } } @Override protected FileBuffer createReceiver() { FileBuffer receiver = super.createReceiver(); /* * Make receiver not to deleteLogically files after they have been * handled by #handleFile(). */ receiver.setDeleteFiles(false); return receiver; } }; multiFileUpload.setWidth("100%"); addValueChangeListener(new ValueChangeListener() { @SuppressWarnings("unchecked") @Override public void valueChange(Property.ValueChangeEvent event) { List<Object> listValue; Object newValue = BaseUploadField.this.getValue(); if (newValue instanceof List) { listValue = (List<Object>) newValue; } else { listValue = new ArrayList<Object>(); if (newValue != null) { listValue.add(newValue); } } itemCaptions.clear(); fileUploadsContainer.removeAllItems(); for (Object listValueElement : listValue) { Object itemId = listValueElement; fileUploadsContainer.addItem(itemId); Item listValueElementItem = fileUploadsContainer.getItem(itemId); Component itemCaption = newItemCaption(itemId); listValueElementItem.getItemProperty(CAPTION_PROPERTY_ID).setValue(itemCaption); itemCaptions.put(itemId, itemCaption); } } }); fileUploadsContainer = new ButtonsContainer<>(new IndexedContainer()); fileUploadsContainer.addContainerProperty(CAPTION_PROPERTY_ID, Component.class, null); fileUploadsContainer.addButton(new ContainerButton() { @Override protected Button newButtonInstance(final Object itemId, ButtonsContainer<?> container) { DeleteButton deleteButton = new DeleteButton() { @SuppressWarnings("unchecked") @Override protected void confirmButtonClick(ConfirmDialog dialog) { if (itemId instanceof TempFileUpload) { TempFileUpload tempFileUpload = (TempFileUpload) itemId; tempFileUpload.delete(); } else { deleteTempFile(itemId); } if (!isMultiValue()) { BaseUploadField.this.setValue(null); } else { List<Object> previousListValue = (List<Object>) BaseUploadField.this.getValue(); List<Object> newListValue = new ArrayList<Object>(previousListValue); newListValue.remove(itemId); BaseUploadField.this.setValue(newListValue); } } }; deleteButton.setReadOnly(BaseUploadField.this.isReadOnly()); deleteButton.setEnabled(BaseUploadField.this.isEnabled()); deleteButton.setVisible(isDeleteLink(itemId)); return deleteButton; } }); fileUploadsTable = new Table(); fileUploadsTable.setContainerDataSource(fileUploadsContainer); fileUploadsTable.setPageLength(0); fileUploadsTable.setWidth("100%"); fileUploadsTable.setColumnHeaderMode(ColumnHeaderMode.HIDDEN); fileUploadsTable.setColumnWidth(ButtonsContainer.DEFAULT_BUTTONS_PROPERTY_ID, 47); mainLayout.addComponents(multiFileUpload, fileUploadsTable); } @Override public void attach() { super.attach(); if (viewChangeListener == null) { viewChangeListener = new ViewChangeListener() { @Override public boolean beforeViewChange(ViewChangeEvent event) { return true; } @Override public void afterViewChange(ViewChangeEvent event) { deleteTempFiles(); UI.getCurrent().getNavigator().removeViewChangeListener(viewChangeListener); } }; UI.getCurrent().getNavigator().addViewChangeListener(viewChangeListener); } } protected VerticalLayout getMainLayout() { return mainLayout; } protected Object getItemId(TempFileUpload tempFileUpload) { return tempFileUpload; } protected Component getItemCaption(Object itemId) { return itemCaptions.get(itemId); } protected Map<Object, Component> getItemCaptions() { return Collections.unmodifiableMap(itemCaptions); } protected Component newItemCaption(Object itemId) { String itemCaption; if (itemId instanceof TempFileUpload) { TempFileUpload tempFileUpload = (TempFileUpload) itemId; itemCaption = tempFileUpload.getFileName(); } else { itemCaption = itemId.toString(); } return new Label(itemCaption); } @Override public void setInternalValue(Object newValue) { super.setInternalValue(newValue); } protected void deleteTempFile(Object itemId) { } protected boolean isDeleteLink(Object itemId) { return true; } @Override public void drop(DragAndDropEvent event) { multiFileUpload.drop(event); } @Override public AcceptCriterion getAcceptCriterion() { return multiFileUpload.getAcceptCriterion(); } @Override protected Component initContent() { DragAndDropWrapper dragAndDropWrapper = new DragAndDropWrapper(mainLayout); dragAndDropWrapper.setDropHandler(this); return dragAndDropWrapper; } @SuppressWarnings("unchecked") protected final void deleteTempFiles() { Object currentValue = getInternalValue(); if (currentValue instanceof TempFileUpload) { TempFileUpload tempFileUpload = (TempFileUpload) currentValue; tempFileUpload.delete(); } else if (currentValue instanceof List) { List<Object> currentListValue = (List<Object>) currentValue; for (Object currentListElement : currentListValue) { if (currentListElement instanceof TempFileUpload) { TempFileUpload tempFileUpload = (TempFileUpload) currentListElement; tempFileUpload.delete(); } else { deleteTempFile(currentListElement); } } } else if (currentValue != null) { deleteTempFile(currentValue); } } @Override public void discard() throws SourceException { super.discard(); deleteTempFiles(); } public final boolean isMultiValue() { return multiValue; } public final void setMultiValue(boolean multiValue) { this.multiValue = multiValue; } public String getUploadButtonCaption() { return multiFileUpload.getUploadButtonCaption(); } public void setUploadButtonCaption(String uploadButtonCaption) { multiFileUpload.setUploadButtonCaption(uploadButtonCaption); } public final String getDropZoneCaption() { return multiFileUpload.getDropZoneCaption(); } public final void setDropZoneCaption(String dropZoneCaption) { multiFileUpload.setDropZoneCaption(dropZoneCaption); } @Override public Class<? extends Object> getType() { Class<?> type; if (isMultiValue()) { type = List.class; } else { type = Object.class; } return type; } @Override public void setValue(Object newFieldValue) throws com.vaadin.data.Property.ReadOnlyException, ConversionException { super.setValue(newFieldValue); } }