/* $Id: ModeAddToDiagram.java 17865 2010-01-12 20:45:26Z linus $ ***************************************************************************** * Copyright (c) 2009 Contributors - see below * 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: * tfmorris ***************************************************************************** * * Some portions of this file was previously release using the BSD License: */ // Copyright (c) 2008 The Regents of the University of California. All // Rights Reserved. Permission to use, copy, modify, and distribute this // software and its documentation without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph appear in all copies. This software program and // documentation are copyrighted by The Regents of the University of // California. The software program and documentation are supplied "AS // IS", without any accompanying services from The Regents. The Regents // does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program // was developed for research purposes and is advised not to rely // exclusively on the program for any reason. IN NO EVENT SHALL THE // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. package org.argouml.uml.diagram.ui; import java.awt.Cursor; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.log4j.Logger; import org.argouml.uml.diagram.ArgoDiagram; import org.argouml.uml.diagram.DiagramUtils; import org.tigris.gef.base.Editor; import org.tigris.gef.base.FigModifyingModeImpl; import org.tigris.gef.base.Layer; import org.tigris.gef.graph.GraphNodeRenderer; import org.tigris.gef.graph.MutableGraphModel; import org.tigris.gef.presentation.Fig; import org.tigris.gef.presentation.FigNode; import org.tigris.gef.undo.Memento; import org.tigris.gef.undo.UndoManager; /** * This is the mode the editor is in having selected a number of model elements * and executing Add To Diagram. */ public class ModeAddToDiagram extends FigModifyingModeImpl { private static final long serialVersionUID = 8861862975789222877L; /** * The nodes to be added. */ private final Collection<Object> modelElements; private final boolean addRelatedEdges = true; private final String instructions; private static final Logger LOG = Logger.getLogger(ModeAddToDiagram.class); /** * Create a mode to add the given elements to the diagram * @param modelElements the model elements to add * @param instructions the instruction to place in status bar */ public ModeAddToDiagram( final Collection<Object> modelElements, final String instructions) { this.modelElements = modelElements; if (instructions == null) { this.instructions = ""; } else { this.instructions = instructions; } } //////////////////////////////////////////////////////////////// // user feedback /** * @return A string to be shown in the status bar of the Editor when this * mode is on top of the ModeManager. */ @Override public String instructions() { return instructions; } /** * @return a cross hair cursor */ public Cursor getInitialCursor() { return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); } /** * On mouse release add the elements to the diagram * @param me the mouse event */ @Override public void mouseReleased(final MouseEvent me) { if (me.isConsumed()) { if (LOG.isDebugEnabled()) { LOG.debug("MouseReleased but rejected as already consumed"); } return; } // TODO: Use per-project undo manager, not global UndoManager.getInstance().addMementoLock(this); start(); MutableGraphModel gm = (MutableGraphModel) editor.getGraphModel(); final int x = me.getX(); final int y = me.getY(); editor.damageAll(); final Point snapPt = new Point(x, y); editor.snap(snapPt); editor.damageAll(); int count = 0; Layer lay = editor.getLayerManager().getActiveLayer(); GraphNodeRenderer renderer = editor.getGraphNodeRenderer(); final List<FigNode> placedFigs = new ArrayList<FigNode>(modelElements.size()); ArgoDiagram diag = DiagramUtils.getActiveDiagram(); if (diag instanceof UMLDiagram) { for (final Object node : modelElements) { if (((UMLDiagram) diag).doesAccept(node)) { final FigNode pers = renderer.getFigNodeFor(gm, lay, node, null); pers.setLocation(snapPt.x + (count++ * 100), snapPt.y); if (LOG.isDebugEnabled()) { LOG.debug("mouseMoved: Location set (" + pers.getX() + "," + pers.getY() + ")"); } // TODO: Use per-project undo manager, not global UndoManager.getInstance().startChain(); editor.add(pers); gm.addNode(node); if (addRelatedEdges) { gm.addNodeRelatedEdges(node); } Fig encloser = null; final Rectangle bbox = pers.getBounds(); final List<Fig> otherFigs = lay.getContents(); for (final Fig otherFig : otherFigs) { if (!(otherFig.getUseTrapRect())) { continue; } if (!(otherFig instanceof FigNode)) { continue; } if (!otherFig.isVisible()) { continue; } if (otherFig.equals(pers)) { continue; } final Rectangle trap = otherFig.getTrapRect(); if (trap != null && trap.contains(bbox.x, bbox.y) && trap.contains( bbox.x + bbox.width, bbox.y + bbox.height)) { encloser = otherFig; } } pers.setEnclosingFig(encloser); placedFigs.add(pers); } } } // TODO: Use per-project undo manager, not global UndoManager.getInstance().removeMementoLock(this); if (UndoManager.getInstance().isGenerateMementos()) { AddToDiagramMemento memento = new AddToDiagramMemento(editor, placedFigs); UndoManager.getInstance().addMemento(memento); } UndoManager.getInstance().addMementoLock(this); editor.getSelectionManager().select(placedFigs); done(); me.consume(); } public void keyTyped(KeyEvent ke) { if (ke.getKeyChar() == KeyEvent.VK_ESCAPE) { LOG.debug("ESC pressed"); leave(); } } } class AddToDiagramMemento extends Memento { private final List<FigNode> nodesPlaced; private final Editor editor; private final MutableGraphModel mgm; AddToDiagramMemento(final Editor ed, final List<FigNode> nodesPlaced) { this.nodesPlaced = nodesPlaced; this.editor = ed; this.mgm = (MutableGraphModel) editor.getGraphModel(); } public void undo() { // TODO: Use per-project undo manager, not global UndoManager.getInstance().addMementoLock(this); for (FigNode figNode : nodesPlaced) { mgm.removeNode(figNode.getOwner()); editor.remove(figNode); } UndoManager.getInstance().removeMementoLock(this); } public void redo() { // TODO: Use per-project undo manager, not global UndoManager.getInstance().addMementoLock(this); for (FigNode figNode : nodesPlaced) { editor.add(figNode); mgm.addNode(figNode.getOwner()); } UndoManager.getInstance().removeMementoLock(this); } public void dispose() { } public String toString() { return (isStartChain() ? "*" : " ") + "AddToDiagramMemento"; } }