Package pl.net.bluesoft.rnd.processtool.ui.basewidgets.editor

Source Code of pl.net.bluesoft.rnd.processtool.ui.basewidgets.editor.ProcessDataHierarchyEditor$TreeSortDropHandler

package pl.net.bluesoft.rnd.processtool.ui.basewidgets.editor;

import com.vaadin.data.Item;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.event.*;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptAll;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
import com.vaadin.ui.*;
import org.apache.commons.beanutils.PropertyUtils;
import org.vaadin.dialogs.ConfirmDialog;
import pl.net.bluesoft.rnd.processtool.ui.basewidgets.xml.WidgetDefinitionLoader;
import pl.net.bluesoft.rnd.processtool.ui.basewidgets.xml.XmlConstants;
import pl.net.bluesoft.rnd.processtool.ui.basewidgets.xml.jaxb.*;
import pl.net.bluesoft.rnd.processtool.ui.basewidgets.xml.validation.XmlValidationError;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import static pl.net.bluesoft.rnd.processtool.ui.basewidgets.editor.EditorHelper.*;

/**
* @author tlipski@bluesoft.net.pl
*/
public class ProcessDataHierarchyEditor extends VerticalLayout {
    public static final Logger LOGGER = Logger.getLogger(ProcessDataWidgetsDefinitionEditor.class.getName());

    private WidgetDefinitionLoader definitionLoader = WidgetDefinitionLoader.getInstance();
    private HierarchicalContainer hierarchicalContainer;
    private WidgetsDefinitionElement rootWidget;
    private Tree widgetTree = new Tree();
    private ProcessDataWidgetsDefinitionEditor editor;

    public ProcessDataHierarchyEditor(ProcessDataWidgetsDefinitionEditor editor) {
        this.editor = editor;
        initGUI();
    }

    private void initGUI() {
        setSizeUndefined();
        setWidth("100%");
        hierarchicalContainer = new HierarchicalContainer();
        hierarchicalContainer.addContainerProperty("name", String.class, null);
        hierarchicalContainer.addContainerProperty("widget", Object.class, null);

        HorizontalLayout treeAndForm = new HorizontalLayout();
        final VerticalLayout formLayout = getFormLayout();
        treeAndForm.addComponent(getInitedWidgetTreePanel());
        treeAndForm.addComponent(formLayout);
        treeAndForm.setExpandRatio(formLayout, 1.0f);
        treeAndForm.setWidth("100%");
        treeAndForm.setSpacing(true);

        addComponent(getAvailableWidgetsComponent());
        addComponent(new Label(getLocalizedMessage("info")));
        addComponent(treeAndForm);
        setExpandRatio(treeAndForm, 1.0f);
    }

    private VerticalLayout getFormLayout() {
        final VerticalLayout formLayout = new VerticalLayout();
        formLayout.setWidth("100%");
        final WidgetPropertiesEditorFormComponent[] prevFormHandler = new WidgetPropertiesEditorFormComponent[1];
        widgetTree.addListener(new ItemClickEvent.ItemClickListener() {
            @Override
            public void itemClick(ItemClickEvent event) {
                final Object itemId = event.getItemId();
                final WidgetPropertiesEditorFormComponent formComponent = prevFormHandler[0];
                if (formComponent != null && formComponent.getForm().isModified()) {
                    if (formComponent.getForm().isValid()) {
                        formComponent.commit();
                        renderForm(itemId);
                    } else {
                        ConfirmDialog.show(
                                getApplication().getMainWindow(),
                                getLocalizedMessage("unsaved-data-warning"),
                                new ConfirmDialog.Listener() {
                                    @Override
                                    public void onClose(ConfirmDialog confirmDialog) {
                                        if (confirmDialog.isConfirmed()) {
                                            renderForm(itemId);
                                        } else {
                                            widgetTree.select(formComponent.getItemId());
                                        }
                                    }
                                });
                    }
                } else {
                    renderForm(itemId);
                }
            }
            private void renderForm(Object itemId) {
                prevFormHandler[0] = null;
                formLayout.removeAllComponents();
                if (itemId != null) {
                    WidgetPropertiesEditorFormComponent editorFormComponent = new WidgetPropertiesEditorFormComponent(itemId, ProcessDataHierarchyEditor.this);
                    formLayout.addComponent(editorFormComponent);
                    prevFormHandler[0] = editorFormComponent;
                }
            }
        });
        return formLayout;
    }

