/* * 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.text.DecimalFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; 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.Group; import org.eclipse.swt.widgets.Label; 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.PEPeerManager; 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.DisplayFormatters; import org.gudy.azureus2.ui.swt.Messages; 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.views.AbstractIView; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.AzureusCoreFactory; 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; /** * */ public class TransferStatsView extends AbstractIView { 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 Composite connectionPanel; private Label upload_label, connection_label; private SpeedGraphic upload_graphic; private SpeedGraphic connection_graphic; private Composite generalPanel; private BufferedLabel nowUp, nowDown, sessionDown, sessionUp, session_ratio, sessionTime, totalDown, totalUp, total_ratio, totalTime; 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; public TransferStatsView() { AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { global_manager = core.getGlobalManager(); stats = global_manager.getStats(); speedManager = core.getSpeedManager(); totalStats = StatsFactory.getStats(); } }); } public 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.BORDER); GridData generalPanelData = new GridData(GridData.FILL_HORIZONTAL); generalPanel.setLayoutData(generalPanelData); GridLayout panelLayout = new GridLayout(); panelLayout.numColumns = 5; panelLayout.makeColumnsEqualWidth = true; generalPanel.setLayout(panelLayout); GridData gridData; Label lbl = new Label(generalPanel,SWT.NULL); lbl = new Label(generalPanel,SWT.NULL); Messages.setLanguageText(lbl,"SpeedView.stats.downloaded"); lbl = new Label(generalPanel,SWT.NULL); Messages.setLanguageText(lbl,"SpeedView.stats.uploaded"); lbl = new Label(generalPanel,SWT.NULL); Messages.setLanguageText(lbl,"SpeedView.stats.ratio"); lbl = new Label(generalPanel,SWT.NULL); Messages.setLanguageText(lbl,"SpeedView.stats.uptime"); lbl = new Label(generalPanel,SWT.NULL); lbl = new Label(generalPanel,SWT.NULL); lbl = new Label(generalPanel,SWT.NULL); lbl = new Label(generalPanel,SWT.NULL); lbl = new Label(generalPanel,SWT.NULL); /////// NOW ///////// lbl = new Label(generalPanel,SWT.NULL); Messages.setLanguageText(lbl,"SpeedView.stats.now"); nowDown = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); nowDown.setLayoutData(gridData); nowUp = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); nowUp.setLayoutData(gridData); lbl = new Label(generalPanel,SWT.NULL); lbl = new Label(generalPanel,SWT.NULL); //////// SESSION //////// lbl = new Label(generalPanel,SWT.NULL); Messages.setLanguageText(lbl,"SpeedView.stats.session"); sessionDown = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); sessionDown.setLayoutData(gridData); sessionUp = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); sessionUp.setLayoutData(gridData); session_ratio = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); session_ratio.setLayoutData(gridData); sessionTime = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); sessionTime.setLayoutData(gridData); ///////// TOTAL /////////// lbl = new Label(generalPanel,SWT.NULL); Messages.setLanguageText(lbl,"SpeedView.stats.total"); totalDown = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); totalDown.setLayoutData(gridData); totalUp = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); totalUp.setLayoutData(gridData); total_ratio = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); total_ratio.setLayoutData(gridData); totalTime = new BufferedLabel(generalPanel,SWT.NULL); gridData = new GridData(GridData.FILL_HORIZONTAL); totalTime.setLayoutData(gridData); } 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,"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); label = new Label(blahPanel,SWT.NONE); 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; 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 Label( conn_area, SWT.NULL ); 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 Label( upload_area, SWT.NULL ); gridData = new GridData(GridData.FILL_HORIZONTAL); upload_label.setLayoutData(gridData); // connections Canvas connection_canvas = new Canvas(connectionPanel,SWT.NO_BACKGROUND); 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 ); // upload queued Canvas upload_canvas = new Canvas(connectionPanel,SWT.NO_BACKGROUND); gridData = new GridData(GridData.FILL_BOTH); 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 createAutoSpeedPanel() { autoSpeedPanel = new Group(mainPanel,SWT.NONE); GridData generalPanelData = new GridData(GridData.FILL_BOTH); autoSpeedPanel.setLayoutData(generalPanelData); Messages.setLanguageText(autoSpeedPanel,"SpeedView.stats.autospeed"); 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 = PingGraphic.getInstance(); 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 ); } public 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(); } } } public String getFullTitle() { return MessageText.getString("SpeedView.title.full"); //$NON-NLS-1$ } public Composite getComposite() { return mainPanel; } public 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) { totalDown.setText(DisplayFormatters.formatByteCountToKiBEtc( totalStats.getDownloadedBytes() )); totalUp.setText(DisplayFormatters.formatByteCountToKiBEtc( totalStats.getUploadedBytes() )); sessionTime.setText( DisplayFormatters.formatETA( totalStats.getSessionUpTime() ) ); totalTime.setText( DisplayFormatters.formatETA( totalStats.getTotalUpTime() ) ); long dl_bytes = totalStats.getDownloadedBytes(); long t_ratio_raw = (1000* totalStats.getUploadedBytes() / (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 ); } } 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()); } 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; 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(); } } Messages.setLanguageText( connection_label, "SpeedView.stats.con_details", new String[]{ String.valueOf(total_connections), 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 }); Messages.setLanguageText( upload_label, "SpeedView.stats.upload_details", new String[]{ DisplayFormatters.formatByteCountToKiBEtc( total_data_queued )}); upload_graphic.addIntValue( total_data_queued ); upload_graphic.refresh(); connection_graphic.refresh(); } 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(); } } 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++) { pings[i] = sources[i].getPingTime(); } pingGraph.addIntsValue(pings); for (int i=0;i<plot_views.length;i++){ plot_views[i].update(); } for (int i=0;i<zone_views.length;i++){ zone_views[i].update(); } } } } public String getData() { return "TransferStatsView.title.full"; } 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.initialize(_canvas); } protected void update() { int[][] history = mapper.getHistory(); plotGraph.update(history); plotGraph.setTitle( getMapperTitle( mapper )); } protected void refresh() { plotGraph.refresh(); } 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 texts = new ArrayList(); 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 it = texts.iterator(); while( it.hasNext()){ Object[] old = (Object[])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 = (Object[])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 ); } } }