package org.limewire.ui.swing.search;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.application.Resource;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.painter.Painter;
import org.limewire.core.api.search.SearchDetails.SearchType;
import org.limewire.core.api.search.browse.BrowseStatus;
import org.limewire.core.api.search.browse.BrowseStatus.BrowseState;
import org.limewire.friend.api.Friend;
import org.limewire.ui.swing.action.AbstractAction;
import org.limewire.ui.swing.components.Disposable;
import org.limewire.ui.swing.components.HyperlinkButton;
import org.limewire.ui.swing.components.IconButton;
import org.limewire.ui.swing.components.LimePopupDialog;
import org.limewire.ui.swing.friends.refresh.AllFriendsRefreshManager;
import org.limewire.ui.swing.friends.refresh.BrowseRefreshStatus;
import org.limewire.ui.swing.friends.refresh.BrowseRefreshStatusListener;
import org.limewire.ui.swing.painter.ComponentBackgroundPainter;
import org.limewire.ui.swing.painter.BorderPainter.AccentType;
import org.limewire.ui.swing.search.model.SearchResultsModel;
import org.limewire.ui.swing.util.GuiUtils;
import org.limewire.ui.swing.util.I18n;
/**
* Shows status updates for browses. Must be disposed.
*/
public class BrowseStatusPanel extends JXPanel implements Disposable{
private BrowseStatus status;
private JButton warningButton;
private JXPanel refreshPanel;
private JButton refreshButton;
private JLabel updatesLabel;
@Resource private Icon warningIcon;
@Resource private int arcWidth;
@Resource private int arcHeight;
@Resource private Color innerBorder;
@Resource private Color innerBackground;
@Resource private Color bevelLeft;
@Resource private Color bevelTop1;
@Resource private Color bevelTop2;
@Resource private Color bevelRight;
@Resource private Color bevelBottom;
@Resource private Font font;
@Resource private Color foreground;
@Resource private Color headerForeground;
@Resource private Font headerFont;
private final SearchResultsModel searchResultsModel;
private final AllFriendsRefreshManager allFriendsRefreshManager;
private BrowseRefreshStatusListener browseRefreshStatusListener;
public BrowseStatusPanel(SearchResultsModel searchResultsModel, AllFriendsRefreshManager allFriendsRefreshManager){
GuiUtils.assignResources(this);
this.searchResultsModel = searchResultsModel;
this.allFriendsRefreshManager = allFriendsRefreshManager;
setOpaque(false);
initializeComponents();
if(isAllFriendsBrowse()){
initializeAllFriendsListener();
}
layoutComponents();
update();
}
private void initializeAllFriendsListener(){
browseRefreshStatusListener = new BrowseRefreshStatusListener(){
@Override
public void statusChanged(final BrowseRefreshStatus status) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
refreshPanel.setVisible(status != BrowseRefreshStatus.REFRESHED);
}
});
}
};
allFriendsRefreshManager.addBrowseRefreshStatusListener(browseRefreshStatusListener);
}
private void initializeComponents() {
warningButton = new IconButton(warningIcon);
warningButton.addActionListener(new WarningAction());
warningButton.setVisible(false);
refreshPanel = new JXPanel();
refreshPanel.setOpaque(false);
refreshPanel.setBackgroundPainter(createRefreshBackgroundPainter());
refreshPanel.setVisible(false);
updatesLabel = new JLabel(I18n.tr("There are updates!"));
updatesLabel.setFont(font);
updatesLabel.setForeground(foreground);
refreshButton = new HyperlinkButton(new RefreshAction());
refreshButton.setFont(font);
}
private void layoutComponents() {
refreshPanel.setLayout(new MigLayout("insets 6 8 6 8, gap 0, novisualpadding, aligny 50%, fill"));
refreshPanel.add(updatesLabel);
refreshPanel.add(refreshButton, "gapleft 3");
setLayout(new MigLayout("insets 0, gap 0, novisualpadding, filly"));
add(warningButton);
add(refreshPanel);
}
public void setBrowseStatus(BrowseStatus status) {
this.status = status;
update();
}
private void update() {
if (!isAllFriendsBrowse()) {
warningButton.setVisible(status != null && status.getState() == BrowseState.PARTIAL_FAIL);
refreshPanel.setVisible(status != null && status.getState() == BrowseState.UPDATED);
}
}
private void showFailedBrowses(){
//TODO: present this properly
List<String> friends = new ArrayList<String>();
List<String> p2pUsers = new ArrayList<String>();
for(Friend person : status.getFailedFriends()){
if(person.isAnonymous()){
p2pUsers.add(person.getRenderName());
} else {
friends.add(person.getRenderName());
}
}
JXPanel centerPanel = new JXPanel(new MigLayout("insets 0 5 5 5, gap 0, novisualpadding, fill"));
if(friends.size() > 0){
centerPanel.add(createHeaderLabel(I18n.tr("Friends")), "gaptop 5, wrap");
}
for (String name : friends){
centerPanel.add(createItemLabel(name), "wrap");
}
if(p2pUsers.size() > 0){
centerPanel.add(createHeaderLabel(I18n.tr("P2P Users")), "gaptop 5, wrap");
}
for (String name : p2pUsers){
centerPanel.add(createItemLabel(name), "wrap");
}
LimePopupDialog popup = new LimePopupDialog(I18n.tr("Unable to Browse"), centerPanel);
popup.showPopup(warningButton, 0, 0);
}
private JLabel createHeaderLabel(String text){
JLabel header = new JLabel(text);
header.setForeground(headerForeground);
header.setFont(headerFont);
return header;
}
private JLabel createItemLabel(String text){
JLabel item = new JLabel(text);
item.setForeground(foreground);
item.setFont(font);
return item;
}
private Painter<JXPanel> createRefreshBackgroundPainter() {
return new ComponentBackgroundPainter<JXPanel>(innerBackground, innerBorder, bevelLeft, bevelTop1,
bevelTop2, bevelRight,bevelBottom, arcWidth, arcHeight,
AccentType.NONE);
}
private boolean isAllFriendsBrowse(){
return searchResultsModel.getSearchType() == SearchType.ALL_FRIENDS_BROWSE;
}
private class RefreshAction extends AbstractAction {
public RefreshAction(){
super(I18n.tr("Refresh"));
}
@Override
public void actionPerformed(ActionEvent e) {
if(isAllFriendsBrowse()){
allFriendsRefreshManager.refresh();
} else {
new DefaultSearchRepeater(status.getBrowseSearch(), searchResultsModel).refresh();
}
}
}
private class WarningAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
showFailedBrowses();
}
}
@Override
public void dispose() {
if(browseRefreshStatusListener != null){
allFriendsRefreshManager.removeBrowseRefreshStatusListener(browseRefreshStatusListener);
browseRefreshStatusListener = null;
}
}
}