package org.limewire.ui.swing.downloads;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.jdesktop.application.Application;
import org.jdesktop.application.Resource;
import org.limewire.core.api.URN;
import org.limewire.core.api.download.DownloadItem;
import org.limewire.core.api.download.DownloadListManager;
import org.limewire.core.settings.DownloadSettings;
import org.limewire.inject.LazySingleton;
import org.limewire.setting.evt.SettingEvent;
import org.limewire.setting.evt.SettingListener;
import org.limewire.ui.swing.downloads.table.DownloadTable;
import org.limewire.ui.swing.downloads.table.DownloadTableFactory;
import org.limewire.ui.swing.event.DownloadVisibilityEvent;
import org.limewire.ui.swing.settings.SwingUiSettings;
import org.limewire.ui.swing.tray.Notification;
import org.limewire.ui.swing.tray.TrayNotifier;
import org.limewire.ui.swing.util.GuiUtils;
import org.limewire.ui.swing.util.I18n;
import org.limewire.ui.swing.util.SwingUtils;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;
import com.google.inject.Inject;
import com.google.inject.Provider;
@LazySingleton
public class MainDownloadPanel extends JPanel {
public static final String NAME = "MainDownloadPanel";
private TrayNotifier notifier;
private DownloadMediator downloadMediator;
private boolean isInitialized = false;
private final Provider<DownloadTableFactory> downloadTableFactory;
private final DownloadListManager downloadListManager;
private final ArrayList<DownloadVisibilityListener> downloadVisibilityListeners = new ArrayList<DownloadVisibilityListener>();
@Resource private int preferredHeight;
private DownloadTable table;
/**
* Create the panel.
*/
@Inject
public MainDownloadPanel(Provider<DownloadTableFactory> downloadTableFactory,
DownloadMediator downloadMediator,
TrayNotifier notifier,
DownloadListManager downloadListManager) {
this.downloadMediator = downloadMediator;
this.downloadTableFactory = downloadTableFactory;
this.downloadListManager = downloadListManager;
this.notifier = notifier;
GuiUtils.assignResources(this);
int savedHeight = SwingUiSettings.DOWNLOAD_TRAY_SIZE.getValue();
int height = savedHeight == 0 ? preferredHeight : savedHeight;
setPreferredSize(new Dimension(getPreferredSize().width, height));
}
public void selectAndScrollTo(URN urn) {
table.selectAndScrollTo(urn);
if(getVisibleRect().height < table.getRowHeight()){
alertDownloadVisibilityListeners(true);
}
}
@Inject
public void register() {
downloadMediator.getDownloadList().addListEventListener(new VisibilityListListener());
DownloadSettings.ALWAYS_SHOW_DOWNLOADS_TRAY.addSettingListener(new SettingListener() {
@Override
public void settingChanged(SettingEvent evt) {
SwingUtils.invokeLater(new Runnable() {
@Override
public void run() {
updateVisibility(downloadMediator.getDownloadList());
}
});
}
});
//we have to eagerly initialize the table when the ALWAYS_SHOW_DOWNLOAD_TRAY setting
//is set to true on startup, otherwise the table space will be empty and the lines will
//be put in the first time a download comes in, which looks a little weird
if(DownloadSettings.ALWAYS_SHOW_DOWNLOADS_TRAY.getValue()) {
initialize();
}
}
public void addDownloadVisibilityListener(DownloadVisibilityListener listener){
downloadVisibilityListeners.add(listener);
}
public void removeDownloadVisibilityListener(DownloadVisibilityListener listener){
downloadVisibilityListeners.remove(listener);
}
//Lazily initialized - initialize() is called when the first downloadItem is added to the list.
private void initialize() {
isInitialized = true;
setLayout(new BorderLayout());
table = downloadTableFactory.get().create(downloadMediator.getDownloadList());
table.setTableHeader(null);
JScrollPane pane = new JScrollPane(table);
pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
add(pane, BorderLayout.CENTER);
// handle individual completed downloads
initializeDownloadListeners(downloadListManager);
}
public List<DownloadItem> getSelectedDownloadItems(){
return table.getSelectedItems();
}
public int getDefaultPreferredHeight(){
return preferredHeight;
}
private void initializeDownloadListeners(final DownloadListManager downloadListManager) {
// handle individual completed downloads
downloadListManager.addPropertyChangeListener(new DownloadPropertyListener());
}
private class DownloadPropertyListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals(DownloadListManager.DOWNLOAD_COMPLETED)) {
final DownloadItem downloadItem = (DownloadItem) event.getNewValue();
notifier.showMessage(new Notification(I18n.tr("Download Complete"), downloadItem.getFileName(),
new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
ActionMap map = Application.getInstance().getContext().getActionManager()
.getActionMap();
map.get("restoreView").actionPerformed(e);
if (downloadItem.isLaunchable()) {
DownloadItemUtils.launch(downloadItem);
}
}
}));
}
}
}
/**
* Initializes the download panel contents the first time the list changes (when the first DownloadItem is added).
* Adjusts visibility of the panel depending on whether or not the list is empty.
*/
private class VisibilityListListener implements ListEventListener<DownloadItem> {
@Override
public void listChanged(ListEvent<DownloadItem> listChanges) {
EventList sourceList = listChanges.getSourceList();
updateVisibility(sourceList);
}
}
private void updateVisibility(EventList sourceList) {
if(!isInitialized){
initialize();
}
int downloadCount = sourceList.size();
if(DownloadSettings.ALWAYS_SHOW_DOWNLOADS_TRAY.getValue() && !isVisible()){
alertDownloadVisibilityListeners(true);
} else if(DownloadSettings.ALWAYS_SHOW_DOWNLOADS_TRAY.getValue()){
//Do nothing - it is already set.
return;
} else if (downloadCount == 0 && isVisible()) {
alertDownloadVisibilityListeners(false);
} else if (downloadCount > 0 && !isVisible()) {
alertDownloadVisibilityListeners(true);
}
}
/**
* Ignores DownloadSettings.ALWAYS_SHOW_DOWNLOADS_TRAY
*/
private void alertDownloadVisibilityListeners(boolean isVisible) {
for (DownloadVisibilityListener listener : downloadVisibilityListeners) {
listener.updateVisibility(new DownloadVisibilityEvent(isVisible));
}
}
}