More progress. Har!
git-svn-id: https://samskivert.googlecode.com/svn/trunk@185 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// $Id: Driver.java,v 1.1 2001/07/14 00:55:21 mdb Exp $
|
||||
|
||||
package com.samskivert.viztool;
|
||||
|
||||
import com.samskivert.viztool.enum.*;
|
||||
import com.samskivert.viztool.viz.*;
|
||||
|
||||
public class Driver
|
||||
{
|
||||
public static void main (String[] args)
|
||||
{
|
||||
if (args.length < 1) {
|
||||
System.err.println("Usage: Driver package_root");
|
||||
System.exit(-1);
|
||||
}
|
||||
String pkgroot = args[0];
|
||||
|
||||
// run ourselves on the classpath
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
ClassEnumerator enum = new ClassEnumerator(classpath);
|
||||
|
||||
// print out the warnings
|
||||
ClassEnumerator.Warning[] warnings = enum.getWarnings();
|
||||
for (int i = 0; i < warnings.length; i++) {
|
||||
System.err.println("Warning: " + warnings[i].reason);
|
||||
}
|
||||
|
||||
// and finally generate the visualization
|
||||
PackageEnumerator penum = new PackageEnumerator(pkgroot, enum, true);
|
||||
HierarchyVisualizer viz = new HierarchyVisualizer(pkgroot, penum);
|
||||
viz.render(10, System.out);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: CascadingChainVisualizer.java,v 1.1 2001/07/13 23:25:13 mdb Exp $
|
||||
// $Id: CascadingChainVisualizer.java,v 1.2 2001/07/14 00:55:21 mdb Exp $
|
||||
|
||||
package com.samskivert.viztool.viz;
|
||||
|
||||
@@ -40,7 +40,7 @@ public class CascadingChainLayout
|
||||
|
||||
// the children will be below the name of this chain and inset by
|
||||
// four points to make space for the connecty lines
|
||||
int x = GAP, y = hhei;
|
||||
int x = 2*GAP, y = hhei;
|
||||
ArrayList kids = chain.getChildren();
|
||||
|
||||
for (int i = 0; i < kids.size(); i++) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Chain.java,v 1.2 2001/07/13 23:25:13 mdb Exp $
|
||||
// $Id: Chain.java,v 1.3 2001/07/14 00:55:21 mdb Exp $
|
||||
|
||||
package com.samskivert.viztool.viz;
|
||||
|
||||
@@ -16,14 +16,10 @@ public class Chain implements Element
|
||||
/**
|
||||
* Constructs a chain with the specified class as its root.
|
||||
*/
|
||||
public Chain (String pkgroot, Class root)
|
||||
public Chain (String name, Class root)
|
||||
{
|
||||
_pkgroot = pkgroot;
|
||||
_name = name;
|
||||
_root = root;
|
||||
_name = _root.getName();
|
||||
if (_name.startsWith(pkgroot)) {
|
||||
_name = _name.substring(_pkgroot.length()+1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,9 +131,9 @@ public class Chain implements Element
|
||||
* Adds a child to this chain. The specified class is assumed to
|
||||
* directly inherit from the class that is the root of this chain.
|
||||
*/
|
||||
public void addClass (Class child)
|
||||
public void addClass (String name, Class child)
|
||||
{
|
||||
Chain chain = new Chain(_pkgroot, child);
|
||||
Chain chain = new Chain(name, child);
|
||||
if (!_children.contains(chain)) {
|
||||
_children.add(chain);
|
||||
}
|
||||
@@ -192,9 +188,8 @@ public class Chain implements Element
|
||||
}
|
||||
}
|
||||
|
||||
protected String _pkgroot;
|
||||
protected Class _root;
|
||||
protected String _name;
|
||||
protected Class _root;
|
||||
|
||||
protected ArrayList _children = new ArrayList();
|
||||
protected Dimension _size = new Dimension(0, 0);
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// $Id: ChainGroup.java,v 1.1 2001/07/14 00:55:21 mdb Exp $
|
||||
|
||||
package com.samskivert.viztool.viz;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A chain group is used to group together all of the classes from a
|
||||
* particular package.
|
||||
*/
|
||||
public class ChainGroup
|
||||
{
|
||||
/**
|
||||
* Constructs a chain group for a particular package with the
|
||||
* specified package root and an iterator that is configured only to
|
||||
* return classes from the specified package.
|
||||
*/
|
||||
public ChainGroup (String pkgroot, String pkg, Iterator iter)
|
||||
{
|
||||
// keep track of the package
|
||||
_pkg = pkg;
|
||||
|
||||
// process the classes provided by our enumerator
|
||||
_roots = ChainUtil.buildChains(pkgroot, iter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lays out the chains in this group and returns the total size.
|
||||
*/
|
||||
public Dimension layout (int pointSize)
|
||||
{
|
||||
// lay out the internal structure of our chains
|
||||
ChainLayout clay = new CascadingChainLayout();
|
||||
for (int i = 0; i < _roots.size(); i++) {
|
||||
Chain chain = (Chain)_roots.get(i);
|
||||
chain.layout(pointSize, clay);
|
||||
}
|
||||
|
||||
// arrange them on the page
|
||||
ElementLayout elay = new PackedColumnElementLayout();
|
||||
Dimension[] dims = elay.layout(_roots, MAX_WIDTH, MAX_HEIGHT);
|
||||
|
||||
// for now we're punting and assume that no group will exceed a
|
||||
// single page in size
|
||||
_size = new Dimension();
|
||||
_size.width = dims[0].width + 2*BORDER;
|
||||
_size.height = dims[0].height + 2*BORDER;
|
||||
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the chains in this group to the supplied output stream.
|
||||
* This function requires that <code>layoutGroup</code> has previously
|
||||
* been called to lay out the group's chains.
|
||||
*
|
||||
* @return the size of the rectangle occupied by the rendered chain
|
||||
* group.
|
||||
*
|
||||
* @see #layoutGroup
|
||||
*/
|
||||
public void render (int pointSize, PrintStream out, int x, int y)
|
||||
{
|
||||
// render our chains
|
||||
ChainRenderer renderer = new CascadingChainRenderer();
|
||||
for (int i = 0; i < _roots.size(); i++) {
|
||||
Chain chain = (Chain)_roots.get(i);
|
||||
Point loc = chain.getLocation();
|
||||
renderer.renderChain(chain, out, pointSize,
|
||||
x + BORDER, y + BORDER);
|
||||
}
|
||||
|
||||
// print our title and a box around our border
|
||||
out.println("/tname (" + _pkg + ") def");
|
||||
out.println("/twid tname stringwidth pop def");
|
||||
|
||||
int bx = x + BORDER + 2, by = y - pointSize/2;
|
||||
out.println(bx + " " + by + " moveto");
|
||||
out.println("tname abshow");
|
||||
|
||||
out.println((x + BORDER - 2) + " " + y + " moveto");
|
||||
out.println("-" + (BORDER - 2) + " 0 rlineto");
|
||||
out.println("0 " + _size.height + " rlineto");
|
||||
out.println(_size.width + " 0 rlineto");
|
||||
out.println("0 -" + _size.height + " rlineto");
|
||||
out.println((_size.width - BORDER - 4) + " twid sub neg 0 rlineto");
|
||||
out.println("stroke");
|
||||
}
|
||||
|
||||
protected String _pkg;
|
||||
protected ArrayList _roots;
|
||||
protected Dimension _size;
|
||||
|
||||
protected static final int PAGE_WIDTH = (int)(72 * 7.5);
|
||||
protected static final int PAGE_HEIGHT = (int)(72 * 10);
|
||||
|
||||
protected static final int BORDER = 72/8;
|
||||
|
||||
protected static final int MAX_WIDTH = PAGE_WIDTH - 2*BORDER;
|
||||
protected static final int MAX_HEIGHT = PAGE_HEIGHT - 2*BORDER;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: ChainUtil.java,v 1.2 2001/07/13 23:25:13 mdb Exp $
|
||||
// $Id: ChainUtil.java,v 1.3 2001/07/14 00:55:21 mdb Exp $
|
||||
|
||||
package com.samskivert.viztool.viz;
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ChainUtil
|
||||
void computeRoots (String pkgroot, Iterator iter, ArrayList roots)
|
||||
{
|
||||
while (iter.hasNext()) {
|
||||
insertClass(roots, pkgroot, (String)iter.next());
|
||||
insertClass(roots, pkgroot, (String)iter.next(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,8 +79,8 @@ public class ChainUtil
|
||||
* Loads the supplied class and inserts it into the appropriate
|
||||
* position in the hierarchy based on its inheritance properties.
|
||||
*/
|
||||
protected static
|
||||
void insertClass (ArrayList roots, String pkgroot, String clazz)
|
||||
protected static void insertClass (
|
||||
ArrayList roots, String pkgroot, String clazz, boolean outpkg)
|
||||
{
|
||||
try {
|
||||
// sanity check
|
||||
@@ -92,7 +92,7 @@ public class ChainUtil
|
||||
}
|
||||
|
||||
// load and insert the class
|
||||
insertClass(roots, pkgroot, Class.forName(clazz));
|
||||
insertClass(roots, pkgroot, Class.forName(clazz), outpkg);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Unable to process class [class=" + clazz +
|
||||
@@ -105,22 +105,27 @@ public class ChainUtil
|
||||
* Inserts the specified class into the appropriate position in the
|
||||
* hierarchy based on its inheritance properties.
|
||||
*/
|
||||
protected static
|
||||
void insertClass (ArrayList roots, String pkgroot, Class target)
|
||||
protected static void insertClass (
|
||||
ArrayList roots, String pkgroot, Class target, boolean outpkg)
|
||||
{
|
||||
// insert the parent of this class into the hierarchy
|
||||
Class parent = target.getSuperclass();
|
||||
String name = generateName(target, pkgroot, outpkg);
|
||||
|
||||
// if we have no parent, we want to insert ourselves as a root
|
||||
// class
|
||||
if (parent == null || parent.equals(Object.class)) {
|
||||
insertRoot(roots, pkgroot, target);
|
||||
insertRoot(roots, name, target);
|
||||
|
||||
} else {
|
||||
String tpkg = pkgFromClass(target.getName());
|
||||
String ppkg = pkgFromClass(parent.getName());
|
||||
|
||||
// if our parent is not in this package, we want to insert it
|
||||
// into the hierarchy as a root class
|
||||
if (!parent.getName().startsWith(pkgroot)) {
|
||||
insertRoot(roots, pkgroot, parent);
|
||||
if (!tpkg.equals(ppkg)) {
|
||||
String pname = generateName(parent, pkgroot, true);
|
||||
insertRoot(roots, pname, parent);
|
||||
}
|
||||
|
||||
// and now hang ourselves off of our parent class
|
||||
@@ -128,7 +133,9 @@ public class ChainUtil
|
||||
if (chain == null) {
|
||||
// if there's no chain for our parent class, we'll need to
|
||||
// insert it into the hierarchy
|
||||
insertClass(roots, pkgroot, parent);
|
||||
boolean samepkg = pkgFromClass(parent.getName()).equals(
|
||||
pkgFromClass(target.getName()));
|
||||
insertClass(roots, pkgroot, parent, !samepkg);
|
||||
// and refetch our chain
|
||||
chain = getChain(roots, parent);
|
||||
// sanity check
|
||||
@@ -140,16 +147,58 @@ public class ChainUtil
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// add class will ignore our request if this class was already
|
||||
// added due to some previous operation
|
||||
chain.addClass(target);
|
||||
chain.addClass(name, target);
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean insertRoot (ArrayList roots, String pkgroot,
|
||||
protected static String generateName (Class target, String pkgroot,
|
||||
boolean outpkg)
|
||||
{
|
||||
String name;
|
||||
|
||||
if (outpkg) {
|
||||
// start with the fully qualified class name
|
||||
name = target.getName();
|
||||
// if we're in the package root, we want to strip off the
|
||||
// package root and prefix ...
|
||||
if (name.startsWith(pkgroot)) {
|
||||
name = ".." + name.substring(pkgroot.length());
|
||||
}
|
||||
|
||||
} else {
|
||||
name = nameFromClass(target.getName());
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns just the package qualifier given a fully qualified class
|
||||
* name.
|
||||
*/
|
||||
public static String pkgFromClass (String fqn)
|
||||
{
|
||||
int didx = fqn.lastIndexOf(".");
|
||||
return (didx == -1) ? fqn : fqn.substring(0, didx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unqualified class name given a fully qualified class
|
||||
* name.
|
||||
*/
|
||||
public static String nameFromClass (String fqn)
|
||||
{
|
||||
int didx = fqn.lastIndexOf(".");
|
||||
return (didx == -1) ? fqn : fqn.substring(didx+1);
|
||||
}
|
||||
|
||||
protected static boolean insertRoot (ArrayList roots, String name,
|
||||
Class root)
|
||||
{
|
||||
Chain chroot = new Chain(pkgroot, root);
|
||||
Chain chroot = new Chain(name, root);
|
||||
// make sure no chain already exists for this root
|
||||
if (!roots.contains(chroot)) {
|
||||
roots.add(chroot);
|
||||
|
||||
+57
-38
@@ -1,13 +1,16 @@
|
||||
//
|
||||
// $Id: HierarchyVisualizer.java,v 1.2 2001/07/13 23:25:13 mdb Exp $
|
||||
// $Id: HierarchyVisualizer.java,v 1.3 2001/07/14 00:55:21 mdb Exp $
|
||||
|
||||
package com.samskivert.viztool.viz;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
|
||||
import com.samskivert.viztool.Log;
|
||||
import com.samskivert.viztool.enum.PackageEnumerator;
|
||||
import com.samskivert.util.Comparators;
|
||||
|
||||
/**
|
||||
* The hierarchy visualizer displays inheritance hierarchies in a compact
|
||||
@@ -33,64 +36,80 @@ public class HierarchyVisualizer
|
||||
|
||||
// dump all the classes into an array list so that we can
|
||||
// repeatedly scan through the list
|
||||
_classes = new ArrayList();
|
||||
while (iter.hasNext()) {
|
||||
_classes.add(iter.next());
|
||||
}
|
||||
|
||||
// process the classes provided by our enumerator
|
||||
_roots = ChainUtil.buildChains(pkgroot, _classes.iterator());
|
||||
// compile a list of all packages in our collection
|
||||
HashSet pkgset = new HashSet();
|
||||
iter = _classes.iterator();
|
||||
while (iter.hasNext()) {
|
||||
pkgset.add(ChainUtil.pkgFromClass((String)iter.next()));
|
||||
}
|
||||
|
||||
// now we need to sort out
|
||||
// sort our package names
|
||||
_packages = new String[pkgset.size()];
|
||||
iter = pkgset.iterator();
|
||||
for (int i = 0; iter.hasNext(); i++) {
|
||||
_packages[i] = (String)iter.next();
|
||||
}
|
||||
Arrays.sort(_packages, Comparators.STRING);
|
||||
|
||||
// now create chain groups for each package
|
||||
_groups = new ChainGroup[_packages.length];
|
||||
for (int i = 0; i < _groups.length; i++) {
|
||||
PackageEnumerator penum = new PackageEnumerator(
|
||||
_packages[i], _classes.iterator(), false);
|
||||
_groups[i] = new ChainGroup(pkgroot, _packages[i], penum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the hierarchy of class chains assigning coordinates to
|
||||
* all of the chains and subchains so that they can be used to
|
||||
* generate a visualization.
|
||||
* Lays out and renders each of the chain groups that make up this
|
||||
* package hierarchy visualization.
|
||||
*/
|
||||
public void layoutChains (int pointSize)
|
||||
public void render (int pointSize, PrintStream out)
|
||||
{
|
||||
// lay out the internal structure of our chains
|
||||
ChainLayout clay = new CascadingChainLayout();
|
||||
for (int i = 0; i < _roots.size(); i++) {
|
||||
Chain chain = (Chain)_roots.get(i);
|
||||
chain.layout(pointSize, clay);
|
||||
}
|
||||
int x = X_MARGIN, y = Y_MARGIN;
|
||||
|
||||
// arrange them on the page
|
||||
ElementLayout elay = new PackedColumnElementLayout();
|
||||
Dimension[] pdims = elay.layout(_roots, PAGE_WIDTH, PAGE_HEIGHT);
|
||||
// print the preamble for the first page
|
||||
out.println("0 setlinewidth");
|
||||
|
||||
// render them
|
||||
for (int p = 0; p < pdims.length; p++) {
|
||||
ChainRenderer renderer = new CascadingChainRenderer();
|
||||
for (int i = 0; i < _roots.size(); i++) {
|
||||
Chain chain = (Chain)_roots.get(i);
|
||||
// skip chains not on this page
|
||||
if (chain.getPage() != p) {
|
||||
continue;
|
||||
}
|
||||
Point loc = chain.getLocation();
|
||||
renderer.renderChain(chain, System.out, pointSize,
|
||||
X_MARGIN, Y_MARGIN);
|
||||
for (int i = 0; i < _groups.length; i++) {
|
||||
// lay out the group in question
|
||||
Dimension dims = _groups[i].layout(pointSize);
|
||||
|
||||
// determine if we need to skip to the next page or not
|
||||
if ((y > 0) && (y + dims.height > PAGE_HEIGHT)) {
|
||||
// print the postamble for this page and preamble for the
|
||||
// new page
|
||||
out.println("showpage");
|
||||
out.println("0 setlinewidth");
|
||||
y = Y_MARGIN;
|
||||
}
|
||||
System.out.println("showpage");
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpClasses ()
|
||||
{
|
||||
ChainUtil.dumpClasses(System.err, _roots);
|
||||
// render the group at the requested location
|
||||
_groups[i].render(pointSize, out, x, y);
|
||||
|
||||
// increment our y location
|
||||
y += (dims.height + GAP);
|
||||
}
|
||||
|
||||
// print the postamble for the final page
|
||||
out.println("showpage");
|
||||
}
|
||||
|
||||
protected String _pkgroot;
|
||||
protected ArrayList _roots;
|
||||
protected ArrayList _classes;
|
||||
protected ArrayList _classes = new ArrayList();
|
||||
|
||||
protected String[] _packages;
|
||||
protected ChainGroup[] _groups;
|
||||
|
||||
protected static final int PAGE_WIDTH = (int)(72 * 7.5);
|
||||
protected static final int PAGE_HEIGHT = (int)(72 * 10);
|
||||
|
||||
protected static final int X_MARGIN = 72/2;
|
||||
protected static final int Y_MARGIN = 72/2;
|
||||
|
||||
protected static final int GAP = 72/4;
|
||||
}
|
||||
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: PackedColumnElementLayout.java,v 1.1 2001/07/13 23:25:13 mdb Exp $
|
||||
// $Id: PackedColumnElementLayout.java,v 1.2 2001/07/14 00:55:21 mdb Exp $
|
||||
|
||||
package com.samskivert.viztool.viz;
|
||||
|
||||
@@ -70,6 +70,11 @@ public class PackedColumnElementLayout implements ElementLayout
|
||||
x += (size.width + GAP);
|
||||
}
|
||||
|
||||
// take a final stab at our maxwidth
|
||||
if (x > maxwidth) {
|
||||
maxwidth = x;
|
||||
}
|
||||
|
||||
// make a note of how big the final page is
|
||||
pagedims.add(new Dimension(maxwidth, y+rowheight));
|
||||
Dimension[] dims = new Dimension[pagedims.size()];
|
||||
|
||||
Reference in New Issue
Block a user