📄 accordiontreedrawer.java
字号:
/* Copyright (c) 2002 Compaq Computer Corporation SOFTWARE RELEASE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the names of Compaq Research, Compaq Computer Corporation nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL COMPAQ COMPUTER CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/package AccordionTreeDrawer;import java.util.*;import java.awt.*;import java.io.*;import gl4java.*;import AccordionDrawer.*;/** * An abstract class representing a multi-scale rectangular grid on which * a tree consisting of horizontal and vertical line segments is drawn * * Fills in the fields of the abstract class AccordionDrawer based on * information from the Tree class. * * @author Tamara Munzner, Li Zhang * @version * @see AccordionDrawer.AccordionDrawer * @see TreeJuxtaposer.AccordionTreeDrawerFinal * @see AccordionDrawer.Tree * @see AccordionDrawer.TreeNode * @see AccordionDrawer.TreeEdge * @see AccordionDrawer.GridCell *///public class AccordionTreeDrawer extends AccordionDrawer {public abstract class AccordionTreeDrawer extends AccordionDrawer { String fname; protected float pointoffset[] = new float[2]; protected int labeloffset[] = new int[2]; protected int labelbuffer[] = new int[2]; public final float pixelDiv = 4.0f; public boolean basePass = false; // draw the base image, nothing marked, no text public boolean groupPass = false; // draw the groups, no text public boolean textPass = false; // draw the text /** * framebuffer pixels from last mouseover label drawn */ protected float labelPixels[]; // pixels for drawing the label (if there is one) protected LabelBox flashLabelBox = null; protected float linePixel[][] = new float[2][]; // vertical/horizontal line pixels (if there is one for each) protected int lineLength[] = new int[2]; // length of x/y edges (width is line thickness + 1 on each side) protected int linePos[][] = new int[2][2]; // starting x/y point for x/y edges protected float[][] pal;// protected float drawAngle; /** * GL rasterpos of last mouseover label drawn */ protected double drawnlabelpos[] = new double[2]; protected int interactionBoxPos[] = new int[2]; /** * width and height of last mouseover label drawn */ protected int drawnlabelsize[] = new int[2]; protected int interactionBoxSize[] = new int[2]; //how the labels are drawn // dealing with variable font size public int minFontHeight = 10; public int maxFontHeight = 14; public int popupFontHeight = 14; protected float forestShrinkFactor; protected float pickoffset[] = new float[2]; public int pickFuzz; // static String fontFile = "BitmapFont/OlduvaiFont";// static String fontFile = "/OlduvaiFont";// static BitmapFontsFamily bff = new BitmapFontsFamily(fontFile); static boolean fontInitialized = false; public Tree tree; protected TreeNode rootNode; protected TreeEdge rootEdge; public static boolean fullyQualified; // benchmarking public static int countDrawnFrame; public static int countDrawnScene; public static int cumFrameTime; protected Color objectColor; public AccordionTreeDrawer(Tree t, int w, int h) { super(w,h); expandleaves = 1; dimbrite = true; horiz = true; objectColor = new Color(0.0f, 0.0f, 0.0f, 1.0f); labeloffset[X] = 2; labeloffset[Y] = 4; labelbuffer[X] = 10; labelbuffer[Y] = 1; pointoffset[X] = .1f; pointoffset[Y] = .52f; pickoffset[0] = .1f; pickoffset[1] = .1f; pickFuzz = 5; // in pixels forestShrinkFactor = -0.3f; tree = t; tree.setNodeFontSize(maxFontHeight, minFontHeight); rootNode = tree.getRoot(); initCells();// buildGrids();// attachEdges(); flashGeom = tree.getRoot(); flashGeomOld = null; doBox = false;// drawAngle = 30.0f; } /** * clear the objects initiated in ATD * @see TreeJuxtaposer.TreeJuxtaposer.deleteTree * @see AccordionDrawer.close */ public void shutdown(){ super.shutdown(); tree=null; rootNode=null; rootEdge=null; fname=null; pointoffset=null; labeloffset = null; labelbuffer = null; drawnlabelpos = null; drawnlabelsize =null; } protected void finalize() throws Throwable { try { shutdown(); } finally { System.out.println("finally clean ATD"); super.finalize(); } } /** * Initialization done after graphics context has been established. * @author Tamara Munzner */ public void init() { super.init(); } // get the maxline for some node given children have set minlines private int getMaxLineX(ArrayList children) { int maxLine = bottomSize[X]; Iterator iter = children.iterator(); while (iter.hasNext()) { int currNodeMinLine = ((TreeNode)iter.next()).getCell().getMinLine(X); if (currNodeMinLine < maxLine) maxLine = currNodeMinLine; } return maxLine; } // update the children minlines to the maxline of the parent private void updateMinLineX(ArrayList children, int newMinLine) { Iterator iter = children.iterator(); while (iter.hasNext()) { ((TreeNode)iter.next()).getCell().setMinLine(newMinLine, X); } } // build all splitLines private void buildCells() { int leafCount = 0; Vector leafVector = new Vector(); int currY = 0; // for positioning leaves in splitLine Y for(TreeNode n = tree.posorderStartNode; n!=null; n=n.posorderNext) { GridCell c = new GridCell(this); n.setCell(c); n.computedFrame = -1; if (n.isLeaf()) { // leaf splitLine[X].addCell(c, bottomSize[X]-1); splitLine[Y].addCell(c, currY++); leafVector.add(n); leafCount++; } else { // internal node n.addEdge(new TreeEdge(n, false), Y); // vertical edge int maxLineX = getMaxLineX(n.children); updateMinLineX(n.children, maxLineX); splitLine[X].addCell(c, maxLineX); int minLineY = n.getLeftmostLeaf().getCell().getMinLine(Y); int maxLineY = n.getRightmostLeaf().getCell().getMaxLine(Y); splitLine[Y].addCell(c, minLineY, maxLineY); } if (!n.isRoot()) { n.addEdge(new TreeEdge(n, true), X); // horizontal edge } else { rootNode = n; rootEdge = n.getEdge(Y); rootCell = c; } } } /** * Initializes level 0 GridCells based on Tree tree, assign tree * nodes to them. Set {@link #maxUsed maxUsed[]} in directions X * and Y. * * * @author Tamara Munzner, Serdar Tasiran * * * @see AccordionDrawer.GridCell * @see AccordionDrawer.Tree * @see AccordionDrawer.TreeNode */ public void initCells() { int numLeaves = tree.getLeafCount(); int treeHeight = tree.getHeight(); bottomSize[0] = treeHeight; bottomSize[1] = numLeaves; initSplitLines(); splitLine[X].setMinStuckValue(0.01f);// splitLine[X].setMinStuckValue(0.5f); // debugging gridDepth = new int[2]; double logBase2 = Math.log(2); for (int xy = 0; xy < 2; xy++) { gridDepth[xy] = (int)Math.ceil(Math.log(bottomSize[xy]) / logBase2); gridDepth[xy] = gridDepth[xy] <= 0 ? 1 : gridDepth[xy]; } System.out.println("gridDepth: " +gridDepth[0] + " " +gridDepth[1] + " rows:numLeaves " + numLeaves + " cols:treeHeight " + treeHeight + " total nodes " + tree.getTotalNodeCount() + " treeNum " + tree.getKey()); buildCells(); System.out.println("root cell " + rootNode.getCell()); } // x and y are pixel positions public CellGeom pickAttached(int x, int y) { return pickGeom(x, y); } public CellGeom pickGeom(int x, int y) { double xPos = s2w(x, X); double yPos = s2w(y, Y); double xFuzz = s2w(pickFuzz, X); double yFuzz = s2w(pickFuzz, Y); return rootNode.pickDescend(xPos, yPos, xFuzz, yFuzz); } /** * Create box enclosing the subtree beneath input node/edge. The * resulting box is the nearest GridLine boundaries to that point, * which are cached so that redraws to erase the box can happen * after the lines change position. * @param cg TreeNode to act upon, passed in as CellGeom from * AccordionDrawer (where TreeNodes are not known) * @see IntersectionBox * @author Tamara Munzner */ public InteractionBox makeBox(CellGeom cg) { if (null == cg) return null; TreeNode tn; if (cg instanceof TreeNode) tn = (TreeNode)cg; else if (cg instanceof TreeEdge) tn = ((TreeEdge)cg).node; else return null; // not a node or an edge? TreeNode minLeaf = tn.leftmostLeaf; TreeNode maxLeaf = tn.rightmostLeaf; int[] minLine = {tn.getCell().getMinLine(X), minLeaf.getCell().getMinLine(Y)}; // maxLine[X] could use any leaf to get rightmost splitLine int[] maxLine = {minLeaf.getCell().getMaxLine(X), maxLeaf.getCell().getMaxLine(Y)}; return new InteractionBox(minLine, maxLine, cg, tn.getCell().drawer); } /** * On mouseover, flash the object under the mouse and draw its * label at maximum size. * * @author Tamara Munzner * * * @see AccordionDrawer.GridCell * @see AccordionDrawer.Tree * @see AccordionDrawer.TreeNode */ public void doFlash() { if (noflash || (flashGeom == flashGeomOld && flashBox == flashBoxOld) || null == glj || keepDrawing || !drawStart(false)) // no swap return;//System.out.println("Depth test when entering doFlash: " + gl.) boolean doubleBufferedOriginal = getDoubleBuffer(); setDoubleBuffer(false, false); // deactivate double buffering for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -