/* * Copyright 2015 JBoss, by Red Hat, Inc * * 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.uberfire.ext.wires.core.client.palette; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Event; import javax.inject.Inject; import com.ait.lienzo.client.core.event.NodeMouseDownEvent; import com.ait.lienzo.client.core.event.NodeMouseDownHandler; import com.ait.lienzo.client.core.shape.Group; import com.ait.lienzo.client.core.shape.Layer; import com.ait.lienzo.client.core.shape.Rectangle; import com.ait.lienzo.client.core.shape.Text; import com.ait.lienzo.client.widget.LienzoPanel; import com.ait.lienzo.shared.core.types.TextBaseLine; import com.google.gwt.dom.client.Style; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseMoveHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.RootPanel; import org.uberfire.ext.wires.core.api.events.ShapeDragCompleteEvent; import org.uberfire.ext.wires.core.api.events.ShapeDragPreviewEvent; import org.uberfire.ext.wires.core.api.factories.FactoryHelper; import org.uberfire.ext.wires.core.api.factories.ShapeDragProxy; import org.uberfire.ext.wires.core.api.factories.ShapeDragProxyCompleteCallback; import org.uberfire.ext.wires.core.api.factories.ShapeDragProxyPreviewCallback; import org.uberfire.ext.wires.core.api.factories.ShapeFactory; import org.uberfire.ext.wires.core.api.factories.ShapeGlyph; import org.uberfire.ext.wires.core.api.shapes.WiresBaseShape; import org.uberfire.ext.wires.core.client.util.ShapeFactoryUtil; @ApplicationScoped public class StencilPaletteBuilder { private static final int ZINDEX = Integer.MAX_VALUE; private static final double GLYPH_WIDTH = 65; private static final double GLYPH_HEIGHT = 65; @Inject private Event<ShapeDragCompleteEvent> shapeDragCompleteEvent; @Inject private Event<ShapeDragPreviewEvent> shapeDragPreviewEvent; public PaletteShape build(final LienzoPanel dragProxyParentPanel, final FactoryHelper helper, final ShapeFactory factory) { final PaletteShape paletteShape = new PaletteShape(); final ShapeGlyph glyph = drawGlyph(factory, helper); final Text description = drawDescription(factory, helper); final Rectangle bounding = drawBoundingBox(factory, helper); //Callback is invoked when the drag operation ends final ShapeDragProxyCompleteCallback dragCompleteCallback = new ShapeDragProxyCompleteCallback() { @Override public void callback(final double x, final double y) { shapeDragCompleteEvent.fire(new ShapeDragCompleteEvent(factory.getShape(helper), x, y)); } }; //Callback is invoked during the drag operation final WiresBaseShape shape = factory.getShape(helper); final ShapeDragProxyPreviewCallback dragPreviewCallback = new ShapeDragProxyPreviewCallback() { @Override public void callback(final double x, final double y) { shapeDragPreviewEvent.fire(new ShapeDragPreviewEvent(shape, x, y)); } }; //Attach handles for drag operation final ShapeDragProxy dragProxy = factory.getDragProxy(helper, dragPreviewCallback, dragCompleteCallback); addDragHandlers(dragProxyParentPanel, dragProxy, paletteShape); //Build Palette Shape paletteShape.setBounding(bounding); paletteShape.setGroup(scaleGlyph(glyph)); paletteShape.setDescription(description); return paletteShape; } /** * Return a ShapeGlyph that represents the Factory in the Palette. * This implementation delegates this to the ShapeFactory. * @param factory ShapeFactory that is capable of providing a default ShapeGlyph * @param helper FactoryHelper that might provide additional information to build a Glyph. Unused by this implementation. * @return A ShapeGlyph object or null if one is not required. */ protected ShapeGlyph drawGlyph(final ShapeFactory factory, final @SuppressWarnings("unused") FactoryHelper helper) { return factory.getGlyph(); } /** * Scale the Shape provided by the ShapeFactory as the glyph to fit the PaletteShape. * @param glyph * @return */ protected Group scaleGlyph(final ShapeGlyph glyph) { final double sx = GLYPH_WIDTH / glyph.getWidth(); final double sy = GLYPH_HEIGHT / glyph.getHeight(); final Group group = glyph.getGroup(); return group.setX(ShapeFactoryUtil.WIDTH_BOUNDING / 2).setY(ShapeFactoryUtil.WIDTH_BOUNDING / 2).setScale(sx, sy); } /** * Return Text that represents the Factory in the Palette. * This implementation delegates this to the ShapeFactory. * @param factory ShapeFactory that is capable of providing a default description * @param helper FactoryHelper that might provide additional information to build a Glyph. Unused by this implementation. * @return A Text object or null if one is not required. */ protected Text drawDescription(final ShapeFactory factory, final @SuppressWarnings("unused") FactoryHelper helper) { Text text = new Text(factory.getShapeDescription(), ShapeFactoryUtil.FONT_FAMILY_DESCRIPTION, ShapeFactoryUtil.FONT_SIZE_DESCRIPTION); text.setFillColor(ShapeFactoryUtil.RGB_TEXT_DESCRIPTION); text.setTextBaseLine(TextBaseLine.MIDDLE); text.setX(5); text.setY(85); return text; } /** * Return a Rectangle that is the bounding box for the PaletteShape. * This implementation does not use the ShapeFactory but sub-classes could. * @param factory ShapeFactory that might be useful for sub-classes to build a bounding Rectangle * @param helper FactoryHelper that might provide additional information to build a Glyph. Unused by this implementation. * @return A Rectangle object or null if one is not required. */ protected Rectangle drawBoundingBox(final @SuppressWarnings("unused") ShapeFactory factory, final @SuppressWarnings("unused") FactoryHelper helper) { final Rectangle boundingBox = new Rectangle(ShapeFactoryUtil.WIDTH_BOUNDING, ShapeFactoryUtil.HEIGHT_BOUNDING); boundingBox.setStrokeColor(ShapeFactoryUtil.RGB_STROKE_BOUNDING) .setStrokeWidth(1) .setFillColor(ShapeFactoryUtil.RGB_FILL_BOUNDING) .setDraggable(false); return boundingBox; } private void addDragHandlers(final LienzoPanel dragProxyParentPanel, final ShapeDragProxy proxy, final Group shape) { shape.addNodeMouseDownHandler(getShapeDragStartHandler(dragProxyParentPanel, proxy)); } private NodeMouseDownHandler getShapeDragStartHandler(final LienzoPanel dragProxyParentPanel, final ShapeDragProxy proxy) { return new NodeMouseDownHandler() { @Override public void onNodeMouseDown(final NodeMouseDownEvent event) { final double proxyWidth = proxy.getWidth(); final double proxyHeight = proxy.getHeight(); final Group dragShape = proxy.getDragGroup(); dragShape.setX(proxyWidth / 2); dragShape.setY(proxyHeight / 2); final LienzoPanel dragProxyPanel = new LienzoPanel((int) proxyWidth, (int) proxyHeight); final Layer dragProxyLayer = new Layer(); dragProxyLayer.add(dragShape); dragProxyPanel.add(dragProxyLayer); dragProxyLayer.batch(); setDragProxyPosition(dragProxyParentPanel, dragProxyPanel, proxyWidth, proxyHeight, event); attachDragProxyHandlers(dragProxyPanel, proxy); RootPanel.get().add(dragProxyPanel); } }; } private void setDragProxyPosition(final LienzoPanel dragProxyParentPanel, final LienzoPanel dragProxyPanel, final double proxyWidth, final double proxyHeight, final NodeMouseDownEvent event) { Style style = dragProxyPanel.getElement().getStyle(); style.setPosition(Style.Position.ABSOLUTE); style.setLeft(dragProxyParentPanel.getAbsoluteLeft() + event.getX() - (proxyWidth / 2), Style.Unit.PX); style.setTop(dragProxyParentPanel.getAbsoluteTop() + event.getY() - (proxyHeight / 2), Style.Unit.PX); style.setZIndex(ZINDEX); } private void attachDragProxyHandlers(final LienzoPanel floatingPanel, final ShapeDragProxy proxy) { final Style style = floatingPanel.getElement().getStyle(); final HandlerRegistration[] handlerRegs = new HandlerRegistration[2]; //MouseMoveEvents handlerRegs[0] = RootPanel.get().addDomHandler(new MouseMoveHandler() { @Override public void onMouseMove(final MouseMoveEvent mouseMoveEvent) { style.setLeft(mouseMoveEvent.getX() - (floatingPanel.getWidth() / 2), Style.Unit.PX); style.setTop(mouseMoveEvent.getY() - (floatingPanel.getHeight() / 2), Style.Unit.PX); proxy.onDragPreview(mouseMoveEvent.getX(), mouseMoveEvent.getY()); } }, MouseMoveEvent.getType()); //MouseUpEvent handlerRegs[1] = RootPanel.get().addDomHandler(new MouseUpHandler() { @Override public void onMouseUp(final MouseUpEvent mouseUpEvent) { handlerRegs[0].removeHandler(); handlerRegs[1].removeHandler(); RootPanel.get().remove(floatingPanel); proxy.onDragComplete(mouseUpEvent.getX(), mouseUpEvent.getY()); } }, MouseUpEvent.getType()); } }