Index: /trunk/quest-core-events/src/main/java/de/ugoe/cs/quest/eventcore/guimodel/GUIModel.java
===================================================================
--- /trunk/quest-core-events/src/main/java/de/ugoe/cs/quest/eventcore/guimodel/GUIModel.java	(revision 845)
+++ /trunk/quest-core-events/src/main/java/de/ugoe/cs/quest/eventcore/guimodel/GUIModel.java	(revision 846)
@@ -227,4 +227,50 @@
         mergeSubTree(root);
     }
+    
+    /**
+     * <p>
+     * Merges the tree nodes of two GUI elements. The GUI elements need to have the same parent.
+     * </p>
+     * 
+     * @param guiElement1
+     *            the first merge GUI element
+     * @param guiElement2
+     *            the second merge GUI element
+     * @throws IllegalArgumentException
+     *             thrown if the two GUI elements do not have the same parent
+     */
+    public void mergeGUIElements(IGUIElement guiElement1, IGUIElement guiElement2)
+        throws IllegalArgumentException
+    {
+        // check if both nodes have the same parent
+        IGUIElement parentElement = guiElement1.getParent();
+        if (parentElement != null && !parentElement.equals(guiElement2.getParent())) {
+            throw new IllegalArgumentException("can only merge nodes with the same parent");
+        }
+
+        // get the TreeNode of the parent of the GUI elements
+        TreeNode parent = findNode(parentElement);
+
+        // get the TreeNodes for both GUI elements
+        TreeNode node1 = findNode(guiElement1);
+        TreeNode node2 = findNode(guiElement2);
+
+        if (node1 == null || node2 == null) {
+            throw new IllegalArgumentException(
+                                               "Error while merging nodes: one element is not part of the GUI model!");
+        }
+
+        TreeNode replacement = mergeTreeNodes(node1, node2);
+
+        if (parent != null) {
+            // remove node1 and node2 from the parent's children and add the replacement instead
+            // assumes that there are no duplicates of node1 and node2
+            if (parent.children != null) {
+                parent.children.set(parent.children.indexOf(node1), replacement);
+                parent.children.remove(node2);
+            }
+        }
+
+    }
 
     /**
@@ -428,4 +474,36 @@
 
         out.println();
+    }
+    
+    /**
+     * <p>
+     * Retrieves the TreeNode associated with a GUI element. Returns null if no such TreeNode is
+     * found.
+     * </p>
+     * 
+     * @param element
+     *            the GUI element
+     * @return associated TreeNode; null if no such node exists
+     */
+    private TreeNode findNode(IGUIElement element) {
+        if (element == null) {
+            return null;
+        }
+
+        TreeNode result = null;
+        for (TreeNode node : allNodes) {
+            if (node.guiElement.equals(element)) {
+                if (result == null) {
+                    result = node;
+                }
+                else {
+                    Console
+                        .traceln(Level.SEVERE,
+                                 "Multiple nodes in the internal GUI model match the same GUI element. "
+                                     + "This should not be the case and the GUI model is probably invalid.");
+                }
+            }
+        }
+        return result;
     }
 
Index: /trunk/quest-ui-swt/src/main/java/de/ugoe/cs/quest/ui/swt/ShowGuiModelDialog.java
===================================================================
--- /trunk/quest-ui-swt/src/main/java/de/ugoe/cs/quest/ui/swt/ShowGuiModelDialog.java	(revision 845)
+++ /trunk/quest-ui-swt/src/main/java/de/ugoe/cs/quest/ui/swt/ShowGuiModelDialog.java	(revision 846)
@@ -12,4 +12,5 @@
 import org.eclipse.swt.widgets.Dialog;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Tree;
@@ -18,4 +19,6 @@
 import de.ugoe.cs.quest.eventcore.guimodel.GUIModel;
 import de.ugoe.cs.quest.eventcore.guimodel.IGUIElement;
+import de.ugoe.cs.util.console.Console;
+
 import org.eclipse.swt.widgets.Label;
 
@@ -72,8 +75,8 @@
         shell.setText(getText());
 
-        shell.setLayout(new GridLayout(2, false));
+        shell.setLayout(new GridLayout(3, false));
 
-        guiTree = new Tree(shell, SWT.BORDER);
-        guiTree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+        guiTree = new Tree(shell, SWT.BORDER | SWT.MULTI);
+        guiTree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
 
         buildGuiTree();
@@ -96,4 +99,16 @@
         });
         btnCollapseAll.setText("Collapse all");
+        
+        Button btnMerge = new Button(shell, SWT.NONE);
+        btnMerge.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                mergeSelectedNode(guiTree);
+            }
+        });
+        btnMerge.setText("Merge");
+        
+        //new Label(shell, SWT.NONE);
+        new Label(shell, SWT.NONE);
         new Label(shell, SWT.NONE);
         new Label(shell, SWT.NONE);
@@ -105,4 +120,5 @@
             TreeItem child = new TreeItem(guiTree, SWT.NULL);
             child.setText(element.toString());
+            child.setData(element);
             buildGuiTree(child, model.getChildren(element));
         }
@@ -113,4 +129,5 @@
             TreeItem child = new TreeItem(currentParent, SWT.NULL);
             child.setText(element.toString());
+            child.setData(element);
             buildGuiTree(child, model.getChildren(element));
         }
@@ -129,4 +146,41 @@
         }
     }
+    
+    private void mergeSelectedNode(Tree tree) {
+        TreeItem[] selectedNodes = tree.getSelection();
+        if( selectedNodes.length<2 ) {
+            MessageBox messageBox = new MessageBox(shell, SWT.ERROR);
+            messageBox.setMessage("Must select at least two nodes to merge!");
+            messageBox.setText("Error");
+            messageBox.open();
+            return;
+        }
+        
+        TreeItem firstParent = selectedNodes[0].getParentItem();
+        for( int i=1 ; i<selectedNodes.length ; i++ ) {
+            if( firstParent!=selectedNodes[i].getParentItem() ) {
+                MessageBox messageBox = new MessageBox(shell, SWT.ERROR);
+                messageBox.setMessage("All selected nodes must have the same parent!");
+                messageBox.setText("Error");
+                messageBox.open();
+                return;
+            }
+        }
+        
+        try {
+            // try to merge the elements
+            IGUIElement firstElement = (IGUIElement) selectedNodes[0].getData();
+            for( int i=1 ; i<selectedNodes.length ; i++ ) {
+                model.mergeGUIElements(firstElement, (IGUIElement) selectedNodes[i].getData());
+            }
+        } catch( IllegalArgumentException e) {
+            Console.logException(e);
+        }
+        
+        // update visualization of the model
+        firstParent.removeAll();
+        buildGuiTree(firstParent, model.getChildren((IGUIElement) firstParent.getData()));
+        firstParent.setExpanded(true);
+    }
 
 }
