Author: clopes
Date: 2012-11-07 12:59:13 -0800 (Wed, 07 Nov 2012)
New Revision: 30755

Modified:
   
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/MCODEAboutAction.java
   
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/MCODEVisualStyleAction.java
   
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/model/MCODEAlgorithm.java
   
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/model/MCODECluster.java
   
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/util/MCODEUtil.java
   
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODEAboutDialog.java
   
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODELoader.java
   
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODEResultsPanel.java
   
csplugins/trunk/toronto/clopes/mcode/src/test/java/org/cytoscape/mcode/internal/model/MCODEAlgorithmTest.java
Log:
Fixed a bug that could cause an infinite loop when changing the size threshold 
of an MCODE cluster.
Some minor refactoring.

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/MCODEAboutAction.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/MCODEAboutAction.java
       2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/MCODEAboutAction.java
       2012-11-07 20:59:13 UTC (rev 30755)
@@ -55,6 +55,7 @@
 
        private final OpenBrowser openBrowser;
        private final MCODEUtil mcodeUtil;
+       private MCODEAboutDialog aboutDialog;
 
        public MCODEAboutAction(final String name,
                                                        final 
CyApplicationManager applicationManager,
@@ -71,7 +72,17 @@
        @Override
        public void actionPerformed(ActionEvent e) {
                //display about box
-               MCODEAboutDialog aboutDialog = new 
MCODEAboutDialog(swingApplication, openBrowser, mcodeUtil);
-               aboutDialog.setVisible(true);
+               synchronized (this) {
+                       if (aboutDialog == null) {
+                               aboutDialog = new 
MCODEAboutDialog(swingApplication, openBrowser, mcodeUtil);
+                       }
+                       
+                       if (!aboutDialog.isVisible()) {
+                               aboutDialog.setLocationRelativeTo(null);
+                               aboutDialog.setVisible(true);
+                       }
+               }
+               
+               aboutDialog.toFront();
        }
 }

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/MCODEVisualStyleAction.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/MCODEVisualStyleAction.java
 2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/MCODEVisualStyleAction.java
 2012-11-07 20:59:13 UTC (rev 30755)
@@ -97,13 +97,14 @@
                        double maxScore = 
resultsPanel.setNodeAttributesAndGetMaxScore();
                        // We also need the selected row if one is selected at 
all
                        resultsPanel.selectCluster(null);
-                       int selectedRow = 
resultsPanel.getClusterBrowserTable().getSelectedRow();
-                       resultsPanel.getClusterBrowserTable().clearSelection();
-
-                       if (selectedRow >= 0) {
-                               
resultsPanel.getClusterBrowserTable().setRowSelectionInterval(selectedRow, 
selectedRow);
-                       }
-
+// TODO: delete/fix
+//                     int selectedRow = resultsPanel.getSelectedRow();
+//                     resultsPanel.getClusterBrowserTable().clearSelection();
+//
+//                     if (selectedRow >= 0) {
+//                             
resultsPanel.getClusterBrowserTable().setRowSelectionInterval(selectedRow, 
selectedRow);
+//                     }
+                       
                        // Get the updated app's style
                        VisualStyle appStyle = mcodeUtil.getAppStyle(maxScore);
                        // Register the app's style but don't make it active by 
default

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/model/MCODEAlgorithm.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/model/MCODEAlgorithm.java
   2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/model/MCODEAlgorithm.java
   2012-11-07 20:59:13 UTC (rev 30755)
@@ -335,7 +335,7 @@
                                currentNode = alNodesWithSameScore.get(j);
 
                                if (!nodeSeenHashMap.containsKey(currentNode)) {
-                                       // We store the current node seen hash 
map for later exploration purposes
+                                       // Store the list of all the nodes that 
have already been seen and incorporated in other clusters
                                        Map<Long, Boolean> 
nodeSeenHashMapSnapShot = new HashMap<Long, Boolean>(nodeSeenHashMap);
 
                                        // Here we use the original node score 
cutoff
@@ -361,15 +361,11 @@
                                                                
fluffClusterBoundary(alCluster, nodeSeenHashMap, nodeInfoHashMap);
 
                                                        clusterNet = 
createClusterNetwork(alCluster, inputNetwork);
+                                                       final double score = 
scoreCluster(clusterNet);
                                                        
-                                                       MCODECluster 
currentCluster = new MCODECluster();
-                                                       
currentCluster.setALCluster(alCluster);
-                                                       
currentCluster.setSeedNode(currentNode);//store the current node as the seed 
node
-                                                       
currentCluster.setNetwork(clusterNet);
-                                                       
currentCluster.setClusterScore(scoreCluster(currentCluster));
-                                                       
currentCluster.setNodeSeenHashMap(nodeSeenHashMapSnapShot);//store the list of 
all the nodes that have already been seen and incorporated in other clusters
-                                                       
currentCluster.setResultId(resultId);
-                                                       //store detected 
cluster for later
+                                                       MCODECluster 
currentCluster = new MCODECluster(resultId, currentNode, clusterNet, score,
+                                                                       
alCluster, nodeSeenHashMapSnapShot);
+                                                       
                                                        
alClusters.add(currentCluster);
                                                }
                                        }
@@ -446,22 +442,21 @@
                                                                           