    private Panel getInitedWidgetTreePanel() {
        widgetTree.setContainerDataSource(hierarchicalContainer);
        widgetTree.setDragMode(Tree.TreeDragMode.NODE);
        widgetTree.setItemCaptionPropertyId("name");
        widgetTree.setDropHandler(new TreeSortDropHandler(widgetTree, hierarchicalContainer));
        widgetTree.setWidth("100%");
        widgetTree.addShortcutListener(getDeleteShortcutListener());

        Panel panel = new Panel(getLocalizedMessage("widget-hierarchy"));
        panel.setHeight("340px");
        panel.setWidth("250px");
        panel.addComponent(widgetTree);
        return panel;
    }

    private ShortcutListener getDeleteShortcutListener() {
        return new ShortcutListener("Delete", null, ShortcutAction.KeyCode.DELETE) {
            @Override
            public void handleAction(Object sender, Object target) {
                if (target instanceof Tree) {
                    Tree target1 = (Tree) target;
                    final Object itemId = target1.getValue();
                    if (itemId != null) {
                        ConfirmDialog.show(
                                getApplication().getMainWindow(),
                                getLocalizedMessage("remove-item-confirm"),
                                new ConfirmDialog.Listener() {
                                    @Override
                                    public void onClose(ConfirmDialog confirmDialog) {
                                        if (confirmDialog.isConfirmed()) {
                                            removeItemFromTreeRecursively(itemId);
                                        }
                                        refreshRawXmlAndPreview();
                                    }
                                });
                    }
                }
            }
        };
    }

    private void removeItemFromTreeRecursively(Object itemId) {
        hierarchicalContainer.removeItemRecursively(itemId);
    }

    private void updateXml(Object itemId) {
        //fix relations between widgets
        Collection<?> children = hierarchicalContainer.getChildren(itemId);
        if (itemId instanceof HasWidgetsElement) {
            HasWidgetsElement hasWidgetsElement = (HasWidgetsElement) itemId;
            ArrayList<WidgetElement> widgets = new ArrayList<WidgetElement>();
            if (children != null) for (Object subItemId : children) {
                updateXml(subItemId);
                if (subItemId instanceof WidgetElement)
                    widgets.add((WidgetElement) subItemId);
            }
            hasWidgetsElement.setWidgets(widgets);
        } else if (itemId instanceof AbstractSelectWidgetElement) { //special case, but it should be supported in more generic manner
            AbstractSelectWidgetElement selectWidgetElement = (AbstractSelectWidgetElement) itemId;
            ArrayList<ItemElement> values = new ArrayList<ItemElement>();
            if (children != null) for (Object subItemId : children) {
                if (subItemId instanceof ItemElement) {
                    values.add((ItemElement) subItemId);
                }
            }
            selectWidgetElement.setValues(values);
        }
    }

  public void refreshRawXmlAndPreview() {
        updateXml(rootWidget);
        List<XmlValidationError> xmlValidationErrors = rootWidget.validate();
       
    Collection<?> all = hierarchicalContainer.getItemIds();
        Set<String> ids=new HashSet<String>();
        boolean duplicated=false;
        for (Object obj : all) {
          if (obj instanceof WidgetElement){
            WidgetElement we = (WidgetElement) obj;
            if (!ids.add(we.getId()) && we.getId()!=null){
                duplicated=true;
              }
          }
         
        }
        if (duplicated)xmlValidationErrors.add(new XmlValidationError("select", "id", XmlConstants.XML_TAG_DUPLICATED));
       
        if (xmlValidationErrors != null && !xmlValidationErrors.isEmpty()) {
            String msg = joinValidationErrors(xmlValidationErrors);
            Window.Notification n = new Window.Notification(getLocalizedMessage("validation-errors"),
                    msg, Window.Notification.TYPE_TRAY_NOTIFICATION);
            n.setDelayMsec(4000);
            getApplication().getMainWindow().showNotification(n);
        } else {
            editor.updateFromWidgetsDefinitionElement(rootWidget);
            Window.Notification n = new Window.Notification(getLocalizedMessage("update-success"),
                    getLocalizedMessage("xml-definition-generate-success"), Window.Notification.TYPE_TRAY_NOTIFICATION);
            n.setDelayMsec(2000);
            getApplication().getMainWindow().showNotification(n);
        }
    }

