// BlogBridge -- RSS feed reader, manager, and web based service // Copyright (C) 2002-2006 by R. Pito Salas // // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software Foundation; // either version 2 of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with this program; // if not, write to the Free Software Foundation, Inc., 59 Temple Place, // Suite 330, Boston, MA 02111-1307 USA // // Contact: R. Pito Salas // mailto:pitosalas@users.sourceforge.net // More information: about BlogBridge // http://www.blogbridge.com // http://sourceforge.net/projects/blogbridge // // $Id: DownloadsProgressDialog.java,v 1.11 2006/12/13 19:59:28 spyromus Exp $ // package com.salas.bb.updates.ui; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.uif.AbstractDialog; import com.jgoodies.uif.util.SystemUtils; import com.salas.bb.updates.Location; import com.salas.bb.utils.Constants; import com.salas.bb.utils.i18n.Strings; import com.salas.bb.utils.net.IStreamProgressListener; import com.salas.bb.utils.net.URLInputStream; import com.salas.bb.utils.uif.BBFormBuilder; import com.salas.bb.utils.uif.ComponentsFactory; import javax.swing.*; import java.awt.*; import java.awt.event.WindowEvent; import java.io.IOException; import java.text.MessageFormat; import java.util.List; /** * Downloads progress dialog. */ public class DownloadsProgressDialog extends AbstractDialog { private IStreamProgressListener progressListener; private Location[] locations; private int currentDownload; private long currentRead; private long currentTotal; private long overallTotal; private long overallRead; private JProgressBar prOverall; private JLabel lbCurrent; private JProgressBar prCurrent; private JButton btnCancel; private JButton btnExit; private JTextArea lbReport; private JPanel pnlReport; private JCheckBox chStartInstallation; private boolean finished; private boolean exitBlogBridge; private Runnable actInstall; private Runnable actCancel; private Runnable actExit; /** * Creates downloads progress dialog. * * @param frame parent frame. * @param aLocations list of locations which are going to be downloaded. */ public DownloadsProgressDialog(Frame frame, Location[] aLocations) { super(frame, Strings.message("updates.downloading.dialog.title"), false); locations = aLocations; currentDownload = -1; progressListener = new ProgressListener(); finished = false; exitBlogBridge = false; overallRead = 0; overallTotal = 0; for (int i = 0; i < aLocations.length; i++) overallTotal += aLocations[i].getSize(); initComponents(); pack(); enableEvents(AWTEvent.WINDOW_EVENT_MASK); } /** * Returns <code>TRUE</code> if a user chose to exit BB. * * @return <code>TRUE</code> to exit. */ public boolean isExitBlogBridge() { return exitBlogBridge; } /** * Handles window events depending on the state of the <code>defaultCloseOperation</code> * property. * * @see #setDefaultCloseOperation */ protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_OPENED) pack(); } /** * Opens the dialog. * * @param installAction installation code. * @param cancelAction cancelling code. * @param exitAction exiting code. */ public void open(Runnable installAction, Runnable cancelAction, Runnable exitAction) { actInstall = installAction; actCancel = cancelAction; actExit = exitAction; super.open(); } /** * Creates page content. * * @return content. */ protected JComponent buildContent() { JPanel panel = new JPanel(new BorderLayout()); panel.add(createMainPanel(), BorderLayout.CENTER); panel.add(createButtonBar(), BorderLayout.SOUTH); return panel; } /** * Creates main panel. * * @return main panel. */ private Component createMainPanel() { BBFormBuilder builder = new BBFormBuilder("max(p;200dlu)"); builder.setDefaultDialogBorder(); String msg = Strings.message(SystemUtils.IS_OS_MAC ? "updates.downloading.wording.mac" : "updates.downloading.wording"); builder.appendRow("pref:grow"); builder.append(ComponentsFactory.createWrappedMultilineLabel(msg), 1); builder.appendUnrelatedComponentsGapRow(2); builder.append(Strings.message("updates.downloading.overall.progress"), 1); builder.append(prOverall); builder.appendUnrelatedComponentsGapRow(2); builder.append(lbCurrent); builder.append(prCurrent); builder.append(pnlReport); builder.append(chStartInstallation); builder.appendUnrelatedComponentsGapRow(2); return builder.getPanel(); } /** Initializes components. */ private void initComponents() { lbReport = ComponentsFactory.createWrappedMultilineLabel(""); BBFormBuilder builder = new BBFormBuilder("0:grow"); builder.appendRelatedComponentsGapRow(1); builder.append(lbReport); pnlReport = builder.getPanel(); pnlReport.setVisible(false); prOverall = new JProgressBar(); lbCurrent = new JLabel(); prCurrent = new JProgressBar(); prOverall.setMinimum(0); prOverall.setMaximum(100); prOverall.setValue(0); prCurrent.setMinimum(0); prCurrent.setMaximum(100); chStartInstallation = ComponentsFactory.createCheckBox(Strings.message("updates.downloading.close.blogbridge.and.install.new.version")); chStartInstallation.setVisible(false); nextDownload(); } /** * Creates button bar. * * @return button bar. */ private Component createButtonBar() { btnExit = createOKButton(false); btnExit.setText(Strings.message("updates.downloading.exit")); btnExit.setVisible(false); btnCancel = createCancelButton(); ButtonBarBuilder builder = new ButtonBarBuilder(); builder.getPanel().setBorder(Constants.DIALOG_BUTTON_BAR_BORDER); builder.addGlue(); builder.addFixed(btnExit); builder.addRelatedGap(); builder.addFixed(btnCancel); return builder.getPanel(); } /** * Returns progress listener which is going to listen for downloads. * * @return listener. */ public IStreamProgressListener getProgressListener() { return progressListener; } /** * Switches controls to */ public void nextDownload() { SwingUtilities.invokeLater(new Runnable() { public void run() { currentDownload++; if (currentDownload < locations.length) { resetCurrentProgress(); setCurrentLabel(locations[currentDownload].getDescription()); } else { prCurrent.setValue(100); btnCancel.setText(Strings.message("updates.downloading.close")); } } }); } /** * Resets the position of currently downloaded file progress. */ private void resetCurrentProgress() { prCurrent.setValue(0); currentRead = 0; } /** * Sets the downloading details label. * * @param aDescription description. */ private void setCurrentLabel(String aDescription) { lbCurrent.setText(MessageFormat.format( Strings.message("updates.downloading.status"), new Object[] { aDescription })); } /** * Invoked when downloading starts. Can be invoked several time per * single download. * * @param aLength length of resource. */ private void onDownloadStarted(final long aLength) { currentTotal = aLength; } /** * Invoked when download finishes with error. */ private void onDownloadFailed() { onDownloadFinished(); } /** * Invoked when download finishes successfully. */ private void onDownloadFinished() { SwingUtilities.invokeLater(new Runnable() { public void run() { prCurrent.setValue(prCurrent.getMaximum()); } }); } /** * Invoked when some bytes have been read. * * @param aBytes number of bytes read. */ private void onRead(final long aBytes) { SwingUtilities.invokeLater(new Runnable() { public void run() { overallRead += aBytes; currentRead += aBytes; prCurrent.setValue((int)(currentRead * 100 / currentTotal)); prOverall.setValue((int)(overallRead * 100 / overallTotal)); } }); } public void doAccept() { super.doAccept(); actExit.run(); } public synchronized void doCancel() { if (finished) { super.doAccept(); if (shouldStartInstallation()) actInstall.run(); } else { super.doCancel(); actCancel.run(); } } /** * Reports complete download status. * * @param aSuccessful list of successful downloads. * @param aFailed list of failed downloads. */ public synchronized void allDone(List aSuccessful, List aFailed) { String msg; int sucSize = aSuccessful.size(); int failSize = aFailed.size(); if (sucSize > 0) { msg = MessageFormat.format(Strings.message("updates.downloading.successfully.downloaded.0.to.your.desktop"), new Object[] { (sucSize == 1) ? Strings.message("updates.downloading.package") : MessageFormat.format(Strings.message("updates.downloading.0.packages"), new Object[] { new Integer(sucSize) }) }); } else msg = ""; if (failSize > 0) { msg += MessageFormat.format(Strings.message("updates.downloading.failed.to.download.0.packages"), new Object[] { new Integer(failSize) }); } lbReport.setText(msg); pnlReport.setVisible(true); Location mainPackage = Location.getMainPackage(aSuccessful); if (SystemUtils.IS_OS_WINDOWS && mainPackage != null) { chStartInstallation.setVisible(true); } else { btnExit.setVisible(true); } pack(); finished = true; } /** * Returns <code>TRUE</code> if user is willing to start installation. * * @return <code>TRUE</code> if user is willing to start installation. */ public boolean shouldStartInstallation() { return chStartInstallation.isSelected(); } /** * Stream progress listener which is used to update dialog progress bars. */ private class ProgressListener implements IStreamProgressListener { /** * Indicates the the source is being connected. * * @param source source. */ public void connecting(URLInputStream source) { } /** * Indicates that the source has been successfully connected. * * @param source source. * @param length length of the resource (-1 if unknown). */ public void connected(URLInputStream source, long length) { onDownloadStarted(length); } /** * Indicates that there's an error happened during reading of stream. * (We already did attempts to recover). * * @param source source. * @param ex cause of error. */ public void errored(URLInputStream source, IOException ex) { onDownloadFailed(); } /** * Indicates that the stream has been finished. * * @param source source. */ public void finished(URLInputStream source) { onDownloadFinished(); } /** * Indicates that some bytes has been read. * * @param source source. * @param bytes bytes. */ public void read(URLInputStream source, long bytes) { onRead(bytes); } } }