add progress implementation

git-svn-id: https://osmand.googlecode.com/svn/trunk@48 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-05-07 22:26:50 +00:00
parent 6d7a01ed9d
commit 2a94d0beb1
9 changed files with 408 additions and 109 deletions

View file

@ -19,6 +19,7 @@ import com.osmand.data.Amenity;
import com.osmand.data.City;
import com.osmand.data.DataTileManager;
import com.osmand.data.Region;
import com.osmand.impl.ConsoleProgressImplementation;
import com.osmand.osm.Entity;
import com.osmand.osm.LatLon;
import com.osmand.osm.MapUtils;
@ -102,7 +103,7 @@ public class DataExtraction {
OsmExtractionUI ui = new OsmExtractionUI(country);
ui.runUI();
ui.createUI();
List<Long> interestedObjects = new ArrayList<Long>();
// MapUtils.addIdsToList(places, interestedObjects);
@ -167,8 +168,6 @@ public class DataExtraction {
}
if (n.getTag(OSMTagKey.PLACE) != null) {
places.add(n);
if (places.size() % 500 == 0) System.out.println();
System.out.print("-");
}
return true;
@ -189,7 +188,7 @@ public class DataExtraction {
};
storage.parseOSM(stream);
storage.parseOSM(stream, new ConsoleProgressImplementation());
System.out.println("File parsed : " +(System.currentTimeMillis() - st));
// 1. found towns !

View file

@ -0,0 +1,27 @@
package com.osmand;
/**
* That common interface that could be used by background operations.
* Implementation of it depends on chosen UI platform
*/
public interface IProgress {
/**
* @param taskName
* @param work - -1 means that indeterminate task,
* otherwise number of could be specified
*/
public void startTask(String taskName, int work);
public void startWork(int work);
public void progress(int deltaWork);
public void remaining(int remainingWork);
public void finishTask();
public boolean isIndeterminate();
}

View file

@ -0,0 +1,72 @@
package com.osmand.impl;
import java.text.MessageFormat;
import com.osmand.Algoritms;
import com.osmand.IProgress;
public class ConsoleProgressImplementation implements IProgress {
public static double deltaPercentsToPrint = 3.5;
String currentTask;
int work;
int currentDone;
double lastPercentPrint = 0;
@Override
public void finishTask() {
System.out.println("Task " + currentTask + " is finished ");
this.currentTask = null;
}
@Override
public boolean isIndeterminate() {
return work == -1;
}
@Override
public void progress(int deltaWork) {
this.currentDone += deltaWork;
printIfNeeded();
}
private void printIfNeeded() {
if(getCurrentPercent() - lastPercentPrint >= deltaPercentsToPrint){
System.out.println(MessageFormat.format("Done {0} %.", getCurrentPercent()));
this.lastPercentPrint = getCurrentPercent();
}
}
public double getCurrentPercent(){
return (double) currentDone * 100d / work;
}
@Override
public void remaining(int remainingWork) {
this.currentDone = work - remainingWork;
printIfNeeded();
}
@Override
public void startTask(String taskName, int work) {
if(!Algoritms.objectEquals(currentTask, taskName)){
this.currentTask = taskName;
System.out.println("Started new task : " + currentTask + " - " + work);
}
startWork(work);
}
@Override
public void startWork(int work) {
if(this.work != work){
this.work = work;
System.out.println("Amount of work was changed to " + work);
}
this.currentDone = 0;
this.lastPercentPrint = 0;
}
}

View file

@ -15,6 +15,7 @@ import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.osmand.IProgress;
import com.osmand.osm.Entity;
import com.osmand.osm.Node;
import com.osmand.osm.Relation;
@ -48,6 +49,10 @@ public class OsmBaseStorage extends DefaultHandler {
protected Map<Long, Entity> entities = new LinkedHashMap<Long, Entity>();
// this is used to show feedback to user
private IProgress progress;
private InputStream inputStream;
/**
@ -55,11 +60,20 @@ public class OsmBaseStorage extends DefaultHandler {
* @throws IOException
* @throws SAXException - could be
*/
public synchronized void parseOSM(InputStream stream) throws IOException, SAXException {
public synchronized void parseOSM(InputStream stream, IProgress progress) throws IOException, SAXException {
this.inputStream = stream;
this.progress = progress;
SAXParser parser = initSaxParser();
parseStarted = false;
entities.clear();
if(progress != null){
progress.startWork(stream.available());
}
parser.parse(stream, this);
if(progress != null){
progress.finishTask();
}
completeReading();
}
@ -110,7 +124,6 @@ public class OsmBaseStorage extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
name = saxParser.isNamespaceAware() ? localName : name;
if(!parseStarted){
if(!ELEM_OSM.equals(name) || !supportedVersions.contains(attributes.getValue(ATTR_VERSION))){
throw new OsmVersionNotSupported();
@ -118,6 +131,13 @@ public class OsmBaseStorage extends DefaultHandler {
parseStarted = true;
}
if (currentParsedEntity == null) {
if(progress != null && !progress.isIndeterminate()){
try {
progress.remaining(inputStream.available());
} catch (IOException e) {
progress.startWork(-1);
}
}
if (ELEM_NODE.equals(name)) {
currentParsedEntity = new Node(parseDouble(attributes, ATTR_LAT, 0), parseDouble(attributes, ATTR_LON, 0),
parseId(attributes, ATTR_ID, -1));

View file

@ -3,12 +3,15 @@ package com.osmand.swing;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
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.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -19,6 +22,7 @@ import java.util.TreeMap;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
@ -34,8 +38,13 @@ import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import org.xml.sax.SAXException;
import com.osmand.DataExtraction;
import com.osmand.DefaultLauncherConstants;
import com.osmand.IMapLocationListener;
import com.osmand.data.Amenity;
@ -57,29 +66,39 @@ public class OsmExtractionUI implements IMapLocationListener {
private DefaultMutableTreeNode amenitiesTree;
private JTree treePlaces;
private JList searchList;
private final Region r;
private Region region;
private JFrame frame;
private JTextField searchTextField;
public OsmExtractionUI(final Region r){
this.r = r;
this.region = r;
createUI();
setRegion(r);
}
public static void main(String[] args) {
OsmExtractionUI ui = new OsmExtractionUI(null);
ui.runUI();
}
public void runUI(){
JFrame frame = new JFrame("Tree of choose");
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
public void setRegion(Region region){
if(this.region == region){
return;
}
DefaultMutableTreeNode root = new DataExtractionTreeNode(r.getName(), r);
amenitiesTree = new DataExtractionTreeNode("Amenities", r);
amenitiesTree.add(new DataExtractionTreeNode("closest", r));
this.region = region;
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
amenitiesTree = new DataExtractionTreeNode("Amenities", region);
amenitiesTree.add(new DataExtractionTreeNode("closest", region));
root.add(amenitiesTree);
for(CityType t : CityType.values()){
DefaultMutableTreeNode cityTree = new DataExtractionTreeNode(t.toString(), t);
root.add(cityTree);
for(City ct : r.getCitiesByType(t)){
for(City ct : region.getCitiesByType(t)){
DefaultMutableTreeNode cityNodeTree = new DataExtractionTreeNode(ct.getName(), ct);
cityTree.add(cityNodeTree);
@ -94,17 +113,35 @@ public class OsmExtractionUI implements IMapLocationListener {
}
}
}
DataTileManager<LatLon> amenitiesManager = new DataTileManager<LatLon>();
for(Amenity a : region.getAmenityManager().getAllObjects()){
amenitiesManager.registerObject(a.getNode().getLatitude(), a.getNode().getLongitude(), a.getNode().getLatLon());
}
mapPanel.setPoints(amenitiesManager);
updateListCities(region, searchTextField.getText(), searchList);
mapPanel.updateUI();
treePlaces.setModel(new DefaultTreeModel(root, false));
}
public void createUI(){
frame = new JFrame("Tree of choose");
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
frame.addWindowListener(new ExitListener());
Container content = frame.getContentPane();
frame.setFocusable(true);
treePlaces = new JTree(root);
final JList jList = new JList();
jList.setCellRenderer(new DefaultListCellRenderer(){
treePlaces = new JTree();
treePlaces.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Region"), false));
searchList = new JList();
searchList.setCellRenderer(new DefaultListCellRenderer(){
private static final long serialVersionUID = 4661949460526837891L;
@Override
@ -126,14 +163,8 @@ public class OsmExtractionUI implements IMapLocationListener {
mapPanel.addMapLocationListener(this);
DataTileManager<LatLon> amenitiesManager = new DataTileManager<LatLon>();
for(Amenity a : r.getAmenityManager().getAllObjects()){
amenitiesManager.registerObject(a.getNode().getLatitude(), a.getNode().getLongitude(), a.getNode().getLatLon());
}
mapPanel.setPoints(amenitiesManager);
JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(jList), panelForTreeAndImage);
JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(searchList), panelForTreeAndImage);
pane.setResizeWeight(0.2);
content.add(pane, BorderLayout.CENTER);
@ -141,37 +172,37 @@ public class OsmExtractionUI implements IMapLocationListener {
content.add(label, BorderLayout.SOUTH);
JPanel panel = new JPanel(new BorderLayout());
final JTextField textField = new JTextField();
searchTextField = new JTextField();
final JButton button = new JButton();
button.setText("Set town");
panel.add(textField, BorderLayout.CENTER);
panel.add(searchTextField, BorderLayout.CENTER);
panel.add(button, BorderLayout.WEST);
content.add(panel, BorderLayout.NORTH);
updateListCities(r, textField.getText(), jList);
textField.getDocument().addUndoableEditListener(new UndoableEditListener(){
updateListCities(region, searchTextField.getText(), searchList);
searchTextField.getDocument().addUndoableEditListener(new UndoableEditListener(){
@Override
public void undoableEditHappened(UndoableEditEvent e) {
updateListCities(r, textField.getText(), jList);
updateListCities(region, searchTextField.getText(), searchList);
}
});
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
selectedCity = (City)jList.getSelectedValue();
selectedCity = (City)searchList.getSelectedValue();
}
});
jList.addListSelectionListener(new ListSelectionListener(){
searchList.addListSelectionListener(new ListSelectionListener(){
@Override
public void valueChanged(ListSelectionEvent e) {
if(jList.getSelectedValue() != null){
Node node = ((City)jList.getSelectedValue()).getNode();
if(searchList.getSelectedValue() != null){
Node node = ((City)searchList.getSelectedValue()).getNode();
String text = "Lat : " + node.getLatitude() + " Lon " + node.getLongitude();
if(selectedCity != null){
text += " distance " + MapUtils.getDistance(selectedCity.getNode(), node);
@ -223,78 +254,136 @@ public class OsmExtractionUI implements IMapLocationListener {
});
MenuBar bar = new MenuBar();
bar.add(MapPanel.getMenuToChooseSource(mapPanel));
fillMenuWithActions(bar);
frame.setMenuBar(bar);
frame.setSize(1024, 768);
}
public void runUI(){
frame.setSize(1024, 768);
frame.setVisible(true);
}
@Override
public void locationChanged(final double newLatitude, final double newLongitude, Object source){
Region reg = (Region) amenitiesTree.getUserObject();
List<Amenity> closestAmenities = reg.getClosestAmenities(newLatitude, newLongitude);
Collections.sort(closestAmenities, new Comparator<Amenity>(){
public void fillMenuWithActions(MenuBar bar){
Menu menu = new Menu("File");
bar.add(menu);
MenuItem loadFile = new MenuItem("Load file...");
menu.add(loadFile);
bar.add(MapPanel.getMenuToChooseSource(mapPanel));
loadFile.addActionListener(new ActionListener(){
@Override
public int compare(Amenity o1, Amenity o2) {
return Double.compare(MapUtils.getDistance(o1.getNode(), newLatitude, newLongitude),
MapUtils.getDistance(o2.getNode(), newLatitude, newLongitude));
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Choose osm file");
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setAcceptAllFileFilterUsed(true);
fc.setCurrentDirectory(new File(DefaultLauncherConstants.pathToDirWithTiles));
//System.out.println("opening fc for extension " + extension);
fc.setFileFilter(new FileFilter(){
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().endsWith(".bz2") || f.getName().endsWith(".osm");
}
@Override
public String getDescription() {
return "Osm Files (*.bz2, *.osm)";
}
});
int answer = fc.showOpenDialog(frame) ;
if (answer == JFileChooser.APPROVE_OPTION && fc.getSelectedFile() != null){
try {
Region region = new DataExtraction().readCountry(fc.getSelectedFile().getAbsolutePath());
setRegion(region);
} catch (IOException e1) {
// TODO
e1.printStackTrace();
} catch (SAXException e1) {
// TODO
e1.printStackTrace();
}
}
}
});
Map<String, List<Amenity>> filter = new TreeMap<String, List<Amenity>>();
for(Amenity n : closestAmenities){
String type = n.getType().toString();
if(!filter.containsKey(type)){
filter.put(type, new ArrayList<Amenity>());
}
@Override
public void locationChanged(final double newLatitude, final double newLongitude, Object source){
if (amenitiesTree != null) {
Region reg = (Region) amenitiesTree.getUserObject();
List<Amenity> closestAmenities = reg.getClosestAmenities(newLatitude, newLongitude);
Collections.sort(closestAmenities, new Comparator<Amenity>() {
@Override
public int compare(Amenity o1, Amenity o2) {
return Double.compare(MapUtils.getDistance(o1.getNode(), newLatitude, newLongitude), MapUtils.getDistance(o2.getNode(),
newLatitude, newLongitude));
}
});
Map<String, List<Amenity>> filter = new TreeMap<String, List<Amenity>>();
for (Amenity n : closestAmenities) {
String type = n.getType().toString();
if (!filter.containsKey(type)) {
filter.put(type, new ArrayList<Amenity>());
}
filter.get(type).add(n);
}
filter.get(type).add(n);
}
for(int i=1; i< amenitiesTree.getChildCount(); ){
if(!filter.containsKey(((DefaultMutableTreeNode)amenitiesTree.getChildAt(i)).getUserObject())){
amenitiesTree.remove(i);
} else {
i++;
}
}
((DefaultMutableTreeNode)amenitiesTree.getChildAt(0)).removeAllChildren();
for(int i=0; i<15 && i < closestAmenities.size(); i++){
Amenity n = closestAmenities.get(i);
int dist = (int) (MapUtils.getDistance(n.getNode(), newLatitude, newLongitude));
String str = n.getSimpleFormat() + " [" +dist+" m ]";
((DefaultMutableTreeNode)amenitiesTree.getChildAt(0)).add(
new DataExtractionTreeNode(str, n));
}
for(String s : filter.keySet()){
DefaultMutableTreeNode p = null;
for(int i=0; i< amenitiesTree.getChildCount(); i++){
if(s.equals(((DefaultMutableTreeNode)amenitiesTree.getChildAt(i)).getUserObject())){
p = ((DefaultMutableTreeNode)amenitiesTree.getChildAt(i));
break;
for (int i = 1; i < amenitiesTree.getChildCount();) {
if (!filter.containsKey(((DefaultMutableTreeNode) amenitiesTree.getChildAt(i)).getUserObject())) {
amenitiesTree.remove(i);
} else {
i++;
}
}
if (p == null) {
p = new DefaultMutableTreeNode(s);
}
((DefaultMutableTreeNode) amenitiesTree.getChildAt(0)).removeAllChildren();
p.removeAllChildren();
for (Amenity n : filter.get(s)) {
for (int i = 0; i < 15 && i < closestAmenities.size(); i++) {
Amenity n = closestAmenities.get(i);
int dist = (int) (MapUtils.getDistance(n.getNode(), newLatitude, newLongitude));
String str = n.getSimpleFormat() + " [" + dist + " m ]";
DataExtractionTreeNode node = new DataExtractionTreeNode(str, n);
p.add(node);
((DefaultMutableTreeNode) amenitiesTree.getChildAt(0)).add(new DataExtractionTreeNode(str, n));
}
amenitiesTree.add(p);
for (String s : filter.keySet()) {
DefaultMutableTreeNode p = null;
for (int i = 0; i < amenitiesTree.getChildCount(); i++) {
if (s.equals(((DefaultMutableTreeNode) amenitiesTree.getChildAt(i)).getUserObject())) {
p = ((DefaultMutableTreeNode) amenitiesTree.getChildAt(i));
break;
}
}
if (p == null) {
p = new DefaultMutableTreeNode(s);
}
p.removeAllChildren();
for (Amenity n : filter.get(s)) {
int dist = (int) (MapUtils.getDistance(n.getNode(), newLatitude, newLongitude));
String str = n.getSimpleFormat() + " [" + dist + " m ]";
DataExtractionTreeNode node = new DataExtractionTreeNode(str, n);
p.add(node);
}
amenitiesTree.add(p);
}
treePlaces.updateUI();
}
treePlaces.updateUI();
}
public void updateListCities(Region r, String text, JList jList){
Collection<City> city = r.getSuggestedCities(text, 100);
Collection<City> city;
if(r == null){
city = Collections.emptyList();
} else {
city = r.getSuggestedCities(text, 100);
}
City[] names = new City[city.size()];
int i=0;
for(City c : city){

View file

@ -15,8 +15,6 @@
<activity android:name=".activities.SettingsActivity"
android:label="@string/settings_activity"></activity>
<activity android:name=".activities.SettingsActivity" android:label="@string/settings_activity"></activity>
</application>

View file

@ -0,0 +1,97 @@
package com.osmand;
import android.app.ProgressDialog;
import android.os.Handler;
import android.os.Message;
public class ProgressDialogImplementation implements IProgress {
private static final float deltaToChange = 0.04f;
private String taskName;
private int progress;
private int work;
private int deltaWork;
private String message = "";
private Handler mViewUpdateHandler;
public ProgressDialogImplementation(final ProgressDialog dlg){
mViewUpdateHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
dlg.setMessage(message);
}
};
}
@Override
public void progress(int deltaWork) {
this.deltaWork += deltaWork;
if(change(progress + deltaWork)){
this.progress += deltaWork;
updateMessage();
}
}
private void updateMessage() {
message = taskName + String.format(" %.1f %%", this.progress * 100f / ((float) this.work));
mViewUpdateHandler.sendEmptyMessage(0);
}
public boolean change(int newProgress) {
if (newProgress < progress) {
return false;
}
if ((newProgress - progress) / ((float) work) < deltaToChange) {
return false;
}
return true;
}
@Override
public void remaining(int remainingWork) {
if(change(work - remainingWork)){
this.progress = work - remainingWork;
updateMessage();
}
deltaWork = work - remainingWork - this.progress;
}
public boolean isIndeterminate(){
return work == -1;
}
@Override
public void startTask(String taskName, int work) {
if(taskName == null){
taskName = "";
}
message = taskName;
mViewUpdateHandler.sendEmptyMessage(0);
this.taskName = taskName;
startWork(work);
}
@Override
public void finishTask() {
if (taskName != null) {
message = "Finished : " + taskName;
mViewUpdateHandler.sendEmptyMessage(0);
}
work = -1;
progress = 0;
}
@Override
public void startWork(int work) {
this.work = work;
if(this.work == 0){
this.work = 1;
}
progress = 0;
deltaWork = 0;
}
}

View file

@ -14,7 +14,6 @@ import org.apache.commons.logging.Log;
import org.apache.tools.bzip2.CBZip2InputStream;
import org.xml.sax.SAXException;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
@ -192,7 +191,7 @@ public class ResourceManager {
// POI INDEX //
public void indexingPoi(ProgressDialog dlg){
public void indexingPoi(IProgress progress){
if (poiIndex == null) {
File file = new File(Environment.getExternalStorageDirectory(), POI_PATH);
poiIndex = new DataTileManager<Amenity>();
@ -202,9 +201,6 @@ public class ResourceManager {
if (log.isDebugEnabled()) {
log.debug("Starting index POI " + f.getAbsolutePath());
}
if(dlg != null){
dlg.setMessage("Indexing poi " + f.getName());
}
boolean zipped = f.getName().endsWith(".bz2");
InputStream stream = null;
try {
@ -220,7 +216,10 @@ public class ResourceManager {
stream = new CBZip2InputStream(stream);
}
}
storage.parseOSM(stream);
if(progress != null){
progress.startTask("Indexing poi " + f.getName(), stream.available());
}
storage.parseOSM(stream, progress);
for (Entity e : storage.getRegisteredEntities().values()) {
if (e instanceof Node && Amenity.isAmenity((Node) e)) {
poiIndex.registerObject(((Node)e).getLatitude(), ((Node)e).getLongitude(), new Amenity((Node) e));

View file

@ -12,6 +12,7 @@ import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.osmand.ProgressDialogImplementation;
import com.osmand.R;
import com.osmand.ResourceManager;
@ -33,10 +34,10 @@ public class MainMenuActivity extends Activity {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent mapIndent = new Intent(MainMenuActivity.this, MapActivity.class);
Notification notification = new Notification(R.drawable.icon, "Notify",
Notification notification = new Notification(R.drawable.icon, "",
System.currentTimeMillis());
notification.setLatestEventInfo(MainMenuActivity.this, "OsmAnd",
"OsmAnd are running in background", PendingIntent.getActivity(
"OsmAnd is running in background", PendingIntent.getActivity(
this.getBaseContext(), 0, mapIndent,
PendingIntent.FLAG_CANCEL_CURRENT));
mNotificationManager.notify(APP_NOTIFICATION_ID, notification);
@ -69,16 +70,13 @@ public class MainMenuActivity extends Activity {
}
});
// add notification
final ProgressDialog dlg = ProgressDialog.show(this, "Loading data",
"Reading indices...");
final ProgressDialog dlg = ProgressDialog.show(this, "Loading data", "Reading indices...");
final ProgressDialogImplementation impl = new ProgressDialogImplementation(dlg);
new Thread() {
@Override
public void run() {
try {
dlg.setMessage("Indexing poi...");
ResourceManager.getResourceManager().indexingPoi(dlg);
ResourceManager.getResourceManager().indexingPoi(impl);
} finally {
dlg.dismiss();
}