/*
* Copyright 2016 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.lienzo.toolbox;
import java.util.Iterator;
import java.util.List;
import com.ait.lienzo.client.core.Attribute;
import com.ait.lienzo.client.core.animation.AnimationCallback;
import com.ait.lienzo.client.core.animation.AnimationProperties;
import com.ait.lienzo.client.core.animation.AnimationProperty;
import com.ait.lienzo.client.core.animation.AnimationTweener;
import com.ait.lienzo.client.core.animation.IAnimation;
import com.ait.lienzo.client.core.animation.IAnimationHandle;
import com.ait.lienzo.client.core.event.AnimationFrameAttributesChangedBatcher;
import com.ait.lienzo.client.core.event.AttributesChangedEvent;
import com.ait.lienzo.client.core.event.AttributesChangedHandler;
import com.ait.lienzo.client.core.event.IAttributesChangedBatcher;
import com.ait.lienzo.client.core.shape.Group;
import com.ait.lienzo.client.core.shape.Layer;
import com.ait.lienzo.client.core.shape.Node;
import com.ait.lienzo.client.core.shape.Shape;
import com.ait.lienzo.client.core.shape.wires.WiresShape;
import com.ait.lienzo.client.core.shape.wires.WiresUtils;
import com.ait.lienzo.client.core.types.Point2D;
import com.ait.lienzo.shared.core.types.Direction;
import com.ait.tooling.common.api.flow.Flows;
import com.ait.tooling.nativetools.client.event.HandlerRegistrationManager;
import org.kie.workbench.common.stunner.lienzo.grid.Grid;
import org.kie.workbench.common.stunner.lienzo.toolbox.grid.GridToolbox;
import static com.ait.lienzo.client.core.AttributeOp.any;
public abstract class AbstractToolbox implements GridToolbox {
private static final double ANIMATION_DURATION = 200;
private static final Flows.BooleanOp XYWH_OP = any(Attribute.X,
Attribute.Y,
Attribute.WIDTH,
Attribute.HEIGHT);
protected final Layer layer;
protected final WiresShape shape;
protected final Direction anchor;
protected final Direction towards;
protected final List<ToolboxButton> buttons;
protected final HandlerRegistrationManager handlerRegistrationManager = new HandlerRegistrationManager();
protected IAttributesChangedBatcher attributesChangedBatcher = new AnimationFrameAttributesChangedBatcher();
protected final Grid grid;
protected Group group;
protected void initialize() {
if (grid.size() < buttons.size()) {
throw new IllegalStateException("added more buttons than the grid can contain");
}
this.group = new Group().setDraggable(false);
Iterator<Grid.Point> gridIterator = grid.iterator();
for (ToolboxButton button : buttons) {
Grid.Point point = gridIterator.next();
button.getShape().setX(point.getX()).setY(point.getY());
button.getShape().getGroup().setAlpha(0);
registerButton(button);
group.add(button.getShape().getGroup());
}
getLayer().add(group);
reposition();
initHandlers();
batch();
}
protected void registerButton(final ToolboxButton button) {
}
protected void initHandlers() {
shape.getGroup().setAttributesChangedBatcher(attributesChangedBatcher);
final AttributesChangedHandler handler = new AttributesChangedHandler() {
@Override
public void onAttributesChanged(final AttributesChangedEvent event) {
if (event.evaluate(XYWH_OP)) {
reposition();
}
}
};
// Attribute change handlers.
handlerRegistrationManager.register(
shape.getGroup().addAttributesChangedHandler(Attribute.X,
handler)
);
handlerRegistrationManager.register(
shape.getGroup().addAttributesChangedHandler(Attribute.Y,
handler)
);
handlerRegistrationManager.register(
shape.getPath().addAttributesChangedHandler(Attribute.WIDTH,
handler)
);
handlerRegistrationManager.register(
shape.getPath().addAttributesChangedHandler(Attribute.HEIGHT,
handler)
);
// Shape resize handlers.
handlerRegistrationManager.register(
shape.addWiresResizeStartHandler(event -> reposition(true))
);
handlerRegistrationManager.register(
shape.addWiresResizeStepHandler(event -> reposition(true))
);
handlerRegistrationManager.register(
shape.addWiresResizeEndHandler(event -> reposition(true))
);
}
private void reposition() {
reposition(false);
}
private void reposition(final boolean batch) {
final double gx = WiresUtils.getLocation(shape.getGroup()).getX();
final double gy = WiresUtils.getLocation(shape.getGroup()).getY();
final Point2D anchorPoint = Positioning.anchorFor(this.shape.getPath().getBoundingPoints().getBoundingBox(),
this.anchor);
final Grid.Point toolboxPosition = this.grid.findPosition(new Grid.Point((int) anchorPoint.getX(),
(int) anchorPoint.getY()),
this.towards);
group.setX(gx + toolboxPosition.getX());
group.setY(gy + toolboxPosition.getY());
if (batch) {
batch();
}
}
@Override
public void show() {
reposition(true);
for (ToolboxButton button : buttons) {
button.getShape().getGroup().animate(AnimationTweener.LINEAR,
AnimationProperties.toPropertyList(AnimationProperty.Properties.ALPHA(1)),
ANIMATION_DURATION,
new AnimationCallback());
}
}
@Override
public void remove() {
attributesChangedBatcher.cancelAttributesChangedBatcher();
handlerRegistrationManager.removeHandler();
for (ToolboxButton button : buttons) {
button.remove();
}
group.removeFromParent();
}
@Override
public void hide() {
for (final ToolboxButton button : buttons) {
button.getShape().getGroup().animate(
AnimationTweener.LINEAR,
AnimationProperties.toPropertyList(AnimationProperty.Properties.ALPHA(0)),
ANIMATION_DURATION,
new AnimationCallback() {
@Override
public void onClose(final IAnimation animation,
final IAnimationHandle handle) {
}
});
}
}
Layer getLayer() {
return layer;
}
protected AbstractToolbox(final Layer layer,
final WiresShape shape,
final Shape<?> attachTo,
final Direction anchor,
final Direction towards,
final int rows,
final int cols,
final int padding,
final int iconSize,
final List<ToolboxButton> buttons) {
this.layer = layer;
this.shape = shape;
this.anchor = anchor;
this.towards = towards;
this.buttons = buttons;
this.grid = new Grid(padding,
iconSize,
rows,
cols);
initialize();
registerHandlers(attachTo);
}
private void registerHandlers(final Shape<?> attachTo) {
Node<?> node = attachTo != null ? attachTo : shape.getPath();
registerHandlers(node);
}
protected void registerHandlers(final Node<?> node) {
}
private void batch() {
this.getLayer().batch();
}
}