src/main/java/gchisto/gui/panels/VisualizationPanel.java
public interface VisualizationPanel {
    
    /**
     * It returns the panel that will be added to the tabbed pane of
     * the main frame.
     *
     * @return The panel that will be added to the tabbed pane of
     * the main frame.
     */
    public JPanel getPanel();
    
    /**
     * It returns the name of this panel.
     *
     * @return The name of this panel.
     */
    public String getPanelName();
    
    /**
     * It returns the GC trace set listener associated with this panel.
     *
     * @return The GC trace set listener associated with this panel.
     */
    public GCTraceSetListener getListener();
    
    /**
     * It installs the GC trace set of the application in the panel.
     *
     * @param gcTraceSet The GC trace set of the application.
     */
    public void setGCTraceSet(GCTraceSet gcTraceSet);
    
}
src/main/java/gchisto/gctrace/GCTraceSetListener.java
public interface GCTraceSetListener {
    
    /**
     * Called after a GC trace has been added to the GC trace set.
     *
     * @param gcTrace The GC trace added to the GC trace set.
     */
    public void gcTraceAdded(GCTrace gcTrace);
    
    /**
     * Called after a GC trace has been renamed in the GC trace set.
     *
     * @param gcTrace The GC trace renamed in the GC trace set.
     */
    public void gcTraceRenamed(GCTrace gcTrace);
    
    /**
     * Called after a GC trace has been removed from the GC trace set.
     *
     * @param gcTrace The GC trace removed from the GC trace set.
     */
    public void gcTraceRemoved(GCTrace gcTrace);
    
    /**
     * Called after a GC trace has been moved up in the GC trace set.
     *
     * @param gcTrace The GC trace moved up in the GC trace set.
     */
    public void gcTraceMovedUp(GCTrace gcTrace);
    
    /**
     * Called after a GC trace has been moved down in the GC trace set.
     *
     * @param gcTrace The GC trace moved down in the GC trace set.
     */
    public void gcTraceMovedDown(GCTrace gcTrace);
    
}
src/main/java/gchisto/jfreechart/extensions/ChartLocker.java
public class ChartLocker extends Locker implements ChartProgressListener {

    public void chartProgress(ChartProgressEvent event) {
        switch (event.getType()) {
            case ChartProgressEvent.DRAWING_STARTED:
                lock();
                break;
            case ChartProgressEvent.DRAWING_FINISHED:
                unlock();
                break;
        }
    }
}
src/main/java/gchisto/jfreechart/extensions/ChangingCategoryDatasetWithTTG.java
public interface ChangingCategoryDatasetWithTTG
        extends ChangingCategoryDataset, CategoryToolTipGenerator {
}
src/main/java/gchisto/gctrace/GCTrace.java
public abstract class GCTrace extends ArrayList<GCActivitySet> {

    /**
     * The name that is associated with this GC trace. This is unique across
     * all the GC traces that are included in a single GC trace set.
     *
     * @see #getName()
     * @see #setName(String)
     * @see gchisto.gctraceset.GCTraceSet#createUniqueGCTraceName(File)
     */
    private String name;
    /**
     * The date/time when this GC trace was populated.
     *
     * @see #getAddedDate()
     * @see #setAddedDate(Date)
     *
     * TODO
     */
    private Date addedDate;
    /**
     * A map of the GC activity names that appear in this GC trace.
     */
    final private GCActivityNames gcActivityNames = new GCActivityNames();
    /**
     * TODO
     */
    final private GCTraceListenerSet listeners = new GCTraceListenerSet();
    final private Object hashCodeObject = new Object();
    final private GCActivitySet allGCActivities = new GCActivitySet("All");
    private double lastTimeStampSec;

    /**
     * TODO
     */
    abstract public String getSuggestedName();

    /**
     * TODO
     */
    abstract public String getInfoString();

    public boolean equals(Object gcTrace) {
        assert gcTrace instanceof GCTrace;
        return ((GCTrace) gcTrace).hashCodeObject == hashCodeObject;
    }

    public int hashCode() {
        return hashCodeObject.hashCode();
    }

