/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.workbench.common.stunner.cm.client.wires;
import java.util.Optional;
import com.ait.lienzo.client.core.shape.wires.WiresContainer;
import com.ait.lienzo.client.core.shape.wires.WiresLayer;
import com.ait.lienzo.client.core.shape.wires.WiresManager;
import com.ait.lienzo.client.core.shape.wires.WiresShape;
import com.ait.lienzo.client.core.shape.wires.WiresUtils;
import com.ait.lienzo.client.core.shape.wires.handlers.impl.WiresDockingAndContainmentControlImpl;
import com.ait.lienzo.client.core.shape.wires.picker.ColorMapBackedPicker;
import com.ait.lienzo.client.core.types.Point2D;
import com.ait.lienzo.client.widget.DragContext;
import com.ait.tooling.nativetools.client.collection.NFastArrayList;
public class CaseManagementDockingAndContainmentControlImpl extends WiresDockingAndContainmentControlImpl {
private final CaseManagementContainmentStateHolder state;
public CaseManagementDockingAndContainmentControlImpl(final WiresShape shape,
final WiresManager wiresManager,
final CaseManagementContainmentStateHolder state) {
super(shape,
wiresManager);
this.state = state;
}
@Override
public void dragStart(final DragContext context) {
super.dragStart(context);
state.setGhost(Optional.empty());
state.setOriginalIndex(Optional.empty());
state.setOriginalParent(Optional.empty());
if (!(m_shape instanceof AbstractCaseManagementShape)) {
return;
}
state.setOriginalParent(Optional.ofNullable(m_parent));
state.setOriginalIndex(Optional.ofNullable(getShapeIndex()));
state.setGhost(Optional.ofNullable(((AbstractCaseManagementShape) m_shape).getGhost()));
if ((m_parent instanceof AbstractCaseManagementShape)) {
((AbstractCaseManagementShape) m_parent).logicallyReplace(m_shape,
state.getGhost().get());
}
}
private Integer getShapeIndex() {
if (m_parent == null || m_shape == null) {
return null;
}
return m_parent.getChildShapes().toList().indexOf(m_shape);
}
@Override
public boolean dragAdjust(final Point2D dxy) {
super.dragAdjust(dxy);
final double mouseX = m_mouseStartX + dxy.getX();
final double mouseY = m_mouseStartY + dxy.getY();
//Handle moving ghost from one container to another
if (state.getGhost().isPresent() && m_parent != null) {
if (m_parent.getContainmentAcceptor().containmentAllowed(m_parent,
m_shape)) {
final Point2D parentAbsLoc = WiresUtils.getLocation(m_parent.getGroup());
final Point2D mouseRelativeLoc = new Point2D(mouseX - parentAbsLoc.getX(),
mouseY - parentAbsLoc.getY());
//Children contains m_ghost and others excluding m_shape. This therefore moves m_ghost within children.
m_parent.getLayoutHandler().add(state.getGhost().get(),
m_parent,
mouseRelativeLoc);
m_layer.getLayer().batch();
m_picker = makeColorMapBackedPicker(m_layer,
m_parent,
m_shape);
}
}
return true;
}
@Override
protected ColorMapBackedPicker makeColorMapBackedPicker(final WiresLayer layer,
final WiresContainer parent,
final WiresShape shape) {
final NFastArrayList<WiresShape> shapesToSkip = new NFastArrayList<>();
state.getGhost().ifPresent(shapesToSkip::add);
shapesToSkip.add(shape);
return new CaseManagementColorMapBackedPicker(layer.getChildShapes(),
layer.getLayer().getScratchPad(),
shapesToSkip,
shape.getDockingAcceptor().dockingAllowed(parent,
shape),
shape.getDockingAcceptor().getHotspotSize());
}
@Override
protected boolean addShapeToParent() {
if (!(state.getOriginalParent().isPresent() || state.getOriginalIndex().isPresent())) {
return true;
}
if (!state.getGhost().isPresent()) {
return true;
}
//Children contains m_ghost and others excluding m_shape. This replaces m_ghost with m_shape.
final AbstractCaseManagementShape ghost = state.getGhost().get();
final WiresContainer originalParent = state.getOriginalParent().get();
final int originalIndex = state.getOriginalIndex().get();
final DragEndMode mode = getDragEndMode();
switch (mode) {
case VETO:
restore(ghost,
originalParent,
originalIndex);
break;
default:
reparentDraggedShape(ghost,
originalParent);
}
ghost.getChildShapes().toList().forEach(WiresShape::destroy);
ghost.destroy();
state.setGhost(Optional.empty());
state.setOriginalIndex(Optional.empty());
state.setOriginalParent(Optional.empty());
m_layer.getLayer().batch();
m_picker = null;
return true;
}
private DragEndMode getDragEndMode() {
if (m_parent == null) {
return DragEndMode.VETO;
} else if (!m_parent.getContainmentAcceptor().containmentAllowed(m_parent,
m_shape)) {
return DragEndMode.VETO;
} else if (state.getGhost().isPresent()) {
return DragEndMode.REMOVE_GHOST;
}
return DragEndMode.ADD;
}
private void restore(final AbstractCaseManagementShape ghost,
final WiresContainer originalParent,
final int originalIndex) {
if (originalParent instanceof AbstractCaseManagementShape) {
restore(ghost,
(AbstractCaseManagementShape) originalParent,
originalIndex);
} else {
restoreGhostParent(ghost);
}
}
private void restore(final AbstractCaseManagementShape ghost,
final AbstractCaseManagementShape parent,
final int index) {
ghost.removeFromParent();
parent.addShape(m_shape,
index);
}
private void reparentDraggedShape(final AbstractCaseManagementShape ghost,
final WiresContainer originalParent) {
if (originalParent instanceof AbstractCaseManagementShape) {
if (originalParent.getChildShapes().contains(ghost)) {
((AbstractCaseManagementShape) originalParent).logicallyReplace(ghost,
m_shape);
} else {
restoreGhostParent(ghost);
}
} else {
restoreGhostParent(ghost);
}
super.addShapeToParent();
}
private void restoreGhostParent(final AbstractCaseManagementShape ghost) {
if (ghost.getParent() != null) {
final WiresContainer ghostContainer = ghost.getParent();
final int ghostIndex = ghostContainer.getChildShapes().toList().indexOf(ghost);
if (ghostContainer instanceof AbstractCaseManagementShape) {
restore(ghost,
(AbstractCaseManagementShape) ghostContainer,
ghostIndex);
}
}
}
private enum DragEndMode {
VETO,
REMOVE_GHOST,
ADD
}
}