/*
* Created on Sep 13, 2004
* Created by Olivier Chalouhi
* Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.ui.swt.views.stats;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.impl.DownloadManagerRateController;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.global.GlobalManagerStats;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.peer.PEPeer;
import org.gudy.azureus2.core3.peer.PEPeerManager;
import org.gudy.azureus2.core3.peer.PEPeerStats;
import org.gudy.azureus2.core3.stats.transfer.OverallStats;
import org.gudy.azureus2.core3.stats.transfer.StatsFactory;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.DisplayFormatters;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.TextViewerWindow;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.BufferedLabel;
import org.gudy.azureus2.ui.swt.components.Legend;
import org.gudy.azureus2.ui.swt.components.graphics.PingGraphic;
import org.gudy.azureus2.ui.swt.components.graphics.Plot3D;
import org.gudy.azureus2.ui.swt.components.graphics.SpeedGraphic;
import org.gudy.azureus2.ui.swt.components.graphics.ValueFormater;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.plugins.UISWTView;
import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.networkmanager.NetworkConnection;
import com.aelitis.azureus.core.networkmanager.Transport;
import com.aelitis.azureus.core.networkmanager.TransportStartpoint;
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
import com.aelitis.azureus.core.proxy.AEProxySelector;
import com.aelitis.azureus.core.proxy.AEProxySelectorFactory;
import com.aelitis.azureus.core.speedmanager.SpeedManager;
import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
import com.aelitis.azureus.core.speedmanager.SpeedManagerPingMapper;
import com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource;
import com.aelitis.azureus.core.speedmanager.SpeedManagerPingZone;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.net.udp.uc.PRUDPPacketHandler;
import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory;
/**
*
*/
public class TransferStatsView
implements UISWTViewCoreEventListener
{
public static final String MSGID_PREFIX = "TransferStatsView";
private static final int MAX_DISPLAYED_PING_MILLIS = 1199; // prevents us hitting 1200 and resulting in graph expanding to 1400
private static final int MAX_DISPLAYED_PING_MILLIS_DISP = 1200; // tidy display
private AzureusCore azureus_core;
private GlobalManager global_manager;
private GlobalManagerStats stats;
private SpeedManager speedManager;
private OverallStats totalStats;
private Composite mainPanel;
private Composite blahPanel;
private BufferedLabel asn,estUpCap,estDownCap;
private BufferedLabel uploadBiaser;
private BufferedLabel currentIP;
private Composite connectionPanel;
private BufferedLabel upload_label, connection_label;
private SpeedGraphic upload_graphic;
private SpeedGraphic connection_graphic;
private TabFolder con_folder;
private long last_route_update;
private Composite route_comp;
private BufferedLabel[][] route_labels = new BufferedLabel[0][0];
private Map<String,Long> route_last_seen = new HashMap<String, Long>();
private Composite generalPanel;
private BufferedLabel totalLabel;
private BufferedLabel nowUp, nowDown, sessionDown, sessionUp, session_ratio, sessionTime, totalDown, totalUp, total_ratio, totalTime;
private Label socksState;
private BufferedLabel socksCurrent, socksFails;
private Label socksMore;
private Group autoSpeedPanel;
private StackLayout autoSpeedPanelLayout;
private Composite autoSpeedInfoPanel;
private Composite autoSpeedDisabledPanel;
private PingGraphic pingGraph;
private plotView[] plot_views;
private zoneView[] zone_views;
private limitToTextHelper limit_to_text = new limitToTextHelper();
private final DecimalFormat formatter = new DecimalFormat( "##.#" );
private boolean initialised;
private UISWTView swtView;
public TransferStatsView() {
AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
public void azureusCoreRunning(AzureusCore core) {
azureus_core = core;
global_manager = core.getGlobalManager();
stats = global_manager.getStats();
speedManager = core.getSpeedManager();
totalStats = StatsFactory.getStats();
}
});
pingGraph = PingGraphic.getInstance();
}
private void initialize(Composite composite) {
mainPanel = new Composite(composite,SWT.NULL);
GridLayout mainLayout = new GridLayout();
mainPanel.setLayout(mainLayout);
AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
public void azureusCoreRunning(AzureusCore core) {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (mainPanel == null || mainPanel.isDisposed()) {
return;
}
createGeneralPanel();
createConnectionPanel();
createCapacityPanel();
createAutoSpeedPanel();
initialised = true;
}
});
}
});
}
private void createGeneralPanel() {
generalPanel = new Composite(mainPanel, SWT.NULL);
GridLayout outerLayout = new GridLayout();
outerLayout.numColumns = 2;
generalPanel.setLayout(outerLayout);
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
generalPanel.setLayoutData(gridData);
Composite generalStatsPanel = new Composite(generalPanel,SWT.BORDER);
GridData generalStatsPanelGridData = new GridData(GridData.FILL_HORIZONTAL);
generalStatsPanelGridData.grabExcessHorizontalSpace = true;
generalStatsPanel.setLayoutData(generalStatsPanelGridData);
GridLayout panelLayout = new GridLayout();
panelLayout.numColumns = 5;
panelLayout.makeColumnsEqualWidth = true;
generalStatsPanel.setLayout(panelLayout);
Label lbl = new Label(generalStatsPanel,SWT.NULL);
lbl = new Label(generalStatsPanel,SWT.NULL);
Messages.setLanguageText(lbl,"SpeedView.stats.downloaded");
lbl = new Label(generalStatsPanel,SWT.NULL);
Messages.setLanguageText(lbl,"SpeedView.stats.uploaded");
lbl = new Label(generalStatsPanel,SWT.NULL);
Messages.setLanguageText(lbl,"SpeedView.stats.ratio");
lbl = new Label(generalStatsPanel,SWT.NULL);
Messages.setLanguageText(lbl,"SpeedView.stats.uptime");
lbl = new Label(generalStatsPanel,SWT.NULL);
lbl = new Label(generalStatsPanel,SWT.NULL);
lbl = new Label(generalStatsPanel,SWT.NULL);
lbl = new Label(generalStatsPanel,SWT.NULL);
lbl = new Label(generalStatsPanel,SWT.NULL);
/////// NOW /////////
Label nowLabel = new Label(generalStatsPanel,SWT.NULL);
gridData = new GridData(GridData.FILL_HORIZONTAL);
nowLabel.setLayoutData(gridData);
Messages.setLanguageText(nowLabel,"SpeedView.stats.now");
nowDown = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
nowDown.setLayoutData(gridData);
nowUp = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
nowUp.setLayoutData(gridData);
lbl = new Label(generalStatsPanel,SWT.NULL);
lbl = new Label(generalStatsPanel,SWT.NULL);
//////// SESSION ////////
Label sessionLabel = new Label(generalStatsPanel,SWT.NULL);
gridData = new GridData(GridData.FILL_HORIZONTAL);
sessionLabel.setLayoutData(gridData);
Messages.setLanguageText(sessionLabel,"SpeedView.stats.session");
sessionDown = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
sessionDown.setLayoutData(gridData);
sessionUp = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
sessionUp.setLayoutData(gridData);
session_ratio = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
session_ratio.setLayoutData(gridData);
sessionTime = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED );
gridData = new GridData(GridData.FILL_HORIZONTAL);
sessionTime.setLayoutData(gridData);
///////// TOTAL ///////////
totalLabel = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED );
gridData = new GridData(GridData.FILL_HORIZONTAL);
totalLabel.setLayoutData(gridData);
Messages.setLanguageText(totalLabel.getWidget(),"SpeedView.stats.total");
totalDown = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
totalDown.setLayoutData(gridData);
totalUp = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
totalUp.setLayoutData(gridData);
total_ratio = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
total_ratio.setLayoutData(gridData);
totalTime = new BufferedLabel(generalStatsPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
totalTime.setLayoutData(gridData);
for ( Object obj: new Object[]{ nowLabel, sessionLabel, totalLabel }){
Control control;
if ( obj instanceof BufferedLabel ){
control = ((BufferedLabel)obj).getControl();
}else{
control = (Label)obj;
}
final Menu menu = new Menu(control.getShell(), SWT.POP_UP );
control.setMenu( menu );
MenuItem item = new MenuItem( menu,SWT.NONE );
Messages.setLanguageText( item, "MainWindow.menu.view.configuration" );
item.addSelectionListener(
new SelectionAdapter()
{
public void
widgetSelected(
SelectionEvent e)
{
UIFunctions uif = UIFunctionsManager.getUIFunctions();
if (uif != null) {
uif.openView(UIFunctions.VIEW_CONFIG, "Stats");
}
}
});
}
// SOCKS area
Composite generalSocksPanel = new Composite(generalPanel,SWT.BORDER);
GridData generalSocksData = new GridData();
generalSocksPanel.setLayoutData(generalSocksData);
GridLayout socksLayout = new GridLayout();
socksLayout.numColumns = 2;
generalSocksPanel.setLayout(socksLayout);
lbl = new Label(generalSocksPanel,SWT.NULL);
Messages.setLanguageText(lbl,"label.socks");
lbl = new Label(generalSocksPanel,SWT.NULL);
// proxy state
lbl = new Label(generalSocksPanel,SWT.NULL);
lbl.setText( MessageText.getString( "label.proxy" ) + ":" );
socksState = new Label(generalSocksPanel,SWT.NULL);
gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.widthHint = 120;
socksState.setLayoutData(gridData);
// current details
lbl = new Label(generalSocksPanel,SWT.NULL);
lbl.setText( MessageText.getString( "PeersView.state" ) + ":" );
socksCurrent = new BufferedLabel(generalSocksPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
socksCurrent.setLayoutData(gridData);
// fail details
lbl = new Label(generalSocksPanel,SWT.NULL);
lbl.setText( MessageText.getString( "label.fails" ) + ":" );
socksFails = new BufferedLabel(generalSocksPanel,SWT.DOUBLE_BUFFERED);
gridData = new GridData(GridData.FILL_HORIZONTAL);
socksFails.setLayoutData(gridData);
// more info
lbl = new Label(generalSocksPanel,SWT.NULL);
gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalAlignment = GridData.END;
socksMore = new Label(generalSocksPanel, SWT.NULL );
socksMore.setText( MessageText.getString( "label.more") + "..." );
socksMore.setLayoutData( gridData );
socksMore.setCursor(socksMore.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
socksMore.setForeground(Colors.blue);
socksMore.addMouseListener(new MouseAdapter() {
public void mouseDoubleClick(MouseEvent arg0) {
showSOCKSInfo();
}
public void mouseUp(MouseEvent arg0) {
showSOCKSInfo();
}
});
// got a rare layout bug that results in the generalStatsPanel not showing the bottom row correctly until the panel
// is resized - attempt to fix by sizing based on the socks panel which seems to consistently layout OK
Point socks_size = generalSocksPanel.computeSize( SWT.DEFAULT, SWT.DEFAULT );
Rectangle trim = generalSocksPanel.computeTrim(0, 0, socks_size.x, socks_size.y );
generalStatsPanelGridData.heightHint = socks_size.y - ( trim.height - socks_size.y );
}
private void
showSOCKSInfo()
{
AEProxySelector proxy_selector = AEProxySelectorFactory.getSelector();
String info = proxy_selector.getInfo();
TextViewerWindow viewer = new TextViewerWindow(
MessageText.getString( "proxy.info.title" ),
null,
info, false );
}
private void
createCapacityPanel()
{
blahPanel = new Composite(mainPanel,SWT.NONE);
GridData blahPanelData = new GridData(GridData.FILL_HORIZONTAL);
blahPanel.setLayoutData(blahPanelData);
GridLayout panelLayout = new GridLayout();
panelLayout.numColumns = 8;
blahPanel.setLayout(panelLayout);
Label label;
GridData gridData;
label = new Label(blahPanel,SWT.NONE);
Messages.setLanguageText(label,"SpeedView.stats.asn");
asn = new BufferedLabel(blahPanel,SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL);
asn.setLayoutData(gridData);
label = new Label(blahPanel,SWT.NONE);
Messages.setLanguageText(label,"label.current_ip");
currentIP = new BufferedLabel(blahPanel,SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL);
currentIP.setLayoutData(gridData);
label = new Label(blahPanel,SWT.NONE);
Messages.setLanguageText(label,"SpeedView.stats.estupcap");
estUpCap = new BufferedLabel(blahPanel,SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL);
estUpCap.setLayoutData(gridData);
label = new Label(blahPanel,SWT.NONE);
Messages.setLanguageText(label,"SpeedView.stats.estdowncap");
estDownCap = new BufferedLabel(blahPanel,SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL);
estDownCap.setLayoutData(gridData);
label = new Label(blahPanel,SWT.NONE);
Messages.setLanguageText(label,"SpeedView.stats.upbias");
uploadBiaser = new BufferedLabel(blahPanel,SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 7;
uploadBiaser.setLayoutData(gridData);
}
private void
createConnectionPanel()
{
connectionPanel = new Composite(mainPanel,SWT.NONE);
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
connectionPanel.setLayoutData(gridData);
GridLayout panelLayout = new GridLayout();
panelLayout.numColumns = 2;
panelLayout.makeColumnsEqualWidth = true;
connectionPanel.setLayout(panelLayout);
Composite conn_area = new Composite( connectionPanel, SWT.NULL );
gridData = new GridData(GridData.FILL_HORIZONTAL);
conn_area.setLayoutData(gridData);
panelLayout = new GridLayout();
panelLayout.numColumns = 2;
conn_area.setLayout(panelLayout);
Label label = new Label( conn_area, SWT.NULL );
Messages.setLanguageText( label, "SpeedView.stats.con" );
connection_label = new BufferedLabel( conn_area, SWT.DOUBLE_BUFFERED );
gridData = new GridData(GridData.FILL_HORIZONTAL);
connection_label.setLayoutData(gridData);
Composite upload_area = new Composite( connectionPanel, SWT.NULL );
gridData = new GridData(GridData.FILL_HORIZONTAL);
upload_area.setLayoutData(gridData);
panelLayout = new GridLayout();
panelLayout.numColumns = 2;
upload_area.setLayout(panelLayout);
label = new Label( upload_area, SWT.NULL );
Messages.setLanguageText( label, "SpeedView.stats.upload" );
upload_label = new BufferedLabel( upload_area, SWT.DOUBLE_BUFFERED );
gridData = new GridData(GridData.FILL_HORIZONTAL);
upload_label.setLayoutData(gridData);
// connections
con_folder = new TabFolder(connectionPanel, SWT.LEFT);
gridData = new GridData(GridData.FILL_BOTH);
gridData.horizontalSpan = 1;
con_folder.setLayoutData(gridData);
con_folder.setBackground(Colors.background);
// connection counts
TabItem conn_item = new TabItem(con_folder, SWT.NULL);
conn_item.setText( MessageText.getString( "label.connections" ));
Canvas connection_canvas = new Canvas(con_folder,SWT.NO_BACKGROUND);
conn_item.setControl( connection_canvas );
gridData = new GridData(GridData.FILL_BOTH);
gridData.heightHint = 200;
connection_canvas.setLayoutData(gridData);
connection_graphic =
SpeedGraphic.getInstance(
new ValueFormater()
{
public String
format(int value)
{
return( String.valueOf( value ));
}
});
connection_graphic.initialize(connection_canvas);
Color[] colors = connection_graphic.colors;
connection_graphic.setLineColors( colors );
// route info
TabItem route_info_tab = new TabItem(con_folder, SWT.NULL);
route_info_tab.setText( MessageText.getString( "label.routing" ));
Composite route_tab_comp = new Composite( con_folder, SWT.NULL );
route_tab_comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
GridLayout routeTabLayout = new GridLayout();
routeTabLayout.numColumns = 1;
route_tab_comp.setLayout(routeTabLayout);
route_info_tab.setControl( route_tab_comp );
ScrolledComposite sc = new ScrolledComposite( route_tab_comp, SWT.V_SCROLL );
sc.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
route_comp = new Composite( sc, SWT.NULL );
route_comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
GridLayout routeLayout = new GridLayout();
routeLayout.numColumns = 3;
//routeLayout.makeColumnsEqualWidth = true;
route_comp.setLayout(routeLayout);
sc.setContent( route_comp );
buildRouteComponent( 5 );
// upload queued
Canvas upload_canvas = new Canvas(connectionPanel,SWT.NO_BACKGROUND);
gridData = new GridData(GridData.FILL_BOTH);
gridData.heightHint = 200;
upload_canvas.setLayoutData(gridData);
upload_graphic =
SpeedGraphic.getInstance(
new ValueFormater()
{
public String
format(int value)
{
return DisplayFormatters.formatByteCountToKiBEtc(value);
}
});
upload_graphic.initialize(upload_canvas);
}
private void
buildRouteComponent(
int rows )
{
boolean changed = false;
if ( rows <= route_labels.length ){
for ( int i=rows;i<route_labels.length;i++){
for ( int j=0;j<3;j++){
route_labels[i][j].setText( "" );
}
}
}else{
Control[] labels = route_comp.getChildren();
for (int i = 0; i < labels.length; i++){
labels[i].dispose();
}
Label h1 = new Label( route_comp, SWT.NULL );
h1.setLayoutData( new GridData(GridData.FILL_HORIZONTAL ));
h1.setText( MessageText.getString( "label.route" ));
Label h2 = new Label( route_comp, SWT.NULL );
h2.setLayoutData( new GridData(GridData.FILL_HORIZONTAL ));
h2.setText( MessageText.getString( "tps.type.incoming" ));
Label h3 = new Label( route_comp, SWT.NULL );
h3.setLayoutData( new GridData(GridData.FILL_HORIZONTAL ));
h3.setText( MessageText.getString( "label.outgoing" ));
new Label( route_comp, SWT.NULL );
new Label( route_comp, SWT.NULL );
new Label( route_comp, SWT.NULL );
route_labels = new BufferedLabel[rows][3];
for ( int i=0;i<rows;i++ ){
for ( int j=0;j<3;j++){
BufferedLabel l = new BufferedLabel( route_comp, SWT.DOUBLE_BUFFERED );
GridData gridData = new GridData(GridData.FILL_HORIZONTAL );
l.setLayoutData( gridData );
route_labels[i][j] = l;
}
}
changed = true;
}
Point size = route_comp.computeSize(route_comp.getParent().getSize().x, SWT.DEFAULT);
changed = changed || !route_comp.getSize().equals( size );
route_comp.setSize(size);
if ( !changed ){
// sometimes things get layouted when not visibel and things don't work proper when visibilized ;(
// look for something zero height that shouldn't be
for ( int i=0;i<route_labels.length;i++){
for (int j=0;j<3;j++){
BufferedLabel lab = route_labels[i][j];
if ( lab.getControl().getSize().y == 0 && lab.getText().length() > 0 ){
changed = true;
}
}
}
}
if ( changed ){
route_comp.getParent().layout( true, true );
}
route_comp.update();
}
private void createAutoSpeedPanel() {
autoSpeedPanel = new Group(mainPanel,SWT.NONE);
GridData generalPanelData = new GridData(GridData.FILL_BOTH);
autoSpeedPanel.setLayoutData(generalPanelData);
Messages.setLanguageText(autoSpeedPanel,"SpeedView.stats.autospeed", new String[]{ String.valueOf( MAX_DISPLAYED_PING_MILLIS_DISP )});
autoSpeedPanelLayout = new StackLayout();
autoSpeedPanel.setLayout(autoSpeedPanelLayout);
autoSpeedInfoPanel = new Composite(autoSpeedPanel,SWT.NULL);
autoSpeedInfoPanel.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout layout = new GridLayout();
layout.numColumns = 8;
layout.makeColumnsEqualWidth = true;
autoSpeedInfoPanel.setLayout(layout);
Canvas pingCanvas = new Canvas(autoSpeedInfoPanel,SWT.NO_BACKGROUND);
GridData gridData = new GridData(GridData.FILL_BOTH);
gridData.horizontalSpan = 4;
pingCanvas.setLayoutData(gridData);
pingGraph.initialize(pingCanvas);
TabFolder folder = new TabFolder(autoSpeedInfoPanel, SWT.LEFT);
gridData = new GridData(GridData.FILL_BOTH);
gridData.horizontalSpan = 4;
folder.setLayoutData(gridData);
folder.setBackground(Colors.background);
ValueFormater speed_formatter =
new ValueFormater()
{
public String
format(
int value)
{
return( DisplayFormatters.formatByteCountToKiBEtc( value ));
}
};
ValueFormater time_formatter =
new ValueFormater()
{
public String
format(
int value)
{
return( value + " ms" );
}
};
ValueFormater[] formatters = new ValueFormater[]{ speed_formatter, speed_formatter, time_formatter };
String[] labels = new String[]{ "up", "down", "ping" };
SpeedManagerPingMapper[] mappers = speedManager.getMappers();
plot_views = new plotView[mappers.length];
zone_views = new zoneView[mappers.length];
for (int i=0;i<mappers.length;i++){
SpeedManagerPingMapper mapper = mappers[i];
TabItem plot_item = new TabItem(folder, SWT.NULL);
plot_item.setText( "Plot " + mapper.getName());
Canvas plotCanvas = new Canvas(folder,SWT.NO_BACKGROUND);
gridData = new GridData(GridData.FILL_BOTH);
plotCanvas.setLayoutData(gridData);
plot_views[i] = new plotView( mapper, plotCanvas, labels, formatters );
plot_item.setControl( plotCanvas );
TabItem zones_item = new TabItem(folder, SWT.NULL);
zones_item.setText( "Zones " + mapper.getName() );
Canvas zoneCanvas = new Canvas(folder,SWT.NO_BACKGROUND);
gridData = new GridData(GridData.FILL_BOTH);
zoneCanvas.setLayoutData(gridData);
zone_views[i] = new zoneView( mapper, zoneCanvas, labels, formatters );
zones_item.setControl( zoneCanvas );
}
autoSpeedDisabledPanel = new Composite(autoSpeedPanel,SWT.NULL);
autoSpeedDisabledPanel.setLayout(new GridLayout());
Label disabled = new Label(autoSpeedDisabledPanel,SWT.NULL);
disabled.setEnabled(false);
Messages.setLanguageText(disabled,"SpeedView.stats.autospeed.disabled");
disabled.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL));
autoSpeedPanelLayout.topControl = speedManager.isAvailable() ? autoSpeedInfoPanel : autoSpeedDisabledPanel;
gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 8;
Legend.createLegendComposite(
autoSpeedInfoPanel,
PingGraphic.colors,
new String[]{
"TransferStatsView.legend.pingaverage",
"TransferStatsView.legend.ping1",
"TransferStatsView.legend.ping2",
"TransferStatsView.legend.ping3" },
gridData );
}
private void delete() {
Utils.disposeComposite(generalPanel);
Utils.disposeComposite(blahPanel);
if ( upload_graphic != null ){
upload_graphic.dispose();
}
if ( connection_graphic != null ){
connection_graphic.dispose();
}
if (pingGraph != null) {
pingGraph.dispose();
}
if (plot_views != null) {
for (int i = 0; i < plot_views.length; i++) {
plot_views[i].dispose();
}
}
if (zone_views != null) {
for (int i = 0; i < zone_views.length; i++) {
zone_views[i].dispose();
}
}
}
private Composite getComposite() {
return mainPanel;
}
private void refresh() {
if ( !initialised ){
return;
}
refreshGeneral();
refreshCapacityPanel();
refreshConnectionPanel();
refreshPingPanel();
}
private void refreshGeneral() {
if ( stats == null ){
return;
}
int now_prot_down_rate = stats.getProtocolReceiveRate();
int now_prot_up_rate = stats.getProtocolSendRate();
int now_total_down_rate = stats.getDataReceiveRate() + now_prot_down_rate;
int now_total_up_rate = stats.getDataSendRate() + now_prot_up_rate;
float now_perc_down = (float)(now_prot_down_rate *100) / (now_total_down_rate==0?1:now_total_down_rate);
float now_perc_up = (float)(now_prot_up_rate *100) / (now_total_up_rate==0?1:now_total_up_rate);
nowDown.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec( now_total_down_rate ) +
" (" + DisplayFormatters.formatByteCountToKiBEtcPerSec( now_prot_down_rate ) +
", " +formatter.format( now_perc_down )+ "%)" );
nowUp.setText(DisplayFormatters.formatByteCountToKiBEtcPerSec( now_total_up_rate ) +
" (" + DisplayFormatters.formatByteCountToKiBEtcPerSec( now_prot_up_rate ) +
", " +formatter.format( now_perc_up )+ "%)" );
///////////////////////////////////////////////////////////////////////
long session_prot_received = stats.getTotalProtocolBytesReceived();
long session_prot_sent = stats.getTotalProtocolBytesSent();
long session_total_received = stats.getTotalDataBytesReceived() + session_prot_received;
long session_total_sent = stats.getTotalDataBytesSent() + session_prot_sent;
float session_perc_received = (float)(session_prot_received *100) / (session_total_received==0?1:session_total_received);
float session_perc_sent = (float)(session_prot_sent *100) / (session_total_sent==0?1:session_total_sent);
sessionDown.setText(DisplayFormatters.formatByteCountToKiBEtc( session_total_received ) +
" (" + DisplayFormatters.formatByteCountToKiBEtc( session_prot_received ) +
", " +formatter.format( session_perc_received )+ "%)" );
sessionUp.setText(DisplayFormatters.formatByteCountToKiBEtc( session_total_sent ) +
" (" + DisplayFormatters.formatByteCountToKiBEtc( session_prot_sent ) +
", " +formatter.format( session_perc_sent )+ "%)" );
////////////////////////////////////////////////////////////////////////
if (totalStats != null) {
long mark = totalStats.getMarkTime();
if ( mark > 0 ){
Messages.setLanguageText(totalLabel.getWidget(),"SpeedView.stats.total.since", new String[]{ new SimpleDateFormat().format( new Date( mark )) });
}else{
Messages.setLanguageText(totalLabel.getWidget(),"SpeedView.stats.total");
}
long dl_bytes = totalStats.getDownloadedBytes( true );
long ul_bytes = totalStats.getUploadedBytes( true );
totalDown.setText(DisplayFormatters.formatByteCountToKiBEtc( dl_bytes ));
totalUp.setText(DisplayFormatters.formatByteCountToKiBEtc( ul_bytes ));
long session_up_time = totalStats.getSessionUpTime();
long total_up_time = totalStats.getTotalUpTime( true );
sessionTime.setText( session_up_time==0?"":DisplayFormatters.formatETA( session_up_time ));
totalTime.setText( total_up_time==0?"":DisplayFormatters.formatETA( total_up_time ));
long t_ratio_raw = (1000* ul_bytes / (dl_bytes==0?1:dl_bytes) );
long s_ratio_raw = (1000* session_total_sent / (session_total_received==0?1:session_total_received) );
String t_ratio = "";
String s_ratio = "";
String partial = String.valueOf(t_ratio_raw % 1000);
while (partial.length() < 3) {
partial = "0" + partial;
}
t_ratio = (t_ratio_raw / 1000) + "." + partial;
partial = String.valueOf(s_ratio_raw % 1000);
while (partial.length() < 3) {
partial = "0" + partial;
}
s_ratio = (s_ratio_raw / 1000) + "." + partial;
total_ratio.setText( t_ratio );
session_ratio.setText( s_ratio );
}
AEProxySelector proxy_selector = AEProxySelectorFactory.getSelector();
Proxy proxy = proxy_selector.getActiveProxy();
socksMore.setEnabled( proxy != null );
if ( Constants.isOSX ){
socksMore.setForeground(proxy==null?Colors.light_grey:Colors.blue);
}
socksState.setText( proxy==null?MessageText.getString( "label.inactive" ): ((InetSocketAddress)proxy.address()).getHostName());
if ( proxy == null ){
socksCurrent.setText( "" );
socksFails.setText( "" );
}else{
long last_con = proxy_selector.getLastConnectionTime();
long last_fail = proxy_selector.getLastFailTime();
int total_cons = proxy_selector.getConnectionCount();
int total_fails = proxy_selector.getFailCount();
long now = SystemTime.getMonotonousTime();
long con_ago = now - last_con;
long fail_ago = now - last_fail;
String state_str;
if ( last_fail < 0 ){
state_str = "PeerManager.status.ok";
}else{
if ( fail_ago > 60*1000 ){
if ( con_ago < fail_ago ){
state_str = "PeerManager.status.ok";
}else{
state_str = "SpeedView.stats.unknown";
}
}else{
state_str = "ManagerItem.error";
}
}
socksCurrent.setText( MessageText.getString( state_str ) + ", con=" + total_cons );
long fail_ago_secs = fail_ago/1000;
if ( fail_ago_secs == 0 ){
fail_ago_secs = 1;
}
socksFails.setText( last_fail<0?"":(DisplayFormatters.formatETA( fail_ago_secs, false ) + " " + MessageText.getString( "label.ago" ) + ", tot=" + total_fails ));
}
}
private void
refreshCapacityPanel()
{
if ( speedManager == null ){
return;
}
asn.setText(speedManager.getASN());
estUpCap.setText(limit_to_text.getLimitText(speedManager.getEstimatedUploadCapacityBytesPerSec()));
estDownCap.setText(limit_to_text.getLimitText(speedManager.getEstimatedDownloadCapacityBytesPerSec()));
uploadBiaser.setText( DownloadManagerRateController.getString());
InetAddress current_ip = NetworkAdmin.getSingleton().getDefaultPublicAddress();
currentIP.setText(current_ip==null?"":current_ip.getHostAddress() );
}
private void
refreshConnectionPanel()
{
if ( global_manager == null ){
return;
}
int total_connections = 0;
int total_con_queued = 0;
int total_con_blocked = 0;
int total_con_unchoked = 0;
int total_data_queued = 0;
int total_in = 0;
List<DownloadManager> dms = global_manager.getDownloadManagers();
for ( DownloadManager dm: dms ){
PEPeerManager pm = dm.getPeerManager();
if ( pm != null ){
total_data_queued += pm.getBytesQueuedForUpload();
total_connections += pm.getNbPeers() + pm.getNbSeeds();
total_con_queued += pm.getNbPeersWithUploadQueued();
total_con_blocked += pm.getNbPeersWithUploadBlocked();
total_con_unchoked += pm.getNbPeersUnchoked();
total_in += pm.getNbRemoteTCPConnections() + pm.getNbRemoteUDPConnections() + pm.getNbRemoteUTPConnections();
}
}
connection_label.setText(
MessageText.getString(
"SpeedView.stats.con_details",
new String[]{
String.valueOf(total_connections) + "[" +MessageText.getString( "label.in").toLowerCase() + ":" + total_in + "]",
String.valueOf(total_con_unchoked), String.valueOf(total_con_queued), String.valueOf(total_con_blocked) }));
connection_graphic.addIntsValue( new int[]{ total_connections, total_con_unchoked, total_con_queued, total_con_blocked });
upload_label.setText(
MessageText.getString(
"SpeedView.stats.upload_details",
new String[]{ DisplayFormatters.formatByteCountToKiBEtc( total_data_queued )}));
upload_graphic.addIntValue( total_data_queued );
upload_graphic.refresh(false);
connection_graphic.refresh(false);
if ( con_folder.getSelectionIndex() == 1 ){
long now = SystemTime.getMonotonousTime();
if ( now - last_route_update >= 2*1000 ){
last_route_update = now;
NetworkAdmin na = NetworkAdmin.getSingleton();
Map<InetAddress,String> ip_to_name_map = new HashMap<InetAddress,String>();
Map<String,RouteInfo> name_to_route_map = new HashMap<String,RouteInfo>();
RouteInfo udp_info = null;
RouteInfo unknown_info = null;
List<PRUDPPacketHandler> udp_handlers = PRUDPPacketHandlerFactory.getHandlers();
InetAddress udp_bind_ip = null;
for ( PRUDPPacketHandler handler: udp_handlers ){
if ( handler.hasPrimordialHandler()){
udp_bind_ip = handler.getBindIP();
if ( udp_bind_ip != null ){
if( udp_bind_ip.isAnyLocalAddress()){
udp_bind_ip = null;
}
}
}
}
for ( DownloadManager dm: dms ){
PEPeerManager pm = dm.getPeerManager();
if ( pm != null ){
List<PEPeer> peers = pm.getPeers();
for ( PEPeer p: peers ){
NetworkConnection nc = PluginCoreUtils.unwrap( p.getPluginConnection());
boolean done = false;
if ( nc != null ){
Transport transport = nc.getTransport();
if ( transport != null ){
if ( transport.isTCP()){
TransportStartpoint start = transport.getTransportStartpoint();
if ( start != null ){
InetSocketAddress socket_address = start.getProtocolStartpoint().getAddress();
if ( socket_address != null ){
InetAddress address = socket_address.getAddress();
String name;
if ( address.isAnyLocalAddress()){
name = "* (TCP)";
}else{
name = ip_to_name_map.get( address );
}
if ( name == null ){
name = na.classifyRoute( address);
ip_to_name_map.put( address, name );
}
if ( transport.isSOCKS()){
name += " (SOCKS)";
}
RouteInfo info = name_to_route_map.get( name );
if ( info == null ){
info = new RouteInfo( name );
name_to_route_map.put( name, info );
route_last_seen.put( name, now );
}
info.update( p );
done = true;
}
}
}else{
if ( udp_bind_ip != null ){
RouteInfo info;
String name = ip_to_name_map.get( udp_bind_ip );
if ( name == null ){
name = na.classifyRoute( udp_bind_ip);
ip_to_name_map.put( udp_bind_ip, name );
info = name_to_route_map.get( name );
route_last_seen.put( name, now );
if ( info == null ){
info = new RouteInfo( name );
name_to_route_map.put( name, info );
}
}else{
info = name_to_route_map.get( name );
}
info.update( p );
done = true;
}else{
if ( udp_info == null ){
udp_info = new RouteInfo( "* (UDP)" );
name_to_route_map.put( udp_info.getName(), udp_info );
route_last_seen.put( udp_info.getName(), now );
}
udp_info.update( p );
done = true;
}
}
}
}
if ( !done ){
if ( unknown_info == null ){
unknown_info = new RouteInfo( "Pending" );
name_to_route_map.put( unknown_info.getName(), unknown_info );
route_last_seen.put( unknown_info.getName(), now );
}
unknown_info.update( p );
}
}
}
}
List<RouteInfo> rows = new ArrayList<RouteInfo>();
Iterator<Map.Entry<String,Long>> it = route_last_seen.entrySet().iterator();
while( it.hasNext()){
Map.Entry<String,Long> entry = it.next();
long when = entry.getValue();
if ( now - when > 60*1000 ){
it.remove();
}else if ( when != now ){
rows.add( new RouteInfo( entry.getKey()));
}
}
rows.addAll( name_to_route_map.values());
Collections.sort(
rows,
new Comparator<RouteInfo>()
{
public int
compare(
RouteInfo o1,
RouteInfo o2)
{
String n1 = o1.getName();
String n2 = o2.getName();
// wildcard and pending to the bottom
if ( n1.startsWith( "*" ) || n1.equals( "Pending" )){
n1 = "zzzz" + n1;
}
if ( n2.startsWith( "*" ) || n2.equals( "Pending" )){
n2 = "zzzz" + n2;
}
return( n1.compareTo(n2));
}
});
buildRouteComponent( rows.size());
for ( int i=0;i<rows.size();i++){
RouteInfo info = rows.get( i );
route_labels[i][0].setText( info.getName());
route_labels[i][1].setText( info.getIncomingString());
route_labels[i][2].setText( info.getOutgoingString());
}
buildRouteComponent( rows.size());
}
}
}
private static class
RouteInfo
{
private String name;
private RouteInfoRecord incoming = new RouteInfoRecord();
private RouteInfoRecord outgoing = new RouteInfoRecord();
private
RouteInfo(
String _name )
{
name = _name;
}
private String
getName()
{
return( name );
}
private String
getIncomingString()
{
return( incoming.getString());
}
private String
getOutgoingString()
{
return( outgoing.getString());
}
private void
update(
PEPeer peer )
{
RouteInfoRecord record;
if ( peer.isIncoming()){
record = incoming;
}else{
record = outgoing;
}
record.update( peer );
}
}
private static class
RouteInfoRecord
{
private int peer_count;
private int up_rate;
private int down_rate;
private void
update(
PEPeer peer )
{
peer_count++;
PEPeerStats stats = peer.getStats();
up_rate += stats.getDataSendRate() + stats.getProtocolSendRate();
down_rate += stats.getDataReceiveRate() + stats.getProtocolReceiveRate();
}
private String
getString()
{
if ( peer_count == 0 ){
return( "0" );
}
return( peer_count + ": up=" +
DisplayFormatters.formatByteCountToKiBEtcPerSec( up_rate ) + ", down=" +
DisplayFormatters.formatByteCountToKiBEtcPerSec( down_rate ));
}
}
private void refreshPingPanel() {
if (speedManager == null) {
return;
}
if(speedManager.isAvailable()){// && speedManager.isEnabled()) {
autoSpeedPanelLayout.topControl = autoSpeedInfoPanel;
autoSpeedPanel.layout();
pingGraph.refresh();
for (int i=0;i<plot_views.length;i++){
plot_views[i].refresh();
}
for (int i=0;i<zone_views.length;i++){
zone_views[i].refresh();
}
} else {
autoSpeedPanelLayout.topControl = autoSpeedDisabledPanel;
autoSpeedPanel.layout();
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.stats.PeriodicViewUpdate#periodicUpdate()
*/
public void periodicUpdate() {
if (speedManager == null) {
return;
}
if(speedManager.isAvailable()){// && speedManager.isEnabled()) {
SpeedManagerPingSource sources[] = speedManager.getPingSources();
if(sources.length > 0) {
int[] pings = new int[sources.length];
for(int i = 0 ; i < sources.length ; i++) {
SpeedManagerPingSource source = sources[i];
if ( source != null ){
int ping = source.getPingTime();
ping = Math.min( ping, MAX_DISPLAYED_PING_MILLIS );
pings[i] = ping;
}
}
pingGraph.addIntsValue(pings);
if (plot_views != null) {
for ( plotView view: plot_views ){
if ( view != null ){
view.update();
}
}
}
if (zone_views != null) {
for ( zoneView view: zone_views ){
if ( view != null ){
view.update();
}
}
}
}
}
}
protected String
getMapperTitle(
SpeedManagerPingMapper mapper )
{
if ( mapper.isActive()){
SpeedManagerLimitEstimate up_1 = mapper.getEstimatedUploadLimit(false);
SpeedManagerLimitEstimate up_2 = mapper.getEstimatedUploadLimit(true);
SpeedManagerLimitEstimate down_1 = mapper.getEstimatedDownloadLimit(false);
SpeedManagerLimitEstimate down_2 = mapper.getEstimatedDownloadLimit(true);
return( "ul=" + DisplayFormatters.formatByteCountToKiBEtc(up_1.getBytesPerSec()) + ":" + DisplayFormatters.formatByteCountToKiBEtc(up_2.getBytesPerSec())+
",dl=" + DisplayFormatters.formatByteCountToKiBEtc(down_1.getBytesPerSec()) + ":" + DisplayFormatters.formatByteCountToKiBEtc(down_2.getBytesPerSec()) +
",mr=" + DisplayFormatters.formatDecimal( mapper.getCurrentMetricRating(),2));
}
return( "" );
}
class
plotView
{
private SpeedManagerPingMapper mapper;
private Plot3D plotGraph;
protected
plotView(
SpeedManagerPingMapper _mapper,
Canvas _canvas,
String[] _labels,
ValueFormater[] _formatters )
{
mapper = _mapper;
plotGraph = new Plot3D( _labels, _formatters );
plotGraph.setMaxZ( MAX_DISPLAYED_PING_MILLIS );
plotGraph.initialize(_canvas);
}
protected void
update()
{
int[][] history = mapper.getHistory();
plotGraph.update(history);
plotGraph.setTitle( getMapperTitle( mapper ));
}
protected void
refresh()
{
plotGraph.refresh( false );
}
protected void
dispose()
{
plotGraph.dispose();
}
}
class
zoneView
implements ParameterListener
{
private SpeedManagerPingMapper mapper;
private SpeedManagerPingZone[] zones = new SpeedManagerPingZone[0];
private Canvas canvas;
private ValueFormater[] formatters;
private String[] labels;
private String title = "";
private int refresh_count;
private int graphicsUpdate;
private Point old_size;
protected Image buffer_image;
protected
zoneView(
SpeedManagerPingMapper _mapper,
Canvas _canvas,
String[] _labels,
ValueFormater[] _formatters )
{
mapper = _mapper;
canvas = _canvas;
labels = _labels;
formatters = _formatters;
COConfigurationManager.addAndFireParameterListener( "Graphics Update", this );
}
public void
parameterChanged(
String name )
{
graphicsUpdate = COConfigurationManager.getIntParameter( name );
}
protected void
update()
{
zones = mapper.getZones();
title = getMapperTitle( mapper );
}
private void
refresh()
{
if ( canvas.isDisposed()){
return;
}
Rectangle bounds = canvas.getClientArea();
if ( bounds.height < 30 || bounds.width < 100 || bounds.width > 2000 || bounds.height > 2000 ){
return;
}
boolean size_changed = (old_size == null || old_size.x != bounds.width || old_size.y != bounds.height);
old_size = new Point(bounds.width,bounds.height);
refresh_count++;
if ( refresh_count > graphicsUpdate ){
refresh_count = 0;
}
if ( refresh_count == 0 || size_changed ){
if ( buffer_image != null && ! buffer_image.isDisposed()){
buffer_image.dispose();
}
buffer_image = draw( bounds );
}
if ( buffer_image != null ){
GC gc = new GC( canvas );
gc.drawImage( buffer_image, bounds.x, bounds.y );
gc.dispose();
}
}
private Image
draw(
Rectangle bounds )
{
final int PAD_TOP = 10;
final int PAD_BOTTOM = 10;
final int PAD_RIGHT = 10;
final int PAD_LEFT = 10;
int usable_width = bounds.width - PAD_LEFT - PAD_RIGHT;
int usable_height = bounds.height - PAD_TOP - PAD_BOTTOM;
Image image = new Image( canvas.getDisplay(), bounds );
GC gc = new GC( image );
try {
gc.setAntialias( SWT.ON );
} catch (Exception e) {
// Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
}
int font_height = gc.getFontMetrics().getHeight();
int char_width = gc.getFontMetrics().getAverageCharWidth();
Color[] colours = plot_views[0].plotGraph.getColours();
int max_x = 0;
int max_y = 0;
if ( zones.length > 0 ){
int max_metric = 0;
for (int i=0;i<zones.length;i++){
SpeedManagerPingZone zone = zones[i];
int metric = zone.getMetric();
if ( metric > 0 ){
max_metric = Math.max( max_metric, metric );
max_x = Math.max( max_x, zone.getUploadEndBytesPerSec());
max_y = Math.max( max_y, zone.getDownloadEndBytesPerSec());
}
}
if ( max_x > 0 && max_y > 0 ){
double x_ratio = (double)usable_width/max_x;
double y_ratio = (double)usable_height/max_y;
List<Object[]> texts = new ArrayList<Object[]>();
for (int i=0;i<zones.length;i++){
SpeedManagerPingZone zone = zones[i];
int metric = zone.getMetric();
int x1 = zone.getUploadStartBytesPerSec();
int y1 = zone.getDownloadStartBytesPerSec();
int x2 = zone.getUploadEndBytesPerSec();
int y2 = zone.getDownloadEndBytesPerSec();
if ( metric > 0 ){
int colour_index = (int)((float)metric*colours.length/max_metric);
if ( colour_index >= colours.length ){
colour_index = colours.length-1;
}
gc.setBackground( colours[colour_index] );
int x = PAD_LEFT + (int)(x1*x_ratio);
int y = PAD_TOP + (int)(y1*y_ratio);
int width = (int)Math.ceil((x2-x1+1)*x_ratio);
int height = (int)Math.ceil((y2-y1+1)*y_ratio );
int y_draw = usable_height + PAD_TOP + PAD_TOP - y - height;
gc.fillRectangle( x, y_draw, width, height );
int text_metric = zone.getMetric();
String text = String.valueOf( metric );
int text_width = text.length()*char_width + 4;
if ( width >= text_width && height >= font_height ){
Rectangle text_rect =
new Rectangle(
x + ((width-text_width)/2),
y_draw + ((height-font_height)/2),
text_width, font_height );
// check for overlap with existing and delete older
Iterator<Object[]> it = texts.iterator();
while( it.hasNext()){
Object[] old = it.next();
Rectangle old_coords = (Rectangle)old[1];
if ( old_coords.intersects( text_rect )){
it.remove();
}
}
texts.add( new Object[]{ new Integer( text_metric ), text_rect });
}
}
}
// only do the last 100 texts as things get a little cluttered
int text_num = texts.size();
for (int i=(text_num>100?(text_num-100):0);i<text_num;i++){
Object[] entry = texts.get(i);
String str = String.valueOf(entry[0]);
Rectangle rect = (Rectangle)entry[1];
gc.drawText(str, rect.x, rect.y, SWT.DRAW_TRANSPARENT );
}
}
}
// x axis
int x_axis_left_x = PAD_LEFT;
int x_axis_left_y = usable_height + PAD_TOP;
int x_axis_right_x = PAD_LEFT + usable_width;
int x_axis_right_y = x_axis_left_y;
gc.drawLine( x_axis_left_x, x_axis_left_y, x_axis_right_x, x_axis_right_y );
gc.drawLine( usable_width, x_axis_right_y - 4, x_axis_right_x, x_axis_right_y );
gc.drawLine( usable_width, x_axis_right_y + 4, x_axis_right_x, x_axis_right_y );
for (int i=1;i<10;i++){
int x = x_axis_left_x + ( x_axis_right_x - x_axis_left_x )*i/10;
gc.drawLine( x, x_axis_left_y, x, x_axis_left_y+4 );
}
SpeedManagerLimitEstimate le = mapper.getEstimatedUploadLimit( false );
if ( le != null ){
gc.setForeground(Colors.grey );
int[][] segs = le.getSegments();
if ( segs.length > 0 ){
int max_metric = 0;
int max_pos = 0;
for (int i=0;i<segs.length;i++){
int[] seg = segs[i];
max_metric = Math.max( max_metric, seg[0] );
max_pos = Math.max( max_pos, seg[2] );
}
double metric_ratio = max_metric==0?1:((float)50/max_metric);
double pos_ratio = max_pos==0?1:((float)usable_width/max_pos);
int prev_x = 1;
int prev_y = 1;
for (int i=0;i<segs.length;i++){
int[] seg = segs[i];
int next_x = (int)((seg[1] + (seg[2]-seg[1])/2)*pos_ratio) + 1;
int next_y = (int)((seg[0])*metric_ratio) + 1;
gc.drawLine(
x_axis_left_x + prev_x,
x_axis_left_y - prev_y,
x_axis_left_x + next_x,
x_axis_left_y - next_y );
prev_x = next_x;
prev_y = next_y;
}
}
gc.setForeground( Colors.black );
}
SpeedManagerLimitEstimate[] bad_up = mapper.getBadUploadHistory();
if ( bad_up.length > 0 ){
gc.setLineWidth( 3 );
gc.setForeground( Colors.red );
for (int i=0;i<bad_up.length;i++){
int speed = bad_up[i].getBytesPerSec();
int x = max_x == 0?0:(speed * usable_width / max_x);
gc.drawLine(
x_axis_left_x + x,
x_axis_left_y - 0,
x_axis_left_x + x,
x_axis_left_y - 10 );
}
gc.setForeground( Colors.black );
gc.setLineWidth( 1 );
}
String x_text = labels[0] + " - " + formatters[0].format( max_x+1 );
gc.drawText( x_text,
x_axis_right_x - 20 - x_text.length()*char_width,
x_axis_right_y - font_height - 2,
SWT.DRAW_TRANSPARENT );
// y axis
int y_axis_bottom_x = PAD_LEFT;
int y_axis_bottom_y = usable_height + PAD_TOP;
int y_axis_top_x = PAD_LEFT;
int y_axis_top_y = PAD_TOP;
gc.drawLine( y_axis_bottom_x, y_axis_bottom_y, y_axis_top_x, y_axis_top_y );
gc.drawLine( y_axis_top_x-4, y_axis_top_y+PAD_TOP, y_axis_top_x, y_axis_top_y );
gc.drawLine( y_axis_top_x+4, y_axis_top_y+PAD_TOP, y_axis_top_x, y_axis_top_y );
for (int i=1;i<10;i++){
int y = y_axis_bottom_y + ( y_axis_top_y - y_axis_bottom_y )*i/10;
gc.drawLine( y_axis_bottom_x, y, y_axis_bottom_x-4, y );
}
le = mapper.getEstimatedDownloadLimit( false );
if ( le != null ){
gc.setForeground(Colors.grey );
int[][] segs = le.getSegments();
if ( segs.length > 0 ){
int max_metric = 0;
int max_pos = 0;
for (int i=0;i<segs.length;i++){
int[] seg = segs[i];
max_metric = Math.max( max_metric, seg[0] );
max_pos = Math.max( max_pos, seg[2] );
}
double metric_ratio = max_metric==0?1:((float)50/max_metric);
double pos_ratio = max_pos==0?1:((float)usable_height/max_pos);
int prev_x = 1;
int prev_y = 1;
for (int i=0;i<segs.length;i++){
int[] seg = segs[i];
int next_x = (int)((seg[0])*metric_ratio) + 1;
int next_y = (int)((seg[1] + (seg[2]-seg[1])/2)*pos_ratio) + 1;
gc.drawLine(
y_axis_bottom_x + prev_x,
y_axis_bottom_y - prev_y,
y_axis_bottom_x + next_x,
y_axis_bottom_y - next_y );
prev_x = next_x;
prev_y = next_y;
}
}
gc.setForeground( Colors.black );
}
SpeedManagerLimitEstimate[] bad_down = mapper.getBadDownloadHistory();
if ( bad_down.length > 0 ){
gc.setForeground( Colors.red );
gc.setLineWidth( 3 );
for (int i=0;i<bad_down.length;i++){
int speed = bad_down[i].getBytesPerSec();
int y = max_y==0?0:( speed * usable_height / max_y );
gc.drawLine(
y_axis_bottom_x + 0,
y_axis_bottom_y - y,
y_axis_bottom_x + 10,
y_axis_bottom_y - y );
}
gc.setForeground( Colors.black );
gc.setLineWidth( 1 );
}
String y_text = labels[1] + " - " + formatters[1].format( max_y+1 );
gc.drawText( y_text, y_axis_top_x+4, y_axis_top_y + 2, SWT.DRAW_TRANSPARENT );
gc.drawText( title, ( bounds.width - title.length()*char_width )/2, 1, SWT.DRAW_TRANSPARENT );
gc.dispose();
return( image );
}
protected void
dispose()
{
if ( buffer_image != null && ! buffer_image.isDisposed()){
buffer_image.dispose();
}
COConfigurationManager.removeParameterListener("Graphics Update",this);
}
}
public static class
limitToTextHelper
{
String msg_text_unknown;
String msg_text_estimate;
String msg_text_choke_estimate;
String msg_text_measured_min;
String msg_text_measured;
String msg_text_manual;
String msg_unlimited;
String[] setable_types;
public
limitToTextHelper()
{
msg_text_unknown = MessageText.getString( "SpeedView.stats.unknown" );
msg_text_estimate = MessageText.getString( "SpeedView.stats.estimate" );
msg_text_choke_estimate = MessageText.getString( "SpeedView.stats.estimatechoke" );
msg_text_measured = MessageText.getString( "SpeedView.stats.measured" );
msg_text_measured_min = MessageText.getString( "SpeedView.stats.measuredmin" );
msg_text_manual = MessageText.getString( "SpeedView.stats.manual" );
msg_unlimited = MessageText.getString( "ConfigView.unlimited" );
setable_types = new String[]{ "", msg_text_estimate, msg_text_measured, msg_text_manual };
}
public String[]
getSettableTypes()
{
return( setable_types );
}
public String
getSettableType(
SpeedManagerLimitEstimate limit )
{
float type = limit.getEstimateType();
String text;
if ( type == SpeedManagerLimitEstimate.TYPE_UNKNOWN){
text = "";
}else if ( type == SpeedManagerLimitEstimate.TYPE_MANUAL){
text = msg_text_manual;
}else if ( type == SpeedManagerLimitEstimate.TYPE_MEASURED){
text = msg_text_measured;
}else if ( type == SpeedManagerLimitEstimate.TYPE_MEASURED_MIN){
text = msg_text_measured;
}else if ( type == SpeedManagerLimitEstimate.TYPE_CHOKE_ESTIMATED){
text = msg_text_estimate;
}else{
text = msg_text_estimate;
}
return( text ); }
public String
typeToText(
float type )
{
String text;
if ( type == SpeedManagerLimitEstimate.TYPE_UNKNOWN){
text = msg_text_unknown;
}else if ( type == SpeedManagerLimitEstimate.TYPE_MANUAL){
text = msg_text_manual;
}else if ( type == SpeedManagerLimitEstimate.TYPE_MEASURED){
text = msg_text_measured;
}else if ( type == SpeedManagerLimitEstimate.TYPE_MEASURED_MIN){
text = msg_text_measured_min;
}else if ( type == SpeedManagerLimitEstimate.TYPE_CHOKE_ESTIMATED){
text = msg_text_choke_estimate;
}else{
text = msg_text_estimate;
}
return( text );
}
public float
textToType(
String text )
{
if ( text.equals( msg_text_estimate )){
return( SpeedManagerLimitEstimate.TYPE_ESTIMATED);
}else if ( text.equals( msg_text_choke_estimate )){
return( SpeedManagerLimitEstimate.TYPE_CHOKE_ESTIMATED);
}else if ( text.equals( msg_text_measured )){
return( SpeedManagerLimitEstimate.TYPE_MEASURED);
}else if ( text.equals( msg_text_manual )){
return( SpeedManagerLimitEstimate.TYPE_MANUAL);
}else{
return( SpeedManagerLimitEstimate.TYPE_UNKNOWN);
}
}
public String
getLimitText(
SpeedManagerLimitEstimate limit )
{
float type = limit.getEstimateType();
String text = typeToText( type );
int l = limit.getBytesPerSec();
if ( l == 0 ){
return( msg_unlimited + " (" + text + ")");
}else{
return( DisplayFormatters.formatByteCountToKiBEtcPerSec( l ) + " (" + text + ")");
}
}
public String
getUnlimited()
{
return( msg_unlimited );
}
}
public boolean eventOccurred(UISWTViewEvent event) {
switch (event.getType()) {
case UISWTViewEvent.TYPE_CREATE:
swtView = (UISWTView)event.getData();
swtView.setTitle(MessageText.getString(MSGID_PREFIX + ".title.full"));
break;
case UISWTViewEvent.TYPE_DESTROY:
delete();
break;
case UISWTViewEvent.TYPE_INITIALIZE:
initialize((Composite)event.getData());
break;
case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
Messages.updateLanguageForControl(getComposite());
break;
case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
break;
case UISWTViewEvent.TYPE_FOCUSGAINED:
break;
case UISWTViewEvent.TYPE_REFRESH:
refresh();
break;
case StatsView.EVENT_PERIODIC_UPDATE:
periodicUpdate();
break;
}
return true;
}
}