    /**
     * It returns the name that is associated with this GC trace. This is
     * unique across all the GC traces that are included in a single GC trace
     * set.
     *
     * @return The name that is associated with this GC trace. This is
     * unique across all the GC traces that are included in a single GC trace
     * set.
     *
     * @see #setName(String)
     * @see gchisto.gctraceset.GCTraceSet#createUniqueGCTraceName(File)
     */
    public String getName() {
        return name;
    }
    
    public String getLongName() {
        return getName();
    }

    /**
     * It returns the date/time when this GC trace was populated.
     *
     * @return The date/time when this GC trace was populated.
     * @see #setAddedDate(Date)
     *
     * TODO
     */
    public Date getAddedDate() {
        return addedDate;
    }

    /**
     * It returns a map of the GC activity names that appear in this GC trace.
     *
     * @return A map of the GC activity names that appear in this GC trace.
     */
    public GCActivityNames getGCActivityNames() {
        return gcActivityNames;
    }

    public GCActivitySet getAllGCActivities() {
        return allGCActivities;
    }

    public double getLastTimeStampSec() {
        return lastTimeStampSec;
    }
    
    /**
     * It returns an array containing the GC activity names that appear in
     * this GC trace.
     *
     * @return An array containing the GC activity names that appear in this
     * GC trace.
     */
    public String[] getGCActivityNamesArray() {
        return gcActivityNames.getNames();
    }

    /**
     * It sets the name of this GC trace.
     *
     * @param name The new name of this GC trace.
     *
     * @see #getName()
     * @see gchisto.gctraceset.GCTraceSet#createUniqueGCTraceName(File)
     */
    public void setName(String name) {
        ArgumentChecking.notNull(name, "name");

        this.name = name;
    }

    /**
     * It sets the read date/time of this GC trace.
     *
     *
     * @param addedDate The new read date/time of this GC trace.
     * @see #getAddedDate()
     *
     * TODO
     */
    public void setAddedDate(Date addedDate) {
        ArgumentChecking.notNull(addedDate, "addedDate");

        this.addedDate = addedDate;
    }

    /**
     * It adds a new GC activity to this GC trace. The GC activity will be added
     * to the GC activity set that corresponds to the given GC activity name.
     * If a GC activity set does not exist in this GC trace for this GC activity
     * name, it will be created. This version should be used for concurrent
     * GC activities.
     *
     * @param gcActivityName The name of the GC activity to be added.
     * @param startSec The time stamp of the start of the GC activity to
     * be added, in seconds.
     * @param durationSec The duration of the GC activity, in seconds.
     */
    public void addGCActivity(
            int id,
            double startSec,
            double durationSec) {
        ArgumentChecking.withinBounds(id, 0, size() - 1, "id");

        String gcActivityName = gcActivityNames.get(id);
        addGCActivity(id,
                new GCActivity(gcActivityName, startSec, durationSec));
    }

    /**
     * It adds a new GC activity to this GC trace. The GC activity will be added
     * to the GC activity set that corresponds to the given GC activity name.
     * If a GC activity set does not exist in this GC trace for this GC activity
     * name, it will be created. This version should be used for stop-the-world
     * GC activities.
     *
     * @param gcActivityName The name of the GC activity to be added.
     * @param startSec The time stamp of the start of the GC activity to
     * be added, in seconds.
     * @param durationSec The duration of the GC activity, in seconds.
     * @param overheadPerc The concurrent overhead of the GC activity to
     * be added.
     */
    public void addGCActivity(
            int id,
            double startSec,
            double durationSec,
            double overheadPerc) {
        ArgumentChecking.withinBounds(id, 0, size() - 1, "id");

        String gcActivityName = gcActivityNames.get(id);
        addGCActivity(id, new GCActivity(
                gcActivityName,
                startSec, durationSec,
                overheadPerc));
    }

    /**
     * It adds a new GC activity to this GC trace. This is a private method
     * that is used by all the public ones.
     *
     * @param gcActivityName The name of the GC activity to be added.
     * @param gcActivity The GC activity to be added.
     */
    synchronized private void addGCActivity(
            int id,
            GCActivity gcActivity) {
        assert 0 <= id && id < size();
        assert 0 <= id && id < gcActivityNames.size();
        assert gcActivityNames.get(id).equals(gcActivity.getName());

        GCActivitySet gcActivitySet = get(id);
        gcActivitySet.addGCActivity(gcActivity);
        allGCActivities.addGCActivity(gcActivity);
        lastTimeStampSec = gcActivity.getEndSec();

        listeners.callGCActivityAdded(this, gcActivitySet, gcActivity);
    }

