1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.diagram.handler;
\r
14 import java.awt.geom.Point2D;
\r
15 import java.util.ArrayList;
\r
16 import java.util.HashSet;
\r
17 import java.util.List;
\r
18 import java.util.Set;
\r
20 import org.simantics.db.ReadGraph;
\r
21 import org.simantics.db.Resource;
\r
22 import org.simantics.db.exception.DatabaseException;
\r
23 import org.simantics.db.request.Read;
\r
24 import org.simantics.diagram.elements.ElementTransforms;
\r
25 import org.simantics.diagram.stubs.DiagramResource;
\r
26 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
\r
27 import org.simantics.g2d.diagram.DiagramMutator;
\r
28 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
\r
29 import org.simantics.g2d.diagram.participant.Selection;
\r
30 import org.simantics.g2d.element.ElementHints;
\r
31 import org.simantics.g2d.element.IElement;
\r
32 import org.simantics.g2d.element.handler.Rotate;
\r
33 import org.simantics.g2d.element.handler.Scale;
\r
34 import org.simantics.g2d.participant.MouseUtil;
\r
35 import org.simantics.g2d.participant.MouseUtil.MouseInfo;
\r
36 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
\r
37 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
\r
38 import org.simantics.scenegraph.g2d.events.command.Commands;
\r
39 import org.simantics.ui.SimanticsUI;
\r
40 import org.simantics.utils.ui.ErrorLogger;
\r
43 * Handles commands {@link Commands#ROTATE_ELEMENT_CCW},
\r
44 * {@link Commands#ROTATE_ELEMENT_CW}, {@link Commands#FLIP_ELEMENT_HORIZONTAL},
\r
45 * {@link Commands#FLIP_ELEMENT_VERTICAL} and {@link Commands#SCALE_ELEMENT} for
\r
46 * rotating (in 90 degree steps), flipping and continuously scaling the current
\r
49 * @author Tuukka Lehtonen
\r
51 public class SimpleElementTransformHandler extends AbstractDiagramParticipant {
\r
53 @Dependency protected Selection selection;
\r
54 @Dependency protected MouseUtil mouseUtil;
\r
56 protected final boolean rotation;
\r
57 protected final boolean flip;
\r
58 protected final boolean scale;
\r
60 public SimpleElementTransformHandler() {
\r
61 this(true, true, false);
\r
64 public SimpleElementTransformHandler(boolean enableRotation, boolean enableFlip, boolean enableScale) {
\r
65 this.rotation = enableRotation;
\r
66 this.flip = enableFlip;
\r
67 this.scale = enableScale;
\r
70 public boolean isRotateEnabled() {
\r
74 public boolean isFlipEnabled() {
\r
78 public boolean isScaleEnabled() {
\r
82 @EventHandler(priority = 0)
\r
83 public boolean handleCommand(CommandEvent ke) {
\r
84 if (isRotateEnabled() && (ke.command.equals( Commands.ROTATE_ELEMENT_CCW ) || ke.command.equals( Commands.ROTATE_ELEMENT_CW ))) {
\r
85 return rotate(ke.command.equals( Commands.ROTATE_ELEMENT_CW ));
\r
86 } else if (isFlipEnabled() && (ke.command.equals( Commands.FLIP_ELEMENT_HORIZONTAL ) || ke.command.equals( Commands.FLIP_ELEMENT_VERTICAL))) {
\r
87 return flip(ke.command.equals( Commands.FLIP_ELEMENT_VERTICAL ));
\r
88 } else if (isScaleEnabled() && Commands.SCALE_ELEMENT.equals(ke.command)) {
\r
89 return startSelectionMouseScale(0);
\r
97 private boolean flip(boolean xAxis) {
\r
98 // final double sx = ke.command.equals( Commands.FLIP_ELEMENT_HORIZONTAL ) ? -1 : 1;
\r
99 // final double sy = ke.command.equals( Commands.FLIP_ELEMENT_VERTICAL ) ? -1 : 1;
\r
100 // DiagramUtils.mutateDiagram(diagram, new Callback<DiagramMutator>() {
\r
102 // public void run(DiagramMutator mutator) {
\r
103 // scaleAllSelections(mutator, sx, sy);
\r
106 // DiagramUtils.validateAndFix(diagram, getContext());
\r
109 Resource[] elements = getSelection();
\r
110 if (elements.length == 0)
\r
113 ElementTransforms.flip(elements, xAxis);
\r
120 private boolean rotate(boolean clockwise) {
\r
121 // final double rotation = ke.command.equals(Commands.ROTATE_ELEMENT_CCW) ? -90 : 90;
\r
122 // DiagramUtils.mutateDiagram(diagram, new Callback<DiagramMutator>() {
\r
124 // public void run(DiagramMutator mutator) {
\r
125 // rotateAllSelections(mutator, rotation);
\r
128 // DiagramUtils.validateAndFix(diagram, getContext());
\r
131 Resource[] elements = getSelection();
\r
132 if (elements.length == 0)
\r
135 ElementTransforms.rotate(elements, clockwise);
\r
139 protected Resource[] getSelection() {
\r
140 Set<IElement> els = selection.getSelection(0);
\r
141 final Set<Resource> resources = new HashSet<Resource>();
\r
142 for (IElement el : els) {
\r
143 Object o = el.getHint(ElementHints.KEY_OBJECT);
\r
144 if (o instanceof Resource)
\r
145 resources.add((Resource) o);
\r
148 return SimanticsUI.getSession().syncRequest(new Read<Resource[]>() {
\r
150 public Resource[] perform(ReadGraph graph) throws DatabaseException {
\r
151 List<Resource> result = getSelection(graph, resources);
\r
152 return result.toArray(new Resource[result.size()]);
\r
155 } catch (DatabaseException e) {
\r
156 ErrorLogger.defaultLogError(e);
\r
157 return Resource.NONE;
\r
161 protected List<Resource> getSelection(ReadGraph graph, Set<Resource> resources) throws DatabaseException {
\r
162 DiagramResource dr = DiagramResource.getInstance(graph);
\r
163 List<Resource> result = new ArrayList<Resource>();
\r
164 for (Resource r : resources) {
\r
165 if (graph.isInstanceOf(r, dr.Element) /*&& graph.isInstanceOf(r, dr.Monitor)*/)
\r
171 protected MouseScaleMode createMouseScaleMode(int mouseId, MouseInfo mi, Set<IElement> s) {
\r
172 return new MouseScaleMode(mouseId, mi, s);
\r
175 boolean startSelectionMouseScale(int mouseId) {
\r
176 Set<IElement> s = selection.getSelection(mouseId);
\r
179 // Prevent multiple mouse scale modes from being activated.
\r
180 for (MouseScaleMode msm : getContext().getItemsByClass(MouseScaleMode.class))
\r
181 if (msm.getMouseId() == mouseId)
\r
183 MouseInfo mi = mouseUtil.getMouseInfo(mouseId);
\r
184 getContext().add( createMouseScaleMode(mouseId, mi, s) );
\r
188 void scaleAllSelections(DiagramMutator mutator, double xscale, double yscale) {
\r
189 for (Set<IElement> s : selection.getSelections().values()) {
\r
190 for (IElement e : s) {
\r
191 Scale scale = e.getElementClass().getAtMostOneItemOfClass(Scale.class);
\r
192 if (scale != null) {
\r
193 mutator.modifyTransform(e);
\r
194 Point2D sc = scale.getScale(e);
\r
195 sc.setLocation(xscale*sc.getX(), yscale*sc.getY());
\r
196 scale.setScale(e, sc);
\r
202 void rotateAllSelections(DiagramMutator mutator, double degrees) {
\r
203 double angrad = Math.toRadians(degrees);
\r
204 Point2D origin = new Point2D.Double(0, 0);
\r
205 for (Set<IElement> s : selection.getSelections().values()) {
\r
206 for (IElement e : s) {
\r
207 Rotate rotate = e.getElementClass().getAtMostOneItemOfClass(Rotate.class);
\r
208 if (rotate != null) {
\r
209 mutator.modifyTransform(e);
\r
210 rotate.rotate(e, angrad, origin);
\r