refactor filter load for specified area

git-svn-id: https://osmand.googlecode.com/svn/trunk@60 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-05-16 07:22:09 +00:00
parent db441f5179
commit c845cd9175
8 changed files with 243 additions and 179 deletions

View file

@ -28,7 +28,6 @@ public class ToDoConstants {
// 1. POI SEARCH NEAR TO YOU
// 2. FIX BACK TO your location & gps & point of view (may be compass)
// 3. Revise UI icons/layout
// 4. Fix Java Spring to prepare your data!!! (add progress, import/export data)
// 5. Enable city/streets/buildings index
// 7. Search for city/streets/buildings!
// 8. Enable change POI directly on map
@ -41,10 +40,9 @@ public class ToDoConstants {
/// SWING version :
// TODO :
// 1. Add preferences dialog (use internet, )
// 2. specify area to download tiles ()
// 2. implement bundle downloading tiles ()
// 3. download tiles without using dir tiles
// 4. Config file log & see log from file
// 5. specify area to load map (filter for osm loading)
// 6. Predefine what should be extracted from osm (building, poi or roads)
// 7. Fix TODO in files (accept amenity - way)

View file

@ -21,6 +21,7 @@ public class City extends MapObject<Node> {
public double getRadius() {
return radius;
}
}
private final Node el;

View file

@ -10,20 +10,15 @@ import java.util.Map;
import com.osmand.Algoritms;
import com.osmand.data.City.CityType;
import com.osmand.osm.Entity;
import com.osmand.osm.LatLon;
import com.osmand.osm.MapUtils;
import com.osmand.osm.Node;
import com.osmand.osm.OSMSettings.OSMTagKey;
import com.osmand.osm.io.OsmBaseStorage;
public class Region {
private Entity entity;
private DataTileManager<Amenity> amenities = new DataTileManager<Amenity>();
private String name;
private OsmBaseStorage storage;
private static class CityComparator implements Comparator<City>{
@ -42,12 +37,12 @@ public class Region {
}
}
public Region(Entity entity){
this.entity = entity;
public Region(){
this.name = "Region";
}
public OsmBaseStorage getStorage() {
return storage;
}
@ -56,16 +51,10 @@ public class Region {
this.storage = storage;
}
public void setEntity(Entity e){
this.entity = e;
}
public String getName(){
if(name != null){
return name;
}
return entity == null ? "" : entity.getTag(OSMTagKey.NAME);
}
public void setName(String name) {
this.name = name;
@ -167,5 +156,4 @@ public class Region {
}
}

View file

@ -1,5 +1,6 @@
package com.osmand.data.preparation;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@ -17,6 +18,7 @@ import org.apache.tools.bzip2.CBZip2InputStream;
import org.apache.tools.bzip2.CBZip2OutputStream;
import org.xml.sax.SAXException;
import com.osmand.Algoritms;
import com.osmand.IProgress;
import com.osmand.data.Amenity;
import com.osmand.data.City;
@ -35,7 +37,6 @@ import com.osmand.osm.OSMSettings.OSMTagKey;
import com.osmand.osm.io.IOsmStorageFilter;
import com.osmand.osm.io.OSMStorageWriter;
import com.osmand.osm.io.OsmBaseStorage;
import com.osmand.swing.OsmExtractionUI;
// TO implement
@ -75,9 +76,10 @@ import com.osmand.swing.OsmExtractionUI;
public class DataExtraction {
private static final Log log = LogFactory.getLog(DataExtraction.class);
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XMLStreamException {
new DataExtraction().testReadingOsmFile();
}
// public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XMLStreamException {
// new DataExtraction().testReadingOsmFile();
// }
// External files
public static String pathToTestDataDir = "E:\\Information\\OSM maps\\";
public static String pathToOsmFile = pathToTestDataDir + "minsk.osm";
@ -85,17 +87,13 @@ public class DataExtraction {
public static String pathToWorkingDir = pathToTestDataDir +"osmand\\";
public static String pathToDirWithTiles = pathToWorkingDir +"tiles";
public static String writeTestOsmFile = "C:\\1_tmp.osm"; // could be null - wo writing
private static boolean parseSmallFile = true;
private static boolean parseOSM = true;
private ArrayList<Way> ways;
private ArrayList<Amenity> amenities;
private ArrayList<Entity> buildings;
private ArrayList<Node> places;
private DataTileManager<Way> waysManager;
///////////////////////////////////////////
// 1. Reading data - preparing data for UI
// Test method for local purposes
public void testReadingOsmFile() throws ParserConfigurationException, SAXException, IOException, XMLStreamException {
String f;
if(parseSmallFile){
@ -107,21 +105,15 @@ public class DataExtraction {
Region country;
if(parseOSM){
country = readCountry(f, new ConsoleProgressImplementation());
country = readCountry(f, new ConsoleProgressImplementation(), null);
} else {
country = new Region(null);
country = new Region();
country.setStorage(new OsmBaseStorage());
}
OsmExtractionUI ui = new OsmExtractionUI(country);
ui.createUI();
// TODO add interested objects
List<Long> interestedObjects = new ArrayList<Long>();
// MapUtils.addIdsToList(places, interestedObjects);
// MapUtils.addIdsToList(amenities, interestedObjects);
MapUtils.addIdsToList(waysManager.getAllObjects(), interestedObjects);
// MapUtils.addIdsToList(buildings, interestedObjects);
if (writeTestOsmFile != null) {
OSMStorageWriter writer = new OSMStorageWriter(country.getStorage().getRegisteredEntities());
OutputStream output = new FileOutputStream(writeTestOsmFile);
@ -141,28 +133,28 @@ public class DataExtraction {
}
public Region readCountry(String path, IProgress progress, IOsmStorageFilter... filters) throws IOException, SAXException{
InputStream stream = new FileInputStream(path);
public Region readCountry(String path, IProgress progress, IOsmStorageFilter addFilter) throws IOException, SAXException{
File f = new File(path);
InputStream stream = new FileInputStream(f);
InputStream streamFile = stream;
long st = System.currentTimeMillis();
if (path.endsWith(".bz2")) {
if (stream.read() != 'B' || stream.read() != 'Z')
throw new RuntimeException(
"The source stream must start with the characters BZ if it is to be read as a BZip2 stream.");
else
if (stream.read() != 'B' || stream.read() != 'Z') {
throw new RuntimeException("The source stream must start with the characters BZ if it is to be read as a BZip2 stream.");
} else {
stream = new CBZip2InputStream(stream);
}
}
if(progress != null){
progress.startTask("Loading file " + path, -1);
}
// preloaded data
places = new ArrayList<Node>();
buildings = new ArrayList<Entity>();
amenities = new ArrayList<Amenity>();
// highways count
ways = new ArrayList<Way>();
final ArrayList<Node> places = new ArrayList<Node>();
final ArrayList<Entity> buildings = new ArrayList<Entity>();
final ArrayList<Amenity> amenities = new ArrayList<Amenity>();
final ArrayList<Way> ways = new ArrayList<Way>();
IOsmStorageFilter filter = new IOsmStorageFilter(){
@Override
@ -190,12 +182,8 @@ public class DataExtraction {
};
OsmBaseStorage storage = new OsmBaseStorage();
if(filters != null){
for(IOsmStorageFilter f : filters){
if(f != null){
storage.getFilters().add(f);
}
}
if (addFilter != null) {
storage.getFilters().add(addFilter);
}
storage.getFilters().add(filter);
@ -204,29 +192,59 @@ public class DataExtraction {
log.debug("File parsed : " + (System.currentTimeMillis() - st));
}
// 1. found towns !
Region country = new Region(null);
// 1. Initialize region
Region country = new Region();
int i = f.getName().indexOf('.');
country.setName(Algoritms.capitalizeFirstLetterAndLowercase(f.getName().substring(0, i)));
country.setStorage(storage);
for (Node s : places) {
String place = s.getTag(OSMTagKey.PLACE);
if(place == null){
continue;
// 2. Reading amenities
readingAmenities(amenities, country);
// 3. Reading cities
readingCities(places, country);
// 4. Reading streets
readingStreets(progress, ways, country);
// 5. reading buildings
readingBuildings(progress, buildings, country);
country.doDataPreparation();
return country;
}
if("country".equals(place)){
country.setEntity(s);
private void readingBuildings(IProgress progress, final ArrayList<Entity> buildings, Region country) {
// found buildings (index addresses)
progress.startTask("Indexing buildings...", buildings.size());
for(Entity b : buildings){
LatLon center = b.getLatLon();
progress.progress(1);
// TODO first of all tag could be checked NodeUtil.getTag(e, "addr:city")
if(center == null){
// no nodes where loaded for this way
} else {
country.registerCity(s);
City city = country.getClosestCity(center);
if(city == null){
Node n = new Node(center.getLatitude(), center.getLongitude(), -1);
n.putTag(OSMTagKey.PLACE.getValue(), CityType.TOWN.name());
n.putTag(OSMTagKey.NAME.getValue(), "Uknown city");
country.registerCity(n);
city = country.getClosestCity(center);
}
if (city != null) {
city.registerBuilding(b);
}
}
}
progress.finishTask();
}
for(Amenity a: amenities){
country.registerAmenity(a);
}
private void readingStreets(IProgress progress, final ArrayList<Way> ways, Region country) {
progress.startTask("Indexing streets...", ways.size());
waysManager = new DataTileManager<Way>();
DataTileManager<Way> waysManager = new DataTileManager<Way>();
for (Way w : ways) {
progress.progress(1);
if (w.getTag(OSMTagKey.NAME) != null) {
@ -254,35 +272,24 @@ public class DataExtraction {
}
progress.finishTask();
/// way with name : МЗОР, ул. ...,
// found buildings (index addresses)
progress.startTask("Indexing buildings...", buildings.size());
for(Entity b : buildings){
LatLon center = b.getLatLon();
progress.progress(1);
// TODO first of all tag could be checked NodeUtil.getTag(e, "addr:city")
if(center == null){
// no nodes where loaded for this way
} else {
City city = country.getClosestCity(center);
if(city == null){
Node n = new Node(center.getLatitude(), center.getLongitude(), -1);
n.putTag(OSMTagKey.PLACE.getValue(), CityType.TOWN.name());
n.putTag(OSMTagKey.NAME.getValue(), "Uknown city");
country.registerCity(n);
city = country.getClosestCity(center);
}
if (city != null) {
city.registerBuilding(b);
}
}
}
progress.finishTask();
country.doDataPreparation();
return country;
}
private void readingAmenities(final ArrayList<Amenity> amenities, Region country) {
for(Amenity a: amenities){
country.registerAmenity(a);
}
}
public void readingCities(ArrayList<Node> places, Region country) {
for (Node s : places) {
String place = s.getTag(OSMTagKey.PLACE);
if (place == null) {
continue;
}
country.registerCity(s);
}
}
}

View file

@ -62,8 +62,15 @@ public abstract class Entity {
public abstract LatLon getLatLon();
public boolean isVirtual(){
return id < 0;
}
@Override
public int hashCode() {
if (id < 0) {
return System.identityHashCode(this);
}
return (int) id;
}
@ -78,6 +85,10 @@ public abstract class Entity {
Entity other = (Entity) obj;
if (id != other.id)
return false;
// virtual are not equal
if(id < 0){
return false;
}
return true;
}
}

View file

@ -2,6 +2,7 @@ package com.osmand.swing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
@ -28,9 +29,15 @@ import java.util.Map;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
@ -149,6 +156,10 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
private MapTileDownloader downloader = MapTileDownloader.getInstance();
Map<String, Image> cache = new HashMap<String, Image>();
private JLabel gpsLocation;
private JButton areaButton;
public MapPanel(File fileWithTiles) {
@ -159,6 +170,8 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
zoom = DataExtractionSettings.getSettings().getDefaultZoom();
addControls();
downloader.setDownloaderCallback(this);
setFocusable(true);
addComponentListener(new ComponentAdapter(){
@ -172,7 +185,7 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
addMouseMotionListener(mouse);
addMouseWheelListener(mouse);
addZoomButtons();
}
@ -228,10 +241,8 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
g.fillRect(r.x, r.y, r.width, r.height);
}
g.setColor(Color.black);
String s = MessageFormat.format("Lat : {0}, lon : {1}, zoom : {2}", latitude, longitude, zoom);
g.drawString(s, 5, 20);
g.setColor(Color.black);
g.fillOval(getWidth() / 2 - 2, getHeight() / 2 - 2, 4, 4);
g.drawOval(getWidth() / 2 - 2, getHeight() / 2 - 2, 4, 4);
g.drawOval(getWidth() / 2 - 5, getHeight() / 2 - 5, 10, 10);
@ -294,6 +305,10 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
return cache.get(file);
}
public void setAreaActionHandler(Action a){
areaButton.setAction(a);
}
@Override
public void tileDownloaded(DownloadRequest request) {
int tileSize = getTileSize();
@ -428,7 +443,12 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
listeners.remove(l);
}
private void updateLocationLabel(){
gpsLocation.setText(MessageFormat.format("Lat : {0}, lon : {1}, zoom : {2}", latitude, longitude, zoom));
}
protected void fireMapLocationListeners(){
updateLocationLabel();
for(IMapLocationListener l : listeners){
l.locationChanged(latitude, longitude, null);
}
@ -458,7 +478,7 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
}
}
if(e.getID() == KeyEvent.KEY_TYPED){
if(e.getKeyChar() == '+'){
if(e.getKeyChar() == '+' || e.getKeyChar() == '=' ){
if(zoom < map.getMaximumZoomSupported()){
zoom ++;
processed = true;
@ -488,9 +508,27 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
prepareImage();
}
public void addZoomButtons(){
public void addControls(){
BoxLayout layout = new BoxLayout(this, BoxLayout.LINE_AXIS);
setLayout(layout);
setBorder(BorderFactory.createEmptyBorder(2, 10, 10, 10));
gpsLocation = new JLabel();
gpsLocation.setOpaque(false);
updateLocationLabel();
JButton zoomIn = new JButton("+");
JButton zoomOut = new JButton("-");
areaButton = new JButton();
areaButton.setAction(new AbstractAction("Preload area"){
private static final long serialVersionUID = -5512220294374994021L;
@Override
public void actionPerformed(ActionEvent e) {
}
});
zoomIn.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
@ -503,8 +541,17 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
setZoom(getZoom() - 1);
}
});
add(gpsLocation);
add(Box.createHorizontalGlue());
add(areaButton);
add(zoomIn);
add(zoomOut);
gpsLocation.setAlignmentY(Component.TOP_ALIGNMENT);
areaButton.setVisible(false);
areaButton.setAlignmentY(Component.TOP_ALIGNMENT);
zoomOut.setAlignmentY(Component.TOP_ALIGNMENT);
zoomIn.setAlignmentY(Component.TOP_ALIGNMENT);
}
public class MapSelectionArea {
@ -569,6 +616,7 @@ public class MapPanel extends JPanel implements IMapDownloaderCallback {
lat2 = MapUtils.getLatitudeFromTile(zoom, yTile2);
lon1 = MapUtils.getLongitudeFromTile(zoom, xTile1);
lon2 = MapUtils.getLongitudeFromTile(zoom, xTile2);
areaButton.setVisible(isVisible());
}
}

View file

@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.AbstractAction;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JCheckBox;
@ -108,14 +109,12 @@ public class OsmExtractionUI implements IMapLocationListener {
private JButton generateDataButton;
private JCheckBox buildPoiIndex;
private JCheckBox buildAddressIndex;
private JCheckBox filterAreaToLoad;
private TreeModelListener treeModelListener;
public OsmExtractionUI(final Region r){
this.region = r;
mapPanel = new MapPanel(DataExtractionSettings.getSettings().getTilesDirectory());
createUI();
setRegion(r, "Region");
}
@ -187,6 +186,10 @@ public class OsmExtractionUI implements IMapLocationListener {
Container content = frame.getContentPane();
frame.setFocusable(true);
mapPanel = new MapPanel(DataExtractionSettings.getSettings().getTilesDirectory());
mapPanel.setFocusable(true);
mapPanel.addMapLocationListener(this);
statusBarLabel = new JLabel();
content.add(statusBarLabel, BorderLayout.SOUTH);
File workingDir = DataExtractionSettings.getSettings().getDefaultWorkingDir();
@ -196,8 +199,8 @@ public class OsmExtractionUI implements IMapLocationListener {
JSplitPane panelForTreeAndMap = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(createTree(content)), mapPanel);
panelForTreeAndMap.setResizeWeight(0.2);
mapPanel.setFocusable(true);
mapPanel.addMapLocationListener(this);
createButtonsBar(content);
@ -324,11 +327,6 @@ public class OsmExtractionUI implements IMapLocationListener {
panel.add(buildAddressIndex);
buildAddressIndex.setSelected(true);
filterAreaToLoad = new JCheckBox();
filterAreaToLoad.setText("Filtering area when load file");
panel.add(filterAreaToLoad);
filterAreaToLoad.setSelected(false);
updateButtonsBar();
}
@ -401,6 +399,9 @@ public class OsmExtractionUI implements IMapLocationListener {
bar.add(menu);
JMenuItem loadFile = new JMenuItem("Load osm file...");
menu.add(loadFile);
JMenuItem loadSpecifiedAreaFile = new JMenuItem("Load osm file for specifed area...");
menu.add(loadSpecifiedAreaFile);
menu.addSeparator();
JMenuItem saveOsmFile = new JMenuItem("Save data to osm file...");
menu.add(saveOsmFile);
JMenuItem specifyWorkingDir = new JMenuItem("Specify working directory...");
@ -438,33 +439,56 @@ public class OsmExtractionUI implements IMapLocationListener {
}
});
loadSpecifiedAreaFile.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = getOsmFileChooser();
int answer = fc.showOpenDialog(frame) ;
if (answer == JFileChooser.APPROVE_OPTION && fc.getSelectedFile() != null){
final JDialog dlg = new JDialog(frame, true);
dlg.setTitle("Select area to filter");
MapPanel panel = new MapPanel(DataExtractionSettings.getSettings().getTilesDirectory());
panel.setLatLon(mapPanel.getLatitude(), mapPanel.getLongitude());
panel.setZoom(mapPanel.getZoom());
final StringBuilder res = new StringBuilder();
panel.setAreaActionHandler(new AbstractAction("Select area"){
private static final long serialVersionUID = -3452957517341961969L;
@Override
public void actionPerformed(ActionEvent e) {
res.append(true);
dlg.setVisible(false);
}
});
dlg.add(panel);
JMenuBar bar = new JMenuBar();
bar.add(MapPanel.getMenuToChooseSource(panel));
dlg.setJMenuBar(bar);
dlg.setSize(512, 512);
double x = frame.getBounds().getCenterX();
double y = frame.getBounds().getCenterY();
dlg.setLocation((int) x - dlg.getWidth() / 2, (int) y - dlg.getHeight() / 2);
dlg.setVisible(true);
if(res.length() > 0 && panel.getSelectionArea().isVisible()){
MapSelectionArea area = panel.getSelectionArea();
IOsmStorageFilter filter = new OsmBoundsFilter(area.getLat1(), area.getLon1(), area.getLat2(), area.getLon2());
loadCountry(fc.getSelectedFile(), filter);
}
}
}
});
loadFile.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Choose osm file");
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setAcceptAllFileFilterUsed(true);
fc.setCurrentDirectory(DataExtractionSettings.getSettings().getDefaultWorkingDir().getParentFile());
//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)";
}
});
JFileChooser fc = getOsmFileChooser();
int answer = fc.showOpenDialog(frame) ;
if (answer == JFileChooser.APPROVE_OPTION && fc.getSelectedFile() != null){
loadCountry(fc.getSelectedFile());
loadCountry(fc.getSelectedFile(), null);
}
}
@ -476,12 +500,22 @@ public class OsmExtractionUI implements IMapLocationListener {
if(region == null){
return;
}
JFileChooser fc = getOsmFileChooser();
int answer = fc.showSaveDialog(frame);
if (answer == JFileChooser.APPROVE_OPTION && fc.getSelectedFile() != null){
saveCountry(fc.getSelectedFile());
}
}
});
}
public JFileChooser getOsmFileChooser(){
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Choose osm file to save");
fc.setDialogTitle("Choose osm file");
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setAcceptAllFileFilterUsed(true);
fc.setCurrentDirectory(DataExtractionSettings.getSettings().getDefaultWorkingDir().getParentFile());
//System.out.println("opening fc for extension " + extension);
fc.setFileFilter(new FileFilter(){
@Override
@ -494,24 +528,10 @@ public class OsmExtractionUI implements IMapLocationListener {
return "Osm Files (*.bz2, *.osm)";
}
});
int answer = fc.showSaveDialog(frame);
if (answer == JFileChooser.APPROVE_OPTION && fc.getSelectedFile() != null){
saveCountry(fc.getSelectedFile());
}
return fc;
}
});
}
public void loadCountry(final File f){
final IOsmStorageFilter filter;
if(filterAreaToLoad.isSelected() && mapPanel.getSelectionArea().isVisible()){
MapSelectionArea area = mapPanel.getSelectionArea();
filter = new OsmBoundsFilter(area.getLat1(), area.getLon1(), area.getLat2(), area.getLon2());
} else {
filter = null;
}
public void loadCountry(final File f, final IOsmStorageFilter filter){
try {
final ProgressDialog dlg = new ProgressDialog(frame, "Loading osm file");
dlg.setRunnable(new Runnable(){
@ -531,10 +551,6 @@ public class OsmExtractionUI implements IMapLocationListener {
});
Region region = (Region) dlg.run();
if(region != null){
int i = f.getName().indexOf('.');
if(region.getName().isEmpty()){
region.setName(Algoritms.capitalizeFirstLetterAndLowercase(f.getName().substring(0, i)));
}
setRegion(region, region.getName());
frame.setTitle("OsmAnd Map Creator - " + f.getName());
} else {

View file

@ -24,7 +24,6 @@ public class ProgressDialog extends JDialog implements IProgress {
private InvocationTargetException exception = null;
private Object result;
private boolean finished;
@ -41,13 +40,9 @@ public class ProgressDialog extends JDialog implements IProgress {
}
public Object run() throws InvocationTargetException, InterruptedException {
finished = false;
result = null;
new WorkerThread().start();
setVisible(true);
if (!finished) {
}
if (exception != null) {
throw exception;
}