    public void addGCActivityName(int id, String gcActivityName) {
        assert gcActivityNames.size() == id;
        gcActivityNames.add(id, gcActivityName);
        assert gcActivityNames.size() == id + 1;

        assert size() == id;
        GCActivitySet gcActivitySet = new GCActivitySet(gcActivityName);
        add(id, gcActivitySet);
        assert size() == id + 1;

        listeners.callGCActivityNameAdded(this, id, gcActivityName);
    }

    /**
     * TODO
     */
    synchronized public void addListener(GCTraceListener listener) {
        ArgumentChecking.notNull(listener, "listener");

        listeners.add(listener);
    }

    /**
     * TODO
     */
    synchronized public void removeListener(GCTraceListener listener) {
        ArgumentChecking.notNull(listener, "listener");

        listeners.remove(listener);
    }

    /**
     * TODO
     */
    public void afterAddingToGCTraceSet() {
    // do nothing, unless overriden
    }

    /**
     * TODO
     */
    public void beforeRemovingFromGCTraceSet() {
    // do nothing, unless overriden
    // this has to return before the GC trace is removed from the GC trace set
    }

    /**
     * It creates a new GC trace instance.
     *
     * @param file The file associated with the new GC trace.
     * @param lastModifiedDate The last modified date/time of the new GC trace.
     * @param addedDate Thenew read date/time of the new GC trace.
     *
     * TODO
     */
    public GCTrace() {
    }
}
src/main/java/gchisto/gcactivity/GCActivitySet.java
public class GCActivitySet extends ArrayList<GCActivity> {
    
    /**
     * The name of the GC activities in the set. This name is the "kind"
     * of the GC activities in the set.
     *
     * @see #getGCActivityName()
     */
    final private String gcActivityName;
    
    final private NumberSeq numberSeq = new NumberSeq();
    
    /**
     * It adds a new GC activity to the set. After adding it, it will call the
     * <tt>added()</tt> method on the listeners of this set.
     *
     * @param gcActivity The GC activity to be added to the set.
     */
    public void addGCActivity(GCActivity gcActivity) {
        assert gcActivity != null;
        
        add(gcActivity);
        numberSeq.add(gcActivity.getDurationSec());
    }
    
    /**
     * It returns the name of the GC activities in the set. This name is 
     * the "kind" of the GC activities in the set.
     *
     * @return The name of the GC activities in the set.
     */
    public String getGCActivityName() {
        return gcActivityName;
    }
    
    public NumberSeq getNumberSeq() {
        return numberSeq;
    }
    
    /**
     * It verifies the correctness of the contents in the set.
     */
    public void verify() {
        throw new NotImplementedException();
    }
    
    /**
     * It creates a new GC activity set instance.
     * 
     * @param gcActivityName The name of the GC activites in the set. This
     * name is the "kind" of the GC activities in the set.
     */
    public GCActivitySet(String gcActivityName) {
        this.gcActivityName = gcActivityName;
    }
    
}
src/main/java/gchisto/gctrace/GCTraceListener.java
public interface GCTraceListener {

    /**
     * TODO
     */
    public void gcActivityAdded(
            GCTrace gcTrace,
            GCActivitySet gcActivitySet,
            GCActivity gcActivity);

    public void gcActivityNameAdded(
            GCTrace gcTrace,
            int id,
            String gcActivityName);
}
src/main/java/gchisto/gctrace/GCTraceSet.java
public class GCTraceSet extends LinkedList<GCTrace> implements GCTraceListener {
    
    /**
     * The map that contains all the GC activity names of all the
     * GC traces added to this set.
     *
     * @see #recreateAllGCActivityNames()
     */
    private GCActivityNames allGCActivityNames = new GCActivityNames();
    
    /**
     * The GC trace set listeners.
     *
     * @see #addListener(GCTraceSetListener)
     * @see #removeListener(GCTraceSetListener)
     */
    final private GCTraceSetListenerSet listeners = new GCTraceSetListenerSet();
    
