001    package org.shiftone.jrat.provider.tree.ui.trace.pie;
002    
003    
004    import org.shiftone.jrat.provider.tree.ui.TraceTreeNode;
005    import org.shiftone.jrat.provider.tree.ui.trace.PercentColorLookup;
006    import org.shiftone.jrat.provider.tree.ui.trace.graph.BufferedJComponent;
007    import org.shiftone.jrat.util.log.Logger;
008    
009    import java.awt.*;
010    
011    
012    /**
013     * @author jeff@shiftone.org (Jeff Drost)
014     */
015    public class PieGraphComponent extends BufferedJComponent {
016    
017        private static final Logger LOG = Logger.getLogger(PieGraphComponent.class);
018        private TraceTreeNode root;
019        private PercentColorLookup colorLookup = new PercentColorLookup();
020    
021        public synchronized void setStackTreeNode(TraceTreeNode root) {
022    
023            this.root = root;
024    
025            dataChanged();
026    
027            if (isVisible()) {
028                repaint();
029            }
030        }
031    
032    
033        protected void paintBuffer(Graphics2D g) {
034    
035            double totalRadius = Math.min(getWidth(), getHeight()) / 2;
036            int x = getWidth() / 2;
037            int y = getHeight() / 2;
038    
039            // int maxDepth = getMaxEffectiveDepth(root) ;
040            int maxDepth = 10;
041            double radiusDelta = totalRadius / maxDepth;
042    
043            paintNode(g, root, x, y, radiusDelta, 0, 360, 1, maxDepth);
044        }
045    
046    
047        public int getMaxEffectiveDepth(TraceTreeNode node) {
048    
049            int maxChildDepth = 0;
050    
051            for (int i = 0; i < node.getChildCount(); i++) {
052                TraceTreeNode child = (TraceTreeNode) node.getChildAt(i);
053    
054                if (child.getTotalDuration() > 0) {
055                    maxChildDepth = Math.max(maxChildDepth, getMaxEffectiveDepth(child));
056                }
057            }
058    
059            return 1 + maxChildDepth;
060        }
061    
062    
063        public void paintNode(Graphics2D g, TraceTreeNode node, int x, int y, double radiusDelta, int min, int max,
064                              int depth, int maxDepth) {
065    
066            if ((node == null) || (depth > maxDepth)) {
067                return;
068            }
069    
070            long totalDegrees = max - min;
071            long totalNanos = node.getTotalDuration();
072    
073            if ((totalNanos > 0) && (node.getChildCount() > 0)) {
074                int startDegrees = min;
075    
076                for (int i = 0; i < node.getChildCount(); i++) {
077                    TraceTreeNode child = (TraceTreeNode) node.getChildAt(i);
078                    long partNanos = child.getTotalDuration();
079                    int partDegrees = (int) ((partNanos * totalDegrees) / totalNanos);
080    
081                    if (partDegrees > 1) {
082                        paintNode(g, child, x, y, radiusDelta, startDegrees, startDegrees + partDegrees, depth + 1,
083                                maxDepth);
084                    }
085    
086                    startDegrees += partDegrees;
087                }
088            }
089    
090            int radius = (int) (radiusDelta * depth);
091            int diameter = radius * 2;
092    
093            g.setColor(colorLookup.getColor(node.getPctOfAvgParentDuration()));
094            g.fillArc(x - radius, y - radius, diameter, diameter, min, max - min);
095        }
096    }