Index: /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/AddressEditAction.java
===================================================================
--- /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/AddressEditAction.java	(revision 23813)
+++ /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/AddressEditAction.java	(revision 23814)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.plugins.addressEdit;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.event.ActionEvent;
@@ -6,13 +8,17 @@
 import java.util.Collection;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.data.SelectionChangedListener;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener;
+import org.openstreetmap.josm.plugins.addressEdit.gui.AddressEditDialog;
+import org.openstreetmap.josm.plugins.addressEdit.gui.AddressEditModel;
 import org.openstreetmap.josm.tools.Shortcut;
-import static org.openstreetmap.josm.tools.I18n.tr;
 
 public class AddressEditAction extends JosmAction implements
-		SelectionChangedListener {
+SelectionChangedListener, CancelListener {
 
 	/**
@@ -20,12 +26,16 @@
 	 */
 	private static final long serialVersionUID = 1L;
+	private AddressEditModel addressModel;
+	private boolean isCanceled = false;
 
 	public AddressEditAction() {
-		super(tr("Address Editor"), "addressedit_24", tr("Handy Address Editing Functions"),
-                Shortcut.registerShortcut("tools:AddressEdit", tr("Tool: {0}", tr("Address Edit")),
-                        KeyEvent.VK_A, Shortcut.GROUP_MENU,
-                        InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK), false);
-        setEnabled(false);
-        DataSet.addSelectionListener(this);
+		super(tr("Address Editor"), "addressedit_24",
+				tr("Handy Address Editing Functions"), Shortcut
+				.registerShortcut("tools:AddressEdit", tr("Tool: {0}",
+						tr("Address Edit")), KeyEvent.VK_A,
+						Shortcut.GROUP_MENU, InputEvent.ALT_DOWN_MASK
+						| InputEvent.SHIFT_DOWN_MASK), false);
+		setEnabled(false);
+		DataSet.addSelectionListener(this);
 	}
 
@@ -33,34 +43,95 @@
 	public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
 		synchronized (this) {
-			AddressVisitor addrVisitor = new AddressVisitor();
-			
-			for (OsmPrimitive osm : newSelection) {
-	            osm.visit(addrVisitor);
-	        }
-			//generateTagCode(addrVisitor);
-			
-			addrVisitor.resolveAddresses();
+			collectAddressesAndStreets(newSelection);
 		}
 	}
+
+	@Override
+	public void actionPerformed(ActionEvent arg0) {
+		collectAddressesAndStreets(Main.main.getCurrentDataSet()
+				.allPrimitives());
+
+		if (addressModel != null) {
+			AddressEditDialog dlg = new AddressEditDialog(addressModel);
+			dlg.setVisible(true);
+		}
+	}
+
+	private void collectAddressesAndStreets(
+			final Collection<? extends OsmPrimitive> osmData) {
+		if (osmData == null || osmData.isEmpty())
+			return;
+
+		final AddressVisitor addrVisitor = new AddressVisitor();
+
+		//final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor(tr("Prepare OSM data..."));
+		// int ticks = osmData.size();
+
+
+
+		try {
+			for (OsmPrimitive osm : osmData) {
+				osm.visit(addrVisitor);
+
+				if (isCanceled) {
+					addrVisitor.clearData(); // free visitor data
+					return;
+				}
+			}
+			//monitor.worked(1);
+
+			// generateTagCode(addrVisitor);
+			//monitor.setCustomText(tr("Resolving addresses..."));
+			addrVisitor.resolveAddresses();
+			//monitor.worked(1);
+
+
+		} finally {
+			//monitor.close();
+		}
+
+		addressModel = new AddressEditModel(
+				addrVisitor.getStreetList(), 
+				addrVisitor.getUnresolvedItems());
+	}
+
+	@Override
+	protected void updateEnabledState() {
+		setEnabled(getCurrentDataSet() != null);
+	}
+
+	@Override
+	protected void updateEnabledState(
+			Collection<? extends OsmPrimitive> selection) {
+		setEnabled(selection != null && !selection.isEmpty());
+	}
+
+	/* ----------------------------------------- */
 
 	private void generateTagCode(AddressVisitor addrVisitor) {
 		/* This code is abused to generate tag utility code */
 		for (String tag : addrVisitor.getTags()) {
-			String methodName = createMethodName(tag);			
-			System.out.println(String.format("/** Check if OSM primitive has a tag '%s'.\n * @param osmPrimitive The OSM entity to check.*/\npublic static boolean has%sTag(OsmPrimitive osmPrimitive) {\n return osmPrimitive != null ? osmPrimitive.hasKey(%s_TAG) : false;\n}\n",
-					tag,
-					methodName, 
-					tag.toUpperCase().replaceAll(":", "_")));
-			System.out.println(String.format("/** Gets the value of tag '%s'.\n * @param osmPrimitive The OSM entity to check.*/\npublic static String get%sValue(OsmPrimitive osmPrimitive) {\n return osmPrimitive != null ? osmPrimitive.get(%s_TAG) : null;\n}\n",
-					tag,
-					methodName, 
-					tag.toUpperCase().replaceAll(":", "_")));
+			String methodName = createMethodName(tag);
+			System.out
+			.println(String
+					.format(
+							"/** Check if OSM primitive has a tag '%s'.\n * @param osmPrimitive The OSM entity to check.*/\npublic static boolean has%sTag(OsmPrimitive osmPrimitive) {\n return osmPrimitive != null ? osmPrimitive.hasKey(%s_TAG) : false;\n}\n",
+							tag, methodName, tag.toUpperCase()
+							.replaceAll(":", "_")));
+			System.out
+			.println(String
+					.format(
+							"/** Gets the value of tag '%s'.\n * @param osmPrimitive The OSM entity to check.*/\npublic static String get%sValue(OsmPrimitive osmPrimitive) {\n return osmPrimitive != null ? osmPrimitive.get(%s_TAG) : null;\n}\n",
+							tag, methodName, tag.toUpperCase()
+							.replaceAll(":", "_")));
 		}
-		
+
 		for (String tag : addrVisitor.getTags()) {
-			System.out.println(String.format("public static final String %s_TAG = \"%s\";", tag.toUpperCase().replaceAll(":", "_"), tag));
+			System.out.println(String.format(
+					"public static final String %s_TAG = \"%s\";", tag
+					.toUpperCase().replaceAll(":", "_"), tag));
 		}
 	}
-	
+
 	private String createMethodName(String osmName) {
 		StringBuffer result = new StringBuffer(osmName.length());
@@ -79,16 +150,15 @@
 					nextUp = false;
 				} else {
-					result.append(c);		
+					result.append(c);
 				}
 			}
 		}