    /**
     * It creates a name for the GC trace that is associated with the
     * given file that is unique in this GC trace set. Typically, the name will
     * be the name of the file, let's call it NAME, without the associated path
     * information. If that is not unique, a suffix .NUM will be added, where
     * NUM is an integer. NUM will start from 0 and will increase until
     * NAME.NUM is unique.
     *
     * @param file The file for which a unique name will be created.
     * @return A unique GC trace name for the given file.
     *
     * TODO
     */
    private String createUniqueGCTraceName(GCTrace gcTrace) {
        assert gcTrace != null;
        
        String originalName = gcTrace.getSuggestedName();
        String name = originalName;
        int i = 0;
        while (findGCTrace(name) != null) {
            ++i;
            name = originalName + "." + i;
        }
        return name;
    }
    
    /**
     * It iterates over the GC traces in this set and recreates
     * the map that contains all the GC activity names.
     */
    private void recreateAllGCActivityNames() {
        allGCActivityNames = new GCActivityNames();
        for (GCTrace trace : this) {
            GCActivityNames gcActivityNames =  trace.getGCActivityNames();
            allGCActivityNames.merge(gcActivityNames);
            
        }
    }
    
    /**
     * It finds the GC trace associated with the given name.
     *
     * @param gcTraceName The name of the GC trace to be looked up.
     * @return The GC trace associated with the given name, or <tt>null</tt>
     * if the name does not appear in this GC trace set.
     */
    public GCTrace findGCTrace(String gcTraceName) {
        ArgumentChecking.notNull(gcTraceName, "gcTraceName");
        
        for (GCTrace trace : this) {
            if (trace.getName().equals(gcTraceName)) {
                return trace;
            }
        }
        return null;
    }
    
    /**
     * It finds the GC trace with the given index.
     *
     * @param index The index of the GC trace to be looked up.
     * @return The GC trace associated with the given index.
     */
    public GCTrace findGCTrace(int index) {
        ArgumentChecking.withinBounds(index, 0, size() - 1, "index");
        
        return get(index);
    }
    
    /**
     * It finds the index of the GC trace associated with the given name.
     *
     * @param gcTraceName The name of the GC trace to be looked up.
     * @return The index of the GC trace associated with the given name,
     * or <tt>-1</tt> if the name does not appear in this GC trace set.
     */
    public int findGCTraceIndex(String gcTraceName) {
        ArgumentChecking.notNull(gcTraceName, "gcTraceName");
        
        int index = 0;
        for (GCTrace trace : this) {
            if (trace.getName().equals(gcTraceName)) {
                return index;
            }
            ++index;
        }
        return -1;
    }
    
    /**
     * It adds a new GC trace to this set. Before adding it, it will set
     * its name to one that is based on the file of the GC trace and
     * that is unique in this set. After adding it, it will call the
     * <tt>gcTraceAdded()</tt> method on the listeners of this set.
     *
     * @param gcTrace The new GC trace to be added to this set.
     *
     * @see #createUniqueGCTraceName(File)
     * @see gchisto.gctraceset.GCTraceSetListener#gcTraceAdded(GCTrace)
     *
     * TODO
     */
    synchronized public void addGCTrace(GCTrace gcTrace) {
        ArgumentChecking.notNull(gcTrace, "gcTrace");
        
        String gcTraceName = createUniqueGCTraceName(gcTrace);
        gcTrace.setName(gcTraceName);
        gcTrace.setAddedDate(new Date(System.currentTimeMillis()));
        gcTrace.addListener(this);
        add(gcTrace);
        
        recreateAllGCActivityNames();
        listeners.callGCTraceAdded(gcTrace);
        gcTrace.afterAddingToGCTraceSet();
    }
    
    /**
     * It renames a GC trace. If the new name already exists, it will do
     * nothing. If the new name does not exist, it will set the name of
     * the GC trace to the new one. After renaming it, it will call the
     * <tt>gcTraceRenamed()</tt> method on the listeners of this set.
     *
     * @param gcTraceName The name of the GC trace to be renamed.
     * @param newName The new name of the GC trace.
     *
     * @see gchisto.gctraceset.GCTraceSetListener#gcTraceRenamed(GCTrace)
     */
    synchronized public void rename(String gcTraceName, String newName) {
        ArgumentChecking.notNull(gcTraceName, "gcTraceName");
        ArgumentChecking.notNull(newName, "newName");
        
        GCTrace gcTrace = findGCTrace(gcTraceName);
        ErrorReporting.fatalError(gcTrace != null,
                gcTraceName + " does not exist in the GC trace set.");
        if (findGCTrace(newName) == null) {
            gcTrace.setName(newName);
            listeners.callGCTraceRenamed(gcTrace);
        } else {
            ErrorReporting.warning("GC trace name " + newName +
                    " already exists.");
        }
    }
    
