blob: 585bffbf4437cb0443607e9486223d05cab82e83 [file] [log] [blame]
/**
* Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florian Pirchner - Initial implementation
*/
package org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.internal;
import java.util.Locale;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.osbp.ecview.core.common.context.ContextException;
import org.eclipse.osbp.ecview.core.common.context.IViewContext;
import org.eclipse.osbp.ecview.core.common.editpart.IElementEditpart;
import org.eclipse.osbp.ecview.core.common.extender.IECViewCache;
import org.eclipse.osbp.ecview.core.common.model.core.YView;
import org.eclipse.osbp.ecview.core.extension.model.extension.ExtensionModelFactory;
import org.eclipse.osbp.ecview.core.extension.model.extension.ExtensionModelPackage;
import org.eclipse.osbp.ecview.core.extension.model.extension.YKanban;
import org.eclipse.osbp.ecview.core.extension.model.extension.YKanbanEvent;
import org.eclipse.osbp.ecview.core.extension.model.extension.YKanbanVisibilityProcessor;
import org.eclipse.osbp.ecview.core.ui.core.editparts.extension.IKanbanEditpart;
import org.eclipse.osbp.runtime.common.annotations.DtoUtils;
import org.eclipse.osbp.runtime.common.state.ISharedStateContext;
import org.eclipse.osbp.runtime.common.util.BeanUtils;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.VaadinRenderer;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.AbstractVaadinWidgetPresenter;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.FilteringComponentEmbeddable;
import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.internal.util.Util;
import org.eclipse.osbp.runtime.web.vaadin.common.data.BeanServiceLazyLoadingContainer;
import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanSearchServiceFactory;
import org.eclipse.osbp.vaadin.addons.kanban.KanbanBoard;
import org.eclipse.osbp.vaadin.addons.kanban.KanbanBoard.FilterChangedListener;
import org.eclipse.osbp.vaadin.addons.kanban.KanbanCard;
import com.vaadin.data.Container.Filter;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.VerticalLayout;
/**
* This presenter is responsible to render a list on the given layout.
*/
public class KanbanPresentation extends AbstractVaadinWidgetPresenter<Component> {
/** The model access. */
private final ModelAccess modelAccess;
/** The KanbanBoard */
private CustomKanbanBoard kanban;
@SuppressWarnings("rawtypes")
private FilteringComponentEmbeddable filteringComponent;
private CustomDropAdapter dropAdapter;
private CustomFilterProvider filterProvider;
private CustomCardAdapter cardAdapter;
private YView cardView;
private AdapterCustom modelAdapter;
/** The property. */
/**
* Constructor.
*
* @param editpart
* The editpart of that presenter
*/
public KanbanPresentation(IElementEditpart editpart) {
super((IKanbanEditpart) editpart);
this.modelAccess = new ModelAccess((YKanban) editpart.getModel());
}
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Component doCreateWidget(Object parent) {
if (kanban == null) {
findCardView();
kanban = new CustomKanbanBoard();
kanban.addStyleName(CSS_CLASS_CONTROL);
kanban.setImmediate(true);
kanban.setDoubleClickListener(this::cardDoubleClicked);
setupComponent(kanban, getCastedModel());
associateWidget(kanban, modelAccess.yField);
if (modelAccess.isCssIdValid()) {
kanban.setId(modelAccess.getCssID());
} else {
kanban.setId(getEditpart().getId());
}
if (modelAccess.yField.getType() != null) {
modelAdapter = new AdapterCustom();
modelAccess.yField.eAdapters().add(modelAdapter);
dropAdapter = new CustomDropAdapter();
filterProvider = new CustomFilterProvider();
cardAdapter = new CustomCardAdapter();
filteringComponent = new FilteringComponentEmbeddable(modelAccess.yField.getType(), 2);
filteringComponent.setHideGrid(true);
filteringComponent.init(getLocale());
filteringComponent.setFilterAcceptedCallback(e -> filterProvider.notifyChangedFilter());
kanban.initialize(getPermittedStates(), dropAdapter, cardAdapter, filterProvider);
IBeanSearchServiceFactory factory = getViewContext()
.getService(IBeanSearchServiceFactory.class.getName());
if (factory != null) {
ISharedStateContext sharedState = getViewContext().getService(ISharedStateContext.class.getName());
BeanServiceLazyLoadingContainer<?> datasource = new BeanServiceLazyLoadingContainer(
factory.createService(modelAccess.yField.getType()), modelAccess.yField.getType(),
sharedState);
kanban.setContainerDatasource(datasource);
}
}
// creates the binding for the field
createBindings(modelAccess.yField, kanban);
if (modelAccess.isCssClassValid()) {
kanban.addStyleName(modelAccess.getCssClass());
}
applyCaptions();
initialize(kanban, modelAccess.yField);
}
return kanban;
}
private void cardDoubleClicked(KanbanCard card) {
Object dto = card.getDto();
modelAccess.yField.setDoubleClicked(new YKanbanEvent(dto));
}
private void cardStateChanged(Enum<?> sourceState, Enum<?> targetState, Object dto) {
modelAccess.yField.setStateChanged(new YKanbanEvent(dto, sourceState, targetState));
}
private void findCardView() {
IECViewCache ecviewCache = getViewContext().getService(IECViewCache.class.getName());
cardView = ecviewCache.getView(modelAccess.yField.getCardECViewId());
}
protected Enum<?>[] getPermittedStates() {
Enum<?>[] result = BeanUtils.getKanbanStateEnumLiterals(modelAccess.yField.getType());
return result;
}
@Override
protected void doUpdateLocale(Locale locale) {
// no need to set the locale to the ui elements. Is handled by vaadin
// internally.
// update the captions
applyCaptions();
}
/**
* Applies the labels to the widgets.
*/
protected void applyCaptions() {
Util.applyCaptions(getI18nService(), modelAccess.getLabel(), modelAccess.getLabelI18nKey(), getLocale(),
kanban);
}
/**
* Creates the bindings for the given values.
*
* @param yField
* the y field
* @param field
* the field
*/
protected void createBindings(YKanban yField, KanbanBoard field) {
super.createBindings(yField, field, null);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation#
* getWidget()
*/
@Override
public Component getWidget() {
return kanban;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation#
* isRendered()
*/
@Override
public boolean isRendered() {
return kanban != null;
}
/**
* {@inheritDoc}
*/
@Override
public void doUnrender() {
if (kanban != null) {
modelAccess.yField.eAdapters().remove(modelAdapter);
modelAdapter = null;
// unbind all active bindings
unbind();
Component parent = ((Component) kanban.getParent());
if (parent != null && parent instanceof ComponentContainer) {
((ComponentContainer) parent).removeComponent(kanban);
}
// remove assocations
unassociateWidget(kanban);
kanban = null;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void internalDispose() {
try {
unrender();
} finally {
super.internalDispose();
}
}
/**
* A helper class.
*/
private static class ModelAccess {
/** The y field. */
private final YKanban yField;
/**
* Instantiates a new model access.
*
* @param yField
* the y field
*/
public ModelAccess(YKanban yField) {
super();
this.yField = yField;
}
/**
* Gets the css class.
*
* @return the css class
* @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssClass()
*/
public String getCssClass() {
return yField.getCssClass();
}
/**
* Returns true, if the css class is not null and not empty.
*
* @return true, if is css class valid
*/
public boolean isCssClassValid() {
return getCssClass() != null && !getCssClass().equals("");
}
/**
* Gets the css id.
*
* @return the css id
* @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssID()
*/
public String getCssID() {
return yField.getCssID();
}
/**
* Returns true, if the css id is not null and not empty.
*
* @return true, if is css id valid
*/
public boolean isCssIdValid() {
return getCssID() != null && !getCssID().equals("");
}
/**
* Returns the label.
*
* @return the label
*/
public String getLabel() {
return yField.getDatadescription() != null ? yField.getDatadescription().getLabel() : null;
}
/**
* Returns the label.
*
* @return the label i18n key
*/
public String getLabelI18nKey() {
return yField.getDatadescription() != null ? yField.getDatadescription().getLabelI18nKey() : null;
}
}
/**
* Converts the string value of the item icon property to
* {@link ThemeResource}.
*/
@SuppressWarnings("serial")
private class CustomKanbanBoard extends KanbanBoard {
/*
* (non-Javadoc)
*
* @see com.vaadin.ui.AbstractField#getErrorMessage()
*/
@Override
public ErrorMessage getErrorMessage() {
if (isDisposed()) {
// after disposal, Vaadin will call this method once.
return null;
}
ErrorMessage message = super.getErrorMessage();
return message;
}
}
private class CustomDropAdapter implements KanbanBoard.DropAdapter {
@Override
public boolean dropAllowed(Enum<?> sourceState, Enum<?> targetState, Object itemId) {
return true;
}
@Override
public boolean drop(Enum<?> sourceState, Enum<?> targetState, Object dto) {
cardStateChanged(sourceState, targetState, dto);
return true;
}
}
private class CustomFilterProvider implements KanbanBoard.FilterProvider {
private FilterChangedListener listener;
@Override
public Component getFilterComponent() {
return filteringComponent;
}
@Override
public void setFilterChangedListener(FilterChangedListener listener) {
this.listener = listener;
}
private void notifyChangedFilter() {
if (listener != null) {
listener.filterChanged();
}
}
@Override
public Filter getFilter() {
return filteringComponent.getFilter();
}
}
private class CustomCardAdapter implements KanbanBoard.KanbanCardAdapter {
@Override
public KanbanCard createCard(Object itemId) {
KanbanCard card = new CustomKanbanCard(DtoUtils.getIdValue(itemId).toString(),
BeanUtils.getKanbanState(itemId), itemId, cardView);
return card;
}
}
@SuppressWarnings("serial")
private class CustomKanbanCard extends KanbanCard {
private YView yView;
public CustomKanbanCard(String id, Enum<?> cardState, Object dto, YView yView) {
super(id, cardState, dto);
this.yView = yView;
initCard();
}
private void initCard() {
VerticalLayout content = new VerticalLayout();
content.addStyleName("o-kanban-card-content");
content.setSizeFull();
content.setMargin(false);
content.setSpacing(false);
content.setEnabled(false);
setContent(content);
try {
YView cardView = EcoreUtil.copy(yView);
// add a vp for autobinded cards
if (cardView.getTags().contains("autobinded")) {
YKanbanVisibilityProcessor vp = ExtensionModelFactory.eINSTANCE.createYKanbanVisibilityProcessor();
cardView.getVisibilityProcessors().add(vp);
}
IViewContext context = new VaadinRenderer().render(content, cardView, null);
context.setBean(IViewContext.MAIN_BEAN_SLOT, dto);
} catch (ContextException e) {
e.printStackTrace();
}
}
}
private class AdapterCustom extends AdapterImpl {
@Override
public void notifyChanged(Notification msg) {
if (msg.getFeature() == ExtensionModelPackage.Literals.YKANBAN__TO_REFRESH) {
YKanbanEvent event = (YKanbanEvent) msg.getNewValue();
if (event != null) {
kanban.refresh(event.dto);
}
}
}
}
}