Tree drag/drop handling: UI freezes with custom AcceptCriterion

Hi all,

I’m working on drag/drop handling for a tree. I’ve created my own AcceptCriterion which extends ClientSideCriterion. Using this criterion, which checks the class of the dragged item, dragging an item results in the UI crashing after releasing it.

I also noticed that ClientSideCriterion has an empty method paintContent which is nevertheless called in another method:

@Override
public void paint(PaintTarget target) throws PaintException {
    target.startTag("-ac");
    target.addAttribute("name", getIdentifier());
    paintContent(target);
    target.endTag("-ac");
}

protected void paintContent(PaintTarget target) throws PaintException {
}

All seems odd to me. I’m still trying to figure out what goes wrong, but does anyone have a guess what may be the problem and why the method above is empty?

Does anyone have experience writing a custom AcceptCriterion? Is this even possible?

Finally solved this. I had to implement my own ServerSideCriterion instead of a ClientSideCriterion. Kind of logical since the client side wouldn’t know of the criteria I wanted to use.

I’m just looking at DnD, so I’m not an expert but adding my findings here so I can refer to them in the future!

When extending ClientSideCriterion you also need to compile your own widgetset and provide appropriate client side elements.

e.g. :Server side:

public class CustomAcceptCriterion extends ClientSideCriterion implements AcceptCriterion {

    @Override
    public void paintContent(PaintTarget target) throws PaintException {
        super.paintContent(target);
        target.addAttribute("SomeKey", "SomeValue");
    }

    @Override
    public boolean accept(DragAndDropEvent dragEvent) {
        ...
    }
}

And ClientSide:

@AcceptCriterion(CustomAcceptCriterion.class)
public class ClientCustomAcceptCriterion extends VAcceptCriterion {

    @Override
    protected boolean accept(VDragEvent drag, UIDL configuration) {
        ...
    }
}

Note that the @AcceptCriterion() annotation on the Client impl takes the class of the server impl - allowing Vaadin to tie the two together. The paintTarget in the server impl is optional, but allows the server component to pass attributes to the client, and the client impl can then check to e.g. see if the target-candidate should accept the drop - useful if e.g. dropping into a table (or component that contains multiple children) where your Criterion wishes to accept to drops into some children, but not accept drops into others. This “painting” happens when the component is rendered to the client, NOT during Drags.

If you want to perform some evaluation server side during a drag, then it is correct to use ServerSideCriterion, as you concluded!

Dave