    /**
     * It removes the GC trace associated with the given name from this set.
     * After removing it, it will call the <tt>gcTraceRemoved</tt> method
     * on the listeners of this set.
     *
     * @param gcTraceName The name of the GC trace to be removed.
     *
     * @see gchisto.gctraceset.GCTraceSetListener#gcTraceRemoved(GCTrace)
     */
    synchronized public void remove(String gcTraceName) {
        ArgumentChecking.notNull(gcTraceName, "gcTraceName");
        
        GCTrace gcTrace = findGCTrace(gcTraceName);
        ErrorReporting.fatalError(gcTrace != null,
                gcTraceName + " does not exist in the GC trace set");
        gcTrace.beforeRemovingFromGCTraceSet();
        boolean ret = super.remove(gcTrace);
        assert ret;
        
        recreateAllGCActivityNames();
        listeners.callGCTraceRemoved(gcTrace);
    }
    
    /**
     * It moves the GC trace associated with the given name up in the order
     * in this set, so that its index is its old index minus 1. If its
     * index is 0, then it does nothing. After moving it, it will call
     * the <tt>gcTraceMovedUp</tt> method on the listeners of this set.
     *
     * @param gcTraceName The name of the GC trace to be moved.
     *
     * @see gchisto.gctraceset.GCTraceSetListener#gcTraceMovedUp(GCTrace)
     */
    synchronized public void moveUp(String gcTraceName) {
        ArgumentChecking.notNull(gcTraceName, "gcTraceName");
        
        GCTrace gcTrace = findGCTrace(gcTraceName);
        ErrorReporting.fatalError(gcTrace != null,
                gcTraceName + " does not exist in the GC trace set");
        int index = indexOf(gcTrace);
        assert 0 <= index && index < size();
        if (index > 0) {
            super.remove(gcTrace);
            add(index - 1, gcTrace);
            listeners.callGCTraceMovedUp(gcTrace);
        } else {
            ErrorReporting.warning("GC trace " + gcTraceName +
                    " already at small index.");
        }
    }
    
    /**
     * It moves the GC trace associated with the given name down in the order
     * in this set, so that its index is its old index plus 1. If its
     * index is the highest, then it does nothing. After moving it, it will call
     * the <tt>gcTraceMovedDown</tt> method on the listeners of this set.
     *
     * @param gcTraceName The name of the GC trace to be moved.
     *
     * @see gchisto.gctraceset.GCTraceSetListener#gcTraceMovedDown(GCTrace)
     */
    synchronized public void moveDown(String gcTraceName) {
        ArgumentChecking.notNull(gcTraceName, "gcTraceName");
        
        GCTrace gcTrace = findGCTrace(gcTraceName);
        ErrorReporting.fatalError(gcTrace != null,
                gcTraceName + " does not exist in the GC trace set");
        int index = indexOf(gcTrace);
        assert 0 <= index && index < size();
        if (index < (size() - 1)) {
            super.remove(gcTrace);
            add(index + 1, gcTrace);
            listeners.callGCTraceMovedDown(gcTrace);
        } else {
            ErrorReporting.warning("GC trace " + gcTraceName +
                    " already at highest index.");
        }
    }
    
    /**
     * It adds a listener to this set.
     *
     * @param listener The listener to be added to this set.
     */
    synchronized public void addListener(GCTraceSetListener listener) {
        ArgumentChecking.notNull(listener, "listener");
        
        listeners.add(listener);
    }
    
    /**
     * It removes a listener from this set.
     *
     * @param listener The listener to be removed from this set.
     */
    synchronized public void removeListener(GCTraceSetListener listener) {
        ArgumentChecking.notNull(listener, "listener");
        
        listeners.remove(listener);
    }
    
    public GCActivityNames getAllGCActivityNames() {
        return allGCActivityNames;
    }
    