final int resultId) {
                // This method is similar to the finding method with the 
exception of the filtering so that the decrease of the cluster size
                // can produce a single node, also the use of the node seen 
hash map is differentially applied...
-               Map<Long, NodeInfo> nodeInfoHashMap = 
nodeInfoResultsMap.get(resultId);
-               MCODEParameterSet params = 
mcodeUtil.getCurrentParameters().getResultParams(cluster.getResultId());
+               final Map<Long, NodeInfo> nodeInfoHashMap = 
nodeInfoResultsMap.get(resultId);
+               final MCODEParameterSet params = 
mcodeUtil.getCurrentParameters().getResultParams(cluster.getResultId());
                final Map<Long, Boolean> nodeSeenHashMap;
 
                // If the size slider is below the set node score cutoff we use 
the node seen hash map so that clusters
                // with higher scoring seeds have priority, however when the 
slider moves higher than the node score cutoff
                // we allow the cluster to accrue nodes from all around without 
the priority restriction
-               if (nodeScoreCutoff <= params.getNodeScoreCutoff()) {
+               if (nodeScoreCutoff <= params.getNodeScoreCutoff())
                        nodeSeenHashMap = new HashMap<Long, 
Boolean>(cluster.getNodeSeenHashMap());
-               } else {
+               else
                        nodeSeenHashMap = new HashMap<Long, Boolean>();
-               }
 
-               Long seedNode = cluster.getSeedNode();
+               final Long seedNode = cluster.getSeedNode();
 
-               List<Long> alCluster = getClusterCore(seedNode, 
nodeSeenHashMap, nodeScoreCutoff, params
+               final List<Long> alCluster = getClusterCore(seedNode, 
nodeSeenHashMap, nodeScoreCutoff, params
                                .getMaxDepthFromStart(), nodeInfoHashMap);
 
                // Make sure seed node is part of cluster, if not already in 
there
@@ -478,12 +473,13 @@
                        fluffClusterBoundary(alCluster, nodeSeenHashMap, 
nodeInfoHashMap);
 
                clusterNet = createClusterNetwork(alCluster, inputNet);
+               final double score = scoreCluster(clusterNet);
                
-               cluster.setNetwork(clusterNet);
-               cluster.setALCluster(alCluster);
-               cluster.setClusterScore(scoreCluster(cluster));
+               final MCODECluster newCluster = new MCODECluster(resultId, 
seedNode, clusterNet, score, alCluster,
+                               nodeSeenHashMap);
+               newCluster.setRank(cluster.getRank());
                
-               return cluster;
+               return newCluster;
        }
 
        private CySubNetwork createClusterNetwork(final List<Long> alCluster, 
final CyNetwork inputNet) {
@@ -521,15 +517,15 @@
         * Score a cluster.  Currently this ranks larger, denser clusters 
higher, although
         * in the future other scoring functions could be created
         *
-        * @param cluster
+        * @param clusterNet
         * @return The score of the cluster
         */
-       public double scoreCluster(MCODECluster cluster) {
+       public double scoreCluster(final CySubNetwork clusterNet) {
                int numNodes = 0;
                double density = 0.0, score = 0.0;
 
-               numNodes = cluster.getNetwork().getNodeCount();
-               density = calcDensity(cluster.getNetwork(), 
params.isIncludeLoops());
+               numNodes = clusterNet.getNodeCount();
+               density = calcDensity(clusterNet, params.isIncludeLoops());
                score = density * numNodes;
 
                return score;

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/model/MCODECluster.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/model/MCODECluster.java
     2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/model/MCODECluster.java
     2012-11-07 20:59:13 UTC (rev 30755)
@@ -52,104 +52,110 @@
        private CySubNetwork network;
        private Long seedNode;
        private Map<Long, Boolean> nodeSeenHashMap; // stores the nodes that 
have already been included in higher ranking clusters
-       private double clusterScore;
-       private String clusterName; // pretty much unused so far, but could 
store name by user's input
+       private double score;
+       private String name; // pretty much unused so far, but could store name 
by user's input
        private int rank;
        private int resultId;
+       private boolean disposed;
 
-       public MCODECluster() {
+       public MCODECluster(final int resultId,
+                                               final Long seedNode,
+                                               final CySubNetwork network,
+                                               final double score,
+                                               final List<Long> alCluster,
+                                               final Map<Long, Boolean> 
nodeSeenHashMap) {
+               assert seedNode != null;
+               assert network != null;
+               assert alCluster != null;
+               assert nodeSeenHashMap != null;
+               
+               this.resultId = resultId;
+               this.seedNode = seedNode;
+               this.network = network;
+               this.score = score;
+               this.alCluster = alCluster;
+               this.nodeSeenHashMap = nodeSeenHashMap;
        }
 
        public int getResultId() {
                return resultId;
        }
 
-       public void setResultId(int resultId) {
-               this.resultId = resultId;
+       public String getName() {
+               return name;
        }
 
-       public String getClusterName() {
-               return clusterName;
+       public void setName(final String name) {
+               throwExceptionIfDisposed();
+               this.name = name;
        }
 
-       public void setClusterName(final String clusterName) {
-               this.clusterName = clusterName;
-       }
-
-       public CyNetworkView getView() {
+       public synchronized CyNetworkView getView() {
                return view;
        }
 
-       public void setView(final CyNetworkView view) {
+       public synchronized void setView(final CyNetworkView view) {
+               throwExceptionIfDisposed();
+               
                if (this.view != null)
                        this.view.dispose();
                
                this.view = view;
        }
 
-       public CySubNetwork getNetwork() {
+       public synchronized CySubNetwork getNetwork() {
                return network;
        }
 
-       public void setNetwork(final CySubNetwork network) {
-               if (view != null && view.getModel().equals(this.network))
-                       view.dispose();
-               
-               dispose(this.network);
-               this.network = network;
+       public double getScore() {
+               return score;
        }
 
-       public double getClusterScore() {
-               return clusterScore;
-       }
-
-       public void setClusterScore(final double clusterScore) {
-               this.clusterScore = clusterScore;
-       }
-
        public List<Long> getALCluster() {
                return alCluster;
        }
 
-       public void setALCluster(final List<Long> alCluster) {
-               this.alCluster = alCluster;
-       }
-
        public Long getSeedNode() {
                return seedNode;
        }
 
-       public void setSeedNode(Long seedNode) {
-               this.seedNode = seedNode;
-       }
-
        public Map<Long, Boolean> getNodeSeenHashMap() {
                return nodeSeenHashMap;
        }
 
-       public void setNodeSeenHashMap(Map<Long, Boolean> nodeSeenHashMap) {
-               this.nodeSeenHashMap = nodeSeenHashMap;
-       }
-
        public int getRank() {
                return rank;
        }
 
        public void setRank(int rank) {
                this.rank = rank;
-               this.clusterName = "Cluster " + (rank + 1);
+               this.name = "Cluster " + (rank + 1);
        }
        
-       public void dispose() {
+       public synchronized boolean isDisposed() {
+               return disposed;
+       }
+
+       public synchronized void dispose() {
+               if (isDisposed()) return;
+               
                if (view != null)
                        view.dispose();
-               dispose(network);
+               
+               network.getRootNetwork().removeSubNetwork(network);
+               network.dispose();
+               
+               disposed = true;
        }
-       
-       private static void dispose(final CySubNetwork net) {
-               if (net != null) {
-                       net.getRootNetwork().removeSubNetwork(net);
-                       net.dispose();
-               }
+
+       @Override
+       public String toString() {
+               return "MCODECluster [clusterName=" + name + ", clusterScore=" 
+ score + 
+                               ", rank=" + rank + ", resultId=" + resultId + 
", disposed=" + disposed + "]";
        }
+
+       private void throwExceptionIfDisposed() {
+               if (isDisposed())
+                       throw new RuntimeException("MCODECluster has been 
disposed and cannot be used anymore: ");
+       }
 }

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/util/MCODEUtil.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/util/MCODEUtil.java
 2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/util/MCODEUtil.java
 2012-11-07 20:59:13 UTC (rev 30755)
@@ -333,6 +333,8 @@
                                                                        
SpringEmbeddedLayouter layouter,
                                                                        boolean 
layoutNecessary,
                                                                        final 
MCODELoader loader) {
+               final CyNetwork net = cluster.getNetwork();
+               
                // Progress reporters.
                // There are three basic tasks, the progress of each is 
calculated and then combined
                // using the respective weighting to get an overall progress 
global progress
@@ -349,14 +351,14 @@
                double progress = 0;
 
                final VisualStyle vs = getClusterStyle();
-               final CyNetworkView clusterView = 
createNetworkView(cluster.getNetwork(), vs);
+               final CyNetworkView clusterView = createNetworkView(net, vs);
 
                clusterView.setVisualProperty(NETWORK_WIDTH, new Double(width));
                clusterView.setVisualProperty(NETWORK_HEIGHT, new 
Double(height));
 
                for (View<CyNode> nv : clusterView.getNodeViews()) {
                        if (interrupted) {
-                               logger.error("Interrupted: Node Setup");
+                               logger.debug("Interrupted: Node Setup");
                                // before we short-circuit the method we reset 
the interruption so that the method can run without
                                // problems the next time around
                                if (layouter != null) layouter.resetDoLayout();
@@ -446,7 +448,6 @@
                final Graphics2D g = (Graphics2D) image.getGraphics();
 
                SwingUtilities.invokeLater(new Runnable() {
-
                        @Override
                        public void run() {
                                try {
@@ -476,7 +477,8 @@
 
                                        if (clusterView.getNodeViews().size() > 
0) {
                                                cluster.setView(clusterView);
-                                       }
+                                       } else {
+System.out.println("\t>> no node views--nodes: " + 
clusterView.getModel().getNodeCount() + " | " + net.getNodeCount());}// TODO: 
delete
                                } catch (Exception ex) {
                                        throw new RuntimeException(ex);
                                }
@@ -485,7 +487,7 @@
 
                layouter.resetDoLayout();
                resetLoading();
-
+               
                return image;
        }
 
@@ -525,6 +527,7 @@
                if (vs == null) vs = visualMappingMgr.getDefaultVisualStyle();
                visualMappingMgr.setVisualStyle(vs, view);
                vs.apply(view);
+               view.updateView();
 
                return view;
        }
@@ -711,8 +714,8 @@
 
                        //sorting clusters by decreasing score
                        public int compare(MCODECluster c1, MCODECluster c2) {
-                               double d1 = c1.getClusterScore();
-                               double d2 = c2.getClusterScore();
+                               double d1 = c1.getScore();
+                               double d2 = c2.getScore();
                                if (d1 == d2) {
                                        return 0;
                                } else if (d1 < d2) {
@@ -795,7 +798,7 @@
                                        fout.write((i + 1) + "\t"); //rank
                                        NumberFormat nf = 
NumberFormat.getInstance();
                                        nf.setMaximumFractionDigits(3);
-                                       
fout.write(nf.format(clusters[i].getClusterScore()) + "\t");
+                                       
fout.write(nf.format(clusters[i].getScore()) + "\t");
                                        // cluster size - format: (# prot, # 
intx)
                                        
fout.write(clusterNetwork.getNodeCount() + "\t");
                                        
fout.write(clusterNetwork.getEdgeCount() + "\t");

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODEAboutDialog.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODEAboutDialog.java
  2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODEAboutDialog.java
  2012-11-07 20:59:13 UTC (rev 30755)
@@ -1,7 +1,6 @@
 package org.cytoscape.mcode.internal.view;
 
 import java.awt.BorderLayout;
-import java.awt.Component;
 import java.awt.Insets;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -66,7 +65,6 @@
 
        private static final long serialVersionUID = 635333288924094273L;
 
-       private final CySwingApplication swingApplication;
        private final OpenBrowser openBrowser;
        private final String version;
        private final String buildDate;
@@ -79,8 +77,7 @@
        public MCODEAboutDialog(final CySwingApplication swingApplication,
                                                        final OpenBrowser 
openBrowser,
                                                        final MCODEUtil 
mcodeUtil) {
-               super(swingApplication.getJFrame(), "About MCODE", true);
-               this.swingApplication = swingApplication;
+               super(swingApplication.getJFrame(), "About MCODE", false);
                this.openBrowser = openBrowser;
                version = mcodeUtil.getProperty("project.version");
                buildDate = mcodeUtil.getProperty("buildDate");
@@ -89,7 +86,6 @@
                getContentPane().add(getMainContainer(), BorderLayout.CENTER);
                getContentPane().add(getButtonPanel(), BorderLayout.SOUTH);
                pack();
-               setLocationRelativeTo(getApplicationParent());
        }
 
        private JEditorPane getMainContainer() {
@@ -177,13 +173,4 @@
                        }
                }
        }
-
-       private Component getApplicationParent() {
-               Component c = swingApplication.getJFrame();
-               
-               while (c.getParent() != null)
-                       c = c.getParent();
-               
-               return c;
-       }
 }

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODELoader.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODELoader.java
       2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODELoader.java
       2012-11-07 20:59:13 UTC (rev 30755)
@@ -52,35 +52,36 @@
     
        private static final long serialVersionUID = 3709336791661338561L;
        
-       JTable table; //cluster browser table reference
-    int selectedRow; //row of cluster
-    ImageIcon graphImage; //picture of the graph as is before loading
-    BufferedImage onScreenLoader; //picture of loader
-    BufferedImage offScreenLoader;
-    Graphics2D onScreenG2; //graphics context of loader
-    Graphics2D offScreenG2;
-    Color bgColor; //background of selected cluster browser table cell
-    Color fgColor; //color of foreground in the selected cluster browser table 
cell
-    double fadeInAlpha; //global variable that allows the loader to fade in 
when it's first displayed
-    int degreesForDisk; //global variable keeping track of the loading disk 
rotation
-    int fontSize;
+       private JTable table; //cluster browser table reference
+       private int selectedRow; //row of cluster
+       private ImageIcon graphImage; //picture of the graph as is before 
loading
+       private BufferedImage onScreenLoader; //picture of loader
+       private BufferedImage offScreenLoader;
+       private Graphics2D onScreenG2; //graphics context of loader
+       private Graphics2D offScreenG2;
+       private Color bgColor; //background of selected cluster browser table 
cell
+       private Color fgColor; //color of foreground in the selected cluster 
browser table cell
+       private double fadeInAlpha; //global variable that allows the loader to 
fade in when it's first displayed
+       private int degreesForDisk; //global variable keeping track of the 
loading disk rotation
+       private int fontSize;
 
-    int progress; //progress bar progress value
-    String process; //current process being computed
+       private int progress; //progress bar progress value
+       private String process; //current process being computed
 
-    Thread t;
-    boolean loading; // run switch
-    boolean loaderDisplayed; //allows mcode to display a continous loading 
animation during continous exploration
+       private Thread t;
+       private boolean loading; // run switch
+       private boolean loaderDisplayed; //allows mcode to display a continuous 
loading animation during continuous exploration
 
     /**
-     * Constructer for the loader.
+     * Constructor for the loader.
      *
      * @param table Reference to the cluster browser table
      * @param width cell width
      * @param height cell height
      */
-    MCODELoader (JTable table, int width, int height) {
-        this.table = table;
+    MCODELoader (final int selectedRow, final JTable table, int width, int 
height) {
+       this.selectedRow = selectedRow;
+       this.table = table;
         //First we get the tables colors and set the font
         bgColor = table.getSelectionBackground();
         fgColor = table.getSelectionForeground();
@@ -99,78 +100,69 @@
 
         //the on screen image is the one that this ImageIcon will display      
  
         this.setImage(onScreenLoader);
-
-        loading = false;
-
-        t = new Thread(this);
-        
     }
 
-    /**
-     * Sets the row and network image on top of which the loader will be drawn 
as well as
-     * progress to 0 and process to "Starting".
-     *
-     * @param selectedRow the row in a table where the loader is to be drawn
-     * @param table an image of the cluster before the loader is drawn on top
-     */
-    public void setLoader(int selectedRow, JTable table) {
-        this.selectedRow = selectedRow;
+    public void start() {
         graphImage = (ImageIcon) table.getValueAt(selectedRow, 0);
         fadeInAlpha = 0.0;
         degreesForDisk = 0;
         progress = 0;
         process = "Starting";
-
         loaderDisplayed = false;
         loading = true;
+        
+        t = new Thread(this);
+        t.start();
     }
 
+    /**
+     * Sets the run switch to false to stop the drawing process
+     */
+    public void stop() {
+        loading = false;
+        loaderDisplayed = false;
+        t = null;
+    }
+    
     @Override
     public void run() {
         try {
-            while (true) {
+               final Thread curentThread = Thread.currentThread();
+               
+            while (t == curentThread) {
+                //First we make sure that if the loader is being displayed for 
the first time in this exploration
+                //session, then we wait half a second to make sure it isn't 
displayed for process that are really quick
+                if (loading && !loaderDisplayed)
+                    Thread.sleep(500);
+                
+                //Then we compute the loading picture if loading is still 
taking place
                 if (loading) {
-                    //First we make sure that if the loader is being displayed 
for the first time in this exploration
-                    //session, then we wait half a second to make sure it 
isn't displayed for process that are really
-                    //quick
+                    drawLoader();
+                    
+                    //If the loader has not been displayed yet and loading is 
still taking place, we put it in the table
                     if (loading && !loaderDisplayed) {
-                        Thread.sleep(500);
+                        table.setValueAt(this, selectedRow, 0);
+                        loaderDisplayed = true;
                     }
-                    //Then we compute the loading picture if loading is still 
taking place
-                    if (loading) {
-                        drawLoader();
-                        //If the loader has not been displayed yet and loading 
is still taking place,
-                        //we put it in the table
-                        if (loading && !loaderDisplayed) {
-                            table.setValueAt(this, selectedRow, 0);
-                            loaderDisplayed = true;
-                        }
 
-                        //Since the table consolidates paint updates, the 
animation would not show up unless
-                        //we implicitly force it to repaint
-                        //This paintImmediately function causes problems in 
windows (paints on every component sometimes)
-                        //Rectangle bounds = table.getCellRect(selectedRow, 0, 
false);
-                        //if (loading) table.paintImmediately(bounds);
-                        //This fireTableCellUpdated function seems to 
consolidate some painting too so it is not very responsive in windows
-                        if (loading) ((AbstractTableModel) 
table.getModel()).fireTableCellUpdated(selectedRow, 0);
-                        //Both work on the mac just fine
-                    }
+                    //Since the table consolidates paint updates, the 
animation would not show up unless
+                    //we implicitly force it to repaint.
+                    //This paintImmediately function causes problems in 
windows (paints on every component sometimes)
+                    //Rectangle bounds = table.getCellRect(selectedRow, 0, 
false);
+                    //if (loading) table.paintImmediately(bounds);
+                    //This fireTableCellUpdated function seems to consolidate 
some painting too so it is not very responsive in windows
+                    if (loading)
+                       ((AbstractTableModel) 
table.getModel()).fireTableCellUpdated(selectedRow, 0);
+                    //Both work on the mac just fine
                 }
-                //This sleep time generates a ~30 fps animation
-                Thread.sleep(30);
             }
+            
+            //This sleep time generates a ~30 fps animation
+            Thread.sleep(30);
         } catch (Exception e) {}
     }
 
     /**
-     * Sets the run switch to false to stop the drawing process
-     */
-    public void loaded() {
-        loading = false;
-        loaderDisplayed = false;
-    }
-
-    /**
      * Initially, fades the graph into the background color, draws the Loading 
string and an animated disk to indicate
      * responsiveness as well as a progress bar and process status.
      */
@@ -212,7 +204,7 @@
         int r = 20;//radius of the disk
         //To draw the animated rotating disk, we must create the Mask, or 
drawable area, in which we will
         //rotate a triangular polygon around a common center
-        //the inner circle is subracted from the outter to create the disk area
+        //the inner circle is subtracted from the outer to create the disk area
         Ellipse2D circOutter = new Ellipse2D.Double((loader.getWidth() / 2) - 
r, (loader.getHeight() / 2) - r, 2 * r, 2 * r);
         Ellipse2D circInner = new Ellipse2D.Double((loader.getWidth() / 2) - 
(r / 2), (loader.getHeight() / 2) - (r / 2), r, r);
 
@@ -240,10 +232,10 @@
         //In order for the leading portion of the rotating disk to be one 
color and the trailing portion another we use
         //this weighting variable to slowly change the weighting of the two 
colors in finding the average between the two
         double markerLeadColorWeighting = 1.0;
-        //this is the transparency of the initial polygon which is 
exponantially decremented to fade away the polygons
+        //this is the transparency of the initial polygon which is 
exponentially decremented to fade away the polygons
         double markerAlpha = 255 * fadeInAlpha;
 
-        //In order for the polygons to cover the disk entirely, the outter 
polygon points must circle in an orbit that is further
+        //In order for the polygons to cover the disk entirely, the outer 
polygon points must circle in an orbit that is further
         //than the disk itself, otherwise we would get a flat line between the 
two points and the resulting circle would not be smooth
         r = r + 10;
         //We will only draw the polygons as long as they are visible
@@ -356,8 +348,4 @@
         this.progress = progress;
         this.process = process;
     }
-
-       public void start() {
-               t.start();
-       }
 }

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODEResultsPanel.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODEResultsPanel.java
 2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/main/java/org/cytoscape/mcode/internal/view/MCODEResultsPanel.java
 2012-11-07 20:59:13 UTC (rev 30755)
@@ -28,6 +28,10 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
 import javax.swing.AbstractAction;
 import javax.swing.BorderFactory;
@@ -74,6 +78,8 @@
 import org.cytoscape.view.model.CyNetworkView;
 import org.cytoscape.view.model.View;
 import org.cytoscape.view.vizmap.VisualStyle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * * Copyright (c) 2004 Memorial Sloan-Kettering Cancer Center
@@ -126,8 +132,7 @@
        private int resultId;
        private MCODEAlgorithm alg;
        private MCODECluster[] clusters;
-       private JTable table;
-       private MCODEResultsPanel.MCODEClusterBrowserTableModel modelBrowser;
+       
        // Actual cluster data
        private CyNetwork network; // Keep a record of the original input 
record for use in
        // the table row selection listener
@@ -141,10 +146,12 @@
        private int enumerationSelection = 0;
 
        // Graphical classes
-       private MCODELoader loader;
+       private MCODEClusterBrowserPanel clusterBrowserPanel;
 
        private final MCODEUtil mcodeUtil;
        private final MCODEDiscardResultAction discardResultAction;
+       
+       private static final Logger logger = 
LoggerFactory.getLogger(MCODEResultsPanel.class);
 
        /**
         * Constructor for the Results Panel which displays the clusters in a
@@ -153,7 +160,7 @@
         * @param clusters Found clusters from the MCODEAnalyzeTask
         * @param alg A reference to the alg for this particular network
         * @param network Network were these clusters were found
-        * @param imageList A list of images of the found clusters
+        * @param clusterImages A list of images of the found clusters
         * @param resultId Title of this result as determined by 
MCODESCoreAndFindAction
         */
        public MCODEResultsPanel(MCODECluster[] clusters,
@@ -161,7 +168,7 @@
                                                         MCODEUtil mcodeUtil,
                                                         CyNetwork network,
                                                         CyNetworkView 
networkView,
-                                                        Image[] imageList,
+                                                        Image[] clusterImages,
                                                         int resultId,
                                                         final 
MCODEDiscardResultAction discardResultAction) {
                setLayout(new BorderLayout());
@@ -174,18 +181,12 @@
                // The view may not exist, but we only test for that when we 
need to (in the TableRowSelectionHandler below)
                this.networkView = networkView;
                this.discardResultAction = discardResultAction;
-
-               currentParamsCopy = 
mcodeUtil.getCurrentParameters().getResultParams(resultId);
-
-               JPanel clusterBrowserPanel = 
createClusterBrowserPanel(imageList);
-               JPanel bottomPanel = createBottomPanel();
-
+               this.currentParamsCopy = 
mcodeUtil.getCurrentParameters().getResultParams(resultId);
+               
+               this.clusterBrowserPanel = new 
MCODEClusterBrowserPanel(clusterImages);
                add(clusterBrowserPanel, BorderLayout.CENTER);
-               add(bottomPanel, BorderLayout.SOUTH);
+               add(createBottomPanel(), BorderLayout.SOUTH);
 
-               loader = new MCODELoader(table, graphPicSize, graphPicSize);
-               loader.start();
-
                this.setSize(this.getMinimumSize());
        }
 
@@ -217,6 +218,10 @@
        public CyNetworkView getNetworkView() {
                return networkView;
        }
+       
+       public int getSelectedClusterRow() {
+               return clusterBrowserPanel.getSelectedRow();
+       }
 
        public void discard(final boolean requestUserConfirmation) {
                SwingUtilities.invokeLater(new Runnable() {
@@ -236,39 +241,6 @@
        }
 
        /**
-        * Creates a panel that contains the browser table with a scroll bar.
-        * 
-        * @param imageList
-        *            images of cluster graphs
-        * @return panel
-        */
-       private JPanel createClusterBrowserPanel(Image[] imageList) {
-               JPanel panel = new JPanel();
-               panel.setLayout(new BorderLayout());
-               panel.setBorder(BorderFactory.createTitledBorder("Cluster 
Browser"));
-
-               // main data table
-               modelBrowser = new 
MCODEResultsPanel.MCODEClusterBrowserTableModel(imageList);
-
-               table = new JTable(modelBrowser);
-               table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-               table.setDefaultRenderer(StringBuffer.class, new 
MCODEResultsPanel.JTextAreaRenderer(defaultRowHeight));
-               table.setIntercellSpacing(new Dimension(0, 4)); // gives a 
little vertical room between clusters
-               table.setFocusable(false); // removes an outline that appears 
when the user clicks on the images
-
-               // Ask to be notified of selection changes.
-               ListSelectionModel rowSM = table.getSelectionModel();
-               rowSM.addListSelectionListener(new 
MCODEResultsPanel.TableRowSelectionHandler());
-
-               JScrollPane tableScrollPane = new JScrollPane(table);
-               tableScrollPane.getViewport().setBackground(Color.WHITE);
-
-               panel.add(tableScrollPane, BorderLayout.CENTER);
-
-               return panel;
-       }
-
-       /**
         * Creates a panel containing the explore collapsable panel and result 
set
         * specific buttons
         * 
@@ -447,7 +419,7 @@
                                        if (nodeRow.isSet(CLUSTER_ATTR))
                                                
clusterNameSet.addAll(nodeRow.getList(CLUSTER_ATTR, String.class));
 
-                                       
clusterNameSet.add(cluster.getClusterName());
+                                       clusterNameSet.add(cluster.getName());
                                        nodeRow.set(CLUSTER_ATTR, new 
ArrayList<String>(clusterNameSet));
 
                                        if (cluster.getSeedNode() == rgi)
@@ -460,7 +432,30 @@
 
                return alg.getMaxScore(resultId);
        }
+       
+       private static StringBuffer getClusterDetails(final MCODECluster 
cluster) {
+               StringBuffer details = new StringBuffer();
 
+               details.append("Rank: ");
+               details.append(String.valueOf(cluster.getRank() + 1));
+
+               details.append("\n");
+               details.append("Score: ");
+               NumberFormat nf = NumberFormat.getInstance();
+               nf.setMaximumFractionDigits(3);
+               details.append(nf.format(cluster.getScore()));
+
+               details.append("\n");
+               details.append("Nodes: ");
+               details.append(cluster.getNetwork().getNodeCount());
+
+               details.append("\n");
+               details.append("Edges: ");
+               details.append(cluster.getNetwork().getEdgeCount());
+
+               return details;
+       }
+
        /**
         * Handles the create child network press in the cluster exploration 
panel
         */
@@ -480,8 +475,8 @@
                        nf.setMaximumFractionDigits(3);
                        final MCODECluster cluster = clusters[selectedRow];
                        final CyNetwork clusterNetwork = cluster.getNetwork();
-                       final String title = trigger.getResultId() + ": " + 
cluster.getClusterName() + " (Score: " +
-                                                                
nf.format(cluster.getClusterScore()) + ")";
+                       final String title = trigger.getResultId() + ": " + 
cluster.getName() + " (Score: " +
+                                                                
nf.format(cluster.getScore()) + ")";
                        // Create the child network and view
                        final SwingWorker<CyNetworkView, ?> worker = new 
SwingWorker<CyNetworkView, Object>() {
 
@@ -549,13 +544,62 @@
        }
 
        /**
+        * Panel that contains the browser table with a scroll bar.
+        */
+       private class MCODEClusterBrowserPanel extends JPanel {
+               
+               private final MCODEResultsPanel.MCODEClusterBrowserTableModel 
browserModel;
+               private final JTable table;
+               
+               public MCODEClusterBrowserPanel(final Image[] images) {
+                       super();
+                       setLayout(new BorderLayout());
+                       setBorder(BorderFactory.createTitledBorder("Cluster 
Browser"));
+
+                       // main data table
+                       browserModel = new 
MCODEResultsPanel.MCODEClusterBrowserTableModel(images);
+
+                       table = new JTable(browserModel);
+                       
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+                       table.setDefaultRenderer(StringBuffer.class, new 
MCODEResultsPanel.JTextAreaRenderer(defaultRowHeight));
+                       table.setIntercellSpacing(new Dimension(0, 4)); // 
gives a little vertical room between clusters
+                       table.setFocusable(false); // removes an outline that 
appears when the user clicks on the images
+
+                       // Ask to be notified of selection changes.
+                       ListSelectionModel rowSM = table.getSelectionModel();
+                       rowSM.addListSelectionListener(new 
MCODEResultsPanel.TableRowSelectionHandler());
+
+                       JScrollPane tableScrollPane = new JScrollPane(table);
+                       
tableScrollPane.getViewport().setBackground(Color.WHITE);
+
+                       add(tableScrollPane, BorderLayout.CENTER);
+               }
+
+               public int getSelectedRow() {
+                       return table.getSelectedRow();
+               }
+               
+               public void update(final ImageIcon image, final int row) {
+                       table.setValueAt(image, row, 0);
+               }
+               
+               public void update(final MCODECluster cluster, final int row) {
+                       final StringBuffer details = getClusterDetails(cluster);
+                       table.setValueAt(details, row, 1);
+               }
+
+               JTable getTable() { // TODO: delete it: do not expose the JTable
+                       return table;
+               }
+       }
+       
+       /**
         * Handles the data to be displayed in the cluster browser table
         */
        private class MCODEClusterBrowserTableModel extends AbstractTableModel {
 
-               // Create column headings
-               String[] columnNames = { "Network", "Details" };
-               Object[][] data; // the actual table data
+               private final String[] columnNames = { "Network", "Details" };
+               private final Object[][] data; // the actual table data
 
                public MCODEClusterBrowserTableModel(Image[] imageList) {
                        exploreContent = new JPanel[clusters.length];
@@ -563,7 +607,7 @@
 
                        for (int i = 0; i < clusters.length; i++) {
                                clusters[i].setRank(i);
-                               StringBuffer details = new 
StringBuffer(getClusterDetails(clusters[i]));
+                               StringBuffer details = 
getClusterDetails(clusters[i]);
                                data[i][1] = new StringBuffer(details);
 
                                // get an image for each cluster - make it a 
nice layout of the cluster
@@ -572,63 +616,39 @@
                        }
                }
 
+               @Override
                public String getColumnName(int col) {
                        return columnNames[col];
                }
 
+               @Override
                public int getColumnCount() {
                        return columnNames.length;
                }
 
+               @Override
                public int getRowCount() {
                        return data.length;
                }
 
+               @Override
                public Object getValueAt(int row, int col) {
                        return data[row][col];
                }
 
+               @Override
                public void setValueAt(Object object, int row, int col) {
                        data[row][col] = object;
                        fireTableCellUpdated(row, col);
                }
 
+               @Override
                public Class<?> getColumnClass(int c) {
                        return getValueAt(0, c).getClass();
                }
        }
 
        /**
-        * Generates a string buffer with the cluster's details
-        * 
-        * @param cluster
-        *            The cluster
-        * @return details String buffer containing the details
-        */
-       private StringBuffer getClusterDetails(MCODECluster cluster) {
-               StringBuffer details = new StringBuffer();
-
-               details.append("Rank: ");
-               details.append(String.valueOf(cluster.getRank() + 1));
-
-               details.append("\n");
-               details.append("Score: ");
-               NumberFormat nf = NumberFormat.getInstance();
-               nf.setMaximumFractionDigits(3);
-               details.append(nf.format(cluster.getClusterScore()));
-
-               details.append("\n");
-               details.append("Nodes: ");
-               details.append(cluster.getNetwork().getNodeCount());
-
-               details.append("\n");
-               details.append("Edges: ");
-               details.append(cluster.getNetwork().getEdgeCount());
-
-               return details;
-       }
-
-       /**
         * Handles the data to be displayed in the node attribute enumeration 
table
         */
        private class MCODEResultsEnumeratorTableModel extends 
AbstractTableModel {
@@ -873,8 +893,8 @@
                                // event to display the new content with the 
name of the cluster, if it exists
                                String title = "Explore: ";
 
-                               if (clusters[selectedRow].getClusterName() != 
null) {
-                                       title = title + 
clusters[selectedRow].getClusterName();
+                               if (clusters[selectedRow].getName() != null) {
+                                       title = title + 
clusters[selectedRow].getName();
                                } else {
                                        title = title + "Cluster " + 
(selectedRow + 1);
                                }
@@ -992,96 +1012,88 @@
        }
 
        /**
-        * Getter for the browser table used in MCODEVisualStyleAction to 
reselect
-        * the selected cluster whenever the user focuses on this result set
-        */
-       public JTable getClusterBrowserTable() {
-               return table;
-       }
-
-       /**
         * Handles the dynamic cluster size manipulation via the JSlider
         */
        private class SizeAction implements ChangeListener {
 
+               private final ScheduledExecutorService scheduler =  
Executors.newScheduledThreadPool(3);
+               private ScheduledFuture<?> futureLoader;
+               
                private int selectedRow;
-               public boolean loaderSet = false;
                private JComboBox nodeAttributesComboBox;
-               private GraphDrawer drawer;
                private boolean drawPlaceHolder;
-
+               private final GraphDrawer drawer;
+               private final MCODELoader loader;
+               
                /**
-                * Constructor
-                * 
-                * @param selectedRow
-                *            The selected cluster
-                * @param nodeAttributesComboBox
-                *            Reference to the attribute enumeration picker
+                * @param selectedRow The selected cluster
+                * @param nodeAttributesComboBox Reference to the attribute 
enumeration picker
                 */
-               SizeAction(int selectedRow, JComboBox nodeAttributesComboBox) {
+               SizeAction(final int selectedRow, final JComboBox 
nodeAttributesComboBox) {
                        this.selectedRow = selectedRow;
                        this.nodeAttributesComboBox = nodeAttributesComboBox;
-                       drawer = new GraphDrawer();
-                       loaderSet = false;
+                       loader = new MCODELoader(selectedRow, 
clusterBrowserPanel.getTable(), graphPicSize, graphPicSize);
+                       drawer = new GraphDrawer(loader);
                }
 
-               public void stateChanged(ChangeEvent e) {
+               public void stateChanged(final ChangeEvent e) {
                        // This method as been written so that the slider is 
responsive to the user's input at all times, despite
                        // the computationally challenging drawing, layout out, 
and selection of large clusters. As such, we only
                        // perform real work if the slider produces a different 
cluster, and furthermore we only perform the quick
                        // processes here, while the heavy weights are handled 
by the drawer's thread.
-                       JSlider source = (JSlider) e.getSource();
-                       double nodeScoreCutoff = (((double) source.getValue()) 
/ 1000);
-
+                       final JSlider source = (JSlider) e.getSource();
+                       final double nodeScoreCutoff = (((double) 
source.getValue()) / 1000);
+                       final int clusterRow = selectedRow;
                        // Store current cluster content for comparison
-                       List<Long> oldCluster = 
clusters[selectedRow].getALCluster();
-
-                       // Find the new cluster given the node score cutoff
-                       MCODECluster cluster = 
alg.exploreCluster(clusters[selectedRow], nodeScoreCutoff, network, resultId);
-
-                       // We only want to do the following work if the newly 
found cluster
-                       // is actually different
-                       // So we get the new cluster content
-                       List<Long> newCluster = cluster.getALCluster();
-
-                       // If the new cluster is too large to draw within a 
reasonable time
-                       // and won't look understandable in the table cell then 
we draw a place holder
-                       drawPlaceHolder = newCluster.size() > 300;
-
-                       // And compare the old and new
-                       if (!newCluster.equals(oldCluster)) {
-                               // If the cluster has changed, then we conduct 
all
-                               // non-rate-limiting steps:
-                               // Interrupt the drawing
-                               drawer.interruptDrawing();
-                               // Update the cluster array
-                               clusters[selectedRow] = cluster;
-                               // Update the details
-                               StringBuffer details = 
getClusterDetails(cluster);
-                               table.setValueAt(details, selectedRow, 1);
-                               // Fire the enumeration action
-                               
nodeAttributesComboBox.setSelectedIndex(nodeAttributesComboBox.getSelectedIndex());
-
-                               // Ensure that a loader is set with the 
selected row and table object
-                               // Also, we want to set the loader only once 
during continuous exploration
-                               // It is only set again when a graph is fully 
loaded and placed in the table
-                               if (!loaderSet && !drawPlaceHolder) {
-                                       // internally, the loader is only drawn 
into the appropriate
-                                       // cell after a short sleep period
-                                       // to ensure that quick loads are not 
displayed unecessarily
-                                       loader.setLoader(selectedRow, table);
-                                       loaderSet = true;
-                               }
-
-                               // There is a small difference between 
expanding and retracting the cluster size.
-                               // When expanding, new nodes need random 
position and thus must go through the layout.
-                               // When retracting, we simply use the layout 
that was generated and stored.
-                               // This speeds up the drawing process greatly.
-                               boolean layoutNecessary = newCluster.size() > 
oldCluster.size();
-                               // Draw Graph and select the cluster in the 
view in a separate thread so that it can be
-                               // interrupted by the slider movement
-                               drawer.drawGraph(cluster, layoutNecessary, 
this, drawPlaceHolder);
+               final MCODECluster oldCluster = clusters[clusterRow];
+                       
+                       if (futureLoader != null && !futureLoader.isDone()) {
+                               drawer.stop();
+                               futureLoader.cancel(false);
                        }
+                       
+                       final Runnable command = new Runnable() {
+                   @Override
+                       public void run() {
+                       final List<Long> oldALCluster = 
oldCluster.getALCluster();
+                                       // Find the new cluster given the node 
score cutoff
+                                       final MCODECluster newCluster = 
alg.exploreCluster(oldCluster, nodeScoreCutoff, network, resultId);
+                                       
+                                       // We only want to do the following 
work if the newly found cluster is actually different
+                                       // So we get the new cluster content
+                                       List<Long> newALCluster = 
newCluster.getALCluster();
+                                       
+                                       // If the new cluster is too large to 
draw within a reasonable time
+                                       // and won't look understandable in the 
table cell, then we draw a place holder
+                                       drawPlaceHolder = newALCluster.size() > 
300;
+                                       
+                                       // And compare the old and new
+                                       if (!newALCluster.equals(oldALCluster)) 
{
+                                               // If the cluster has changed, 
then we conduct all non-rate-limiting steps:
+                                               // Update the cluster array
+                                               clusters[clusterRow] = 
newCluster;
+                                               // Update the cluster details
+                                               
clusterBrowserPanel.update(newCluster, clusterRow);
+                                               // Fire the enumeration action
+                                               
nodeAttributesComboBox.setSelectedIndex(nodeAttributesComboBox.getSelectedIndex());
+               
+                                               // There is a small difference 
between expanding and retracting the cluster size.
+                                               // When expanding, new nodes 
need random position and thus must go through the layout.
+                                               // When retracting, we simply 
use the layout that was generated and stored.
+                                               // This speeds up the drawing 
process greatly.
+                                               boolean layoutNecessary = 
newALCluster.size() > oldALCluster.size();
+                                               // Draw Graph and select the 
cluster in the view in a separate thread so that it can be
+                                               // interrupted by the slider 
movement
+                                               if (!newCluster.isDisposed())
+                                                       
drawer.drawGraph(newCluster, layoutNecessary, drawPlaceHolder);
+                                               
+                                               // Prevent memory leaks
+                                               oldCluster.dispose();
+                                       }
+                   }
+               };
+               
+               futureLoader = scheduler.schedule(command, 100, 
TimeUnit.MILLISECONDS);
                }
        }
 
@@ -1091,22 +1103,19 @@
         */
        private class GraphDrawer implements Runnable {
 
-               private Thread t;
                private boolean drawGraph; // run switch
                private boolean placeHolderDrawn;
                private boolean drawPlaceHolder;
                MCODECluster cluster;
                SpringEmbeddedLayouter layouter;
-               MCODEResultsPanel.SizeAction trigger;
                boolean layoutNecessary;
                boolean clusterSelected;
+               private Thread t;
+               private final  MCODELoader loader;
 
-               GraphDrawer() {
-                       drawGraph = false;
-                       drawPlaceHolder = false;
+               GraphDrawer(final MCODELoader loader) {
+                       this.loader = loader;
                        layouter = new SpringEmbeddedLayouter();
-                       t = new Thread(this);
-                       t.start();
                }
 
                /**
@@ -1120,10 +1129,8 @@
                 */
                public void drawGraph(MCODECluster cluster,
                                                          boolean 
layoutNecessary,
-                                                         
MCODEResultsPanel.SizeAction trigger,
                                                          boolean 
drawPlaceHolder) {
                        this.cluster = cluster;
-                       this.trigger = trigger;
                        this.layoutNecessary = layoutNecessary;
 
                        // Graph drawing will only occur if the cluster is not 
too large,
@@ -1131,11 +1138,23 @@
                        drawGraph = !drawPlaceHolder;
                        this.drawPlaceHolder = drawPlaceHolder;
                        clusterSelected = false;
+                       t = new Thread(this);
+                       t.start();
                }
 
                public void run() {
                        try {
-                               while (true) {
+                               // We want to set the loader only once during 
continuous exploration
+                               // It is only set again when a graph is fully 
loaded and placed in the table
+                               if (!drawPlaceHolder) {
+                                       // internally, the loader is only drawn 
into the appropriate cell after a short sleep period
+                                       // to ensure that quick loads are not 
displayed unnecessarily
+                                       loader.start();
+                               }
+                               
+                               final Thread currentThread = 
Thread.currentThread(); 
+                               
+                               while (t == currentThread) {
                                        // This ensures that the drawing of 
this cluster is only attempted once
                                        // if it is unsuccessful it is because 
the setup or layout
                                        // process was interrupted by the 
slider movement
@@ -1157,12 +1176,7 @@
                                                        
selectCluster(cluster.getNetwork());
                                                        clusterSelected = true;
                                                        // Update the table
-                                                       table.setValueAt(new 
ImageIcon(image), cluster.getRank(), 0);
-                                                       // Loader is no longer 
showing, so we let the SizeAction know that
-                                                       trigger.loaderSet = 
false;
-                                                       // stop loader from 
animating and taking up computer processing power
-                                                       loader.loaded();
-
+                                                       
clusterBrowserPanel.update(new ImageIcon(image), cluster.getRank());
                                                        drawGraph = false;
                                                }
 
@@ -1172,13 +1186,9 @@
                                                // draw place holder, only once 
though (as per the if statement)
                                                Image image = 
mcodeUtil.getPlaceHolderImage(graphPicSize, graphPicSize);
                                                // Update the table
-                                               table.setValueAt(new 
ImageIcon(image), cluster.getRank(), 0);
+                                               clusterBrowserPanel.update(new 
ImageIcon(image), cluster.getRank());
                                                // select the cluster
                                                
selectCluster(cluster.getNetwork());
-                                               // Loader is no longer showing, 
so we let the SizeAction know that
-                                               trigger.loaderSet = false;
-                                               // stop loader from animating 
and taking up computer processing power
-                                               loader.loaded();
                                                drawGraph = false;
                                                // Make sure this block is not 
run again unless if we need to reload the image
                                                placeHolderDrawn = true;
@@ -1187,17 +1197,24 @@
                                                clusterSelected = true;
                                        }
 
+                                       if ((!drawGraph && !drawPlaceHolder) || 
placeHolderDrawn)
+                                               stop();
+                                       
                                        // This sleep time produces the drawing 
response time of 1 20th of a second
                                        Thread.sleep(100);
                                }
                        } catch (Exception e) {
+                               logger.error("Error while drawing cluster 
image", e);
                        }
                }
 
-               public void interruptDrawing() {
-                       drawGraph = false;
+               void stop() {
+                       // stop loader from animating and taking up computer 
processing power
+                       loader.stop();
                        layouter.interruptDoLayout();
                        mcodeUtil.interruptLoading();
+                       drawGraph = false;
+                       t = null;
                }
        }
 }

Modified: 
csplugins/trunk/toronto/clopes/mcode/src/test/java/org/cytoscape/mcode/internal/model/MCODEAlgorithmTest.java
===================================================================
--- 
csplugins/trunk/toronto/clopes/mcode/src/test/java/org/cytoscape/mcode/internal/model/MCODEAlgorithmTest.java
       2012-11-07 20:10:08 UTC (rev 30754)
+++ 
csplugins/trunk/toronto/clopes/mcode/src/test/java/org/cytoscape/mcode/internal/model/MCODEAlgorithmTest.java
       2012-11-07 20:59:13 UTC (rev 30755)
@@ -125,7 +125,7 @@
                
                assertNotNull(cn);
                assertEquals(resultId, c.getResultId());
-               assertEquals(16, c.getClusterScore(), 0.0);
+               assertEquals(16, c.getScore(), 0.0);
                assertEquals(16, cn.getNodeCount());
                assertEquals(120, cn.getEdgeCount());
                assertNotNull(c.getSeedNode());
@@ -152,7 +152,7 @@
                
                assertNotNull(cn);
                assertEquals(resultId, c.getResultId());
-               assertEquals(14.118, c.getClusterScore(), 0.0009);
+               assertEquals(14.118, c.getScore(), 0.0009);
                assertEquals(16, cn.getNodeCount());
                assertEquals(120, cn.getEdgeCount());
                assertNotNull(c.getSeedNode());

-- 
You received this message because you are subscribed to the Google Groups 
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/cytoscape-cvs?hl=en.

Reply via email to