X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fdnd%2FDragPainter.java;h=3a7609b947ece077c2fcee878b20cec5675a3d6f;hp=208d4d0ca30ce8ff9a11ee08d28e0308f41308a0;hb=5a370e0b751e60f36445716bef0cb2485c5fc7ef;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/dnd/DragPainter.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/dnd/DragPainter.java index 208d4d0ca..3a7609b94 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/dnd/DragPainter.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/dnd/DragPainter.java @@ -1,217 +1,225 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.g2d.dnd; - -import java.awt.AlphaComposite; -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import org.simantics.g2d.canvas.ICanvasContext; -import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; -import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup; -import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; -import org.simantics.g2d.diagram.DiagramHints; -import org.simantics.g2d.participant.TransformUtil; -import org.simantics.scenegraph.g2d.G2DParentNode; -import org.simantics.scenegraph.g2d.IG2DNode; -import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; -import org.simantics.scenegraph.g2d.events.command.CommandEvent; -import org.simantics.scenegraph.g2d.events.command.Commands; -import org.simantics.scenegraph.g2d.nodes.SingleElementNode; -import org.simantics.scenegraph.g2d.snap.ISnapAdvisor; -import org.simantics.utils.datastructures.context.IContext; -import org.simantics.utils.datastructures.context.IContextListener; - -/** - * This participant paints an array of icons of a drag operation. - * - * @author Toni Kalajainen - */ -public class DragPainter extends AbstractCanvasParticipant { - // Priority of drag event, eats ecs key - public final static int DRAG_EVENT_PRIORITY = Integer.MAX_VALUE - 1500; - public final static int DRAG_PAINT_PRIORITY = Integer.MAX_VALUE - 1100; - public final static int MARGIN = 5; - - final IDnDContext dropCtx; - Point2D mouseControlPos; - - public DragPainter(IDnDContext dropCtx, Point2D mouseControlPos) { - super(); - this.dropCtx = dropCtx; - this.mouseControlPos = (Point2D) mouseControlPos.clone(); - } - - IContextListener contextListener = new IContextListener() { - @Override - public void itemAdded(IContext sender, IDragItem item) { - updateItemPositions(); - getContext().getContentContext().setDirty(); - } - @Override - public void itemRemoved(IContext sender, IDragItem item) { - updateItemPositions(); - getContext().getContentContext().setDirty(); - } - }; - - @Override - public void addedToContext(ICanvasContext ctx) { - super.addedToContext(ctx); - dropCtx.addContextListener(getContext().getThreadAccess(), contextListener); - } - - @Override - public void removedFromContext(ICanvasContext ctx) { - dropCtx.removeContextListener(getContext().getThreadAccess(), contextListener); - super.removedFromContext(ctx); - } - - public boolean setMousePos(Point2D mouseControlPos) { - return setMousePos(mouseControlPos, false); - } - - public boolean setMousePos(Point2D mouseControlPos, boolean forceUpdate) { - if (!forceUpdate && mouseControlPos.equals(this.mouseControlPos)) - return false; - this.mouseControlPos = (Point2D) mouseControlPos.clone(); - getContext().getContentContext().setDirty(); - updateItemPositions(); - return true; - } - - /** - * Get the size of the largest drop item - * @param items - * @return - */ - private Point2D calcItemSize(IDragItem[] items) - { - double w = Double.MIN_VALUE; - double h = Double.MIN_VALUE; - for (IDragItem i : items) { - Rectangle2D bounds = i.getBounds(); - if (bounds == null) bounds = new Rectangle2D.Double(0,0,1,1); - if (w < bounds.getWidth()) - w = bounds.getWidth(); - if (h < bounds.getHeight()) - h = bounds.getHeight(); - } - return new Point2D.Double(w, h); - } - - private void updateItemPositions() { - // Calculate mouse position on diagram - TransformUtil vi = getContext().getSingleItem(TransformUtil.class); - AffineTransform controlToDiagram = vi.getInverseTransform(); - if (controlToDiagram==null) return; - Point2D mouseDiagramPos = controlToDiagram.transform(mouseControlPos, new Point2D.Double()); - - //System.out.println("updateItemPositions: mousepos: " + mouseControlPos + " - " + mouseDiagramPos); - - IDragItem items[] = dropCtx.toArray(); - int count = items.length; - int columns = (int) Math.ceil( Math.sqrt( count) ); - Integer columnsHint = dropCtx.getHints().getHint(DnDHints.KEY_DND_GRID_COLUMNS); - if (columnsHint != null) - columns = columnsHint; - int rows = (int) Math.ceil((double)count / (double)columns); - int margin = MARGIN; - // Size of the largest item - Point2D size = calcItemSize(items); - - // Calculate center point of the whole item mass - double cx = ((columns-1)*(size.getX()+margin))/2 + size.getX()/2; - double cy = ((rows -1)*(size.getY()+margin))/2 + size.getY()/2; - //double cx = ((columns)*(size.getX()+margin)-margin)/2 /*- size.getX()/2*/; - //double cy = ((rows )*(size.getY()+margin)-margin)/2 /*- size.getY()/2*/; - //double cx = 0; - //double cy = 0; - - int index = 0; - for (IDragItem i : items) { - Rectangle2D bounds = i.getBounds(); - double x = (index % columns) * (margin + size.getX()); - double y = (index / columns) * (margin + size.getY()); -// Point2D pos = new Point2D.Double(x, y); - index++; - - x -= bounds.getX(); - y -= bounds.getY(); - x += mouseDiagramPos.getX(); - y += mouseDiagramPos.getY(); - - x -= cx; - y -= cy; - - Point2D p = new Point2D.Double(x, y); - ISnapAdvisor snap = getHint(DiagramHints.SNAP_ADVISOR); - if (snap != null) - snap.snap(p); - dropCtx.setItemPosition(i, p); - } - updateSG(); - } - - protected G2DParentNode node = null; - - @SGInit - public void initSG(G2DParentNode parent) { - node = parent.addNode(G2DParentNode.class); - node.setZIndex(DRAG_PAINT_PRIORITY); - updateSG(); - } - - @SGCleanup - public void cleanupSG() { - node.remove(); - node = null; - } - - private void updateSG() { - IDragItem items[] = dropCtx.toArray(); -// updateItemPositions(); - for (IDragItem item : items) { - Point2D pos = dropCtx.getItemPosition(item); - if(pos != null) { // Position can (or at least seems to be) be null on the first frame - AffineTransform subt = AffineTransform.getTranslateInstance(pos.getX(), pos.getY()); - - IG2DNode itemHolder = node.getNode(""+item.hashCode()); - if (itemHolder != null && !(itemHolder instanceof SingleElementNode)) { - System.err.println("BUG: item hash codes collide within the dragged item context - found unrecognized item " + itemHolder + " with node id '" + item.hashCode() + "'"); - continue; - } - - SingleElementNode elementHolder = (SingleElementNode) itemHolder; - if (elementHolder == null) { - elementHolder = node.getOrCreateNode(""+item.hashCode(), SingleElementNode.class); - elementHolder.setTransform(subt); - elementHolder.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f)); - item.paint(elementHolder); - } else { - elementHolder.setTransform(subt); - } - } - } - } - - @EventHandler(priority = DRAG_EVENT_PRIORITY) - public boolean handleEvent(CommandEvent e) { - if (e.command.equals( Commands.CANCEL) ) - { - remove(); - return true; - } - return false; - } -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.g2d.dnd; + +import java.awt.AlphaComposite; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; +import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup; +import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.element.ElementHints; +import org.simantics.g2d.participant.TransformUtil; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.IG2DNode; +import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; +import org.simantics.scenegraph.g2d.events.command.CommandEvent; +import org.simantics.scenegraph.g2d.events.command.Commands; +import org.simantics.scenegraph.g2d.nodes.SingleElementNode; +import org.simantics.scenegraph.g2d.snap.ISnapAdvisor; +import org.simantics.utils.datastructures.context.IContext; +import org.simantics.utils.datastructures.context.IContextListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This participant paints an array of icons of a drag operation. + * + * @author Toni Kalajainen + */ +public class DragPainter extends AbstractCanvasParticipant { + private static final Logger LOGGER = LoggerFactory.getLogger(DragPainter.class); + // Priority of drag event, eats ecs key + public final static int DRAG_EVENT_PRIORITY = Integer.MAX_VALUE - 1500; + public final static int DRAG_PAINT_PRIORITY = Integer.MAX_VALUE - 1100; + public final static int MARGIN = 5; + + final IDnDContext dropCtx; + Point2D mouseControlPos; + + public DragPainter(IDnDContext dropCtx, Point2D mouseControlPos) { + super(); + this.dropCtx = dropCtx; + this.mouseControlPos = (Point2D) mouseControlPos.clone(); + } + + IContextListener contextListener = new IContextListener() { + @Override + public void itemAdded(IContext sender, IDragItem item) { + updateItemPositions(); + getContext().getContentContext().setDirty(); + } + @Override + public void itemRemoved(IContext sender, IDragItem item) { + updateItemPositions(); + getContext().getContentContext().setDirty(); + } + }; + + @Override + public void addedToContext(ICanvasContext ctx) { + super.addedToContext(ctx); + dropCtx.addContextListener(getContext().getThreadAccess(), contextListener); + } + + @Override + public void removedFromContext(ICanvasContext ctx) { + dropCtx.removeContextListener(getContext().getThreadAccess(), contextListener); + super.removedFromContext(ctx); + } + + public boolean setMousePos(Point2D mouseControlPos) { + return setMousePos(mouseControlPos, false); + } + + public boolean setMousePos(Point2D mouseControlPos, boolean forceUpdate) { + if (!forceUpdate && mouseControlPos.equals(this.mouseControlPos)) + return false; + this.mouseControlPos = (Point2D) mouseControlPos.clone(); + getContext().getContentContext().setDirty(); + updateItemPositions(); + return true; + } + + /** + * Get the size of the largest drop item + * @param items + * @return + */ + private Point2D calcItemSize(IDragItem[] items) + { + double w = Double.MIN_VALUE; + double h = Double.MIN_VALUE; + for (IDragItem i : items) { + Rectangle2D bounds = i.getBounds(); + if (bounds == null) bounds = new Rectangle2D.Double(0,0,1,1); + if (w < bounds.getWidth()) + w = bounds.getWidth(); + if (h < bounds.getHeight()) + h = bounds.getHeight(); + } + return new Point2D.Double(w, h); + } + + private void updateItemPositions() { + // Calculate mouse position on diagram + TransformUtil vi = getContext().getSingleItem(TransformUtil.class); + AffineTransform controlToDiagram = vi.getInverseTransform(); + if (controlToDiagram==null) return; + Point2D mouseDiagramPos = controlToDiagram.transform(mouseControlPos, new Point2D.Double()); + + //System.out.println("updateItemPositions: mousepos: " + mouseControlPos + " - " + mouseDiagramPos); + + IDragItem items[] = dropCtx.toArray(); + int count = items.length; + int columns = (int) Math.ceil( Math.sqrt( count) ); + Integer columnsHint = dropCtx.getHints().getHint(DnDHints.KEY_DND_GRID_COLUMNS); + if (columnsHint != null) + columns = columnsHint; + int rows = (int) Math.ceil((double)count / (double)columns); + int margin = MARGIN; + // Size of the largest item + Point2D size = calcItemSize(items); + + // Calculate center point of the whole item mass + double cx = ((columns-1)*(size.getX()+margin))/2 + size.getX()/2; + double cy = ((rows -1)*(size.getY()+margin))/2 + size.getY()/2; + //double cx = ((columns)*(size.getX()+margin)-margin)/2 /*- size.getX()/2*/; + //double cy = ((rows )*(size.getY()+margin)-margin)/2 /*- size.getY()/2*/; + //double cx = 0; + //double cy = 0; + + int index = 0; + for (IDragItem i : items) { + Rectangle2D bounds = i.getBounds(); + double x = (index % columns) * (margin + size.getX()); + double y = (index / columns) * (margin + size.getY()); +// Point2D pos = new Point2D.Double(x, y); + index++; + + x -= bounds.getX(); + y -= bounds.getY(); + x += mouseDiagramPos.getX(); + y += mouseDiagramPos.getY(); + + x -= cx; + y -= cy; + + Point2D p = new Point2D.Double(x, y); + ISnapAdvisor snap = getHint(DiagramHints.SNAP_ADVISOR); + if (snap != null) + snap.snap(p); + dropCtx.setItemPosition(i, p); + } + updateSG(); + } + + protected G2DParentNode node = null; + + @SGInit + public void initSG(G2DParentNode parent) { + node = parent.addNode(G2DParentNode.class); + node.setZIndex(DRAG_PAINT_PRIORITY); + updateSG(); + } + + @SGCleanup + public void cleanupSG() { + node.remove(); + node = null; + } + + private void updateSG() { + IDragItem items[] = dropCtx.toArray(); +// updateItemPositions(); + for (IDragItem item : items) { + Point2D pos = dropCtx.getItemPosition(item); + if(pos != null) { // Position can (or at least seems to be) be null on the first frame + AffineTransform subt = AffineTransform.getTranslateInstance(pos.getX(), pos.getY()); + AffineTransform at = item.getHintContext().getHint(ElementHints.KEY_TRANSFORM); + if (at != null) { + subt.concatenate(at); + } + + IG2DNode itemHolder = node.getNode(""+item.hashCode()); + if (itemHolder != null && !(itemHolder instanceof SingleElementNode)) { + LOGGER.error("BUG: item hash codes collide within the dragged item context - found unrecognized item " + itemHolder + " with node id '" + item.hashCode() + "'"); + continue; + } + + SingleElementNode elementHolder = (SingleElementNode) itemHolder; + if (elementHolder == null) { + elementHolder = node.getOrCreateNode(""+item.hashCode(), SingleElementNode.class); + elementHolder.setTransform(subt); + elementHolder.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f)); + item.paint(elementHolder); + } else { + elementHolder.setTransform(subt); + } + } + } + } + + @EventHandler(priority = DRAG_EVENT_PRIORITY) + public boolean handleEvent(CommandEvent e) { + if (e.command.equals( Commands.CANCEL) ) + { + remove(); + return true; + } + return false; + } +}