1 package org.simantics.diagram.elements;
\r
3 import java.awt.geom.AffineTransform;
\r
4 import java.awt.geom.Point2D;
\r
5 import java.awt.geom.Rectangle2D;
\r
6 import java.util.ArrayList;
\r
7 import java.util.Collection;
\r
8 import java.util.Collections;
\r
9 import java.util.Comparator;
\r
10 import java.util.List;
\r
12 import org.simantics.db.ReadGraph;
\r
13 import org.simantics.db.Resource;
\r
14 import org.simantics.db.UndoContext;
\r
15 import org.simantics.db.WriteGraph;
\r
16 import org.simantics.db.common.CommentMetadata;
\r
17 import org.simantics.db.common.request.IndexRoot;
\r
18 import org.simantics.db.common.request.WriteRequest;
\r
19 import org.simantics.db.exception.DatabaseException;
\r
20 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
\r
21 import org.simantics.db.exception.NoSingleResultException;
\r
22 import org.simantics.db.exception.ServiceException;
\r
23 import org.simantics.db.request.Write;
\r
24 import org.simantics.diagram.query.DiagramRequests;
\r
25 import org.simantics.diagram.stubs.DiagramResource;
\r
26 import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
\r
27 import org.simantics.g2d.diagram.DiagramClass;
\r
28 import org.simantics.g2d.diagram.IDiagram;
\r
29 import org.simantics.g2d.diagram.impl.Diagram;
\r
30 import org.simantics.g2d.element.ElementClass;
\r
31 import org.simantics.g2d.element.ElementUtils;
\r
32 import org.simantics.g2d.element.IElement;
\r
33 import org.simantics.g2d.element.impl.Element;
\r
34 import org.simantics.g2d.utils.GeometryUtils;
\r
35 import org.simantics.scl.commands.Command;
\r
36 import org.simantics.scl.commands.Commands;
\r
37 import org.simantics.ui.SimanticsUI;
\r
40 * Tools to align, rotate, and flip diagram elements.
\r
42 * TODO : We need to add capability hints to elements to prevent rotating and mirroring elements that do not support that.
\r
43 * Example: mirrored text does not make any sense.
\r
46 * @author Marko Luukkainen <marko.luukkainen@vtt.fi> (implementation)
\r
47 * @author Tuukka Lehtonen (documentation)
\r
49 public final class ElementTransforms {
\r
51 public static enum SIDE { LEFT, RIGHT, TOP, BOTTOM, VERT, HORIZ, VERT_BTW, HORIZ_BTW };
\r
54 * Align the specified set of diagram element resources in line with each
\r
55 * other calculated by the specified side.
\r
58 * Alignment requires at least two elements to do anything.
\r
60 * @param resources diagram element resources to rotate
\r
61 * @param side the side of each element to use for distancing. Does not support between aligments.
\r
63 public static void align(final Resource resources[], final SIDE side) {
\r
64 if (resources.length < 2)
\r
66 if (side == SIDE.HORIZ_BTW || side == SIDE.VERT_BTW )
\r
69 SimanticsUI.getSession().asyncRequest(new WriteRequest() {
\r
72 public void perform(WriteGraph graph) throws DatabaseException {
\r
73 graph.markUndoPoint();
\r
74 IDiagram hints = Diagram.spawnNew(DiagramClass.DEFAULT);
\r
76 List<AlignElement> elements = new ArrayList<AlignElement>();
\r
77 for (Resource r : resources) {
\r
78 AlignElement e = create(graph, hints, r);
\r
82 if (elements.size() < 2)
\r
86 for (AlignElement e : elements) {
\r
87 mx += e.transform[4];
\r
88 my += e.transform[5];
\r
90 mx /= elements.size();
\r
91 my /= elements.size();
\r
93 // prevent moving symbols into the same position
\r
95 for (AlignElement e : elements) {
\r
96 if (side == SIDE.VERT || side == SIDE.LEFT || side == SIDE.RIGHT) {
\r
97 if (Math.abs(e.transform[5] - my) < 0.1) {
\r
101 if (Math.abs(e.transform[4] - mx) < 0.1) {
\r
109 if (side == SIDE.HORIZ || side == SIDE.VERT) {
\r
112 for (AlignElement e : elements) {
\r
114 if (side == SIDE.VERT)
\r
115 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],mx,e.transform[5]});
\r
116 else if (side == SIDE.HORIZ) {
\r
117 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],e.transform[4],my});
\r
123 lx = elements.get(0).transform[4] + elements.get(0).rotatedBounds.getMinX();
\r
124 rx = elements.get(0).transform[4] + elements.get(0).rotatedBounds.getMaxX();
\r
126 ty = elements.get(0).transform[5] + elements.get(0).rotatedBounds.getMinY();
\r
127 by = elements.get(0).transform[5] + elements.get(0).rotatedBounds.getMaxY();
\r
129 for (int i = 1; i < elements.size(); i++) {
\r
132 tlx = elements.get(i).transform[4] + elements.get(i).rotatedBounds.getMinX();
\r
133 trx = elements.get(i).transform[4] + elements.get(i).rotatedBounds.getMaxX();
\r
135 tty = elements.get(i).transform[5] + elements.get(i).rotatedBounds.getMinY();
\r
136 tby = elements.get(i).transform[5] + elements.get(i).rotatedBounds.getMaxY();
\r
148 for (AlignElement e : elements) {
\r
149 mx = e.transform[4];
\r
150 my = e.transform[5];
\r
151 if (side == SIDE.LEFT) {
\r
152 mx = lx - e.rotatedBounds.getMinX() ;
\r
153 } else if (side == SIDE.RIGHT) {
\r
154 mx = rx - e.rotatedBounds.getMaxX();
\r
155 } else if (side == SIDE.TOP) {
\r
156 my = ty - e.rotatedBounds.getMinY();
\r
158 my = by - e.rotatedBounds.getMaxY();
\r
160 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],mx,my});
\r
171 * Distance specified set of diagram element resources equally. Distancing
\r
172 * is performed on the specified side of the each element.
\r
175 * Distancing requires at least three elements to work.
\r
177 * @param resources diagram element resources to rotate
\r
178 * @param side the side of each element to use for distancing
\r
180 public static void dist(final Resource resources[], final SIDE side) {
\r
182 if (resources.length < 3)
\r
185 SimanticsUI.getSession().asyncRequest(new WriteRequest() {
\r
188 public void perform(WriteGraph graph) throws DatabaseException {
\r
189 graph.markUndoPoint();
\r
190 IDiagram hints = Diagram.spawnNew(DiagramClass.DEFAULT);
\r
192 List<AlignElement> elements = new ArrayList<AlignElement>();
\r
193 for (Resource r : resources) {
\r
194 //System.out.println(r + " " + GraphUtils.getReadableName(graph, r));
\r
195 AlignElement e = create(graph, hints, r);
\r
199 if (elements.size() < 3)
\r
203 Collections.sort(elements, new XComparator());
\r
204 AlignElement left = elements.get(0);
\r
205 AlignElement right = elements.get(elements.size() - 1);
\r
207 double leftEdge = left.transform[4] + left.rotatedBounds.getMinX();
\r
208 double rightEdge = right.transform[4] + right.rotatedBounds.getMinX();
\r
210 double totalDist = rightEdge - leftEdge;
\r
211 double dist = totalDist / (elements.size() - 1);
\r
212 double d = leftEdge;
\r
214 for (int i = 1; i < elements.size() -1; i++) {
\r
216 AlignElement e = elements.get(i);
\r
218 double mx = d - e.rotatedBounds.getMinX();
\r
220 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],mx,e.transform[5]});
\r
226 Collections.sort(elements, new XComparator());
\r
227 AlignElement left = elements.get(0);
\r
228 AlignElement right = elements.get(elements.size() - 1);
\r
230 double leftEdge = left.transform[4];
\r
231 double rightEdge = right.transform[4];
\r
233 double totalDist = rightEdge - leftEdge;
\r
234 double dist = totalDist / (elements.size() - 1);
\r
235 double d = leftEdge;
\r
237 for (int i = 1; i < elements.size() -1; i++) {
\r
239 AlignElement e = elements.get(i);
\r
243 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],mx,e.transform[5]});
\r
249 Collections.sort(elements, new XComparator());
\r
250 AlignElement left = elements.get(0);
\r
251 AlignElement right = elements.get(elements.size() - 1);
\r
253 double leftEdge = left.transform[4] + left.rotatedBounds.getMaxX();
\r
254 double rightEdge = right.transform[4] + right.rotatedBounds.getMaxX();
\r
256 double totalDist = rightEdge - leftEdge;
\r
257 double dist = totalDist / (elements.size() - 1);
\r
258 double d = leftEdge;
\r
260 for (int i = 1; i < elements.size() -1; i++) {
\r
262 AlignElement e = elements.get(i);
\r
264 double mx = d - e.rotatedBounds.getMaxX();
\r
266 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],mx,e.transform[5]});
\r
271 Collections.sort(elements, new XComparator());
\r
272 AlignElement left = elements.get(0);
\r
273 AlignElement right = elements.get(elements.size() - 1);
\r
275 double leftEdge = left.transform[4] + left.rotatedBounds.getMaxX();
\r
276 double rightEdge = right.transform[4] + right.rotatedBounds.getMinX();
\r
278 double totalDist = rightEdge - leftEdge;
\r
279 double totalElementSize = 0;
\r
280 for (int i = 1; i < elements.size() -1; i++) {
\r
281 totalElementSize += elements.get(i).rotatedBounds.getWidth();
\r
283 double totalAvail = totalDist - totalElementSize;
\r
284 double dist = totalAvail / (elements.size() - 1);
\r
285 double d = leftEdge;
\r
287 for (int i = 1; i < elements.size() -1; i++) {
\r
289 AlignElement e = elements.get(i);
\r
291 double mx = d - e.rotatedBounds.getMinX();
\r
292 d += e.bounds.getWidth();
\r
294 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],mx,e.transform[5]});
\r
300 Collections.sort(elements, new YComparator());
\r
301 AlignElement top = elements.get(0);
\r
302 AlignElement bottom = elements.get(elements.size() - 1);
\r
304 double topEdge = top.transform[5] + top.rotatedBounds.getMaxY();
\r
305 double bottomEdge = bottom.transform[5] + bottom.rotatedBounds.getMaxY();
\r
307 double totalDist = bottomEdge - topEdge;
\r
308 double dist = totalDist / (elements.size() - 1);
\r
309 double d = topEdge;
\r
311 for (int i = 1; i < elements.size() -1; i++) {
\r
313 AlignElement e = elements.get(i);
\r
315 double my = d - e.rotatedBounds.getMaxY();
\r
317 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],e.transform[4],my});
\r
323 Collections.sort(elements, new YComparator());
\r
324 AlignElement top = elements.get(0);
\r
325 AlignElement bottom = elements.get(elements.size() - 1);
\r
327 double topEdge = top.transform[5] + top.rotatedBounds.getMinY();
\r
328 double bottomEdge = bottom.transform[5] + bottom.rotatedBounds.getMinY();
\r
330 double totalDist = bottomEdge - topEdge;
\r
331 double dist = totalDist / (elements.size() - 1);
\r
332 double d = topEdge;
\r
334 for (int i = 1; i < elements.size() -1; i++) {
\r
336 AlignElement e = elements.get(i);
\r
338 double my = d - e.rotatedBounds.getMinY();
\r
340 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],e.transform[4],my});
\r
346 Collections.sort(elements, new YComparator());
\r
347 AlignElement top = elements.get(0);
\r
348 AlignElement bottom = elements.get(elements.size() - 1);
\r
350 double topEdge = top.transform[5];
\r
351 double bottomEdge = bottom.transform[5];
\r
353 double totalDist = bottomEdge - topEdge;
\r
354 double dist = totalDist / (elements.size() - 1);
\r
355 double d = topEdge;
\r
357 for (int i = 1; i < elements.size() -1; i++) {
\r
359 AlignElement e = elements.get(i);
\r
363 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],e.transform[4],my});
\r
369 Collections.sort(elements, new YComparator());
\r
370 AlignElement top = elements.get(0);
\r
371 AlignElement bottom = elements.get(elements.size() - 1);
\r
373 double topEdge = top.transform[5] + top.rotatedBounds.getMaxY();
\r
374 double bottomEdge = bottom.transform[5] + bottom.rotatedBounds.getMinY();
\r
376 double totalDist = bottomEdge - topEdge;
\r
377 double totalElementSize = 0;
\r
378 for (int i = 1; i < elements.size() -1; i++) {
\r
379 totalElementSize += elements.get(i).rotatedBounds.getHeight();
\r
381 double totalAvail = totalDist - totalElementSize;
\r
382 double dist = totalAvail / (elements.size() - 1);
\r
383 double d = topEdge;
\r
385 for (int i = 1; i < elements.size() -1; i++) {
\r
387 AlignElement e = elements.get(i);
\r
389 double my = d - e.rotatedBounds.getMinY();
\r
390 d += e.rotatedBounds.getHeight();
\r
392 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{e.transform[0],e.transform[1],e.transform[2],e.transform[3],e.transform[4],my});
\r
407 * Rotate specified set of diagram element resources around the center of
\r
408 * mass of the specified element selection.
\r
410 * @param resources diagram element resources to rotate
\r
411 * @param clockwise <code>true</code> to rotate 90 degrees clockwise,
\r
412 * <code>false</code> to rotate 90 degrees counter-clockwise
\r
414 public static void rotate(final Resource resources[], final boolean clockwise) {
\r
415 SimanticsUI.getSession().asyncRequest(new WriteRequest() {
\r
417 public void perform(WriteGraph graph) throws DatabaseException {
\r
418 graph.markUndoPoint();
\r
419 IDiagram hints = Diagram.spawnNew(DiagramClass.DEFAULT);
\r
421 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
423 List<AlignElement> elements = new ArrayList<AlignElement>();
\r
424 List<Resource> connections = new ArrayList<Resource>();
\r
425 for (Resource r : resources) {
\r
426 AlignElement e = create(graph, hints, r);
\r
429 else if(graph.isInstanceOf(r, DIA.RouteGraphConnection))
\r
430 connections.add(r);
\r
432 if (elements.size() < 1)
\r
435 // Add comment to change set.
\r
436 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
\r
437 graph.addMetadata( cm.add("Rotate " + elements.size() + " elements " + (clockwise ? "clockwise" : "counter-clockwise")) );
\r
439 AffineTransform at = clockwise ? AffineTransform.getQuadrantRotateInstance(1)
\r
440 : AffineTransform.getQuadrantRotateInstance(3);
\r
442 if (elements.size() == 1 && connections.isEmpty()) {
\r
443 for (AlignElement e : elements) {
\r
444 AffineTransform eat = new AffineTransform(e.transform[0], e.transform[1], e.transform[2], e.transform[3], 0, 0);
\r
445 eat.preConcatenate(at);
\r
447 DiagramGraphUtil.changeTransform(graph, e.element,
\r
448 new double[]{eat.getScaleX(),eat.getShearY(),eat.getShearX(),eat.getScaleY(),e.transform[4],e.transform[5]});
\r
451 Rectangle2D selectionBounds = null;
\r
452 for (AlignElement e : elements) {
\r
453 if (selectionBounds != null) {
\r
454 selectionBounds.add(e.transform[4], e.transform[5]);
\r
456 selectionBounds = new Rectangle2D.Double(e.transform[4], e.transform[5], 0, 0);
\r
460 double cx = selectionBounds.getCenterX();
\r
461 double cy = selectionBounds.getCenterY();
\r
463 for (AlignElement e : elements) {
\r
464 double x = e.transform[4];
\r
465 double y = e.transform[5];
\r
466 double dx = x - cx;
\r
467 double dy = y - cy;
\r
468 Point2D r = at.transform(new Point2D.Double(dx, dy), null);
\r
469 double mx = r.getX() + cx;
\r
470 double my = r.getY() + cy;
\r
471 AffineTransform eat = new AffineTransform(e.transform[0], e.transform[1], e.transform[2], e.transform[3], 0, 0);
\r
472 eat.preConcatenate(at);
\r
474 DiagramGraphUtil.changeTransform(graph, e.element,
\r
475 new double[]{eat.getScaleX(),eat.getShearY(),eat.getShearX(),eat.getScaleY(),mx,my});
\r
478 if(!connections.isEmpty()) {
\r
479 Command rotateConnection = Commands.get(graph, "Simantics/Diagram/rotateConnection");
\r
480 Resource model = graph.syncRequest(new IndexRoot(connections.get(0)));
\r
481 for(Resource r : connections)
\r
482 rotateConnection.execute(graph, model, r, cx, cy, clockwise);
\r
490 * Flip specified set of diagram element resources around either the x or
\r
491 * y-axis specified by the mass center of the selection bounding box.
\r
492 * Each element is considered to weigh an equal amount.
\r
494 * @param resources diagram element resources to flip
\r
495 * @param xAxis <code>true</code> to flip around x-axis, <code>false</code>
\r
498 public static void flip(final Resource resources[], final boolean xAxis) {
\r
499 SimanticsUI.getSession().asyncRequest(new WriteRequest() {
\r
501 public void perform(WriteGraph graph) throws DatabaseException {
\r
502 graph.markUndoPoint();
\r
503 IDiagram hints = Diagram.spawnNew(DiagramClass.DEFAULT);
\r
505 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
507 List<AlignElement> elements = new ArrayList<AlignElement>();
\r
508 List<Resource> connections = new ArrayList<Resource>();
\r
509 for (Resource r : resources) {
\r
510 AlignElement e = create(graph, hints, r);
\r
513 else if(graph.isInstanceOf(r, DIA.RouteGraphConnection))
\r
514 connections.add(r);
\r
516 if (elements.size() < 1)
\r
519 // Add comment to change set.
\r
520 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
\r
521 graph.addMetadata( cm.add("Flip " + elements.size() + " elements " + (xAxis ? "vertically" : "horizontally")) );
\r
523 if (elements.size() == 1 && connections.isEmpty()) {
\r
524 for (AlignElement e : elements) {
\r
526 AffineTransform at = new AffineTransform(e.transform);
\r
527 AffineTransform at2 = AffineTransform.getScaleInstance(1, -1);
\r
528 at.preConcatenate(at2);
\r
529 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{at.getScaleX(),at.getShearY(),at.getShearX(),at.getScaleY(),e.transform[4],e.transform[5]});
\r
531 AffineTransform at = new AffineTransform(e.transform);
\r
532 AffineTransform at2 = AffineTransform.getScaleInstance(-1, 1);
\r
533 at.preConcatenate(at2);
\r
534 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{at.getScaleX(),at.getShearY(),at.getShearX(),at.getScaleY(),e.transform[4],e.transform[5]});
\r
539 Rectangle2D selectionBounds = null;
\r
540 for (AlignElement e : elements) {
\r
541 if (selectionBounds != null) {
\r
542 selectionBounds.add(e.transform[4], e.transform[5]);
\r
544 selectionBounds = new Rectangle2D.Double(e.transform[4], e.transform[5], 0, 0);
\r
548 for (AlignElement e : elements) {
\r
550 double y = e.transform[5];
\r
551 double cy = selectionBounds.getCenterY();
\r
552 double my = cy + cy - y;
\r
553 AffineTransform at = new AffineTransform(e.transform);
\r
554 AffineTransform at2 = AffineTransform.getScaleInstance(1, -1);
\r
555 at.preConcatenate(at2);
\r
556 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{at.getScaleX(),at.getShearY(),at.getShearX(),at.getScaleY(),e.transform[4],my});
\r
558 double x = e.transform[4];
\r
559 double cx = selectionBounds.getCenterX();
\r
560 double mx = cx + cx - x;
\r
562 AffineTransform at = new AffineTransform(e.transform);
\r
563 AffineTransform at2 = AffineTransform.getScaleInstance(-1, 1);
\r
564 at.preConcatenate(at2);
\r
565 DiagramGraphUtil.changeTransform(graph, e.element, new double[]{at.getScaleX(),at.getShearY(),at.getShearX(),at.getScaleY(),mx,e.transform[5]});
\r
569 if(!connections.isEmpty()) {
\r
570 Command flipConnection = Commands.get(graph, "Simantics/Diagram/flipConnection");
\r
571 Resource model = graph.syncRequest(new IndexRoot(connections.get(0)));
\r
572 for(Resource r : connections)
\r
573 flipConnection.execute(graph, model, r, xAxis,
\r
574 xAxis ? selectionBounds.getCenterY()
\r
575 : selectionBounds.getCenterX());
\r
583 private static AlignElement create(ReadGraph graph, IDiagram hints, Resource r) throws ManyObjectsForFunctionalRelationException, NoSingleResultException, ServiceException, DatabaseException {
\r
584 DiagramResource dr = DiagramResource.getInstance(graph);
\r
586 if (graph.isInstanceOf(r, dr.Element) && !graph.isInstanceOf(r, dr.Connection) /*&& !graph.isInstanceOf(r, dr.Monitor)*/) {
\r
587 double transform[] = graph.getPossibleRelatedValue(r, dr.HasTransform);
\r
588 ElementClass ec = graph.syncRequest(DiagramRequests.getElementClass(graph.getSingleType(r, dr.Element), hints));
\r
589 IElement e = Element.spawnNew(ec);
\r
590 Rectangle2D bounds = ElementUtils.getElementBounds(e);
\r
591 if (transform != null && bounds != null) {
\r
592 return new AlignElement(r, transform, bounds);
\r
599 private static class AlignElement {
\r
600 public Resource element;
\r
601 public double[] transform;
\r
602 public Rectangle2D bounds;
\r
603 public Rectangle2D rotatedBounds;
\r
604 // public Rectangle2D transformedBounds;
\r
606 public AlignElement(Resource element, double[] transform, Rectangle2D bounds) {
\r
607 this.element = element;
\r
608 this.transform = transform;
\r
609 this.bounds = bounds;
\r
610 // this.transformedBounds = getBounds();
\r
611 this.rotatedBounds = getRotatedBounds();
\r
614 // public Rectangle2D getBounds() {
\r
615 // AffineTransform at = new AffineTransform(transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]);
\r
616 // return GeometryUtils.transformShape(bounds, at).getBounds2D();
\r
619 public Rectangle2D getRotatedBounds() {
\r
620 AffineTransform at = new AffineTransform(transform[0], transform[1], transform[2], transform[3], 0.0, 0.0);
\r
621 return GeometryUtils.transformShape(bounds, at).getBounds2D();
\r
624 public double getDeterminant() {
\r
625 return transform[0] * transform[3] - transform[1] * transform[2];
\r
630 private static class XComparator implements Comparator<AlignElement> {
\r
632 public int compare(AlignElement o1, AlignElement o2) {
\r
633 if (o1.transform[4] < o2.transform[4])
\r
635 if (o1.transform[4] > o2.transform[4])
\r
642 private static class YComparator implements Comparator<AlignElement> {
\r
644 public int compare(AlignElement o1, AlignElement o2) {
\r
645 if (o1.transform[5] < o2.transform[5])
\r
647 if (o1.transform[5] > o2.transform[5])
\r
655 * Set 2D affine transforms for the listed diagram element resources.
\r
657 * @param elements diagram element resources to set transforms for
\r
658 * @param transforms transforms for each element
\r
660 public static Write setTransformRequest(final Collection<TransformedObject> elements)
\r
662 return new WriteRequest() {
\r
664 public void perform(WriteGraph graph) throws DatabaseException {
\r
665 for (TransformedObject element : elements)
\r
666 DiagramGraphUtil.changeTransform(graph, element.element, element.transform);
\r
672 * Set 2D affine transforms for the listed diagram element resources.
\r
674 * @param undoContext the database undo context to use for the returned
\r
676 * @param elements diagram element resources to set transforms for
\r
677 * @param transforms transforms for each element
\r
678 * @param preConcatenate <code>true</code> to pre-concatenate the
\r
679 * transforms, <code>false</code> to concatenate
\r
681 public static Write concatenateTransformRequest(
\r
682 UndoContext undoContext,
\r
683 final Collection<TransformedObject> elements,
\r
684 final boolean preConcatenate)
\r
686 return new WriteRequest() {
\r
688 public void perform(WriteGraph graph) throws DatabaseException {
\r
689 for (TransformedObject element : elements) {
\r
690 AffineTransform at = DiagramGraphUtil.getTransform(graph, element.element);
\r
691 if (preConcatenate)
\r
692 at.preConcatenate(element.transform);
\r
694 at.concatenate(element.transform);
\r
695 DiagramGraphUtil.setTransform(graph, element.element, at);
\r
701 public static class TransformedObject {
\r
702 public final Resource element;
\r
703 public final AffineTransform transform;
\r
705 public TransformedObject(Resource element) {
\r
706 this.element = element;
\r
707 this.transform = new AffineTransform();
\r
709 public TransformedObject(Resource element, AffineTransform transform) {
\r
710 this.element = element;
\r
711 this.transform = transform;
\r