/*******************************************************************************
* Copyright (c) MOBAC developers
*
* 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, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package mobac.gui;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import mobac.program.AtlasThread;
import mobac.program.Logging;
import mobac.program.interfaces.AtlasInterface;
import mobac.program.interfaces.LayerInterface;
import mobac.program.interfaces.MapInterface;
import mobac.program.interfaces.MapSourceListener;
import mobac.program.model.AtlasOutputFormat;
import mobac.program.model.Settings;
import mobac.utilities.GBC;
import mobac.utilities.GUIExceptionHandler;
import mobac.utilities.I18nUtils;
import mobac.utilities.OSUtilities;
import mobac.utilities.Utilities;
import org.apache.log4j.Logger;
/**
* A window showing the progress while {@link AtlasThread} downloads and processes the map tiles.
*
*/
public class AtlasProgress extends JFrame implements ActionListener, MapSourceListener {
private static Logger log = Logger.getLogger(AtlasProgress.class);
private static final long serialVersionUID = -1L;
private static final Timer TIMER = new Timer(true);
private JProgressBar atlasProgressBar;
private JProgressBar mapDownloadProgressBar;
private JProgressBar mapCreationProgressBar;
private Container background;
private long initialTotalTime;
private long initialMapDownloadTime;
private static class Data {
AtlasInterface atlasInterface;
MapInterface map;
MapInfo mapInfo;
long numberOfDownloadedBytes = 0;
long numberOfBytesLoadedFromCache = 0;
int totalNumberOfTiles = 0;
int totalNumberOfMaps = 0;
int totalProgress = 0;
int totalProgressTenthPercent = -1;
int currentMapNumber = 0;
int mapDownloadProgress = 0;
int mapDownloadNumberOfTiles = 0;
int mapCreationProgress = 0;
int mapCreationMax = 0;
int mapRetryErrors = 0;
int mapPermanentErrors = 0;
int prevMapsRetryErrors = 0;
int prevMapsPermanentErrors = 0;
boolean paused = false;
}
private final Data data = new Data();
private boolean aborted = false;
private boolean finished = false;
private JLabel windowTitle;
private JLabel title;
private JLabel mapInfoLabel;
private JLabel mapDownloadTitle;
private JLabel atlasPercent;
private JLabel mapDownloadPercent;
private JLabel atlasMapsDone;
private JLabel mapDownloadElementsDone;
private JLabel atlasTimeLeft;
private JLabel mapDownloadTimeLeft;
private JLabel mapCreation;
private JLabel nrOfDownloadedBytes;
private JLabel nrOfDownloadedBytesValue;
private JLabel nrOfDownloadedBytesPerSecond;
private JLabel nrOfDownloadedBytesPerSecondValue;
private JLabel nrOfCacheBytes;
private JLabel nrOfCacheBytesValue;
private JLabel activeDownloads;
private JLabel activeDownloadsValue;
private JLabel retryableDownloadErrors;
private JLabel retryableDownloadErrorsValue;
private JLabel permanentDownloadErrors;
private JLabel permanentDownloadErrorsValue;
private JLabel totalDownloadTime;
private JLabel totalDownloadTimeValue;
private JCheckBox ignoreDlErrors;
private JLabel statusLabel;
private JButton dismissWindowButton;
private JButton openProgramFolderButton;
private JButton abortAtlasCreationButton;
private JButton pauseResumeDownloadButton;
private AtlasCreationController downloadControlListener = null;
private UpdateTask updateTask = null;
private GUIUpdater guiUpdater = null;
private AtlasThread atlasThread;
private ArrayList<MapInfo> mapInfos = null;
private static String TEXT_MAP_DOWNLOAD = I18nUtils.localizedStringForKey("dlg_download_zoom_level_progress");
private static String TEXT_PERCENT = I18nUtils.localizedStringForKey("dlg_download_done_percent");
private static String TEXT_TENTHPERCENT = I18nUtils.localizedStringForKey("dlg_download_done_tenthpercent");
public AtlasProgress(AtlasThread atlasThread) {
super(I18nUtils.localizedStringForKey("dlg_download_title"));
this.atlasThread = atlasThread;
ToolTipManager.sharedInstance().setDismissDelay(12000);
if (MainGUI.getMainGUI() == null) // Atlas creation started via command-line, no MainGUi available
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
else
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setIconImages(MainGUI.MOBAC_ICONS);
setLayout(new GridBagLayout());
updateTask = new UpdateTask();
guiUpdater = new GUIUpdater();
createComponents();
// Initialize the layout in respect to the layout (font size ...)
pack();
guiUpdater.run();
// The layout is now initialized - we disable it because we don't want
// want to the labels to jump around if the content changes.
background.setLayout(null);
setResizable(false);
Dimension dScreen = Toolkit.getDefaultToolkit().getScreenSize();
Dimension dContent = getSize();
setLocation((dScreen.width - dContent.width) / 2, (dScreen.height - dContent.height) / 2);
initialTotalTime = System.currentTimeMillis();
initialMapDownloadTime = System.currentTimeMillis();
addWindowListener(new CloseListener());
}
private void createComponents() {
background = new JPanel(new GridBagLayout());
windowTitle = new JLabel(I18nUtils.localizedStringForKey("dlg_download_window_title"));
title = new JLabel(I18nUtils.localizedStringForKey("dlg_download_map_progress"));
mapInfoLabel = new JLabel();
atlasMapsDone = new JLabel(I18nUtils.localizedStringForKey("dlg_download_map_done_count_default"));
atlasPercent = new JLabel(String.format(TEXT_TENTHPERCENT, 100.0));
atlasTimeLeft = new JLabel(I18nUtils.localizedStringForKey("dlg_download_remain_time_default"), JLabel.RIGHT);
atlasProgressBar = new JProgressBar();
mapDownloadTitle = new JLabel(TEXT_MAP_DOWNLOAD + "000");
mapDownloadElementsDone = new JLabel(I18nUtils.localizedStringForKey("dlg_download_tile_done_count_default"));
mapDownloadPercent = new JLabel(String.format(TEXT_PERCENT, 100));
mapDownloadTimeLeft = new JLabel(I18nUtils.localizedStringForKey("dlg_download_remain_time_default"),
JLabel.RIGHT);
mapDownloadProgressBar = new JProgressBar();
mapCreation = new JLabel(I18nUtils.localizedStringForKey("dlg_download_map_create_title"));
mapCreationProgressBar = new JProgressBar();
nrOfDownloadedBytesPerSecond = new JLabel(I18nUtils.localizedStringForKey("dlg_download_avg_speed"));
nrOfDownloadedBytesPerSecondValue = new JLabel();
nrOfDownloadedBytes = new JLabel(I18nUtils.localizedStringForKey("dlg_download_total_bytes"));
nrOfDownloadedBytesValue = new JLabel();
nrOfCacheBytes = new JLabel(I18nUtils.localizedStringForKey("dlg_download_bytes_from_cache"));
nrOfCacheBytesValue = new JLabel();
activeDownloads = new JLabel(I18nUtils.localizedStringForKey("dlg_download_thread_count"));
activeDownloadsValue = new JLabel();
retryableDownloadErrors = new JLabel(I18nUtils.localizedStringForKey("dlg_download_retry_count"));
retryableDownloadErrors.setToolTipText(I18nUtils.localizedStringForKey("dlg_download_error_tips"));
retryableDownloadErrorsValue = new JLabel();
retryableDownloadErrorsValue.setToolTipText(retryableDownloadErrors.getToolTipText());
permanentDownloadErrors = new JLabel(I18nUtils.localizedStringForKey("dlg_download_failed_count"));
permanentDownloadErrors.setToolTipText(I18nUtils.localizedStringForKey("dlg_download_error_tips"));
permanentDownloadErrorsValue = new JLabel();
permanentDownloadErrorsValue.setToolTipText(permanentDownloadErrors.getToolTipText());
totalDownloadTime = new JLabel(I18nUtils.localizedStringForKey("dlg_download_total_time"));
totalDownloadTimeValue = new JLabel();
ignoreDlErrors = new JCheckBox(I18nUtils.localizedStringForKey("dlg_download_checkbox_ignore_error"),
Settings.getInstance().ignoreDlErrors);
statusLabel = new JLabel(I18nUtils.localizedStringForKey("dlg_download_status_title"));
Font f = statusLabel.getFont();
statusLabel.setFont(f.deriveFont(Font.BOLD));
abortAtlasCreationButton = new JButton(I18nUtils.localizedStringForKey("dlg_download_btn_abort"));
abortAtlasCreationButton.setToolTipText(I18nUtils.localizedStringForKey("dlg_download_btn_abort_tips"));
dismissWindowButton = new JButton(I18nUtils.localizedStringForKey("dlg_download_btn_close_win"));
dismissWindowButton.setToolTipText(I18nUtils.localizedStringForKey("dlg_download_btn_close_win_tips_disable"));
dismissWindowButton.setVisible(false);
openProgramFolderButton = new JButton(I18nUtils.localizedStringForKey("dlg_download_btn_open_folder"));
openProgramFolderButton.setToolTipText(I18nUtils
.localizedStringForKey("dlg_download_btn_open_folder_tips_disabled"));
openProgramFolderButton.setEnabled(false);
pauseResumeDownloadButton = new JButton(I18nUtils.localizedStringForKey("dlg_download_btn_pause_resume"));
GBC gbcRIF = GBC.std().insets(0, 0, 20, 0).fill(GBC.HORIZONTAL);
GBC gbcEol = GBC.eol();
GBC gbcEolFill = GBC.eol().fill(GBC.HORIZONTAL);
GBC gbcEolFillI = GBC.eol().fill(GBC.HORIZONTAL).insets(0, 5, 0, 0);
// background.add(windowTitle, gbcEolFill);
// background.add(Box.createVerticalStrut(10), gbcEol);
background.add(mapInfoLabel, gbcEolFill);
background.add(Box.createVerticalStrut(20), gbcEol);
background.add(title, gbcRIF);
background.add(atlasMapsDone, gbcRIF);
background.add(atlasPercent, gbcRIF);
background.add(atlasTimeLeft, gbcEolFill);
background.add(atlasProgressBar, gbcEolFillI);
background.add(Box.createVerticalStrut(20), gbcEol);
background.add(mapDownloadTitle, gbcRIF);
background.add(mapDownloadElementsDone, gbcRIF);
background.add(mapDownloadPercent, gbcRIF);
background.add(mapDownloadTimeLeft, gbcEolFill);
background.add(mapDownloadProgressBar, gbcEolFillI);
background.add(Box.createVerticalStrut(20), gbcEol);
background.add(mapCreation, gbcEol);
background.add(mapCreationProgressBar, gbcEolFillI);
background.add(Box.createVerticalStrut(10), gbcEol);
JPanel infoPanel = new JPanel(new GridBagLayout());
GBC gbci = GBC.std().insets(0, 3, 3, 3);
infoPanel.add(nrOfDownloadedBytes, gbci);
infoPanel.add(nrOfDownloadedBytesValue, gbci.toggleEol());
infoPanel.add(nrOfCacheBytes, gbci.toggleEol());
infoPanel.add(nrOfCacheBytesValue, gbci.toggleEol());
infoPanel.add(nrOfDownloadedBytesPerSecond, gbci.toggleEol());
infoPanel.add(nrOfDownloadedBytesPerSecondValue, gbci.toggleEol());
infoPanel.add(activeDownloads, gbci.toggleEol());
infoPanel.add(activeDownloadsValue, gbci.toggleEol());
infoPanel.add(retryableDownloadErrors, gbci.toggleEol());
infoPanel.add(retryableDownloadErrorsValue, gbci.toggleEol());
infoPanel.add(permanentDownloadErrors, gbci.toggleEol());
infoPanel.add(permanentDownloadErrorsValue, gbci.toggleEol());
infoPanel.add(totalDownloadTime, gbci.toggleEol());
infoPanel.add(totalDownloadTimeValue, gbci.toggleEol());
JPanel bottomPanel = new JPanel(new GridBagLayout());
bottomPanel.add(infoPanel, GBC.std().gridheight(2).fillH());
bottomPanel.add(ignoreDlErrors, GBC.eol().anchor(GBC.EAST));
bottomPanel.add(statusLabel, GBC.eol().anchor(GBC.CENTER));
GBC gbcRight = GBC.std().anchor(GBC.SOUTHEAST).insets(5, 0, 0, 0);
bottomPanel.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL));
bottomPanel.add(abortAtlasCreationButton, gbcRight);
bottomPanel.add(dismissWindowButton, gbcRight);
bottomPanel.add(pauseResumeDownloadButton, gbcRight);
bottomPanel.add(openProgramFolderButton, gbcRight);
background.add(bottomPanel, gbcEolFillI);
JPanel borderPanel = new JPanel(new GridBagLayout());
borderPanel.add(background, GBC.std().insets(10, 10, 10, 10).fill());
add(borderPanel, GBC.std().fill());
abortAtlasCreationButton.addActionListener(this);
dismissWindowButton.addActionListener(this);
openProgramFolderButton.addActionListener(this);
pauseResumeDownloadButton.addActionListener(this);
}
public void initAtlas(AtlasInterface atlasInterface) {
data.atlasInterface = atlasInterface;
if (atlasInterface.getOutputFormat().equals(AtlasOutputFormat.TILESTORE))
data.totalNumberOfTiles = (int) atlasInterface.calculateTilesToDownload();
else
data.totalNumberOfTiles = (int) atlasInterface.calculateTilesToDownload() * 2;
int mapCount = 0;
int tileCount = 0;
mapInfos = new ArrayList<MapInfo>(100);
for (LayerInterface layer : atlasInterface) {
mapCount += layer.getMapCount();
for (MapInterface map : layer) {
int before = tileCount;
int mapTiles = (int) map.calculateTilesToDownload();
tileCount += mapTiles + mapTiles;
mapInfos.add(new MapInfo(map, before, tileCount));
}
}
mapInfos.trimToSize();
data.totalNumberOfMaps = mapCount;
initialTotalTime = System.currentTimeMillis();
initialMapDownloadTime = -1;
updateGUI();
setVisible(true);
TIMER.schedule(updateTask, 0, 500);
}
public void initMapDownload(MapInterface map) {
int index = mapInfos.indexOf(new MapInfo(map, 0, 0));
data.mapInfo = mapInfos.get(index);
data.totalProgress = data.mapInfo.tileCountOnStart;
data.map = map;
data.mapDownloadNumberOfTiles = (int) map.calculateTilesToDownload();
initialMapDownloadTime = System.currentTimeMillis();
data.prevMapsPermanentErrors += data.mapPermanentErrors;
data.prevMapsRetryErrors += data.mapRetryErrors;
data.mapCreationProgress = 0;
data.mapDownloadProgress = 0;
data.currentMapNumber = index + 1;
updateGUI();
}
/**
* Initialize the GUI progress bars
*
* @param maxTilesToProcess
*/
public void initMapCreation(int maxTilesToProcess) {
data.mapCreationProgress = 0;
data.mapCreationMax = maxTilesToProcess;
initialMapDownloadTime = -1;
updateGUI();
}
public void setErrorCounter(int retryErrors, int permanentErrors) {
data.mapRetryErrors = retryErrors;
data.mapPermanentErrors = permanentErrors;
updateGUI();
}
public void incMapDownloadProgress() {
data.mapDownloadProgress++;
data.totalProgress++;
updateGUI();
}
public void incMapCreationProgress() {
setMapCreationProgress(data.mapCreationProgress + 1);
}
public void incMapCreationProgress(int stepSize) {
setMapCreationProgress(data.mapCreationProgress + stepSize);
}
public void setMapCreationProgress(int progress) {
data.mapCreationProgress = progress;
data.totalProgress = data.mapInfo.tileCountOnStart + data.mapInfo.mapTiles
+ (int) (((long) data.mapInfo.mapTiles) * data.mapCreationProgress / data.mapCreationMax);
updateGUI();
}
public boolean ignoreDownloadErrors() {
return ignoreDlErrors.isSelected();
}
public void tileDownloaded(int size) {
synchronized (data) {
data.numberOfDownloadedBytes += size;
}
updateGUI();
}
public void tileLoadedFromCache(int size) {
synchronized (data) {
data.numberOfBytesLoadedFromCache += size;
}
updateGUI();
}
private String formatTime(long longSeconds) {
String timeString = "";
if (longSeconds < 0) {
timeString = I18nUtils.localizedStringForKey("dlg_download_time_unknown");
} else {
int minutes = (int) (longSeconds / 60);
int seconds = (int) (longSeconds % 60);
if (minutes > 0)
timeString += Integer.toString(minutes)
+ " "
+ (minutes == 1 ? I18nUtils.localizedStringForKey("minute") : I18nUtils
.localizedStringForKey("minutes")) + " ";
timeString += Integer.toString(seconds)
+ " "
+ (seconds == 1 ? I18nUtils.localizedStringForKey("second") : I18nUtils
.localizedStringForKey("seconds"));
}
return timeString;
}
public void setZoomLevel(int theZoomLevel) {
mapDownloadTitle.setText(TEXT_MAP_DOWNLOAD + Integer.toString(theZoomLevel));
}
public void atlasCreationFinished() {
finished = true;
stopUpdateTask();
forceUpdateGUI();
downloadControlListener = null;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
abortAtlasCreationButton.setEnabled(false);
if (aborted) {
windowTitle.setText(I18nUtils.localizedStringForKey("dlg_download_abort_window_title"));
setTitle(I18nUtils.localizedStringForKey("dlg_download_abort_title"));
} else {
windowTitle.setText(I18nUtils.localizedStringForKey("dlg_download_succeed_window_title"));
setTitle(I18nUtils.localizedStringForKey("dlg_download_succeed_title"));
}
// mapInfoLabel.setText("");
atlasMapsDone.setText(String.format(I18nUtils.localizedStringForKey("dlg_download_map_done_count"),
data.currentMapNumber, data.totalNumberOfMaps));
abortAtlasCreationButton.setVisible(false);
dismissWindowButton.setToolTipText(I18nUtils
.localizedStringForKey("dlg_download_btn_close_win_tips_enable"));
dismissWindowButton.setVisible(true);
if (!aborted) {
openProgramFolderButton.setToolTipText(I18nUtils
.localizedStringForKey("dlg_download_btn_open_folder_tips_enabled"));
openProgramFolderButton.setEnabled(true);
}
}
});
}
private synchronized void stopUpdateTask() {
try {
updateTask.cancel();
updateTask = null;
} catch (Exception e) {
}
}
public void closeWindow() {
try {
stopUpdateTask();
downloadControlListener = null;
setVisible(false);
} finally {
dispose();
}
}
public AtlasCreationController getDownloadControlListener() {
return downloadControlListener;
}
public void setDownloadControlerListener(AtlasCreationController threadControlListener) {
this.downloadControlListener = threadControlListener;
}
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
File atlasFolder = Settings.getInstance().getAtlasOutputDirectory();
if (openProgramFolderButton.equals(source)) {
try {
OSUtilities.openFolderBrowser(atlasFolder);
} catch (Exception e) {
log.error("", e);
}
} else if (dismissWindowButton.equals(source)) {
downloadControlListener = null;
closeWindow();
} else if (abortAtlasCreationButton.equals(source)) {
aborted = true;
stopUpdateTask();
if (downloadControlListener != null)
downloadControlListener.abortAtlasCreation();
else
closeWindow();
} else if (pauseResumeDownloadButton.equals(source)) {
if (downloadControlListener != null)
downloadControlListener.pauseResumeAtlasCreation();
}
}
public void updateGUI() {
guiUpdater.updateAsynchronously();
}
public void forceUpdateGUI() {
SwingUtilities.invokeLater(guiUpdater);
}
private class GUIUpdater implements Runnable {
int scheduledCounter = 0;
public void updateAsynchronously() {
// If there is still at least one scheduled update request to be
// executed we don't have add another one as this can result in an
// to overloaded swing invocation queue.
synchronized (this) {
if (scheduledCounter > 0)
return;
scheduledCounter++;
}
SwingUtilities.invokeLater(this);
}
public void run() {
synchronized (this) {
scheduledCounter--;
}
if (data.map != null) {
String text = String.format(I18nUtils.localizedStringForKey("dlg_download_map_info_label"),
data.map.getName(), data.map.getLayer().getName(), data.map.getMapSource().toString());
mapInfoLabel.setText(text);
}
// atlas progress
atlasProgressBar.setMaximum(data.totalNumberOfTiles);
atlasProgressBar.setValue(data.totalProgress);
int newTenthPercent = (int) (data.totalProgress * 1000d / (double) data.totalNumberOfTiles);
try {
boolean pauseState = atlasThread.isPaused();
String statusText = I18nUtils.localizedStringForKey("dlg_download_status_running");
if (aborted)
statusText = I18nUtils.localizedStringForKey("dlg_download_status_aborted");
else if (finished)
statusText = I18nUtils.localizedStringForKey("dlg_download_status_finished");
else if (pauseState)
statusText = I18nUtils.localizedStringForKey("dlg_download_status_paused");
else
statusText = I18nUtils.localizedStringForKey("dlg_download_status_running");
statusLabel.setText(I18nUtils.localizedStringForKey("dlg_download_status_title") + " " + statusText);
if (data.totalProgressTenthPercent != newTenthPercent || pauseState != data.paused) {
data.totalProgressTenthPercent = newTenthPercent;
atlasPercent.setText(String.format(TEXT_TENTHPERCENT, data.totalProgressTenthPercent / 10.0));
if (data.atlasInterface != null) {
String text = String.format(I18nUtils.localizedStringForKey("dlg_download_atlas_progress"),
data.totalProgressTenthPercent / 10, data.atlasInterface.getName(),
data.atlasInterface.getOutputFormat());
if (pauseState)
text += " [" + I18nUtils.localizedStringForKey("dlg_download_status_paused") + "]";
AtlasProgress.this.setTitle(text);
}
}
data.paused = pauseState;
} catch (NullPointerException e) {
}
long seconds = -1;
int totalProgress = data.totalProgress;
if (totalProgress != 0) {
// Avoid for a possible division by zero
int totalTilesRemaining = data.totalNumberOfTiles - totalProgress;
long totalElapsedTime = System.currentTimeMillis() - initialTotalTime;
seconds = (totalElapsedTime * totalTilesRemaining / (1000L * totalProgress));
}
atlasTimeLeft.setText(String.format(I18nUtils.localizedStringForKey("dlg_download_remain_time"),
formatTime(seconds)));
// layer progress
mapDownloadProgressBar.setMaximum(data.mapDownloadNumberOfTiles);
mapDownloadProgressBar.setValue(data.mapDownloadProgress);
mapDownloadPercent.setText(String.format(TEXT_PERCENT,
(int) (mapDownloadProgressBar.getPercentComplete() * 100)));
mapDownloadElementsDone.setText(String.format(
I18nUtils.localizedStringForKey("dlg_download_tile_done_count"), data.mapDownloadProgress,
data.mapDownloadNumberOfTiles));
seconds = -1;
int mapDlProgress = data.mapDownloadProgress;
if (mapDlProgress != 0 && initialMapDownloadTime > 0)
seconds = ((System.currentTimeMillis() - initialMapDownloadTime)
* (data.mapDownloadNumberOfTiles - mapDlProgress) / (1000L * mapDlProgress));
mapDownloadTimeLeft.setText(String.format(I18nUtils.localizedStringForKey("dlg_download_remain_time"),
formatTime(seconds)));
// map progress
mapCreation.setText(I18nUtils.localizedStringForKey("dlg_download_map_create_title"));
mapCreationProgressBar.setValue(data.mapCreationProgress);
mapCreationProgressBar.setMaximum(data.mapCreationMax);
atlasMapsDone.setText(String.format(I18nUtils.localizedStringForKey("dlg_download_map_done_count"),
(data.currentMapNumber - 1), data.totalNumberOfMaps));
// bytes per second
long rate = data.numberOfDownloadedBytes * 1000;
long time = System.currentTimeMillis() - initialMapDownloadTime;
if (data.mapCreationProgress == 0 && initialMapDownloadTime > 0) {
if (time == 0) {
nrOfDownloadedBytesPerSecondValue.setText("??");
} else {
rate = rate / time;
nrOfDownloadedBytesPerSecondValue.setText(String.format(
I18nUtils.localizedStringForKey("dlg_download_avg_speed_value"),
Utilities.formatBytes(rate)));
}
}
// downloaded bytes
nrOfDownloadedBytesValue.setText(": " + Utilities.formatBytes(data.numberOfDownloadedBytes));
nrOfCacheBytesValue.setText(": " + Utilities.formatBytes(data.numberOfBytesLoadedFromCache));
// total creation time
long totalSeconds = (System.currentTimeMillis() - initialTotalTime) / 1000;
totalDownloadTimeValue.setText(": " + formatTime(totalSeconds));
totalDownloadTimeValue.repaint();
// active downloads
int activeDownloads = (atlasThread == null) ? 0 : atlasThread.getActiveDownloads();
activeDownloadsValue.setText(": " + activeDownloads);
activeDownloadsValue.repaint();
int totalRetryableErrors = data.prevMapsRetryErrors + data.mapRetryErrors;
retryableDownloadErrorsValue.setText(String.format(
I18nUtils.localizedStringForKey("dlg_download_retry_count_value"), data.mapRetryErrors,
totalRetryableErrors));
retryableDownloadErrorsValue.repaint();
int totalPermanentErrors = data.prevMapsPermanentErrors + data.mapPermanentErrors;
permanentDownloadErrorsValue.setText(String.format(
I18nUtils.localizedStringForKey("dlg_download_failed_count_value"), data.mapPermanentErrors,
totalPermanentErrors));
permanentDownloadErrorsValue.repaint();
}
}
private class UpdateTask extends TimerTask {
@Override
public void run() {
updateGUI();
}
}
private class CloseListener extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) {
log.debug("Closing event detected for atlas progress window");
AtlasCreationController listener = AtlasProgress.this.downloadControlListener;
if (listener != null)
listener.abortAtlasCreation();
}
}
protected static class MapInfo {
final MapInterface map;
final int tileCountOnStart;
final int tileCountOnEnd;
final int mapTiles;
public MapInfo(MapInterface map, int tileCountOnStart, int tileCountOnEnd) {
super();
this.map = map;
this.tileCountOnStart = tileCountOnStart;
this.tileCountOnEnd = tileCountOnEnd;
this.mapTiles = (int) map.calculateTilesToDownload();
}
@Override
public int hashCode() {
return map.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof MapInfo))
return false;
return map.equals(((MapInfo) obj).map);
}
}
public static interface AtlasCreationController {
public void abortAtlasCreation();
public void pauseResumeAtlasCreation();
public boolean isPaused();
}
public static void main(String[] args) {
Logging.configureLogging();
GUIExceptionHandler.installToolkitEventQueueProxy();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
log.error("The selection of look and feel failed!", e);
}
AtlasProgress ap = new AtlasProgress(null);
ap.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ap.setVisible(true);
}
}