    /**
     * It returns the ID of the given GC activity name in the map that
     * contains all the GC activity names that appear in the GC traces of
     * this set.
     *
     * @param gcActivityName The GC activity name that will be looked up.
     * @return The ID of the given GC activity name in the map that
     * contains all the GC activity names that appear in the GC traces of
     * this set.
     */
    public int getActivityID(String gcActivityName) {
        return allGCActivityNames.indexOf(gcActivityName);
    }
    
    public void gcActivityAdded(
            GCTrace gcTrace,
            GCActivitySet gcActivitySet,
            GCActivity gcActivity) {
    }

    public void gcActivityNameAdded(GCTrace gcTrace,
            int id,
            String gcActivityName) {
        recreateAllGCActivityNames();
    }
    
    /**
     * It creates a new GC trace set instance.
     */
    public GCTraceSet() {
    }

}
src/main/java/gchisto/gcactivity/GCActivity.java
public class GCActivity {
    
    private String name;
    
    /**
     * The time stamp of the start of the GC activity, in seconds.
     *
     * @see #getStartSec()
     */
    private double startSec;
    
    /**
     * The duration of the GC activity, in seconds.
     *
     * @see #getDurationSec()
     */
    private double durationSec;
    
    /**
     * It indicates whether the GC activity is stop-the-world (true),
     * or concurrent (false).
     *
     * @see #isSTW()
     */
    private boolean stw;
    
    /**
     * The overhead percentage of the GC activity.
     *
     * @see #getOverheadPerc()
     */
    private double overheadPerc;
    
    public String getName() {
        return name;
    }
    
    /**
     * It returns the time stamp of the start of the GC activity, in seconds. 
     *
     * @return The time stamp of the start of the GC activity, in seconds. 
     */
    public double getStartSec() {
        return startSec;
    }
    
    /**
     * It returns the time stamp of the end of the GC activity, in seconds. 
     *
     * @return The time stamp of the end of the GC activity, in seconds. 
     */
    public double getEndSec() {
        return startSec + durationSec;
    }
    
    /**
     * It returns the duration of the GC activity, in seconds. 
     *
     * @return The duration of the GC activity, in seconds. 
     */
    public double getDurationSec() {
        return durationSec;
    }
    
    /**
     * It returns whether the GC activity is stop-the-world.
     *
     * @return Whether the GC activity is stop-the-world.
     */
    public boolean isSTW() {
        return stw;
    }
    
    /**
     * It returns whether the GC activity is concurrent.
     *
     * @return Whether the GC activity is concurrent.
     */
    public boolean isConcurrent() {
        return !stw;
    }
    
    /**
     * It returns the overhead percentage of the GC activity.
     *
     * @return The overhead percentage of the GC activity.
     */
    public double getOverheadPerc() {
        return overheadPerc;
    }
    
    /**
     * It creates a new GC activity instance. This version should be used for
     * stop-the-world GC activities.
     *
     * @param startSec The time stamp of the start of the GC activity, in
     * seconds.
     * @param durationSec The duration of the GC activity, in seconds.
     */
    public GCActivity(
            String name,
            double startSec,
            double durationSec) {
        this(name, startSec, durationSec, true, 100.0);
    }
    
    /**
     * It creates a new GC activity instance. This version should be used for
     * concurrent GC activities.
     *
     * @param startSec The time stamp of the start of the GC activity, in
     * seconds.
     * @param durationSec The duration of the GC activity, in seconds.
     * @param overheadPerc The concurrent overhead of the GC activity.
     */
    public GCActivity(
            String name,
            double startSec,
            double durationSec,
            double overheadPerc) {
        this(name, startSec, durationSec, false, overheadPerc);
    }
    
    /**
     * It creates a new GC activity instance. This is a private constructor
     * for use by the public ones.
     *
     * @param startSec The time stamp of the start of the GC activity, in
     * seconds.
     * @param durationSec The duration of the GC activity, in seconds.
     * @param stw It indicates whether the GC activity is stop-the-world (true),
     * or concurrent (false).
     * @param overheadPerc The concurrent overhead of the GC activity.
     */
    private GCActivity(
            String name,
            double startSec,
            double durationSec,
            boolean stw,
            double overheadPerc) {
        ArgumentChecking.lowerBound(startSec, 0.0, "startSec");
        ArgumentChecking.lowerBound(durationSec, 0.0, "durationSec");
        ArgumentChecking.withinBounds(overheadPerc, 0.0, 100.0, "oveheadPerc");
        
        this.name = name;
        this.startSec = startSec;
        this.durationSec = durationSec;
        this.stw = stw;
        this.overheadPerc = overheadPerc;
    }
    
}
src/main/java/gchisto/jfreechart/extensions/ChangingPieDatasetWithTTG.java
public interface ChangingPieDatasetWithTTG
 extends ChangingPieDataset, PieToolTipGenerator {

}