    public WidgetsDefinitionElement processXml(String value) {
        hierarchicalContainer.removeAllItems();

    if (value != null) {
      try {
        rootWidget = (WidgetsDefinitionElement) definitionLoader.unmarshall(String.valueOf(value));
      } catch (Exception e) {
        LOGGER.log(Level.SEVERE, e.getMessage(), e);
        rootWidget = new WidgetsDefinitionElement();
      }
    }
    else {
      rootWidget = new WidgetsDefinitionElement();
    }

        Item item = hierarchicalContainer.addItem(rootWidget);
        item.getItemProperty("name").setValue(rootWidget.getClass().getSimpleName());
        item.getItemProperty("widget").setValue(rootWidget);

        hierarchicalContainer.setChildrenAllowed(rootWidget, true);
        processWidgetsTree(rootWidget);
        widgetTree.expandItemsRecursively(rootWidget);
        editor.refreshPreview(rootWidget);
        return rootWidget;
    }


    private Component getAvailableWidgetsComponent() {
        CssLayout cssLayout = new CssLayout() {
            @Override
            protected String getCss(Component c) {
                if (c instanceof WidgetDragAndDropWrapper) {
                    WidgetDragAndDropWrapper widgetDragAndDropWrapper = (WidgetDragAndDropWrapper) c;
                    Class cls = widgetDragAndDropWrapper.getCls();
                    String basicCss = "float: left; margin: 3px; padding: 3px;  display: inline; font-weight: bold; border: 2px solid ";
                    if (getFieldAnnotation(cls, XmlElements.class) != null)
                        return basicCss + "#287ece;";
                    else if (WidgetElement.class.isAssignableFrom(cls))
                        return basicCss + "#60b30e;";
                    else
                        return basicCss + "#c6c6c6";
                }
                return super.getCss(c);
            }
        };
        cssLayout.setWidth("100%");
        Class[] supportedClasses = definitionLoader.getSupportedClasses();
        for (Class cls : supportedClasses) {
            if (getAnnotation(cls, XmlRootElement.class) != null) continue; //ignore root elements
            if (Modifier.isAbstract(cls.getModifiers())) continue;
            Label lbl = new Label(cls.getSimpleName());
            lbl.setSizeUndefined();
            DragAndDropWrapper c = new WidgetDragAndDropWrapper(lbl, cls);
            c.setData(cls);
            c.setSizeUndefined();
            cssLayout.addComponent(c);
            c.setDragStartMode(DragAndDropWrapper.DragStartMode.WRAPPER);
        }

        DragAndDropWrapper wr = new DragAndDropWrapper(cssLayout);
        wr.setDropHandler(new DropHandler() {
            @Override
            public void drop(DragAndDropEvent event) {
                Transferable t = event.getTransferable();
                Component src = t.getSourceComponent();
                if (src != widgetTree || !(t instanceof DataBoundTransferable)) {
                    return;
                }
                Object sourceItemId = ((DataBoundTransferable) t).getItemId();
                removeItemFromTreeRecursively(sourceItemId);
                refreshRawXmlAndPreview();
            }

            @Override
            public AcceptCriterion getAcceptCriterion() {
                return AcceptAll.get();
            }
        });
        return wr;

    }


