diff --git a/.classpath b/.classpath
index 104dbe2f77b890e4054f81fa0a249755694c4c5a..2c34b7a4e6de7648241807962351265ee930b033 100644
--- a/.classpath
+++ b/.classpath
@@ -8,43 +8,10 @@
 	<classpathentry kind="src" path="src/main/java"/>
 	<classpathentry kind="src" path="src/main/resources"/>
 	<classpathentry kind="src" path="src/test/java"/>
-	<classpathentry kind="var" path="ICY_HOME/plugins/adufour/blocks/Blocks.jar"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Blocks"/>
-	<classpathentry kind="lib" path="F:/SDKs/Java/jdk1.8.0_241/lib/tools.jar"/>
-	<classpathentry kind="lib" path="F:/SDKs/Java/jdk1.8.0_241/lib/tools.jar"/>
-	<classpathentry kind="var" path="USER_HOME/SDKs/Java/jdk1.8.0_251/lib/tools.jar"/>
-	<classpathentry kind="var" path="USER_HOME/SDKs/Java/jdk1.8.0_251/lib/tools.jar"/>
-	<classpathentry kind="lib" path="D:/SDKs/Java/jdk1.8.0_241/lib/tools.jar"/>
-	<classpathentry kind="var" path="USER_HOME/SDKs/Java/jdk1.8.0_251/lib/tools.jar"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.bioimageanalysis.icy:icy-kernel:2.1.0"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: net.sf.ehcache:ehcache:2.10.6"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.slf4j:slf4j-api:1.7.25"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.bioimageanalysis.icy:icy-bioformats:6.3.1"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.bioimageanalysis.icy:icy-insubstantial:7.3.7"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.bioimageanalysis.icy:icy-vtk:6.3.0.1"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: net.imagej:ij:1.52q"/>
-	<classpathentry kind="var" path="USER_HOME/SDKs/Java/jdk1.8.0_251/lib/tools.jar"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: javax.media:jai-core:1.1.3"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: javax.media:jai-codec:1.1.3"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.jogl:jogl-all:2.1.5-01"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.jogl:jogl-all-natives-linux-amd64:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.jogl:jogl-all-natives-linux-i586:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.jogl:jogl-all-natives-macosx-universal:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.jogl:jogl-all-natives-windows-amd64:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.jogl:jogl-all-natives-windows-i586:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.gluegen:gluegen-rt:2.1.5-01"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.gluegen:gluegen-rt-natives-linux-amd64:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.gluegen:gluegen-rt-natives-linux-i586:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.gluegen:gluegen-rt-natives-macosx-universal:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.gluegen:gluegen-rt-natives-windows-amd64:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.jogamp.gluegen:gluegen-rt-natives-windows-i586:2.1.5"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.javassist:javassist:3.22.0-GA"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: net.sourceforge.jexcelapi:jxl:2.6.12"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: log4j:log4j:1.2.14"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.swinglabs.swingx:swingx-all:1.6.5-1"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.bioimageanalysis.icy:icy-blocks:1.0.1"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.bioimageanalysis.icy:icy-ezplug:3.15.13"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: org.bioimageanalysis.icy:icy-javadocparser:1.0.0"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Maven: com.nativelibs4java:ochafik-util:0.12"/>
+	<classpathentry kind="var" path="ICY_JAR" sourcepath="/ICY_KERNEL"/>
+	<classpathentry kind="var" path="ICY_PLUGINS/adufour/blocks/Blocks.jar"/>
+	<classpathentry kind="var" path="ICY_PLUGINS/adufour/ezplug/EzPlug.jar"/>
+	<classpathentry kind="var" path="ICY_PLUGINS/tprovoost/javadocparser/JavaDocParser.jar"/>
+	<classpathentry kind="var" path="ICY_PLUGINS/stef/library/JavaCLPlugin.jar"/>
 	<classpathentry kind="output" path="target/classes"/>
 </classpath>
diff --git a/.gitignore b/.gitignore
index cc170c9f001df9d84ee09cb06e01df0fb466eac0..b92e5c2b7b10b67a978956d4f7d9224c07b3531a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,5 +5,6 @@ bin/
 build/
 target/
 *.iml
+*.eml
 .classpath
 .project
\ No newline at end of file
diff --git a/export.jardesc b/export.jardesc
index 6cb53c8404aa194a966cd17f3e185e85a147bb61..75e3dcf80a390cae50b0333fa3cd0da5ac6cc113 100644
--- a/export.jardesc
+++ b/export.jardesc
@@ -11,6 +11,8 @@
         </sealing>
     </manifest>
     <selectedElements exportClassFiles="true" exportJavaFiles="true" exportOutputFolder="false">
-        <javaElement handleIdentifier="=Protocols/src"/>
+        <javaElement handleIdentifier="=Protocols/src\/main\/resources"/>
+        <javaElement handleIdentifier="=Protocols/src\/test\/java"/>
+        <javaElement handleIdentifier="=Protocols/src\/main\/java"/>
     </selectedElements>
 </jardesc>
diff --git a/src/main/java/plugins/adufour/protocols/Protocols.java b/src/main/java/plugins/adufour/protocols/Protocols.java
index 4abbff1b91dbe5ca151407be557da29ed80024cc..7d9cd6a886e37bf593120dc6a646c264488bce80 100644
--- a/src/main/java/plugins/adufour/protocols/Protocols.java
+++ b/src/main/java/plugins/adufour/protocols/Protocols.java
@@ -362,7 +362,7 @@ public class Protocols extends PluginActionable
             throw new IllegalArgumentException(protocolFile + " is not a valid protocol file");
 
         System.out.println("Loading workflow...");
-        WorkFlow workFlow = new WorkFlow();
+        WorkFlow workFlow = new WorkFlow(true);
         BlocksML.getInstance().loadWorkFlow(xml, workFlow);
 
         workFlow.run();
diff --git a/src/main/java/plugins/adufour/protocols/gui/MainFrame.java b/src/main/java/plugins/adufour/protocols/gui/MainFrame.java
index d49321a5b75581f28c0c4949dfdef0f646147784..ffff065b26992f2769ed7eb3b5754c34340f2b4f 100644
--- a/src/main/java/plugins/adufour/protocols/gui/MainFrame.java
+++ b/src/main/java/plugins/adufour/protocols/gui/MainFrame.java
@@ -1,26 +1,5 @@
 package plugins.adufour.protocols.gui;
 
-import icy.common.listener.AcceptListener;
-import icy.file.Loader;
-import icy.gui.component.CloseableTabbedPane;
-import icy.gui.component.CloseableTabbedPane.CloseableTabbedPaneListener;
-import icy.gui.frame.IcyFrame;
-import icy.gui.frame.IcyFrameEvent;
-import icy.gui.frame.IcyFrameListener;
-import icy.gui.frame.progress.AnnounceFrame;
-import icy.main.Icy;
-import icy.plugin.PluginDescriptor;
-import icy.plugin.PluginInstaller;
-import icy.plugin.PluginLoader;
-import icy.resource.ResourceUtil;
-import icy.resource.icon.IcyIcon;
-import icy.system.FileDrop;
-import icy.system.FileDrop.FileDropListener;
-import icy.system.IcyExceptionHandler;
-import icy.system.IcyHandledException;
-import icy.system.thread.ThreadUtil;
-import icy.util.XMLUtil;
-
 import java.awt.BorderLayout;
 import java.awt.Component;
 import java.awt.Dimension;
