Index: java/main/src/main/java/com/framsticks/gui/Frame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 96)
+++ java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 97)
@@ -1,29 +1,57 @@
 package com.framsticks.gui;
 
-import com.framsticks.core.Instance;
-import com.framsticks.core.Path;
-import com.framsticks.gui.view.*;
-import com.framsticks.gui.view.TreeCellRenderer;
-import com.framsticks.util.dispatching.Dispatcher;
-import com.framsticks.util.dispatching.JoinableCollection;
-import com.framsticks.util.lang.ScopeEnd;
-import com.framsticks.util.swing.KeyboardModifier;
-import com.framsticks.util.swing.MenuConstructor;
-
-import org.apache.log4j.Logger;
-
-import javax.swing.*;
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTree;
+import javax.swing.KeyStroke;
+import javax.swing.ToolTipManager;
+import javax.swing.UIManager;
 import javax.swing.event.TreeModelEvent;
 import javax.swing.event.TreeModelListener;
 import javax.swing.event.TreeSelectionEvent;
 import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.*;
-
-import java.awt.*;
-import java.awt.datatransfer.StringSelection;
-import java.awt.event.*;
-import java.util.HashMap;
-import java.util.Map;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.DefaultTreeSelectionModel;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.core.Path;
+import com.framsticks.core.Tree;
+import com.framsticks.gui.view.TreeCellRenderer;
+import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
+import com.framsticks.util.dispatching.Joinable;
+import com.framsticks.util.dispatching.JoinableCollection;
+import com.framsticks.util.dispatching.JoinableParent;
+import com.framsticks.util.dispatching.JoinableState;
 import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.util.lang.ScopeEnd;
+import com.framsticks.util.swing.KeyboardModifier;
+import com.framsticks.util.swing.MenuConstructor;
 
 /**
@@ -31,5 +59,5 @@
  */
 @SuppressWarnings("serial")
