/******************************************************************************* * 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.diagram.handler; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; import org.simantics.diagram.elements.ElementTransforms; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; import org.simantics.g2d.diagram.DiagramMutator; import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant; import org.simantics.g2d.diagram.participant.Selection; import org.simantics.g2d.element.ElementHints; import org.simantics.g2d.element.IElement; import org.simantics.g2d.element.handler.Rotate; import org.simantics.g2d.element.handler.Scale; import org.simantics.g2d.participant.MouseUtil; import org.simantics.g2d.participant.MouseUtil.MouseInfo; 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.utils.ui.ErrorLogger; /** * Handles commands {@link Commands#ROTATE_ELEMENT_CCW}, * {@link Commands#ROTATE_ELEMENT_CW}, {@link Commands#FLIP_ELEMENT_HORIZONTAL}, * {@link Commands#FLIP_ELEMENT_VERTICAL} and {@link Commands#SCALE_ELEMENT} for * rotating (in 90 degree steps), flipping and continuously scaling the current * selection. * * @author Tuukka Lehtonen */ public class SimpleElementTransformHandler extends AbstractDiagramParticipant { @Dependency protected Selection selection; @Dependency protected MouseUtil mouseUtil; protected final boolean rotation; protected final boolean flip; protected final boolean scale; public SimpleElementTransformHandler() { this(true, true, false); } public SimpleElementTransformHandler(boolean enableRotation, boolean enableFlip, boolean enableScale) { this.rotation = enableRotation; this.flip = enableFlip; this.scale = enableScale; } public boolean isRotateEnabled() { return rotation; } public boolean isFlipEnabled() { return flip; } public boolean isScaleEnabled() { return scale; } @EventHandler(priority = 0) public boolean handleCommand(CommandEvent ke) { if (isRotateEnabled() && (ke.command.equals( Commands.ROTATE_ELEMENT_CCW ) || ke.command.equals( Commands.ROTATE_ELEMENT_CW ))) { return rotate(ke.command.equals( Commands.ROTATE_ELEMENT_CW )); } else if (isFlipEnabled() && (ke.command.equals( Commands.FLIP_ELEMENT_HORIZONTAL ) || ke.command.equals( Commands.FLIP_ELEMENT_VERTICAL))) { return flip(ke.command.equals( Commands.FLIP_ELEMENT_VERTICAL )); } else if (isScaleEnabled() && Commands.SCALE_ELEMENT.equals(ke.command)) { return startSelectionMouseScale(0); } return false; } /** * @param xAxis */ private boolean flip(boolean xAxis) { // final double sx = ke.command.equals( Commands.FLIP_ELEMENT_HORIZONTAL ) ? -1 : 1; // final double sy = ke.command.equals( Commands.FLIP_ELEMENT_VERTICAL ) ? -1 : 1; // DiagramUtils.mutateDiagram(diagram, new Callback() { // @Override // public void run(DiagramMutator mutator) { // scaleAllSelections(mutator, sx, sy); // } // }); // DiagramUtils.validateAndFix(diagram, getContext()); // setDirty(); Resource[] elements = getSelection(); if (elements.length == 0) return false; ElementTransforms.flip(elements, xAxis); return true; } /** * @param clockwise */ private boolean rotate(boolean clockwise) { // final double rotation = ke.command.equals(Commands.ROTATE_ELEMENT_CCW) ? -90 : 90; // DiagramUtils.mutateDiagram(diagram, new Callback() { // @Override // public void run(DiagramMutator mutator) { // rotateAllSelections(mutator, rotation); // } // }); // DiagramUtils.validateAndFix(diagram, getContext()); // setDirty(); Resource[] elements = getSelection(); if (elements.length == 0) return false; ElementTransforms.rotate(elements, clockwise); return true; } protected Resource[] getSelection() { Set els = selection.getSelection(0); final Set resources = new HashSet(); for (IElement el : els) { Object o = el.getHint(ElementHints.KEY_OBJECT); if (o instanceof Resource) resources.add((Resource) o); } try { return Simantics.getSession().syncRequest(new Read() { @Override public Resource[] perform(ReadGraph graph) throws DatabaseException { List result = getSelection(graph, resources); return result.toArray(new Resource[result.size()]); } }); } catch (DatabaseException e) { ErrorLogger.defaultLogError(e); return Resource.NONE; } } protected List getSelection(ReadGraph graph, Set resources) throws DatabaseException { DiagramResource dr = DiagramResource.getInstance(graph); List result = new ArrayList(); for (Resource r : resources) { if (graph.isInstanceOf(r, dr.Element) /*&& graph.isInstanceOf(r, dr.Monitor)*/) result.add(r); } return result; } protected MouseScaleMode createMouseScaleMode(int mouseId, MouseInfo mi, Set s) { return new MouseScaleMode(mouseId, mi, s); } boolean startSelectionMouseScale(int mouseId) { Set s = selection.getSelection(mouseId); if (s.isEmpty()) return false; // Prevent multiple mouse scale modes from being activated. for (MouseScaleMode msm : getContext().getItemsByClass(MouseScaleMode.class)) if (msm.getMouseId() == mouseId) return false; MouseInfo mi = mouseUtil.getMouseInfo(mouseId); getContext().add( createMouseScaleMode(mouseId, mi, s) ); return true; } void scaleAllSelections(DiagramMutator mutator, double xscale, double yscale) { for (Set s : selection.getSelections().values()) { for (IElement e : s) { Scale scale = e.getElementClass().getAtMostOneItemOfClass(Scale.class); if (scale != null) { mutator.modifyTransform(e); Point2D sc = scale.getScale(e); sc.setLocation(xscale*sc.getX(), yscale*sc.getY()); scale.setScale(e, sc); } } } } void rotateAllSelections(DiagramMutator mutator, double degrees) { double angrad = Math.toRadians(degrees); Point2D origin = new Point2D.Double(0, 0); for (Set s : selection.getSelections().values()) { for (IElement e : s) { Rotate rotate = e.getElementClass().getAtMostOneItemOfClass(Rotate.class); if (rotate != null) { mutator.modifyTransform(e); rotate.rotate(e, angrad, origin); } } } } }