package com.limegroup.gnutella.gui; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.RoundRectangle2D; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSeparator; import javax.swing.SwingConstants; import com.limegroup.gnutella.RouterService; import com.limegroup.gnutella.gui.mp3.MediaPlayerComponent; import com.limegroup.gnutella.gui.themes.ThemeMediator; import com.limegroup.gnutella.gui.themes.ThemeObserver; import com.limegroup.gnutella.settings.ApplicationSettings; import com.limegroup.gnutella.settings.PlayerSettings; import com.limegroup.gnutella.settings.StatusBarSettings; import com.limegroup.gnutella.statistics.BandwidthStat; import com.limegroup.gnutella.util.CommonUtils; import com.limegroup.gnutella.version.UpdateInformation; /** * The component for the space at the bottom of the main application * window, including the connected status and the media player. */ public final class StatusLine implements ThemeObserver { /** * The different connection status possibilities. */ public static final int STATUS_DISCONNECTED = 0; public static final int STATUS_CONNECTING = 1; public static final int STATUS_POOR = 2; public static final int STATUS_FAIR = 3; public static final int STATUS_GOOD = 4; public static final int STATUS_EXCELLENT = 5; public static final int STATUS_TURBOCHARGED = 6; public static final int STATUS_IDLE = 7; public static final int STATUS_WAKING_UP = 8; /** * The main container for the status line component. */ private final JPanel BAR = new JPanel(new GridBagLayout()); /** * The left most panel containing the connection quality. * The switcher changes the actual ImageIcons on this panel. */ private final JLabel _connectionQualityMeter = new JLabel(); private final ImageIcon[] _connectionQualityMeterIcons = new ImageIcon[9]; /** * The label with the firewall status. */ private final JLabel _firewallStatus = new JLabel(); /** * The custom component for displaying the number of shared files. */ private final SharedFilesLabel _sharedFiles = new SharedFilesLabel(); /** * The labels for displaying the bandwidth usage. */ private final JLabel _bandwidthUsageDown = new JLabel(GUIMediator.getThemeImage("downloading_small")); private final JLabel _bandwidthUsageUp = new JLabel(GUIMediator.getThemeImage("uploading_small")); /** * Variables for the center portion of the status bar, which can display * the StatusComponent (progress bar during program load), the UpdatePanel * (notification that a new version of LimeWire is available), and the * StatusLinkHandler (ads for going PRO). */ private final StatusComponent STATUS_COMPONENT = new StatusComponent(StatusComponent.CENTER); private final UpdatePanel _updatePanel = new UpdatePanel(); private final StatusLinkHandler _statusLinkHandler = new StatusLinkHandler(); private final JPanel _centerPanel = new JPanel(new GridBagLayout()); private Component _centerComponent = _updatePanel; /** * The media player. */ private MediaPlayerComponent _mediaPlayer; /////////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////////// /** * Creates a new status line in the disconnected state. */ public StatusLine() { GUIMediator.setSplashScreenString( GUIMediator.getStringResource("SPLASH_STATUS_STATUS_WINDOW")); GUIMediator.addRefreshListener(REFRESH_LISTENER); BAR.addMouseListener(STATUS_BAR_LISTENER); GUIMediator.getAppFrame().addComponentListener(new ComponentListener() { public void componentResized(ComponentEvent arg0) { refresh(); } public void componentMoved(ComponentEvent arg0) { } public void componentShown(ComponentEvent arg0) { } public void componentHidden(ComponentEvent arg0) { } }); // make icons and panels for connection quality createConnectionQualityPanel(); // make the 'Firewall Status' label createFirewallLabel(); // make the 'Sharing X Files' component createSharingFilesLabel(); // make the 'Bandwidth Usage' label createBandwidthLabel(); // make the center panel createCenterPanel(); // Set the bars to not be connected. setConnectionQuality(0); ThemeMediator.addThemeObserver(this); refresh(); } /** * Redraws the status bar based on changes to StatusBarSettings, * and makes sure it has room to add an indicator before adding it. */ public void refresh() { BAR.removeAll(); // figure out remaining width, and do not add indicators if no room int sepWidth = Math.max(2, createSeparator().getWidth()); int remainingWidth = BAR.getWidth(); if (remainingWidth <= 0) remainingWidth = ApplicationSettings.APP_WIDTH.getValue(); // subtract player as needed if (GUIMediator.isPlaylistVisible()) { if (_mediaPlayer == null) _mediaPlayer = MediaPlayerComponent.instance(); remainingWidth -= sepWidth; remainingWidth -= GUIConstants.SEPARATOR / 2; remainingWidth -= Math.max(216, _mediaPlayer.getMediaPanel().getWidth()); remainingWidth -= GUIConstants.SEPARATOR; } // subtract center component int indicatorWidth = _centerComponent.getWidth(); if (indicatorWidth <= 0) if (_updatePanel.shouldBeShown()) { indicatorWidth = 190; if (!GUIMediator.hasDonated()) indicatorWidth = 280; } remainingWidth -= indicatorWidth; // add components to panel, if room GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(0,0,0,0); gbc.weightx = 0; gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.CENTER; gbc.gridx = GridBagConstraints.RELATIVE; // add connection quality indicator if there's room indicatorWidth = GUIConstants.SEPARATOR + Math.max((int)_connectionQualityMeter.getMinimumSize().getWidth(), _connectionQualityMeter.getWidth()) + sepWidth; if (StatusBarSettings.CONNECTION_QUALITY_DISPLAY_ENABLED.getValue() && remainingWidth > indicatorWidth) { BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(_connectionQualityMeter, gbc); BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(createSeparator(), gbc); remainingWidth -= indicatorWidth; } // then add firewall display if there's room indicatorWidth = GUIConstants.SEPARATOR + Math.max((int)_firewallStatus.getMinimumSize().getWidth(), _firewallStatus.getWidth()) + sepWidth; if (StatusBarSettings.FIREWALL_DISPLAY_ENABLED.getValue() && remainingWidth > indicatorWidth) { BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(_firewallStatus, gbc); BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(createSeparator(), gbc); remainingWidth -= indicatorWidth; } // add shared files indicator if there's room indicatorWidth = GUIConstants.SEPARATOR + Math.max((int)_sharedFiles.getMinimumSize().getWidth(), _sharedFiles.getWidth()) + sepWidth; if (StatusBarSettings.SHARED_FILES_DISPLAY_ENABLED.getValue() && remainingWidth > indicatorWidth) { BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(_sharedFiles, gbc); BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(createSeparator(), gbc); remainingWidth -= indicatorWidth; } // add bandwidth display if there's room indicatorWidth = GUIConstants.SEPARATOR + GUIConstants.SEPARATOR / 2 + sepWidth + Math.max((int)_bandwidthUsageDown.getMinimumSize().getWidth(), _bandwidthUsageDown.getWidth()) + Math.max((int)_bandwidthUsageUp.getMinimumSize().getWidth(), _bandwidthUsageUp.getWidth()); if (StatusBarSettings.BANDWIDTH_DISPLAY_ENABLED.getValue() && remainingWidth > indicatorWidth) { BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(_bandwidthUsageDown, gbc); BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR), gbc); BAR.add(_bandwidthUsageUp, gbc); BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(createSeparator(), gbc); remainingWidth -= indicatorWidth; } BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); // make center panel stretchy gbc.weightx = 1; BAR.add(_centerPanel, gbc); gbc.weightx = 0; BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); // media player if (GUIMediator.isPlaylistVisible()) { JPanel jp = _mediaPlayer.getMediaPanel(); jp.setOpaque(false); BAR.add(createSeparator(), gbc); BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR / 2), gbc); BAR.add(jp, gbc); BAR.add(Box.createHorizontalStrut(GUIConstants.SEPARATOR), gbc); } BAR.validate(); BAR.repaint(); } /** * Creates a vertical separator for visually separating status bar elements */ private Component createSeparator() { JSeparator sep = new JSeparator(SwingConstants.VERTICAL); // separators need preferred size in GridBagLayout sep.setPreferredSize(new Dimension(2, 20)); sep.setMinimumSize(new Dimension(2, 20)); return sep; } /** * Sets up _connectionQualityMeter's icons. */ private void createConnectionQualityPanel() { updateTheme(); // loads images _connectionQualityMeter.setOpaque(false); _connectionQualityMeter.setMinimumSize(new Dimension(34, 20)); _connectionQualityMeter.setMaximumSize(new Dimension(90, 30)); // add right-click listener _connectionQualityMeter.addMouseListener(STATUS_BAR_LISTENER); } /** * Sets up the 'Sharing X Files' label. */ private void createSharingFilesLabel() { _sharedFiles.setHorizontalAlignment(SwingConstants.LEFT); // don't allow easy clipping _sharedFiles.setMinimumSize(new Dimension(24, 20)); // add right-click listener _sharedFiles.addMouseListener(STATUS_BAR_LISTENER); // initialize tool tip _sharedFiles.setToolTipText(GUIMediator.getStringResource("STATISTICS_SHARING_TOOLTIP") + " " + 0 + " " + GUIMediator.getStringResource("STATISTICS_FILES_TOOLTIP_PENDING")); } /** * Sets up the 'Firewall Status' label. */ private void createFirewallLabel() { updateFirewall(); // don't allow easy clipping _firewallStatus.setMinimumSize(new Dimension(20, 20)); // add right-click listener _firewallStatus.addMouseListener(STATUS_BAR_LISTENER); } /** * Sets up the 'Bandwidth Usage' label. */ private void createBandwidthLabel() { updateBandwidth(); // don't allow easy clipping _bandwidthUsageDown.setMinimumSize(new Dimension(60, 20)); _bandwidthUsageUp.setMinimumSize(new Dimension(60, 20)); // add right-click listeners _bandwidthUsageDown.addMouseListener(STATUS_BAR_LISTENER); _bandwidthUsageUp.addMouseListener(STATUS_BAR_LISTENER); } /** * Sets up the center panel. */ private void createCenterPanel() { _centerPanel.setOpaque(false); _updatePanel.setOpaque(false); ((JComponent)_statusLinkHandler.getComponent()).setOpaque(false); STATUS_COMPONENT.setProgressPreferredSize(new Dimension(250, 20)); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1; gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.CENTER; _centerPanel.add(STATUS_COMPONENT, gbc); // add right-click listeners _statusLinkHandler.getComponent().addMouseListener(STATUS_BAR_LISTENER); _centerPanel.addMouseListener(STATUS_BAR_LISTENER); _updatePanel.addMouseListener(STATUS_BAR_LISTENER); STATUS_COMPONENT.addMouseListener(STATUS_BAR_LISTENER); } /** * Updates the center panel if non-PRO. Periodically rotates between * the update panel and the status link handler. */ private void updateCenterPanel() { long now = System.currentTimeMillis(); if (_nextUpdateTime > now) return; _nextUpdateTime = now + 1000 * 5; // update every minute _centerPanel.removeAll(); if (GUIMediator.hasDonated()) { if (_updatePanel.shouldBeShown()) _centerComponent = _updatePanel; else _centerComponent = new JLabel(); } else { if ((_centerComponent == _statusLinkHandler.getComponent()) && _updatePanel.shouldBeShown()) _centerComponent = _updatePanel; else _centerComponent = _statusLinkHandler.getComponent(); } GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 0; gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.CENTER; _centerPanel.add(_centerComponent, gbc); refresh(); } private long _nextUpdateTime = System.currentTimeMillis(); /** * Tells the status linke that the update panel should be shown with * the given update information. */ public void showUpdatePanel(boolean popup, UpdateInformation info) { _updatePanel.makeVisible(popup, info); } /** * Updates the status text. */ void setStatusText(final String text) { GUIMediator.safeInvokeAndWait(new Runnable() { public void run() { STATUS_COMPONENT.setText(text); } }); } /** * Updates the firewall text. */ public void updateFirewallLabel(boolean notFirewalled) { if (notFirewalled) { _firewallStatus.setIcon(GUIMediator.getThemeImage("firewall_no")); _firewallStatus.setToolTipText(GUIMediator.getStringResource("STATUS_BAR_FIREWALL_NOT_FOUND_TOOLTIP")); } else { _firewallStatus.setIcon(GUIMediator.getThemeImage("firewall")); _firewallStatus.setToolTipText(GUIMediator.getStringResource("STATUS_BAR_FIREWALL_FOUND_TOOLTIP")); } } /** * Updates the firewall text. */ public void updateFirewall() { updateFirewallLabel(RouterService.acceptedIncomingConnection()); } // variables for time averaging the download and upload bandwidths private int _numTimeSlices = 3; private int[] _pastDownloads = new int[_numTimeSlices]; private int[] _pastUploads = new int[_numTimeSlices]; private int _pastBandwidthIndex = 0; /** * Updates the bandwidth statistics. */ public void updateBandwidth() { // calculate time-averaged stats _pastDownloads[_pastBandwidthIndex] = BandwidthStat.HTTP_DOWNSTREAM_BANDWIDTH.getLastStored(); _pastUploads[_pastBandwidthIndex] = BandwidthStat.HTTP_UPSTREAM_BANDWIDTH.getLastStored(); _pastBandwidthIndex = (_pastBandwidthIndex + 1) % _numTimeSlices; int downBW = 0; int upBW = 0; for (int i = 0; i < _numTimeSlices; i++) downBW += _pastDownloads[i]; downBW /= _numTimeSlices; for (int i = 0; i < _numTimeSlices; i++) upBW += _pastUploads[i]; upBW /= _numTimeSlices; // format strings String sDown = GUIUtils.rate2speed(downBW/1000f); String sUp = GUIUtils.rate2speed(upBW/1000f); int downloads = RouterService.getNumActiveDownloads(); int uploads = RouterService.getNumUploads(); _bandwidthUsageDown.setText(downloads + " @ " + sDown); _bandwidthUsageUp.setText(uploads + " @ " + sUp); // create good-looking table tooltip String tooltip = "<html><table>" + "<tr><td>" + GUIMediator.getStringResource("OPTIONS_STATUS_BAR_BANDWIDTH_DOWNLOADS") + "</td><td>" + downloads + "</td><td>@</td><td align=right>" + sDown + "</td></tr>" + "<tr><td>" + GUIMediator.getStringResource("OPTIONS_STATUS_BAR_BANDWIDTH_UPLOADS") + "</td><td>" + uploads + "</td><td>@</td><td align=right>" + sUp + "</td></tr></table></html>"; _bandwidthUsageDown.setToolTipText(tooltip); _bandwidthUsageUp.setToolTipText(tooltip); } /** * Notification that loading has finished. * * The loading label is removed and the update notification * component is added. If necessary, the center panel will * rotate back and forth between displaying the update * notification and displaying the StatusLinkHandler. */ void loadFinished() { updateCenterPanel(); _centerPanel.revalidate(); _centerPanel.repaint(); refresh(); } /** * Load connection quality theme icons */ public void updateTheme() { for (int i = 0; i < _connectionQualityMeterIcons.length; i++) _connectionQualityMeterIcons[i] = GUIMediator.getThemeImage("connect_small_" + i); if (_mediaPlayer != null) _mediaPlayer.updateTheme(); } /** * Alters the displayed connection quality. * * @modifies this */ public void setConnectionQuality(int quality) { // make sure we don't go over our bounds. if (quality >= _connectionQualityMeterIcons.length) quality = _connectionQualityMeterIcons.length - 1; _connectionQualityMeter.setIcon(_connectionQualityMeterIcons[quality]); String status = null; String tip = null; String connection = GUIMediator.getStringResource("STATISTICS_CONNECTION_QUALITY"); switch(quality) { case STATUS_DISCONNECTED: status = GUIMediator.getStringResource("STATISTICS_CONNECTION_DISCONNECTED"); tip = GUIMediator.getStringResource("STATISTICS_CONNECTION_DISCONNECTED_TIP"); break; case STATUS_CONNECTING: status = GUIMediator.getStringResource("STATISTICS_CONNECTION_CONNECTING") + " " + connection; tip = GUIMediator.getStringResource("STATISTICS_CONNECTION_CONNECTING_TIP"); break; case STATUS_POOR: status = GUIMediator.getStringResource("STATISTICS_CONNECTION_POOR") + " " + connection; tip = GUIMediator.getStringResource("STATISTICS_CONNECTION_POOR_TIP"); break; case STATUS_FAIR: status = GUIMediator.getStringResource("STATISTICS_CONNECTION_FAIR") + " " + connection; tip = GUIMediator.getStringResource("STATISTICS_CONNECTION_FAIR_TIP"); break; case STATUS_GOOD: status = GUIMediator.getStringResource("STATISTICS_CONNECTION_GOOD") + " " + connection; tip = GUIMediator.getStringResource("STATISTICS_CONNECTION_GOOD_TIP"); break; case STATUS_IDLE: case STATUS_EXCELLENT: status = GUIMediator.getStringResource("STATISTICS_CONNECTION_EXCELLENT") + " " + connection; tip = GUIMediator.getStringResource("STATISTICS_CONNECTION_EXCELLENT_TIP"); break; case STATUS_TURBOCHARGED: status = GUIMediator.getStringResource("STATISTICS_CONNECTION_TURBO_CHARGED") + " " + connection; tip = GUIMediator.getStringResource("STATISTICS_CONNECTION_TURBO_CHARGED_TIP_" + (CommonUtils.isPro() ? "PRO" : "FREE")); break; //case STATUS_IDLE: //status = STATISTICS_CONNECTION_IDLE; //tip = null; // impossible to see this //break; case STATUS_WAKING_UP: status = GUIMediator.getStringResource("STATISTICS_CONNECTION_WAKING_UP") + " " + connection; tip = GUIMediator.getStringResource("STATISTICS_CONNECTION_WAKING_UP_TIP"); break; } _connectionQualityMeter.setToolTipText(tip); if (GUIMediator.hasDonated()) _connectionQualityMeter.setText(status); } /** * Sets the horizon statistics for this. * @modifies this * @return A displayable Horizon string. */ public void setStatistics(int share, int pending) { _sharedFiles.update(share, pending); } /** * Accessor for the <tt>JComponent</tt> instance that contains all * of the panels for the status line. * * @return the <tt>JComponent</tt> instance that contains all * of the panels for the status line */ public JComponent getComponent() { return BAR; } /** * The refresh listener for updating the bandwidth usage every second. */ private final RefreshListener REFRESH_LISTENER = new RefreshListener() { public void refresh() { if (StatusBarSettings.BANDWIDTH_DISPLAY_ENABLED.getValue()) updateBandwidth(); updateCenterPanel(); } }; /** * The right-click listener for the status bar. */ private final MouseAdapter STATUS_BAR_LISTENER = new MouseAdapter() { public void mousePressed(MouseEvent me) { processMouseEvent(me); } public void mouseReleased(MouseEvent me) { processMouseEvent(me); } public void mouseClicked(MouseEvent me) { processMouseEvent(me); } public void processMouseEvent(MouseEvent me) { if (me.isPopupTrigger()) { JPopupMenu jpm = new JPopupMenu(); // add 'Show Connection Quality' menu item JCheckBoxMenuItem jcbmi = new JCheckBoxMenuItem(new ShowConnectionQualityAction()); jcbmi.setState(StatusBarSettings.CONNECTION_QUALITY_DISPLAY_ENABLED.getValue()); jpm.add(jcbmi); // add 'Show Firewall Status' menu item jcbmi = new JCheckBoxMenuItem(new ShowFirewallStatusAction()); jcbmi.setState(StatusBarSettings.FIREWALL_DISPLAY_ENABLED.getValue()); jpm.add(jcbmi); // add 'Show Shared Files Count' menu item jcbmi = new JCheckBoxMenuItem(new ShowSharedFilesCountAction()); jcbmi.setState(StatusBarSettings.SHARED_FILES_DISPLAY_ENABLED.getValue()); jpm.add(jcbmi); // add 'Show Bandwidth Consumption' menu item jcbmi = new JCheckBoxMenuItem(new ShowBandwidthConsumptionAction()); jcbmi.setState(StatusBarSettings.BANDWIDTH_DISPLAY_ENABLED.getValue()); jpm.add(jcbmi); jpm.addSeparator(); // add 'Show Media Player' menu item jcbmi = new JCheckBoxMenuItem(new ShowMediaPlayerAction()); jcbmi.setState(PlayerSettings.PLAYER_ENABLED.getValue()); jpm.add(jcbmi); jpm.show(me.getComponent(), me.getX(), me.getY()); } } }; /** * Action for the 'Show Connection Quality' menu item. */ private class ShowConnectionQualityAction extends AbstractAction { public ShowConnectionQualityAction() { putValue(Action.NAME, GUIMediator.getStringResource ("STATUS_BAR_SHOW_CONNECTION_QUALITY")); } public void actionPerformed(ActionEvent e) { StatusBarSettings.CONNECTION_QUALITY_DISPLAY_ENABLED.invert(); refresh(); } } /** * Action for the 'Show Shared Files Count' menu item. */ private class ShowSharedFilesCountAction extends AbstractAction { public ShowSharedFilesCountAction() { putValue(Action.NAME, GUIMediator.getStringResource ("STATUS_BAR_SHOW_SHARED_FILES_COUNT")); } public void actionPerformed(ActionEvent e) { StatusBarSettings.SHARED_FILES_DISPLAY_ENABLED.invert(); refresh(); } } /** * Action for the 'Show Firewall Status' menu item. */ private class ShowFirewallStatusAction extends AbstractAction { public ShowFirewallStatusAction() { putValue(Action.NAME, GUIMediator.getStringResource ("STATUS_BAR_SHOW_FIREWALL_STATUS")); } public void actionPerformed(ActionEvent e) { StatusBarSettings.FIREWALL_DISPLAY_ENABLED.invert(); refresh(); } } /** * Action for the 'Show Bandwidth Consumption' menu item. */ private class ShowBandwidthConsumptionAction extends AbstractAction { public ShowBandwidthConsumptionAction() { putValue(Action.NAME, GUIMediator.getStringResource ("STATUS_BAR_SHOW_BANDWIDTH_CONSUMPTION")); } public void actionPerformed(ActionEvent e) { StatusBarSettings.BANDWIDTH_DISPLAY_ENABLED.invert(); refresh(); } } /** * Action for the 'Show Media Player' menu item. */ private class ShowMediaPlayerAction extends AbstractAction { public ShowMediaPlayerAction() { putValue(Action.NAME, GUIMediator.getStringResource ("STATUS_BAR_SHOW_MEDIA_PLAYER")); } public void actionPerformed(ActionEvent e) { GUIMediator.instance().setPlayerEnabled(!PlayerSettings.PLAYER_ENABLED.getValue()); } } /** * Custom component for displaying the number of shared files. */ private class SharedFilesLabel extends JLabel { /** * The height of this icon. */ private static final int _height = 20; /** * The width of this icon. */ private int _width = 26; private FontMetrics fm = null; private String _string = "0..."; private int _share; private int _pending; public Dimension getMinimumSize() { return getPreferredSize(); } public Dimension getPreferredSize() { return new Dimension(_width, _height); } /** * Updates the component with information about the sharing state. */ public void update(int share, int pending) { boolean shareChanged = share != _share; boolean pendingChanged = pending != _pending; _share = share; _pending = pending; // if no changes, return if (!(shareChanged || pendingChanged)) return; _string = GUIUtils.toLocalizedInteger(_share); if (!RouterService.getFileManager().isLoadFinished() || RouterService.getFileManager().isUpdating()) _string += "..."; if (fm != null) _width = fm.stringWidth(_string) + _height; revalidate(); repaint(); // update tooltip if (RouterService.getFileManager().isLoadFinished()) setToolTipText(GUIMediator.getStringResource("STATISTICS_SHARING_TOOLTIP") + " " + share + " " + GUIMediator.getStringResource("STATISTICS_FILES_TOOLTIP")); else //otherwise display as 'shared / total' setToolTipText(GUIMediator.getStringResource("STATISTICS_SHARING_TOOLTIP") + " " + share + " " + GUIMediator.getStringResource("STATISTICS_FILES_TOOLTIP_PENDING")); } /** * Paints the icon, and then paints the number of shared files on top of it. */ protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; RenderingHints rh = g2.getRenderingHints(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (fm == null) fm = g2.getFontMetrics(); // create string, set background color if (!RouterService.getFileManager().isLoadFinished() || RouterService.getFileManager().isUpdating()) { g2.setPaint(new Color(165, 165, 2)); if (!_string.endsWith("...")) _string += "..."; } else { g2.setPaint(new Color(2, 137, 2)); if (_string.endsWith("...")) _string = _string.substring(0, _string.length() - 3); } // figure out size int width = fm.stringWidth(_string) + _height; if (width != _width) { _width = width; revalidate(); } // draw the round rectangle RoundRectangle2D.Float rect = new RoundRectangle2D.Float(0, 0, _width-2, _height-2, _height, _height); g2.fill(rect); // stroke the rectangle g2.setColor(Color.black); g2.draw(rect); // then draw string g2.setColor(Color.white); g2.drawString(_string, (rect.width - fm.stringWidth(_string)) / 2f, (rect.height + fm.getAscent() - fm.getDescent()) / 2f); g2.setRenderingHints(rh); } } }