Package org.gudy.azureus2.ui.swt.mainwindow

Source Code of org.gudy.azureus2.ui.swt.mainwindow.MainStatusBar$ProgressListener

/*
* Created on Mar 20, 2006 6:40:14 PM
* Copyright (C) 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.mainwindow;

import java.text.NumberFormat;
import java.util.ArrayList;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator;
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.ipfilter.IpFilter;
import org.gudy.azureus2.core3.logging.LogAlert;
import org.gudy.azureus2.core3.stats.transfer.OverallStats;
import org.gudy.azureus2.core3.stats.transfer.StatsFactory;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.PluginManager;
import org.gudy.azureus2.plugins.network.ConnectionManager;
import org.gudy.azureus2.plugins.ui.config.ConfigSection;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.ui.swt.*;
import org.gudy.azureus2.ui.swt.Alerts.AlertHistoryListener;
import org.gudy.azureus2.ui.swt.progress.*;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
import org.gudy.azureus2.ui.swt.update.UpdateWindow;

import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.dht.DHT;
import com.aelitis.azureus.core.networkmanager.NetworkManager;
import com.aelitis.azureus.plugins.dht.DHTPlugin;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.UIStatusTextClickListener;
import com.aelitis.azureus.ui.common.updater.UIUpdatable;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;

/**
* Moved from MainWindow and GUIUpdater
*/
public class MainStatusBar
  implements UIUpdatable
{
  /**
   * Warning status icon identifier
   */
  private static final String STATUS_ICON_WARN = "sb_warning";
 
  private static final String ID = "MainStatusBar";

  private AEMonitor this_mon = new AEMonitor(ID);

  private UpdateWindow updateWindow;

  private Composite statusBar;

  private CLabel statusText;

  private String statusTextKey = "";

  private String statusImageKey = null;

  private Image statusImage = null;

  private AZProgressBar progressBar;

  private CLabelPadding ipBlocked;

  private CLabelPadding srStatus;

  private CLabelPadding natStatus;

  private CLabelPadding dhtStatus;

  private CLabelPadding statusDown;

  private CLabelPadding statusUp;

  private Composite plugin_label_composite;
 
  private ArrayList<Runnable> listRunAfterInit = new ArrayList<Runnable>();

  private Display display;

  // For Refresh..
  private long last_sr_ratio = -1;

  private int last_sr_status = -1;

  private int lastNATstatus = -1;

  private String lastNATimageID = null;

  private int lastDHTstatus = -1;

  private long lastDHTcount = -1;

  private NumberFormat numberFormat;

  private OverallStats overall_stats;

  private ConnectionManager connection_manager;

  private DHTPlugin dhtPlugin;

  private UIFunctions uiFunctions;

  private UIStatusTextClickListener clickListener;

  //   final int borderFlag = (Constants.isOSX) ? SWT.SHADOW_NONE : SWT.SHADOW_IN;
  private static final int borderFlag = SWT.SHADOW_NONE;

  /**
   * Just a flag to differentiate az3 from other versions; default status bar text is handled differently between versions.
   * Specifically speaking the Vuze UI status text is just empty whereas the Classic UI status text has an icon
   * and the application version number.
   */
  private boolean isAZ3 = false;

  /**
   * Just a reference to the static <code>ProgressReportingManager</code> to make the code look cleaner instead of
   * using <code>ProgressReportingManager.getInstance().xxx()</code> everywhere.
   */
  private ProgressReportingManager PRManager = ProgressReportingManager.getInstance();

  /**
   * A <code>GridData</code> for the progress bar; used to dynamically provide .widthHint to the layout manager
   */
  private GridData progressGridData = new GridData(SWT.RIGHT, SWT.CENTER,
      false, false);

  /**
   * A clickable image label that brings up the Progress viewer
   */
  private CLabelPadding progressViewerImageLabel;

  private String lastProgressImageID = null;

  private boolean updateProgressBarDisplayQueued = false;

  protected IProgressReport latestReport = null;

  protected AEMonitor latestReport_mon = new AEMonitor("latestReport");

  private String lastSRimageID = null;

  private int last_dl_limit;

  private long last_rec_data = - 1;

  private long last_rec_prot;

  private long[] max_rec = { 0 };
  private long[] max_sent = { 0 };

  private Image imgRec;
  private Image imgSent;

  private Image  warningIcon;
  private Image  infoIcon;
 
  private CLabelPadding statusWarnings;

  /**
   *
   */
  public MainStatusBar() {
    numberFormat = NumberFormat.getInstance();
    // Proably need to wait for core to be running to make sure dht plugin is fully avail
    AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
      public void azureusCoreRunning(AzureusCore core) {
        PluginManager pm = core.getPluginManager();
        connection_manager = PluginInitializer.getDefaultInterface().getConnectionManager();
        PluginInterface dht_pi = pm.getPluginInterfaceByClass(DHTPlugin.class);
        if (dht_pi != null) {
          dhtPlugin = (DHTPlugin) dht_pi.getPlugin();
        }
      }
    });
  }

  /**
   *
   * @return composite holding the statusbar
   */
  public Composite initStatusBar(final Composite parent) {
    this.display = parent.getDisplay();
    this.uiFunctions = UIFunctionsManager.getUIFunctions();
    ImageLoader imageLoader = ImageLoader.getInstance();

    FormData formData;

    Color fgColor = parent.getForeground();

    statusBar = new Composite(parent, SWT.NONE);
    statusBar.setForeground(fgColor);
    isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui"));
   
    statusBar.getShell().addListener(SWT.Deiconify, new Listener() {
      public void handleEvent(Event event) {
        Utils.execSWTThreadLater(0, new AERunnable() {
          public void runSupport() {
            if (!statusBar.isDisposed()) {
              statusBar.layout();
            }
          }
        });
      }
    });
   
    GridLayout layout_status = new GridLayout();
    layout_status.numColumns = 20;
    layout_status.horizontalSpacing = 0;
    layout_status.verticalSpacing = 0;
    layout_status.marginHeight = 0;
    if (Constants.isOSX) {
      // OSX has a resize widget on the bottom right.  It's about 15px wide.
      try {
        layout_status.marginRight = 15;
      } catch (NoSuchFieldError e) {
        // Pre SWT 3.1
        layout_status.marginWidth = 15;
      }
    } else {
      layout_status.marginWidth = 0;
    }
    statusBar.setLayout(layout_status);

    //Either the Status Text
    statusText = new CLabel(statusBar, borderFlag);
    statusText.setForeground(fgColor);
    statusText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL
        | GridData.VERTICAL_ALIGN_FILL));

    addStatusBarMenu(statusText);

    GC gc = new GC(statusText);
    // add 6, because CLabel forces a 3 pixel indent
    int height = Math.max(16, gc.getFontMetrics().getHeight()) + 6;
    gc.dispose();

    formData = new FormData();
    formData.height = height;
    formData.bottom = new FormAttachment(100, 0); // 2 params for Pre SWT 3.0
    formData.left = new FormAttachment(0, 0); // 2 params for Pre SWT 3.0
    formData.right = new FormAttachment(100, 0); // 2 params for Pre SWT 3.0
    statusBar.setLayoutData(formData);

    Listener listener = new Listener() {
      public void handleEvent(Event e) {
        if (clickListener == null) {
          if (updateWindow != null) {
            updateWindow.show();
          }
        } else {
          clickListener.UIStatusTextClicked();
        }
      }
    };

    statusText.addListener(SWT.MouseUp, listener);
    statusText.addListener(SWT.MouseDoubleClick, listener);

    // final int progressFlag = (Constants.isOSX) ? SWT.INDETERMINATE  : SWT.HORIZONTAL;
    // KN: Don't know why OSX is treated differently but this check was already here from the previous code
    if (true == Constants.isOSX) {
      progressBar = new AZProgressBar(statusBar, true);
    } else {
      progressBar = new AZProgressBar(statusBar, false);
    }

    progressBar.setVisible(false);
    progressGridData = new GridData(SWT.CENTER, SWT.CENTER, false, false);
    progressGridData.widthHint = 5;
    progressBar.setLayoutData(progressGridData);

    if ( isAZ3 ){
   
      try{
        addFeedBack();
      }catch( Throwable e ){
       
        Debug.printStackTrace(e);
      }
    }
   
    /*
     * Progress reporting window image label
     */

    progressViewerImageLabel = new CLabelPadding(statusBar, SWT.NONE);
    // image set below after adding listener
    progressViewerImageLabel.setToolTipText(MessageText.getString("Progress.reporting.statusbar.button.tooltip"));
    progressViewerImageLabel.addMouseListener(new MouseAdapter() {
      public void mouseDown(MouseEvent e) {
        /*
         * Opens the progress viewer if any of the reporters in the array is NOT already opened
         * KN: TODO -- This is only a partial solution to minimize the occurrence of the main progress window
         * opening more than once.  The one remaining case where multiple windows will still open is
         * when you have one opened already... then run another process such as a torrent file download...
         * at this point this new process is not in the already opened window so the check would
         * allow the second window to open.
         */
        IProgressReporter[] reporters = PRManager.getReportersArray(false);
        if (reporters.length == 0) {
          /*
           * If there's nothing to see then open the window; the default widow will say there's nothing to see
           * KN: calling isShowingEmpty return true is there is already a window opened showing the empty panel
           */
          if (false == ProgressReporterWindow.isShowingEmpty()) {
            ProgressReporterWindow.open(reporters,
                ProgressReporterWindow.SHOW_TOOLBAR);
          }
        } else {

          for (int i = 0; i < reporters.length; i++) {
            if (false == ProgressReporterWindow.isOpened(reporters[i])) {
              ProgressReporterWindow.open(reporters,
                  ProgressReporterWindow.SHOW_TOOLBAR);
              break;
            }
          }
        }
      }
    });
    progressViewerImageLabel.addDisposeListener(new DisposeListener() {
      public void widgetDisposed(DisposeEvent e) {
        ImageLoader imageLoader = ImageLoader.getInstance();
        imageLoader.releaseImage("progress_error");
        imageLoader.releaseImage("progress_info");
        imageLoader.releaseImage("progress_viewer");
      }
    });

    this.plugin_label_composite = new Composite(statusBar, SWT.NONE);
    this.plugin_label_composite.setForeground(fgColor);
    GridLayout gridLayout = new GridLayout();
    gridLayout.horizontalSpacing = 0;
    gridLayout.verticalSpacing = 0;
    gridLayout.marginHeight = 0;
    gridLayout.marginBottom = 0;
    gridLayout.marginTop = 0;
    gridLayout.marginLeft = 0;
    gridLayout.marginRight = 0;
    gridLayout.numColumns = 20; // Something nice and big. :)

    GridData gridData = new GridData(GridData.FILL_VERTICAL);
    gridData.heightHint = height;
    gridData.minimumHeight = height;
    plugin_label_composite.setLayout(gridLayout);
    plugin_label_composite.setLayoutData(gridData);

    srStatus = new CLabelPadding(statusBar, borderFlag);
    srStatus.setText(MessageText.getString("SpeedView.stats.ratio"));

    COConfigurationManager.addAndFireParameterListener("Status Area Show SR",
        new ParameterListener() {
          public void parameterChanged(String parameterName) {
            srStatus.setVisible(COConfigurationManager.getBooleanParameter(parameterName));
            statusBar.layout();
          }
        });

    natStatus = new CLabelPadding(statusBar, borderFlag);
    natStatus.setText("");

    COConfigurationManager.addAndFireParameterListener("Status Area Show NAT",
        new ParameterListener() {
          public void parameterChanged(String parameterName) {
            natStatus.setVisible(COConfigurationManager.getBooleanParameter(parameterName));
            statusBar.layout();
          }
        });

    dhtStatus = new CLabelPadding(statusBar, borderFlag);
    dhtStatus.setText("");
    dhtStatus.setToolTipText(MessageText.getString("MainWindow.dht.status.tooltip"));

    COConfigurationManager.addAndFireParameterListener("Status Area Show DDB",
        new ParameterListener() {
          public void parameterChanged(String parameterName) {
            dhtStatus.setVisible(COConfigurationManager.getBooleanParameter(parameterName));
            statusBar.layout();
          }
        });
    ipBlocked = new CLabelPadding(statusBar, borderFlag);
    ipBlocked.setText("{} IPs:"); //$NON-NLS-1$
    Messages.setLanguageText(ipBlocked, "MainWindow.IPs.tooltip");
    ipBlocked.addListener(SWT.MouseDoubleClick, new ListenerNeedingCoreRunning() {
      public void handleEvent(AzureusCore core, Event event) {
        BlockedIpsWindow.showBlockedIps(core, parent.getShell());
      }
    });

    COConfigurationManager.addAndFireParameterListener("Status Area Show IPF",
        new ParameterListener() {
          public void parameterChanged(String parameterName) {
            ipBlocked.setVisible(COConfigurationManager.getBooleanParameter(parameterName));
            statusBar.layout();
          }
        });

    statusDown = new CLabelPadding(statusBar, borderFlag);
    statusDown.setImage(imageLoader.getImage("down"));
    //statusDown.setText(/*MessageText.getString("ConfigView.download.abbreviated") +*/"n/a");
    Messages.setLanguageText(statusDown,
        "MainWindow.status.updowndetails.tooltip");

    Listener lStats = new Listener() {
      public void handleEvent(Event e) {
        uiFunctions.openView(UIFunctions.VIEW_STATS, null);
      }
    };

    statusUp = new CLabelPadding(statusBar, borderFlag);
    statusUp.setImage(imageLoader.getImage("up"));
    //statusUp.setText(/*MessageText.getString("ConfigView.upload.abbreviated") +*/"n/a");
    Messages.setLanguageText(statusUp,
        "MainWindow.status.updowndetails.tooltip");

    statusDown.addListener(SWT.MouseDoubleClick, lStats);
    statusUp.addListener(SWT.MouseDoubleClick, lStats);

    Listener lDHT = new Listener() {
      public void handleEvent(Event e) {
        uiFunctions.openView(UIFunctions.VIEW_STATS, "dht");
      }
    };

    dhtStatus.addListener(SWT.MouseDoubleClick, lDHT);

    Listener lSR = new Listener() {
      public void handleEvent(Event e) {

        uiFunctions.openView(UIFunctions.VIEW_STATS, "transfers");

        OverallStats stats = StatsFactory.getStats();
       
        if (stats == null) {
          return;
        }

        long ratio = (1000 * stats.getUploadedBytes() / (stats.getDownloadedBytes() + 1));

        if (ratio < 900) {

          Utils.launch(Constants.AZUREUS_WIKI + "Share_Ratio");
        }
      }
    };

    srStatus.addListener(SWT.MouseDoubleClick, lSR);

    Listener lNAT = new ListenerNeedingCoreRunning() {
      public void handleEvent(AzureusCore core, Event e) {
        uiFunctions.openView(UIFunctions.VIEW_CONFIG,
            ConfigSection.SECTION_CONNECTION);

        if (PluginInitializer.getDefaultInterface().getConnectionManager().getNATStatus() != ConnectionManager.NAT_OK) {
          Utils.launch(Constants.AZUREUS_WIKI + "NAT_problem");
        }
      }
    };

    natStatus.addListener(SWT.MouseDoubleClick, lNAT);

    boolean bSpeedMenu = COConfigurationManager.getBooleanParameter("GUI_SWT_bOldSpeedMenu");

    if (bSpeedMenu) {
      // Status Bar Menu construction
      final Menu menuUpSpeed = new Menu(statusBar.getShell(), SWT.POP_UP);
      menuUpSpeed.addListener(SWT.Show, new Listener() {
        public void handleEvent(Event e) {
          if (!AzureusCoreFactory.isCoreRunning()) {
            return;
          }
          AzureusCore core = AzureusCoreFactory.getSingleton();
          GlobalManager globalManager = core.getGlobalManager();
         
          SelectableSpeedMenu.generateMenuItems(menuUpSpeed, core,
              globalManager, true);
        }
      });
      statusUp.setMenu(menuUpSpeed);
    } else {

      statusUp.addMouseListener(new MouseAdapter() {
        public void mouseDown(MouseEvent e) {
          if (!(e.button == 3 || (e.button == 1 && e.stateMask == SWT.CONTROL))) {
            return;
          }
          Event event = new Event();
          event.type = SWT.MouseUp;
          event.widget = e.widget;
          event.stateMask = e.stateMask;
          event.button = e.button;
          e.widget.getDisplay().post(event);

          CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
            public void azureusCoreRunning(AzureusCore core) {
              SelectableSpeedMenu.invokeSlider(core, true);
            }
          });
        }
      });
    }

    if (bSpeedMenu) {
      final Menu menuDownSpeed = new Menu(statusBar.getShell(), SWT.POP_UP);
      menuDownSpeed.addListener(SWT.Show, new Listener() {
        public void handleEvent(Event e) {
          if (!AzureusCoreFactory.isCoreRunning()) {
            return;
          }
          AzureusCore core = AzureusCoreFactory.getSingleton();
          GlobalManager globalManager = core.getGlobalManager();

          SelectableSpeedMenu.generateMenuItems(menuDownSpeed, core,
              globalManager, false);
        }
      });
      statusDown.setMenu(menuDownSpeed);
    } else {
      statusDown.addMouseListener(new MouseAdapter() {
        public void mouseDown(MouseEvent e) {
          if (!(e.button == 3 || (e.button == 1 && e.stateMask == SWT.CONTROL))) {
            return;
          }
          Event event = new Event();
          event.type = SWT.MouseUp;
          event.widget = e.widget;
          event.stateMask = e.stateMask;
          event.button = e.button;
          e.widget.getDisplay().post(event);

          CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
            public void azureusCoreRunning(AzureusCore core) {
              SelectableSpeedMenu.invokeSlider(core, false);
            }
          });
        }
      });
    }

    statusWarnings = new CLabelPadding(statusBar, borderFlag);
    warningIcon = imageLoader.getImage("image.sidebar.vitality.alert");
    infoIcon   = imageLoader.getImage("image.sidebar.vitality.info");
    updateStatusWarnings();
    Messages.setLanguageText(statusWarnings,
        "MainWindow.status.warning.tooltip");
    Alerts.addMessageHistoryListener(new AlertHistoryListener() {
      public void alertHistoryAdded(LogAlert params) {
        updateStatusWarnings();
      }
      public void alertHistoryRemoved(LogAlert alert) {
        updateStatusWarnings();
      }
    });
    statusWarnings.addMouseListener(new MouseListener() {
      public void mouseUp(MouseEvent e) {
        if (SystemWarningWindow.numWarningWindowsOpen > 0) {
          return;
        }
        ArrayList<LogAlert> alerts = Alerts.getUnviewedLogAlerts();
        if (alerts.size() == 0) {
          return;
        }

        Shell shell = statusWarnings.getShell();
        Rectangle bounds = statusWarnings.getClientArea();
        Point ptBottomRight = statusWarnings.toDisplay(bounds.x + bounds.width, bounds.y);
        new SystemWarningWindow(alerts.get(0), ptBottomRight, shell, 0);
      }
     
      public void mouseDown(MouseEvent e) {
      }
     
      public void mouseDoubleClick(MouseEvent e) {
      }
    });
   
    COConfigurationManager.addAndFireParameterListener("status.rategraphs",
        new ParameterListener() {
      public void parameterChanged(String parameterName) {
        Utils.execSWTThread(new AERunnable() {
          public void runSupport() {
            boolean doRateGraphs = COConfigurationManager.getBooleanParameter("status.rategraphs");
            if (doRateGraphs) {
              if (imgRec == null || imgRec.isDisposed()) {
                imgRec = new Image(display, 100, 20);
                GC gc = new GC(imgRec);
                gc.setBackground(statusDown.getBackground());
                gc.fillRectangle(0, 0, 100, 20);
                gc.dispose();
                statusDown.setBackgroundImage(imgRec);
              }
             
              if (imgSent == null || imgSent.isDisposed()) {
                imgSent = new Image(display, 100, 20);
                GC gc = new GC(imgSent);
                gc.setBackground(statusUp.getBackground());
                gc.fillRectangle(0, 0, 100, 20);
                gc.dispose();
                statusUp.setBackgroundImage(imgSent);
              }
            } else {
              statusUp.setBackgroundImage(null);
              statusDown.setBackgroundImage(null);
              Utils.disposeSWTObjects(new Object[] { imgRec, imgSent });
              imgRec = imgSent = null;
            }
          }
        });
      }
    });
   
    /////////
   
    PRManager.addListener(new ProgressListener());
    setProgressImage();
   
    uiFunctions.getUIUpdater().addUpdater(this);
   
    ArrayList<Runnable> list;
    this_mon.enter();
    try {
      list = listRunAfterInit;
      listRunAfterInit = null;
    } finally {
      this_mon.exit();
    }
    for (Runnable runnable : list) {
      try {
        runnable.run();
      } catch (Exception e) {
        Debug.out(e);
      }
    }
   
    statusBar.layout(true);

    return statusBar;
  }

  protected void updateStatusWarnings() {
    Utils.execSWTThread(new AERunnable() {
      public void runSupport() {
        if (statusWarnings == null || statusWarnings.isDisposed()) {
          return;
        }
       
        ArrayList<LogAlert> alerts = Alerts.getUnviewedLogAlerts();
        int count = alerts.size();
       
        Image icon = infoIcon;
       
        for ( LogAlert alert: alerts ){
          int type = alert.getType();
         
          if ( type == LogAlert.LT_ERROR || type == LogAlert.LT_WARNING ){
           
            icon = warningIcon;
           
            break;
          }
        }
       
        if ( statusWarnings.getImage() != icon ){
          statusWarnings.setImage( icon );
        }
       
        statusWarnings.setVisible(count > 0);
        statusWarnings.setText("" + count);
        statusWarnings.layoutNow();
      }
    });
  }

  private void addFeedBack() {
    AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
      public void azureusCoreRunning(AzureusCore core) {
        Utils.execSWTThread(new AERunnable() {
          public void runSupport() {
            _addFeedBack();
          }
        });
      }
    });
  }

  private void _addFeedBack() {
    /*
     * Feedback
     *
     */

    // only show after restart after 15 mins uptime
    OverallStats stats = StatsFactory.getStats();

    long secs_uptime = stats.getTotalUpTime();

    long last_uptime = COConfigurationManager.getLongParameter(
        "statusbar.feedback.uptime", 0);

    if (last_uptime == 0) {

      COConfigurationManager.setParameter("statusbar.feedback.uptime",
          secs_uptime);

    } else if (secs_uptime - last_uptime > 15 * 60) {

      createStatusEntry(new CLabelUpdater() {
        public boolean update(CLabelPadding label) {
          return( false );
        }

        public void created(CLabelPadding feedback) {
          feedback.setText(MessageText.getString("statusbar.feedback"));
         
          Listener feedback_listener = new Listener() {
            public void handleEvent(Event e) {
             
              String url = "feedback.start?" + Utils.getWidgetBGColorURLParam()
              + "&fromWeb=false&os.name=" + UrlUtils.encode(Constants.OSName)
              + "&os.version="
              + UrlUtils.encode(System.getProperty("os.version"))
              + "&java.version=" + UrlUtils.encode(Constants.JAVA_VERSION);
             
              // Utils.launch( url );
             
              UIFunctionsManagerSWT.getUIFunctionsSWT().viewURL(url, null, 600,
                  520, true, false);
            }
          };
         
          feedback.setToolTipText(MessageText.getString("statusbar.feedback.tooltip"));
          feedback.setCursor(display.getSystemCursor(SWT.CURSOR_HAND));
          feedback.setForeground(Colors.blue);
          feedback.addListener(SWT.MouseUp, feedback_listener);
          feedback.addListener(SWT.MouseDoubleClick, feedback_listener);
         
          feedback.setVisible(true);
        }
      });
     
    }
  }

  /**
   * @param statusBar2
   *
   * @since 4.0.0.1
   */
  private void addStatusBarMenu(Composite cSB) {
    if (!Constants.isCVSVersion()) {
      return;
    }
    Menu menu = new Menu(cSB);
    cSB.setMenu(menu);

    MenuItem itemShow = new MenuItem(menu, SWT.CASCADE);
    itemShow.setText("Show");
    Menu menuShow = new Menu(itemShow);
    itemShow.setMenu(menuShow);

    final String[] statusAreaLangs = {
      "ConfigView.section.style.status.show_sr",
      "ConfigView.section.style.status.show_nat",
      "ConfigView.section.style.status.show_ddb",
      "ConfigView.section.style.status.show_ipf",
    };
    final String[] statusAreaConfig = {
      "Status Area Show SR",
      "Status Area Show NAT",
      "Status Area Show DDB",
      "Status Area Show IPF",
    };

    for (int i = 0; i < statusAreaConfig.length; i++) {
      final String configID = statusAreaConfig[i];
      String langID = statusAreaLangs[i];

      final MenuItem item = new MenuItem(menuShow, SWT.CHECK);
      Messages.setLanguageText(item, langID);
      item.addListener(SWT.Selection, new Listener() {
        public void handleEvent(Event event) {
          COConfigurationManager.setParameter(configID,
              !COConfigurationManager.getBooleanParameter(configID));
        }
      });
      menuShow.addListener(SWT.Show, new Listener() {
        public void handleEvent(Event event) {
          item.setSelection(COConfigurationManager.getBooleanParameter(configID));
        }
      });
    }
   
  }

  /**
   *
   * @param keyedSentence
   */
  public void setStatusText(String keyedSentence) {
    this.statusTextKey = keyedSentence == null ? "" : keyedSentence;
    setStatusImageKey(null);
    this.clickListener = null;
    if (statusTextKey.length() == 0) { // reset
      resetStatus();
    }

    updateStatusText();
  }
 
  private void setStatusImageKey(String newStatusImageKey) {
    if (("" + statusImageKey).equals("" + newStatusImageKey)) {
      return;
    }
    ImageLoader imageLoader = ImageLoader.getInstance();
    if (statusImageKey != null) {
      imageLoader.releaseImage(statusImageKey);
    }
    statusImageKey = newStatusImageKey;
    if (statusImageKey != null) {
      statusImage = imageLoader.getImage(statusImageKey);
    } else {
      statusImage = null;
    }
  }

  private void resetStatus() {
    if (Constants.isCVSVersion()) {
      statusTextKey = "MainWindow.status.unofficialversion ("
          + Constants.AZUREUS_VERSION + ")";
      setStatusImageKey(STATUS_ICON_WARN);
    } else if (!Constants.isOSX && COConfigurationManager.getStringParameter("ui").equals("az2")) { //don't show official version numbers for OSX L&F
      statusTextKey = Constants.APP_NAME + " " + Constants.AZUREUS_VERSION;
      setStatusImageKey(null);
    }

  }

  /**
   * @param statustype
   * @param string
   * @param l
   */
  public void setStatusText(int statustype, String string,
      UIStatusTextClickListener l) {
    this.statusTextKey = string == null ? "" : string;

    if (statusTextKey.length() == 0) { // reset
      resetStatus();
    }

    this.clickListener = l;
    if (statustype == UIFunctions.STATUSICON_WARNING) {
      setStatusImageKey(STATUS_ICON_WARN);
    }
    if (statustype == UIFunctions.STATUSICON_WARNING) {
      setStatusImageKey(STATUS_ICON_WARN);
    } else {
      setStatusImageKey(null);
    }

    updateStatusText();
  }

  /**
   *
   *
   */
  public void updateStatusText() {
    if (display == null || display.isDisposed())
      return;
    final String text;
    if (updateWindow != null) {
      text = "MainWindow.updateavail";
    } else {
      text = this.statusTextKey;
    }
    Utils.execSWTThread(new AERunnable() {
      public void runSupport() {
        if (statusText != null && !statusText.isDisposed()) {
          statusText.setText(MessageText.getStringForSentence(text));
          statusText.setImage(statusImage);
        }
      }
    });
  }

  /**
   *
   *
   */
  public void refreshStatusText() {
    if (statusText != null && !statusText.isDisposed())
      statusText.update();
  }

  /**
   *
   * @param updateWindow
   */
  public void setUpdateNeeded(UpdateWindow updateWindow) {
    this.updateWindow = updateWindow;
    if (updateWindow != null) {
      statusText.setCursor(display.getSystemCursor(SWT.CURSOR_HAND));
      statusText.setForeground(Colors.colorWarning);
      updateStatusText();
    } else {
      statusText.setCursor(null);
      statusText.setForeground(null);
      updateStatusText();
    }
  }

  // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI()
  public void updateUI() {
    if (statusBar.isDisposed()) {
      uiFunctions.getUIUpdater().removeUpdater(this);
      return;
    }

    // Plugins.
    Control[] plugin_elements = this.plugin_label_composite.getChildren();
    for (int i = 0; i < plugin_elements.length; i++) {
      if (plugin_elements[i] instanceof UpdateableCLabel) {
        ((UpdateableCLabel) plugin_elements[i]).checkForRefresh();
      }
    }

    if (ipBlocked.isVisible()) {
      updateIPBlocked();
    }
   
    if (srStatus.isVisible()) {
      updateShareRatioStatus();
    }


    if (natStatus.isVisible()) {
      updateNatStatus();
    }
   
    if (dhtStatus.isVisible()) {
      updateDHTStatus();
    }


    // UL/DL Status Sections
    if (AzureusCoreFactory.isCoreRunning()) {
      AzureusCore core = AzureusCoreFactory.getSingleton();
      GlobalManager gm = core.getGlobalManager();
      GlobalManagerStats stats = gm.getStats();

      int dl_limit = NetworkManager.getMaxDownloadRateBPS() / 1024;
      long rec_data = stats.getDataReceiveRate();
      long rec_prot = stats.getProtocolReceiveRate();
     
      if (last_dl_limit != dl_limit || last_rec_data != rec_data || last_rec_prot != rec_prot) {
        last_dl_limit = dl_limit;
        last_rec_data = rec_data;
        last_rec_prot = rec_prot;

        statusDown.setText((dl_limit == 0 ? "" : "[" + dl_limit + "K] ")
            + DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(rec_data, rec_prot));
      }
     
      boolean auto_up = TransferSpeedValidator.isAutoSpeedActive(gm)
          && TransferSpeedValidator.isAutoUploadAvailable(core);

      int ul_limit_norm = NetworkManager.getMaxUploadRateBPSNormal() / 1024;

      String seeding_only;
      if (NetworkManager.isSeedingOnlyUploadRate()) {
        int ul_limit_seed = NetworkManager.getMaxUploadRateBPSSeedingOnly() / 1024;
        if (ul_limit_seed == 0) {
          seeding_only = "+" + Constants.INFINITY_STRING + "K";
        } else {
          int diff = ul_limit_seed - ul_limit_norm;
          seeding_only = (diff >= 0 ? "+" : "") + diff + "K";
        }
      } else {
        seeding_only = "";
      }

      int sent_data = stats.getDataSendRate();
      if (imgRec != null && !imgRec.isDisposed()) {
        updateGraph(statusDown, imgRec, rec_data, max_rec);
        updateGraph(statusUp, imgSent, sent_data, max_sent);
      }


      statusUp.setText((ul_limit_norm == 0 ? "" : "[" + ul_limit_norm + "K"
          + seeding_only + "]")
          + (auto_up ? "* " : " ")
          + DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(
              sent_data, stats.getProtocolSendRate()));
    }
  }

  private void updateGraph(CLabelPadding label, Image img,
      long newVal, long[] max) {
    GC gc = new GC(img);
    try {
      long val = newVal;
      Rectangle bounds = img.getBounds();
      final int padding = 2;
      int x = bounds.width - padding - padding;
      if (val > max[0]) {
        int y = 20 - (int) (max[0] * 20 / val);
        gc.setBackground(label.getBackground());
        gc.fillRectangle(padding, 0, x, y);
        // gc.drawImage(imgRec, 1, 0, x, 20, 0, y, x, 20 - y);
        gc.copyArea(padding + 1, 0, x, 20, padding, y);
        max[0] = val;
      } else {
        gc.copyArea(padding + 1, 0, x, 20, padding, 0);
        // gc.drawImage(imgRec, 1, 0, x, 20, 0, 0, x, 20);
      }
      gc.setForeground(label.getBackground());
      int breakPoint = 20 - (max[0] == 0 ? 0
          : (int) (val * 20 / max[0]));
      gc.drawLine(x, 0, x, breakPoint);
      gc.setForeground(Colors.blues[5]);
      gc.drawLine(x, breakPoint, x, 20);
    } finally {
      gc.dispose();
    }
    label.redraw();
  }

  /**
   *
   *
   * @since 3.1.1.1
   */
  private void updateDHTStatus() {
    if (dhtPlugin == null) {
      return;
    }
    // DHT Status Section
    int dht_status = dhtPlugin.getStatus();
    long dht_count = -1;
    //boolean  reachable = false;
    if (dht_status == DHTPlugin.STATUS_RUNNING) {
      DHT[] dhts = dhtPlugin.getDHTs();

      //reachable = dhts.length > 0 && dhts[0].getTransport().isReachable();

      //if ( reachable ){
      dht_count = dhts[0].getControl().getStats().getEstimatedDHTSize();
      //}
    }

    if (lastDHTstatus != dht_status || lastDHTcount != dht_count) {
      boolean hasImage = dhtStatus.getImage() != null;
      boolean needImage = true;
      switch (dht_status) {
        case DHTPlugin.STATUS_RUNNING:

          dhtStatus.setToolTipText(MessageText.getString("MainWindow.dht.status.tooltip"));
          dhtStatus.setText(MessageText.getString("MainWindow.dht.status.users").replaceAll(
              "%1", numberFormat.format(dht_count)));

          /*
          if ( reachable ){
            dhtStatus.setImage(ImageRepository.getImage("greenled"));
            dhtStatus.setToolTipText(MessageText
                .getString("MainWindow.dht.status.tooltip"));
            dhtStatus.setText(MessageText.getString("MainWindow.dht.status.users").replaceAll("%1", numberFormat.format(dht_count)));
          } else {
            dhtStatus.setImage(ImageRepository.getImage("yellowled"));
            dhtStatus.setToolTipText(MessageText
                .getString("MainWindow.dht.status.unreachabletooltip"));
            dhtStatus.setText(MessageText
                .getString("MainWindow.dht.status.unreachable"));
          }
          */
          break;

        case DHTPlugin.STATUS_DISABLED:
          //dhtStatus.setImage(ImageRepository.getImage("grayled"));
          dhtStatus.setText(MessageText.getString("MainWindow.dht.status.disabled"));
          break;

        case DHTPlugin.STATUS_INITALISING:
          //dhtStatus.setImage(ImageRepository.getImage("yellowled"));
          dhtStatus.setText(MessageText.getString("MainWindow.dht.status.initializing"));
          break;

        case DHTPlugin.STATUS_FAILED:
          //dhtStatus.setImage(ImageRepository.getImage("redled"));
          dhtStatus.setText(MessageText.getString("MainWindow.dht.status.failed"));
          break;

        default:
          needImage = false;
          break;
      }

      if (hasImage != needImage) {
        ImageLoader imageLoader = ImageLoader.getInstance();
        if (needImage) {
          Image img = imageLoader.getImage("sb_count");
          dhtStatus.setImage(img);
        } else {
          imageLoader.releaseImage("sb_count");
          dhtStatus.setImage(null);
        }
      }
      lastDHTstatus = dht_status;
      lastDHTcount = dht_count;
    }
  }

  /**
   *
   *
   * @since 3.1.1.1
   */
  private void updateNatStatus() {
    // NAT status Section
    if (connection_manager == null) {
      return;
    }

    int nat_status = connection_manager.getNATStatus();

    if (lastNATstatus != nat_status) {
      String imgID;
      String tooltipID;
      String statusID;

      switch (nat_status) {
        case ConnectionManager.NAT_UNKNOWN:
          imgID = "grayled";
          tooltipID = "MainWindow.nat.status.tooltip.unknown";
          statusID = "MainWindow.nat.status.unknown";
          break;

        case ConnectionManager.NAT_OK:
          imgID = "greenled";
          tooltipID = "MainWindow.nat.status.tooltip.ok";
          statusID = "MainWindow.nat.status.ok";
          break;

        case ConnectionManager.NAT_PROBABLY_OK:
          imgID = "yellowled";
          tooltipID = "MainWindow.nat.status.tooltip.probok";
          statusID = "MainWindow.nat.status.probok";
          break;

        default:
          imgID = "redled";
          tooltipID = "MainWindow.nat.status.tooltip.bad";
          statusID = "MainWindow.nat.status.bad";
          break;
      }
     
      if (!imgID.equals(lastNATimageID)) {
        ImageLoader imageLoader = ImageLoader.getInstance();
        natStatus.setImage(imageLoader.getImage(imgID));

        if (lastNATimageID != null) {
          imageLoader.releaseImage(lastNATimageID);
        }
        lastNATimageID = imgID;
      }

      natStatus.setToolTipText(MessageText.getString(tooltipID));
      natStatus.setText(MessageText.getString(statusID));
      lastNATstatus = nat_status;
    }
  }

  /**
   *
   *
   * @since 3.1.1.1
   */
  private void updateShareRatioStatus() {
    // SR status section
   
    if (overall_stats == null) {
      overall_stats = StatsFactory.getStats();
     
      if (overall_stats == null) {
        return;
      }
    }

    long ratio = (1000 * overall_stats.getUploadedBytes() / (overall_stats.getDownloadedBytes() + 1));

    int sr_status;

    if (ratio < 500) {

      sr_status = 0;

    } else if (ratio < 900) {

      sr_status = 1;

    } else {

      sr_status = 2;
    }

    if (sr_status != last_sr_status) {

      String imgID;

      switch (sr_status) {
        case 2:
          imgID = "greenled";
          break;

        case 1:
          imgID = "yellowled";
          break;

        default:
          imgID = "redled";
          break;
      }

      if (!imgID.equals(lastSRimageID)) {
        ImageLoader imageLoader = ImageLoader.getInstance();
        srStatus.setImage(imageLoader.getImage(imgID));
        if (lastSRimageID != null) {
          imageLoader.releaseImage(lastSRimageID);
        }
        lastSRimageID  = imgID;
      }
     
      last_sr_status = sr_status;
    }

    if (ratio != last_sr_ratio) {

      String tooltipID;

      switch (sr_status) {
        case 2:
          tooltipID = "MainWindow.sr.status.tooltip.ok";
          break;

        case 1:
          tooltipID = "MainWindow.sr.status.tooltip.poor";
          break;

        default:
          tooltipID = "MainWindow.sr.status.tooltip.bad";
          break;
      }

      String ratio_str = "";

      String partial = "" + ratio % 1000;

      while (partial.length() < 3) {

        partial = "0" + partial;
      }

      ratio_str = (ratio / 1000) + "." + partial;

      srStatus.setToolTipText(MessageText.getString(tooltipID, new String[] {
        ratio_str
      }));

      last_sr_ratio = ratio;
    }
  }

  /**
   *
   *
   * @since 3.1.1.1
   */
  private void updateIPBlocked() {
    if (!AzureusCoreFactory.isCoreRunning()) {
      return;
    }
   
    AzureusCore azureusCore = AzureusCoreFactory.getSingleton();

    // IP Filter Status Section
    IpFilter ip_filter = azureusCore.getIpFilterManager().getIPFilter();

    ipBlocked.setText("IPs: "
        + numberFormat.format(ip_filter.getNbRanges())
        + " - "
        + numberFormat.format(ip_filter.getNbIpsBlockedAndLoggable())
        + "/"
        + numberFormat.format(ip_filter.getNbBannedIps())
        + "/"
        + numberFormat.format(azureusCore.getIpFilterManager().getBadIps().getNbBadIps()));
    ipBlocked.setToolTipText(MessageText.getString("MainWindow.IPs.tooltip",
        new String[] {
          DisplayFormatters.formatDateShort(ip_filter.getLastUpdateTime())
        }));
  }

  /**
   * @param string
   */
  public void setDebugInfo(String string) {
    if (statusText != null && !statusText.isDisposed())
      statusText.setToolTipText(string);
  }
 
  public boolean isMouseOver() {
    if (statusText == null || statusText.isDisposed()) {
      return false;
    }
    return statusText.getDisplay().getCursorControl() == statusText;
  }

  public static interface CLabelUpdater
  {
    public void created(CLabelPadding label);
    public boolean update(CLabelPadding label);
  }

  /**
   * CLabel that shrinks to fit text after a specific period of time.
   * Makes textual changes less jumpy
   *
   * @author TuxPaper
   * @created Mar 21, 2006
   *
   */
  public class CLabelPadding
    extends Canvas implements PaintListener
  {
    private int lastWidth = 0;

    private long widthSetOn = 0;

    private static final int KEEPWIDTHFOR_MS = 30 * 1000;
   
    String text = "";

    private Image image;

    private Image bgImage;

    /**
     * Default Constructor
     *
     * @param parent
     * @param style
     */
    public CLabelPadding(Composite parent, int style) {
      super(parent, style | SWT.DOUBLE_BUFFERED);

      GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER
          | GridData.VERTICAL_ALIGN_FILL);
      setLayoutData(gridData);
      setForeground(parent.getForeground());
     
      addPaintListener(this);
    }

    public void paintControl(PaintEvent e) {
      Point size = getSize();
      e.gc.setAdvanced(true);
      if (bgImage != null && !bgImage.isDisposed()) {
        Rectangle bounds = bgImage.getBounds();
        if (display.getCursorControl() != this) {
          e.gc.setAlpha(100);
        }
        e.gc.drawImage(bgImage, 0, 0, bounds.width, bounds.height, 0, 2,
            size.x, size.y - 4);
        e.gc.setAlpha(255);
      }
      Rectangle clientArea = getClientArea();
     

      Image image = getImage();
      Rectangle imageBounds = null;
      if (image != null && !image.isDisposed()) {
        imageBounds = image.getBounds();
      }
      GCStringPrinter sp = new GCStringPrinter(e.gc, getText(), clientArea,
          true, true, SWT.CENTER);
      sp.calculateMetrics();
      Point textSize = sp.getCalculatedSize();

      if (imageBounds != null) {
        int pad = 2;
        int ofs = imageBounds.width + imageBounds.x;
        int xStartImage = (clientArea.width - textSize.x - ofs - pad) / 2;
        e.gc.drawImage(image, xStartImage,
            (clientArea.height / 2) - (imageBounds.height / 2));
        clientArea.x += xStartImage + ofs + pad;
        clientArea.width -= xStartImage + ofs + pad;
      } else {
        int ofs = (clientArea.width / 2) - (textSize.x / 2);
        clientArea.x += ofs;
        clientArea.width -= ofs;
      }
      sp.printString(e.gc, clientArea, SWT.LEFT);

      int x = clientArea.x + clientArea.width - 1;
      e.gc.setAlpha(20);
      e.gc.drawLine(x, 3, x, clientArea.height - 3);
    }

    /* (non-Javadoc)
     * @see org.eclipse.swt.custom.CLabel#computeSize(int, int, boolean)
     */
    public Point computeSize(int wHint, int hHint) {
      return computeSize(wHint, hHint, true);
    }

    public Point computeSize(int wHint, int hHint, boolean changed) {
      try {
        Point pt = computeSize(wHint, hHint, changed, false);

        return pt;
      } catch (Throwable t) {
        Debug.out("Error while computing size for CLabel with text:"
            + getText() + "; " + t.toString());
        return new Point(0, 0);
      }
    }

    // @see org.eclipse.swt.widgets.Control#computeSize(int, int)
    public Point computeSize(int wHint, int hHint, boolean changed, boolean realWidth) {
      if (!isVisible()) {
        return (new Point(0, 0));
      }

      if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT) {
        return new Point(wHint, hHint);
      }
      Point pt = new Point(wHint, hHint);

      Point lastSize = new Point(0, 0);

      Image image = getImage();
      if (image != null && !image.isDisposed()) {
        Rectangle bounds = image.getBounds();
        int ofs = bounds.width + bounds.x + 5;
        lastSize.x += ofs;
        lastSize.y = bounds.height;
      }

      GC gc = new GC(this);
      GCStringPrinter sp = new GCStringPrinter(gc, getText(), new Rectangle(0,
          0, 10000, 20), true, true, SWT.LEFT);
      sp.calculateMetrics();
      Point lastTextSize = sp.getCalculatedSize();
      gc.dispose();

      lastSize.x += lastTextSize.x + 10;
      lastSize.y = Math.max(lastSize.y, lastTextSize.y);

      if (wHint == SWT.DEFAULT) {
        pt.x = lastSize.x;
      }
      if (hHint == SWT.DEFAULT) {
        pt.y = lastSize.y;
      }

      if (!realWidth) {
          long now = System.currentTimeMillis();
          if (lastWidth > pt.x && now - widthSetOn < KEEPWIDTHFOR_MS) {
            pt.x = lastWidth;
          } else {
            if (lastWidth != pt.x) {
              lastWidth = pt.x;
            }
            widthSetOn = now;
          }
      }

      return pt;
    }
   

    public void setImage(Image image) {
      this.image = image;
    }
   
    public Image getImage() {
      return image;
    }
   
    public void setBackgroundImage(Image image) {
      bgImage = image;
    }
   
    public Image getBackgroundImage() {
      return bgImage;
    }
   
    public String getText() {
      return text;
    }
   
    public void setText(String text) {
      if (text == null) {
        text = "";
      }
      if (text.equals(getText())) {
        return;
      }
      this.text = text;
      int oldWidth = lastWidth;
      Point pt = computeSize(SWT.DEFAULT, SWT.DEFAULT, true, true);
      if (pt.x > oldWidth && text.length() > 0) {
        statusBar.layout();
      } else if (pt.x < oldWidth) {
        Utils.execSWTThreadLater(KEEPWIDTHFOR_MS, new AERunnable() {
          public void runSupport() {
            if (statusBar == null || statusBar.isDisposed()) {
              return;
            }
            statusBar.layout();
          }
        });
      }
      redraw();
    }
   
    public void
    reset()
    {
      widthSetOn   = 0;
      lastWidth  = 0;
    }
   
    public void layoutNow() {
      widthSetOn = 0;
      statusBar.layout();
    }

  }

  private class UpdateableCLabel
    extends CLabelPadding
  {

    private CLabelUpdater updater;

    public UpdateableCLabel(Composite parent, int style, CLabelUpdater updater) {
      super(parent, style);
      this.updater = updater;
    }

    private void checkForRefresh() {
      if ( updater.update(this)){
        layoutPluginComposite();
      }
    }
  }

  public void createStatusEntry(final CLabelUpdater updater) {
    AERunnable r = new AERunnable() {
      public void runSupport() {
        UpdateableCLabel result = new UpdateableCLabel(plugin_label_composite, borderFlag,
            updater);
        result.setLayoutData(new GridData(GridData.FILL_BOTH));
        layoutPluginComposite();
        updater.created(result);
      }
    };
    this_mon.enter();
    try {
      if (listRunAfterInit != null) {
        listRunAfterInit.add(r);
        return;
      }
    } finally {
      this_mon.exit();
    }

    Utils.execSWTThread(r);
  }

  private void
  layoutPluginComposite()
  {
    Control[] plugin_elements = this.plugin_label_composite.getChildren();
    for (int i = 0; i < plugin_elements.length; i++) {
      if (plugin_elements[i] instanceof UpdateableCLabel) {
        ((UpdateableCLabel) plugin_elements[i]).reset();
      }
    }
    statusBar.layout();
  }
  // =============================================================
  // Below code are ProgressBar/Status text specific
  // ============================================================= 
  /**
   * Show or hide the Progress Bar
   * @param state
   */
  private void showProgressBar(boolean state) {
    /*
     * We show/hide the progress bar simply by setting the .widthHint and letting the statusBar handle the layout
     */
    if (true == state && false == progressBar.isVisible()) {
      progressGridData.widthHint = 100;
      progressBar.setVisible(true);
      statusBar.layout();
    } else if (false == state && true == progressBar.isVisible()) {
      progressBar.setVisible(false);
      progressGridData.widthHint = 0;
      statusBar.layout();
    }
  }

  /**
   * Updates the display of the ProgressBar and/or the status text
   * @param pReport the <code>ProgressReport</code> containing the information
   * to display; can be <code>null</code> in which case the status text and progress bar will be reset to default states
   */
  private void updateProgressBarDisplay(IProgressReport pReport) {
    latestReport_mon.enter();
    try {
      latestReport = pReport;
    } finally {
      latestReport_mon.exit();
    }
    if (null == progressBar || progressBar.isDisposed()
        || updateProgressBarDisplayQueued) {
      return;
    }
    updateProgressBarDisplayQueued = true;

    Utils.execSWTThread(new AERunnable() {
      public void runSupport() {
        latestReport_mon.enter();
        try {
          updateProgressBarDisplayQueued = false;

          if ((null == progressBar || true == progressBar.isDisposed())) {
            return;
          }

          if (null != latestReport) {
            /*
             * Pass the values through to the progressbar
             */
            progressBar.setMinimum(latestReport.getMinimum());
            progressBar.setMaximum(latestReport.getMaximum());
            progressBar.setIndeterminate(latestReport.isIndeterminate());
            progressBar.setPercentage(latestReport.getPercentage());
            showProgressBar(true);

            /*
             * Update status text
             */
            if (true == isAZ3) {
              statusText.setText(latestReport.getName());
            } else {
              setStatusText(latestReport.getName());
            }
          }

          else {
            /*
             * Since the pReport is null then reset progress display appropriately
             */
            showProgressBar(false);

            if (true == isAZ3) {
              statusText.setText("");
            } else {
              setStatusText(null);
            }
          }
        } finally {
          latestReport_mon.exit();
        }

      }

    }, true);

  }

  private void setProgressImage() {
    String imageID;

    if (PRManager.getReporterCount(ProgressReportingManager.COUNT_ERROR) > 0) {
      imageID = "progress_error";
    } else if (PRManager.getReporterCount(ProgressReportingManager.COUNT_ALL) > 0) {
      imageID = "progress_info";
    } else {
      imageID = "progress_viewer";
    }

    if (!imageID.equals(lastProgressImageID)) {
      final String fImageID = imageID;
      Utils.execSWTThread(new AERunnable() {
        public void runSupport() {
          if (progressViewerImageLabel.isDisposed()) {
            return;
          }
          ImageLoader imageLoader = ImageLoader.getInstance();
          progressViewerImageLabel.setImage(imageLoader.getImage(fImageID));
          if (lastProgressImageID != null) {
            imageLoader.releaseImage(lastProgressImageID);
          }
          lastProgressImageID  = fImageID;
        }
      });
    }
  }

  /**
   * A listener that listens to any changes notified from the <code>ProgressReportingManager</code> and
   * accordingly update the progress bar and/or the status text area.
   * @author knguyen
   *
   */
  private class ProgressListener
    implements IProgressReportingListener, IProgressReportConstants
  {

    public int reporting(int eventType, IProgressReporter reporter) {

      /*
       * Show the appropriate image based on the content of the reporting manager
       */
      setProgressImage();

      if (null == reporter) {
        return RETVAL_OK;
      }

      if (MANAGER_EVENT_REMOVED == eventType) {
        updateFromPrevious();
      } else if (MANAGER_EVENT_ADDED == eventType
          || MANAGER_EVENT_UPDATED == eventType) {
        /*
         * Get a ProgressReport to ensure all data is consistent
         */
        IProgressReport pReport = reporter.getProgressReport();

        /*
         * Pops up the ProgressReportingWindow to show this report if it is an error report;
         * this is to help catch the users attention
         */
        if (true == pReport.isInErrorState()) {
         
          if(true == "reporterType_updater".equals(pReport.getReporterType())){
            /*
             * Suppressing the pop-up for update-related errors
             */
            return RETVAL_OK;
          }
         
          final IProgressReporter final_reporter = reporter;
         

          /*
           * The new window is opened only if there is not one already showing the same reporter
           */
          if (false == ProgressReporterWindow.isOpened(final_reporter)) {
            Utils.execSWTThread(new AERunnable() {
              public void runSupport() {
                if ( !ProgressReporterWindow.isOpened(final_reporter)){
                  ProgressReporterWindow.open(final_reporter,
                      ProgressReporterWindow.NONE);
                }
              }
            }, true);
          }
        }

        /*
         * If this reporter is not active then get the previous reporter that is still active and display info from that
         */
        if (false == pReport.isActive()) {
          updateFromPrevious();
        } else {
          update(pReport);
        }
      }

      return RETVAL_OK;
    }

    private void update(final IProgressReport pReport) {

      if (null == pReport) {
        updateProgressBarDisplay(null);
        return;
      }

      /*
       * If there is at least 2 reporters still active then show the progress bar as indeterminate
       * and display the text from the current reporter
       */
      if (true == PRManager.hasMultipleActive()) {
        Utils.execSWTThread(new AERunnable() {
          public void runSupport() {
            setStatusText(pReport.getName());
            progressBar.setIndeterminate(true);
            showProgressBar(true);
          }
        }, true);
      } else {
        updateProgressBarDisplay(pReport);
      }
    }

    private void updateFromPrevious() {
      /*
       * Get the previous reporter that is still active
       */
      IProgressReporter previousReporter = PRManager.getNextActiveReporter();

      /*
       * If null then we reset the status text and the progress bar
       */
      if (null != previousReporter) {
        update(previousReporter.getProgressReport());
      } else {
        update(null);
      }
    }
  }

  public Rectangle getBounds() {
    if (null != statusBar) {
      return statusBar.getBounds();
    }
    return null;
  }

  // @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName()
  public String getUpdateUIName() {
    return ID;
  }
}
TOP

Related Classes of org.gudy.azureus2.ui.swt.mainwindow.MainStatusBar$ProgressListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.