/*
* Copyright (C) 2011 Shashank Tulsyan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package neembuu.vfs.test.graphprovider;
import com.sun.tools.visualvm.charts.ChartFactory;
import com.sun.tools.visualvm.charts.SimpleXYChartDescriptor;
import com.sun.tools.visualvm.charts.SimpleXYChartSupport;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.netbeans.lib.profiler.charts.ExposeChartsPackagePrivateAPI;
import org.netbeans.lib.profiler.charts.xy.synchronous.SynchronousXYChart;
/**
* Comments by Jiri Sedlacek
* <pre>
* JFreeCharts are great for creating any kind of static graphs (typically for reports).
* They provide support for all types of existing chart types.
* The benefit of using JFreeChart is fully customizable appearance and
* export to various formats. The only problem of this library is that
* it's not primarily designed for displaying live data. You can hack it to
* display data in real time, but the performance is poor.
*
* That's why I've created the VisualVM charts. The primary (and so far only)
* goal is to provide charts optimized for displaying live data with minimal
* performance and memory overhead. You can easily display a fullscreen graph
* and it will still scroll smoothly while running and adding new values
* (when running on physical hardware, virtualized environment may give
* slightly worse results). There's a real rendering engine behind the
* charts which ensures that only the changed areas of the chart are repainted
* (no full-repaints because of a 1px change). Scrolling the chart means moving
* the already rendered image and only painting the newly displayed area. Last
* but not least, the charts are optimized for displaying over a remote X session -
* rendering is automatically switched to low-quality ensuring good response
* times and interactivity.
*
* The Tracer engine introduced in VisualVM 1.3 further improves
* performance of the charts. I've intensively profiled and optimized
* the charts to minimize the cpu cycles/memory allocations for each repaint.
* As of now, I believe that the VisualVM charts are the fastest real time
* Java charts with the lowest cpu/memory footprint.
* </pre>
* @author Shashank Tulsyan
* @author Geertjan
*/
public final class SpeedGraphJFluid
extends JPanel {
private static final int VALUES_LIMIT = 10;
private final SimpleXYChartSupport support;
private final SynchronousXYChart actual_chart;
public SpeedGraphJFluid() {
SimpleXYChartDescriptor descriptor =
//SimpleXYChartDescriptor.decimal(0,true,VALUES_LIMIT);
SimpleXYChartDescriptor.decimal(0, 10/*24*8*/, 10, 1d, true, VALUES_LIMIT);
descriptor.addLineFillItems("Download Speed");
descriptor.addLineFillItems("Request Speed");
//descriptor.setDetailsItems(new String[]{"Download Speed(KiB/s)", "Request Speed(KiB/s)"});
//descriptor.setChartTitle("<html><font size='+1'><b>SpeedGraph</b></font></html>");
//descriptor.setXAxisDescription("<html>Time</html>");
descriptor.setYAxisDescription("<html>Speed (KiB/s)</html>");
support = ChartFactory.createSimpleXYChart(descriptor);
//new Generator(support).start();
setLayout(new BorderLayout());
add(support.getChart(), BorderLayout.CENTER);
actual_chart = ExposeChartsPackagePrivateAPI.findSynchronousXYChart(support.getChart(),0);
if(actual_chart==null)throw new RuntimeException("Could not find actual chart");
}
//@Override
public void speedChanged(
double downloadSpeedInKiBps,
double requestSpeedInKiBps) {
recentDownloadSpeedObservation = downloadSpeedInKiBps;
recentRequestSpeedObservation = requestSpeedInKiBps;
support.addValues(System.currentTimeMillis(), new long[]{
(long)(recentDownloadSpeedObservation),
(long)(recentRequestSpeedObservation)
});
maxValues[index%VALUES_LIMIT] =
Math.max(recentRequestSpeedObservation, recentDownloadSpeedObservation);
index++;
double max = 0;
for (int i = 0; i < maxValues.length; i++) {
max = Math.max(maxValues[i],max);
}
if(max < previousHeight/2 || previousHeight==-1){
previousHeight = max*1.1;
//System.out.println("contracting to "+previousHeight);
changeHeight(previousHeight);
}if(previousHeight< max ){
previousHeight = max*1.1;
//System.out.println("expanding to "+previousHeight);
changeHeight(previousHeight);
}
}
private void changeHeight(double h){
/*try{
System.out.println("before="+actual_chart.getDataHeight());
Field f = TransformableCanvasComponent.class.getDeclaredField("dataHeight");
f.setAccessible(true);
f.setLong(actual_chart, (long)h);
Method m = ChartComponent.class.getDeclaredMethod("dataBoundsChanged",long.class,long.class,long.class,long.class
,long.class,long.class,long.class,long.class);
m.setAccessible(true);
m.invoke(actual_chart,
actual_chart.getOffsetX(),actual_chart.getOffsetY(),
actual_chart.getDataWidth(),(long)h,
actual_chart.getOffsetX(),actual_chart.getOffsetY(),
actual_chart.getDataWidth(),actual_chart.getDataHeight());
f = TransformableCanvasComponent.class.getDeclaredField("maxOffsetY");
f.setAccessible(true);
f.setLong(actual_chart, (long)h);
//pendingDataHeight
f = TransformableCanvasComponent.class.getDeclaredField("pendingDataHeight");
f.setAccessible(true);
f.setLong(actual_chart, (long)h);
System.out.println("after="+actual_chart.getDataHeight());
}catch(Exception a){
a.printStackTrace(System.err);
}
actual_chart.setDataBounds(actual_chart.getDataOffsetX(),
actual_chart.getDataOffsetY(),
actual_chart.getDataWidth(),
(long)(h));*/
}
private volatile double recentDownloadSpeedObservation = 0;
private volatile double recentRequestSpeedObservation = 0;
double[]maxValues = new double[VALUES_LIMIT];
double previousHeight = -1;
int index = 0;
public static void main(String[] args) {
JFrame fr = new JFrame();
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.setSize(600,400);
fr.getContentPane().add(new SpeedGraphJFluid());
fr.setVisible(true);
}
}