/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ /* * MultipleDownloadPanel.java * * Created on 13.07.2011, 11:57:37 */ package de.cismet.tools.gui.downloadmanager; import org.apache.log4j.Logger; import org.openide.util.NbBundle; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.SystemColor; import java.awt.geom.Path2D; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Observable; import java.util.Observer; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JPanel; /** * A subclass of JPanel which visualises one MultipleDownload. * * @author jweintraut * @version $Revision$, $Date$ */ public class MultipleDownloadPanel extends javax.swing.JPanel implements Observer { //~ Static fields/initializers --------------------------------------------- private static final Logger LOG = Logger.getLogger(MultipleDownloadPanel.class); //~ Instance fields -------------------------------------------------------- private Map<Download, JPanel> downloadsInSingleDownloadsPanel = new HashMap<Download, JPanel>(); private MultipleDownload download; private JPanel pnlSingleDownloads; private boolean isSingleDownloadsPanelShown; // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel lblIcon; private javax.swing.JLabel lblMessage; private javax.swing.JLabel lblTitle; private javax.swing.JMenuItem mniRemove; private javax.swing.JPopupMenu popContextMenu; private javax.swing.JProgressBar prbProgress; private javax.swing.JSeparator sepDownloadPanels; private javax.swing.JSeparator sepSingleDownloadsPanel; private javax.swing.JToggleButton tbtDownloads; // End of variables declaration//GEN-END:variables //~ Constructors ----------------------------------------------------------- /** * Creates new form MultipleDownloadPanel. * * @param download The MultipleDownload object to visualise. */ public MultipleDownloadPanel(final MultipleDownload download) { this.download = download; initComponents(); updateComponents(); initSingleDownloadsPanel(); } //~ Methods ---------------------------------------------------------------- /** * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The * content of this method is always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; sepSingleDownloadsPanel = new javax.swing.JSeparator(); popContextMenu = new javax.swing.JPopupMenu(); mniRemove = new javax.swing.JMenuItem(); lblIcon = new javax.swing.JLabel(); lblTitle = new javax.swing.JLabel(); lblMessage = new javax.swing.JLabel(); prbProgress = new javax.swing.JProgressBar(); sepDownloadPanels = new javax.swing.JSeparator(); tbtDownloads = new javax.swing.JToggleButton(); mniRemove.setText(org.openide.util.NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.mniRemove.text")); // NOI18N mniRemove.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(final java.awt.event.ActionEvent evt) { mniRemoveActionPerformed(evt); } }); popContextMenu.add(mniRemove); setComponentPopupMenu(popContextMenu); setMaximumSize(new java.awt.Dimension(2147483647, 54)); setMinimumSize(new java.awt.Dimension(193, 54)); addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mouseClicked(final java.awt.event.MouseEvent evt) { formMouseClicked(evt); } }); setLayout(new java.awt.GridBagLayout()); lblIcon.setIcon(new javax.swing.ImageIcon( getClass().getResource("/de/cismet/tools/gui/downloadmanager/documenttypes/multiple_closed.png"))); // NOI18N lblIcon.setText(org.openide.util.NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.lblIcon.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridheight = 2; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); add(lblIcon, gridBagConstraints); lblTitle.setFont(new java.awt.Font("Tahoma", 0, 14)); lblTitle.setText(download.getTitle()); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); add(lblTitle, gridBagConstraints); lblMessage.setBackground(new java.awt.Color(255, 102, 0)); lblMessage.setText(org.openide.util.NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.lblMessage.text")); // NOI18N lblMessage.setMaximumSize(new java.awt.Dimension(32767, 15)); lblMessage.setMinimumSize(new java.awt.Dimension(10, 15)); lblMessage.setPreferredSize(new java.awt.Dimension(8, 15)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); add(lblMessage, gridBagConstraints); prbProgress.setMaximum(download.getDownloadsTotal()); prbProgress.setBorderPainted(false); prbProgress.setMaximumSize(new java.awt.Dimension(32767, 15)); prbProgress.setMinimumSize(new java.awt.Dimension(10, 15)); prbProgress.setPreferredSize(new java.awt.Dimension(146, 15)); prbProgress.setString(org.openide.util.NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.prbProgress.string")); // NOI18N prbProgress.setStringPainted(true); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); add(prbProgress, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.gridwidth = 3; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; add(sepDownloadPanels, gridBagConstraints); tbtDownloads.setIcon(new javax.swing.ImageIcon( getClass().getResource("/de/cismet/tools/gui/downloadmanager/res/listDownloads.png"))); // NOI18N tbtDownloads.setText(org.openide.util.NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.tbtDownloads.text")); // NOI18N tbtDownloads.setBorderPainted(false); tbtDownloads.setContentAreaFilled(false); tbtDownloads.setFocusPainted(false); tbtDownloads.setSelectedIcon(new javax.swing.ImageIcon( getClass().getResource("/de/cismet/tools/gui/downloadmanager/res/listDownloads_selected.png"))); // NOI18N tbtDownloads.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(final java.awt.event.ActionEvent evt) { tbtDownloadsActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridheight = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); add(tbtDownloads, gridBagConstraints); } // </editor-fold>//GEN-END:initComponents /** * The action listener for the more button. * * @param evt An action event. */ private void tbtDownloadsActionPerformed(final java.awt.event.ActionEvent evt) { //GEN-FIRST:event_tbtDownloadsActionPerformed if (isSingleDownloadsPanelShown) { hideSingleDownloads(); } else { showSingleDownloads(); } } //GEN-LAST:event_tbtDownloadsActionPerformed /** * DOCUMENT ME! * * @param evt DOCUMENT ME! */ private void formMouseClicked(final java.awt.event.MouseEvent evt) { //GEN-FIRST:event_formMouseClicked if (evt.getClickCount() > 1) { if (download.getCaughtException() != null) { DownloadManagerDialog.getInstance().showTheExceptionDialog(download); } else if (download.getDownloadsTotal() > 0) { if (isSingleDownloadsPanelShown) { hideSingleDownloads(); } else { showSingleDownloads(); } } } } //GEN-LAST:event_formMouseClicked /** * DOCUMENT ME! * * @param evt DOCUMENT ME! */ private void mniRemoveActionPerformed(final java.awt.event.ActionEvent evt) { //GEN-FIRST:event_mniRemoveActionPerformed DownloadManager.instance().removeDownload(download); } //GEN-LAST:event_mniRemoveActionPerformed /** * As soon as a download changes its state, this method is called by the download (Observer pattern). * * @param o The Observable which called the method. * @param arg The arguments specified by the Observable. */ @Override public void update(final Observable o, final Object arg) { if ((o == null) || !(o.equals(download))) { return; } updateComponents(); revalidate(); repaint(); } /** * Updates the components according to the new state of a download. */ private void updateComponents() { switch (download.getStatus()) { case WAITING: { if (download instanceof BackgroundTaskMultipleDownload) { lblMessage.setVisible(false); prbProgress.setIndeterminate(true); prbProgress.setString(NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.prbProgress.string.waiting.BackgroundTaskMultipleDownload")); prbProgress.setVisible(true); } else { mniRemove.setEnabled(true); prbProgress.setVisible(false); lblMessage.setVisible(true); } break; } case RUNNING: { lblMessage.setVisible(false); mniRemove.setEnabled(false); lblTitle.setForeground(SystemColor.textText); prbProgress.setVisible(true); // set the maximum of prbProgress because it is now known for BackgroundTaskMultipleDownload prbProgress.setMaximum(download.getDownloadsTotal()); if (download.getDownloadsCompleted() == 0) { prbProgress.setIndeterminate(true); prbProgress.setString(NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.prbProgress.string.running.allRunning")); } else { prbProgress.setIndeterminate(false); prbProgress.setString(NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.prbProgress.string.running", download.getDownloadsCompleted(), download.getDownloadsTotal())); prbProgress.setValue(download.getDownloadsCompleted()); } break; } case RUNNING_WITH_ERROR: { lblMessage.setVisible(false); mniRemove.setEnabled(false); lblTitle.setForeground(SystemColor.textText); prbProgress.setVisible(true); prbProgress.setString(NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.prbProgress.string.running_with_error", download.getDownloadsCompleted(), download.getDownloadsTotal(), download.getDownloadsErroneous())); prbProgress.setValue(download.getDownloadsCompleted()); prbProgress.setBackground(Color.pink); setBackground(Color.pink); break; } case COMPLETED: { prbProgress.setVisible(false); mniRemove.setEnabled(true); lblTitle.setForeground(SystemColor.textInactiveText); download.deleteObserver(this); lblMessage.setVisible(true); lblMessage.setText(NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.lblMessage.text.completed", download.getDownloadsCompleted())); break; } case COMPLETED_WITH_ERROR: { prbProgress.setVisible(false); mniRemove.setEnabled(true); lblTitle.setForeground(SystemColor.textInactiveText); setBackground(Color.pink); download.deleteObserver(this); lblMessage.setVisible(true); lblMessage.setText(NbBundle.getMessage( MultipleDownloadPanel.class, "MultipleDownloadPanel.lblMessage.text.completed_with_error", download.getDownloadsCompleted(), download.getDownloadsErroneous())); break; } } } /** * Initialises the panel which shows the single downloads. */ private void initSingleDownloadsPanel() { if (pnlSingleDownloads != null) { return; } pnlSingleDownloads = new JPanel(); pnlSingleDownloads.setLayout(new BoxLayout(pnlSingleDownloads, BoxLayout.PAGE_AXIS)); addDownloadsToPnlSingleDownloads(download.getDownloads()); } /** * Shows the panel visualising the single downloads. */ private void showSingleDownloads() { if (isSingleDownloadsPanelShown) { return; } tbtDownloads.setSelected(true); lblIcon.setIcon(new ImageIcon( getClass().getResource("/de/cismet/tools/gui/downloadmanager/documenttypes/fallback_multiple.png"))); remove(sepDownloadPanels); final GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = 1; constraints.gridy = 2; constraints.gridwidth = 2; constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 1.0; constraints.weighty = 1.0; add(sepDownloadPanels, constraints); constraints.gridx = 0; constraints.gridy = 3; constraints.gridwidth = 3; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.weightx = 0.0; constraints.weighty = 0.0; add(pnlSingleDownloads, constraints); constraints.gridx = 0; constraints.gridy = 4; constraints.gridwidth = 3; constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 1.0; constraints.weighty = 1.0; add(sepSingleDownloadsPanel, constraints); final int width = getMaximumSize().width; final int height = getMaximumSize().height; setMaximumSize(new Dimension(width, height + (download.getDownloadsTotal() * 44))); isSingleDownloadsPanelShown = true; revalidate(); repaint(); } /** * Hides the panel visualising the single downloads. */ private void hideSingleDownloads() { if (!isSingleDownloadsPanelShown) { return; } tbtDownloads.setSelected(false); lblIcon.setIcon(new ImageIcon( getClass().getResource("/de/cismet/tools/gui/downloadmanager/documenttypes/multiple_closed.png"))); remove(sepDownloadPanels); remove(sepSingleDownloadsPanel); remove(pnlSingleDownloads); final GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 2; constraints.gridwidth = 3; constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 1.0; constraints.weighty = 1.0; add(sepDownloadPanels, constraints); final int width = getMaximumSize().width; setMaximumSize(new Dimension(width, 54)); isSingleDownloadsPanelShown = false; revalidate(); repaint(); } /** * DOCUMENT ME! */ public void redrawEncapsulatedDownloads() { addDownloadsToPnlSingleDownloads(download.getDownloads()); } /** * DOCUMENT ME! * * @param downloads DOCUMENT ME! */ private void addDownloadsToPnlSingleDownloads(final Collection<? extends Download> downloads) { final Iterator<? extends Download> iterDownloads = downloads.iterator(); Branch.Position position = null; for (int i = 0; iterDownloads.hasNext(); i++) { final Download singleDownload = iterDownloads.next(); if (!downloadsInSingleDownloadsPanel.containsKey(singleDownload)) { final DownloadPanel pnlSingleDownloadPanel = new DownloadPanel( singleDownload, true, !iterDownloads.hasNext()); singleDownload.addObserver(pnlSingleDownloadPanel); if (i == (download.getDownloads().size() - 1)) { position = Branch.Position.LAST; } else if (i == 0) { position = Branch.Position.FIRST; } else { position = Branch.Position.NORMAL; } final JComponent braBranch = new Branch(pnlSingleDownloadPanel, position); final JPanel pnlSingleDownload = new JPanel(); pnlSingleDownload.setLayout(new BoxLayout(pnlSingleDownload, BoxLayout.LINE_AXIS)); pnlSingleDownload.add(braBranch); pnlSingleDownload.add(pnlSingleDownloadPanel); downloadsInSingleDownloadsPanel.put(singleDownload, pnlSingleDownload); pnlSingleDownloads.add(pnlSingleDownload); } } // the single downloads should only be visible if there are downloads to show tbtDownloads.setVisible(!downloads.isEmpty()); } //~ Inner Classes ---------------------------------------------------------- /** * A visual component drawing branches in the panel which shows the single downloads. * * @version $Revision$, $Date$ */ private static class Branch extends JComponent { //~ Static fields/initializers ----------------------------------------- private static final int INSET = 4; //~ Enums -------------------------------------------------------------- /** * An enumeration for all positions a branch component can be used for. * * @version $Revision$, $Date$ */ enum Position { //~ Enum constants ------------------------------------------------- FIRST, NORMAL, LAST } //~ Instance fields ---------------------------------------------------- private Position position; private JComponent parent; //~ Constructors ------------------------------------------------------- /** * Creates a new Branch object. * * @param parent The parent component of the branch. It's needed to draw the background of the branch in the * same color. */ public Branch(final JComponent parent) { this(parent, Position.NORMAL); } /** * Creates a new Branch object. * * @param parent The parent component of the branch. It's needed to draw the background of the branch in the * same color. * @param position The position of the branch. */ public Branch(final JComponent parent, final Position position) { this.parent = parent; this.position = position; } //~ Methods ------------------------------------------------------------ @Override public void paintComponent(final Graphics g) { super.paintComponent(g); if (!(g instanceof Graphics2D)) { return; } final Graphics2D g2d = (Graphics2D)g; g2d.setColor(parent.getBackground()); g2d.fillRect(0, 0, getWidth(), getHeight()); g2d.setColor(SystemColor.textInactiveText); g2d.setStroke(new BasicStroke( 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, new float[] { 1, 1 }, 0)); final Path2D shape = new Path2D.Float(); if (position == Position.FIRST) { shape.moveTo((getWidth() / 2), INSET); } else { shape.moveTo((getWidth() / 2), 0); } if (position == Position.LAST) { shape.lineTo(getWidth() / 2, getHeight() / 2); } else { shape.lineTo(getWidth() / 2, getHeight()); } shape.moveTo(getWidth() / 2, getHeight() / 2); shape.lineTo(getWidth() - INSET, getHeight() / 2); g2d.draw(shape); } @Override public Dimension getMinimumSize() { return new Dimension(42, 44); } @Override public Dimension getPreferredSize() { return new Dimension(42, 44); } } }