@@ -54,6 +33,26 @@ import org.pushingpixels.substance.internal.ui.SubstanceSplitPaneUI;
 import org.pushingpixels.substance.internal.utils.SubstanceSplitPaneDivider;
 import org.w3c.dom.Document;
 
+import icy.common.listener.AcceptListener;
+import icy.file.Loader;
+import icy.gui.component.CloseableTabbedPane;
+import icy.gui.component.CloseableTabbedPane.CloseableTabbedPaneListener;
+import icy.gui.frame.IcyFrame;
+import icy.gui.frame.IcyFrameEvent;
+import icy.gui.frame.IcyFrameListener;
+import icy.gui.frame.progress.AnnounceFrame;
+import icy.main.Icy;
+import icy.plugin.PluginDescriptor;
+import icy.plugin.PluginInstaller;
+import icy.plugin.PluginLoader;
+import icy.resource.ResourceUtil;
+import icy.resource.icon.IcyIcon;
+import icy.system.FileDrop;
+import icy.system.FileDrop.FileDropListener;
+import icy.system.IcyExceptionHandler;
+import icy.system.IcyHandledException;
+import icy.system.thread.ThreadUtil;
+import icy.util.XMLUtil;
 import plugins.adufour.blocks.Blocks;
 import plugins.adufour.blocks.lang.Block;
 import plugins.adufour.blocks.lang.BlockDescriptor;
@@ -70,12 +69,13 @@ import plugins.adufour.protocols.Protocols;
 import plugins.adufour.protocols.gui.block.WorkFlowContainer;
 import plugins.adufour.vars.lang.Var;
 
-public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListener, CloseableTabbedPaneListener, AcceptListener, ChangeListener, BlockListener, FileDropListener
+public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListener, CloseableTabbedPaneListener,
+        AcceptListener, ChangeListener, BlockListener, FileDropListener
 {
     private static final String UNTITLED = "untitled";
-    
+
     private final JToolBar toolBar;
-    
+
     private final JButton bNew = new JButton("New", new IcyIcon(ResourceUtil.ICON_DOC_NEW));
     private final JButton bLoad = new JButton("Load", new IcyIcon(ResourceUtil.ICON_OPEN));
     private final JButton bSave = new JButton("Save", new IcyIcon(ResourceUtil.ICON_SAVE));
@@ -83,53 +83,54 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
     private final JButton bEmbed = new JButton("Embed", new IcyIcon(ResourceUtil.ICON_WINDOW_COLLAPSE));
     private final JButton bRun = new JButton("Run", new IcyIcon(ResourceUtil.ICON_PLAY));
     private final JButton bClean = new JButton("Reset", new IcyIcon(ResourceUtil.ICON_TRASH));
-    
-    private final CloseableTabbedPane closeableTabbedPane = new CloseableTabbedPane(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT);
-    
+
+    private final CloseableTabbedPane closeableTabbedPane = new CloseableTabbedPane(JTabbedPane.TOP,
+            JTabbedPane.WRAP_TAB_LAYOUT);
+
     private final ArrayList<ProtocolPanel> protocolPanels = new ArrayList<ProtocolPanel>();
-    
+
     private BlockSearchPanel blockSearchPanel = new BlockSearchPanel();
-    
+
     private JSplitPane splitPane;
-    
+
     // Copy-paste support
     private static final HashMap<BlockDescriptor, BlockDescriptor> blocksClipBoard = new HashMap<BlockDescriptor, BlockDescriptor>();
     private static final HashMap<BlockDescriptor, BlockDescriptor> blocksClipBoardBackup = new HashMap<BlockDescriptor, BlockDescriptor>();
     private static final ArrayList<Link<?>> linksClipBoard = new ArrayList<Link<?>>();
     private static final ArrayList<Link<?>> linksClipBoardBackup = new ArrayList<Link<?>>();
-    
+
     private static final String LINKS_CUT_MSG = "Some links will not be copied. Continue?";
-    
+
     private final Protocols pluginInstance;
-    
+
     private boolean isFrameClosing = false;
-    
+
     public MainFrame(Protocols pluginInstance)
     {
         super("Protocols editor (" + new Blocks().getFriendlyVersion() + ")", true, true, true, true, true);
-        
+
         this.pluginInstance = pluginInstance;
-        
+
         // handle close event locally
         setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
         addFrameListener(this);
-        
+
         setPreferredSize(new Dimension(800, 640));
-        
+
         // Menus
-        
+
         toolBar = new JToolBar("Blocks toolbar", SwingConstants.HORIZONTAL);
-        
+
         getContentPane().add(toolBar, BorderLayout.NORTH);
-        
-        for (JButton button : new JButton[] { bNew, bLoad, bSave, bSaveAs, bEmbed, bRun, bClean })
+
+        for (JButton button : new JButton[] {bNew, bLoad, bSave, bSaveAs, bEmbed, bRun, bClean})
         {
             button.setFocusPainted(false);
             button.setBorderPainted(true);
             button.addActionListener(this);
             button.setBorder(null);
         }
-        
+
         bNew.setToolTipText("<html><h4>Create a new empty protocol</h4></html>");
         bLoad.setToolTipText("<html><h4>Load a protocol from a file</h4></html>");
         bSave.setToolTipText("<html><h4>Save the current protocol</h4></html>");
@@ -137,7 +138,7 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
         bEmbed.setToolTipText("<html><h4>Embed the current selection into a new work flow or a batch</h4></html>");
         bRun.setToolTipText("<html><h4>Run the current protocol</h4></html>");
         bClean.setToolTipText("<html><h4>Clear all intermediate results (may help saving memory)</h4></html>");
-        
+
         toolBar.add(bNew);
         toolBar.add(bLoad);
         toolBar.add(bSave);
@@ -147,61 +148,62 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
         toolBar.add(new JToolBar.Separator());
         toolBar.add(bRun);
         toolBar.add(bClean);
-        
+
         closeableTabbedPane.addCloseableTabbedPaneListener(this);
-        
+
         splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, blockSearchPanel, closeableTabbedPane);
         splitPane.setOneTouchExpandable(true);
         splitPane.setContinuousLayout(true);
         splitPane.setUI(new MySplitPaneUI());
         getContentPane().add(splitPane, BorderLayout.CENTER);
-        
+
         getContentPane().addKeyListener(new KeyListener()
         {
             @Override
             public void keyPressed(KeyEvent key)
             {
-                if ((key.getModifiers() & Protocols.MENU_SHORTCUT_KEY) == Protocols.MENU_SHORTCUT_KEY && key.getComponent() instanceof WorkFlowContainer)
+                if ((key.getModifiers() & Protocols.MENU_SHORTCUT_KEY) == Protocols.MENU_SHORTCUT_KEY
+                        && key.getComponent() instanceof WorkFlowContainer)
                 {
                     WorkFlow wf = ((WorkFlowContainer) key.getComponent()).getWorkFlow();
-                    
+
                     switch (key.getKeyCode())
                     {
                         case KeyEvent.VK_C:
                             copySelection(wf, false);
-                        break;
+                            break;
                         case KeyEvent.VK_V:
                             pasteSelection(wf, false);
-                        break;
+                            break;
                         case KeyEvent.VK_X:
                             copySelection(wf, false);
                             deleteSelection(wf);
-                        break;
+                            break;
                         case KeyEvent.VK_BACK_SPACE:
                         case KeyEvent.VK_DELETE:
                             deleteSelection(wf);
                     }
-                    
+
                     key.getComponent().requestFocus(); // enable successive operations
                 }
             }
-            
+
             @Override
             public void keyTyped(KeyEvent arg0)
             {
             }
-            
+
             @Override
             public void keyReleased(KeyEvent arg0)
             {
             }
         });
-        
+
         Icy.getMainInterface().addCanExitListener(this);
-        
+
         pack();
     }