    private void processWidgetsTree(Object el) {
        java.lang.reflect.Field field = getFieldWithAnnotation(el.getClass(), XmlElements.class);
        Collection coll = null;
        if (field != null) {
            try {
                Object property = PropertyUtils.getProperty(el, field.getName());
                if (property instanceof Collection) {
                    coll = (Collection) property;
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        if (coll != null) for (Object widget : coll) {
            addTreeItem(widget);
            hierarchicalContainer.setParent(widget, el);
            if (getFieldAnnotation(widget.getClass(), XmlElements.class) != null) {
                processWidgetsTree(widget);
            }
        }
    }

    private Item addTreeItem(Object widgetElement) {
        Class cls = widgetElement.getClass();
        Item subItem;
        subItem = hierarchicalContainer.addItem(widgetElement);
        subItem.getItemProperty("name").setValue(widgetElement.getClass().getSimpleName());
        subItem.getItemProperty("widget").setValue(widgetElement);
        if (getFieldAnnotation(cls, XmlElements.class) != null) {
            hierarchicalContainer.setChildrenAllowed(widgetElement, true);
            widgetTree.expandItem(widgetElement);
        } else {
            hierarchicalContainer.setChildrenAllowed(widgetElement, false);
        }
        return subItem;
    }


    private class TreeSortDropHandler implements DropHandler {
        private final Tree tree;

        public TreeSortDropHandler(Tree tree, HierarchicalContainer container) {
            this.tree = tree;
        }

        public AcceptCriterion getAcceptCriterion() {
            return AcceptAll.get();
        }

        public void drop(DragAndDropEvent dropEvent) {
            Transferable t = dropEvent.getTransferable();
            Component src = t.getSourceComponent();
            Object sourceItemId;
            Object newItemId = null;
//            Item subItem = null;
            HierarchicalContainer container = (HierarchicalContainer) tree.getContainerDataSource();
            if (src instanceof WidgetDragAndDropWrapper) {
                WidgetDragAndDropWrapper dragAndDropWrapper = (WidgetDragAndDropWrapper) src;
                Class cls = dragAndDropWrapper.getCls();
                Object widgetElement = null;
                try {
                    widgetElement = cls.newInstance();
                    /*subItem = */addTreeItem(widgetElement);
                    newItemId = widgetElement;
                    sourceItemId = widgetElement;
                } catch (Throwable e) {
                    LOGGER.log(Level.SEVERE, e.getMessage(), e);
                    src.getApplication().getMainWindow().showNotification(getLocalizedMessage("widget-creation-failed"),
                            e.getClass().getName() + ", " + e.getMessage(),
                            Window.Notification.TYPE_ERROR_MESSAGE);
//                    if (subItem != null && widgetElement != null) {
//                        container.removeItem(widgetElement);
//                    }
                    return;
                }
            } else {
                if (src != tree || !(t instanceof DataBoundTransferable)) {
                    return;
                }
                sourceItemId = ((DataBoundTransferable) t).getItemId();
            }


            Tree.TreeTargetDetails dropData = ((Tree.TreeTargetDetails) dropEvent
                    .getTargetDetails());
            Object targetItemId = dropData.getItemIdOver();
            VerticalDropLocation location = dropData.getDropLocation();
            if (targetItemId instanceof WidgetsDefinitionElement) {  //the can be only one! ... root element2
                location = VerticalDropLocation.MIDDLE;
            }
            if (!moveNode(sourceItemId, targetItemId, location)) {
                if (newItemId != null) {
                    container.removeItem(newItemId);
                }
            } else {
                refreshRawXmlAndPreview();
            }
        }


        private boolean moveNode(Object sourceItemId, Object targetItemId,
                                 VerticalDropLocation location) {
            HierarchicalContainer container = (HierarchicalContainer) tree.getContainerDataSource();
            if (sourceItemId == null || targetItemId == null) return false;
            Class srcClass = sourceItemId.getClass();
            Class targetClass = targetItemId.getClass();
            if (location == VerticalDropLocation.MIDDLE) {
                if (!checkIfParentChildRelationIsPossible(srcClass, targetClass)) return false;
                if (container.setParent(sourceItemId, targetItemId)
                        && container.hasChildren(targetItemId)) {
                    container.moveAfterSibling(sourceItemId, null);
                }
            } else if (location == VerticalDropLocation.TOP) {
                Object parentId = container.getParent(targetItemId);
                if (!checkIfParentChildRelationIsPossible(srcClass, parentId.getClass())) return false;
                if (container.setParent(sourceItemId, parentId)) {
                    container.moveAfterSibling(sourceItemId, targetItemId);
                    container.moveAfterSibling(targetItemId, sourceItemId);
                }
            } else if (location == VerticalDropLocation.BOTTOM) {
                Object parentId = container.getParent(targetItemId);
                if (!checkIfParentChildRelationIsPossible(srcClass, parentId.getClass())) return false;
                if (container.setParent(sourceItemId, parentId)) {
                    container.moveAfterSibling(sourceItemId, targetItemId);
                }
            }
            return true;
        }


        private boolean checkIfParentChildRelationIsPossible(Class srcClass, Class targetClass) {
            XmlElements targetClassAnnotation = (XmlElements) getFieldAnnotation(targetClass, XmlElements.class);
            if (targetClassAnnotation == null) {
                return false;
            }
            for (XmlElement xe : targetClassAnnotation.value()) {
                if (srcClass.isAssignableFrom(xe.type())) {
                    return true;
                }
            }
            return false;
        }
    }

    private static class WidgetDragAndDropWrapper extends DragAndDropWrapper {

        private Class cls;

        private WidgetDragAndDropWrapper(Component root, Class cls) {
            super(root);
            this.cls = cls;
        }

        public Class getCls() {
            return cls;
        }
    }

}
TOP

Related Classes of pl.net.bluesoft.rnd.processtool.ui.basewidgets.editor.ProcessDataHierarchyEditor$TreeSortDropHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.