-		
+
 		return result.toString();
 	}
 
 	@Override
-	public void actionPerformed(ActionEvent arg0) {
-
+	public void operationCanceled() {
+		isCanceled = true;
 	}
-
 }
Index: /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/AddressVisitor.java
===================================================================
--- /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/AddressVisitor.java	(revision 23813)
+++ /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/AddressVisitor.java	(revision 23814)
@@ -129,4 +129,8 @@
 		return streetDict;
 	}
+	
+	public List<StreetNode> getStreetList() {
+		return new ArrayList<StreetNode>(streetDict.values());
+	}
 
 	public List<AddressNode> getUnresolvedItems() {
@@ -174,3 +178,8 @@
 		System.out.println("Still unresolved: " + unresolvedAddresses.size() + " addresses");
 	}
+	
+	public void clearData() {
+		streetDict.clear();
+		unresolvedAddresses.clear();
+	}
 }
Index: /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/StreetNode.java
===================================================================
--- /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/StreetNode.java	(revision 23813)
+++ /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/StreetNode.java	(revision 23814)
@@ -67,4 +67,8 @@
 	}
 	
+	public boolean hasAddresses() {
+		return addresses != null && addresses.size() > 0;
+	}
+	
 	public List<AddressNode> getAddresses() {
 		return addresses;
Index: /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/gui/AddressEditDialog.java
===================================================================
--- /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/gui/AddressEditDialog.java	(revision 23814)
+++ /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/gui/AddressEditDialog.java	(revision 23814)
@@ -0,0 +1,121 @@
+/*
+ * 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 3 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 org.openstreetmap.josm.plugins.addressEdit.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.HeadlessException;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import static org.openstreetmap.josm.tools.I18n.tr;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JSplitPane;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeModel;
+
+public class AddressEditDialog extends JFrame implements ActionListener {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 6251676464816335631L;
+	private AddressEditModel model;
+	private JTree unresolvedTree;
+	private JTree incompleteTree;
+	private JTree streetsTree;
+	
+	/**
+	 * @param arg0
+	 * @throws HeadlessException
+	 */
+	public AddressEditDialog(AddressEditModel model) throws HeadlessException  {
+		super(tr("Edit Addresses"));
+	
+		this.model = model; 
+		setLayout(new BorderLayout());
+		setSize(800,600);
+		// TODO: Center on screen
+		setLocation(100, 100);
+
+		if (model != null) {
+			JPanel streetPanel = new JPanel(new BorderLayout());
+			streetsTree = new JTree(new DefaultTreeModel(model.getStreetsTree()));
+			JScrollPane scroll1 = new JScrollPane(streetsTree);
+			streetPanel.add(scroll1, BorderLayout.CENTER);
+			streetPanel.add(new JLabel("Unresolved Addresses"), BorderLayout.NORTH);
+			streetPanel.setMinimumSize(new Dimension(300, 400));
+			
+			JPanel unresolvedPanel = new JPanel(new BorderLayout());		
+			unresolvedTree = new JTree(new DefaultTreeModel(model.getUnresolvedAddressesTree()));
+			JScrollPane scroll2 = new JScrollPane(unresolvedTree);
+			unresolvedPanel.add(scroll2, BorderLayout.CENTER);
+			unresolvedPanel.add(new JLabel("Unresolved Addresses"), BorderLayout.NORTH);
+			unresolvedPanel.setMinimumSize(new Dimension(300, 200));
+			
+			JPanel incompletePanel = new JPanel(new BorderLayout());
+			incompleteTree = new JTree(new DefaultTreeModel(model.getIncompleteAddressesTree()));
+			JScrollPane scroll3 = new JScrollPane(incompleteTree);
+			incompletePanel.add(scroll3, BorderLayout.CENTER);
+			incompletePanel.add(new JLabel("Incomplete Addresses"), BorderLayout.NORTH);
+			incompletePanel.setMinimumSize(new Dimension(300, 200));
+			
+			JSplitPane addrSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, unresolvedPanel, incompletePanel);
+			
+			JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, streetPanel, addrSplitPane);
+			this.getContentPane().add(pane, BorderLayout.CENTER);
+		} else {
+			this.getContentPane().add(new JLabel(tr("(No data)")), BorderLayout.CENTER);
+		}
+		
+		JPanel buttonPanel = new JPanel(new GridLayout(1,10));
+		JButton ok = new JButton("Ok");
+		ok.addActionListener(this);
+		JButton cancel = new JButton("Cancel");
+		cancel.addActionListener(this);
+		
+		buttonPanel.add(cancel);
+		buttonPanel.add(ok);
+		// Murks
+		for (int i = 0; i < 8; i++) {
+			buttonPanel.add(new JSeparator());
+		}
+		
+		this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
+	}
+
+	public AddressEditModel getModel() {
+		return model;
+	}
+
+	public void setModel(AddressEditModel model) {
+		if (this.model != model) {
+			this.model = model;
+			if (model != null) {
+				streetsTree.setModel(new DefaultTreeModel(model.getStreetsTree()));
+				unresolvedTree.setModel(new DefaultTreeModel(model.getUnresolvedAddressesTree()));
+				incompleteTree.setModel(new DefaultTreeModel(model.getIncompleteAddressesTree()));
+			}
+		}
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		
+	}
+}
Index: /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/gui/AddressEditModel.java
===================================================================
--- /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/gui/AddressEditModel.java	(revision 23814)
+++ /applications/editors/josm/plugins/AddressEdit/src/org/openstreetmap/josm/plugins/addressEdit/gui/AddressEditModel.java	(revision 23814)
@@ -0,0 +1,119 @@
+/*
+ * 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 3 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 org.openstreetmap.josm.plugins.addressEdit.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+import org.openstreetmap.josm.plugins.addressEdit.AddressNode;
+import org.openstreetmap.josm.plugins.addressEdit.INodeEntity;
+import org.openstreetmap.josm.plugins.addressEdit.StreetNode;
+
+public class AddressEditModel {
+	private List<StreetNode> streets;
+	private List<AddressNode> unresolvedAddresses;
+	private List<AddressNode> incompleteAddresses = new ArrayList<AddressNode>();
+	private DefaultMutableTreeNode streetRoot;
+	private DefaultMutableTreeNode unresolvedRoot;
+	private DefaultMutableTreeNode incompleteRoot;
+	
+	/**
+	 * @param streets
+	 * @param unresolvedAddresses
+	 */
+	public AddressEditModel(List<StreetNode> streets,
+			List<AddressNode> unresolvedAddresses) {
+		super();
+		this.streets = streets;
+		this.unresolvedAddresses = unresolvedAddresses;
+	}
+	
+	public TreeNode getStreetsTree() {
+		if (streets == null) return new DefaultMutableTreeNode(tr("(No data)"));
+		
+		if (streetRoot == null) {
+			streetRoot = new DefaultMutableTreeNode();
+			for (StreetNode sNode : streets) {
+				DefaultMutableTreeNode treeStreetNode = new DefaultMutableTreeNode(sNode);
+				
+				DefaultMutableTreeNode segmentsNode = new DefaultMutableTreeNode(tr("Segments"));
+				treeStreetNode.add(segmentsNode);
+				
+				// Add street segment(s)
+				for (INodeEntity child : sNode.getChildren()) {
+					segmentsNode.add(new DefaultMutableTreeNode(child));
+				}
+				
+				if (sNode.hasAddresses()) {
+					// Add address nodes
+					DefaultMutableTreeNode addressNode = new DefaultMutableTreeNode(tr("Addresses"));
+					treeStreetNode.add(addressNode);
+					
+					for (AddressNode addr : sNode.getAddresses()) {
+						addressNode.add(new DefaultMutableTreeNode(addr));
+						if (!addr.isComplete()) {
+							incompleteAddresses.add(addr);
+						}
+					}
+				}
+				streetRoot.add(treeStreetNode);
+			}
+		}
+		
+		return streetRoot;
+	}
+	
+	/**
+	 * Gets the tree node containing all unresolved addresses.
+	 * @return
+	 */
+	public TreeNode getUnresolvedAddressesTree() {
+		if (unresolvedAddresses == null) return new DefaultMutableTreeNode(tr("(No data)"));
+
+		if (unresolvedRoot == null) {
+			unresolvedRoot = new DefaultMutableTreeNode();
+			
+			for (AddressNode addr : unresolvedAddresses) {
+				// Add address nodes				
+				unresolvedRoot.add(new DefaultMutableTreeNode(addr));
+			}
+		}
+		
+		return unresolvedRoot;
+	}
+	
+	/**
+	 * Gets the tree node containing all incomplete addresses.
+	 * @return
+	 */
+	public TreeNode getIncompleteAddressesTree() {
+		if (incompleteAddresses == null) return new DefaultMutableTreeNode(tr("(No data)"));
+
+		if (incompleteRoot == null) {
+			incompleteRoot = new DefaultMutableTreeNode();
+			
+			for (AddressNode addr : incompleteAddresses) {
+				// Add address nodes				
+				incompleteRoot.add(new DefaultMutableTreeNode(addr));
+			}
+		}
+		
+		return incompleteRoot;
+	}
+}