-    
+
     public static void copySelection(WorkFlow wf, boolean embedding) throws LinkCutException
     {
         // do not modify clip-board when embedding/dis-embedding
@@ -215,10 +217,10 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             linksClipBoardBackup.clear();
             linksClipBoardBackup.addAll(linksClipBoard);
         }
-        
+
         blocksClipBoard.clear();
         linksClipBoard.clear();
-        
+
         // copy the whole workflow
         if (wf.getBlockSelection().isEmpty())
         {
@@ -235,39 +237,41 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             for (Link<?> l : wf.getLinkSelection())
                 linksClipBoard.add(l);
         }
-        
-        if (embedding && linkCut(wf.getLinksIterator())) throw new LinkCutException(LINKS_CUT_MSG);
+
+        if (embedding && linkCut(wf.getLinksIterator()))
+            throw new LinkCutException(LINKS_CUT_MSG);
     }
-    
-    @SuppressWarnings({ "rawtypes", "unchecked" })
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
     public static void pasteSelection(WorkFlow wf, boolean embedding)
     {
         for (BlockDescriptor bd : blocksClipBoard.keySet())
         {
-            if (bd.getBlock() instanceof WorkFlow) // avoid getting the selection back in the
-                                                   // container
+            // avoid getting the selection back in the container
+            if (bd.getBlock() instanceof WorkFlow)
                 ((WorkFlow) blocksClipBoard.get(bd).getBlock()).newSelection();
+
             wf.addBlock(blocksClipBoard.get(bd));
         }
-        
+
         for (Link<?> l : linksClipBoard)
         {
             Link clone = linkClone(wf, l);
-            
+
             if (clone == null)
             {
                 System.err.println("Warning: cannot copy a link to an exposed variable");
                 continue;
             }
-            
+
             wf.addLink(clone.srcBlock, clone.srcVar, clone.dstBlock, clone.dstVar);
         }
-        
+
         // re-copy the first copy
         // avoid pasting an altered state of the block
         for (BlockDescriptor bd : blocksClipBoard.keySet())
             blocksClipBoard.put(bd, blocksClipBoard.get(bd).clone(embedding));
-        
+
         if (embedding)
         {
             // restore the backup
@@ -280,7 +284,7 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             linksClipBoard.addAll(linksClipBoardBackup);
         }
     }
-    
+
     private static void deleteSelection(WorkFlow wf)
     {
         if (wf.getBlockSelection().isEmpty())
@@ -290,7 +294,7 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
                 tmp.add(l); // avoid concurrent modification exception
             for (Link<?> l : tmp)
                 wf.removeLink(l.dstVar);
-            
+
             for (int i = 0; i < wf.size();)
                 wf.removeBlock(wf.getBlock(i), false);
         }
@@ -298,26 +302,27 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
         {
             for (Link<?> l : wf.getLinkSelection())
                 wf.removeLink(l.dstVar);
-            
+
             // avoid infinite loop when canceling
             ArrayList<BlockDescriptor> tmp = new ArrayList<BlockDescriptor>(wf.getBlockSelection());
             for (BlockDescriptor bd : tmp)
                 wf.removeBlock(bd, false);
         }
     }
-    
+
     private static boolean linkCut(Iterable<Link<?>> links)
     {
         for (Link<?> l : links)
-            if (blocksClipBoard.keySet().contains(l.dstBlock) ^ blocksClipBoard.keySet().contains(l.srcBlock)) return true;
+            if (blocksClipBoard.keySet().contains(l.dstBlock) ^ blocksClipBoard.keySet().contains(l.srcBlock))
+                return true;
         return false;
     }
-    
-    @SuppressWarnings({ "rawtypes", "unchecked" })
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
     private static Link<?> linkClone(WorkFlow wf, Link<?> l)
     {
         Var<?> newSrc = null, newDst = null;
-        
+
         try
         {
             // get link input from block inputs
@@ -330,25 +335,25 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             newSrc = blocksClipBoard.get(l.srcBlock).outputVars.get(l.srcBlock.outputVars.getID(l.srcVar));
             newDst = blocksClipBoard.get(l.dstBlock).inputVars.get(l.dstBlock.inputVars.getID(l.dstVar));
         }
-        
+
         // if the link contains an exposed variable of a work flow, newSrc or newDst == null
         // (because the ID of the cloned variable is different in the cloned work flow)
         if (newSrc == null || newDst == null)
         {
             return null;
         }
-        
+
         return new Link(wf, blocksClipBoard.get(l.srcBlock), newSrc, blocksClipBoard.get(l.dstBlock), newDst);
     }
-    
+
     public void addProtocolPane(ProtocolPanel protocol)
     {
         getProtocolPanels().add(protocol);
         protocol.addPropertyChangeListener(ProtocolPanel.WORKFLOW_MODIFIED, this);
         protocol.addBlockListener(this);
-        
+
         new FileDrop(protocol, false, this);
-        
+
         if (protocol.getFile() != null)
         {
             File f = protocol.getFile();
@@ -361,16 +366,16 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             protocol.setName(UNTITLED);
             closeableTabbedPane.addTab(UNTITLED, protocol);
         }
-        
+
         closeableTabbedPane.setSelectedIndex(getProtocolPanels().size() - 1);
     }
-    
+
     public ProtocolPanel getActiveProtocol()
     {
         int index = closeableTabbedPane.getSelectedIndex();
         return (index == -1) ? null : getProtocolPanels().get(index);
     }
-    
+
     @Override
     public void actionPerformed(ActionEvent e)
     {
@@ -389,15 +394,16 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
         else if (e.getSource() == bSaveAs)
         {
             ProtocolPanel protocol = getActiveProtocol();
-            
-            if (protocol == null) return;
-            
+
+            if (protocol == null)
+                return;
+
             // save the old file to restore it in case a problem occurs
             File oldFile = protocol.getFile();
-            
+
             // erase the file to force an open file dialog
             protocol.setFile(null);
-            
+
             if (!saveWorkFlow(protocol, true))
             {
                 // work flow was not saved => restore the old file
@@ -407,9 +413,10 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
         else if (e.getSource() == bRun)
         {
             ProtocolPanel protocol = getActiveProtocol();
-            
-            if (protocol == null) return;
-            
+
+            if (protocol == null)
+                return;
+
             WorkFlow wf = protocol.getWorkFlow();
             if (wf.getBlockDescriptor().getStatus() == BlockStatus.RUNNING)
             {
@@ -423,19 +430,21 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
         else if (e.getSource() == bEmbed)
         {
             ProtocolPanel panel = getActiveProtocol();
-            if (panel != null) panel.showBlocksEmbedMenu(bEmbed);
+            if (panel != null)
+                panel.showBlocksEmbedMenu(bEmbed);
         }
         else if (e.getSource() == bClean)
         {
             ProtocolPanel protocol = getActiveProtocol();
-            
-            if (protocol == null) return;
-            
+
+            if (protocol == null)
+                return;
+
             WorkFlow wf = protocol.getWorkFlow();
             wf.reset();
         }
     }
-    
+
     @Override
     public void propertyChange(PropertyChangeEvent evt)
     {
@@ -443,17 +452,19 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
         {
             ProtocolPanel protocolPanel = (ProtocolPanel) evt.getSource();
             int index = getProtocolPanels().indexOf(protocolPanel);
-            
+
             if (index == -1)
             {
                 String message = "in method \"icy.adufour.protocols.Protocols.propertyChange(PropertyChangeEvent)\":\n";
                 message += "A protocol was modified, but its panel is already closed (index = -1)";
-                IcyExceptionHandler.handleException(pluginInstance.getDescriptor(), new ArrayIndexOutOfBoundsException(message), true);
+                IcyExceptionHandler.handleException(pluginInstance.getDescriptor(),
+                        new ArrayIndexOutOfBoundsException(message), true);
                 return;
             }
-            
-            if (closeableTabbedPane.getTabCount() <= index) return;
-            
+
+            if (closeableTabbedPane.getTabCount() <= index)
+                return;
+
             if (((Boolean) evt.getNewValue()).booleanValue())
             {
                 closeableTabbedPane.setTitleAt(index, "* " + closeableTabbedPane.getTitleAt(index));
@@ -468,12 +479,12 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             super.propertyChange(evt);
         }
     }
-    
+
     @Override
     public void tabClosed(int index, String title)
     {
     }
-    
+
     @Override
     public boolean tabClosing(int index, String title)
     {
@@ -481,57 +492,65 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
         if (protocol.isDirty() && !protocol.isEmpty() && !pluginInstance.isReloading())
         {
             String name = protocol.getFile() == null ? UNTITLED : protocol.getFile().getName();
-            int option = JOptionPane.showConfirmDialog(protocol, name + " has not been saved.\nSave workflow before closing ?", "Confirmation", JOptionPane.YES_NO_CANCEL_OPTION);
-            
-            if (option == JOptionPane.CANCEL_OPTION) return false;
-            
-            if (option == JOptionPane.YES_OPTION && !saveWorkFlow(protocol, false)) return false;
+            int option = JOptionPane.showConfirmDialog(protocol,
+                    name + " has not been saved.\nSave workflow before closing ?", "Confirmation",
+                    JOptionPane.YES_NO_CANCEL_OPTION);
+
+            if (option == JOptionPane.CANCEL_OPTION)
+                return false;
+
+            if (option == JOptionPane.YES_OPTION && !saveWorkFlow(protocol, false))
+                return false;
         }
         protocol.removePropertyChangeListener(this);
         protocol.removeBlockListener(this);
         protocol.dispose();
-        
+
         // Remove drag'n'drop hooks
         FileDrop.remove(protocol);
         getProtocolPanels().remove(protocol);
-        
+
         return true;
     }
-    
+
     /**
      * @param protocol
      * @param updateTabName
      * @return true if the saving operation was successful, false if canceled
      * @throws BlocksException
-     *             if an error occurred while saving to disk
+     *         if an error occurred while saving to disk
      */
     private boolean saveWorkFlow(ProtocolPanel protocol, boolean updateTabName) throws BlocksException
     {
-        if (protocol == null) return false;
-        
+        if (protocol == null)
+            return false;
+
         boolean success = protocol.saveToDisk();
-        
-        if (!success) return false;
-        
+
+        if (!success)
+            return false;
+
         File savedFile = protocol.getFile();
-        
-        if (updateTabName) closeableTabbedPane.setTitleAt(closeableTabbedPane.getSelectedIndex(), savedFile.getName());
-        
+
+        if (updateTabName)
+            closeableTabbedPane.setTitleAt(closeableTabbedPane.getSelectedIndex(), savedFile.getName());
+
         return true;
     }
-    
+
     private File getFile()
     {
         final JFileChooser jfc = new JFileChooser(Protocols.getDefaultProtocolFolder());
-        
+
         jfc.setFileFilter(BlocksML.XML_FILE_FILTER);
         jfc.setDialogTitle("Load an Icy protocol...");
-        
-        if (jfc.showOpenDialog(getFrame()) != JFileChooser.APPROVE_OPTION) return null;
-        
+
+        if (jfc.showOpenDialog(getFrame()) != JFileChooser.APPROVE_OPTION)
+            return null;
+
         return jfc.getSelectedFile();
     }
-    
+
     /**
      * @return the protocolPanels
      */
@@ -539,61 +558,67 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
     {
         return protocolPanels;
     }
-    
+
     /**
      * Loads the specified file as a new workflow
      * 
      * @param file
      * @throws IllegalArgumentException
-     *             if the file is not a protocol
+     *         if the file is not a protocol
      */
     public void loadWorkFlow(File file) throws IllegalArgumentException
     {
-        if (file == null) file = getFile();
-        
-        if (file == null) return;
-        
+        if (file == null)
+            file = getFile();
+
+        if (file == null)
+            return;
+
         final File workingFile = file;
-        
+
         Protocols.setDefaultProtocolFolder(file.getParent());
-        
+
         // check that the work flow is not already opened
         for (ProtocolPanel protocol : getProtocolPanels())
-            if (file.equals(protocol.getFile())) return;
-        
+            if (file.equals(protocol.getFile()))
+                return;
+
         // make sure the xml is well-formed
         final Document xml = XMLUtil.loadDocument(file);
-        
+
         boolean isFileValid = false;
-        
+
         if (xml != null)
         {
             String rootName = XMLUtil.getRootElement(xml).getNodeName();
             isFileValid = rootName.equalsIgnoreCase("protocol") || rootName.equalsIgnoreCase("workspace");
         }
-        
-        if (!isFileValid) throw new IcyHandledException("Error while loading \"" + file.getPath() + "\":\nThe selected file is not an Icy protocol.");
-        
+
+        if (!isFileValid)
+            throw new IcyHandledException(
+                    "Error while loading \"" + file.getPath() + "\":\nThe selected file is not an Icy protocol.");
+
         final ProtocolPanel panel = new ProtocolPanel(this);
         panel.setFile(file);
         addProtocolPane(panel);
-        
+
         ThreadUtil.bgRun(new Runnable()
         {
             @Override
             public void run()
             {
                 AnnounceFrame announce = new AnnounceFrame("Loading protocol " + workingFile.getName() + "...");
-                
+
                 try
                 {
                     PluginInstaller.waitInstall();
                     PluginLoader.waitWhileLoading();
-                    
+
                     ArrayList<PluginDescriptor> plugins = PluginLoader.getPlugins(Block.class, true, false, false);
-                    
-                    if (plugins.size() == 0) throw new BlocksReloadedException();
-                    
+
+                    if (plugins.size() == 0)
+                        throw new BlocksReloadedException();
+
                     panel.loadWorkFlow(xml, false);
                 }
                 catch (BlocksReloadedException e)
@@ -611,17 +636,18 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
                             message += " - Yes: send the report and the protocol (recommended for diagnosis).\n";
                             message += " - No: send the report but not the protocol (recommended for privacy).\n";
                             message += " - Cancel: discard this message (nothing will be sent)";
-                            int answer = JOptionPane.showConfirmDialog(getFrame(), message, "Couldn't load protocol", JOptionPane.YES_NO_CANCEL_OPTION);
-                            
+                            int answer = JOptionPane.showConfirmDialog(getFrame(), message, "Couldn't load protocol",
+                                    JOptionPane.YES_NO_CANCEL_OPTION);
+
                             StringWriter sw = new StringWriter();
                             e.printStackTrace(new PrintWriter(sw));
-                            
+
                             message += "\n\n" + sw.toString();
-                            
+
                             switch (answer)
                             {
                                 case JOptionPane.YES_OPTION:
-                                    
+
                                     try
                                     {
                                         message += "\n\n" + BlocksML.getInstance().toString(xml);
@@ -638,11 +664,11 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
                                     {
                                         e1.printStackTrace();
                                     }
-                                    
+
                                     //$FALL-THROUGH$ Send the report anyway
                                 case JOptionPane.NO_OPTION:
                                     IcyExceptionHandler.report(pluginInstance.getDescriptor(), message);
-                                break;
+                                    break;
                                 default:
                                     return;
                             }
@@ -656,59 +682,60 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             }
         });
     }
-    
+
     @Override
     public void icyFrameOpened(IcyFrameEvent e)
     {
     }
-    
+
     @Override
     public void icyFrameClosing(IcyFrameEvent e)
     {
         if (e.getFrame() == this)
         {
             isFrameClosing = true;
-            
-            if (!accept(this)) isFrameClosing = false;
+
+            if (!accept(this))
+                isFrameClosing = false;
         }
     }
-    
+
     @Override
     public void icyFrameClosed(IcyFrameEvent e)
     {
         pluginInstance.setReloading(false);
     }
-    
+
     @Override
     public void icyFrameIconified(IcyFrameEvent e)
     {
     }
-    
+
     @Override
     public void icyFrameDeiconified(IcyFrameEvent e)
     {
     }
-    
+
     @Override
     public void icyFrameActivated(IcyFrameEvent e)
     {
     }
-    
+
     @Override
     public void icyFrameDeactivated(IcyFrameEvent e)
     {
     }
-    
+
     @Override
     public void icyFrameInternalized(IcyFrameEvent e)
     {
     }
-    
+
     @Override
     public void icyFrameExternalized(IcyFrameEvent e)
     {
     }
-    
+
     @Override
     public void filesDropped(File[] files)
     {
@@ -720,63 +747,67 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             }
             catch (IllegalArgumentException e)
             {
-                if (Loader.isSupportedImageFile(file.getPath())) Loader.load(file.getPath(), true);
+                if (Loader.isSupportedImageFile(file.getPath()))
+                    Loader.load(file.getPath(), true);
             }
         }
     }
-    
+
     @Override
     public boolean accept(Object source)
     {
         while (closeableTabbedPane.getTabCount() > 0)
         {
             int tabCount = closeableTabbedPane.getTabCount();
-            
+
             for (int i = 0; i < tabCount; i++)
             {
                 if (closeableTabbedPane.getSelectedIndex() == i)
                 {
                     boolean closeAccepted = tabClosing(i, null);
-                    
+
                     // if "cancel" is clicked for either tab, stop the closing process
-                    if (!closeAccepted) return false;
-                    
-                    if (closeableTabbedPane.getTabCount() > i) closeableTabbedPane.removeTabAt(i);
-                    
+                    if (!closeAccepted)
+                        return false;
+
+                    if (closeableTabbedPane.getTabCount() > i)
+                        closeableTabbedPane.removeTabAt(i);
+
                     break;
                 }
             }
         }
-        
+
         for (Component component : toolBar.getComponents())
         {
-            if (component instanceof JButton) ((JButton) component).removeActionListener(this);
-            
+            if (component instanceof JButton)
+                ((JButton) component).removeActionListener(this);
+
             toolBar.remove(component);
         }
-        
+
         getContentPane().removeAll();
-        
+
         removeFrameListener(this);
-        
+
         // close manually
-        
+
         setVisible(false);
-        
+
         close();
-        
+
         Icy.getMainInterface().removeCanExitListener(this);
-        
+
         Protocols.close();
-        
+
         return true;
     }
-    
+
     @Override
     public void stateChanged(ChangeEvent e)
     {
         ProtocolPanel panel = getActiveProtocol();
-        
+
         if (e.getSource() == closeableTabbedPane && panel != null)
         {
             // tab was selected, added or removed
@@ -784,70 +815,70 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
             updateRunButton(getActiveProtocol().getWorkFlow().getBlockDescriptor().getStatus());
         }
     }
-    
+
     private void updateRunButton(BlockStatus status)
     {
         switch (status)
         {
             case RUNNING:
                 bRun.setIcon(new IcyIcon(ResourceUtil.ICON_STOP));
-            break;
+                break;
             default:
                 bRun.setIcon(new IcyIcon(ResourceUtil.ICON_PLAY));
         }
     }
-    
+
     @Override
     public void blockCollapsed(BlockDescriptor block, boolean collapsed)
     {
-        
+
     }
-    
+
     @Override
     public void blockDimensionChanged(BlockDescriptor block, int newWidth, int newHeight)
     {
     }
-    
+
     @Override
     public void blockLocationChanged(BlockDescriptor block, int newX, int newY)
     {
     }
-    
+
     @Override
     public void blockStatusChanged(BlockDescriptor block, BlockStatus status)
     {
         updateRunButton(status);
     }
-    
+
     @Override
     public void blockVariableAdded(BlockDescriptor block, Var<?> variable)
     {
     }
-    
+
     @Override
     public <T> void blockVariableChanged(BlockDescriptor block, Var<T> variable, T newValue)
     {
     }
-    
+
     private class MySplitPaneUI extends SubstanceSplitPaneUI
     {
-        
+
         @SuppressWarnings("serial")
         private class MySplitPaneDivider extends SubstanceSplitPaneDivider
         {
-            
+
             public MySplitPaneDivider(SubstanceSplitPaneUI ui)
             {
                 super(ui);
             }
-            
+
             protected JButton createLeftOneTouchButton()
             {
                 JButton button = super.createLeftOneTouchButton();
                 button.setPreferredSize(new Dimension(20, 40));
                 return button;
             }
-            
+
             protected JButton createRightOneTouchButton()
             {
                 JButton button = super.createRightOneTouchButton();
@@ -855,7 +886,7 @@ public class MainFrame extends IcyFrame implements IcyFrameListener, ActionListe
                 return button;
             }
         }
-        
+
         public BasicSplitPaneDivider createDefaultDivider()
         {
             return new MySplitPaneDivider(this);
diff --git a/src/main/java/plugins/adufour/protocols/gui/ProtocolPanel.java b/src/main/java/plugins/adufour/protocols/gui/ProtocolPanel.java
index 0aa76de4d433a4b6f8d0390110d4505994da2938..5df0e476d1f4206cfecfa4dcd9ed7d67db71e432 100644
--- a/src/main/java/plugins/adufour/protocols/gui/ProtocolPanel.java
+++ b/src/main/java/plugins/adufour/protocols/gui/ProtocolPanel.java
@@ -80,7 +80,7 @@ public class ProtocolPanel extends JPanel implements WorkFlowListener, PropertyC
     
     public ProtocolPanel(MainFrame frame)
     {
-        this(null, new WorkFlow(), frame);
+        this(null, new WorkFlow(true), frame);
     }
     
     private ProtocolPanel(File file, final WorkFlow workFlow, MainFrame frame)
diff --git a/src/main/java/plugins/adufour/protocols/gui/block/WorkFlowContainer.java b/src/main/java/plugins/adufour/protocols/gui/block/WorkFlowContainer.java
index f07994a50be0a182be04cf009a2783e42722738d..3a64436b5ed50a56ced759a9ed9b456443d68b9e 100644
--- a/src/main/java/plugins/adufour/protocols/gui/block/WorkFlowContainer.java
+++ b/src/main/java/plugins/adufour/protocols/gui/block/WorkFlowContainer.java
@@ -335,7 +335,7 @@ public class WorkFlowContainer extends JLayeredPane implements WorkFlowListener,
                     }
                     else
                         dstBlockPanel.refreshNow();
-                    
+
                     repaint();
                 }
             }
@@ -368,8 +368,29 @@ public class WorkFlowContainer extends JLayeredPane implements WorkFlowListener,
                 }
 
                 panel.drawPanel();
+
                 blockPanels.put(blockDesc, panel);
                 add(panel);
+
+                // FIX: get exposed links correctly restored on copy/paste as setVisibility isn't called in that case (Stephane)
+                // this is really an ugly fix but the whole stuff is a complete mess honestly :-/
+                if (blockDesc.isWorkFlow())
+                {
+                    synchronized (blockDesc.inputVars)
+                    {
+                        // update exposed links
+                        for (Var<?> var : blockDesc.inputVars)
+                            ((WorkFlowPanel) panel).updateExposedLink(var, blockDesc.inputVars.isVisible(var));
+                    }
+
+                    synchronized (blockDesc.outputVars)
+                    {
+                        // update exposed links
+                        for (Var<?> var : blockDesc.outputVars)
+                            ((WorkFlowPanel) panel).updateExposedLink(var, blockDesc.outputVars.isVisible(var));
+                    }
+                }
+
                 // Layer 0 for blocks
                 // Layer 1 for work flows
                 setLayer(panel, blockDesc.isWorkFlow() ? 1 : 0, 0);
@@ -531,9 +552,9 @@ public class WorkFlowContainer extends JLayeredPane implements WorkFlowListener,
                 workFlow.removeBlock(workFlow.getBlock(i), true);
         }
 
-        workFlow.addBlock(embed.getBlockDescriptor());
-
         MainFrame.pasteSelection(embed, true);
+        
+        workFlow.addBlock(embed.getBlockDescriptor());
     }
 
     /**
diff --git a/src/main/java/plugins/adufour/protocols/gui/block/WorkFlowPanel.java b/src/main/java/plugins/adufour/protocols/gui/block/WorkFlowPanel.java
index b1114dc50a7aed7c0ec1c43805d253ffc107f0c4..fed9063753ccc61534e87a5365d4199d94482dd3 100644
--- a/src/main/java/plugins/adufour/protocols/gui/block/WorkFlowPanel.java
+++ b/src/main/java/plugins/adufour/protocols/gui/block/WorkFlowPanel.java
@@ -40,25 +40,25 @@ import plugins.adufour.vars.lang.Var;
 public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
 {
     private final WorkFlow innerWorkFlow;
-    
+
     protected final JScrollPane scrollPane;
-    
+
     protected final WorkFlowContainer innerFlowPane;
-    
+
     private final HashMap<Var<?>, Line> exposingLinks = new HashMap<Var<?>, Line>();
-    
+
     private final MouseAdapter mouseAdapter;
-    
+
     protected Box varBox;
-    
+
     protected final JMenuItem menuRemoveEnclosure = new JMenuItem("Remove block but keep contents");
-    
+
     public WorkFlowPanel(WorkFlowContainer wfPane, final BlockDescriptor blockDesc)
     {
         super(wfPane, blockDesc);
-        
+
         this.innerWorkFlow = (WorkFlow) blockDesc.getBlock();
-        
+
         mouseAdapter = new MouseAdapter()
         {
             @Override
@@ -67,55 +67,56 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
                 int xShift = innerFlowPane.getLocationOnScreen().x - getLocationOnScreen().x;
                 int yShift = innerFlowPane.getLocationOnScreen().y - getLocationOnScreen().y;
                 Point realPoint = new Point(e.getX() + xShift, e.getY() + yShift);
-                
+
                 for (Var<?> var : exposingLinks.keySet())
                     if (exposingLinks.get(var).isOverCloseButton(realPoint))
                     {
                         VarList vars = blockDesc.inputVars;
-                        
-                        if (!vars.contains(var)) vars = blockDesc.outputVars;
-                        
+
+                        if (!vars.contains(var))
+                            vars = blockDesc.outputVars;
+
                         vars.setVisible(var, !vars.isVisible(var));
-                        
+
                         // prevent concurrent modification
                         break;
                     }
             }
-            
+
             @Override
             public void mouseMoved(MouseEvent e)
             {
                 int xShift = innerFlowPane.getLocationOnScreen().x - getLocationOnScreen().x;
                 int yShift = innerFlowPane.getLocationOnScreen().y - getLocationOnScreen().y;
                 Point realPoint = new Point(e.getX() + xShift, e.getY() + yShift);
-                
+
                 for (Line l : exposingLinks.values())
                     l.setCustomColor(l.contains(realPoint.x, realPoint.y));
             }
         };
-        
+
         blockDesc.inputVars.addVisibilityListener(this);
         blockDesc.outputVars.addVisibilityListener(this);
-        
+
         this.innerFlowPane = new WorkFlowContainer(innerWorkFlow, wfPane.isEditable());
         this.innerFlowPane.setParentPanel(this);
-        
+
         this.innerFlowPane.addMouseListener(mouseAdapter);
         this.innerFlowPane.addMouseMotionListener(mouseAdapter);
-        
+
         this.scrollPane = new JScrollPane(innerFlowPane);
         scrollPane.setOpaque(false);
         scrollPane.setPreferredSize(new Dimension());
-        
+
         // XXX
         varBox = Box.createVerticalBox();
         varBox.setOpaque(false);
         varBox.setVisible(false);
         add(varBox, BorderLayout.SOUTH);
-        
+
         // check whether the descriptor has a stored size
         Dimension size = innerWorkFlow.getBlockDescriptor().getDimension();
-        
+
         if (size.width != 0)
         {
             // use it
@@ -127,13 +128,13 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
             setPreferredSize(new Dimension(400, 400));
         }
         setResizeable(!blockDesc.isCollapsed());
-        
+
         // add an extra option to close the work flow while preserving its contents
         menuRemoveEnclosure.addActionListener(this);
         menuRemoveEnclosure.setIcon(ICON_REMOVE);
         menuRemoveEnclosure.setToolTipText("<html><h4>Remove this block but keep its contents</h4></html>");
     }
-    
+
     @Override
     public void actionPerformed(ActionEvent e)
     {
@@ -142,31 +143,32 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
             innerFlowPane.selectAllBlocks();
             workFlowPane.getWorkFlow().removeBlock(blockDesc, true);
         }
-        else super.actionPerformed(e);
+        else
+            super.actionPerformed(e);
     }
-    
+
     @Override
     protected void drawMenu()
     {
         super.drawMenu();
-        
+
         // add an extra option to close the work flow while preserving its contents
         super.menu.add(menuRemoveEnclosure);
     }
-    
+
     @Override
     protected void drawContent()
     {
         int maxRow = drawExposedLinks(0);
-        
+
         drawInnerWorkFlowContainer(maxRow + 1);
     }
-    
+
     /**
      * Draws the drag'n'drop zones representing the exposed variables of the inner work flow
      * 
      * @param gridRow
-     *            the row where to start drawing within the {@link GridBagLayout}
+     *        the row where to start drawing within the {@link GridBagLayout}
      * @return the last row used in the {@link GridBagLayout}
      */
     protected int drawExposedLinks(int row)
@@ -175,13 +177,16 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
         for (Var<?> input : innerWorkFlow.getBlockDescriptor().inputVars)
         {
             // don't show hidden variable
-            if (!blockDesc.inputVars.isVisible(input)) continue;
-            
+            if (!blockDesc.inputVars.isVisible(input))
+                continue;
+
             // don't show local loop variables
-            if (blockDesc.isLoop() && ((Loop) blockDesc.getBlock()).isLoopVariable(input)) continue;
-            
-            if (!varDropZones.containsKey(input)) varDropZones.put(input, createVarDropZone(input, true, DragDropZone.LINK_RIGHT));
-            
+            if (blockDesc.isLoop() && ((Loop) blockDesc.getBlock()).isLoopVariable(input))
+                continue;
+
+            if (!varDropZones.containsKey(input))
+                varDropZones.put(input, createVarDropZone(input, true, DragDropZone.LINK_RIGHT));
+
             GridBagConstraints gbc_dropZone = new GridBagConstraints();
             gbc_dropZone.anchor = GridBagConstraints.WEST;
             gbc_dropZone.fill = GridBagConstraints.NONE;
@@ -192,18 +197,21 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
             DragDropZone dropZone = varDropZones.get(input);
             jPanelContent.add(dropZone, gbc_dropZone);
         }
-        
+
         int rowOut = row;
         for (Var<?> output : innerWorkFlow.getBlockDescriptor().outputVars)
         {
             // don't show hidden variable
-            if (!blockDesc.outputVars.isVisible(output)) continue;
-            
+            if (!blockDesc.outputVars.isVisible(output))
+                continue;
+
             // don't show local loop variables
-            if (blockDesc.isLoop() && ((Loop) blockDesc.getBlock()).isLoopVariable(output)) continue;
-            
-            if (!varDragZones.containsKey(output)) varDragZones.put(output, createVarDragZone(output, true));
-            
+            if (blockDesc.isLoop() && ((Loop) blockDesc.getBlock()).isLoopVariable(output))
+                continue;
+
+            if (!varDragZones.containsKey(output))
+                varDragZones.put(output, createVarDragZone(output, true));
+
             GridBagConstraints gbc_dragZone = new GridBagConstraints();
             gbc_dragZone.anchor = GridBagConstraints.EAST;
             gbc_dragZone.fill = GridBagConstraints.NONE;
@@ -213,15 +221,15 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
             DragDropZone dragZone = varDragZones.get(output);
             jPanelContent.add(dragZone, gbc_dragZone);
         }
-        
+
         return Math.max(rowIn, rowOut);
     }
-    
+
     /**
      * Draws the container representing the inner work flow
      * 
      * @param row
-     *            the row where the container should be added within the {@link GridBagLayout}
+     *        the row where the container should be added within the {@link GridBagLayout}
      */
     protected void drawInnerWorkFlowContainer(int row)
     {
@@ -236,41 +244,42 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
         gbc.weighty = 1;
         jPanelContent.add(scrollPane, gbc);
     }
-    
+
     @Override
     void dispose()
     {
         blockDesc.inputVars.addVisibilityListener(this);
         blockDesc.outputVars.addVisibilityListener(this);
-        
+
         menuRemoveEnclosure.removeActionListener(this);
-        
+
         innerFlowPane.removeMouseListener(mouseAdapter);
         innerFlowPane.removeMouseMotionListener(mouseAdapter);
-        
+
         innerFlowPane.dispose();
-        
+
         super.dispose();
     }
-    
+
     @Override
     public void paintChildren(Graphics g)
     {
-        Graphics gg = g.create();        
-        
+        Graphics gg = g.create();
+
         super.paintChildren(g);
-        
+
         Rectangle clip = scrollPane.getBounds();
         gg.clipRect(clip.x, clip.y, clip.width, clip.height);
-        if (!blockDesc.isCollapsed()) for (Line line : exposingLinks.values())
-        {
-            line.update();
-            line.paint((Graphics2D) gg);
-        }
+        if (!blockDesc.isCollapsed())
+            for (Line line : exposingLinks.values())
+            {
+                line.update();
+                line.paint((Graphics2D) gg);
+            }
         gg.dispose();
-        
+
     }
-    
+
     @Override
     public void visibilityChanged(final Var<?> variable, boolean isVisible)
     {
@@ -283,21 +292,25 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
                 refreshNow();
             }
         });
