📄 newobjectdiagram.java
字号:
/* * USE - UML based specification environment * Copyright (C) 1999-2004 Mark Richters, University of Bremen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* $ProjectHeader: use 2-3-0-release.1 Mon, 12 Sep 2005 20:18:33 +0200 green $ */package org.tzi.use.gui.views.diagrams.objectdiagram;import java.awt.Color;import java.awt.Dimension;import java.awt.Font;import java.awt.Graphics;import java.awt.Point;import java.awt.datatransfer.DataFlavor;import java.awt.datatransfer.Transferable;import java.awt.datatransfer.UnsupportedFlavorException;import java.awt.dnd.DnDConstants;import java.awt.dnd.DropTargetDropEvent;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.ComponentAdapter;import java.awt.event.ComponentEvent;import java.awt.event.MouseEvent;import java.io.IOException;import java.io.PrintWriter;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import javax.swing.AbstractAction;import javax.swing.BorderFactory;import javax.swing.Box;import javax.swing.JComponent;import javax.swing.JLabel;import javax.swing.JMenuItem;import javax.swing.JPanel;import javax.swing.JPopupMenu;import javax.swing.JSeparator;import javax.swing.JWindow;import javax.swing.SwingUtilities;import javax.swing.border.Border;import org.tzi.use.graph.DirectedGraphBase;import org.tzi.use.gui.util.Selection;import org.tzi.use.gui.views.diagrams.BinaryEdge;import org.tzi.use.gui.views.diagrams.DiagramView;import org.tzi.use.gui.views.diagrams.DiamondNode;import org.tzi.use.gui.views.diagrams.EdgeBase;import org.tzi.use.gui.views.diagrams.HalfEdge;import org.tzi.use.gui.views.diagrams.LayoutInfos;import org.tzi.use.gui.views.diagrams.NodeBase;import org.tzi.use.gui.views.diagrams.NodeEdge;import org.tzi.use.gui.views.diagrams.PlaceableNode;import org.tzi.use.gui.views.diagrams.event.ActionLoadLayout;import org.tzi.use.gui.views.diagrams.event.ActionSaveLayout;import org.tzi.use.gui.views.diagrams.event.DiagramMouseHandling;import org.tzi.use.gui.views.diagrams.event.HideAdministration;import org.tzi.use.gui.views.diagrams.event.HighlightChangeEvent;import org.tzi.use.gui.views.diagrams.event.HighlightChangeListener;import org.tzi.use.uml.mm.MAssociation;import org.tzi.use.uml.mm.MAssociationClass;import org.tzi.use.uml.mm.MAttribute;import org.tzi.use.uml.mm.MClass;import org.tzi.use.uml.mm.MModelElement;import org.tzi.use.uml.ocl.value.Value;import org.tzi.use.uml.sys.MLink;import org.tzi.use.uml.sys.MLinkEnd;import org.tzi.use.uml.sys.MLinkObject;import org.tzi.use.uml.sys.MObject;import org.tzi.use.uml.sys.MObjectState;import org.tzi.use.util.Log;/** * A panel drawing UML object diagrams. * * @version $ProjectVersion: 2-3-0-release.1 $ * @author Mark Richters */public class NewObjectDiagram extends DiagramView implements HighlightChangeListener{ private Map fObjectToNodeMap; // (MObject -> ObjectNode) private Map fBinaryLinkToEdgeMap; // (MLink -> BinaryLinkEdge) private Map fNaryLinkToDiamondNodeMap; // (MLink -> DiamondNode) private Map fHalfLinkToEdgeMap; // (MLink -> List(HalfEdge)) private Map fLinkObjectToNodeEdge; // (MLinkObject -> NodeEdge) private NewObjectDiagramView fParent; private double fNextNodeX; private double fNextNodeY; /** * Creates a new empty diagram. */ NewObjectDiagram(NewObjectDiagramView parent, PrintWriter log) { fOpt = new ObjDiagramOptions(); fGraph = new DirectedGraphBase(); fObjectToNodeMap = new HashMap(); fBinaryLinkToEdgeMap = new HashMap(); fNaryLinkToDiamondNodeMap = new HashMap(); fHalfLinkToEdgeMap = new HashMap(); fLinkObjectToNodeEdge = new HashMap(); fHiddenNodes = new HashSet(); fHiddenEdges = new HashSet(); fParent = parent; fNodeSelection = new Selection(); fEdgeSelection = new Selection(); fLog = log; fLayoutInfos = new LayoutInfos( fBinaryLinkToEdgeMap, fObjectToNodeMap, fNaryLinkToDiamondNodeMap, fHalfLinkToEdgeMap, fLinkObjectToNodeEdge, null, null, fHiddenNodes, fHiddenEdges, fOpt, fParent.system(), this ); fHideAdmin = new HideAdministration( fNodeSelection, fGraph, fLayoutInfos ); fActionSaveLayout = new ActionSaveLayout( "USE object diagram layout", "olt", fGraph, fLog, fLayoutInfos ); fActionLoadLayout = new ActionLoadLayout( "USE object diagram layout", "olt", this, fLog, fHideAdmin, fGraph, fLayoutInfos ); DiagramMouseHandling mouseHandling = new DiagramMouseHandling( fNodeSelection, fEdgeSelection, fGraph, fHideAdmin, fHiddenNodes, fOpt, this); fParent.getModelBrowser().addHighlightChangeListener( this ); setLayout(null); setBackground(Color.white); setPreferredSize(new Dimension(400, 400)); addMouseListener(mouseHandling); addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { // need a new layouter to adapt to new window size fLayouter = null; } }); startLayoutThread(); } /** * Displays objects of the selected class in the modelbrowser. */ public void stateChanged( HighlightChangeEvent e ) { if ( !fParent.isSelectedView() ) { return; } MModelElement elem = e.getModelElement(); List edges = new ArrayList(); boolean allEdgesSelected = true; // elem is an association if ( elem != null && elem instanceof MAssociation ) { int size = ((MAssociation) elem).associationEnds().size(); Set links = fParent.system().state().linksOfAssociation( (MAssociation) elem ).links(); EdgeBase eb = null; if ( size == 2 ) { Iterator it = links.iterator(); while ( it.hasNext() ) { MLink link = (MLink) it.next(); eb = (EdgeBase) fBinaryLinkToEdgeMap.get( link ); if ( elem instanceof MAssociationClass ) { eb = (EdgeBase) fLinkObjectToNodeEdge.get( (MLinkObject) link ); } edges.add( eb ); } } else { Iterator it = links.iterator(); while ( it.hasNext() ) { MLink link = (MLink) it.next(); Iterator itLinkEnd = link.linkEnds().iterator(); while ( itLinkEnd.hasNext() ) { MLinkEnd lEnd = (MLinkEnd) itLinkEnd.next(); eb = (EdgeBase) fHalfLinkToEdgeMap.get( lEnd ); edges.add( eb ); } if ( elem instanceof MAssociationClass ) { eb = (EdgeBase) fLinkObjectToNodeEdge.get( (MLinkObject) link ); if ( !edges.contains( eb ) ) { edges.add( eb ); } } } } // check all edges in the list if they are suppose to be selected // or deselected. Iterator it = edges.iterator(); while ( it.hasNext() ) { EdgeBase edge = (EdgeBase) it.next(); if ( edge != null ) { if ( e.getHighlight() ) { fEdgeSelection.add( edge ); allEdgesSelected = true; } else { fEdgeSelection.remove( edge ); allEdgesSelected = false; } } } } // elem is a class if ( elem != null && elem instanceof MClass ) { Iterator it = fParent.system().state().objectsOfClass( (MClass) elem ).iterator(); while ( it.hasNext() ) { MObject obj = (MObject) it.next(); NodeBase node = (NodeBase) fObjectToNodeMap.get( obj ); if ( elem instanceof MAssociationClass ) { if ( e.getHighlight() && allEdgesSelected ) { fNodeSelection.add( node ); } else { fNodeSelection.remove( node ); } } else { if ( e.getHighlight() ) { fNodeSelection.add( node ); } else { fNodeSelection.remove( node ); } } } } repaint(); } /** * Determinds if the auto layout of the diagram is on or off. * @return <code>true</code> if the auto layout is on, otherwise * <code>false</code> */ public boolean isDoAutoLayout() { return fOpt.isDoAutoLayout(); } /** * Draws the diagram. */ public void paintComponent(Graphics g) { synchronized (fLock) { Font f = Font.getFont("use.gui.view.objectdiagram", getFont()); g.setFont(f); drawDiagram(g); //drawDiagram(g); } } /** * Adds an object to the diagram. */ public void addObject(MObject obj) { // Find a random new position. getWidth and getheight return 0 // if we are called on a new diagram.// if ( isDoAutoLayout() ) {// fNextNodeX = Math.random() * Math.max(100, getWidth());// fNextNodeY = Math.random() * Math.max(100, getHeight());// }// ObjectNode n = new ObjectNode( obj, fParent, fOpt); n.setPosition( fNextNodeX, fNextNodeY ); synchronized (fLock) { fGraph.add(n); fObjectToNodeMap.put(obj, n); fLayouter = null; } } /** * Deletes an object from the diagram. */ public void deleteObject(MObject obj) { ObjectNode n = (ObjectNode) fObjectToNodeMap.get(obj); if (n == null) { if ( fHiddenNodes.contains(obj) ) { fHiddenNodes.remove(obj); fLog.println("Deleted object `" + obj + "' from the hidden objects."); } else { throw new RuntimeException("no node for object `" + obj + "' in current state."); } } synchronized (fLock) { fGraph.remove(n); fObjectToNodeMap.remove(obj); fLayouter = null; } } /** * Adds a link to the diagram. */ public void addLink(MLink link) { String label = link.association().name(); Iterator linkEndIter = link.linkEnds().iterator(); MLinkEnd linkEnd1 = (MLinkEnd) linkEndIter.next(); MLinkEnd linkEnd2 = (MLinkEnd) linkEndIter.next(); MObject obj1 = linkEnd1.object(); MObject obj2 = linkEnd2.object(); if (link.linkEnds().size() == 2) { // object link if (link instanceof MObject) { NodeEdge e = new NodeEdge(label, fObjectToNodeMap.get(obj1), fObjectToNodeMap.get(obj2), linkEnd1.associationEnd(), linkEnd2.associationEnd(), link, (NodeBase) fObjectToNodeMap.get(link), this, link.association() ); synchronized (fLock) { fGraph.addEdge(e); fLinkObjectToNodeEdge.put(link, e); fLayouter = null; } } else { // binary link BinaryEdge e = new BinaryEdge( label, fObjectToNodeMap.get(obj1), fObjectToNodeMap.get(obj2), linkEnd1.associationEnd(), linkEnd2.associationEnd(), this, link.association() ); synchronized (fLock) { fGraph.addEdge(e); fBinaryLinkToEdgeMap.put(link, e); fLayouter = null; } } } else synchronized (fLock) { // Find a random new position. getWidth and getheight return 0 // if we are called on a new diagram. double fNextNodeX = Math.random() * Math.max(100, getWidth()); double fNextNodeY = Math.random() * Math.max(100, getHeight()); // n-ary link: create a diamond node and n edges to objects DiamondNode node = new DiamondNode( link, fOpt ); node.setPosition( fNextNodeX, fNextNodeY ); fGraph.add(node); // connected to an "object link" if (link instanceof MObject) { NodeEdge e = new NodeEdge(label, fObjectToNodeMap.get(obj1), fObjectToNodeMap.get(obj2), node, (ObjectNode) fObjectToNodeMap.get(link), this, link.association() ); synchronized (fLock) { fGraph.addEdge(e); fLinkObjectToNodeEdge.put(link, e); fLayouter = null; } } // connected to a "normal" link fNaryLinkToDiamondNodeMap.put(link, node); List halfEdges = new ArrayList(); linkEndIter = link.linkEnds().iterator(); while (linkEndIter.hasNext()) { MLinkEnd linkEnd = (MLinkEnd) linkEndIter.next(); MObject obj = linkEnd.object(); HalfEdge e = new HalfEdge( node, (NodeBase) fObjectToNodeMap.get(obj), linkEnd.associationEnd().name(),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -