All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.gov.nasa.worldwindx.examples.BulkDownloadPanel Maven / Gradle / Ivy

Go to download

World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.

There is a newer version: 2.0.0-986
Show newest version
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwindx.examples;

import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.cache.BasicDataFileStore;
import gov.nasa.worldwind.event.*;
import gov.nasa.worldwindx.examples.util.SectorSelector;
import gov.nasa.worldwind.geom.Sector;
import gov.nasa.worldwind.globes.ElevationModel;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.retrieve.*;
import gov.nasa.worldwind.terrain.CompoundElevationModel;

import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.File;
import java.util.ArrayList;

/**
 * Bulk download panel.
 *
 * @author Patrick Murris
 * @version $Id: BulkDownloadPanel.java 1171 2013-02-11 21:45:02Z dcollins $
 * @see BulkRetrievalThread
 * @see BulkRetrievable
 */
public class BulkDownloadPanel extends JPanel
{
    @SuppressWarnings( {"FieldCanBeLocal"})
    protected WorldWindow wwd;
    protected Sector currentSector;
    protected ArrayList retrievables;

    protected JButton selectButton;
    protected JLabel sectorLabel;
    protected JButton startButton;
    protected JPanel monitorPanel;
    protected BasicDataFileStore cache;

    protected SectorSelector selector;

    public BulkDownloadPanel(WorldWindow wwd)
    {
        this.wwd = wwd;

        // Init retievable list
        this.retrievables = new ArrayList();
        // Layers
        for (Layer layer : this.wwd.getModel().getLayers())
        {
            if (layer instanceof BulkRetrievable)
                this.retrievables.add(new BulkRetrievablePanel((BulkRetrievable) layer));
        }
        // Elevation models
        CompoundElevationModel cem = (CompoundElevationModel) wwd.getModel().getGlobe().getElevationModel();
        for (ElevationModel elevationModel : cem.getElevationModels())
        {
            if (elevationModel instanceof BulkRetrievable)
                this.retrievables.add(new BulkRetrievablePanel((BulkRetrievable) elevationModel));
        }

        // Init sector selector
        this.selector = new SectorSelector(wwd);
        this.selector.setInteriorColor(new Color(1f, 1f, 1f, 0.1f));
        this.selector.setBorderColor(new Color(1f, 0f, 0f, 0.5f));
        this.selector.setBorderWidth(3);
        this.selector.addPropertyChangeListener(SectorSelector.SECTOR_PROPERTY, new PropertyChangeListener()
        {
            public void propertyChange(PropertyChangeEvent evt)
            {
                updateSector();
            }
        });

        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
        ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
        this.initComponents();
    }

    protected void updateSector()
    {
        this.currentSector = this.selector.getSector();
        if (this.currentSector != null)
        {
            // Update sector description
            this.sectorLabel.setText(makeSectorDescription(this.currentSector));
            this.selectButton.setText("Clear sector");
            this.startButton.setEnabled(true);
        }
        else
        {
            // null sector
            this.sectorLabel.setText("-");
            this.selectButton.setText("Select sector");
            this.startButton.setEnabled(false);
        }
        updateRetrievablePanels(this.currentSector);
    }

    protected void updateRetrievablePanels(Sector sector)
    {
        for (BulkRetrievablePanel panel : this.retrievables)
        {
            panel.updateDescription(sector);
        }
    }

    @SuppressWarnings( {"UnusedDeclaration"})
    protected void selectButtonActionPerformed(ActionEvent event)
    {
        if (this.selector.getSector() != null)
        {
            this.selector.disable();
        }
        else
        {
            this.selector.enable();
        }
        updateSector();
    }

    /** Clear the current selection sector and remove it from the globe. */
    public void clearSector()
    {
        if (this.selector.getSector() != null)
        {
            this.selector.disable();
        }
        updateSector();
    }

    @SuppressWarnings( {"UnusedDeclaration"})
    protected void startButtonActionPerformed(ActionEvent event)
    {
        for (BulkRetrievablePanel panel : this.retrievables)
        {
            if (panel.selectCheckBox.isSelected())
            {
                BulkRetrievable retrievable = panel.retrievable;
                BulkRetrievalThread thread = retrievable.makeLocal(this.currentSector, 0, this.cache,
                    new BulkRetrievalListener()
                    {
                        public void eventOccurred(BulkRetrievalEvent event)
                        {
                            // This is how you'd include a retrieval listener. Uncomment below to monitor downloads.
                            // Be aware that the method is not invoked on the event dispatch thread, so any interaction
                            // with AWT or Swing must be within a SwingUtilities.invokeLater() runnable.

                            //System.out.printf("%s: item %s\n",
                            //    event.getEventType().equals(BulkRetrievalEvent.RETRIEVAL_SUCCEEDED) ? "Succeeded"
                            //: event.getEventType().equals(BulkRetrievalEvent.RETRIEVAL_FAILED) ? "Failed"
                            //    : "Unknown event type", event.getItem());
                        }
                    });

                if (thread != null)
                    this.monitorPanel.add(new DownloadMonitorPanel(thread));
            }
        }
        this.getTopLevelAncestor().validate();
    }

    /**
     * Determines whether there are any active downloads running.
     *
     * @return true if at leat one download thread is active.
     */
    public boolean hasActiveDownloads()
    {
        for (Component c : this.monitorPanel.getComponents())
        {
            if (c instanceof DownloadMonitorPanel)
                if (((DownloadMonitorPanel) c).thread.isAlive())
                    return true;
        }
        return false;
    }

    /** Cancel all active downloads. */
    public void cancelActiveDownloads()
    {
        for (Component c : this.monitorPanel.getComponents())
        {
            if (c instanceof DownloadMonitorPanel)
            {
                if (((DownloadMonitorPanel) c).thread.isAlive())
                {
                    DownloadMonitorPanel panel = (DownloadMonitorPanel) c;
                    panel.cancelButtonActionPerformed(null);
                    try
                    {
                        // Wait for thread to die before moving on
                        long t0 = System.currentTimeMillis();
                        while (panel.thread.isAlive() && System.currentTimeMillis() - t0 < 500)
                        {
                            Thread.sleep(10);
                        }
                    }
                    catch (Exception ignore)
                    {
                    }
                }
            }
        }
    }

    /** Remove inactive downloads from the monitor panel. */
    public void clearInactiveDownloads()
    {
        for (int i = this.monitorPanel.getComponentCount() - 1; i >= 0; i--)
        {
            Component c = this.monitorPanel.getComponents()[i];
            if (c instanceof DownloadMonitorPanel)
            {
                DownloadMonitorPanel panel = (DownloadMonitorPanel) c;
                if (!panel.thread.isAlive() || panel.thread.isInterrupted())
                {
                    this.monitorPanel.remove(i);
                }
            }
        }
        this.monitorPanel.validate();
    }

    protected void initComponents()
    {
        int border = 6;
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        this.setBorder(
            new CompoundBorder(BorderFactory.createEmptyBorder(9, 9, 9, 9), new TitledBorder("Download")));
        this.setToolTipText("Layer imagery bulk download.");

        final JPanel locationPanel = new JPanel(new BorderLayout(5, 5));
        JLabel locationLabel = new JLabel(" Cache:");
        final JLabel locationName = new JLabel("");
        JButton locationButton = new JButton("...");
        locationPanel.add(locationLabel, BorderLayout.WEST);
        locationPanel.add(locationName, BorderLayout.CENTER);
        locationPanel.add(locationButton, BorderLayout.EAST);
        this.add(locationPanel);

        locationButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                JFileChooser fc = new JFileChooser();
                fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                fc.setMultiSelectionEnabled(false);
                int status = fc.showOpenDialog(locationPanel);
                if (status == JFileChooser.APPROVE_OPTION)
                {
                    File file = fc.getSelectedFile();
                    if (file != null)
                    {
                        locationName.setText(file.getPath());
                        cache = new BasicDataFileStore(file);
                        updateRetrievablePanels(selector.getSector());
                    }
                }
            }
        });

        // Select sector button
        JPanel sectorPanel = new JPanel(new GridLayout(0, 1, 0, 0));
        sectorPanel.setBorder(BorderFactory.createEmptyBorder(border, border, border, border));
        selectButton = new JButton("Select sector");
        selectButton.setToolTipText("Press Select then press and drag button 1 on globe");
        selectButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                selectButtonActionPerformed(event);
            }
        });
        sectorPanel.add(selectButton);
        sectorLabel = new JLabel("-");
        sectorLabel.setPreferredSize(new Dimension(350, 16));
        sectorLabel.setHorizontalAlignment(JLabel.CENTER);
        sectorPanel.add(sectorLabel);
        this.add(sectorPanel);

        // Retrievable list combo and start button
        JPanel retrievablesPanel = new JPanel();
        retrievablesPanel.setLayout(new BoxLayout(retrievablesPanel, BoxLayout.Y_AXIS));
        retrievablesPanel.setBorder(BorderFactory.createEmptyBorder(border, border, border, border));

        // RetrievablePanel list
        for (JPanel panel : this.retrievables)
        {
            retrievablesPanel.add(panel);
        }
        this.add(retrievablesPanel);

        // Start button
        JPanel startPanel = new JPanel(new GridLayout(0, 1, 0, 0));
        startPanel.setBorder(BorderFactory.createEmptyBorder(border, border, border, border));
        startButton = new JButton("Start download");
        startButton.setEnabled(false);
        startButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                startButtonActionPerformed(event);
            }
        });
        startPanel.add(startButton);
        this.add(startPanel);

        // Download monitor panel
        monitorPanel = new JPanel();
        monitorPanel.setLayout(new BoxLayout(monitorPanel, BoxLayout.Y_AXIS));
        monitorPanel.setBorder(BorderFactory.createEmptyBorder(border, border, border, border));
        //this.add(monitorPanel);

        // Put the monitor panel in a scroll pane.
        JPanel dummyPanel = new JPanel(new BorderLayout());
        dummyPanel.add(monitorPanel, BorderLayout.NORTH);

        JScrollPane scrollPane = new JScrollPane(dummyPanel);
        scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
        scrollPane.setPreferredSize(new Dimension(350, 200));
        this.add(scrollPane);
    }

    public static String makeSectorDescription(Sector sector)
    {
        return String.format("S %7.4f\u00B0 W %7.4f\u00B0 N %7.4f\u00B0 E %7.4f\u00B0",
            sector.getMinLatitude().degrees,
            sector.getMinLongitude().degrees,
            sector.getMaxLatitude().degrees,
            sector.getMaxLongitude().degrees);
    }

    public static String makeSizeDescription(long size)
    {
        double sizeInMegaBytes = size / 1024 / 1024;
        if (sizeInMegaBytes < 1024)
            return String.format("%,.1f MB", sizeInMegaBytes);
        else if (sizeInMegaBytes < 1024 * 1024)
            return String.format("%,.1f GB", sizeInMegaBytes / 1024);
        return String.format("%,.1f TB", sizeInMegaBytes / 1024 / 1024);
    }

    public class BulkRetrievablePanel extends JPanel
    {
        protected BulkRetrievable retrievable;
        protected JCheckBox selectCheckBox;
        protected JLabel descriptionLabel;
        protected Thread updateThread;
        protected Sector sector;

        BulkRetrievablePanel(BulkRetrievable retrievable)
        {
            this.retrievable = retrievable;

            this.initComponents();
        }

        protected void initComponents()
        {
            this.setLayout(new BorderLayout());
            this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));

            // Check + name
            this.selectCheckBox = new JCheckBox(this.retrievable.getName());
            this.selectCheckBox.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    if (((JCheckBox) e.getSource()).isSelected() && sector != null)
                        updateDescription(sector);
                }
            });
            this.add(this.selectCheckBox, BorderLayout.WEST);
            // Description (size...)
            this.descriptionLabel = new JLabel();
            this.add(this.descriptionLabel, BorderLayout.EAST);
        }

        public void updateDescription(final Sector sector)
        {
            if (this.updateThread != null && this.updateThread.isAlive())
                return;

            this.sector = sector;
            if (!this.selectCheckBox.isSelected())
            {
                doUpdateDescription(null);
                return;
            }

            this.updateThread = new Thread(new Runnable()
            {
                public void run()
                {
                    doUpdateDescription(sector);
                }
            });
            this.updateThread.setDaemon(true);
            this.updateThread.start();
        }

        protected void doUpdateDescription(final Sector sector)
        {
            if (sector != null)
            {
                try
                {
                    long size = retrievable.getEstimatedMissingDataSize(sector, 0, cache);
                    final String formattedSize = BulkDownloadPanel.makeSizeDescription(size);
                    SwingUtilities.invokeLater(new Runnable()
                    {
                        public void run()
                        {
                            descriptionLabel.setText(formattedSize);
                        }
                    });
                }
                catch (Exception e)
                {
                    SwingUtilities.invokeLater(new Runnable()
                    {
                        public void run()
                        {
                            descriptionLabel.setText("-");
                        }
                    });
                }
            }
            else
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        descriptionLabel.setText("-");
                    }
                });
        }

        public String toString()
        {
            return this.retrievable.getName();
        }
    }

    public class DownloadMonitorPanel extends JPanel
    {
        protected BulkRetrievalThread thread;
        protected Progress progress;
        protected Timer updateTimer;

        protected JLabel descriptionLabel;
        protected JProgressBar progressBar;
        protected JButton cancelButton;

        public DownloadMonitorPanel(BulkRetrievalThread thread)
        {
            this.thread = thread;
            this.progress = thread.getProgress();

            this.initComponents();

            this.updateTimer = new Timer(1000, new ActionListener()
            {
                public void actionPerformed(ActionEvent event)
                {
                    updateStatus();
                }
            });
            this.updateTimer.start();
        }

        protected void updateStatus()
        {
            // Update description
            String text = thread.getRetrievable().getName();
            text = text.length() > 30 ? text.substring(0, 27) + "..." : text;
            text += " (" + BulkDownloadPanel.makeSizeDescription(this.progress.getCurrentSize())
                + " / " + BulkDownloadPanel.makeSizeDescription(this.progress.getTotalSize())
                + ")";
            this.descriptionLabel.setText(text);
            // Update progress bar
            int percent = 0;
            if (this.progress.getTotalCount() > 0)
                percent = (int) ((float) this.progress.getCurrentCount() / this.progress.getTotalCount() * 100f);
            this.progressBar.setValue(Math.min(percent, 100));
            // Update tooltip
            String tooltip = BulkDownloadPanel.makeSectorDescription(this.thread.getSector());
            this.descriptionLabel.setToolTipText(tooltip);
            this.progressBar.setToolTipText(makeProgressDescription());

            // Check for end of thread
            if (!this.thread.isAlive())
            {
                // Thread is done
                this.cancelButton.setText("Remove");
                this.cancelButton.setBackground(Color.GREEN);
                this.updateTimer.stop();
            }
        }

        @SuppressWarnings( {"UnusedDeclaration"})
        protected void cancelButtonActionPerformed(ActionEvent event)
        {
            if (this.thread.isAlive())
            {
                // Cancel thread
                this.thread.interrupt();
                this.cancelButton.setBackground(Color.ORANGE);
                this.cancelButton.setText("Remove");
                this.updateTimer.stop();
            }
            else
            {
                // Remove from monitor panel
                Container top = this.getTopLevelAncestor();
                this.getParent().remove(this);
                top.validate();
            }
        }

        protected void initComponents()
        {
            int border = 2;
            this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));

            // Description label
            JPanel descriptionPanel = new JPanel(new GridLayout(0, 1, 0, 0));
            descriptionPanel.setBorder(BorderFactory.createEmptyBorder(border, border, border, border));
            String text = thread.getRetrievable().getName();
            text = text.length() > 40 ? text.substring(0, 37) + "..." : text;
            descriptionLabel = new JLabel(text);
            descriptionPanel.add(descriptionLabel);
            this.add(descriptionPanel);

            // Progrees and cancel button
            JPanel progressPanel = new JPanel();
            progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.X_AXIS));
            progressPanel.setBorder(BorderFactory.createEmptyBorder(border, border, border, border));
            progressBar = new JProgressBar(0, 100);
            progressBar.setPreferredSize(new Dimension(100, 16));
            progressPanel.add(progressBar);
            progressPanel.add(Box.createHorizontalStrut(8));
            cancelButton = new JButton("Cancel");
            cancelButton.setBackground(Color.RED);
            cancelButton.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent event)
                {
                    cancelButtonActionPerformed(event);
                }
            });
            progressPanel.add(cancelButton);
            this.add(progressPanel);
        }

        protected String makeProgressDescription()
        {
            String text = "";
            if (this.progress.getTotalCount() > 0)
            {
                int percent = (int) ((double) this.progress.getCurrentCount() / this.progress.getTotalCount() * 100d);
                text = percent + "% of ";
                text += makeSizeDescription(this.progress.getTotalSize());
            }
            return text;
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy