package org.limewire.ui.swing.search; import java.awt.Color; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import net.miginfocom.swing.MigLayout; import org.jdesktop.application.Resource; import org.limewire.core.api.library.RemoteLibraryManager; import org.limewire.core.api.search.browse.BrowseSearch; import org.limewire.core.api.search.browse.BrowseStatus.BrowseState; import org.limewire.friend.api.Friend; import org.limewire.friend.api.FriendConnectionEvent; import org.limewire.friend.api.FriendConnectionEvent.Type; import org.limewire.listener.EventBean; import org.limewire.listener.EventListener; import org.limewire.listener.ListenerSupport; import org.limewire.listener.SwingEDTEvent; import org.limewire.ui.swing.components.Disposable; import org.limewire.ui.swing.components.HTMLLabel; import org.limewire.ui.swing.components.HyperlinkButton; import org.limewire.ui.swing.components.MessageComponent; import org.limewire.ui.swing.components.decorators.MessageDecorator; import org.limewire.ui.swing.friends.chat.ChatMediator; import org.limewire.ui.swing.search.model.SearchResultsModel; import org.limewire.ui.swing.util.GuiUtils; import org.limewire.ui.swing.util.I18n; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.assistedinject.Assisted; /** * Replaces the search results when a browse fails. Must be disposed. */ public class BrowseFailedMessagePanel extends JPanel implements Disposable{ @Resource private Font chatFont; @Resource private Color chatForeground; private final SearchResultsModel searchResultsModel; private final Provider<ChatMediator> chatMediator; private final EventBean<FriendConnectionEvent> connectionEventBean; private EventListener<FriendConnectionEvent> connectionListener; private ListenerSupport<FriendConnectionEvent> connectionSupport; private final RemoteLibraryManager remoteLibraryManager; private final Provider<MessageDecorator> messageDecoratorProvider; private BrowseSearch browseSearch; private boolean isInitialized = false; private BrowseState state; private List<Friend> friends; @Inject public BrowseFailedMessagePanel(EventBean<FriendConnectionEvent> connectionEventBean, Provider<ChatMediator> chatMediator, RemoteLibraryManager remoteLibraryManager, Provider<MessageDecorator> messageDecoratorProvider, @Assisted SearchResultsModel searchResultsModel) { GuiUtils.assignResources(this); this.connectionEventBean = connectionEventBean; this.chatMediator = chatMediator; this.searchResultsModel = searchResultsModel; this.remoteLibraryManager = remoteLibraryManager; this.messageDecoratorProvider = messageDecoratorProvider; } public void update(BrowseState state, BrowseSearch browseSearch, List<Friend> friends){ this.state = state; this.browseSearch = browseSearch; this.friends = friends; if(!isInitialized){ isInitialized = true; initialize(); } updateLabel(); } @Inject void registerListener(ListenerSupport<FriendConnectionEvent> connectionSupport) { this.connectionSupport = connectionSupport; //TODO: this should probably be handled in the BrowseSearch models eventually connectionListener = new EventListener<FriendConnectionEvent>() { @Override @SwingEDTEvent public void handleEvent(FriendConnectionEvent event) { if (isInitialized) { updateLabel(); repaint(); } } }; connectionSupport.addListener(connectionListener); } private void initialize() { setLayout(new MigLayout("insets 0, gap 0, fill")); } private void updateLabel(){ removeAll(); add(createMessageComponent(getLabelText()), "pos 0.50al 0.4al"); add(createBottomComponent(), "pos 1al 1al"); } /** * Floating message in the FriendLibrary. This displays feedback to the user * as to what state their friend is in when no files are displayed. */ private JComponent createMessageComponent(String text) { MessageComponent messageComponent = new MessageComponent(); messageDecoratorProvider.get().decorateGrayMessage(messageComponent); JLabel message = new JLabel(text); messageComponent.decorateHeaderLabel(message); messageComponent.addComponent(message, hasRefresh() ? "" : "wrap"); if (hasRefresh()) { HyperlinkButton refresh = new HyperlinkButton(I18n.tr("Retry")); refresh.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { BrowseFailedMessagePanel.this.setVisible(false); new DefaultSearchRepeater(browseSearch, searchResultsModel).refresh(); } }); messageComponent.decorateHeaderLink(refresh); messageComponent.addComponent(refresh, "gapleft 5, wrap"); } if(state == BrowseState.NO_FRIENDS_SHARING || state == BrowseState.OFFLINE){ String subText = null; if (isUserOffline()) { if(state == BrowseState.NO_FRIENDS_SHARING){ subText = I18n.tr("When you sign on to LimeWire, your friends' files will appear here."); } else {//BrowseState.OFFLINE subText = I18n.tr("When you sign on to LimeWire, your friend's files will appear here."); } } else { subText = I18n.tr("When they sign on to LimeWire and share with you, their files will appear here."); } JLabel subMessage = new JLabel(subText); messageComponent.decorateSubLabel(subMessage); messageComponent.addComponent(subMessage, ""); } return messageComponent; } private boolean hasRefresh(){ return state != BrowseState.OFFLINE && state != BrowseState.NO_FRIENDS_SHARING; } private JComponent createBottomComponent(){ if(state == BrowseState.NO_FRIENDS_SHARING && !isUserOffline()){ String text; if(areFriendsSignedOnToLimeWire()){ text = I18n.tr("<HTML><A href=\"\">Chat</A> and tell them to share.</HTML>"); } else { text = I18n.tr("<HTML><A href=\"\">Chat</A> and tell them to sign on.</HTML>"); } HTMLLabel message = new HTMLLabel(text); message.setHtmlFont(chatFont); message.setHtmlForeground(chatForeground); message.addHyperlinkListener(new HyperlinkListener(){ @Override public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { chatMediator.get().setVisible(true); } } }); JPanel panel = new JPanel(new MigLayout("insets 0, gap 0, novisualpadding")); panel.add(message, "gapright 5"); return panel; } return new JLabel(); } private String getLabelText() { if (isUserOffline() && (state == BrowseState.NO_FRIENDS_SHARING || state == BrowseState.OFFLINE)) { return getUserOfflineText(); } if (state == BrowseState.NO_FRIENDS_SHARING) { if (areFriendsSignedOnToLimeWire()){ return I18n.tr("No friends are sharing with you"); } return I18n.tr("No friends are on LimeWire"); } if (state == BrowseState.OFFLINE) { if (isSingleBrowse()) { return I18n.tr("{0} is not signed on to LimeWire.", getSingleFriendName()); } else { return I18n.tr("These people are not signed on to LimeWire."); } } if (isSingleBrowse()) { return I18n.tr("There was a problem browsing {0}.", getSingleFriendName()); } else { return I18n.tr("There was a problem viewing these people."); } } private boolean isUserOffline(){ return connectionEventBean.getLastEvent() == null || connectionEventBean.getLastEvent().getType() != Type.CONNECTED; } private boolean isSingleBrowse(){ return friends.size() == 1; } public boolean areFriendsSignedOnToLimeWire(){ return remoteLibraryManager.getFriendLibraryList().size() != 0; } private String getSingleFriendName(){ return friends.get(0).getRenderName(); } private String getUserOfflineText(){ return I18n.tr("You are offline."); } public void dispose() { if (connectionSupport != null) { connectionSupport.removeListener(connectionListener); } } }