/*
* 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.client.lienzo.components.palette.view;
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.shape.Arrow;
import com.ait.lienzo.client.core.shape.Group;
import com.ait.lienzo.client.core.shape.IPrimitive;
import com.ait.lienzo.client.core.shape.Layer;
import com.ait.lienzo.client.core.shape.Rectangle;
import com.ait.lienzo.client.core.types.Point2D;
import com.ait.lienzo.shared.core.types.ArrowType;
import com.ait.lienzo.shared.core.types.ColorName;
import org.kie.workbench.common.stunner.client.lienzo.components.palette.AbstractLienzoPalette;
import org.kie.workbench.common.stunner.client.lienzo.components.palette.view.element.LienzoGlyphPaletteItemView;
import org.kie.workbench.common.stunner.client.lienzo.components.palette.view.element.LienzoPaletteElementView;
import org.kie.workbench.common.stunner.core.client.components.palette.view.AbstractPaletteView;
import org.kie.workbench.common.stunner.core.client.components.palette.view.PaletteGrid;
import org.kie.workbench.common.stunner.core.client.shape.view.event.HandlerRegistrationImpl;
import org.kie.workbench.common.stunner.lienzo.palette.AbstractPalette;
import org.kie.workbench.common.stunner.lienzo.palette.HoverPalette;
public abstract class AbstractLienzoPaletteView<V extends LienzoPaletteView>
extends AbstractPaletteView<V, Layer, LienzoPaletteElementView>
implements LienzoPaletteView<V, LienzoPaletteElementView> {
protected double animationDuration = 500;
protected AbstractLienzoPalette presenter;
protected AbstractPalette<? extends AbstractPalette> palette;
protected IPrimitive<?> colExpButton;
protected final HandlerRegistrationImpl handlerRegistrationManager = new HandlerRegistrationImpl();
protected abstract AbstractPalette<? extends AbstractPalette> buildPalette();
protected AbstractPalette<? extends AbstractPalette> getPalette() {
if (null == palette) {
this.palette = buildPalette();
initPaletteCallbacks();
}
return palette;
}
public void setPresenter(final AbstractLienzoPalette presenter) {
this.presenter = presenter;
}
@Override
protected void doClear() {
if (getPalette().isVisible() && getPalette().getAlpha() > 0) {
getPalette().setAlpha(0);
draw();
}
}
protected boolean isExpandable() {
return presenter.isExpandable();
}
@Override
@SuppressWarnings("unchecked")
public V attach(final Layer layer) {
if (null == colExpButton && isExpandable()) {
colExpButton = createExpandCollapseButton();
layer.add(colExpButton);
}
layer.add(getPalette());
return (V) this;
}
public Layer getLayer() {
return getPalette().getLayer();
}
public void draw() {
getPalette().redraw();
}
@SuppressWarnings("unchecked")
public V show() {
if (null == getPalette().getParent()) {
throw new IllegalStateException("Palette must be attached to a layer before calling #show.");
}
if (!items.isEmpty()) {
final AbstractPalette.Item[] primitives = new AbstractPalette.Item[items.size()];
int _x = 0;
for (final LienzoPaletteElementView paletteItemView : items) {
final AbstractPalette.Item i = buildLienzoPaletteItem(paletteItemView);
primitives[_x] = i;
_x++;
}
double paletteStartY = 0;
if (null != colExpButton && isExpandable()) {
colExpButton.setX(x + getGrid().getPadding());
colExpButton.setY(y);
paletteStartY = colExpButton.getBoundingBox().getHeight() + getGrid().getPadding();
}
getPalette().setX(x);
getPalette().setY(paletteStartY + y);
getPalette().setRows(getGrid().getRows());
getPalette().setColumns(getGrid().getColumns());
getPalette().setIconSize(getGrid().getIconSize());
getPalette().setPadding(getGrid().getPadding());
getPalette().build(primitives);
getPalette().setAlpha(0);
getPalette().animate(AnimationTweener.LINEAR,
AnimationProperties.toPropertyList(AnimationProperty.Properties.ALPHA(1)),
animationDuration);
draw();
} else {
clear();
}
return (V) this;
}
@Override
public V hide() {
getPalette().clearItems();
getLayer().batch();
return (V) this;
}
protected AbstractPalette.Item buildLienzoPaletteItem(final LienzoPaletteElementView paletteItemView) {
AbstractPalette.ItemDecorator decorator = null;
if (paletteItemView instanceof LienzoGlyphPaletteItemView) {
final LienzoGlyphPaletteItemView.Decorator d = ((LienzoGlyphPaletteItemView) paletteItemView).getDecorator();
if (null != d) {
decorator = AbstractPalette.ItemDecorator.DEFAULT;
}
}
return new AbstractPalette.Item(paletteItemView.getView(),
decorator);
}
@Override
public double getWidth() {
return presenter.computePaletteSize()[0];
}
@Override
public double getHeight() {
return presenter.computePaletteSize()[1];
}
@Override
public V clear() {
removeExpandCollapseButton();
return super.clear();
}
@Override
public void destroy() {
removeExpandCollapseButton();
if (null != palette) {
palette.setItemCallback(null);
palette.clear();
palette.removeFromParent();
palette = null;
}
}
protected IPrimitive<?> createExpandCollapseButton() {
final boolean isExpanded = presenter.isExpanded();
final double w = getGrid().getIconSize();
final double h = getGrid().getIconSize() / 1.5;
final Rectangle rectangle = new Rectangle(w,
h)
.setFillAlpha(0.01)
.setStrokeWidth(0)
.setStrokeAlpha(0);
final Arrow expandArrow =
new Arrow(new Point2D(0,
h / 2),
new Point2D(w,
h / 2),
h / 2,
h,
45,
90,
ArrowType.AT_END_TAPERED)
.setFillColor(getArrowOutColor())
.setFillAlpha(0.5)
.setVisible(!isExpanded);
final Arrow collapseArrow =
new Arrow(new Point2D(w,
h / 2),
new Point2D(0,
h / 2),
h / 2,
h,
45,
90,
ArrowType.AT_END_TAPERED)
.setFillColor(getArrowOutColor())
.setFillAlpha(0.5)
.setVisible(isExpanded);
handlerRegistrationManager.register(
rectangle.addNodeMouseClickHandler(nodeMouseClickEvent -> {
if (presenter.isExpanded()) {
expandArrow.setVisible(true);
collapseArrow.setVisible(false);
presenter.collapse();
} else {
expandArrow.setVisible(false);
collapseArrow.setVisible(true);
presenter.expand();
}
})
);
handlerRegistrationManager.register(
rectangle.addNodeMouseEnterHandler(nodeMouseEnterEvent -> {
stopHoverTimeoutPalette();
if (presenter.isExpanded()) {
animate(collapseArrow,
getArrowHoverColor(),
1,
1);
} else {
animate(expandArrow,
getArrowHoverColor(),
1,
1);
}
})
);
handlerRegistrationManager.register(
rectangle.addNodeMouseExitHandler(nodeMouseExitEvent -> {
startHoverTimeoutPalette();
if (presenter.isExpanded()) {
animate(collapseArrow,
getArrowOutColor(),
0.5,
0.5);
} else {
animate(expandArrow,
getArrowOutColor(),
0.5,
0.5);
}
})
);
return new Group()
.add(expandArrow)
.add(collapseArrow)
.add(rectangle.moveToTop());
}
private void animate(final IPrimitive<?> primitive,
final String fillColor,
final double fillAlpha,
final double strokeAlpha) {
primitive.animate(
AnimationTweener.LINEAR,
AnimationProperties.toPropertyList(
AnimationProperty.Properties.FILL_COLOR(fillColor),
AnimationProperty.Properties.FILL_ALPHA(fillAlpha),
AnimationProperty.Properties.STROKE_ALPHA(strokeAlpha)
),
200
);
}
protected void removeExpandCollapseButton() {
handlerRegistrationManager.removeHandler();
if (null != colExpButton) {
colExpButton.removeFromParent();
colExpButton = null;
}
}
protected void initPaletteCallbacks() {
getPalette().setItemCallback(new AbstractPalette.Callback() {
@Override
public void onItemHover(final int index,
final double mouseX,
final double mouseY,
final double itemX,
final double itemY) {
if (null != presenter) {
presenter.onItemHover(index,
mouseX,
mouseY,
itemX,
itemY);
}
}
@Override
public void onItemOut(final int index) {
if (null != presenter) {
presenter.onItemOut(index);
}
}
@Override
public void onItemMouseDown(final int index,
final double mouseX,
final double mouseY,
final double itemX,
final double itemY) {
if (null != presenter) {
presenter.onItemMouseDown(index,
mouseX,
mouseY,
itemX,
itemY);
}
}
@Override
public void onItemClick(final int index,
final double mouseX,
final double mouseY,
final double itemX,
final double itemY) {
if (null != presenter) {
presenter.onItemClick(index,
mouseX,
mouseY,
itemX,
itemY);
}
}
});
}
protected void stopHoverTimeoutPalette() {
if (palette instanceof HoverPalette) {
final HoverPalette hoverPalette = (HoverPalette) palette;
hoverPalette.stopTimeout();
}
}
protected void startHoverTimeoutPalette() {
if (palette instanceof HoverPalette) {
final HoverPalette hoverPalette = (HoverPalette) palette;
hoverPalette.startTimeout();
}
}
protected String getArrowHoverColor() {
return ColorName.DARKBLUE.getColorString();
}
protected String getArrowOutColor() {
return ColorName.LIGHTBLUE.getColorString();
}
protected PaletteGrid getGrid() {
return presenter.getGrid();
}
}