Modified code to deal better with splitting chain groups across pages. It
still chokes if a single chain won't fit on a page, but what to do there is complicated and non-obvious. git-svn-id: https://samskivert.googlecode.com/svn/trunk@205 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: Driver.java,v 1.5 2001/07/17 07:18:09 mdb Exp $
|
// $Id: Driver.java,v 1.6 2001/07/24 18:07:35 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.viztool;
|
package com.samskivert.viztool;
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@ public class Driver
|
|||||||
|
|
||||||
// run ourselves on the classpath
|
// run ourselves on the classpath
|
||||||
String classpath = System.getProperty("java.class.path");
|
String classpath = System.getProperty("java.class.path");
|
||||||
|
// System.err.println("Scanning " + classpath + ".");
|
||||||
ClassEnumerator enum = new ClassEnumerator(classpath);
|
ClassEnumerator enum = new ClassEnumerator(classpath);
|
||||||
|
|
||||||
// print out the warnings
|
// print out the warnings
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ChainGroup.java,v 1.6 2001/07/17 06:01:08 mdb Exp $
|
// $Id: ChainGroup.java,v 1.7 2001/07/24 18:07:35 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.viztool.viz;
|
package com.samskivert.viztool.viz;
|
||||||
|
|
||||||
@@ -28,13 +28,60 @@ public class ChainGroup
|
|||||||
|
|
||||||
// process the classes provided by our enumerator
|
// process the classes provided by our enumerator
|
||||||
_roots = ChainUtil.buildChains(pkgroot, iter);
|
_roots = ChainUtil.buildChains(pkgroot, iter);
|
||||||
|
// System.err.println(_roots.size() + " chains for " + pkg + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ChainGroup (String pkg, ArrayList roots)
|
||||||
|
{
|
||||||
|
_pkg = pkg;
|
||||||
|
_roots = roots;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lays out the chains in this group and returns the total size.
|
* Returns the dimensions of this chain group. This value is only
|
||||||
|
* valid after <code>layout</code> has been called.
|
||||||
*/
|
*/
|
||||||
public Rectangle2D layout (Graphics2D gfx, double pageWidth,
|
public Rectangle2D getBounds ()
|
||||||
double pageHeight)
|
{
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
// lay out the internal structure of our chains
|
// lay out the internal structure of our chains
|
||||||
ChainVisualizer clay = new CascadingChainVisualizer();
|
ChainVisualizer clay = new CascadingChainVisualizer();
|
||||||
@@ -58,19 +105,28 @@ public class ChainGroup
|
|||||||
|
|
||||||
// arrange them on the page
|
// arrange them on the page
|
||||||
ElementLayout elay = new PackedColumnElementLayout();
|
ElementLayout elay = new PackedColumnElementLayout();
|
||||||
Rectangle2D[] dims = elay.layout(_roots, pageWidth, pageHeight);
|
ArrayList overflow = new ArrayList();
|
||||||
|
_size = elay.layout(_roots, pageWidth, pageHeight, overflow);
|
||||||
// for now we're punting and assume that no group will exceed a
|
|
||||||
// single page in size
|
|
||||||
double width = dims[0].getWidth();
|
|
||||||
double height = dims[0].getHeight() + titleAscent;
|
|
||||||
|
|
||||||
// make sure we're wide enough for our title
|
// make sure we're wide enough for our title
|
||||||
width = Math.max(width, layout.getAdvance() + 4);
|
double width = Math.max(_size.getWidth(), layout.getAdvance() + 4);
|
||||||
|
|
||||||
_size = new Rectangle2D.Double();
|
// adjust for our border and title
|
||||||
|
double height = _size.getHeight() + titleAscent;
|
||||||
_size.setRect(0, 0, width + 2*BORDER, height + 2*BORDER);
|
_size.setRect(0, 0, width + 2*BORDER, height + 2*BORDER);
|
||||||
return _size;
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,9 +188,17 @@ public class ChainGroup
|
|||||||
return (Chain)_roots.get(index);
|
return (Chain)_roots.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return "[pkg=" + _pkg + ", roots=" + _roots.size() +
|
||||||
|
", size=" + _size + ", page=" + _page + "]";
|
||||||
|
}
|
||||||
|
|
||||||
protected String _pkg;
|
protected String _pkg;
|
||||||
protected ArrayList _roots;
|
protected ArrayList _roots;
|
||||||
|
|
||||||
protected Rectangle2D _size;
|
protected Rectangle2D _size;
|
||||||
|
protected int _page;
|
||||||
|
|
||||||
protected static final double BORDER = 72/8;
|
protected static final double BORDER = 72/8;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-27
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: HierarchyVisualizer.java,v 1.7 2001/07/17 07:18:09 mdb Exp $
|
// $Id: HierarchyVisualizer.java,v 1.8 2001/07/24 18:07:35 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.viztool.viz;
|
package com.samskivert.viztool.viz;
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ public class HierarchyVisualizer implements Printable
|
|||||||
}
|
}
|
||||||
_classes.add(name);
|
_classes.add(name);
|
||||||
}
|
}
|
||||||
|
// System.err.println("Scanned " + _classes.size() + " classes.");
|
||||||
|
|
||||||
// compile a list of all packages in our collection
|
// compile a list of all packages in our collection
|
||||||
HashSet pkgset = new HashSet();
|
HashSet pkgset = new HashSet();
|
||||||
@@ -60,18 +61,15 @@ public class HierarchyVisualizer implements Printable
|
|||||||
_packages[i] = (String)iter.next();
|
_packages[i] = (String)iter.next();
|
||||||
}
|
}
|
||||||
Arrays.sort(_packages, Comparators.STRING);
|
Arrays.sort(_packages, Comparators.STRING);
|
||||||
|
// System.err.println("Scanned " + _packages.length + " packages.");
|
||||||
|
|
||||||
// now create chain groups for each package
|
// now create chain groups for each package
|
||||||
_groups = new ChainGroup[_packages.length];
|
_groups = new ArrayList();
|
||||||
for (int i = 0; i < _groups.length; i++) {
|
for (int i = 0; i < _packages.length; i++) {
|
||||||
PackageEnumerator penum = new PackageEnumerator(
|
PackageEnumerator penum = new PackageEnumerator(
|
||||||
_packages[i], _classes.iterator(), false);
|
_packages[i], _classes.iterator(), false);
|
||||||
_groups[i] = new ChainGroup(pkgroot, _packages[i], penum);
|
_groups.add(new ChainGroup(pkgroot, _packages[i], penum));
|
||||||
}
|
}
|
||||||
|
|
||||||
// we'll need these for later
|
|
||||||
_bounds = new Rectangle2D.Double[_packages.length];
|
|
||||||
_pagenos = new int[_packages.length];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,12 +96,16 @@ public class HierarchyVisualizer implements Printable
|
|||||||
|
|
||||||
// render the groups on the requested page
|
// render the groups on the requested page
|
||||||
int rendered = 0;
|
int rendered = 0;
|
||||||
for (int i = 0; i < _groups.length; i++) {
|
for (int i = 0; i < _groups.size(); i++) {
|
||||||
|
ChainGroup group = (ChainGroup)_groups.get(i);
|
||||||
|
|
||||||
// skip groups not on this page
|
// skip groups not on this page
|
||||||
if (_pagenos[i] != pageIndex) {
|
if (group.getPage() != pageIndex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_groups[i].render(gfx, _bounds[i].getX(), _bounds[i].getY());
|
|
||||||
|
Rectangle2D bounds = group.getBounds();
|
||||||
|
group.render(gfx, bounds.getX(), bounds.getY());
|
||||||
rendered++;
|
rendered++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,26 +115,32 @@ public class HierarchyVisualizer implements Printable
|
|||||||
public void layout (Graphics2D gfx, double x, double y,
|
public void layout (Graphics2D gfx, double x, double y,
|
||||||
double width, double height)
|
double width, double height)
|
||||||
{
|
{
|
||||||
double starty = x;
|
double starty = y;
|
||||||
int pageno = 0;
|
int pageno = 0;
|
||||||
|
|
||||||
// lay out our groups
|
// lay out our groups
|
||||||
for (int i = 0; i < _groups.length; i++) {
|
for (int i = 0; i < _groups.size(); i++) {
|
||||||
|
ChainGroup group = (ChainGroup)_groups.get(i);
|
||||||
|
|
||||||
// lay out the group in question
|
// lay out the group in question
|
||||||
Rectangle2D bounds = _groups[i].layout(gfx, width, height);
|
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
|
// determine if we need to skip to the next page or not
|
||||||
if ((y > 0) && (y + bounds.getHeight() > height)) {
|
Rectangle2D bounds = group.getBounds();
|
||||||
|
if ((y > starty) && (y + bounds.getHeight() > height + starty)) {
|
||||||
y = starty;
|
y = starty;
|
||||||
pageno++;
|
pageno++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign x and y coordinates to this group
|
// assign x and y coordinates to this group
|
||||||
bounds.setRect(x, y, bounds.getWidth(), bounds.getHeight());
|
group.setPosition(x, y);
|
||||||
// and store it
|
// make a note of our page index
|
||||||
_bounds[i] = bounds;
|
group.setPage(pageno);
|
||||||
// also make a note of our page index
|
|
||||||
_pagenos[i] = pageno;
|
|
||||||
|
|
||||||
// increment our y location
|
// increment our y location
|
||||||
y += (bounds.getHeight() + GAP);
|
y += (bounds.getHeight() + GAP);
|
||||||
@@ -142,13 +150,16 @@ public class HierarchyVisualizer implements Printable
|
|||||||
public void paint (Graphics2D gfx, int pageIndex)
|
public void paint (Graphics2D gfx, int pageIndex)
|
||||||
{
|
{
|
||||||
// render the groups on the requested page
|
// render the groups on the requested page
|
||||||
for (int i = 0; i < _groups.length; i++) {
|
for (int i = 0; i < _groups.size(); i++) {
|
||||||
|
ChainGroup group = (ChainGroup)_groups.get(i);
|
||||||
|
|
||||||
// skip groups not on this page
|
// skip groups not on this page
|
||||||
if (_pagenos[i] != pageIndex) {
|
if (group.getPage() != pageIndex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_groups[i].render((Graphics2D)gfx,
|
|
||||||
_bounds[i].getX(), _bounds[i].getY());
|
Rectangle2D bounds = group.getBounds();
|
||||||
|
group.render((Graphics2D)gfx, bounds.getX(), bounds.getY());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,11 +167,9 @@ public class HierarchyVisualizer implements Printable
|
|||||||
protected ArrayList _classes = new ArrayList();
|
protected ArrayList _classes = new ArrayList();
|
||||||
|
|
||||||
protected String[] _packages;
|
protected String[] _packages;
|
||||||
protected ChainGroup[] _groups;
|
protected ArrayList _groups;
|
||||||
|
|
||||||
protected PageFormat _format;
|
protected PageFormat _format;
|
||||||
protected Rectangle2D[] _bounds;
|
|
||||||
protected int[] _pagenos;
|
|
||||||
|
|
||||||
protected static final int PAGE_WIDTH = (int)(72 * 7.5);
|
protected static final int PAGE_WIDTH = (int)(72 * 7.5);
|
||||||
protected static final int PAGE_HEIGHT = (int)(72 * 10);
|
protected static final int PAGE_HEIGHT = (int)(72 * 10);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ElementLayout.java,v 1.2 2001/07/17 01:54:19 mdb Exp $
|
// $Id: ElementLayout.java,v 1.3 2001/07/24 18:07:35 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.viztool.viz;
|
package com.samskivert.viztool.viz;
|
||||||
|
|
||||||
@@ -15,12 +15,13 @@ import java.util.List;
|
|||||||
public interface ElementLayout
|
public interface ElementLayout
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Lay out the supplied list of elements. Page numbers should be
|
* Lay out the supplied list of elements. Any elements that do not fit
|
||||||
* assigned to all elements if the layout spans multiple pages.
|
* into the allotted space should be added to the overflow list. The
|
||||||
|
* supplied elements list should not be modified.
|
||||||
*
|
*
|
||||||
* @return an array of rectangle objects representing the width and
|
* @return the bounding dimensions of the collection of elements that
|
||||||
* height of each page that was laid out.
|
* were laid out.
|
||||||
*/
|
*/
|
||||||
public Rectangle2D[] layout (List elements,
|
public Rectangle2D layout (List elements, double pageWidth,
|
||||||
double pageWidth, double pageHeight);
|
double pageHeight, List overflow);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-23
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: PackedColumnElementLayout.java,v 1.4 2001/07/17 05:16:16 mdb Exp $
|
// $Id: PackedColumnElementLayout.java,v 1.5 2001/07/24 18:07:35 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.viztool.viz;
|
package com.samskivert.viztool.viz;
|
||||||
|
|
||||||
@@ -13,19 +13,16 @@ import java.util.*;
|
|||||||
public class PackedColumnElementLayout implements ElementLayout
|
public class PackedColumnElementLayout implements ElementLayout
|
||||||
{
|
{
|
||||||
// docs inherited from interface
|
// docs inherited from interface
|
||||||
public Rectangle2D[] layout (List elements,
|
public Rectangle2D layout (List elements, double pageWidth,
|
||||||
double pageWidth, double pageHeight)
|
double pageHeight, List overflow)
|
||||||
{
|
{
|
||||||
// create a new list containing the elements whose order we can
|
// sort the elements first by height then alphabetically
|
||||||
// manipulate willy nilly
|
|
||||||
Element[] elems = new Element[elements.size()];
|
Element[] elems = new Element[elements.size()];
|
||||||
elements.toArray(elems);
|
elements.toArray(elems);
|
||||||
Arrays.sort(elems, HEIGHT_COMP);
|
Arrays.sort(elems, HEIGHT_COMP);
|
||||||
|
|
||||||
// lay out the elements across the page
|
// lay out the elements across the page
|
||||||
ArrayList pagedims = new ArrayList();
|
|
||||||
double x = 0, y = 0, rowheight = 0, maxwidth = 0;
|
double x = 0, y = 0, rowheight = 0, maxwidth = 0;
|
||||||
int pageno = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < elems.length; i++) {
|
for (int i = 0; i < elems.length; i++) {
|
||||||
Rectangle2D bounds = elems[i].getBounds();
|
Rectangle2D bounds = elems[i].getBounds();
|
||||||
@@ -42,26 +39,25 @@ public class PackedColumnElementLayout implements ElementLayout
|
|||||||
// move down to the next row
|
// move down to the next row
|
||||||
x = 0;
|
x = 0;
|
||||||
y += (rowheight + GAP);
|
y += (rowheight + GAP);
|
||||||
// reset our max rowheight
|
// reset our max rowheight (we set it to -GAP because we
|
||||||
rowheight = bounds.getHeight();
|
// 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
|
// make sure we fit on this page (but force placement if we're
|
||||||
// currently at the top margin)
|
// currently at the top margin)
|
||||||
if ((y > 0) && ((y + bounds.getHeight()) > pageHeight)) {
|
if ((y > 0) && ((y + bounds.getHeight()) > pageHeight)) {
|
||||||
// make a note of how big the current page is
|
// if we didn't fit, we go onto the overflow list
|
||||||
pagedims.add(new Rectangle2D.Double(0, 0, maxwidth, y));
|
overflow.add(elems[i]);
|
||||||
// move to the next page
|
// and continue on because maybe some shorter elements
|
||||||
x = 0;
|
// further down the list will fit
|
||||||
y = 0;
|
continue;
|
||||||
rowheight = bounds.getHeight();
|
|
||||||
maxwidth = 0;
|
|
||||||
pageno++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// lay this element out at our current coordinates
|
// lay this element out at our current coordinates
|
||||||
elems[i].setBounds(x, y, bounds.getWidth(), bounds.getHeight());
|
elems[i].setBounds(x, y, bounds.getWidth(), bounds.getHeight());
|
||||||
// elems[i].setPage(pageno);
|
|
||||||
|
|
||||||
// keep track of the maximum row height
|
// keep track of the maximum row height
|
||||||
if (bounds.getHeight() > rowheight) {
|
if (bounds.getHeight() > rowheight) {
|
||||||
@@ -78,11 +74,7 @@ public class PackedColumnElementLayout implements ElementLayout
|
|||||||
maxwidth = x;
|
maxwidth = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a note of how big the final page is
|
return new Rectangle2D.Double(0, 0, maxwidth, y+rowheight);
|
||||||
pagedims.add(new Rectangle2D.Double(0, 0, maxwidth, y+rowheight));
|
|
||||||
Rectangle2D[] dims = new Rectangle2D[pagedims.size()];
|
|
||||||
pagedims.toArray(dims);
|
|
||||||
return dims;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class HeightComparator implements Comparator
|
protected static class HeightComparator implements Comparator
|
||||||
|
|||||||
Reference in New Issue
Block a user