package org.limewire.ui.swing.statusbar; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.swing.Timer; import org.limewire.core.api.Application; import org.limewire.i18n.I18nMarker; import org.limewire.setting.evt.SettingEvent; import org.limewire.setting.evt.SettingListener; import org.limewire.ui.swing.components.HyperlinkButton; import org.limewire.ui.swing.settings.SwingUiSettings; import org.limewire.ui.swing.util.I18n; import org.limewire.ui.swing.util.LanguageUtils; import org.limewire.ui.swing.util.NativeLaunchUtils; import com.google.inject.Inject; import com.google.inject.Singleton; @Singleton public class ProStatusPanel extends HyperlinkButton implements SettingListener, ActionListener { private final Set<InvisibilityCondition> conditions = new HashSet<InvisibilityCondition>(); /** Default banner to use on non-English systems */ private static final Banner DEFAULT_BANNER = new Banner(new String[] { I18nMarker.marktr("For Turbo-Charged searches get LimeWire PRO."), "http://www.limewire.com/index.jsp/pro&21", "0.111111", I18nMarker.marktr("Want faster downloads? Get LimeWire PRO."), "http://www.limewire.com/index.jsp/pro&22", "0.111111", I18nMarker.marktr("Purchase LimeWire PRO to help us make downloads faster."), "http://www.limewire.com/index.jsp/pro&23", "0.111111", I18nMarker.marktr("For Turbo-Charged downloads get LimeWire PRO."), "http://www.limewire.com/index.jsp/pro&24", "0.111111", I18nMarker.marktr("For the best BitTorrent downloads, get LimeWire PRO."), "http://www.limewire.com/index.jsp/pro&25", "0.111111", I18nMarker.marktr("LimeWire PRO comes with FREE tech support. "), "http://www.limewire.com/index.jsp/pro&26", "0.111111", I18nMarker.marktr("For Turbo-Charged performance get LimeWire PRO."), "http://www.limewire.com/index.jsp/pro&27", "0.111111", I18nMarker.marktr("Keep the Internet open. Get LimeWire PRO."), "http://www.limewire.com/index.jsp/pro&28", "0.111111", I18nMarker.marktr("FREE updates and support - LimeWire PRO."), "http://www.limewire.com/index.jsp/pro&29", "0.111111" }); /** * banner of pro ads. * LOCKING: labels */ private Banner ads; /** * Map from pro ads to a label. */ private final Map<Ad,LabelURLPair> labels = Collections.synchronizedMap(new HashMap<Ad, LabelURLPair>()); /** * The currently displayed <tt>LabelURLPair</tt>. */ private LabelURLPair currentLabel; private boolean isInitialised = false; private final Application application; @Inject public ProStatusPanel(Application application) { this.application = application; setName("ProStatusPanel"); if (application.isProVersion()) { addCondition(InvisibilityCondition.IS_PRO); } } /** * Add a new visibility condition, will probably result * in the panel being hidden. */ public void addCondition(InvisibilityCondition condition) { conditions.add(condition); updateVisibility(); } /** * Remove a visibility condition. If there are none left the * panel will be shown. */ public void removeCondition(InvisibilityCondition condition) { conditions.remove(condition); updateVisibility(); } private void updateVisibility() { if (!isVisible() && !isInitialised && conditions.isEmpty()) { init(); isInitialised = true; } setVisible(conditions.isEmpty()); } private void init() { if (LanguageUtils.isEnglishLocale(LanguageUtils.getCurrentLocale())) { loadLabels(); SwingUiSettings.PRO_ADS.addSettingListener(this); } // if not English or loading from props failed, load default synchronized(labels) { if (labels.isEmpty()) { updateLabels(DEFAULT_BANNER); } assert !labels.isEmpty() : "couldn't load any pro banner!"; } addActionListener(this); // only build and start timer if there are labels to cycle through if (labels.size() > 1) { new Timer(30 * 1000, new LabelTimerListener()).start(); // Load first label handleLinkChange(); } } /** * Conditions that cause this panel to be hidden. * If any of these conditions are added to the panel * it will not be visible. */ public static enum InvisibilityCondition { NOT_FULLY_CONNECTED, PRO_ADD_SHOWN, IS_PRO ; } public void settingChanged(SettingEvent evt) { if (evt.getEventType() != SettingEvent.EventType.VALUE_CHANGED) return; loadLabels(); } private void loadLabels() { try { Banner b = new Banner(SwingUiSettings.PRO_ADS.get()); updateLabels(b); } catch (IllegalArgumentException bad) { return; } } private void updateLabels(Banner b) { synchronized(labels) { ads = b; labels.clear(); for (Ad ad : ads.getAllAds()) { String text = ad.getText(); text = I18n.tr(text); labels.put(ad,new LabelURLPair(text, ad.getURI())); } } } /** * @return the next <tt>LabelURLPair</tt> in the list */ private LabelURLPair getNextLabelURLPair() { synchronized(labels) { currentLabel = labels.get(ads.getAd()); } return currentLabel; } /** * Handle a change in the current <tt>LabelURLPair</tt> pair. */ private void handleLinkChange() { String label = getNextLabelURLPair().getLabel(); this.setText(label); } /** * Handles a click on the current link by opening the appropriate web * page. */ private void handleLinkClick() { NativeLaunchUtils.openURL(application.addClientInfoToUrl(currentLabel.getURL())); } @Override public void actionPerformed(ActionEvent e) { handleLinkClick(); } /** * Private class for handling a change in the link/label pair. */ private class LabelTimerListener implements ActionListener { public void actionPerformed(ActionEvent e) { ProStatusPanel.this.handleLinkChange(); } } /** * This class wraps a label for the link and the url to link to. */ private static final class LabelURLPair { /** * Constant for the label string for this pair. */ private final String LABEL_STRING; /** * Constant for the url for this pair. */ private final String URL; /** * Creates a new <tt>LabelURLPair</tt> instance with the * specified label and url. * * @param label the label for the link * @param url to url to link to */ private LabelURLPair(final String label, final String url) { LABEL_STRING = label; URL = url; } /** * Returns the label's text * previous implementation returned the text in html format * to simulate a hyperlink look; the new label provides the * framework to simulate this work at a substantial reduction * in memory and processor cost; the jvm treats any html as a * possible full blown document and sets up the structures to * process hyper text formatting for just these couple of words * every 30 seconds (no reuse either). Also, the old html link * wasn't truly clickable, we use a mouse listener to provide * mouse clicking action support; <font color=blue>LABEL_STRING</font> * would have provided the same effect (or affect :) * previous: return "<html><a href=\"\">"+LABEL_STRING+"</a></html>"; * * @return the label */ private String getLabel() { return LABEL_STRING; } /** * * @return the url to link to */ private String getURL() { return URL; } } }