Goal

Add drag and drop functionality to Tree table.

Implementation

Class diagram:

 

 

TreeViewImpl (info.magnolia.ui.workbench.tree.TreeViewImpl)
If the workbenchDefinition has a DropConstrainer implemented class defined, activate drag&drop ability on the Tree using the TreeViewDropHandler implementation.

TreeViewDropHandler (info.magnolia.ui.workbench.tree.drop.TreeViewDropHandler)
Implements com.vaadin.event.dd.DropHandler, and use DropConstrained in order to define if the move or drop are allowed.

Issues

Currently, it's not possible to lock a dragged element (do not drag a property row).
Client side implementation should be performed in order to detect drag event on such an element and lock him.

Not yet Implemented/ToDo

Evolution:

Use the DropConstraint in the WorkBench Tree (based on the allowedAsChild(), define if the creation of a sub child is accepted)

Move Action based on a Workbench Action

From the workbench menu, click move --> Activate drag and drop.

User Guide (Implement your own drop constraint)

Assume that we want to add drag&drop functionality to the Contact-app.

Requirements:
  • A contact can not be added as child of another contact
  • A folder can not be added as child of a contact.
  • A folder may be added as child of another folder
  • A contact may be added as child of a folder
Implementation

Implement a new class extending the DropConstraint interface.

/**
 * Contact App specific implementation of {@link DropConstraint}.
 */
public class ContactDropConstraint implements DropConstraint {
    private static final Logger log = LoggerFactory.getLogger(ContactDropConstraint.class);
    @Override
    public boolean allowedAsChild(Item sourceItem, Item targetItem) {
        try {
            String sourceNodeType = ((JcrNodeAdapter) sourceItem).getNode().getPrimaryNodeType().getName();
            String targetNodeType = ((JcrNodeAdapter) targetItem).getNode().getPrimaryNodeType().getName();
            // if both are Contact, return false.
            if (ContactNodeType.Contact.NAME.equals(sourceNodeType) && ContactNodeType.Contact.NAME.equals(targetNodeType)) {
                log.debug("Could not move a Contact under a Contact");
                return false;
            }
            // if source is Folder and target Contact, return false
            if (NodeTypes.Folder.NAME.equals(sourceNodeType) && ContactNodeType.Contact.NAME.equals(targetNodeType)) {
                log.debug("Could not move a Folder under a Contact");
                return false;
            }
        } catch (RepositoryException e) {
            log.warn("Could not check if child is allowed. ", e);
        }
        return true;
    }
    @Override
    public boolean allowedBefore(Item sourceItem, Item targetItem) {
        return true;
    }
    @Override
    public boolean allowedAfter(Item sourceItem, Item targetItem) {
        return true;
    }
    @Override
    public boolean allowedToMove(Item sourceItem) {
        return true;
    }
}

As we only want to put restriction in Child Item drag and drop, only allowedAsChild has some business logic defined.

Configuration

The DropConstraint is used to restrict where you can drop tree items. For example, to prevent the user from dropping a folder as a child node for a contact node.

Using configuration by code, add the DropConstraint definition to the confiduration. In contat-app case, update the ContactModule class:

ContactsModule
                                .workbench(
                                        cfg.workbenches
                                        .workbench()
                                        .workspace("contacts")
                                                .path("/")
                                                .dropConstraintClass(ContactDropConstraint.class)

 

And this is all, now the Contact TreeView will have customized Drag and Drop capability.

 

1 Comment

  1. This topic does not need to be included in end-user documentation.