implement bundle tile download
git-svn-id: https://osmand.googlecode.com/svn/trunk@66 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
2b9afd0abb
commit
31a56b670a
4 changed files with 260 additions and 2 deletions
|
@ -40,6 +40,10 @@ public class ToDoConstants {
|
||||||
// 14. Show zoom level directly on map
|
// 14. Show zoom level directly on map
|
||||||
// -------------------
|
// -------------------
|
||||||
|
|
||||||
|
// BUGS Androd :
|
||||||
|
// 1. When firstly run osmand navigation (from notification bar) show map & go to menu shows desktop.
|
||||||
|
// No chance to close application
|
||||||
|
|
||||||
|
|
||||||
/// SWING version :
|
/// SWING version :
|
||||||
// TODO :
|
// TODO :
|
||||||
|
@ -52,5 +56,6 @@ public class ToDoConstants {
|
||||||
// 9. Normalizing streets
|
// 9. Normalizing streets
|
||||||
// 10. Reinvent index mechanism (save in zip file with tile indexes, save city/town addresses separately, read partially !)
|
// 10. Reinvent index mechanism (save in zip file with tile indexes, save city/town addresses separately, read partially !)
|
||||||
// 11. Street setName() change in city index!
|
// 11. Street setName() change in city index!
|
||||||
|
// 12. Invent different file extensions for poi.index, address.index,...
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,14 @@ public class MapTileDownloader {
|
||||||
return currentlyDownloaded.contains(f);
|
return currentlyDownloaded.contains(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSomethingBeingDownloaded(){
|
||||||
|
return !currentlyDownloaded.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRemainingWorkers(){
|
||||||
|
return (int) (threadPoolExecutor.getTaskCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void refuseAllPreviousRequests(){
|
public void refuseAllPreviousRequests(){
|
||||||
while(!threadPoolExecutor.getQueue().isEmpty()){
|
while(!threadPoolExecutor.getQueue().isEmpty()){
|
||||||
|
@ -130,7 +138,7 @@ public class MapTileDownloader {
|
||||||
|
|
||||||
|
|
||||||
private class DownloadMapWorker implements Runnable, Comparable<DownloadMapWorker> {
|
private class DownloadMapWorker implements Runnable, Comparable<DownloadMapWorker> {
|
||||||
private long time = System.currentTimeMillis();
|
|
||||||
private DownloadRequest request;
|
private DownloadRequest request;
|
||||||
|
|
||||||
private DownloadMapWorker(DownloadRequest request){
|
private DownloadMapWorker(DownloadRequest request){
|
||||||
|
@ -143,6 +151,7 @@ public class MapTileDownloader {
|
||||||
log.debug("Start downloading tile : " + request.url);
|
log.debug("Start downloading tile : " + request.url);
|
||||||
}
|
}
|
||||||
if (request != null && request.fileToSave != null && request.url != null) {
|
if (request != null && request.fileToSave != null && request.url != null) {
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
currentlyDownloaded.add(request.fileToSave);
|
currentlyDownloaded.add(request.fileToSave);
|
||||||
try {
|
try {
|
||||||
request.fileToSave.getParentFile().mkdirs();
|
request.fileToSave.getParentFile().mkdirs();
|
||||||
|
|
|
@ -398,6 +398,7 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.zoom = zoom;
|
this.zoom = zoom;
|
||||||
|
updateLocationLabel();
|
||||||
prepareImage();
|
prepareImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,7 +530,7 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
new TileBundleDownloadDialog(MapPanel.this, MapPanel.this).showDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,243 @@
|
||||||
|
package com.osmand.swing;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.SpinnerNumberModel;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
|
import com.osmand.ExceptionHandler;
|
||||||
|
import com.osmand.data.preparation.MapTileDownloader;
|
||||||
|
import com.osmand.data.preparation.MapTileDownloader.DownloadRequest;
|
||||||
|
import com.osmand.data.preparation.MapTileDownloader.IMapDownloaderCallback;
|
||||||
|
import com.osmand.map.ITileSource;
|
||||||
|
import com.osmand.osm.MapUtils;
|
||||||
|
import com.osmand.swing.MapPanel.MapSelectionArea;
|
||||||
|
|
||||||
|
public class TileBundleDownloadDialog extends JDialog {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -4862884032977071296L;
|
||||||
|
|
||||||
|
private JLabel label;
|
||||||
|
private ITileSource map;
|
||||||
|
private MapSelectionArea selectionArea;
|
||||||
|
private int zoom;
|
||||||
|
private JSpinner startSpinner;
|
||||||
|
private JSpinner endSpinner;
|
||||||
|
private JButton downloadButton;
|
||||||
|
private JButton cancelButton;
|
||||||
|
private File tilesLocation;
|
||||||
|
|
||||||
|
public TileBundleDownloadDialog(Component parent, MapPanel panel){
|
||||||
|
super(JOptionPane.getFrameForComponent(parent), true);
|
||||||
|
map = panel.getMap();
|
||||||
|
panel.getLatitude();
|
||||||
|
selectionArea = panel.getSelectionArea();
|
||||||
|
zoom = panel.getZoom();
|
||||||
|
tilesLocation = panel.getTilesLocation();
|
||||||
|
setTitle("Download bundle tiles");
|
||||||
|
initDialog();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showDialog(){
|
||||||
|
setSize(550, 150);
|
||||||
|
double x = getParent().getBounds().getCenterX();
|
||||||
|
double y = getParent().getBounds().getCenterY();
|
||||||
|
setLocation((int) x - getWidth() / 2, (int) y - getHeight() / 2);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SpinnerNumberModel getSpinnerModel(int minimum, int maximum){
|
||||||
|
SpinnerNumberModel model = new SpinnerNumberModel();
|
||||||
|
model.setStepSize(1);
|
||||||
|
model.setValue(zoom);
|
||||||
|
model.setMaximum(maximum);
|
||||||
|
model.setMinimum(minimum);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDialog() {
|
||||||
|
JPanel pane = new JPanel(new BorderLayout());
|
||||||
|
pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
add(pane);
|
||||||
|
|
||||||
|
label = new JLabel();
|
||||||
|
pane.add(label, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel zoomControls = new JPanel();
|
||||||
|
zoomControls.setLayout(new BoxLayout(zoomControls, BoxLayout.X_AXIS));
|
||||||
|
|
||||||
|
JLabel lab = new JLabel("Start zoom level : ");
|
||||||
|
zoomControls.add(lab);
|
||||||
|
startSpinner = new JSpinner(getSpinnerModel(map.getMinimumZoomSupported(), zoom));
|
||||||
|
zoomControls.add(startSpinner);
|
||||||
|
startSpinner.setMaximumSize(new Dimension(15, startSpinner.getMaximumSize().height));
|
||||||
|
|
||||||
|
zoomControls.add(Box.createHorizontalStrut(15));
|
||||||
|
lab = new JLabel("End zoom level : ");
|
||||||
|
zoomControls.add(lab);
|
||||||
|
endSpinner = new JSpinner(getSpinnerModel(zoom, map.getMaximumZoomSupported()));
|
||||||
|
zoomControls.add(endSpinner);
|
||||||
|
endSpinner.setMaximumSize(new Dimension(15, endSpinner.getMaximumSize().height));
|
||||||
|
zoomControls.add(Box.createHorizontalGlue());
|
||||||
|
pane.add(zoomControls, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
|
||||||
|
JPanel buttonControls = new JPanel();
|
||||||
|
buttonControls.setLayout(new BoxLayout(buttonControls, BoxLayout.X_AXIS));
|
||||||
|
buttonControls.add(Box.createHorizontalGlue());
|
||||||
|
downloadButton = new JButton("Download tiles");
|
||||||
|
buttonControls.add(downloadButton);
|
||||||
|
buttonControls.add(Box.createHorizontalStrut(3));
|
||||||
|
cancelButton = new JButton("Cancel");
|
||||||
|
buttonControls.add(cancelButton);
|
||||||
|
pane.add(buttonControls, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
updateLabel();
|
||||||
|
addListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addListeners(){
|
||||||
|
cancelButton.addActionListener(new ActionListener(){
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
startSpinner.addChangeListener(new ChangeListener(){
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
((SpinnerNumberModel)endSpinner.getModel()).setMinimum((Integer) startSpinner.getValue());
|
||||||
|
updateLabel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
endSpinner.addChangeListener(new ChangeListener(){
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
((SpinnerNumberModel)startSpinner.getModel()).setMaximum((Integer) endSpinner.getValue());
|
||||||
|
updateLabel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
downloadButton.addActionListener(new ActionListener(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
downloadTiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadTiles(){
|
||||||
|
setVisible(false);
|
||||||
|
final ProgressDialog progressDialog = new ProgressDialog(this, "Downloading tiles");
|
||||||
|
int numberTiles = 0;
|
||||||
|
final int startZoom = (Integer) startSpinner.getValue();
|
||||||
|
final int endZoom = (Integer) endSpinner.getValue();
|
||||||
|
for (int zoom = startZoom; zoom <= endZoom; zoom++) {
|
||||||
|
int x1 = (int) MapUtils.getTileNumberX(zoom, selectionArea.getLon1());
|
||||||
|
int x2 = (int) MapUtils.getTileNumberX(zoom, selectionArea.getLon2());
|
||||||
|
int y1 = (int) MapUtils.getTileNumberY(zoom, selectionArea.getLat1());
|
||||||
|
int y2 = (int) MapUtils.getTileNumberY(zoom, selectionArea.getLat2());
|
||||||
|
numberTiles += (x2 - x1 + 1) * (y2 - y1 + 1);
|
||||||
|
}
|
||||||
|
final int number = numberTiles;
|
||||||
|
final MapTileDownloader instance = MapTileDownloader.getInstance();
|
||||||
|
progressDialog.setRunnable(new Runnable(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
progressDialog.startTask("Loading...", number);
|
||||||
|
for (int zoom = startZoom; zoom <= endZoom; zoom++) {
|
||||||
|
int x1 = (int) MapUtils.getTileNumberX(zoom, selectionArea.getLon1());
|
||||||
|
int x2 = (int) MapUtils.getTileNumberX(zoom, selectionArea.getLon2());
|
||||||
|
int y1 = (int) MapUtils.getTileNumberY(zoom, selectionArea.getLat1());
|
||||||
|
int y2 = (int) MapUtils.getTileNumberY(zoom, selectionArea.getLat2());
|
||||||
|
for(int x = x1; x <= x2; x++){
|
||||||
|
for(int y=y1; y<= y2; y++){
|
||||||
|
String file = getFileForImage(x, y, zoom, map.getTileFormat());
|
||||||
|
if(new File(tilesLocation, file).exists()){
|
||||||
|
progressDialog.progress(1);
|
||||||
|
} else {
|
||||||
|
DownloadRequest req = new DownloadRequest(map.getUrlToLoad(x, y, zoom),
|
||||||
|
new File(tilesLocation, file), x, y, zoom);
|
||||||
|
instance.requestToDownload(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(instance.isSomethingBeingDownloaded()){
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
IMapDownloaderCallback previousCallback = instance.getDownloaderCallback();
|
||||||
|
instance.setDownloaderCallback(new IMapDownloaderCallback(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tileDownloaded(DownloadRequest request) {
|
||||||
|
// TODO request could be null if bundle loading?
|
||||||
|
progressDialog.progress(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
progressDialog.run();
|
||||||
|
instance.refuseAllPreviousRequests();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
ExceptionHandler.handle((Exception) e.getCause());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
ExceptionHandler.handle(e);
|
||||||
|
} finally {
|
||||||
|
instance.setDownloaderCallback(previousCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileForImage (int x, int y, int zoom, String ext){
|
||||||
|
return map.getName() +"/"+zoom+"/"+(x) +"/"+y+ext+".tile";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void updateLabel(){
|
||||||
|
int numberTiles = 0;
|
||||||
|
for (int zoom = (Integer) startSpinner.getValue(); zoom <= (Integer) endSpinner.getValue(); zoom++) {
|
||||||
|
int x1 = (int) MapUtils.getTileNumberX(zoom, selectionArea.getLon1());
|
||||||
|
int x2 = (int) MapUtils.getTileNumberX(zoom, selectionArea.getLon2());
|
||||||
|
int y1 = (int) MapUtils.getTileNumberY(zoom, selectionArea.getLat1());
|
||||||
|
int y2 = (int) MapUtils.getTileNumberY(zoom, selectionArea.getLat2());
|
||||||
|
numberTiles += (x2 - x1 + 1) * (y2 - y1 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String text = MessageFormat.format("Request to download {0} tiles from ''{1}'' (approximately {2} Mb)",
|
||||||
|
numberTiles, map.getName(), (double)numberTiles*12/1000);
|
||||||
|
label.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue