📄 treevisualizer.java
字号:
//from overlapping
//it will leave the view centered
int dist;
Node ln,rn;
Dimension temp = new Dimension(10, 10);
if (m_numNodes <= 1) {
return;
}
//calc height needed by first node
dist = (m_nodes[0].m_height + 40) * m_numLevels;
if (dist > temp.height) {
temp.height = dist;
}
for (int noa = 0;noa < m_numNodes - 1;noa++) {
calcScreenCoords(noa);
calcScreenCoords(noa+1);
if (m_nodes[noa+1].m_change) {
//then on a new level so don't check width this time round
}
else {
dist = m_nodes[noa+1].m_center - m_nodes[noa].m_center;
//the distance between the node centers, along horiz
if (dist <= 0) {
dist = 1;
}
dist = ((6 + m_nodes[noa].m_side + m_nodes[noa+1].m_side)
* m_viewSize.width) / dist; //calc optimal size for width
if (dist > temp.width) {
temp.width = dist;
}
}
//now calc.. minimun hieght needed by nodes
dist = (m_nodes[noa+1].m_height + 40) * m_numLevels;
if (dist > temp.height) {
temp.height = dist;
}
}
int y1, y2, xa, xb;
y1 = m_nodes[m_edges[0].m_parent].m_top;
y2 = m_nodes[m_edges[0].m_child].m_top;
dist = y2 - y1;
if (dist <= 0) {
dist = 1;
}
dist = ((60 + m_edges[0].m_height + m_nodes[m_edges[0].m_parent].m_height)
* m_viewSize.height) / dist;
if (dist > temp.height) {
temp.height = dist;
}
for (int noa = 0;noa < m_numNodes - 2; noa++) {
//check the edges now
if (m_nodes[m_edges[noa+1].m_child].m_change) {
//then edge is on a different level , so skip this one
}
else {
//calc the width requirements of this pair of edges
xa = m_nodes[m_edges[noa].m_child].m_center
- m_nodes[m_edges[noa].m_parent].m_center;
xa /= 2;
xa += m_nodes[m_edges[noa].m_parent].m_center;
xb = m_nodes[m_edges[noa+1].m_child].m_center -
m_nodes[m_edges[noa+1].m_parent].m_center;
xb /= 2;
xb += m_nodes[m_edges[noa+1].m_parent].m_center;
dist = xb - xa;
if (dist <= 0) {
dist = 1;
}
dist = ((12 + m_edges[noa].m_side + m_edges[noa+1].m_side)
* m_viewSize.width)
/ dist;
if (dist > temp.width) {
temp.width = dist;
}
}
//now calc height need by the edges
y1 = m_nodes[m_edges[noa+1].m_parent].m_top;
y2 = m_nodes[m_edges[noa+1].m_child].m_top;
dist = y2 - y1;
if (dist <= 0) {
dist = 1;
}
dist = ((60 + m_edges[noa+1].m_height
+ m_nodes[m_edges[noa+1].m_parent].m_height)
* m_viewSize.height) / dist;
if (dist > temp.height) {
temp.height = dist;
}
}
Dimension e = getSize();
Dimension np = new Dimension();
np.width = (int)(e.width / 2 - (((double)e.width / 2) - m_viewPos.width) /
((double)m_viewSize.width) * (double)temp.width);
np.height = (int)(e.height / 2 - (((double)e.height / 2) -
m_viewPos.height) /
((double)m_viewSize.height) * (double)temp.height);
//animate_scaling(c_size,c_pos,25);
for (int noa = 0;noa < m_numNodes;noa++) {
//this resets the coords so that next time a refresh occurs they don't
//accidentally get used
//I will use 32000 to signify that they are invalid, even if this
//coordinate occurs it doesn't
//matter as it is only for the sake of the caching
m_nodes[noa].m_top = 32000;
}
animateScaling(np, temp, 10);
}
/**
* This will increment the size and position of the tree towards the
* desired size and position
* a little (depending on the value of <i>frames</i>) everytime it is called.
*
* @param n_pos The final position of the tree wanted.
* @param n_size The final size of the tree wanted.
* @param frames The number of frames that shall occur before the final
* size and pos is reached.
*/
private void animateScaling(Dimension n_pos,Dimension n_size,int frames) {
//this function will take new size and position coords , and incrementally
//scale the view to these
//since I will be tying it in with the framelimiter I will simply call
//this function and increment it once
//I will have to use a global variable since I am doing it proportionally
if (frames == 0) {
System.out.println("the timer didn't end in time");
m_scaling = 0;
}
else {
if (m_scaling == 0) {
//new animate session
//start timer and set scaling
m_frameLimiter.start();
m_nViewPos.width = n_pos.width;
m_nViewPos.height = n_pos.height;
m_nViewSize.width = n_size.width;
m_nViewSize.height = n_size.height;
m_scaling = frames;
}
int s_w = (n_size.width - m_viewSize.width) / frames;
int s_h = (n_size.height - m_viewSize.height) / frames;
int p_w = (n_pos.width - m_viewPos.width) / frames;
int p_h = (n_pos.height - m_viewPos.height) / frames;
m_viewSize.width += s_w;
m_viewSize.height += s_h;
m_viewPos.width += p_w;
m_viewPos.height += p_h;
repaint();
m_scaling--;
if (m_scaling == 0) {
//all done
m_frameLimiter.stop();
}
}
}
/**
* This will change the font size for displaying the tree to the one
* specified.
*
* @param s The new pointsize of the font.
*/
private void changeFontSize(int s) {
//this will set up the new font that shall be used
//it will also recalculate the size of the nodes as these will change as
//a result of
//the new font size
setFont(m_currentFont = new Font("A Name", 0, s));
m_fontSize = getFontMetrics(getFont());
Dimension d;
for (int noa = 0; noa < m_numNodes; noa++) {
//this will set the size info for each node and edge
d = m_nodes[noa].m_node.stringSize(m_fontSize);
if (m_nodes[noa].m_node.getShape() == 1) {
m_nodes[noa].m_height = d.height + 10;
m_nodes[noa].m_width = d.width + 8;
m_nodes[noa].m_side = m_nodes[noa].m_width / 2;
}
else if (m_nodes[noa].m_node.getShape() == 2) {
m_nodes[noa].m_height = (int)((d.height + 2) * 1.6);
m_nodes[noa].m_width = (int)((d.width + 2) * 1.6);
m_nodes[noa].m_side = m_nodes[noa].m_width / 2;
}
if (noa < m_numNodes - 1) {
//this will do the same for edges
d = m_edges[noa].m_edge.stringSize(m_fontSize);
m_edges[noa].m_height = d.height + 8;
m_edges[noa].m_width = d.width + 8;
m_edges[noa].m_side = m_edges[noa].m_width / 2;
m_edges[noa].m_tb = m_edges[noa].m_height / 2;
}
}
}
/**
* This will fill two arrays with the Nodes and Edges from the tree
* into a particular order.
*
* @param t The top Node of the tree.
* @param l An array that has already been allocated, to be filled.
* @param k An array that has already been allocated, to be filled.
*/
private void arrayFill(Node t, NodeInfo[] l, EdgeInfo[] k) {
//this will take the top node and the array to fill
//it will go through the tree structure and and fill the array with the
//nodes
//from top to bottom left to right
//note I do not believe this function will be able to deal with multiple
//parents
if (t == null || l == null) {
System.exit(1); //this is just a preliminary safety check
//(i shouldn' need it)
}
Edge e;
Node r,s;
l[0] = new NodeInfo();
l[0].m_node = t;
l[0].m_parent = -1;
l[0].m_change = true;
int floater; //this will point at a node that has previously been
//put in the list
//all of the children that this node has shall be put in the list ,
//once this is done the floater shall point at the next node in the list
//this will allow the nodes to be put into order from closest to top node
//to furtherest from top node
int free_space = 1; //the next empty array position
double height = t.getTop(); //this will be used to determine if the node
//has a
//new height compared to the
//previous one
for (floater = 0;floater < free_space;floater++) {
r = l[floater].m_node;
for (int noa = 0;(e = r.getChild(noa)) != null;noa++) {
//this loop pulls out each child of r
//e points to a child edge, getTarget will return that edges child node
s = e.getTarget();
l[free_space] = new NodeInfo();
l[free_space].m_node = s;
l[free_space].m_parent = free_space - 1;
k[free_space - 1] = new EdgeInfo();
k[free_space - 1].m_edge = e;
k[free_space - 1].m_parent = floater;
k[free_space - 1].m_child = free_space; //note although it's child
//will always have a subscript
//of 1 more , I may not nessecarily have access to that
//and it will need the subscr.. for multiple parents
//determine if level of node has changed from previous one
if (height != s.getTop()) {
l[free_space].m_change = true;
height = s.getTop();
}
else {
l[free_space].m_change = false;
}
free_space++;
}
}
}
/**
* Internal Class for containing display information about a Node.
*/
private class NodeInfo {
//this class contains a pointer to the node itself along with extra
//information
//about the node used by the Displayer class
/** The y pos of the node on screen. */
int m_top = 32000; //the main node coords calculated out
/** The x pos of the node on screen. */
int m_center; // these coords will probably change each refresh
//and are the positioning coords
//which the rest of the offsets use
/** The offset to get to the left or right of the node. */
int m_side; //these are the screen offset for the dimensions of
//the node relative to the nodes
//internal top and center values (after they have been converted to
//screen coords
/** The width of the node. */
int m_width;
/** The height of the node. */
int m_height;
/** True if the node is at the start (left) of a new level (not sibling
* group). */
boolean m_change; //this is quickly used to identify whether the node
//has chenged height from the
//previous one to help speed up the calculation of what row it lies in
/** The subscript number of the Nodes parent. */
int m_parent; //this is the index of the nodes parent edge in an array
/** The rough position of the node relative to the screen. */
int m_quad; //what of nine quadrants is it in
/*
12 10 9
20 18 17 //18 being the screen
36 34 33 //this arrangement uses 6 bits, each bit represents a
row or column
*/
/** The Node itself. */
Node m_node;
}
/**
* Internal Class for containing display information about an Edge.
*/
private class EdgeInfo {
//this class contains a pointer to the edge along with all the other
//extra info about the edge
/** The parent subscript (for a Node). */
int m_parent; //array indexs for its two connections
/** The child subscript (for a Node). */
int m_child;
/** The distance from the center of the text to either side. */
int m_side; //these are used to describe the dimensions of the
//text
/** The distance from the center of the text to top or bottom. */
int m_tb; //tb stands for top , bottom, this is simply the
//distance from the middle to top bottom
/** The width of the text. */
int m_width;
/** The height of the text. */
int m_height;
/** The Edge itself. */
Edge m_edge;
}
/**
* Main method for testing this class.
* @param args first argument should be the name of a file that contains
* a tree discription in dot format.
*/
public static void main(String[] args)
{
try
{
//put in the random data generator right here
// this call with import java.lang gives me between 0 and 1 Math.random
TreeBuild builder = new TreeBuild();
Node top = null;
NodePlace arra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -