| /** |
| * 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); |
| } |
| } |
| } |
| } |
| } |