-        
-        if (isVisible)
+
+        updateExposedLink(variable, isVisible);
+    }
+
+    public void updateExposedLink(final Var<?> variable, boolean visible)
+    {
+        if (visible)
         {
             if (innerWorkFlow.getInputOwner(variable) != null)
             {
                 // source is an input variable
-                
                 final BlockDescriptor innerBlock = innerWorkFlow.getInputOwner(variable);
-                
+
                 ThreadUtil.invokeLater(new Runnable()
                 {
                     public void run()
                     {
                         final BlockPanel ownerPanel = innerFlowPane.getBlockPanel(innerBlock);
-                        
+
                         exposingLinks.put(variable, new RoundedSquareLine(WorkFlowPanel.this, ownerPanel, variable)
                         {
                             @Override
@@ -305,26 +318,27 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
                             {
                                 return varDropZones.get(variable);
                             }
-                            
+
                             @Override
                             protected DragDropZone getP2Zone()
                             {
                                 return ownerPanel.varDropZones.get(variable);
                             }
-                            
+
                             @Override
                             public void updateP1()
                             {
-                                if (blockDesc.isCollapsed()) return;
-                                
+                                if (blockDesc.isCollapsed())
+                                    return;
+
                                 DragDropZone dz = varDropZones.get(variable);
                                 int y = dz.getLocationOnScreen().y;
                                 int offsetY = getLocationOnScreen().y;
-                                
+
                                 x1 = dz.getWidth();
                                 y1 = y - offsetY + dz.getHeight() / 2;
                             }
-                            
+
                             @Override
                             public void updateP2()
                             {
@@ -343,25 +357,20 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
                                 }
                             }
                         });
-                        
-                        refresh();
                     }
                 }, true);
-                
             }
             else
             {
                 // source is an output variable
-                
                 final BlockDescriptor innerBlock = innerWorkFlow.getOutputOwner(variable);
-                
+
                 ThreadUtil.invokeLater(new Runnable()
                 {
                     public void run()
                     {
-                        
                         final BlockPanel ownerPanel = innerFlowPane.getBlockPanel(innerBlock);
-                        
+
                         exposingLinks.put(variable, new RoundedSquareLine(ownerPanel, WorkFlowPanel.this, variable)
                         {
                             @Override
@@ -369,13 +378,13 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
                             {
                                 return ownerPanel.varDragZones.get(variable);
                             }
-                            
+
                             @Override
                             protected DragDropZone getP2Zone()
                             {
                                 return varDragZones.get(variable);
                             }
-                            
+
                             @Override
                             public void updateP1()
                             {
@@ -393,16 +402,17 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
                                     y1 = loc.y - getLocationOnScreen().y + dz.getHeight() / 2;
                                 }
                             }
-                            
+
                             @Override
                             public void updateP2()
                             {
-                                if (blockDesc.isCollapsed()) return;
-                                
+                                if (blockDesc.isCollapsed())
+                                    return;
+
                                 DragDropZone dz = varDragZones.get(variable);
                                 int y = dz.getLocationOnScreen().y;
                                 int innerY = getLocationOnScreen().y;
-                                
+
                                 x2 = dz.getLocation().x;
                                 y2 = y - innerY + dz.getHeight() / 2;
                             }
@@ -414,48 +424,49 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
         else if (exposingLinks.containsKey(variable))
         {
             variable.setReference(null);
-            
+
             exposingLinks.remove(variable).dispose();
-            
+
             BlockDescriptor block = innerWorkFlow.getInputOwner(variable);
-            
+
             WorkFlow parentWorkFlow = blockDesc.getContainer();
-            
+
             if (block != null)
             {
                 // source is an input variable
                 varDropZones.remove(variable);
                 blockDesc.getContainer().getBlockDescriptor().removeInput(variable);
-                
+
                 // remove links pointed to the exposed variable (if any)
-                if (parentWorkFlow.isLinked(variable)) parentWorkFlow.removeLink(variable);
+                if (parentWorkFlow.isLinked(variable))
+                    parentWorkFlow.removeLink(variable);
             }
             else
             {
                 block = innerWorkFlow.getOutputOwner(variable);
-                
+
                 if (block != null)
                 {
                     varDragZones.remove(variable);
                     blockDesc.getContainer().getBlockDescriptor().removeOutput(variable);
-                    
+
                     // remove links pointed to the exposed variable (if any)
                     ArrayList<Link<?>> linksToDelete = new ArrayList<Link<?>>();
                     for (Link<?> link : parentWorkFlow.getLinksIterator())
-                        if (link.srcVar == variable) linksToDelete.add(link);
-                        
+                        if (link.srcVar == variable)
+                            linksToDelete.add(link);
+
                     for (Link<?> link : linksToDelete)
                         parentWorkFlow.removeLink(link.dstVar);
                 }
             }
         }
-        
+
         repaint();
-        
         // Repaint the top-level container
         getParent().repaint();
     }
-    
+
     public void drawPanel()
     {
         super.drawPanel();
@@ -467,39 +478,39 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
             gbc_dropZone.fill = GridBagConstraints.NONE;
             gbc_dropZone.insets = new Insets(2, 0, 0, 0);
             gbc_dropZone.gridx = 0;
-            
+
             GridBagConstraints gbc_varName = new GridBagConstraints();
             gbc_varName.anchor = GridBagConstraints.CENTER;
             gbc_varName.fill = GridBagConstraints.HORIZONTAL;
             gbc_varName.insets = new Insets(2, 5, 0, 0);
             gbc_varName.gridx = 1;
             gbc_varName.weightx = 1;
-            
+
             GridBagConstraints gbc_dragZone = new GridBagConstraints();
             gbc_dragZone.anchor = GridBagConstraints.EAST;
             gbc_dragZone.fill = GridBagConstraints.NONE;
             gbc_dragZone.insets = new Insets(2, 5, 0, 0);
             gbc_dragZone.gridx = 2;
-            
+
             LinkedHashMap<BlockDescriptor, ArrayList<Var<?>>> inputs = new LinkedHashMap<BlockDescriptor, ArrayList<Var<?>>>();
             LinkedHashMap<BlockDescriptor, ArrayList<Var<?>>> outputs = new LinkedHashMap<BlockDescriptor, ArrayList<Var<?>>>();
-            
+
             JPanel blockP;
             Box blockBox;
             JPanel varPanel;
-            
+
             varBox.removeAll();
-            
+
             ArrayList<Var<?>> in;
             ArrayList<Var<?>> out;
-            
+
             int nbExposingBlocks = 0;
-            
+
             for (BlockDescriptor bd : innerWorkFlow)
             {
                 in = new ArrayList<Var<?>>();
                 out = new ArrayList<Var<?>>();
-                
+
                 for (Var<?> v : bd.inputVars)
                     if (exposingLinks.keySet().contains(v))
                     {
@@ -523,58 +534,59 @@ public class WorkFlowPanel extends BlockPanel implements VarVisibilityListener
                         }
                     }
             }
-            
+
             varBox.setPreferredSize(new Dimension(0, exposingLinks.size() * 20 + nbExposingBlocks * 25));
-            
+
             for (BlockDescriptor bd : inputs.keySet())
             {
                 varBox.add(new JSeparator(JSeparator.HORIZONTAL));
                 blockP = new JPanel(new BorderLayout());
                 blockP.setOpaque(false);
-                
+
                 JLabel blockName = new JLabel("\t" + bd.getDefinedName(), JLabel.CENTER);
                 blockName.setFont(blockName.getFont().deriveFont(Font.BOLD + Font.ITALIC, 12));
                 blockP.add(blockName, BorderLayout.NORTH);
-                
+
                 blockBox = Box.createVerticalBox();
                 blockBox.setOpaque(false);
                 blockP.add(blockBox, BorderLayout.CENTER);
-                
+
                 for (Var<?> v : inputs.get(bd))
                 {
                     varPanel = new JPanel(new GridBagLayout());
                     varPanel.setOpaque(false);
-                    
+
                     varPanel.add(varDropZones.get(v), gbc_dropZone);
                     varPanel.add(new JLabel("\t" + v.getName()), gbc_varName);
-                    
+
                     blockBox.add(varPanel);
                 }
-                
+
                 for (Var<?> v : outputs.get(bd))
                 {
                     varPanel = new JPanel(new GridBagLayout());
                     varPanel.setOpaque(false);
-                    
+
                     varPanel.add(new JLabel("\t\t\t"), gbc_dropZone);
                     varPanel.add(new JLabel("\t" + v.getName()), gbc_varName);
                     varPanel.add(varDragZones.get(v), gbc_dragZone);
-                    
+
                     blockBox.add(varPanel);
                 }
-                
+
                 varBox.add(blockP);
             }
             setSize(getPreferredSize());
         }
     }
-    
+
     public Dimension getPreferredSize()
     {
         Dimension d = super.getPreferredSize();
-        
-        if (!blockDesc.isCollapsed()) return d;
-        
+
+        if (!blockDesc.isCollapsed())
+            return d;
+
         return new Dimension(200, d.height + varBox.getPreferredSize().height);
     }
 }