📄 newclassdiagram.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.classdiagram;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
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.JCheckBoxMenuItem;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
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.GeneralizationEdge;
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.MAssociationEnd;
import org.tzi.use.uml.mm.MClass;
import org.tzi.use.uml.mm.MGeneralization;
import org.tzi.use.uml.mm.MModelElement;
import org.tzi.use.uml.ocl.type.EnumType;
/**
* A panel drawing UML class diagrams.
*
* @version $ProjectVersion: 2-3-0-release.1 $
* @author Fabian Gutsche
*/
public class NewClassDiagram extends DiagramView
implements HighlightChangeListener {
private NewClassDiagramView fParent;
private Map fClassToNodeMap; // (MClass -> ClassNode)
private Map fEnumToNodeMap; // (EnumType -> EnumNode)
private Map fBinaryAssocToEdgeMap; // (MAssociation -> BinaryAssocEdge)
private Map fAssocClassToEdgeMap; // (MAssociationClass -> ClassNode)
private Map fNaryAssocToDiamondNodeMap; // (MAssociation -> DiamondNode)
private Map fNaryAssocToHalfEdgeMap; // (MAssociation -> List(HalfEdge))
private Map fGenToGeneralizationEdge; // (MGeneralization -> GeneralizationEdge)
NewClassDiagram( NewClassDiagramView parent, PrintWriter log ) {
fOpt = new ClsDiagramOptions();
fGraph = new DirectedGraphBase();
fClassToNodeMap = new HashMap();
fEnumToNodeMap = new HashMap();
fBinaryAssocToEdgeMap = new HashMap();
fAssocClassToEdgeMap = new HashMap();
fNaryAssocToDiamondNodeMap = new HashMap();
fNaryAssocToHalfEdgeMap = new HashMap();
fGenToGeneralizationEdge = new HashMap();
fParent = parent;
fHiddenNodes = new HashSet();
fHiddenEdges = new HashSet();
fNodeSelection = new Selection();
fEdgeSelection = new Selection();
setLayout( null );
setBackground( Color.white );
fLog = log;
setPreferredSize( new Dimension( 400, 400 ) );
fLayoutInfos = new LayoutInfos( fBinaryAssocToEdgeMap,
fClassToNodeMap,
fNaryAssocToDiamondNodeMap,
fNaryAssocToHalfEdgeMap,
fAssocClassToEdgeMap,
fEnumToNodeMap,
fGenToGeneralizationEdge,
fHiddenNodes, fHiddenEdges,
fOpt, fParent.system(), this );
fHideAdmin = new HideAdministration( fNodeSelection, fGraph, fLayoutInfos );
fActionSaveLayout = new ActionSaveLayout( "USE class diagram layout",
"clt", fGraph, fLog, fLayoutInfos );
fActionLoadLayout = new ActionLoadLayout( "USE class diagram layout",
"clt", this, fLog,
fHideAdmin, fGraph,
fLayoutInfos );
DiagramMouseHandling mouseHandling =
new DiagramMouseHandling( fNodeSelection, fEdgeSelection,
fGraph, fHideAdmin, fHiddenNodes,
fOpt, this);
addMouseListener( mouseHandling );
fParent.getModelBrowser().addHighlightChangeListener( this );
addComponentListener( new ComponentAdapter() {
public void componentResized( ComponentEvent e ) {
// need a new layouter to adapt to new window size
fLayouter = null;
}
} );
startLayoutThread();
}
/**
* Displays the selected class of the modelbrowser in the class diagram.
*/
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();
EdgeBase eb = null;
if ( size == 2 ) {
eb = (EdgeBase) fBinaryAssocToEdgeMap.get( (MAssociation) elem );
if ( elem instanceof MAssociationClass ) {
eb = (EdgeBase) fAssocClassToEdgeMap.get( (MAssociationClass) elem );
}
edges.add( eb );
} else {
List halfEdges =
(List) fNaryAssocToHalfEdgeMap.get( (MAssociation) elem );
if ( edges != null && halfEdges != null ) {
edges.addAll( halfEdges );
}
if ( elem instanceof MAssociationClass ) {
eb = (EdgeBase) fAssocClassToEdgeMap.get( (MAssociationClass) elem );
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 ( fEdgeSelection.isSelected( edge ) ) {
fEdgeSelection.remove( edge );
allEdgesSelected = true;
} else {
fEdgeSelection.add( edge );
allEdgesSelected = false;
}
}
}
}
// elem is a class
if ( elem != null && elem instanceof MClass ) {
NodeBase node = (NodeBase) fClassToNodeMap.get( (MClass) elem );
if ( node != null ) {
if ( elem instanceof MAssociationClass ) {
if ( fNodeSelection.isSelected( node ) && allEdgesSelected ) {
fNodeSelection.remove( node );
} else {
fNodeSelection.add( node );
}
} else {
if ( fNodeSelection.isSelected( node ) ) {
fNodeSelection.remove( node );
} else {
fNodeSelection.add( 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 );
}
}
/**
* Adds a class to the diagram.
*
* @param cls Class to be added.
*/
public void addClass( MClass cls ) {
// 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() );
ClassNode n = new ClassNode( cls, fOpt );
n.setPosition( fNextNodeX, fNextNodeY );
synchronized ( fLock ) {
fGraph.add( n );
fClassToNodeMap.put( cls, n );
fLayouter = null;
}
}
/**
* Deletes a class from the diagram.
*/
public void deleteClass( MClass cls ) {
NodeBase n = (NodeBase) fClassToNodeMap.get( cls );
if (n == null) {
if ( fHiddenNodes.contains( cls ) ) {
fHiddenNodes.remove( cls );
fLog.println("Deleted class `" + cls.name()
+ "' from the hidden classes.");
} else {
throw new RuntimeException("no node for class `"
+ cls.name() + "' in current state.");
}
}
synchronized ( fLock ) {
fGraph.remove( n );
fClassToNodeMap.remove( cls );
fLayouter = null;
}
}
/**
* Adds an enumeration to the diagram.
*
* @param enumeration Enumeration to be added.
*/
public void addEnum( EnumType enumeration ) {
// 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() );
EnumNode n = new EnumNode( enumeration, fOpt );
n.setPosition( fNextNodeX, fNextNodeY );
synchronized ( fLock ) {
fGraph.add( n );
fEnumToNodeMap.put( enumeration, n );
fLayouter = null;
}
}
/**
* Deletes an enumeration from the diagram.
*/
public void deleteEnum( EnumType enumeration ) {
NodeBase n = (NodeBase) fEnumToNodeMap.get( enumeration );
if (n == null) {
if ( fHiddenNodes.contains( enumeration ) ) {
fHiddenNodes.remove( enumeration );
fLog.println("Deleted enumeration `" + enumeration.name()
+ "' from the hidden enumerations.");
} else {
throw new RuntimeException("no node for enumeration `"
+ enumeration.name()
+ "' in current state.");
}
}
synchronized ( fLock ) {
fGraph.remove( n );
fEnumToNodeMap.remove( enumeration );
fLayouter = null;
}
}
/**
* Adds an association to the diagram.
*/
public void addAssociation( MAssociation assoc ) {
String label = assoc.name();
Iterator assocEndIter = assoc.associationEnds().iterator();
MAssociationEnd assocEnd1 = (MAssociationEnd) assocEndIter.next();
MAssociationEnd assocEnd2 = (MAssociationEnd) assocEndIter.next();
MClass cls1 = assocEnd1.cls();
MClass cls2 = assocEnd2.cls();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -