package com.didi.codeProfiler;

import java.awt.*;

import java.util.*;

// A remix of Brad Paley's CodeProfiler,

// this applet shows simultaneous threads of execution.

// as superimposed layers of code. Lines of code are

// sized according to their proportion of execution

// during a given thread, and the layers are colored

// and ordered by thread priority.

// The applet connects three people: Brad, me, and the author of the

// program being profiled.

// Created by Martin Wattenberg, Aug 31, 2002.

// Coded in "remix style": concise & site-specific rather

//                         than general & optimized.

public class CodeLayers extends CodeProfiler {

    class ThreadData { Thread thread; double timing, usage; 

                        LineData[] profile=new LineData[256];}

    class LineData {double usage, currentSize;}

    Hashtable threadTable=new Hashtable();

    Vector threads=new Vector(); // list of threads in order of priority.

    Font[] lineFont=new Font[300];


    public CodeLayers() {

        for (int i=1; i<lineFont.length; i++)

            lineFont[i]=new Font("Helvetica", Font.BOLD, i);




    // Record profile data for each execution thread.

    public synchronized int line(int i) {		

        Thread thread=Thread.currentThread();

        ThreadData data=(ThreadData)threadTable.get(thread);

        if (data==null) {

            data=new ThreadData(); data.thread=thread;

            threadTable.put(thread, data);

            int j; 

            for (j=0; j<threads.size() && data(j).thread.getPriority()<thread.getPriority(); j++);



        if (data.profile[i]==null) data.profile[i]=new LineData();

        data.profile[i].usage++; data.usage++; data.timing=2;

        return i;


    ThreadData data(int i) { return (ThreadData)threads.elementAt(i);}


    void drawCodeLayers(Graphics g, int w, int h) {



        if (programLines==null) return;

        int i,j,n=threads.size();		

        for (i=0; i<n; i++) {

            ThreadData data=data(i);

            if (data.usage<=0 || data.timing<=0) continue;

            LineData[] profile=data.profile;			

            for (j=0; j<profile.length; j++) {

                if (profile[j]==null) continue;





            nt c=Math.max(0, Math.min(255, 1230-200*data.thread.getPriority()));

            g.setColor(new Color((int)(c*.5),64+(int)(c*.5),(int)(100+c*.5)));

            double position=Math.min(data.timing,1)-1; // slide new, old threads in and out of view.			

            for (j=0; j<programLines.length; j++) {

                Line line=programLines[j];

                if (!line.hasLineCall || profile[line.lineAsWrittenIndex]==null)


                double u=profile[line.lineAsWrittenIndex].currentSize;

                if (u==0) continue;

                int lineH=(int)(u*h), lineY=(int)(5+position*(h-10));

                g.setFont(lineFont[Math.max(1,Math.min(lineH, lineFont.length-1))]);

                int q=line.s.indexOf("line(");

                if (q>-1) line.s=line.s.substring(0,q);


                if (line.s.length()==0) // means real code is on previous line.





            data.usage*=.95; data.timing-=.04; // "decay" thread data for smooth animation.					




    // Hook into superclass's animation engine, following Brad's code.

    public synchronized void drawAll(Graphics g) {      

        int w=size().width/2, h=size().height;

        if (w<21 || h<21) return;  

        if (offscreenImage==null ||   

            w!=offscreenImage.getWidth(this) ||   

            h!=offscreenImage.getHeight(this)) {  

            offscreenImage=createImage(w, h);  



        if (offscreenGraphics==null) return;         

            drawCodeLayers(offscreenGraphics, w,h);

        g.drawImage(offscreenImage, 0, 0, this);