-public class Frame extends JoinableCollection<Instance> implements Dispatcher<Frame> {
+public class Frame extends FrameJoinable implements JoinableParent {
 
 	private static final Logger log = Logger.getLogger(Frame.class.getName());
@@ -42,11 +70,8 @@
 	protected JPanel cardPanel;
 
-	protected final String title;
-	protected JFrame swing;
 	protected JScrollPane treeScrollPane;
-	protected JTree tree;
+	protected JTree jtree;
 	protected DefaultTreeModel treeModel;
 	protected javax.swing.tree.MutableTreeNode rootNode;
-	//final Instance instance;
 	protected JPanel treePanel;
 	protected JPopupMenu treePopupMenu;
@@ -54,5 +79,4 @@
 
 	TreeNode currentlyPoppedTreeNode;
-	protected JLabel statusBar;
 	protected JPanel mainPanel;
 	protected JPanel leftPanel;
@@ -67,21 +91,13 @@
 	protected JMenu helpMenu;
 
-	protected final Map<Instance, InstanceAtFrame> instancesAtFrames = new HashMap<Instance, InstanceAtFrame>();
-
-	public Frame(String title, Browser browser) {
-		this.title = title;
+	protected final Map<Tree, TreeAtFrame> treeAtFrames = new HashMap<Tree, TreeAtFrame>();
+	protected JoinableCollection<Tree> trees = new JoinableCollection<Tree>();
+
+	public Frame(Browser browser) {
 		this.browser = browser;
 	}
 
-	public void configure() {
-		swing = new JFrame(title);
-		swing.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
-		swing.addWindowListener(new WindowAdapter() {
-			@Override
-			public void windowClosing(WindowEvent e) {
-				log.info("received closing");
-				interrupt();
-			}
-		});
+	protected void initializeGui() {
+		super.initializeGui();
 		/** this is done to remove the current value label from above the slider,
 		 * because it cannot put to work properly with floating-point value sliders,
@@ -90,33 +106,8 @@
 		log.debug("creating " + this);
 
-		statusBar = new JLabel("not connected");
-
-		Container contentPane = swing.getContentPane();
-		contentPane.setLayout(new BorderLayout());
-
+
+		Container contentPane = getSwing().getContentPane();
 		treePopupMenu = new JPopupMenu("title");
 		treePopupMenu.setName("popup");
-		treePopupMenuHeader = new JMenuItem();
-		treePopupMenuHeader.setForeground(Color.BLUE);
-		treePopupMenu.add(treePopupMenuHeader);
-		treePopupMenu.addSeparator();
-		//TODO: add to favourites
-		//TODO: remove from favourites
-		//TODO: open in new window as root
-		//TODO: refresh
-		//TODO: open in console
-
-		treePopupMenu.add(new JMenuItem("Refresh"));
-		treePopupMenu.add(new JMenuItem("Open in new frame as root"));
-		addNodeActionToTreePopupMenu("Copy path to clipboard", new NodeAction() {
-			@Override
-			public void actionPerformed(TreeNode treeNode) {
-				Path path = treeNode.getInstancePath();
-				StringSelection selection = new StringSelection(path.toString());
-				swing.getToolkit().getSystemClipboard().setContents(selection, selection);
-			}
-		});
-		//this.add(createMenuItem("Add to favourites", null));
-		//this.add(createMenuItem("Remove from favourites", null));
 
 		treePanel = new JPanel();
@@ -147,12 +138,12 @@
 		});
 
-		tree = new JTree(treeModel);
-		tree.setName("tree");
-		tree.setRootVisible(false);
-		tree.setExpandsSelectedPaths(true);
-		tree.setSelectionModel(new DefaultTreeSelectionModel());
-		ToolTipManager.sharedInstance().registerComponent(tree);
-
-		tree.addTreeSelectionListener(new TreeSelectionListener() {
+		jtree = new JTree(treeModel);
+		jtree.setName("tree");
+		jtree.setRootVisible(false);
+		jtree.setExpandsSelectedPaths(true);
+		jtree.setSelectionModel(new DefaultTreeSelectionModel());
+		ToolTipManager.sharedInstance().registerComponent(jtree);
+
+		jtree.addTreeSelectionListener(new TreeSelectionListener() {
 			@Override
 			public void valueChanged(TreeSelectionEvent e) {
@@ -161,12 +152,12 @@
 		});
 
-		tree.setExpandsSelectedPaths(true);
-		tree.setEditable(false);
-		tree.setDoubleBuffered(true);
-		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
-		tree.setShowsRootHandles(true);
-		tree.setRowHeight(26);
-		tree.setDoubleBuffered(true);
-		tree.addMouseListener(new MouseAdapter() {
+		jtree.setExpandsSelectedPaths(true);
+		jtree.setEditable(false);
+		jtree.setDoubleBuffered(true);
+		jtree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+		jtree.setShowsRootHandles(true);
+		jtree.setRowHeight(26);
+		jtree.setDoubleBuffered(true);
+		jtree.addMouseListener(new MouseAdapter() {
 			@Override
 			public void mousePressed(MouseEvent e) {
@@ -182,9 +173,9 @@
 		});
 
-		new KeyboardModifier(tree, JComponent.WHEN_FOCUSED).join(KeyStroke.getKeyStroke('h'), KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)).join(KeyStroke.getKeyStroke('j'), KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)).join(KeyStroke.getKeyStroke('k'), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)).join(KeyStroke.getKeyStroke('l'), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
-
-		tree.setCellRenderer(new TreeCellRenderer());
-
-		treeScrollPane = new JScrollPane(tree);
+		new KeyboardModifier(jtree, JComponent.WHEN_FOCUSED).join(KeyStroke.getKeyStroke('h'), KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)).join(KeyStroke.getKeyStroke('j'), KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)).join(KeyStroke.getKeyStroke('k'), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)).join(KeyStroke.getKeyStroke('l'), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
+
+		jtree.setCellRenderer(new TreeCellRenderer());
+
+		treeScrollPane = new JScrollPane(jtree);
 		treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
 
@@ -215,5 +206,4 @@
 		contentPane.add(menuBar, BorderLayout.NORTH);
 		contentPane.add(mainPanel, BorderLayout.CENTER);
-		contentPane.add(statusBar, BorderLayout.SOUTH);
 
 		leftPanel = new JPanel();
@@ -246,6 +236,6 @@
 		cardPanel.setLayout(cardPanelLayout);
 
-		swing.pack();
-		tree.requestFocusInWindow();
+		getSwing().pack();
+		jtree.requestFocusInWindow();
 
 		log.debug("frame configured: " + this);
@@ -266,45 +256,16 @@
 	public void addRootPath(Path path) {
 		assert isActive();
-		Instance instance = path.getInstance();
-		assert browser.getInstances().contains(instance);
-
-		InstanceAtFrame e = new InstanceAtFrame(instance, this);
-		instance.addListener(e);
-		instancesAtFrames.put(instance, e);
+		Tree tree = path.getTree();
+		assert browser.getTrees().contains(tree);
+
+		TreeAtFrame e = new TreeAtFrame(tree, this);
+		tree.addListener(e);
+		treeAtFrames.put(tree, e);
 		TreeNode node = new TreeNode(e, path);
 		e.rootTreeNode = node;
 		treeModel.insertNodeInto(node, rootNode, rootNode.getChildCount());
-		tree.expandPath(new TreePath(rootNode));
-	}
-
-	@Override
-	public boolean isActive() {
-		return SwingDispatcher.instance.isActive();
-	}
-
-	@Override
-	public void dispatch(RunAt<? extends Frame> runnable) {
-		SwingDispatcher.getInstance().dispatch(runnable);
-	}
-
-	public Action addActionToTreePopupMenu(Action action) {
-		assert isActive();
-		treePopupMenu.add(action);
-		return action;
-	}
-
-	public Action addNodeActionToTreePopupMenu(String title, final NodeAction nodeAction) {
-		assert isActive();
-		return addActionToTreePopupMenu(new AbstractAction(title) {
-			@Override
-			public void actionPerformed(ActionEvent e) {
-				TreeNode treeNode = getCurrentlyPoppedTreeNode();
-				if (treeNode == null) {
-					return;
-				}
-				nodeAction.actionPerformed(treeNode);
-			}
-		});
-	}
+		jtree.expandPath(new TreePath(rootNode));
+	}
+
 
 	public void showPanel(Panel panel) {
@@ -319,18 +280,18 @@
 			return;
 		}
-		currentlyPoppedTreeNode = findTreeNodeByTreePath(tree.getPathForLocation(e.getX(), e.getY()));
+		currentlyPoppedTreeNode = findTreeNodeByTreePath(jtree.getPathForLocation(e.getX(), e.getY()));
 		if (currentlyPoppedTreeNode == null) {
 			return;
 		}
+
+		Path path = currentlyPoppedTreeNode.getTreePath();
+		treePopupMenu.removeAll();
+
+		for (PopupMenuEntryProvider provider : browser.popupMenuEntryProviders) {
+			provider.provide(treePopupMenu, path);
+		}
+		// treePopupMenuHeader.setText(path.getTree().getName() + path.getTextual());
 		treePopupMenu.show(e.getComponent(), e.getX(), e.getY());
 		//currentlyPoppedPanel.getNode().getFramsClass().getName()
-		//treePopupMenuHeader.setText(currentlyPoppedTreeNode.getNode().getPath());
-	}
-
-	/**
-	 * @return the swing
-	 */
-	public JFrame getSwing() {
-		return swing;
 	}
 
@@ -344,10 +305,10 @@
 		cardPanel.removeAll();
 		cardPanel.updateUI();
-		tree.setEnabled(false);
+		jtree.setEnabled(false);
 	}
 
 	public ScopeEnd startChange(final DefaultMutableTreeNode node) {
 		assert isActive();
-		final TreePath selection = tree.getSelectionPath();
+		final TreePath selection = jtree.getSelectionPath();
 		return new ScopeEnd() {
 			@Override
@@ -355,5 +316,5 @@
 				assert isActive();
 				treeModel.nodeChanged(node);
-				tree.setSelectionPath(selection);
+				jtree.setSelectionPath(selection);
 			}
 		};
@@ -391,18 +352,28 @@
 	}
 
+	protected final ExceptionResultHandler dialogHandler = new ExceptionResultHandler() {
+
+		@Override
+		public void handle(FramsticksException exception) {
+			//TODO TEH
+			throw exception;
+
+		}
+	};
+
 	public void goTo(Path path) {
 		assert isActive();
-		final TreePath treePath = instancesAtFrames.get(path.getInstance()).getTreePath(path, false);
+		final TreePath treePath = treeAtFrames.get(path.getTree()).getTreePath(path, false);
 		log.info("go to path: " + path + "(" + treePath + ")");
 
-		new RunAt<Frame>(this) {
-			@Override
-			public void run() {
+		this.dispatch(new RunAt<Frame>(dialogHandler) {
+			@Override
+			protected void runAt() {
 				log.info("executed");
-				tree.setSelectionPath(treePath);
-				tree.makeVisible(treePath);
-				assert tree.isVisible(treePath);
-			}
-		};
+				jtree.setSelectionPath(treePath);
+				jtree.makeVisible(treePath);
+				assert jtree.isVisible(treePath);
+			}
+		});
 
 	}
@@ -422,34 +393,32 @@
 
 	@Override
+	protected void joinableStart() {
+		super.joinableStart();
+		Dispatching.use(trees, this);
+	}
+
+	@Override
 	protected void joinableInterrupt() {
-		assert isActive();
+		Dispatching.drop(trees, this);
 		super.joinableInterrupt();
-
-		dispatch(new RunAt<Frame>() {
-			@Override
-			public void run() {
-				finish();
-			}
-		});
 	}
 
 	@Override
 	protected void joinableFinish() {
-		assert isActive();
-		log.debug("disposing frame " + this);
-		swing.dispose();
-	}
-
-	// @Override
-	// public boolean isDone() {
-	//	return super.isDone() && !swing.isDisplayable();
-	// }
-
-
-	@Override
-	public String getName() {
-		return title;
-	}
-
+		super.joinableFinish();
+	}
+
+	@Override
+	protected void joinableJoin() throws InterruptedException {
+		Dispatching.join(trees);
+		super.joinableJoin();
+	}
+
+	@Override
+	public void childChangedState(Joinable joinable, JoinableState state) {
+		if (joinable == trees) {
+			proceedToState(state);
+		}
+	}
 
 }
