Moved to separate repository.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@1619 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,59 +0,0 @@
|
||||
* Release 1.1:
|
||||
|
||||
2001-12-03 Michael Bayne <mdb@bering>
|
||||
|
||||
* src/java/com/samskivert/viztool/DriverTask.java:
|
||||
Use File.toURI() rather than build the URI by hand.
|
||||
|
||||
* src/java/com/samskivert/viztool/Driver.java:
|
||||
Added ability to generate postscript output file.
|
||||
|
||||
* various:
|
||||
More Visualizer interface improvements. Created ANT task for invoking
|
||||
viztool which is much nicer than the script.
|
||||
|
||||
* README:
|
||||
Added documentation for the ANT task.
|
||||
|
||||
* build.xml:
|
||||
Added targets to test the ANT driver task.
|
||||
|
||||
* src/java/com/samskivert/viztool/summary/ClassSummary.java, src/java/com/samskivert/viztool/summary/SummaryVisualizer.java:
|
||||
Summary visualization enhancements.
|
||||
|
||||
* src/java/com/samskivert/viztool/layout/PackedColumnElementLayout.java:
|
||||
Made sorting by height optional.
|
||||
|
||||
2001-12-01 Michael Bayne <mdb@bering>
|
||||
|
||||
* various:
|
||||
Created a visualization that displays classes, their public fields,
|
||||
members and constructors rather than the inheritance hierarchy.
|
||||
|
||||
* various:
|
||||
Refactored things into layout and render utility classes. Other
|
||||
cleanups. Upped the on screen font size.
|
||||
|
||||
2001-11-30 Michael Bayne <mdb@bering>
|
||||
|
||||
* various:
|
||||
Rearranged packages in preparation for the addition of a new type of
|
||||
visualization.
|
||||
|
||||
* Release 1.01:
|
||||
|
||||
2001-08-13 Michael Bayne <mdb@bering>
|
||||
|
||||
* bin/runjava: Wasn't incorporating the CLASSPATH environment
|
||||
variable properly.
|
||||
|
||||
* various: Added a better user interface for displaying
|
||||
visualizations on the screen rather than printing them.
|
||||
|
||||
* Release 1.0:
|
||||
|
||||
2001-08-12 Michael Bayne <mdb@bering>
|
||||
|
||||
* various: Initial release.
|
||||
|
||||
$Id: NEWS,v 1.4 2001/12/03 10:00:39 mdb Exp $
|
||||
@@ -1,102 +0,0 @@
|
||||
VIZTOOL: An extensible tool for visualizing Java classes
|
||||
--------------------------------------------------------
|
||||
|
||||
As the catchy subtitle claims, viztool is used to generate visualizations
|
||||
of collections of Java classes. These visualizations are intended to be
|
||||
printed out and taped to the wall or set on the desk beside you or folded
|
||||
into paper airplanes and sailed around the room. Thus viztool does not
|
||||
include a sophisticated user interface for viewing these presentations
|
||||
onscreen (use ghostscript for that), although you can actually display
|
||||
them on the screen because the rendering is done via the Java 2D rendering
|
||||
engine.
|
||||
|
||||
viztool was born from my repeated desire to be able to glance over all of
|
||||
the myriad classes that come to be involved in any large project. I knew I
|
||||
could go out and pay thousands of dollars for a single user license for
|
||||
some object oriented design tool that would diagram my classes three ways
|
||||
to Sunday, generate code, count my chickens and make toast on the side,
|
||||
but I couldn't find a free, simple tool for generating basic class
|
||||
diagrams.
|
||||
|
||||
Building viztool
|
||||
----------------
|
||||
|
||||
Building viztool is very simple. First ensure that the necessary third
|
||||
party jar files are available either in the lib/ directory or in the
|
||||
system wide jar file location specified in build.xml. See lib/README for a
|
||||
list of the necessary third party jar files and how to get them.
|
||||
|
||||
The library is built using ant, a modern build tool available from The
|
||||
Jakarta Project. If you aren't already using ant for other projects, it
|
||||
can be found here:
|
||||
|
||||
http://jakarta.apache.org/ant/
|
||||
|
||||
Invoke ant with any of the following targets:
|
||||
|
||||
all: builds the class files and javadoc documentation
|
||||
compile: builds only the class files (dist/classes)
|
||||
javadoc: builds only the javadoc documentation (dist/docs)
|
||||
dist: builds the distribution jar file (dist/viztool.jar)
|
||||
|
||||
Look at the build.xml file for configurable build parameters.
|
||||
|
||||
Using viztool
|
||||
-------------
|
||||
|
||||
viztool is designed to be easily invoked from ant. Simply ensure that
|
||||
viztool.jar and its associated dependent jar files are in the classpath of
|
||||
the JVM that invokes ant and then add a task like the following to your
|
||||
build.xml file:
|
||||
|
||||
<target name="hierviz">
|
||||
<taskdef name="viztool" classname="com.samskivert.viztool.DriverTask"/>
|
||||
<viztool pkgroot="com.samskivert.viztool"
|
||||
classes="com.samskivert.viztool.*"
|
||||
visualizer="com.samskivert.viztool.hierarchy.HierarchyVisualizer">
|
||||
<classpath refid="classpath"/>
|
||||
</viztool>
|
||||
</target>
|
||||
|
||||
the parameters passed to the task are:
|
||||
|
||||
pkgroot: the base package name which will be used to strip common text
|
||||
from the front of fully qualified class names
|
||||
classes: a regular expression matching the classes to be visualized
|
||||
visualizer: the classname of the visualizer to use
|
||||
|
||||
the <viztool> element should contain a <classpath> element which defines the
|
||||
classpath over which viztool will iterate, searching for classes that
|
||||
match the specified pattern.
|
||||
|
||||
There is also an included shell script (bin/viztool). Add the classes that
|
||||
you wish to visualize to your CLASSPATH environment variable and then
|
||||
invoke the viztool script with the package prefix you wish to visualize.
|
||||
|
||||
For example:
|
||||
|
||||
% export CLASSPATH=<here>/foo.jar:<there>/bar.jar:<everywhere>/baz.jar
|
||||
% ./bin/viztool --print com.whoever.mygreatpackage
|
||||
|
||||
Because the classes are actually resolved by the JVM when visualizing, all
|
||||
classes that the visualized classes depend upon must also be loadable
|
||||
(meaning included in the class path).
|
||||
|
||||
If you want to write your own script, take a look at the viztool script to
|
||||
see what arguments to pass to the visualization driver class.
|
||||
|
||||
Distribution
|
||||
------------
|
||||
|
||||
viztool is released under the GPL. The most recent version of the code is
|
||||
available here:
|
||||
|
||||
http://www.waywardgeeks.org/code/viztool/
|
||||
|
||||
Contribution
|
||||
------------
|
||||
|
||||
Contributions are welcome. Patches and suggestions can be sent to Michael
|
||||
Bayne <mdb@samskivert.com>.
|
||||
|
||||
$Id: README,v 1.3 2001/12/03 08:34:05 mdb Exp $
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $Id: build-dist.sh,v 1.2 2001/08/12 04:21:13 mdb Exp $
|
||||
#
|
||||
# Builds a distribution archive. This should be run from the top-level
|
||||
# project directory and it will place the distribution archive into the
|
||||
# directory identified by $DISTDIR.
|
||||
|
||||
USAGE="Usage: $0 distname (eg. viztool-1.4)"
|
||||
DISTDIR=dist
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo $USAGE
|
||||
exit -1
|
||||
else
|
||||
TARGET=$1
|
||||
fi
|
||||
|
||||
# build our excludes file
|
||||
cat > .excludes <<EOF
|
||||
build-dist.sh
|
||||
CVS
|
||||
dist
|
||||
lib/*.jar
|
||||
code
|
||||
.excludes
|
||||
.cvsignore
|
||||
EOF
|
||||
|
||||
# create our distribution directory
|
||||
mkdir /tmp/$TARGET
|
||||
|
||||
# temporarily move the distribution files into temp so that we can put
|
||||
# them into a properly named directory
|
||||
tar --exclude-from=.excludes -cf - * | tar -C /tmp/$TARGET -xf -
|
||||
|
||||
# now build the actual archive file
|
||||
tar -C /tmp -czf $DISTDIR/$TARGET.tgz $TARGET
|
||||
|
||||
# and clean up after ourselves
|
||||
rm -rf /tmp/$TARGET
|
||||
rm .excludes
|
||||
@@ -1,105 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# $Id: runjava,v 1.3 2001/08/13 23:30:52 mdb Exp $
|
||||
#
|
||||
# A script for invoking java. The project root is inferred to be one
|
||||
# directory above the directory in which this script lives. Based on the
|
||||
# root, all .jar files in the lib subdirectory are added to the classpath.
|
||||
# Additionally all shared libraries in lib/$arch, where $arch is generated
|
||||
# via uname and looks something like i686-Linux, are added to the
|
||||
# LD_LIBRARY_PATH environment variable. Classes are assumed to live in
|
||||
# $classdir as defined below.
|
||||
|
||||
use strict;
|
||||
use Getopt::Std;
|
||||
|
||||
# this is where our classfiles live (relative to the project root)
|
||||
my $classdir = "dist/classes";
|
||||
|
||||
# parse the arguments
|
||||
my %opts;
|
||||
getopts('p:v', \%opts);
|
||||
my $pid_file = $opts{"p"};
|
||||
my $verbose = $opts{"v"};
|
||||
|
||||
# make sure they specified a classfile
|
||||
my $usage = "Usage: $0 [-p pid_file] [-v] [-- args to pass to java] class\n";
|
||||
die $usage unless (@ARGV);
|
||||
|
||||
# get the server root by popping the /bin off of our directory
|
||||
my $location;
|
||||
chomp($location = `dirname $0`);
|
||||
my @parts = split(/\//, $location);
|
||||
pop(@parts);
|
||||
my $root = join("/", @parts);
|
||||
|
||||
# figure out where our JVM lives
|
||||
my $jhome = $ENV{"JAVA_HOME"};
|
||||
|
||||
# make sure JAVA_HOME is set
|
||||
if (!defined $jhome) {
|
||||
warn "$0: Error: No JAVA_HOME specified!\n";
|
||||
warn "\n";
|
||||
warn "You must set your JAVA_HOME environment variable to the\n";
|
||||
warn "the absolute path of your JDK installation. For example:\n";
|
||||
warn "\n";
|
||||
warn " % JAVA_HOME=/usr/local/jdk1.2\n";
|
||||
warn " % export JAVA_HOME\n";
|
||||
die "\n";
|
||||
}
|
||||
|
||||
my $java = "$jhome/bin/java";
|
||||
my $jlib = "$jhome/lib/classes.zip";
|
||||
|
||||
# use rt.jar if necessary
|
||||
if (! -f $jlib) {
|
||||
$jlib = "$jhome/lib/rt.jar";
|
||||
}
|
||||
if (! -f $jlib) {
|
||||
$jlib = "$jhome/jre/lib/rt.jar";
|
||||
}
|
||||
|
||||
# make sure we can run the jvm
|
||||
if (! -x $java) {
|
||||
die "$0: Can't find a java interpreter in '$jhome'.\n";
|
||||
}
|
||||
|
||||
# determine our machine architecture
|
||||
my $ostype = `uname -s`;
|
||||
my $machtype = `uname -m`;
|
||||
chomp($ostype);
|
||||
chomp($machtype);
|
||||
my $arch = "$machtype-$ostype";
|
||||
|
||||
# add our native libraries to the runtime library path
|
||||
my $libs = "$root/lib/$arch";
|
||||
my $libpath = $ENV{"LD_LIBRARY_PATH"};
|
||||
|
||||
if (defined $libpath) {
|
||||
$ENV{"LD_LIBRARY_PATH"} = "$libs:$libpath";
|
||||
} else {
|
||||
$ENV{"LD_LIBRARY_PATH"} = $libs;
|
||||
}
|
||||
|
||||
# put everything in our class path
|
||||
my $classpath = "$jlib:$root/$classdir";
|
||||
|
||||
# if there's an environment variable set, we'll need to include that too
|
||||
my $ecpath = $ENV{"CLASSPATH"};
|
||||
$classpath = "$ecpath:$classpath" if (defined $ecpath);
|
||||
|
||||
# any zip or jar files in our lib/ directory get added to the class path
|
||||
if (opendir(DIR, "$root/lib")) {
|
||||
my $lib;
|
||||
foreach $lib (grep { /.(zip|jar)/ && -f "$root/lib/$_" } readdir(DIR)) {
|
||||
$classpath .= ":$root/lib/$lib";
|
||||
}
|
||||
closedir DIR;
|
||||
}
|
||||
|
||||
# log the pid file if requested to do so
|
||||
print `echo $$ > $pid_file` if (defined $pid_file);
|
||||
|
||||
my $cmd = "$java -mx256M -classpath $classpath " . join(" ", @ARGV);
|
||||
print "$cmd\n" if ($verbose);
|
||||
exec($cmd);
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $Id: viztool,v 1.2 2001/11/08 19:38:54 mdb Exp $
|
||||
#
|
||||
# Sets up the classpath and invokes viztool with arguments supplied to
|
||||
# this script.
|
||||
|
||||
BINDIR=`dirname $0`
|
||||
RUNJAVA=$BINDIR/runjava
|
||||
VIZAPP=com.samskivert.viztool.Driver
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo "Usage: $0 [OPTIONS] package_prefix"
|
||||
cat << EOH
|
||||
|
||||
options:
|
||||
[--exclude=pkg:pkg:...]
|
||||
Note that sub-packages must explicitly be enumerated in this
|
||||
list. Excluding foo.bar will not automatically exclude
|
||||
foo.bar.baz.
|
||||
[--print]
|
||||
[--cpath="jar_file|directory [jar_file|directory ...]"]
|
||||
A list of jar files and directories to include in the classpath
|
||||
(separated by spaces). This will be globbed for you, so you can
|
||||
pass in --cpath="lib/*.jar".
|
||||
EOH
|
||||
exit -1
|
||||
}
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
while test $# -gt 0
|
||||
do
|
||||
case "$1" in
|
||||
-h|-\?)
|
||||
usage
|
||||
;;
|
||||
--print)
|
||||
OPTIONS="$OPTIONS -print"
|
||||
;;
|
||||
--exclude=*)
|
||||
EXCL=`echo $1 | sed 's:--exclude=::g'`
|
||||
JOPTIONS="$JOPTIONS -Dexclude=$EXCL"
|
||||
;;
|
||||
--cpath=*)
|
||||
ELEMS=`echo $1 | sed 's:--cpath=::g'`
|
||||
if [ -z "$CLASSPATH" ] ; then
|
||||
export CLASSPATH=`echo $ELEMS | sed 's/ /:/g'`
|
||||
else
|
||||
export CLASSPATH=$CLASSPATH:`echo $ELEMS | sed 's/ /:/g'`
|
||||
fi
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1"
|
||||
exit -1
|
||||
;;
|
||||
*)
|
||||
PACKAGE=$1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z "$PACKAGE" ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
# invoke the program
|
||||
$RUNJAVA -- $JOPTIONS $VIZAPP $OPTIONS $PACKAGE
|
||||
@@ -1,114 +0,0 @@
|
||||
<!-- build configuration -->
|
||||
<project name="viztool" default="compile" basedir=".">
|
||||
|
||||
<!-- things you may want to change -->
|
||||
<property name="app.name" value="viztool"/>
|
||||
<property name="doc.packages" value="com.samskivert.*"/>
|
||||
<property name="doc.overview" value="com/samskivert/viztool/overview.html"/>
|
||||
<property name="copyright.holder" value="Michael Bayne"/>
|
||||
<property name="build.compiler" value="jikes"/>
|
||||
<property name="java.libraries" value="/usr/share/java"/>
|
||||
|
||||
<!-- things you probably don't want to change -->
|
||||
<property name="src.dir" value="src/java"/>
|
||||
<property name="deploy.dir" value="dist"/>
|
||||
<property name="dist.jar" value="${app.name}.jar"/>
|
||||
<property name="javadoc.dir" value="${deploy.dir}/docs"/>
|
||||
<property name="savedoc.dir" value="docs"/>
|
||||
|
||||
<!-- declare our classpath business -->
|
||||
<path id="base.classpath">
|
||||
<pathelement location="${deploy.dir}/classes"/>
|
||||
<fileset dir="lib" includes="**/*.jar"/>
|
||||
</path>
|
||||
<path id="classpath">
|
||||
<path refid="base.classpath"/>
|
||||
</path>
|
||||
|
||||
<!-- include JAVA_LIBS jars in our classpath if it exists -->
|
||||
<target name="check-java-libs" if="env.JAVA_LIBS">
|
||||
<!-- overwrite the classpath with one that contains JAVA_LIBS jars -->
|
||||
<path id="classpath">
|
||||
<path refid="base.classpath"/>
|
||||
<fileset dir="${env.JAVA_LIBS}" includes="**/*.jar"/>
|
||||
</path>
|
||||
</target>
|
||||
|
||||
<!-- prepares the application directories -->
|
||||
<target name="prepare">
|
||||
<mkdir dir="${deploy.dir}"/>
|
||||
<mkdir dir="${deploy.dir}/classes"/>
|
||||
<mkdir dir="${javadoc.dir}"/>
|
||||
<copy todir="${deploy.dir}/classes">
|
||||
<fileset dir="${src.dir}" includes="**/*.properties"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- cleans out the installed application -->
|
||||
<target name="clean">
|
||||
<delete dir="${deploy.dir}"/>
|
||||
</target>
|
||||
|
||||
<!-- build the java class files -->
|
||||
<target name="compile" depends="prepare">
|
||||
<javac srcdir="${src.dir}" destdir="${deploy.dir}/classes"
|
||||
debug="on" optimize="off" deprecation="off">
|
||||
<classpath refid="classpath"/>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- build the javadoc documentation -->
|
||||
<target name="javadoc" depends="prepare">
|
||||
<javadoc sourcepath="${src.dir}"
|
||||
packagenames="${doc.packages}"
|
||||
windowtitle="${app.name} API"
|
||||
doctitle="${app.name} API"
|
||||
overview="${src.dir}/${doc.overview}"
|
||||
bottom="Copyright © 2001 ${copyright.holder}. All Rights Reserved."
|
||||
destdir="${javadoc.dir}"
|
||||
additionalparam="-breakiterator">
|
||||
<classpath refid="classpath"/>
|
||||
<link href="http://samskivert.com/code/samskivert/samskivert/dist/api"/>
|
||||
<link href="http://java.sun.com/j2se/1.4/docs/api/"/>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
<!-- builds the javadocs and stuffs them in a directory where they won't
|
||||
be blown away when we do "clean" next time -->
|
||||
<target name="savedoc" depends="javadoc">
|
||||
<delete dir="${savedoc.dir}/api"/>
|
||||
<copy todir="${savedoc.dir}/api">
|
||||
<fileset dir="${javadoc.dir}" includes="**/*"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- a target for rebuilding everything -->
|
||||
<target name="all" depends="clean,prepare,compile,javadoc,dist"/>
|
||||
|
||||
<!-- builds our distribution files (war and jar) -->
|
||||
<target name="dist" depends="prepare,compile">
|
||||
<jar file="${deploy.dir}/${dist.jar}"
|
||||
basedir="${deploy.dir}/classes"/>
|
||||
</target>
|
||||
|
||||
<!-- invoke the visualizer on itself for testing -->
|
||||
<target name="sumtest" depends="prepare,compile">
|
||||
<taskdef name="viztool" classname="com.samskivert.viztool.DriverTask"/>
|
||||
<viztool visualizer="com.samskivert.viztool.summary.SummaryVisualizer"
|
||||
pkgroot="com.samskivert.viztool"
|
||||
classes="com.samskivert.viztool.*">
|
||||
<classpath refid="classpath"/>
|
||||
</viztool>
|
||||
</target>
|
||||
|
||||
<target name="hiertest" depends="prepare,compile">
|
||||
<taskdef name="viztool" classname="com.samskivert.viztool.DriverTask"/>
|
||||
<viztool visualizer="com.samskivert.viztool.hierarchy.HierarchyVisualizer"
|
||||
pkgroot="com.samskivert.viztool"
|
||||
classes="com.samskivert.viztool.*"
|
||||
output="hiertest.ps">
|
||||
<classpath refid="classpath"/>
|
||||
</viztool>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -1,60 +0,0 @@
|
||||
viztool notes -*- mode: outline -*-
|
||||
|
||||
* Driver enhancements
|
||||
Create a driver that loads parameters from a properties file. That file
|
||||
can specify what visualization to use, parameters for that visualization
|
||||
and overall parameters like packages to exclude, etc.
|
||||
|
||||
Add support for regular expressions in the package inclusion and exclusion
|
||||
specifications.
|
||||
|
||||
Move the package exclusion processing into the PackageEnumerator rather
|
||||
than the current hack of having the HierarchyVisualizer do it.
|
||||
|
||||
** From <jon@latchkey.com>:
|
||||
Create an Ant Task that allows you to do something like this:
|
||||
|
||||
<target name="viztool">
|
||||
<viztool properties="viztool.properties">
|
||||
<classpath>
|
||||
</classpath>
|
||||
</viztool>
|
||||
</target>
|
||||
|
||||
Or:
|
||||
|
||||
<target name="viztool">
|
||||
<viztool exclude="" include="">
|
||||
<classpath>
|
||||
</classpath>
|
||||
</viztool>
|
||||
</target>
|
||||
|
||||
That would be fun.
|
||||
|
||||
* Chain visualization enhancements
|
||||
Lay chains out vertically rather than horizontally to achieve better
|
||||
density and a more aesthetic arrangement. This will probably require a
|
||||
searching algorithm to try to determine how tall to make each column to
|
||||
make best use of space.
|
||||
|
||||
Provide the option to arrange packages in the order that allows them to
|
||||
fit most compactly on the page rather than visualizing them in
|
||||
alphabetical order and pushing a package to a new page when it doesn't fit
|
||||
in the remaining space on the current page.
|
||||
|
||||
Provide an option to split packages up to fit them in the remaining space
|
||||
on a page rather than pushing them to the next page.
|
||||
|
||||
* Summary visualization enhancements
|
||||
Format field/method names in bold
|
||||
|
||||
* General visualization enhancements
|
||||
Add page numbers somewhere. [shaper@waywardgeeks.org]
|
||||
|
||||
* Printing enhancements
|
||||
Add current date to printed page.
|
||||
|
||||
* Architecture
|
||||
Create renderable primitives and build the visualizations from those
|
||||
primitives rather than encapsulating things in Layout/RenderUtil.
|
||||
@@ -1 +0,0 @@
|
||||
*.jar
|
||||
@@ -1,16 +0,0 @@
|
||||
Required external libraries
|
||||
---------------------------
|
||||
|
||||
The viztool code requires the following external Java libraries (JAR
|
||||
files) to be placed here in the lib/ directory or in the shared library
|
||||
directory specified in the build.xml file (${java.libraries}).
|
||||
|
||||
* samskivert library:
|
||||
http://samskivert.com/code/samskivert/
|
||||
|
||||
Once the jar files are in place (regardless of what they are named), the
|
||||
build system will automatically include them in the compile-time
|
||||
classpath.
|
||||
|
||||
--
|
||||
$Id: README,v 1.3 2001/08/12 02:40:25 mdb Exp $
|
||||
@@ -1,151 +0,0 @@
|
||||
//
|
||||
// $Id: Driver.java,v 1.16 2001/12/03 08:53:31 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.print.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.samskivert.swing.util.SwingUtil;
|
||||
import com.samskivert.viztool.clenum.*;
|
||||
|
||||
import com.samskivert.viztool.hierarchy.HierarchyVisualizer;
|
||||
import com.samskivert.viztool.summary.SummaryVisualizer;
|
||||
import com.samskivert.viztool.util.FontPicker;
|
||||
|
||||
/**
|
||||
* The application driver. This class parses the command line arguments
|
||||
* and invokes the visualization code.
|
||||
*/
|
||||
public class Driver
|
||||
{
|
||||
public static void main (String[] args)
|
||||
{
|
||||
if (args.length < 1) {
|
||||
System.err.println(USAGE);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
// parse our arguments
|
||||
String pkgroot = "";
|
||||
String regexp = null;
|
||||
boolean print = false;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i].equals("-print")) {
|
||||
print = true;
|
||||
} else if (regexp == null) {
|
||||
regexp = args[i];
|
||||
}
|
||||
}
|
||||
|
||||
// run ourselves on the classpath
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
// System.err.println("Scanning " + classpath + ".");
|
||||
ClassEnumerator clenum = new ClassEnumerator(classpath);
|
||||
|
||||
// print out the warnings
|
||||
ClassEnumerator.Warning[] warnings = clenum.getWarnings();
|
||||
for (int i = 0; i < warnings.length; i++) {
|
||||
System.err.println("Warning: " + warnings[i].reason);
|
||||
}
|
||||
|
||||
// initialize the font picker
|
||||
FontPicker.init(print);
|
||||
|
||||
// and finally generate the visualization
|
||||
FilterEnumerator fenum = null;
|
||||
try {
|
||||
fenum = new RegexpEnumerator(regexp, null, clenum);
|
||||
} catch (Exception e) {
|
||||
Log.warning("Invalid package regular expression " +
|
||||
"[regexp=" + regexp + ", error=" + e + "].");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
ArrayList classes = new ArrayList();
|
||||
while (fenum.hasNext()) {
|
||||
String cname = (String)fenum.next();
|
||||
// skip inner classes, the visualizations pick those up
|
||||
// themselves
|
||||
if (cname.indexOf("$") != -1) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
classes.add(Class.forName(cname));
|
||||
} catch (Throwable t) {
|
||||
Log.warning("Unable to introspect class [class=" + cname +
|
||||
", error=" + t + "].");
|
||||
}
|
||||
}
|
||||
|
||||
// Visualizer viz = new HierarchyVisualizer(pkgroot, penum);
|
||||
Visualizer viz = new SummaryVisualizer();
|
||||
viz.setPackageRoot(pkgroot);
|
||||
viz.setClasses(classes.iterator());
|
||||
|
||||
if (print) {
|
||||
// we use the print system to render things
|
||||
PrinterJob job = PrinterJob.getPrinterJob();
|
||||
|
||||
// pop up a dialog to format our pages
|
||||
// PageFormat format = job.pageDialog(job.defaultPage());
|
||||
PageFormat format = job.defaultPage();
|
||||
|
||||
// use sensible margins
|
||||
Paper paper = new Paper();
|
||||
paper.setImageableArea(72*0.5, 72*0.5, 72*7.5, 72*10);
|
||||
format.setPaper(paper);
|
||||
|
||||
// use our configured page format
|
||||
job.setPrintable(viz, format);
|
||||
|
||||
// pop up a dialog to control printing
|
||||
if (job.printDialog()) {
|
||||
try {
|
||||
// invoke the printing process
|
||||
job.print();
|
||||
} catch (PrinterException pe) {
|
||||
pe.printStackTrace(System.err);
|
||||
}
|
||||
|
||||
} else {
|
||||
Log.info("Printing cancelled.");
|
||||
}
|
||||
|
||||
// printing starts up the AWT threads, so we have to
|
||||
// explicitly exit at this point
|
||||
System.exit(0);
|
||||
|
||||
} else {
|
||||
VizFrame frame = new VizFrame(viz);
|
||||
frame.pack();
|
||||
SwingUtil.centerWindow(frame);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected static final String USAGE =
|
||||
"Usage: Driver [-mode hier|sum] [-print] package_regexp " +
|
||||
"[package_root]\n" +
|
||||
" hier = class hierarchy visualization\n" +
|
||||
" sum = class summary visualization\n"
|
||||
;
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
//
|
||||
// $Id: DriverTask.java,v 1.4 2003/01/28 22:39:34 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool;
|
||||
|
||||
import java.awt.print.PageFormat;
|
||||
import java.awt.print.Paper;
|
||||
import java.awt.print.PrinterException;
|
||||
import java.awt.print.PrinterJob;
|
||||
|
||||
import javax.print.attribute.HashPrintRequestAttributeSet;
|
||||
import javax.print.attribute.PrintRequestAttributeSet;
|
||||
import javax.print.attribute.standard.Destination;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.tools.ant.AntClassLoader;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.Task;
|
||||
|
||||
import org.apache.tools.ant.types.CommandlineJava;
|
||||
import org.apache.tools.ant.types.Path;
|
||||
|
||||
import com.samskivert.swing.util.SwingUtil;
|
||||
|
||||
import com.samskivert.viztool.clenum.ClassEnumerator;
|
||||
import com.samskivert.viztool.clenum.FilterEnumerator;
|
||||
import com.samskivert.viztool.clenum.RegexpEnumerator;
|
||||
import com.samskivert.viztool.util.FontPicker;
|
||||
|
||||
/**
|
||||
* The viztool ant task. It takes the following arguments:
|
||||
*
|
||||
* <pre>
|
||||
* pkgroot = the base package from which names will be shortened
|
||||
* classes = a regular expression matching the classes to be visualized
|
||||
* visualizer = the classname of the visualizer to be used
|
||||
* </pre>
|
||||
*
|
||||
* The task should contain an embedded <classpath> element to
|
||||
* provide the classpath over which we will iterate, looking for matching
|
||||
* classes.
|
||||
*/
|
||||
public class DriverTask extends Task
|
||||
{
|
||||
public void setVisualizer (String vizclass)
|
||||
{
|
||||
_vizclass = vizclass;
|
||||
}
|
||||
|
||||
public void setPkgroot (String pkgroot)
|
||||
{
|
||||
_pkgroot = pkgroot;
|
||||
}
|
||||
|
||||
public void setClasses (String classes)
|
||||
{
|
||||
_classes = classes;
|
||||
}
|
||||
|
||||
public void setExclude (String exclude)
|
||||
{
|
||||
_exclude = exclude;
|
||||
}
|
||||
|
||||
public void setOutput (File output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
public Path createClasspath ()
|
||||
{
|
||||
return _cmdline.createClasspath(project).createPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual work of the task.
|
||||
*/
|
||||
public void execute () throws BuildException
|
||||
{
|
||||
// make sure everything was set up properly
|
||||
ensureSet(_vizclass, "Must specify the visualizer class " +
|
||||
"via the 'visualizer' attribute.");
|
||||
ensureSet(_pkgroot, "Must specify the package root " +
|
||||
"via the 'pkgroot' attribute.");
|
||||
ensureSet(_pkgroot, "Must specify the class regular expression " +
|
||||
"via the 'classes' attribute.");
|
||||
Path classpath = _cmdline.getClasspath();
|
||||
ensureSet(classpath, "Must provide a <classpath> subelement " +
|
||||
"describing the classpath to be searched for classes.");
|
||||
|
||||
// initialize the font picker
|
||||
FontPicker.init(_output != null);
|
||||
|
||||
// create the classloader we'll use to load the visualized classes
|
||||
ClassLoader cl = new AntClassLoader(null, project, classpath, false);
|
||||
|
||||
// scan the classpath and determine which classes will be
|
||||
// visualized
|
||||
ClassEnumerator clenum = new ClassEnumerator(classpath.toString());
|
||||
FilterEnumerator fenum = null;
|
||||
try {
|
||||
fenum = new RegexpEnumerator(_classes, _exclude, clenum);
|
||||
} catch (Exception e) {
|
||||
throw new BuildException("Invalid package regular expression " +
|
||||
"[classes=" + _classes +
|
||||
", exclude=" + _exclude + "].", e);
|
||||
}
|
||||
|
||||
ArrayList classes = new ArrayList();
|
||||
while (fenum.hasNext()) {
|
||||
String cname = (String)fenum.next();
|
||||
// skip inner classes, the visualizations pick those up
|
||||
// themselves
|
||||
if (cname.indexOf("$") != -1) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
classes.add(cl.loadClass(cname));
|
||||
} catch (Throwable t) {
|
||||
log("Unable to introspect class [class=" + cname +
|
||||
", error=" + t + "].");
|
||||
}
|
||||
}
|
||||
|
||||
// // remove the packages on our exclusion list
|
||||
// String expkg = System.getProperty("exclude");
|
||||
// if (expkg != null) {
|
||||
// StringTokenizer tok = new StringTokenizer(expkg, ":");
|
||||
// while (tok.hasMoreTokens()) {
|
||||
// pkgset.remove(tok.nextToken());
|
||||
// }
|
||||
// }
|
||||
|
||||
// now create our visualizer and go to work
|
||||
Visualizer viz = null;
|
||||
try {
|
||||
viz = (Visualizer)Class.forName(_vizclass).newInstance();
|
||||
} catch (Throwable t) {
|
||||
throw new BuildException("Unable to instantiate visualizer " +
|
||||
"[vizclass=" + _vizclass +
|
||||
", error=" + t + "].");
|
||||
}
|
||||
|
||||
viz.setPackageRoot(_pkgroot);
|
||||
viz.setClasses(classes.iterator());
|
||||
|
||||
// if no output file was specified, pop up a window
|
||||
if (_output == null) {
|
||||
VizFrame frame = new VizFrame(viz);
|
||||
frame.pack();
|
||||
SwingUtil.centerWindow(frame);
|
||||
frame.setVisible(true);
|
||||
|
||||
// prevent ant from kicking the JVM out from under us
|
||||
synchronized (this) {
|
||||
while (true) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// we use the print system to render things
|
||||
PrinterJob job = PrinterJob.getPrinterJob();
|
||||
|
||||
// use sensible margins
|
||||
PageFormat format = job.defaultPage();
|
||||
Paper paper = new Paper();
|
||||
paper.setImageableArea(72*0.5, 72*0.5, 72*7.5, 72*10);
|
||||
format.setPaper(paper);
|
||||
|
||||
// use our configured page format
|
||||
job.setPrintable(viz, format);
|
||||
|
||||
// tell our printjob to print to a file
|
||||
PrintRequestAttributeSet attrs =
|
||||
new HashPrintRequestAttributeSet();
|
||||
attrs.add(new Destination(_output.toURI()));
|
||||
|
||||
// invoke the printing process
|
||||
try {
|
||||
log("Generating visualization to '" + _output.getPath() + "'.");
|
||||
job.print(attrs);
|
||||
} catch (PrinterException pe) {
|
||||
throw new BuildException("Error printing visualization.", pe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void ensureSet (Object value, String errmsg)
|
||||
throws BuildException
|
||||
{
|
||||
if (value == null) {
|
||||
throw new BuildException(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
protected String _vizclass;
|
||||
protected String _pkgroot;
|
||||
protected String _classes, _exclude;
|
||||
protected File _output;
|
||||
|
||||
// use use this for accumulating our classpath
|
||||
protected CommandlineJava _cmdline = new CommandlineJava();
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
//
|
||||
// $Id: Log.java,v 1.3 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool;
|
||||
|
||||
/**
|
||||
* A placeholder class that contains a reference to the log object used by
|
||||
* the viztool package.
|
||||
*/
|
||||
public class Log
|
||||
{
|
||||
public static com.samskivert.util.Log log =
|
||||
new com.samskivert.util.Log("viztool");
|
||||
|
||||
/** Convenience function. */
|
||||
public static void debug (String message)
|
||||
{
|
||||
log.debug(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void info (String message)
|
||||
{
|
||||
log.info(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void warning (String message)
|
||||
{
|
||||
log.warning(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void logStackTrace (Throwable t)
|
||||
{
|
||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
//
|
||||
// $Id: Visualizer.java,v 1.5 2001/12/03 08:34:53 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.print.Printable;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The interface via which the driver accesses whichever visualizer is
|
||||
* desired for a particular invocation.
|
||||
*/
|
||||
public interface Visualizer extends Printable
|
||||
{
|
||||
/**
|
||||
* Provides the visualizer with the root package which it can use to
|
||||
* format package names relative to the root package.
|
||||
*/
|
||||
public void setPackageRoot (String pkgroot);
|
||||
|
||||
/**
|
||||
* Provides the visualizer with an iterator over all of the {@link
|
||||
* Class} instances that it will be visualizing.
|
||||
*/
|
||||
public void setClasses (Iterator iterator);
|
||||
|
||||
/**
|
||||
* Requests that the visualization lay itself out in pages with the
|
||||
* specified dimensions. Subsequent calls to {@link #print} or {@link
|
||||
* #paint} will assume that things are laid out according to the most
|
||||
* recent call to this method.
|
||||
*/
|
||||
public void layout (Graphics2D gfx, double x, double y,
|
||||
double width, double height);
|
||||
|
||||
/**
|
||||
* Renders the specified page of this visualization.
|
||||
*/
|
||||
public void paint (Graphics2D gfx, int pageIndex);
|
||||
|
||||
/**
|
||||
* Returns the number of pages occupied by the visualization.
|
||||
*/
|
||||
public int getPageCount ();
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
//
|
||||
// $Id: VizController.java,v 1.4 2001/12/01 05:28:01 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.print.*;
|
||||
|
||||
import com.samskivert.swing.*;
|
||||
|
||||
/**
|
||||
* The viz controller manages the user interface and effects actions that
|
||||
* are requested by the user (like moving forward or backward a page).
|
||||
*/
|
||||
public class VizController extends Controller
|
||||
{
|
||||
/** The action command for moving forward one page. */
|
||||
public static final String FORWARD_PAGE = "forward_page";
|
||||
|
||||
/** The action command for moving backward one page. */
|
||||
public static final String BACKWARD_PAGE = "backward_page";
|
||||
|
||||
/** The action command for printing. */
|
||||
public static final String PRINT = "print";
|
||||
|
||||
/** The action command for quitting. */
|
||||
public static final String QUIT = "quit";
|
||||
|
||||
public VizController (VizPanel vpanel)
|
||||
{
|
||||
_vpanel = vpanel;
|
||||
|
||||
// create a print job in case we need to print
|
||||
_job = PrinterJob.getPrinterJob();
|
||||
_format = _job.defaultPage();
|
||||
|
||||
// use sensible margins
|
||||
Paper paper = new Paper();
|
||||
paper.setImageableArea(
|
||||
LEFT_MARGIN, TOP_MARGIN, PAGE_WIDTH, PAGE_HEIGHT);
|
||||
_format.setPaper(paper);
|
||||
}
|
||||
|
||||
public boolean handleAction (ActionEvent action)
|
||||
{
|
||||
String cmd = action.getActionCommand();
|
||||
|
||||
if (cmd.equals(FORWARD_PAGE)) {
|
||||
int pno = _vpanel.getPage();
|
||||
if (pno < _vpanel.getPageCount()-1) {
|
||||
_vpanel.setPage(pno+1);
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (cmd.equals(BACKWARD_PAGE)) {
|
||||
int pno = _vpanel.getPage();
|
||||
if (pno > 0) {
|
||||
_vpanel.setPage(pno-1);
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (cmd.equals(PRINT)) {
|
||||
// create a pageable to be used by our print job that does the
|
||||
// right thing
|
||||
Pageable pable = new Pageable() {
|
||||
public int getNumberOfPages () {
|
||||
return _vpanel.getVisualizer().getPageCount();
|
||||
}
|
||||
|
||||
public PageFormat getPageFormat (int pageIndex) {
|
||||
return _format;
|
||||
}
|
||||
|
||||
public Printable getPrintable (int pageIndex) {
|
||||
return _vpanel.getVisualizer();
|
||||
}
|
||||
};
|
||||
_job.setPageable(pable);
|
||||
|
||||
// pop up a dialog to control printing
|
||||
if (_job.printDialog()) {
|
||||
try {
|
||||
// invoke the printing process
|
||||
_job.print();
|
||||
} catch (PrinterException pe) {
|
||||
pe.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (cmd.equals(QUIT)) {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected VizPanel _vpanel;
|
||||
protected PrinterJob _job;
|
||||
protected PageFormat _format;
|
||||
|
||||
// these should be configurable...
|
||||
protected static final double LEFT_MARGIN = 72*0.5;
|
||||
protected static final double TOP_MARGIN = 72*0.5;
|
||||
protected static final double PAGE_WIDTH = 72*7.5;
|
||||
protected static final double PAGE_HEIGHT = 72*10;
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
//
|
||||
// $Id: VizFrame.java,v 1.6 2001/11/30 22:57:31 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import javax.swing.*;
|
||||
|
||||
import com.samskivert.swing.*;
|
||||
|
||||
/**
|
||||
* The top-level frame in which visualizations are displayed.
|
||||
*/
|
||||
public class VizFrame extends JFrame
|
||||
{
|
||||
public VizFrame (Visualizer viz)
|
||||
{
|
||||
super("viztool");
|
||||
|
||||
// quit if we're closed
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
|
||||
// create our controller and panel for displaying visualizations
|
||||
VizPanel vpanel = new VizPanel(viz);
|
||||
VizController vctrl = new VizController(vpanel);
|
||||
|
||||
// create some control buttons
|
||||
GroupLayout gl = new HGroupLayout(GroupLayout.NONE);
|
||||
gl.setJustification(GroupLayout.RIGHT);
|
||||
JPanel bpanel = new JPanel(gl);
|
||||
JButton btn;
|
||||
|
||||
btn = new JButton("Print");
|
||||
btn.setActionCommand(VizController.PRINT);
|
||||
btn.addActionListener(VizController.DISPATCHER);
|
||||
bpanel.add(btn);
|
||||
|
||||
btn = new JButton("Previous page");
|
||||
btn.setActionCommand(VizController.BACKWARD_PAGE);
|
||||
btn.addActionListener(VizController.DISPATCHER);
|
||||
bpanel.add(btn);
|
||||
|
||||
btn = new JButton("Next page");
|
||||
btn.setActionCommand(VizController.FORWARD_PAGE);
|
||||
btn.addActionListener(VizController.DISPATCHER);
|
||||
bpanel.add(btn);
|
||||
|
||||
btn = new JButton("Quit");
|
||||
btn.setActionCommand(VizController.QUIT);
|
||||
btn.addActionListener(VizController.DISPATCHER);
|
||||
bpanel.add(btn);
|
||||
|
||||
// create a content pane to contain everything
|
||||
JPanel content = new ContentPanel(vctrl);
|
||||
gl = new VGroupLayout(GroupLayout.STRETCH);
|
||||
content.setLayout(gl);
|
||||
content.setBorder(BorderFactory.createEmptyBorder(
|
||||
BORDER, BORDER, BORDER, BORDER));
|
||||
content.add(vpanel);
|
||||
content.add(bpanel, GroupLayout.FIXED);
|
||||
setContentPane(content);
|
||||
}
|
||||
|
||||
protected static final class ContentPanel
|
||||
extends JPanel
|
||||
implements ControllerProvider
|
||||
{
|
||||
public ContentPanel (VizController ctrl)
|
||||
{
|
||||
_ctrl = ctrl;
|
||||
}
|
||||
|
||||
public Controller getController ()
|
||||
{
|
||||
return _ctrl;
|
||||
}
|
||||
|
||||
protected Controller _ctrl;
|
||||
}
|
||||
|
||||
protected static final int BORDER = 5; // pixels
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
//
|
||||
// $Id: VizPanel.java,v 1.8 2001/12/01 05:28:01 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* A very simple UI element for displaying visualizations on screen.
|
||||
*/
|
||||
public class VizPanel extends JPanel
|
||||
{
|
||||
/**
|
||||
* Constructs a panel for displaying a particular visualization.
|
||||
*/
|
||||
public VizPanel (Visualizer viz)
|
||||
{
|
||||
// we'll need this later
|
||||
_viz = viz;
|
||||
|
||||
// set the font
|
||||
Font font = new Font("Courier", Font.PLAIN, 10);
|
||||
setFont(font);
|
||||
}
|
||||
|
||||
public void doLayout ()
|
||||
{
|
||||
super.doLayout();
|
||||
Graphics2D gfx = (Graphics2D)getGraphics();
|
||||
Rectangle2D bounds = getBounds();
|
||||
_viz.layout(gfx, 0, 0, bounds.getWidth(), bounds.getHeight());
|
||||
}
|
||||
|
||||
public void paintComponent (Graphics g)
|
||||
{
|
||||
super.paintComponent(g);
|
||||
_viz.paint((Graphics2D)g, _currentPage);
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize ()
|
||||
{
|
||||
return new Dimension(PAGE_WIDTH, PAGE_HEIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of pages in our current visualization. This is
|
||||
* only valid after we've been rendered at least once because we
|
||||
* needed the rendering graphics to realize the visualization.
|
||||
*/
|
||||
public int getPageCount ()
|
||||
{
|
||||
return _viz.getPageCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the panel display the specified page number (indexed
|
||||
* from zero). Requests to display invalid page numbers will be
|
||||
* ignored.
|
||||
*/
|
||||
public void setPage (int pageno)
|
||||
{
|
||||
if (pageno < _viz.getPageCount()) {
|
||||
_currentPage = pageno;
|
||||
repaint();
|
||||
|
||||
} else {
|
||||
Log.warning("Requested to display invalid page " +
|
||||
"[pageno=" + pageno +
|
||||
", pages=" + _viz.getPageCount() + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the page that we're currently displaying.
|
||||
*/
|
||||
public int getPage ()
|
||||
{
|
||||
return _currentPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the visualizer we're currently displaying.
|
||||
*/
|
||||
public Visualizer getVisualizer ()
|
||||
{
|
||||
return _viz;
|
||||
}
|
||||
|
||||
protected Visualizer _viz;
|
||||
protected int _currentPage = 0;
|
||||
|
||||
// our preferred size is one page at 72 pixels per inch
|
||||
protected static final int PAGE_WIDTH = (int)(72 * 8.5);
|
||||
protected static final int PAGE_HEIGHT = (int)(72 * 11);
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
//
|
||||
// $Id: ClassEnumerator.java,v 1.4 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The class enumerator is supplied with a classpath which it decomposes
|
||||
* and enumerates over all of the classes available via those classpath
|
||||
* componenets. To do this it uses component enumerators which know how to
|
||||
* enumerate all of the classes in a directory tree, in a jar file, etc.
|
||||
* The component enumerators are structured so that new enumerators can be
|
||||
* authored for new kinds of classpath component.
|
||||
*/
|
||||
public class ClassEnumerator implements Iterator
|
||||
{
|
||||
/**
|
||||
* Constructs a class enumerator with the supplied classpath. A set of
|
||||
* component enumerators will be chosen for each element and warnings
|
||||
* will be generated for components that cannot be processed for some
|
||||
* reason or other. Those will be available following the completion
|
||||
* of the constructor via <code>getWarnings()</code>.
|
||||
*
|
||||
* @see #getWarnings
|
||||
*/
|
||||
public ClassEnumerator (String classpath)
|
||||
{
|
||||
// decompose the path and select enumerators for each component
|
||||
StringTokenizer tok = new StringTokenizer(classpath, ":");
|
||||
ArrayList warnings = new ArrayList();
|
||||
ArrayList enums = new ArrayList();
|
||||
|
||||
while (tok.hasMoreTokens()) {
|
||||
String component = tok.nextToken();
|
||||
// locate an enumerator for this token
|
||||
ComponentEnumerator cenum = matchEnumerator(component);
|
||||
if (cenum == null) {
|
||||
String wmsg = "Unable to match enumerator for " +
|
||||
"component '" + component + "'.";
|
||||
warnings.add(new Warning(wmsg));
|
||||
|
||||
} else {
|
||||
try {
|
||||
// System.out.println("Adding [enum=" + cenum +
|
||||
// ", component=" + component + "].");
|
||||
// construct an enumerator to enumerate this component
|
||||
// and put it on our list
|
||||
enums.add(cenum.enumerate(component));
|
||||
|
||||
} catch (EnumerationException ee) {
|
||||
// if there was a problem creating an enumerator for
|
||||
// said component, create a warning to that effect
|
||||
warnings.add(new Warning(ee.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert our list into an array
|
||||
_enums = new ComponentEnumerator[enums.size()];
|
||||
enums.toArray(_enums);
|
||||
|
||||
// convert the warnings into an array
|
||||
_warnings = new Warning[warnings.size()];
|
||||
warnings.toArray(_warnings);
|
||||
|
||||
// scan to the first class
|
||||
scanToNextClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates an enumerator that matches the specified component and
|
||||
* returns the prototype instance of that enumerator. Returns null if
|
||||
* no enumerator could be matched.
|
||||
*/
|
||||
protected ComponentEnumerator matchEnumerator (String component)
|
||||
{
|
||||
for (int i = 0; i < _enumerators.size(); i++) {
|
||||
ComponentEnumerator cenum =
|
||||
(ComponentEnumerator)_enumerators.get(i);
|
||||
if (cenum.matchesComponent(component)) {
|
||||
return cenum;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the warnings generated in parsing the classpath and
|
||||
* constructing enumerators for each component. For example, if a
|
||||
* classpath component specified a directory that was non-existent or
|
||||
* inaccessible, a warning would be generated for that component. If
|
||||
* no warnings were generated, a zero length array will be returned.
|
||||
*/
|
||||
public Warning[] getWarnings ()
|
||||
{
|
||||
return _warnings;
|
||||
}
|
||||
|
||||
public boolean hasNext ()
|
||||
{
|
||||
return (_nextClass != null);
|
||||
}
|
||||
|
||||
public Object next ()
|
||||
{
|
||||
String clazz = _nextClass;
|
||||
_nextClass = null;
|
||||
scanToNextClass();
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public void remove ()
|
||||
{
|
||||
// not supported
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues up the next enumerator in the list or clears out our
|
||||
* enumerator reference if we have no remaining enumerators.
|
||||
*/
|
||||
protected void scanToNextClass ()
|
||||
{
|
||||
if (_enumidx < _enums.length) {
|
||||
// grab the current enumerator
|
||||
ComponentEnumerator cenum = _enums[_enumidx];
|
||||
|
||||
// if it has more classes
|
||||
if (cenum.hasMoreClasses()) {
|
||||
// get the next one
|
||||
_nextClass = cenum.nextClass();
|
||||
return;
|
||||
|
||||
} else {
|
||||
// otherwise try the next enum
|
||||
_enumidx++;
|
||||
scanToNextClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ComponentEnumerator[] _enums;
|
||||
protected int _enumidx;
|
||||
protected String _nextClass;
|
||||
protected Warning[] _warnings;
|
||||
|
||||
/**
|
||||
* A warning is generated when a component of the classpath cannot be
|
||||
* processed for some reason or other.
|
||||
*/
|
||||
public static class Warning
|
||||
{
|
||||
public String reason;
|
||||
|
||||
public Warning (String reason)
|
||||
{
|
||||
this.reason = reason;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
// run ourselves on the classpath
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
ClassEnumerator cenum = new ClassEnumerator(classpath);
|
||||
|
||||
// print out the warnings
|
||||
Warning[] warnings = cenum.getWarnings();
|
||||
for (int i = 0; i < warnings.length; i++) {
|
||||
System.out.println("Warning: " + warnings[i].reason);
|
||||
}
|
||||
|
||||
// enumerate over whatever classes we can
|
||||
while (cenum.hasNext()) {
|
||||
System.out.println("Class: " + cenum.next());
|
||||
}
|
||||
}
|
||||
|
||||
protected static ArrayList _enumerators = new ArrayList();
|
||||
|
||||
static {
|
||||
// register our enumerators
|
||||
_enumerators.add(new ZipFileEnumerator());
|
||||
_enumerators.add(new JarFileEnumerator());
|
||||
// the directory enumerator should always be last in the list
|
||||
// because it picks up all stragglers and tries enumerating them
|
||||
// as if they were directories
|
||||
_enumerators.add(new DirectoryEnumerator());
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
//
|
||||
// $Id: ComponentEnumerator.java,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* A component enumerator knows how to enumerate all of the classes in a
|
||||
* particular classpath component. Examples include a zip file enumerator,
|
||||
* a directory tree enumerator and a jar file enumerator.
|
||||
*/
|
||||
public abstract class ComponentEnumerator
|
||||
{
|
||||
/**
|
||||
* To determine which component enumerator should be used for a given
|
||||
* classpath component, one instance of each is maintained and used
|
||||
* for the matching process.
|
||||
*
|
||||
* @return true if this enumerator should be used to enumerate the
|
||||
* specified classpath component; false otherwise.
|
||||
*/
|
||||
public abstract boolean matchesComponent (String component);
|
||||
|
||||
/**
|
||||
* Instantiates an instance of the underlying enumerator and
|
||||
* configures it to enumerate the specified classpath component.
|
||||
*
|
||||
* @exception EnumerationException thrown if some problem (like file
|
||||
* or directory not existing or being inaccessible) prevents the
|
||||
* enumerator from enumerating the component.
|
||||
*/
|
||||
public abstract ComponentEnumerator enumerate (String component)
|
||||
throws EnumerationException;
|
||||
|
||||
/**
|
||||
* Returns true if there are more classes yet to be enumerated for
|
||||
* this component.
|
||||
*/
|
||||
public abstract boolean hasMoreClasses ();
|
||||
|
||||
/**
|
||||
* Returns the next class in this component's enumeration.
|
||||
*/
|
||||
public abstract String nextClass ();
|
||||
|
||||
/**
|
||||
* Converts a classfile path to a class name (eg. foo/bar/Baz.class
|
||||
* converts to foo.bar.Baz).
|
||||
*/
|
||||
protected String pathToClassName (String path)
|
||||
{
|
||||
// strip off the .class suffix
|
||||
path = path.substring(0, path.length() - CLASS_SUFFIX.length());
|
||||
// convert slashes to dots
|
||||
return StringUtil.replace(path, "/", ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to identify class files.
|
||||
*/
|
||||
protected static final String CLASS_SUFFIX = ".class";
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
//
|
||||
// $Id: DirectoryEnumerator.java,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.viztool.Log;
|
||||
|
||||
/**
|
||||
* The directory enumerator enumerates all of the classes in a directory
|
||||
* hierarchy.
|
||||
*/
|
||||
public class DirectoryEnumerator extends ComponentEnumerator
|
||||
{
|
||||
/**
|
||||
* Constructs a prototype enumerator that can be used for matching.
|
||||
*/
|
||||
public DirectoryEnumerator ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a directory enumerator with the specified root directory
|
||||
* for enumeration.
|
||||
*/
|
||||
public DirectoryEnumerator (String dirpath)
|
||||
throws EnumerationException
|
||||
{
|
||||
_root = new File(dirpath);
|
||||
_rootpath = _root.getAbsolutePath();
|
||||
|
||||
// make sure the specified component exists
|
||||
if (!_root.exists()) {
|
||||
String msg = "Can't enumerate '" + dirpath +
|
||||
"': directory doesn't exist";
|
||||
throw new EnumerationException(msg);
|
||||
}
|
||||
|
||||
// make sure the specified component is a directory
|
||||
if (!_root.isDirectory()) {
|
||||
String msg = "Can't enumerate non-directory '" + dirpath + "'.";
|
||||
throw new EnumerationException(msg);
|
||||
}
|
||||
|
||||
// create a directory record for our root directory
|
||||
addDirectory(_root);
|
||||
|
||||
// and scan to the first class
|
||||
scanToNextClass();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public boolean matchesComponent (String component)
|
||||
{
|
||||
// the directory enumerator picks up anything that falls through
|
||||
// the zip or jar file enumerators
|
||||
return true;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public ComponentEnumerator enumerate (String component)
|
||||
throws EnumerationException
|
||||
{
|
||||
return new DirectoryEnumerator(component);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public boolean hasMoreClasses ()
|
||||
{
|
||||
return (_nextClass != null);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public String nextClass ()
|
||||
{
|
||||
String clazz = _nextClass;
|
||||
_nextClass = null;
|
||||
scanToNextClass();
|
||||
return clazz;
|
||||
}
|
||||
|
||||
protected void scanToNextClass ()
|
||||
{
|
||||
// if we have no drecords, we have nothing to do
|
||||
while (_drecords.size() > 0) {
|
||||
// grab a reference to the last drecord in the list
|
||||
DirRecord rec = (DirRecord)_drecords.get(_drecords.size()-1);
|
||||
|
||||
// grab the file related to our current position
|
||||
File target = rec.kids[rec.kidpos];
|
||||
|
||||
// bump up the kidpos so that things are in place for the next
|
||||
// iteration; if we just grabbed the last kid, pop this record
|
||||
// off of the stack
|
||||
if (++rec.kidpos >= rec.kids.length) {
|
||||
_drecords.remove(_drecords.size()-1);
|
||||
}
|
||||
|
||||
// if our target file is a directory, push another drecord
|
||||
// onto the stack and recurse into it
|
||||
if (target.isDirectory()) {
|
||||
addDirectory(target);
|
||||
continue;
|
||||
}
|
||||
|
||||
// otherwise, process it as a file
|
||||
String path = target.getAbsolutePath();
|
||||
|
||||
// make sure it's readable
|
||||
if (!target.canRead()) {
|
||||
Log.warning("Can't read file '" + path + "'.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// check to see if it matches our filename pattern
|
||||
if (path.endsWith(CLASS_SUFFIX)) {
|
||||
// strip off the root path (plus one for the trailing slash)
|
||||
path = path.substring(_rootpath.length()+1);
|
||||
_nextClass = pathToClassName(path);
|
||||
return;
|
||||
}
|
||||
|
||||
// if we didn't match, we loop back through and process the
|
||||
// next kid (potentially popping back up the directory record
|
||||
// stack in the process)
|
||||
}
|
||||
}
|
||||
|
||||
protected void addDirectory (File dir)
|
||||
{
|
||||
DirRecord rec = new DirRecord(dir);
|
||||
if (rec.kids == null) {
|
||||
String path = dir.getAbsolutePath();
|
||||
// complain if there was an error reading the directory
|
||||
Log.warning("Unable to scan directory '" + path + "'.");
|
||||
|
||||
} else if (rec.kids.length > 0) {
|
||||
// only add the record if the directory actually has some
|
||||
// children that we can scan
|
||||
_drecords.add(rec);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class DirRecord
|
||||
{
|
||||
public File directory;
|
||||
public File[] kids;
|
||||
public int kidpos;
|
||||
|
||||
public DirRecord (File directory)
|
||||
{
|
||||
this.directory = directory;
|
||||
kids = directory.listFiles();
|
||||
}
|
||||
}
|
||||
|
||||
protected File _root;
|
||||
protected String _rootpath;
|
||||
protected ArrayList _drecords = new ArrayList();
|
||||
protected String _nextClass;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
//
|
||||
// $Id: EnumerationException.java,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
/**
|
||||
* An enumeration exception is thrown when some problem occurs while
|
||||
* attempting to enumerate over a classpath component. This may be when
|
||||
* initially attempting to read a zip or jar file, or during the process
|
||||
* of enumeration.
|
||||
*/
|
||||
public class EnumerationException extends Exception
|
||||
{
|
||||
public EnumerationException (String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
//
|
||||
// $Id: FilterEnumerator.java,v 1.3 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The filter enumerator provides the framework by which a particular
|
||||
* subset of classes can be filtered from the total enumeration of classes
|
||||
* in a classpath. This is useful for doing things like only considering
|
||||
* classes in a particular package or only considering interfaces, and so
|
||||
* on.
|
||||
*/
|
||||
public abstract class FilterEnumerator implements Iterator
|
||||
{
|
||||
/**
|
||||
* Constructs a filter enumerator with the supplied class enumerator
|
||||
* as the source of classes.
|
||||
*/
|
||||
public FilterEnumerator (Iterator source)
|
||||
{
|
||||
_source = source;
|
||||
// we'd love to call scanToNextClass() here but that calls
|
||||
// filterClass() and it's extremely bad form to call a function
|
||||
// provided by a derived class in the super class's constructor
|
||||
// because the derived class's constructor hasn't yet been
|
||||
// executed. sigh.
|
||||
}
|
||||
|
||||
public boolean hasNext ()
|
||||
{
|
||||
if (_nextClass == null) {
|
||||
scanToNextClass();
|
||||
}
|
||||
return _nextClass != null;
|
||||
}
|
||||
|
||||
public Object next ()
|
||||
{
|
||||
if (_nextClass == null) {
|
||||
scanToNextClass();
|
||||
}
|
||||
String clazz = _nextClass;
|
||||
_nextClass = null;
|
||||
scanToNextClass();
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public void remove ()
|
||||
{
|
||||
// not supported
|
||||
}
|
||||
|
||||
protected void scanToNextClass ()
|
||||
{
|
||||
while (_source.hasNext()) {
|
||||
String clazz = (String)_source.next();
|
||||
if (!filterClass(clazz)) {
|
||||
_nextClass = clazz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes should override this method and return true if the
|
||||
* specified class should be filtered (meaning it should be excluded
|
||||
* from the classes returned) or false if it should be included.
|
||||
*/
|
||||
protected abstract boolean filterClass (String clazz);
|
||||
|
||||
protected Iterator _source;
|
||||
protected String _nextClass;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
//
|
||||
// $Id: JarFileEnumerator.java,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
/**
|
||||
* The jar file enumerator enumerates all of the classes in a .jar class
|
||||
* archive.
|
||||
*/
|
||||
public class JarFileEnumerator extends ZipFileEnumerator
|
||||
{
|
||||
/**
|
||||
* Constructs a prototype enumerator that can be used for matching.
|
||||
*/
|
||||
public JarFileEnumerator ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a jar file enumerator with the specified jar file for
|
||||
* enumeration.
|
||||
*/
|
||||
public JarFileEnumerator (String jarpath)
|
||||
throws EnumerationException
|
||||
{
|
||||
super(jarpath);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public boolean matchesComponent (String component)
|
||||
{
|
||||
return component.endsWith(JAR_SUFFIX);
|
||||
}
|
||||
|
||||
protected static final String JAR_SUFFIX = ".jar";
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
//
|
||||
// $Id: PackageEnumerator.java,v 1.3 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The package enumerator filters out only classes from the specified
|
||||
* package from the class enumerator provided at construct time.
|
||||
*/
|
||||
public class PackageEnumerator extends FilterEnumerator
|
||||
{
|
||||
public PackageEnumerator (String pkg, Iterator source, boolean subpkgs)
|
||||
{
|
||||
super(source);
|
||||
_package = pkg;
|
||||
_subpkgs = subpkgs;
|
||||
}
|
||||
|
||||
protected boolean filterClass (String clazz)
|
||||
{
|
||||
if (!clazz.startsWith(_package)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _subpkgs ? false:
|
||||
(clazz.substring(_package.length()+1).indexOf(".") != -1);
|
||||
}
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
// run ourselves on the classpath
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
ClassEnumerator clenum = new ClassEnumerator(classpath);
|
||||
String pkg = "com.samskivert.viztool.clenum";
|
||||
PackageEnumerator penum = new PackageEnumerator(pkg, clenum, true);
|
||||
|
||||
// print out the warnings
|
||||
ClassEnumerator.Warning[] warnings = clenum.getWarnings();
|
||||
for (int i = 0; i < warnings.length; i++) {
|
||||
System.out.println("Warning: " + warnings[i].reason);
|
||||
}
|
||||
|
||||
// enumerate over whatever classes match our package
|
||||
while (penum.hasNext()) {
|
||||
System.out.println("Class: " + penum.next());
|
||||
}
|
||||
}
|
||||
|
||||
protected String _package;
|
||||
protected boolean _subpkgs;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
//
|
||||
// $Id: RegexpEnumerator.java,v 1.2 2003/01/28 22:39:35 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
/**
|
||||
* The regex enumerator filters classes based on a regular expression.
|
||||
*/
|
||||
public class RegexpEnumerator extends FilterEnumerator
|
||||
{
|
||||
public RegexpEnumerator (String regexp, String exregex, Iterator source)
|
||||
throws PatternSyntaxException
|
||||
{
|
||||
super(source);
|
||||
_regexp = Pattern.compile(regexp);
|
||||
if (exregex != null) {
|
||||
_exreg = Pattern.compile(exregex);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean filterClass (String clazz)
|
||||
{
|
||||
return !(_regexp.matcher(clazz).matches() &&
|
||||
(_exreg == null || !_exreg.matcher(clazz).matches()));
|
||||
}
|
||||
|
||||
protected Pattern _regexp;
|
||||
protected Pattern _exreg;
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
//
|
||||
// $Id: ZipFileEnumerator.java,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.clenum;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.*;
|
||||
|
||||
import com.samskivert.viztool.Log;
|
||||
|
||||
/**
|
||||
* The zip file enumerator enumerates all of the classes in a .zip class
|
||||
* archive.
|
||||
*/
|
||||
public class ZipFileEnumerator extends ComponentEnumerator
|
||||
{
|
||||
/**
|
||||
* Constructs a prototype enumerator that can be used for matching.
|
||||
*/
|
||||
public ZipFileEnumerator ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a zip file enumerator with the specified zip file for
|
||||
* enumeration.
|
||||
*/
|
||||
public ZipFileEnumerator (String zippath)
|
||||
throws EnumerationException
|
||||
{
|
||||
try {
|
||||
_zipfile = new ZipFile(zippath);
|
||||
_entenum = _zipfile.entries();
|
||||
scanToNextClass();
|
||||
|
||||
} catch (IOException ioe) {
|
||||
String msg = "Can't enumerate zip file '" + zippath + "': " +
|
||||
ioe.getMessage();
|
||||
throw new EnumerationException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public boolean matchesComponent (String component)
|
||||
{
|
||||
return component.endsWith(ZIP_SUFFIX);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public ComponentEnumerator enumerate (String component)
|
||||
throws EnumerationException
|
||||
{
|
||||
return new ZipFileEnumerator(component);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public boolean hasMoreClasses ()
|
||||
{
|
||||
return (_nextClass != null);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public String nextClass ()
|
||||
{
|
||||
String clazz = _nextClass;
|
||||
_nextClass = null;
|
||||
scanToNextClass();
|
||||
return clazz;
|
||||
}
|
||||
|
||||
protected void scanToNextClass ()
|
||||
{
|
||||
// if we've already scanned to the end of our zipfile, we can bail
|
||||
// immediately
|
||||
if (_zipfile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise scan through the zip contents for the next thing that
|
||||
// looks like a class
|
||||
while (_entenum.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry)_entenum.nextElement();
|
||||
String nextClass = entry.getName();
|
||||
if (nextClass.endsWith(CLASS_SUFFIX)) {
|
||||
_nextClass = pathToClassName(nextClass);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we've reached the end of the zip file, we want to close
|
||||
// things up
|
||||
if (_zipfile != null && _nextClass == null) {
|
||||
try {
|
||||
_zipfile.close();
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Error closing archive: " + ioe.getMessage());
|
||||
}
|
||||
_zipfile = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected ZipFile _zipfile;
|
||||
protected Enumeration _entenum;
|
||||
protected String _nextClass;
|
||||
|
||||
protected static final String ZIP_SUFFIX = ".zip";
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
|
||||
$Id: package.html,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
|
||||
viztool - a tool for visualizing collections of java classes
|
||||
Copyright (C) 2001 Michael Bayne
|
||||
|
||||
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.1 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.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
-->
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
|
||||
Provides the ability to enumerate over all classes in the classpath
|
||||
and filter those enumerations.
|
||||
|
||||
<p> The main interface for enumerating classes is the {@link
|
||||
com.samskivert.viztool.enum.ClassEnumerator}. It scans through the
|
||||
class path and attempts to match a component enumerator to each
|
||||
component. The {@link
|
||||
com.samskivert.viztool.enum.DirectoryEnumerator} is used for all
|
||||
components that don't match one of the other (zip or jar)
|
||||
enumerators. These component enumerators are then used in turn to
|
||||
enumerate through all of the classes in the class path.
|
||||
|
||||
<p> The enumeration can be filtered by making use of a {@link
|
||||
com.samskivert.viztool.enum.FilterEnumerator}.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
-189
@@ -1,189 +0,0 @@
|
||||
//
|
||||
// $Id: CascadingChainVisualizer.java,v 1.11 2001/12/01 05:28:01 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.hierarchy;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.geom.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.samskivert.viztool.util.FontPicker;
|
||||
import com.samskivert.viztool.util.LayoutUtil;
|
||||
import com.samskivert.viztool.util.RenderUtil;
|
||||
|
||||
/**
|
||||
* The cascading chain visualizer lays out chains in the standard
|
||||
* cascading format that looks something like this:
|
||||
*
|
||||
* <pre>
|
||||
* Foo
|
||||
* |
|
||||
* +-> Bar
|
||||
* | |
|
||||
* | +-> Biff
|
||||
* |
|
||||
* +-> Baz
|
||||
* </pre>
|
||||
*/
|
||||
public class CascadingChainVisualizer
|
||||
implements ChainVisualizer
|
||||
{
|
||||
// docs inherited from interface
|
||||
public void layoutChain (Chain chain, Graphics2D gfx)
|
||||
{
|
||||
FontRenderContext frc = gfx.getFontRenderContext();
|
||||
|
||||
// the header will be the name of this chain surrounded by N
|
||||
// points of space and a box
|
||||
Rectangle2D bounds = LayoutUtil.getTextBox(
|
||||
chain.getRoot().isInterface() ? FontPicker.getInterfaceFont() :
|
||||
FontPicker.getClassFont(), frc, chain.getName());
|
||||
|
||||
// add our inner classes and interface implementations, but only
|
||||
// if we're not an out of package class
|
||||
if (chain.inPackage()) {
|
||||
String[] impls = chain.getImplementsNames();
|
||||
bounds = LayoutUtil.accomodate(
|
||||
bounds, FontPicker.getImplementsFont(),
|
||||
frc, LayoutUtil.SUBORDINATE_INSET, impls);
|
||||
String[] decls = chain.getDeclaresNames();
|
||||
bounds = LayoutUtil.accomodate(
|
||||
bounds, FontPicker.getDeclaresFont(),
|
||||
frc, LayoutUtil.SUBORDINATE_INSET, decls);
|
||||
}
|
||||
|
||||
double maxwid = bounds.getWidth();
|
||||
|
||||
// the children will be below the name of this chain and inset by
|
||||
// four points to make space for the connecty lines
|
||||
double x = 2*LayoutUtil.GAP, y = bounds.getHeight();
|
||||
ArrayList kids = chain.getChildren();
|
||||
|
||||
for (int i = 0; i < kids.size(); i++) {
|
||||
Chain kid = (Chain)kids.get(i);
|
||||
Rectangle2D kbounds = kid.getBounds();
|
||||
y += LayoutUtil.GAP; // add the gap
|
||||
kid.setBounds(x, y, kbounds.getWidth(), kbounds.getHeight());
|
||||
y += kbounds.getHeight(); // add the dimensions of the kid
|
||||
// track max width
|
||||
if (maxwid < (x + kbounds.getWidth())) {
|
||||
maxwid = x + kbounds.getWidth();
|
||||
}
|
||||
}
|
||||
|
||||
// set the dimensions of the main chain
|
||||
Rectangle2D cbounds = chain.getBounds();
|
||||
chain.setBounds(cbounds.getX(), cbounds.getY(), maxwid, y);
|
||||
}
|
||||
|
||||
// docs inherited from interface
|
||||
public void renderChain (Chain chain, Graphics2D gfx)
|
||||
{
|
||||
// figure out where we'll be rendering
|
||||
Rectangle2D bounds = chain.getBounds();
|
||||
double x = bounds.getX() + LayoutUtil.HEADER_BORDER;
|
||||
double y = bounds.getY() + LayoutUtil.HEADER_BORDER;
|
||||
double maxwid = 0;
|
||||
|
||||
// draw the name
|
||||
FontRenderContext frc = gfx.getFontRenderContext();
|
||||
Font font = chain.getRoot().isInterface() ?
|
||||
FontPicker.getInterfaceFont() : FontPicker.getClassFont();
|
||||
Rectangle2D bnds =
|
||||
RenderUtil.renderString(gfx, frc, font, x, y, chain.getName());
|
||||
maxwid = Math.max(maxwid, bnds.getWidth() +
|
||||
2*LayoutUtil.HEADER_BORDER);
|
||||
y += bnds.getHeight();
|
||||
|
||||
// draw the interface and inner class info, but only if we're not
|
||||
// an out of package class
|
||||
if (chain.inPackage()) {
|
||||
// render the implemented interfaces
|
||||
String[] impls = chain.getImplementsNames();
|
||||
bnds = RenderUtil.renderStrings(
|
||||
gfx, frc, FontPicker.getImplementsFont(),
|
||||
x + LayoutUtil.SUBORDINATE_INSET, y, impls);
|
||||
maxwid = Math.max(maxwid, bnds.getWidth() +
|
||||
2*LayoutUtil.HEADER_BORDER +
|
||||
LayoutUtil.SUBORDINATE_INSET);
|
||||
y += bnds.getHeight();
|
||||
|
||||
// render the declared inner classes
|
||||
String[] decls = chain.getDeclaresNames();
|
||||
bnds = RenderUtil.renderStrings(
|
||||
gfx, frc, FontPicker.getDeclaresFont(),
|
||||
x + LayoutUtil.SUBORDINATE_INSET, y, decls);
|
||||
maxwid = Math.max(maxwid, bnds.getWidth() +
|
||||
2*LayoutUtil.HEADER_BORDER +
|
||||
LayoutUtil.SUBORDINATE_INSET);
|
||||
y += bnds.getHeight();
|
||||
}
|
||||
|
||||
// leave a border at the bottom as well
|
||||
y += LayoutUtil.HEADER_BORDER;
|
||||
|
||||
// stroke a box that will contain the name
|
||||
Rectangle2D outline = new Rectangle2D.Double(
|
||||
bounds.getX(), bounds.getY(), maxwid, y - bounds.getY());
|
||||
gfx.draw(outline);
|
||||
|
||||
// keep track of the bottom
|
||||
double height = y;
|
||||
|
||||
// reset our top level coords
|
||||
x = bounds.getX();
|
||||
y = bounds.getY();
|
||||
|
||||
// render our connecty lines
|
||||
ArrayList kids = chain.getChildren();
|
||||
if (kids.size() > 0) {
|
||||
GeneralPath path = new GeneralPath();
|
||||
Rectangle2D kbounds = ((Chain)kids.get(0)).getBounds();
|
||||
double half = kbounds.getX()/2;
|
||||
path.moveTo((float)(x + half), (float)height);
|
||||
|
||||
for (int i = 0; i < kids.size(); i++) {
|
||||
Chain kid = (Chain)kids.get(i);
|
||||
kbounds = kid.getBounds();
|
||||
double ly = y + kbounds.getY() + 2*LayoutUtil.HEADER_BORDER;
|
||||
path.lineTo((float)(x + half), (float)ly);
|
||||
path.lineTo((float)(x + kbounds.getX()), (float)ly);
|
||||
path.moveTo((float)(x + half), (float)ly);
|
||||
}
|
||||
|
||||
gfx.draw(path);
|
||||
}
|
||||
|
||||
// translate the gfx so that 0,0 is at our origin
|
||||
gfx.translate(x, y);
|
||||
|
||||
// now render the kids
|
||||
for (int i = 0; i < kids.size(); i++) {
|
||||
Chain kid = (Chain)kids.get(i);
|
||||
renderChain(kid, gfx);
|
||||
}
|
||||
|
||||
// undo our prior translation
|
||||
gfx.translate(-x, -y);
|
||||
}
|
||||
}
|
||||
@@ -1,418 +0,0 @@
|
||||
//
|
||||
// $Id: Chain.java,v 1.10 2001/11/30 22:57:31 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.hierarchy;
|
||||
|
||||
import java.util.*;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import com.samskivert.viztool.layout.Element;
|
||||
|
||||
/**
|
||||
* A chain is used by the hierarchy visualizer to represent inheritance
|
||||
* chains.
|
||||
*/
|
||||
public class Chain implements Element
|
||||
{
|
||||
/**
|
||||
* Constructs a chain with the specified class as its root.
|
||||
*/
|
||||
public Chain (String name, Class root, boolean inpkg)
|
||||
{
|
||||
_name = name;
|
||||
_root = root;
|
||||
_inpkg = inpkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this chain (which should be used when
|
||||
* displaying the chain).
|
||||
*/
|
||||
public String getName ()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class that forms the root of this chain.
|
||||
*/
|
||||
public Class getRoot ()
|
||||
{
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the class represented by this point in the chain is
|
||||
* in the package we are visualizing, false if it is not.
|
||||
*/
|
||||
public boolean inPackage ()
|
||||
{
|
||||
return _inpkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the class that forms the root of this chain.
|
||||
*/
|
||||
public String getRootName ()
|
||||
{
|
||||
return _root.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts this chain's children and the children's children so that a
|
||||
* particular ordering is observed throughout the tree (generally
|
||||
* alphabetical, but other orderings could be used).
|
||||
*/
|
||||
public void sortChildren (Comparator comp)
|
||||
{
|
||||
// my kingdom for List.sort() or even ArrayList.sort()... sigh.
|
||||
Chain[] kids = new Chain[_children.size()];
|
||||
_children.toArray(kids);
|
||||
Arrays.sort(kids, comp);
|
||||
_children.clear();
|
||||
for (int i = 0; i < kids.length; i++) {
|
||||
// sort each child
|
||||
kids[i].sortChildren(comp);
|
||||
_children.add(kids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the interfaces implemented by this class.
|
||||
*/
|
||||
public String[] getImplementsNames ()
|
||||
{
|
||||
Class[] ifaces = _root.getInterfaces();
|
||||
String[] names = new String[ifaces.length];
|
||||
String pkg = ChainUtil.pkgFromClass(_root.getName());
|
||||
|
||||
for (int i = 0; i < ifaces.length; i++) {
|
||||
String name = ifaces[i].getName();
|
||||
String ipkg = ChainUtil.pkgFromClass(name);
|
||||
if (pkg.equals(ipkg)) {
|
||||
names[i] = ChainUtil.nameFromClass(name);
|
||||
} else {
|
||||
names[i] = removeOverlap(pkg, name);
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
protected static String removeOverlap (String pkg, String name)
|
||||
{
|
||||
// strip off package elements until we've eliminated all but one
|
||||
// level of overlap
|
||||
String overlap = "";
|
||||
int didx;
|
||||
|
||||
while ((didx = pkg.indexOf(".", overlap.length()+1)) != -1) {
|
||||
// see if this chunk still overlaps
|
||||
String prefix = pkg.substring(0, didx);
|
||||
if (name.startsWith(prefix)) {
|
||||
overlap = prefix;
|
||||
} else {
|
||||
// we've stopped overlapping, we need to back up one
|
||||
// element and then we're good to go
|
||||
if ((didx = overlap.lastIndexOf(".")) == -1) {
|
||||
overlap = "";
|
||||
} else {
|
||||
overlap = overlap.substring(0, didx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if there's an overlap, remove it
|
||||
if (overlap.length() > 0) {
|
||||
return ".." + name.substring(overlap.length());
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the inner classes declared by this class.
|
||||
*/
|
||||
public String[] getDeclaresNames ()
|
||||
{
|
||||
Class[] decls = _root.getDeclaredClasses();
|
||||
ArrayList names = new ArrayList();
|
||||
|
||||
for (int i = 0; i < decls.length; i++) {
|
||||
String name = decls[i].getName();
|
||||
|
||||
// strip off anything up to and including the dollar
|
||||
int didx = name.indexOf("$");
|
||||
if (didx != -1) {
|
||||
name = name.substring(didx+1);
|
||||
}
|
||||
|
||||
// if this inner class name is a number, it's an anonymous
|
||||
// class and we want to skip it
|
||||
try {
|
||||
Integer.parseInt(name);
|
||||
continue;
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
|
||||
// otherwise it passes the test
|
||||
names.add(name);
|
||||
}
|
||||
|
||||
String[] anames = new String[names.size()];
|
||||
names.toArray(anames);
|
||||
return anames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>Rectangle2D</code> instance representing the size
|
||||
* of this chain (and all contained subchains).
|
||||
*/
|
||||
public Rectangle2D getBounds ()
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounds of this chain.
|
||||
*
|
||||
* @see #getBounds
|
||||
*/
|
||||
public void setBounds (double x, double y, double width, double height)
|
||||
{
|
||||
_bounds.setRect(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array list containing the children chains of this chain.
|
||||
* If this chain has no children the list will be of zero length but
|
||||
* will not be null. This list should <em>not</em> be modified. Oh,
|
||||
* for a <code>const</code> keyword.
|
||||
*/
|
||||
public ArrayList getChildren ()
|
||||
{
|
||||
return _children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lays out all of the children of this chain and then requests that
|
||||
* the supplied layout manager arrange those children and compute the
|
||||
* dimensions of this chain based on all of that information.
|
||||
*
|
||||
* @param gfx the graphics context to use when computing dimensions.
|
||||
* @param cviz the chain visualizer to be used for laying out.
|
||||
* @param width the width in which the chain must fit.
|
||||
* @param height the height in which the chain must fit.
|
||||
*
|
||||
* @return if the chain cannot be laid out in the required dimensions,
|
||||
* branches of the chain will be removed so that it can fit into the
|
||||
* necessary dimensions. A new chain will be created with the
|
||||
* remaining branches which should be laid out itself so that it too
|
||||
* may further prune itself to fit into the necessary dimensions. If
|
||||
* the chain fits into the requested dimensions, null will be
|
||||
* returned.
|
||||
*/
|
||||
public Chain layout (Graphics2D gfx, ChainVisualizer cviz,
|
||||
double width, double height)
|
||||
{
|
||||
// lay everything out
|
||||
layout(gfx, cviz);
|
||||
|
||||
// determine if we need to do some pruning (we only deal with
|
||||
// height pruning presently)
|
||||
if (_bounds.getHeight() <= height) {
|
||||
return null;
|
||||
}
|
||||
|
||||
double x = 0, y = 0;
|
||||
Chain oflow = pruneOverflow(x, y, width, height);
|
||||
// if something wigged out and we try to overflow our whole selves
|
||||
// at this point (like this chain is one big fat chain with no
|
||||
// children that doesn't fit into the space) we must punt and
|
||||
// pretend like there's no overflow
|
||||
return (oflow == this) ? null : oflow;
|
||||
}
|
||||
|
||||
protected void layout (Graphics2D gfx, ChainVisualizer cviz)
|
||||
{
|
||||
// first layout our children
|
||||
for (int i = 0; i < _children.size(); i++) {
|
||||
Chain child = (Chain)_children.get(i);
|
||||
child.layout(gfx, cviz);
|
||||
}
|
||||
|
||||
// now lay ourselves out
|
||||
cviz.layoutChain(this, gfx);
|
||||
}
|
||||
|
||||
protected Chain pruneOverflow (
|
||||
double x, double y, double width, double height)
|
||||
{
|
||||
// offset our current position by the position of this chain
|
||||
Rectangle2D bounds = getBounds();
|
||||
x += bounds.getX();
|
||||
y += bounds.getY();
|
||||
|
||||
Chain oflow = null;
|
||||
|
||||
for (int i = 0; i < _children.size(); i++) {
|
||||
Chain child = (Chain)_children.get(i);
|
||||
|
||||
// if we've switched to flowing over, just add this chain to
|
||||
// the overflow chain (and remove it from ourselves)
|
||||
if (oflow != null) {
|
||||
_children.remove(i--);
|
||||
oflow._children.add(child);
|
||||
continue;
|
||||
}
|
||||
|
||||
Rectangle2D cbounds = child.getBounds();
|
||||
double cx = cbounds.getX(), cy = cbounds.getY();
|
||||
|
||||
// if this child doesn't fit in the current space, we need to
|
||||
// break it up and overflow the extra nodes
|
||||
if (y + cy + cbounds.getHeight() > height) {
|
||||
Chain coflow = child.pruneOverflow(x, y, width, height);
|
||||
|
||||
// make sure this child claims some sort of overflow (if
|
||||
// it doesn't something is wacked, but we'll try to deal)
|
||||
if (coflow != null) {
|
||||
// if this entire child is overflowed
|
||||
if (coflow == child) {
|
||||
// remove the child from this chain and add it to our
|
||||
// overflow chain
|
||||
_children.remove(i--);
|
||||
}
|
||||
// regardless, add what we got to the overflow chain
|
||||
oflow = createOverflowChain();
|
||||
oflow._children.add(coflow);
|
||||
|
||||
} else {
|
||||
System.err.println("Overflowing child unable " +
|
||||
"to overflow " + child._name + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have no children (or we overflowed *all* of our children)
|
||||
// then we need to overflow ourselves rather than create a new
|
||||
// chain for overflowing
|
||||
if (_children.size() == 0) {
|
||||
// grab our kids back from the overflow chain
|
||||
if (oflow != null) {
|
||||
_children = oflow._children;
|
||||
}
|
||||
return this;
|
||||
|
||||
} else {
|
||||
// otherwise, adjust our height to just enclose the height of
|
||||
// our last child because we removed some children and changed
|
||||
// our dimensions. this is sort of a hack because it assumes
|
||||
// that the chain visualizer isn't leaving any gap beyond the
|
||||
// bottom of a child chain but it's somewhat safe because if
|
||||
// they did, that gap would accumulate unaesthetically
|
||||
Chain child = (Chain)_children.get(_children.size()-1);
|
||||
Rectangle2D cbounds = child.getBounds();
|
||||
_bounds.setRect(_bounds.getX(), _bounds.getY(), _bounds.getWidth(),
|
||||
cbounds.getY() + cbounds.getHeight());
|
||||
}
|
||||
|
||||
return oflow;
|
||||
}
|
||||
|
||||
protected Chain createOverflowChain ()
|
||||
{
|
||||
return new Chain(_name, _root, _inpkg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (String name, Class child)
|
||||
{
|
||||
// we assume that the addition of a derived class is only done for
|
||||
// classes that are in the package we're visualizing. out of
|
||||
// package classes are only included as roots of chains that
|
||||
// subsequently contain classes that are in the package
|
||||
Chain chain = new Chain(name, child, true);
|
||||
if (!_children.contains(chain)) {
|
||||
_children.add(chain);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the chain for the specified target class and returns it if
|
||||
* it is a registered child of this chain. Returns null if no child
|
||||
* chain of this chain contains the specified target class.
|
||||
*/
|
||||
public Chain getChain (Class target)
|
||||
{
|
||||
if (_root.equals(target)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// just do a depth first search because it's fun
|
||||
for (int i = 0; i < _children.size(); i++) {
|
||||
Chain chain = ((Chain)_children.get(i)).getChain(target);
|
||||
if (chain != null) {
|
||||
return chain;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
if (other == null) {
|
||||
return false;
|
||||
} else if (other instanceof Chain) {
|
||||
return ((Chain)other)._root.equals(_root);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
StringBuffer out = new StringBuffer();
|
||||
toString("", out);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
protected void toString (String indent, StringBuffer out)
|
||||
{
|
||||
out.append(indent).append(_name).append("\n");
|
||||
for (int i = 0; i < _children.size(); i++) {
|
||||
Chain child = (Chain)_children.get(i);
|
||||
child.toString(indent + " ", out);
|
||||
}
|
||||
}
|
||||
|
||||
protected String _name;
|
||||
protected Class _root;
|
||||
protected boolean _inpkg;
|
||||
|
||||
protected ArrayList _children = new ArrayList();
|
||||
protected Rectangle2D _bounds = new Rectangle2D.Double();
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
//
|
||||
// $Id: ChainGroup.java,v 1.13 2001/12/03 08:34:53 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.hierarchy;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.util.*;
|
||||
|
||||
import com.samskivert.viztool.layout.ElementLayout;
|
||||
import com.samskivert.viztool.layout.PackedColumnElementLayout;
|
||||
import com.samskivert.viztool.util.FontPicker;
|
||||
|
||||
/**
|
||||
* 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, pkg, iter);
|
||||
|
||||
// sort our roots
|
||||
for (int i = 0; i < _roots.size(); i++) {
|
||||
Chain root = (Chain)_roots.get(i);
|
||||
root.sortChildren(NAME_COMP);
|
||||
}
|
||||
|
||||
// System.err.println(_roots.size() + " chains for " + pkg + ".");
|
||||
}
|
||||
|
||||
protected ChainGroup (String pkg, ArrayList roots)
|
||||
{
|
||||
_pkg = pkg;
|
||||
_roots = roots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimensions of this chain group. This value is only
|
||||
* valid after <code>layout</code> has been called.
|
||||
*/
|
||||
public Rectangle2D getBounds ()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the upper left coordinate of this group. The group itself
|
||||
* never looks at this information, but it will be made available as
|
||||
* the x and y coordinates of the rectangle returned by
|
||||
* <code>getBounds</code>.
|
||||
*/
|
||||
public void setPosition (double x, double y)
|
||||
{
|
||||
_size.setRect(x, y, _size.getWidth(), _size.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page on which this group should be rendered.
|
||||
*/
|
||||
public int getPage ()
|
||||
{
|
||||
return _page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the page on which this group should be rendered.
|
||||
*/
|
||||
public void setPage (int page)
|
||||
{
|
||||
_page = page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lays out the chains in this group and returns the total size. If
|
||||
* the layout process requires that this chain group be split across
|
||||
* multiple pages, a new chain group containing the overflow chains
|
||||
* will be returned. If the group fits in the allotted space, null
|
||||
* will be returned.
|
||||
*/
|
||||
public ChainGroup layout (
|
||||
Graphics2D gfx, double pageWidth, double pageHeight)
|
||||
{
|
||||
// we'll need room to incorporate our title
|
||||
TextLayout layout = new TextLayout(_pkg, FontPicker.getTitleFont(),
|
||||
gfx.getFontRenderContext());
|
||||
|
||||
// we let the title stick halfway up out of our rectangular
|
||||
// bounding box
|
||||
Rectangle2D tbounds = layout.getBounds();
|
||||
double titleAscent = tbounds.getHeight()/2;
|
||||
|
||||
// keep room for our border and title
|
||||
pageWidth -= 2*BORDER;
|
||||
pageHeight -= (2*BORDER + titleAscent);
|
||||
|
||||
// lay out the internal structure of our chains
|
||||
ChainVisualizer clay = new CascadingChainVisualizer();
|
||||
for (int i = 0; i < _roots.size(); i++) {
|
||||
Chain chain = (Chain)_roots.get(i);
|
||||
Chain oflow = chain.layout(gfx, clay, pageWidth, pageHeight);
|
||||
// if this chain overflowed when being laid out, add the newly
|
||||
// created root to our list
|
||||
if (oflow != null) {
|
||||
_roots.add(i+1, oflow);
|
||||
}
|
||||
}
|
||||
|
||||
// arrange them on the page
|
||||
ElementLayout elay = new PackedColumnElementLayout();
|
||||
ArrayList overflow = new ArrayList();
|
||||
_size = elay.layout(_roots, pageWidth, pageHeight, overflow);
|
||||
|
||||
// make sure we're wide enough for our title
|
||||
double width = Math.max(_size.getWidth(), layout.getAdvance() + 4);
|
||||
|
||||
// adjust for our border and title
|
||||
double height = _size.getHeight() + titleAscent;
|
||||
_size.setRect(0, 0, width + 2*BORDER, height + 2*BORDER);
|
||||
|
||||
// if we have overflow elements, create a new chain group with
|
||||
// these elements, remove them from our roots list and be on our
|
||||
// way
|
||||
if (overflow.size() > 0) {
|
||||
// remove the overflow roots from our list
|
||||
for (int i = 0; i < overflow.size(); i++) {
|
||||
_roots.remove(overflow.get(i));
|
||||
}
|
||||
return new ChainGroup(_pkg, overflow);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the chains in this group to the supplied graphics object.
|
||||
* This function requires that <code>layout</code> has previously been
|
||||
* called to lay out the group's chains.
|
||||
*
|
||||
* @see #layout
|
||||
*/
|
||||
public void render (Graphics2D gfx, double x, double y)
|
||||
{
|
||||
TextLayout layout = new TextLayout(_pkg, FontPicker.getTitleFont(),
|
||||
gfx.getFontRenderContext());
|
||||
|
||||
// we let the title stick halfway up out of our rectangular
|
||||
// bounding box
|
||||
Rectangle2D tbounds = layout.getBounds();
|
||||
double titleAscent = tbounds.getHeight()/2;
|
||||
double dy = -tbounds.getY();
|
||||
|
||||
// print our title
|
||||
layout.draw(gfx, (float)(x + BORDER + 2), (float)(y + dy));
|
||||
|
||||
// shift everything down by the ascent of the title
|
||||
y += titleAscent;
|
||||
|
||||
// translate to our rendering area
|
||||
double cx = x + BORDER;
|
||||
double cy = y + BORDER;
|
||||
gfx.translate(cx, cy);
|
||||
|
||||
// render our chains
|
||||
ChainVisualizer renderer = new CascadingChainVisualizer();
|
||||
for (int i = 0; i < _roots.size(); i++) {
|
||||
Chain chain = (Chain)_roots.get(i);
|
||||
Rectangle2D bounds = chain.getBounds();
|
||||
// render the chain
|
||||
renderer.renderChain(chain, gfx);
|
||||
}
|
||||
|
||||
// undo the translation
|
||||
gfx.translate(-cx, -cy);
|
||||
|
||||
// print our border box
|
||||
double height = _size.getHeight() - titleAscent;
|
||||
GeneralPath path = new GeneralPath();
|
||||
path.moveTo((float)(x + BORDER), (float)y);
|
||||
path.lineTo((float)x, (float)y);
|
||||
path.lineTo((float)x, (float)(y + height));
|
||||
path.lineTo((float)(x + _size.getWidth()),
|
||||
(float)(y + height));
|
||||
path.lineTo((float)(x + _size.getWidth()), (float)y);
|
||||
path.lineTo((float)(x + BORDER + layout.getAdvance() + 4), (float)y);
|
||||
gfx.draw(path);
|
||||
}
|
||||
|
||||
public Chain getRoot (int index)
|
||||
{
|
||||
return (Chain)_roots.get(index);
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return "[pkg=" + _pkg + ", roots=" + _roots.size() +
|
||||
", size=" + _size + ", page=" + _page + "]";
|
||||
}
|
||||
|
||||
protected String _pkg;
|
||||
protected ArrayList _roots;
|
||||
|
||||
protected Rectangle2D _size;
|
||||
protected int _page;
|
||||
|
||||
protected static final double BORDER = 72/8;
|
||||
|
||||
/**
|
||||
* Compares the names of two chains. Used to sort them into
|
||||
* alphabetical order.
|
||||
*/
|
||||
protected static class NameComparator implements Comparator
|
||||
{
|
||||
public int compare (Object o1, Object o2)
|
||||
{
|
||||
Chain c1 = (Chain)o1;
|
||||
Chain c2 = (Chain)o2;
|
||||
return c1.getName().compareTo(c2.getName());
|
||||
}
|
||||
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
return (other == this);
|
||||
}
|
||||
}
|
||||
|
||||
protected static final Comparator NAME_COMP = new NameComparator();
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
//
|
||||
// $Id: ChainUtil.java,v 1.8 2001/12/03 08:34:53 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.hierarchy;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.viztool.Log;
|
||||
|
||||
/**
|
||||
* Chain related utility functions.
|
||||
*/
|
||||
public class ChainUtil
|
||||
{
|
||||
/**
|
||||
* Builds a list of chains for the classes enumerated by the supplied
|
||||
* enumerator. Classes outside the specified package root will be
|
||||
* ignored except where they are the direct parent of an enumerated
|
||||
* class inside the package root.
|
||||
*
|
||||
* @return an array list containing all of the root chains.
|
||||
*/
|
||||
public static ArrayList buildChains (
|
||||
String pkgroot, String pkg, Iterator iter)
|
||||
{
|
||||
ArrayList roots = new ArrayList();
|
||||
computeRoots(pkgroot, pkg, iter, roots);
|
||||
return roots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the chain that contains the specified target class as it's
|
||||
* root class in the supplied array list of chains.
|
||||
*
|
||||
* @return the matching chain or null if no chain could be found.
|
||||
*/
|
||||
public static Chain getChain (ArrayList roots, Class target)
|
||||
{
|
||||
// figure out which of our root chains (if any) contains the
|
||||
// specified class
|
||||
for (int i = 0; i < roots.size(); i++) {
|
||||
Chain root = (Chain)roots.get(i);
|
||||
Chain chain = root.getChain(target);
|
||||
if (chain != null) {
|
||||
return chain;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the classes in the supplied array list of chain instances to
|
||||
* stdout.
|
||||
*/
|
||||
public static void dumpClasses (PrintStream out, ArrayList roots)
|
||||
{
|
||||
for (int i = 0; i < roots.size(); i++) {
|
||||
Chain root = (Chain)roots.get(i);
|
||||
out.print(root.toString());
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the list of classes provided by the supplied iterator and
|
||||
* constructs a hierarchical representation of those classes.
|
||||
*/
|
||||
protected static void computeRoots (
|
||||
String pkgroot, String pkg, Iterator iter, ArrayList roots)
|
||||
{
|
||||
while (iter.hasNext()) {
|
||||
Class clazz = (Class)iter.next();
|
||||
String name = clazz.getName();
|
||||
// skip classes not in the package in question
|
||||
if (!name.startsWith(pkg) ||
|
||||
name.substring(pkg.length()+1).indexOf(".") != -1) {
|
||||
continue;
|
||||
}
|
||||
insertClass(roots, pkgroot, clazz, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, 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, name, target, true);
|
||||
|
||||
} 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 (!tpkg.equals(ppkg)) {
|
||||
String pname = generateName(parent, pkgroot, true);
|
||||
insertRoot(roots, pname, parent, false);
|
||||
}
|
||||
|
||||
// and now hang ourselves off of our parent class
|
||||
Chain chain = getChain(roots, parent);
|
||||
if (chain == null) {
|
||||
// if there's no chain for our parent class, we'll need to
|
||||
// insert it into the hierarchy
|
||||
boolean samepkg = pkgFromClass(parent.getName()).equals(
|
||||
pkgFromClass(target.getName()));
|
||||
insertClass(roots, pkgroot, parent, !samepkg);
|
||||
// and refetch our chain
|
||||
chain = getChain(roots, parent);
|
||||
// sanity check
|
||||
if (chain == null) {
|
||||
Log.warning("Chain still doesn't exist even though " +
|
||||
"we inserted our parent " +
|
||||
"[class=" + target.getName() +
|
||||
", parent=" + parent.getName() + "].");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// add class will ignore our request if this class was already
|
||||
// added due to some previous operation
|
||||
chain.addClass(name, target);
|
||||
}
|
||||
}
|
||||
|
||||
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, boolean inpkg)
|
||||
{
|
||||
Chain chroot = new Chain(name, root, inpkg);
|
||||
// make sure no chain already exists for this root
|
||||
if (!roots.contains(chroot)) {
|
||||
roots.add(chroot);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
//
|
||||
// $Id: ChainVisualizer.java,v 1.4 2001/11/30 22:57:31 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.hierarchy;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
/**
|
||||
* The chain visualizer is used to compute the dimensions of chains and
|
||||
* their children in preparation for rendering and then to perform said
|
||||
* rendering.
|
||||
*/
|
||||
public interface ChainVisualizer
|
||||
{
|
||||
/**
|
||||
* Assigns positions to the children of the supplied chain based on
|
||||
* the layout policies desired by the implementation and assigns
|
||||
* dimensions to the specified chain based on the dimensions of its
|
||||
* children and the aforementioned layout policies. The children of
|
||||
* the provided chain instance are guaranteed to have been layed out
|
||||
* (meaning they have dimensions but no position) prior to this call.
|
||||
*
|
||||
* @param chain the chain to be layed out.
|
||||
* @param gfx the graphics context to use when computing dimensions.
|
||||
*/
|
||||
public void layoutChain (Chain chain, Graphics2D gfx);
|
||||
|
||||
/**
|
||||
* Renders the specified chain (and its subchains) based on the layout
|
||||
* information (dimensions) already computed for this chain.
|
||||
*
|
||||
* @param chain the chain to be rendered.
|
||||
* @param gfx the graphics context in which to render the chain.
|
||||
*/
|
||||
public void renderChain (Chain chain, Graphics2D gfx);
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
//
|
||||
// $Id: HierarchyVisualizer.java,v 1.16 2001/12/03 08:34:53 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.hierarchy;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.print.*;
|
||||
import java.util.*;
|
||||
|
||||
import com.samskivert.util.Comparators;
|
||||
import com.samskivert.util.CollectionUtil;
|
||||
|
||||
import com.samskivert.viztool.Log;
|
||||
import com.samskivert.viztool.Visualizer;
|
||||
import com.samskivert.viztool.clenum.PackageEnumerator;
|
||||
|
||||
/**
|
||||
* The hierarchy visualizer displays inheritance hierarchies in a compact
|
||||
* representation so that an entire package can be displayed on a single
|
||||
* page (or small number of pages).
|
||||
*/
|
||||
public class HierarchyVisualizer implements Visualizer
|
||||
{
|
||||
// documentation inherited
|
||||
public void setPackageRoot (String pkgroot)
|
||||
{
|
||||
_pkgroot = pkgroot;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setClasses (Iterator iter)
|
||||
{
|
||||
// dump all the classes into an array list so that we can
|
||||
// repeatedly scan through the list
|
||||
CollectionUtil.addAll(_classes, iter);
|
||||
|
||||
// compile a list of all packages in our collection
|
||||
HashSet pkgset = new HashSet();
|
||||
iter = _classes.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Class cl = (Class)iter.next();
|
||||
pkgset.add(ChainUtil.pkgFromClass(cl.getName()));
|
||||
}
|
||||
|
||||
// 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);
|
||||
// System.err.println("Scanned " + _packages.length + " packages.");
|
||||
|
||||
// now create chain groups for each package
|
||||
_groups = new ArrayList();
|
||||
for (int i = 0; i < _packages.length; i++) {
|
||||
_groups.add(new ChainGroup(_pkgroot, _packages[i],
|
||||
_classes.iterator()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lays out and renders each of the chain groups that make up this
|
||||
* package hierarchy visualization.
|
||||
*/
|
||||
public int print (Graphics g, PageFormat pf, int pageIndex)
|
||||
throws PrinterException
|
||||
{
|
||||
Graphics2D gfx = (Graphics2D)g;
|
||||
|
||||
// adjust the stroke
|
||||
gfx.setStroke(new BasicStroke(0.1f));
|
||||
|
||||
// only relay things out if the page format has changed
|
||||
if (!pf.equals(_format)) {
|
||||
// keep this around
|
||||
_format = pf;
|
||||
|
||||
// and do the layout
|
||||
layout(gfx, pf.getImageableX(), pf.getImageableY(),
|
||||
pf.getImageableWidth(), pf.getImageableHeight());
|
||||
}
|
||||
|
||||
// render the groups on the requested page
|
||||
int rendered = 0;
|
||||
for (int i = 0; i < _groups.size(); i++) {
|
||||
ChainGroup group = (ChainGroup)_groups.get(i);
|
||||
|
||||
// skip groups not on this page
|
||||
if (group.getPage() != pageIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rectangle2D bounds = group.getBounds();
|
||||
group.render(gfx, bounds.getX(), bounds.getY());
|
||||
rendered++;
|
||||
}
|
||||
|
||||
return (rendered > 0) ? PAGE_EXISTS : NO_SUCH_PAGE;
|
||||
}
|
||||
|
||||
public void layout (Graphics2D gfx, double x, double y,
|
||||
double width, double height)
|
||||
{
|
||||
double starty = y;
|
||||
int pageno = 0;
|
||||
|
||||
// lay out our groups
|
||||
for (int i = 0; i < _groups.size(); i++) {
|
||||
ChainGroup group = (ChainGroup)_groups.get(i);
|
||||
|
||||
// lay out the group in question
|
||||
ChainGroup ngrp = group.layout(gfx, width, height);
|
||||
// if the process of laying this group out caused it to become
|
||||
// split across pages, insert this new group into the list
|
||||
if (ngrp != null) {
|
||||
_groups.add(i+1, ngrp);
|
||||
}
|
||||
|
||||
// determine if we need to skip to the next page or not
|
||||
Rectangle2D bounds = group.getBounds();
|
||||
if ((y > starty) && (y + bounds.getHeight() > height + starty)) {
|
||||
y = starty;
|
||||
pageno++;
|
||||
}
|
||||
|
||||
// assign x and y coordinates to this group
|
||||
group.setPosition(x, y);
|
||||
// make a note of our page index
|
||||
group.setPage(pageno);
|
||||
|
||||
// increment our y location
|
||||
y += (bounds.getHeight() + GAP);
|
||||
}
|
||||
|
||||
// our page count is one more than the highest page number
|
||||
_pageCount = pageno+1;
|
||||
}
|
||||
|
||||
public void paint (Graphics2D gfx, int pageIndex)
|
||||
{
|
||||
// render the groups on the requested page
|
||||
for (int i = 0; i < _groups.size(); i++) {
|
||||
ChainGroup group = (ChainGroup)_groups.get(i);
|
||||
|
||||
// skip groups not on this page
|
||||
if (group.getPage() != pageIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rectangle2D bounds = group.getBounds();
|
||||
group.render((Graphics2D)gfx, bounds.getX(), bounds.getY());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of pages occupied by this visualization. This is
|
||||
* only valid after a call to {@link #layout}.
|
||||
*
|
||||
* @return the page count or -1 if we've not yet been laid out.
|
||||
*/
|
||||
public int getPageCount ()
|
||||
{
|
||||
return _pageCount;
|
||||
}
|
||||
|
||||
protected String _pkgroot;
|
||||
protected ArrayList _classes = new ArrayList();
|
||||
|
||||
protected String[] _packages;
|
||||
protected ArrayList _groups;
|
||||
protected int _pageCount = -1;
|
||||
|
||||
protected PageFormat _format;
|
||||
|
||||
protected static final int GAP = 72/4;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
//
|
||||
// $Id: Element.java,v 1.4 2001/11/30 22:57:31 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.layout;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* A page is composed of elements which have some rectangular bounds.
|
||||
* They can be laid out by <code>ElementLayout</code> implementations in a
|
||||
* general purpose way.
|
||||
*/
|
||||
public interface Element
|
||||
{
|
||||
/**
|
||||
* Returns the name of this element.
|
||||
*/
|
||||
public String getName ();
|
||||
|
||||
/**
|
||||
* Returns the bounds of this element.
|
||||
*/
|
||||
public Rectangle2D getBounds ();
|
||||
|
||||
/**
|
||||
* Sets the bounds of this element.
|
||||
*/
|
||||
public void setBounds (double x, double y, double width, double height);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// $Id: ElementLayout.java,v 1.5 2001/11/30 22:57:31 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.layout;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The element layout is used to lay a collection of elements out on a
|
||||
* page. It computes the desired position of each element and sets it via
|
||||
* <code>setBounds()</code> with the expectation that the location of the
|
||||
* elements will be used later in the rendering process.
|
||||
*/
|
||||
public interface ElementLayout
|
||||
{
|
||||
/**
|
||||
* Lay out the supplied list of elements. Any elements that do not fit
|
||||
* into the allotted space should be added to the overflow list. The
|
||||
* supplied elements list should not be modified.
|
||||
*
|
||||
* @return the bounding dimensions of the collection of elements that
|
||||
* were laid out.
|
||||
*/
|
||||
public Rectangle2D layout (List elements, double pageWidth,
|
||||
double pageHeight, List overflow);
|
||||
}
|
||||
-148
@@ -1,148 +0,0 @@
|
||||
//
|
||||
// $Id: PackedColumnElementLayout.java,v 1.9 2001/12/03 06:13:54 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.layout;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Lays out the elements in columns of balanced height with elements
|
||||
* vertically arranged from tallest to shortest.
|
||||
*/
|
||||
public class PackedColumnElementLayout implements ElementLayout
|
||||
{
|
||||
/**
|
||||
* Configures the element layout to (or not to) first sort by height
|
||||
* before falling back to alphabetical sort.
|
||||
*/
|
||||
public void setSortByHeight (boolean byHeight)
|
||||
{
|
||||
_byHeight = byHeight;
|
||||
}
|
||||
|
||||
// docs inherited from interface
|
||||
public Rectangle2D layout (List elements, double pageWidth,
|
||||
double pageHeight, List overflow)
|
||||
{
|
||||
// sort the elements first by height then alphabetically
|
||||
Element[] elems = new Element[elements.size()];
|
||||
elements.toArray(elems);
|
||||
Arrays.sort(elems, new ElementComparator(_byHeight));
|
||||
|
||||
// lay out the elements across the page
|
||||
double x = 0, y = 0, rowheight = 0, maxwidth = 0;
|
||||
|
||||
for (int i = 0; i < elems.length; i++) {
|
||||
Rectangle2D bounds = elems[i].getBounds();
|
||||
|
||||
// see if we fit into this row or not (but force placement if
|
||||
// we're currently at the left margin)
|
||||
if ((x > 0) && ((x + bounds.getWidth()) > pageWidth)) {
|
||||
// strip off the trailing GAP
|
||||
x -= GAP;
|
||||
// track our maxwidth
|
||||
if (x > maxwidth) {
|
||||
maxwidth = x;
|
||||
}
|
||||
// move down to the next row
|
||||
x = 0;
|
||||
y += (rowheight + GAP);
|
||||
// reset our max rowheight (we set it to -GAP because we
|
||||
// will add rowheight to our last y position to compute
|
||||
// the total height and if no more elements are laid out,
|
||||
// we'll want to remove that trailing gap)
|
||||
rowheight = -GAP;
|
||||
}
|
||||
|
||||
// make sure we fit on this page (but force placement if we're
|
||||
// currently at the top margin)
|
||||
if ((y > 0) && ((y + bounds.getHeight()) > pageHeight)) {
|
||||
// if we didn't fit, we go onto the overflow list
|
||||
overflow.add(elems[i]);
|
||||
// and continue on because maybe some shorter elements
|
||||
// further down the list will fit
|
||||
continue;
|
||||
}
|
||||
|
||||
// lay this element out at our current coordinates
|
||||
elems[i].setBounds(x, y, bounds.getWidth(), bounds.getHeight());
|
||||
|
||||
// keep track of the maximum row height
|
||||
if (bounds.getHeight() > rowheight) {
|
||||
rowheight = bounds.getHeight();
|
||||
}
|
||||
|
||||
// advance in the x direction
|
||||
x += (bounds.getWidth() + GAP);
|
||||
}
|
||||
|
||||
// take a final stab at our maxwidth
|
||||
x -= GAP;
|
||||
if (x > maxwidth) {
|
||||
maxwidth = x;
|
||||
}
|
||||
|
||||
return new Rectangle2D.Double(0, 0, maxwidth, y+rowheight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the sizes of two elements. Used to sort them into order
|
||||
* from highest to lowest. Secondarily sorts alphabetically on the
|
||||
* element names.
|
||||
*/
|
||||
protected static class ElementComparator implements Comparator
|
||||
{
|
||||
public ElementComparator (boolean byHeight)
|
||||
{
|
||||
_byHeight = byHeight;
|
||||
}
|
||||
|
||||
public int compare (Object o1, Object o2)
|
||||
{
|
||||
Element e1 = (Element)o1;
|
||||
Element e2 = (Element)o2;
|
||||
int diff = 0;
|
||||
|
||||
// if we're sorting by height, check that now
|
||||
if (_byHeight) {
|
||||
diff = (int)(e2.getBounds().getHeight() -
|
||||
e1.getBounds().getHeight());
|
||||
}
|
||||
|
||||
// if they are the same height (or we're not sorting by
|
||||
// height), sort alphabetically
|
||||
return (diff != 0) ? diff : e1.getName().compareTo(e2.getName());
|
||||
}
|
||||
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
return (other == this);
|
||||
}
|
||||
|
||||
protected boolean _byHeight;
|
||||
}
|
||||
|
||||
/** Whether or not we're sorting by height. */
|
||||
protected boolean _byHeight = true;
|
||||
|
||||
// hard coded for now, half inch margins
|
||||
protected static final double GAP = 72/4;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
|
||||
$Id: package.html,v 1.3 2001/12/03 10:08:33 mdb Exp $
|
||||
|
||||
viztool - a tool for visualizing collections of java classes
|
||||
Copyright (C) 2001 Michael Bayne
|
||||
|
||||
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.1 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.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
-->
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
|
||||
General purpose layout support classes. These include the {@link
|
||||
com.samskivert.viztool.layout.Element} and {@link
|
||||
com.samskivert.viztool.layout.ElementLayout} interfaces.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,51 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
|
||||
$Id: overview.html,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
|
||||
viztool - a tool for visualizing collections of java classes
|
||||
Copyright (C) 2001 Michael Bayne
|
||||
|
||||
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.1 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.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
-->
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
|
||||
<p> viztool is used to generate visualizations of collections of Java
|
||||
classes. These visualizations are intended to be printed out and
|
||||
taped to the wall or set on the desk beside you or folded into paper
|
||||
airplanes and sailed around the room. Thus viztool does not include
|
||||
a sophisticated user interface for viewing these presentations
|
||||
onscreen (use ghostscript for that), although you can actually
|
||||
display them on the screen because the rendering is done via the
|
||||
Java 2D rendering engine.
|
||||
|
||||
<p> viztool aims to provide an extensible framework for generating
|
||||
visualizations of collections of classes. It currently generates
|
||||
inheritance diagrams organized by package, with information on
|
||||
interfaces implemented and (non-anonymous) inner classes as well.
|
||||
|
||||
<p> It is a fairly small and simple collection of code, which is
|
||||
hopefully understandable enough on its own to allow one to dive in
|
||||
and create their own visualizations or enhance an existing
|
||||
one. Comments and contributions are always welcome.
|
||||
|
||||
<p> -- <a href="mailto:mdb@samskivert.com">mdb@samskivert.com</a>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,32 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
|
||||
$Id: package.html,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
|
||||
viztool - a tool for visualizing collections of java classes
|
||||
Copyright (C) 2001 Michael Bayne
|
||||
|
||||
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.1 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.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
-->
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
|
||||
Top-level stuff like the application driver and log wrapper.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,423 +0,0 @@
|
||||
//
|
||||
// $Id: ClassSummary.java,v 1.2 2001/12/03 06:14:03 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.summary;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.samskivert.viztool.Log;
|
||||
import com.samskivert.viztool.layout.Element;
|
||||
import com.samskivert.viztool.util.FontPicker;
|
||||
import com.samskivert.viztool.util.LayoutUtil;
|
||||
import com.samskivert.viztool.util.RenderUtil;
|
||||
|
||||
/**
|
||||
* A class summary displays information about a particular class
|
||||
* (specifically, the interfaces it implements, the class it extends, its
|
||||
* public instances, member functions, and inner class definitions).
|
||||
*/
|
||||
public class ClassSummary
|
||||
implements Element
|
||||
{
|
||||
/**
|
||||
* Constructs a class summary for the specified class.
|
||||
*/
|
||||
public ClassSummary (Class subject, SummaryVisualizer viz)
|
||||
{
|
||||
_viz = viz;
|
||||
_subject = subject;
|
||||
_name = _viz.name(_subject);
|
||||
|
||||
// obtain information on our subject class
|
||||
Class parent = _subject.getSuperclass();
|
||||
if (parent != null && !parent.equals(Object.class)) {
|
||||
_parentName = _viz.name(parent);
|
||||
}
|
||||
|
||||
// get the implemented interfaces
|
||||
Class[] interfaces = _subject.getInterfaces();
|
||||
int icount = interfaces.length;
|
||||
_interfaces = new String[icount];
|
||||
for (int i = 0; i < icount; i++) {
|
||||
_interfaces[i] = _viz.name(interfaces[i]);
|
||||
}
|
||||
|
||||
// create a comparator that we can use to sort the fields and
|
||||
// methods alphabetically and by staticness
|
||||
Comparator comp = new Comparator() {
|
||||
public int compare (Object o1, Object o2) {
|
||||
Member m1 = (Member)o1;
|
||||
Member m2 = (Member)o2;
|
||||
|
||||
int s1 = m1.getModifiers() & Modifier.STATIC;
|
||||
int s2 = m2.getModifiers() & Modifier.STATIC;
|
||||
|
||||
// if one's static and one isn't...
|
||||
if (s1 + s2 == Modifier.STATIC) {
|
||||
// put the statics after the non-statics
|
||||
return s1 - s2;
|
||||
|
||||
} else {
|
||||
// otherwise compare names
|
||||
return m1.getName().compareTo(m2.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals (Object other) {
|
||||
return (other == this);
|
||||
}
|
||||
};
|
||||
|
||||
// get the public fields
|
||||
Field[] fields = _subject.getDeclaredFields();
|
||||
Arrays.sort(fields, comp);
|
||||
ArrayList fsigtypes = new ArrayList();
|
||||
ArrayList fsigs = new ArrayList();
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
Field f = fields[i];
|
||||
if ((f.getModifiers() & Modifier.PUBLIC) != 0) {
|
||||
fsigtypes.add(genFieldTypeSig(f));
|
||||
fsigs.add(f.getName());
|
||||
}
|
||||
}
|
||||
_fieldTypes = new String[fsigtypes.size()];
|
||||
fsigtypes.toArray(_fieldTypes);
|
||||
_fields = new String[fsigs.size()];
|
||||
fsigs.toArray(_fields);
|
||||
|
||||
// get the public constructors and methods
|
||||
ArrayList sigrets = new ArrayList();
|
||||
ArrayList sigs = new ArrayList();
|
||||
Constructor[] ctors = _subject.getConstructors();
|
||||
for (int i = 0; i < ctors.length; i++) {
|
||||
Constructor c = ctors[i];
|
||||
// make sure it's public
|
||||
if ((c.getModifiers() & Modifier.PUBLIC) != 0 &&
|
||||
// skip the zero argument constructor because it's
|
||||
// uninteresting
|
||||
c.getParameterTypes().length > 0) {
|
||||
sigrets.add(" ");
|
||||
sigs.add(genConstructorSig(c));
|
||||
}
|
||||
}
|
||||
Method[] methods = _subject.getDeclaredMethods();
|
||||
Arrays.sort(methods, comp);
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
Method m = methods[i];
|
||||
if ((m.getModifiers() & Modifier.PUBLIC) != 0) {
|
||||
sigrets.add(genMethodRetSig(m));
|
||||
sigs.add(genMethodSig(m));
|
||||
}
|
||||
}
|
||||
_methodReturns = new String[sigrets.size()];
|
||||
sigrets.toArray(_methodReturns);
|
||||
_methods = new String[sigs.size()];
|
||||
sigs.toArray(_methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Introspects on our subject class and determines how much space
|
||||
* we'll need to visualize it.
|
||||
*
|
||||
* @param gfx the graphics context in which this summary will
|
||||
* eventually be rendered.
|
||||
*/
|
||||
public void layout (Graphics2D gfx)
|
||||
{
|
||||
FontRenderContext frc = gfx.getFontRenderContext();
|
||||
|
||||
// the header will be the name of this class surrounded by N
|
||||
// points of space and a box
|
||||
Rectangle2D bounds = LayoutUtil.getTextBox(
|
||||
_subject.isInterface() ? FontPicker.getInterfaceFont() :
|
||||
FontPicker.getClassFont(), frc, _name);
|
||||
double spacing = 0;
|
||||
|
||||
// add our parent class if we've got one
|
||||
if (_parentName != null) {
|
||||
String subtext = "extends " + _parentName;
|
||||
bounds = LayoutUtil.accomodate(
|
||||
bounds, FontPicker.getDeclaresFont(), frc,
|
||||
LayoutUtil.SUBORDINATE_INSET, subtext);
|
||||
}
|
||||
|
||||
// add our interfaces
|
||||
bounds = LayoutUtil.accomodate(
|
||||
bounds, FontPicker.getImplementsFont(), frc,
|
||||
LayoutUtil.SUBORDINATE_INSET, _interfaces);
|
||||
|
||||
// add our fields
|
||||
bounds = LayoutUtil.accomodate(
|
||||
bounds, FontPicker.getClassFont(), frc, 0, _fieldTypes, _fields);
|
||||
spacing += (_fields.length > 0) ? 2*LayoutUtil.HEADER_BORDER : 0;
|
||||
|
||||
// add our constructors and methods
|
||||
bounds = LayoutUtil.accomodate(
|
||||
bounds, FontPicker.getClassFont(), frc, 0,
|
||||
_methodReturns, _methods);
|
||||
spacing += (_methods.length > 0) ? 2*LayoutUtil.HEADER_BORDER : 0;
|
||||
|
||||
// incorporate space for the gaps
|
||||
bounds.setRect(bounds.getX(), bounds.getY(), bounds.getWidth(),
|
||||
bounds.getHeight() + spacing);
|
||||
|
||||
// grab the new bounds
|
||||
_bounds = bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders this class summary to the specified graphics context.
|
||||
*/
|
||||
public void render (Graphics2D gfx)
|
||||
{
|
||||
// figure out where we'll be rendering
|
||||
Rectangle2D bounds = getBounds();
|
||||
double x = bounds.getX() + LayoutUtil.HEADER_BORDER;
|
||||
double y = bounds.getY() + LayoutUtil.HEADER_BORDER;
|
||||
double maxwid = 0, sy1 = 0, sy2 = 0;
|
||||
|
||||
// draw the name
|
||||
FontRenderContext frc = gfx.getFontRenderContext();
|
||||
Font font = _subject.isInterface() ?
|
||||
FontPicker.getInterfaceFont() : FontPicker.getClassFont();
|
||||
Rectangle2D bnds =
|
||||
RenderUtil.renderString(gfx, frc, font, x, y, _name);
|
||||
maxwid = Math.max(maxwid, bnds.getWidth() +
|
||||
2*LayoutUtil.HEADER_BORDER);
|
||||
y += bnds.getHeight();
|
||||
|
||||
// render the parent classname
|
||||
if (_parentName != null) {
|
||||
bnds = RenderUtil.renderString(
|
||||
gfx, frc, FontPicker.getDeclaresFont(),
|
||||
x + LayoutUtil.SUBORDINATE_INSET, y, _parentName);
|
||||
maxwid = Math.max(maxwid, bnds.getWidth() +
|
||||
2*LayoutUtil.HEADER_BORDER +
|
||||
LayoutUtil.SUBORDINATE_INSET);
|
||||
y += bnds.getHeight();
|
||||
}
|
||||
|
||||
// render our implemented interfaces
|
||||
bnds = RenderUtil.renderStrings(
|
||||
gfx, frc, FontPicker.getImplementsFont(),
|
||||
x + LayoutUtil.SUBORDINATE_INSET, y, _interfaces);
|
||||
maxwid = Math.max(maxwid, bnds.getWidth() +
|
||||
2*LayoutUtil.HEADER_BORDER +
|
||||
LayoutUtil.SUBORDINATE_INSET);
|
||||
y += bnds.getHeight();
|
||||
|
||||
// stroke a box that contains the header
|
||||
Rectangle2D outline = new Rectangle2D.Double(
|
||||
bounds.getX(), bounds.getY(),
|
||||
maxwid, y + LayoutUtil.HEADER_BORDER - bounds.getY());
|
||||
gfx.draw(outline);
|
||||
|
||||
// leave space for a separator
|
||||
if (_fields.length > 0) {
|
||||
y += LayoutUtil.HEADER_BORDER;
|
||||
sy1 = y;
|
||||
y += LayoutUtil.HEADER_BORDER;
|
||||
}
|
||||
|
||||
// render our fields
|
||||
bnds = RenderUtil.renderStrings(
|
||||
gfx, frc, FontPicker.getClassFont(), x, y, _fieldTypes, _fields);
|
||||
maxwid = Math.max(maxwid, bnds.getWidth() +
|
||||
2*LayoutUtil.HEADER_BORDER);
|
||||
y += bnds.getHeight();
|
||||
|
||||
// leave space for a separator
|
||||
if (_methods.length > 0) {
|
||||
y += LayoutUtil.HEADER_BORDER;
|
||||
sy2 = y;
|
||||
y += LayoutUtil.HEADER_BORDER;
|
||||
}
|
||||
|
||||
// render our constructors and methods
|
||||
bnds = RenderUtil.renderStrings(
|
||||
gfx, frc, FontPicker.getClassFont(), x, y,
|
||||
_methodReturns, _methods);
|
||||
maxwid = Math.max(maxwid, bnds.getWidth() +
|
||||
2*LayoutUtil.HEADER_BORDER);
|
||||
y += bnds.getHeight();
|
||||
|
||||
// draw our separators now that we know how wide things are
|
||||
double x1 = bounds.getX(), x2 = x1 + maxwid;
|
||||
if (sy1 > 0) {
|
||||
gfx.draw(new Line2D.Double(x1, sy1, x2, sy1));
|
||||
}
|
||||
if (sy2 > 0) {
|
||||
gfx.draw(new Line2D.Double(x1, sy2, x2, sy2));
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public String getName ()
|
||||
{
|
||||
return _subject.getName();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public Rectangle2D getBounds ()
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setBounds (double x, double y, double width, double height)
|
||||
{
|
||||
_bounds.setRect(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a signature for the type of the supplied field.
|
||||
*/
|
||||
public String genFieldTypeSig (Field field)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
if ((field.getModifiers() & Modifier.STATIC) != 0) {
|
||||
buf.append("static ");
|
||||
}
|
||||
buf.append(_viz.name(field.getType())).append(" ");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a signature for the supplied constructor.
|
||||
*/
|
||||
public String genConstructorSig (Constructor ctor)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(_viz.name(ctor.getDeclaringClass())).append(" (");
|
||||
Class[] ptypes = ctor.getParameterTypes();
|
||||
for (int i = 0; i < ptypes.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(_viz.name(ptypes[i]));
|
||||
}
|
||||
buf.append(")");
|
||||
Class[] etypes = ctor.getExceptionTypes();
|
||||
if (etypes.length > 0) {
|
||||
buf.append(" throws ");
|
||||
for (int i = 0; i < etypes.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(_viz.name(etypes[i]));
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a signature for the return value of the supplied method.
|
||||
*/
|
||||
public String genMethodRetSig (Method method)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
if ((method.getModifiers() & Modifier.STATIC) != 0) {
|
||||
buf.append("static ");
|
||||
}
|
||||
buf.append(_viz.name(method.getReturnType()));
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a signature for the supplied method (minus return type).
|
||||
*/
|
||||
public String genMethodSig (Method method)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(method.getName()).append(" (");
|
||||
Class[] ptypes = method.getParameterTypes();
|
||||
for (int i = 0; i < ptypes.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(_viz.name(ptypes[i]));
|
||||
}
|
||||
buf.append(")");
|
||||
Class[] etypes = method.getExceptionTypes();
|
||||
if (etypes.length > 0) {
|
||||
buf.append(" throws ");
|
||||
for (int i = 0; i < etypes.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(_viz.name(etypes[i]));
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return "[subject=" + _subject.getName() + "]";
|
||||
}
|
||||
|
||||
/** The package we're visualizing, which we'll strip from the front of
|
||||
* class names. */
|
||||
protected SummaryVisualizer _viz;
|
||||
|
||||
/** The class for which we're generating a summary visualization. */
|
||||
protected Class _subject;
|
||||
|
||||
/** The cleaned up name of the class we're summarizing. */
|
||||
protected String _name;
|
||||
|
||||
/** The name of our parent class or null if we don't have an
|
||||
* interesting parent class. */
|
||||
protected String _parentName;
|
||||
|
||||
/** The names of interfaces that we implement. */
|
||||
protected String[] _interfaces;
|
||||
|
||||
/** The types of our public fields. */
|
||||
protected String[] _fieldTypes;
|
||||
|
||||
/** The names of our public fields. */
|
||||
protected String[] _fields;
|
||||
|
||||
/** The return types of our public constructors and methods. */
|
||||
protected String[] _methodReturns;
|
||||
|
||||
/** The signatures of our public constructors and methods (minus
|
||||
* return type). */
|
||||
protected String[] _methods;
|
||||
|
||||
/** Our bounds. */
|
||||
protected Rectangle2D _bounds = new Rectangle2D.Double();
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
//
|
||||
// $Id: SummaryVisualizer.java,v 1.3 2001/12/03 08:34:53 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.summary;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import java.awt.print.PageFormat;
|
||||
import java.awt.print.PrinterException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.samskivert.viztool.Log;
|
||||
import com.samskivert.viztool.Visualizer;
|
||||
import com.samskivert.viztool.layout.PackedColumnElementLayout;
|
||||
|
||||
/**
|
||||
* The summary visualizer displays summaries of the enumerated classes.
|
||||
*/
|
||||
public class SummaryVisualizer implements Visualizer
|
||||
{
|
||||
// documentation inherited
|
||||
public void setPackageRoot (String pkgroot)
|
||||
{
|
||||
_pkgroot = pkgroot;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setClasses (Iterator iter)
|
||||
{
|
||||
// remove any old summaries
|
||||
_summaries.clear();
|
||||
|
||||
// create the new summaries
|
||||
while (iter.hasNext()) {
|
||||
_summaries.add(new ClassSummary((Class)iter.next(), this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the visualizer to prefix classnames with their package
|
||||
* names (when they are outside of the visualized package root) or
|
||||
* not.
|
||||
*/
|
||||
public void setDisplayPackageNames (boolean displayPackageNames)
|
||||
{
|
||||
_displayPackageNames = displayPackageNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lays out the class summary visualizations into the specified page
|
||||
* dimensions.
|
||||
*/
|
||||
public void layout (Graphics2D gfx, double x, double y,
|
||||
double width, double height)
|
||||
{
|
||||
// first layout all of our summaries (giving them dimensions)
|
||||
for (int i = 0; i < _summaries.size(); i++) {
|
||||
ClassSummary sum = (ClassSummary)_summaries.get(i);
|
||||
sum.layout(gfx);
|
||||
}
|
||||
|
||||
// now arrange our summaries onto pages
|
||||
_pages = new ArrayList();
|
||||
ArrayList list = new ArrayList(_summaries);
|
||||
ArrayList next = new ArrayList();
|
||||
PackedColumnElementLayout elay = new PackedColumnElementLayout();
|
||||
elay.setSortByHeight(false);
|
||||
|
||||
while (list.size() > 0) {
|
||||
// lay out the elements that fit on this page
|
||||
elay.layout(list, width, height, next);
|
||||
|
||||
// remove the overflowed elements from the list for this page
|
||||
list.removeAll(next);
|
||||
|
||||
// append this page to the pages list
|
||||
_pages.add(list);
|
||||
|
||||
// move to the next page
|
||||
list = next;
|
||||
next = new ArrayList();
|
||||
}
|
||||
|
||||
// finally adjust all of the bounds of the class summaries by the
|
||||
// x and y offset of the page
|
||||
for (int i = 0; i < _summaries.size(); i++) {
|
||||
ClassSummary sum = (ClassSummary)_summaries.get(i);
|
||||
Rectangle2D b = sum.getBounds();
|
||||
sum.setBounds(b.getX()+x, b.getY()+y, b.getWidth(), b.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lays out and renders each of the classes that make up this package
|
||||
* summary visualization.
|
||||
*/
|
||||
public int print (Graphics g, PageFormat pf, int pageIndex)
|
||||
throws PrinterException
|
||||
{
|
||||
Graphics2D gfx = (Graphics2D)g;
|
||||
|
||||
// relay things out if the page format has changed or if we've
|
||||
// never been laid out
|
||||
if (!pf.equals(_format) || _pages == null) {
|
||||
// keep this around
|
||||
_format = pf;
|
||||
|
||||
// and do the layout
|
||||
layout(gfx, pf.getImageableX(), pf.getImageableY(),
|
||||
pf.getImageableWidth(), pf.getImageableHeight());
|
||||
}
|
||||
|
||||
// adjust the stroke
|
||||
gfx.setStroke(new BasicStroke(0.1f));
|
||||
|
||||
// make sure we're rendering a page that we have
|
||||
if (pageIndex < 0 || pageIndex >= _pages.size()) {
|
||||
return NO_SUCH_PAGE;
|
||||
}
|
||||
|
||||
// render the summaries on the requested page
|
||||
ArrayList list = (ArrayList)_pages.get(pageIndex);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
((ClassSummary)list.get(i)).render(gfx);
|
||||
}
|
||||
return PAGE_EXISTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the specified page to the supplied graphics context.
|
||||
*/
|
||||
public void paint (Graphics2D gfx, int pageIndex)
|
||||
{
|
||||
// ignore them if we haven't been laid out or if we have
|
||||
// absolutely nothing to display
|
||||
if (_pages == null || _pages.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (pageIndex >= _pages.size()) {
|
||||
Log.info("Requested to render non-existent page " +
|
||||
"[index=" + pageIndex + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// adjust the stroke
|
||||
gfx.setStroke(new BasicStroke(0.1f));
|
||||
|
||||
// render the summaries on the requested page
|
||||
ArrayList list = (ArrayList)_pages.get(pageIndex);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
((ClassSummary)list.get(i)).render(gfx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of pages occupied by this visualization. This is
|
||||
* only valid after a call to {@link #layout}.
|
||||
*
|
||||
* @return the page count or -1 if we've not yet been laid out.
|
||||
*/
|
||||
public int getPageCount ()
|
||||
{
|
||||
return (_pages == null) ? -1 : _pages.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up a fully qualified class name according to our
|
||||
* configuration and the package root.
|
||||
*/
|
||||
public String name (Class clazz)
|
||||
{
|
||||
if (clazz.isArray()) {
|
||||
return name(clazz.getComponentType()) + "[]";
|
||||
}
|
||||
|
||||
String name = clazz.getName();
|
||||
if (_displayPackageNames) {
|
||||
if (name.startsWith(_pkgroot)) {
|
||||
return "." + name.substring(_pkgroot.length());
|
||||
} else if (name.startsWith("java.lang")) {
|
||||
return name.substring(10);
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
|
||||
} else {
|
||||
int ldidx = name.lastIndexOf(".");
|
||||
return (ldidx == -1) ? name : name.substring(ldidx+1);
|
||||
}
|
||||
}
|
||||
|
||||
protected String _pkgroot = "";
|
||||
protected ArrayList _summaries = new ArrayList();
|
||||
protected ArrayList _pages;
|
||||
protected PageFormat _format;
|
||||
protected boolean _displayPackageNames = false;
|
||||
|
||||
protected static final int GAP = 72/4;
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
//
|
||||
// $Id: Dumper.java,v 1.4 2001/08/14 06:23:08 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.util;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* A simple utility that dumps out information available via reflection.
|
||||
*/
|
||||
public class Dumper
|
||||
{
|
||||
public void dump (Class clazz)
|
||||
{
|
||||
System.out.println("Dumping: " + clazz.getName());
|
||||
|
||||
Class parent = clazz.getSuperclass();
|
||||
if (parent == null) {
|
||||
System.out.println("P: none");
|
||||
} else {
|
||||
System.out.println("P: " + parent.getName());
|
||||
}
|
||||
|
||||
Class[] ifaces = clazz.getInterfaces();
|
||||
for (int i = 0; i < ifaces.length; i++) {
|
||||
System.out.println("I: " + ifaces[i].getName());
|
||||
}
|
||||
|
||||
dumpFields("F", clazz.getDeclaredFields());
|
||||
dump("C", clazz.getDeclaredConstructors());
|
||||
dumpMethods("M", clazz.getDeclaredMethods());
|
||||
}
|
||||
|
||||
protected void dumpFields (String prefix, Field[] fields)
|
||||
{
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
System.out.println(prefix + ": " + fields[i].getName() +
|
||||
" / " + fields[i].getType().getName());
|
||||
}
|
||||
}
|
||||
|
||||
protected void dumpMethods (String prefix, Method[] methods)
|
||||
{
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
System.out.println(prefix + ": " + methods[i].getName() +
|
||||
StringUtil.toString(
|
||||
methods[i].getParameterTypes()));
|
||||
}
|
||||
}
|
||||
|
||||
protected void dump (String prefix, Member[] members)
|
||||
{
|
||||
for (int i = 0; i < members.length; i++) {
|
||||
System.out.println(prefix + ": " + members[i].getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
if (args.length < 1) {
|
||||
System.err.println("Usage: Dumper classname [classname ...]");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
String classpath = System.getProperty("java.class.path", ".");
|
||||
System.out.println("Classpath: " + classpath);
|
||||
|
||||
Dumper dumper = new Dumper();
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
try {
|
||||
dumper.dump(Class.forName(args[i]));
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Unable to instantiate class: " + args[i]);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
//
|
||||
// $Id: FontPicker.java,v 1.4 2001/12/01 05:28:01 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.util;
|
||||
|
||||
import java.awt.Font;
|
||||
|
||||
/**
|
||||
* The font picker provides the proper font based on operating condtions.
|
||||
*/
|
||||
public class FontPicker
|
||||
{
|
||||
/**
|
||||
* Instructs the font picker to choose fonts for printing or fonts for
|
||||
* displaying on the screen based on the value of the
|
||||
* <code>printing</code> argument.
|
||||
*/
|
||||
public static void init (boolean printing)
|
||||
{
|
||||
int size = printing ? 8 : 12;
|
||||
_titleFont = new Font("Helvetica", Font.BOLD, size);
|
||||
_classFont = new Font("Helvetica", Font.PLAIN, size);
|
||||
_ifaceFont = new Font("Helvetica", Font.ITALIC, size);
|
||||
_implsFont = new Font("Helvetica", Font.ITALIC, size-2);
|
||||
_declsFont = new Font("Helvetica", Font.PLAIN, size-2);
|
||||
}
|
||||
|
||||
public static Font getTitleFont ()
|
||||
{
|
||||
return _titleFont;
|
||||
}
|
||||
|
||||
public static Font getClassFont ()
|
||||
{
|
||||
return _classFont;
|
||||
}
|
||||
|
||||
public static Font getInterfaceFont ()
|
||||
{
|
||||
return _ifaceFont;
|
||||
}
|
||||
|
||||
public static Font getImplementsFont ()
|
||||
{
|
||||
return _implsFont;
|
||||
}
|
||||
|
||||
public static Font getDeclaresFont ()
|
||||
{
|
||||
return _declsFont;
|
||||
}
|
||||
|
||||
protected static Font _titleFont;
|
||||
protected static Font _classFont;
|
||||
protected static Font _ifaceFont;
|
||||
protected static Font _implsFont;
|
||||
protected static Font _declsFont;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
//
|
||||
// $Id: LayoutUtil.java,v 1.2 2001/12/01 06:22:18 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.util;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* Layout related utility functions.
|
||||
*/
|
||||
public class LayoutUtil
|
||||
{
|
||||
/**
|
||||
* The number of points surrounding the name of the chain.
|
||||
*/
|
||||
public static double HEADER_BORDER = 3;
|
||||
|
||||
/**
|
||||
* The number of points of spacing between each child chain.
|
||||
*/
|
||||
public static double GAP = 4;
|
||||
|
||||
/**
|
||||
* The number of points that interfaces, inner classes and generally
|
||||
* any text that is subordinate to other text is indented.
|
||||
*/
|
||||
public static double SUBORDINATE_INSET = 3;
|
||||
|
||||
/**
|
||||
* Returns a rectangle that contains the supplied text with space
|
||||
* around the text for an aesthetically pleasing border.
|
||||
*/
|
||||
public static Rectangle2D getTextBox (
|
||||
Font font, FontRenderContext frc, String text)
|
||||
{
|
||||
TextLayout layout = new TextLayout(text, font, frc);
|
||||
Rectangle2D bounds = layout.getBounds();
|
||||
// incorporate room for the border in the bounds
|
||||
bounds.setRect(bounds.getX(), bounds.getY(),
|
||||
bounds.getWidth() + 2*HEADER_BORDER,
|
||||
bounds.getHeight() + 2*HEADER_BORDER);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rectangle that accomodates the specified text at the
|
||||
* bottom of the supplied rectangle, taking into account the preferred
|
||||
* text spacing and the specified inset for the accomodated text.
|
||||
*/
|
||||
public static Rectangle2D accomodate (
|
||||
Rectangle2D bounds, Font font, FontRenderContext frc, double inset,
|
||||
String text)
|
||||
{
|
||||
TextLayout layout = new TextLayout(text, font, frc);
|
||||
Rectangle2D tbounds = layout.getBounds();
|
||||
bounds.setRect(bounds.getX(), bounds.getY(),
|
||||
Math.max(bounds.getWidth(), tbounds.getWidth()+inset),
|
||||
bounds.getHeight() + tbounds.getHeight());
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rectangle that accomodates the specified lines of text at
|
||||
* the bottom of the supplied rectangle, taking into account the
|
||||
* preferred text spacing and the specified inset for the accomodated
|
||||
* text.
|
||||
*/
|
||||
public static Rectangle2D accomodate (
|
||||
Rectangle2D bounds, Font font, FontRenderContext frc, double inset,
|
||||
String[] text)
|
||||
{
|
||||
double maxwid = bounds.getWidth();
|
||||
double height = 0;
|
||||
|
||||
for (int i = 0; i < text.length; i++) {
|
||||
TextLayout layout = new TextLayout(text[i], font, frc);
|
||||
Rectangle2D tbounds = layout.getBounds();
|
||||
maxwid = Math.max(maxwid, tbounds.getWidth()+inset);
|
||||
height += tbounds.getHeight();
|
||||
}
|
||||
|
||||
bounds.setRect(bounds.getX(), bounds.getY(),
|
||||
maxwid, bounds.getHeight() + height);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rectangle that accomodates the two specified columns of
|
||||
* text at the bottom of the supplied rectangle, taking into account
|
||||
* the preferred text spacing and the specified inset for the
|
||||
* accomodated text.
|
||||
*/
|
||||
public static Rectangle2D accomodate (
|
||||
Rectangle2D bounds, Font font, FontRenderContext frc, double inset,
|
||||
String[] left, String[] right)
|
||||
{
|
||||
double maxleft = 0, maxwid = bounds.getWidth();
|
||||
double height = 0;
|
||||
|
||||
Rectangle2D[] bndl = new Rectangle2D[left.length];
|
||||
Rectangle2D[] bndr = new Rectangle2D[right.length];
|
||||
|
||||
// first compute our dimensions
|
||||
for (int i = 0; i < left.length; i++) {
|
||||
bndl[i] = new TextLayout(left[i], font, frc).getBounds();
|
||||
bndr[i] = new TextLayout(right[i], font, frc).getBounds();
|
||||
maxleft = Math.max(maxleft, bndl[i].getWidth());
|
||||
}
|
||||
|
||||
// now that we have the maxleft width we can calculate the rest
|
||||
for (int i = 0; i < left.length; i++) {
|
||||
maxwid = Math.max(maxwid, maxleft+GAP+bndr[i].getWidth()+inset);
|
||||
height += Math.max(bndl[i].getHeight(), bndr[i].getHeight());
|
||||
}
|
||||
|
||||
bounds.setRect(bounds.getX(), bounds.getY(),
|
||||
maxwid, bounds.getHeight() + height);
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
//
|
||||
// $Id: RenderUtil.java,v 1.2 2001/12/01 06:22:18 mdb Exp $
|
||||
//
|
||||
// viztool - a tool for visualizing collections of java classes
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.1 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.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.samskivert.viztool.util;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* Rendering related utility functions.
|
||||
*/
|
||||
public class RenderUtil
|
||||
{
|
||||
/**
|
||||
* Renders a string to the specified graphics context, in the
|
||||
* specified font at the specified coordinates.
|
||||
*
|
||||
* @return the bounds occupied by the rendered string.
|
||||
*/
|
||||
public static Rectangle2D renderString (
|
||||
Graphics2D gfx, FontRenderContext frc, Font font,
|
||||
double x, double y, String text)
|
||||
{
|
||||
// do the rendering
|
||||
TextLayout ilay = new TextLayout(text, font, frc);
|
||||
Rectangle2D ibounds = ilay.getBounds();
|
||||
ilay.draw(gfx, (float)(x - ibounds.getX()),
|
||||
(float)(y - ibounds.getY()));
|
||||
|
||||
// return the dimensions occupied by the rendered string
|
||||
return ibounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an array of strings to the specified graphics context, in
|
||||
* the specified font at the specified coordinates.
|
||||
*
|
||||
* @return the bounds occupied by the rendered strings.
|
||||
*/
|
||||
public static Rectangle2D renderStrings (
|
||||
Graphics2D gfx, FontRenderContext frc, Font font,
|
||||
double x, double y, String[] text)
|
||||
{
|
||||
return renderStrings(gfx, frc, font, x, y, text, (String)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an array of strings to the specified graphics context, in
|
||||
* the specified font at the specified coordinates. If prefix is
|
||||
* non-null, it will be prefixed to the first string and subsequent
|
||||
* strings will be rendered with the space necessary to line them up
|
||||
* with the first string.
|
||||
*
|
||||
* @return the bounds occupied by the rendered strings.
|
||||
*/
|
||||
public static Rectangle2D renderStrings (
|
||||
Graphics2D gfx, FontRenderContext frc, Font font,
|
||||
double x, double y, String[] text, String prefix)
|
||||
{
|
||||
double maxwid = 0, starty = y;
|
||||
double inset = 0;
|
||||
|
||||
if (prefix != null) {
|
||||
TextLayout play = new TextLayout(prefix, font, frc);
|
||||
inset = play.getBounds().getWidth();
|
||||
}
|
||||
|
||||
for (int i = 0; i < text.length; i++) {
|
||||
// figure some stuff out
|
||||
String string = (i == 0 && prefix != null) ?
|
||||
(prefix + text[i]) : text[i];
|
||||
double sinset = ((i == 0) ? 0 : inset);
|
||||
|
||||
// do the rendering
|
||||
TextLayout ilay = new TextLayout(string, font, frc);
|
||||
Rectangle2D ibounds = ilay.getBounds();
|
||||
ilay.draw(gfx, (float)(x - ibounds.getX() + sinset),
|
||||
(float)(y - ibounds.getY()));
|
||||
|
||||
maxwid = Math.max(sinset + ibounds.getWidth(), maxwid);
|
||||
y += ibounds.getHeight();
|
||||
}
|
||||
|
||||
// return the dimensions occupied by the rendered strings
|
||||
return new Rectangle2D.Double(x, y, maxwid, y-starty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a two column array of strings to the specified graphics
|
||||
* context, in the specified font at the specified coordinates. The
|
||||
* left column is right align and the right, left aligned.
|
||||
*
|
||||
* @return the bounds occupied by the rendered strings.
|
||||
*/
|
||||
public static Rectangle2D renderStrings (
|
||||
Graphics2D gfx, FontRenderContext frc, Font font,
|
||||
double x, double y, String[] left, String[] right)
|
||||
{
|
||||
double maxleft = 0, maxwid = 0, starty = y;
|
||||
double inset = 0;
|
||||
|
||||
// first generate text layout instances and compute bounds for all
|
||||
// entries in both columns
|
||||
TextLayout[] llay = new TextLayout[left.length];
|
||||
Rectangle2D[] lbnds = new Rectangle2D[left.length];
|
||||
TextLayout[] rlay = new TextLayout[right.length];
|
||||
Rectangle2D[] rbnds = new Rectangle2D[right.length];
|
||||
|
||||
// compute the dimensions
|
||||
for (int i = 0; i < left.length; i++) {
|
||||
llay[i] = new TextLayout(left[i], font, frc);
|
||||
lbnds[i] = llay[i].getBounds();
|
||||
rlay[i] = new TextLayout(right[i], font, frc);
|
||||
rbnds[i] = rlay[i].getBounds();
|
||||
maxleft = Math.max(maxleft, lbnds[i].getWidth());
|
||||
}
|
||||
|
||||
// do the rendering
|
||||
for (int i = 0; i < left.length; i++) {
|
||||
double lw = lbnds[i].getWidth();
|
||||
llay[i].draw(gfx, (float)(x - lbnds[i].getX() + maxleft - lw),
|
||||
// we actually mean to use rbnds[i] here because
|
||||
// the right hand side (usually being the method
|
||||
// declaration), tends to be taller than the left
|
||||
// hand side (because of the parenthesis) and
|
||||
// would appear a bit lower than the left hand
|
||||
// side if we didn't use it's y offset
|
||||
(float)(y - rbnds[i].getY()));
|
||||
rlay[i].draw(gfx, (float)(x - rbnds[i].getX() + maxleft +
|
||||
LayoutUtil.GAP),
|
||||
(float)(y - rbnds[i].getY()));
|
||||
maxwid = Math.max(maxwid, maxleft + LayoutUtil.GAP +
|
||||
rbnds[i].getWidth());
|
||||
y += Math.max(lbnds[i].getHeight(), rbnds[i].getHeight());
|
||||
}
|
||||
|
||||
// return the dimensions occupied by the rendered strings
|
||||
return new Rectangle2D.Double(x, y, maxwid, y-starty);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
|
||||
$Id: package.html,v 1.2 2001/08/12 04:36:57 mdb Exp $
|
||||
|
||||
viztool - a tool for visualizing collections of java classes
|
||||
Copyright (C) 2001 Michael Bayne
|
||||
|
||||
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.1 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.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
-->
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
|
||||
Various and sundry utilities.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user