Question: import gchisto.jfreechart.extensions.ChangingCategoryDatasetWithTTG;
import gchisto.jfreechart.extensions.ChangingPieDatasetWithTTG;
import gchisto.jfreechart.extensions.ChartLocker;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JPanel;
import gchisto.gcactivity.GCActivity;
import gchisto.gcactivity.GCActivitySet;
import gchisto.gctrace.GCTrace;
import gchisto.gctrace.GCTraceListener;
import gchisto.gctrace.GCTraceSet;
import gchisto.gctrace.GCTraceSetListener;
import gchisto.gui.panels.VisualizationPanel;
/*
 * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */
package gchisto.gui.panels.gcstats;


/**
 * This is the main GC Stats panel that contains summary GC statistics for the
 * loaded GC traces, in both tables and bar charts.
 *
 * @author Tony Printezis
 */
public class Panel extends javax.swing.JPanel
        implements VisualizationPanel, GCTraceSetListener, GCTraceListener {

    /**
     * The prefix string that will be added to the title of all the tabbed panes,
     * if they contain a chart.
     */
    static final private String CHART_PREFIX = "Chart: ";
    /**
     * The GC trace set that will provide the data for this panel.
     */
    private GCTraceSet gcTraceSet;
    final private List<GCStatsChartPanel> panelsSingle =
            new LinkedList<GCStatsChartPanel>();
    final private List<GCStatsChartPanel> panelsMulti =
            new LinkedList<GCStatsChartPanel>();
    final private List<GCStatsChartPanel> panelsAll =
            new LinkedList<GCStatsChartPanel>();
    /**
     * TODO
     */
    private DatasetGenerator datasetGenerator;
    final private ChartLocker locker = new ChartLocker();

    private void createBreakdownChartPanelSingle(
            int metric,
            DatasetGenerator datasetGenerator,
            List<GCStatsChartPanel> list) {
        ChangingPieDatasetWithTTG dataset =
                datasetGenerator.newPieDatsetWithTTG(metric);
        GCStatsChartPanel panel = new BreakdownChartPanelSingle(
                CHART_PREFIX + DatasetGenerator.getMetricName(metric),
                DatasetGenerator.getUnitName(metric),
                dataset, locker);
        list.add(panel);
    }

    private void createBreakdownChartPanelMulti(
            int metric,
            DatasetGenerator datasetGenerator,
            List<GCStatsChartPanel> list) {
        ChangingCategoryDatasetWithTTG dataset =
                datasetGenerator.newCategoryDatasetWithTTG(metric, true);
        GCStatsChartPanel panel = new BreakdownChartPanelMulti(
                CHART_PREFIX + DatasetGenerator.getMetricName(metric),
                DatasetGenerator.getUnitName(metric),
                dataset, locker);
        list.add(panel);
    }

    /**
     * It adds a new metric chart panel to the tabbed pane set.
     *
     * @param metric The metric that will be shown in the chart.
     * @param datasetGenerator The generator that will produce the datasetGenerator
     * for this chart.
     * @param ignoreAggregate It determines whether to ignore the aggregate
     * GC activity or not.
     */
    private void createMetricChartPanel(
            int metric,
            DatasetGenerator datasetGenerator,
            List<GCStatsChartPanel> list) {
        ChangingCategoryDatasetWithTTG dataset =
                datasetGenerator.newCategoryDatasetWithTTG(metric, false);
        GCStatsChartPanel panel =
                new MetricChartPanel(
                CHART_PREFIX + DatasetGenerator.getMetricName(metric),
                DatasetGenerator.getUnitName(metric),
                dataset, locker);
        list.add(panel);
    }

Answer:     synchronized public void gcTraceAdded(GCTrace gcTrace) {